@godxjp/ui 30.4.2 → 30.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/agent/START-HERE.md +6 -6
  2. package/agent/components/Carousel.json +4 -1
  3. package/agent/components/RecordPicker.json +103 -0
  4. package/agent/components/ResponsiveGrid.json +3 -1
  5. package/agent/components/Reveal.json +6 -1
  6. package/agent/components/Table.json +6 -0
  7. package/agent/components/Text.json +8 -0
  8. package/agent/components-index.json +5 -0
  9. package/agent/components.json +130 -3
  10. package/agent/index.json +7 -7
  11. package/agent/llms.txt +7 -7
  12. package/agent/patterns/brand-theme-block.json +33 -0
  13. package/agent/patterns-index.json +32 -0
  14. package/agent/patterns.json +33 -0
  15. package/agent/tokens.json +12 -0
  16. package/dist/components/data-display/table.d.ts +30 -1
  17. package/dist/components/data-display/table.js +2 -1
  18. package/dist/components/data-entry/index.d.ts +2 -0
  19. package/dist/components/data-entry/index.js +2 -0
  20. package/dist/components/data-entry/record-picker.d.ts +62 -0
  21. package/dist/components/data-entry/record-picker.js +296 -0
  22. package/dist/components/general/typography.d.ts +1 -0
  23. package/dist/components/general/typography.js +10 -0
  24. package/dist/contracts/measurement.json +1 -1
  25. package/dist/i18n/messages/en.json +18 -0
  26. package/dist/i18n/messages/ja.json +18 -0
  27. package/dist/i18n/messages/vi.json +18 -0
  28. package/dist/props/components/data-entry.prop.d.ts +58 -0
  29. package/dist/props/components/general.prop.d.ts +15 -1
  30. package/dist/props/registry.d.ts +17 -0
  31. package/dist/props/registry.js +17 -0
  32. package/dist/props/vocabulary/index.d.ts +1 -1
  33. package/dist/props/vocabulary/interaction.prop.d.ts +13 -0
  34. package/dist/styles/data-display-layout.css +6 -3
  35. package/dist/styles/data-entry-layout.css +71 -0
  36. package/dist/styles/dialog-layout.css +8 -0
  37. package/dist/styles/focus-ring.css +2 -0
  38. package/dist/styles/table-layout.css +13 -0
  39. package/dist/styles/text-layout.css +8 -0
  40. package/dist/tokens/components/data-display.css +2 -0
  41. package/dist/tokens/components/data-entry.css +3 -0
  42. package/docs/FRAME-COVERAGE-REPORT.md +3 -2
  43. package/docs/assets/tcgm/card-1.svg +1 -0
  44. package/docs/assets/tcgm/card-2.svg +1 -0
  45. package/docs/assets/tcgm/card-3.svg +1 -0
  46. package/docs/assets/tcgm/card-4.svg +1 -0
  47. package/docs/assets/tcgm/card-5.svg +1 -0
  48. package/docs/assets/tcgm/card-6.svg +1 -0
  49. package/docs/assets/tcgm/hero-prism.svg +1 -0
  50. package/docs/assets/tcgm/scene-1.svg +1 -0
  51. package/docs/assets/tcgm/scene-2.svg +1 -0
  52. package/docs/assets/tcgm/scene-3.svg +1 -0
  53. package/docs/assets/tcgm/scene-4.svg +1 -0
  54. package/docs/assets/tcgm/scene-5.svg +1 -0
  55. package/docs/assets/tcgm/tcgm-lockup-color.svg +1 -0
  56. package/docs/assets/tcgm/tcgm-symbol-color.svg +1 -0
  57. package/docs/data-entry/record-picker.tsx +208 -0
  58. package/docs/general/typography.tsx +28 -0
  59. package/docs/i18n/messages/en.json +185 -1
  60. package/docs/i18n/messages/ja.json +185 -1
  61. package/docs/i18n/messages/vi.json +185 -1
  62. package/docs/showcase/tcgm-website.tsx +1047 -0
  63. package/package.json +3 -3
  64. package/scripts/ui-audit.mjs +23 -0
@@ -189,6 +189,24 @@
189
189
  "remove": "Remove {name}",
190
190
  "uploading": "Uploading attachment",
191
191
  "error": "Upload failed"
192
+ },
193
+ "recordPicker": {
194
+ "trigger": "Select",
195
+ "placeholder": "Select…",
196
+ "search": "Search",
197
+ "searchPlaceholder": "Search by keyword",
198
+ "dialogTitle": "Select",
199
+ "filters": "Filters",
200
+ "allFilter": "All",
201
+ "selected": "{count} selected",
202
+ "loading": "Loading",
203
+ "empty": "No matching items",
204
+ "error": "Could not load",
205
+ "confirm": "Confirm",
206
+ "cancel": "Cancel",
207
+ "clear": "Clear selection",
208
+ "more": "Load more",
209
+ "openDialog": "Choose from list"
192
210
  }
193
211
  },
194
212
  "feedback": {
@@ -185,6 +185,24 @@
185
185
  "remove": "{name} を削除",
186
186
  "uploading": "添付をアップロード中",
187
187
  "error": "アップロードに失敗しました"
188
+ },
189
+ "recordPicker": {
190
+ "trigger": "選択",
191
+ "placeholder": "選択してください",
192
+ "search": "検索",
193
+ "searchPlaceholder": "キーワードで検索",
194
+ "dialogTitle": "選択",
195
+ "filters": "絞り込み",
196
+ "allFilter": "すべて",
197
+ "selected": "選択中 {count} 件",
198
+ "loading": "読み込み中",
199
+ "empty": "該当する項目がありません",
200
+ "error": "読み込めませんでした",
201
+ "confirm": "決定",
202
+ "cancel": "キャンセル",
203
+ "clear": "選択を解除",
204
+ "more": "さらに読み込む",
205
+ "openDialog": "一覧から選択"
188
206
  }
189
207
  },
190
208
  "feedback": {
@@ -186,6 +186,24 @@
186
186
  "remove": "Xóa {name}",
187
187
  "uploading": "Đang tải tệp đính kèm",
188
188
  "error": "Tải lên thất bại"
189
+ },
190
+ "recordPicker": {
191
+ "trigger": "Chọn",
192
+ "placeholder": "Chọn…",
193
+ "search": "Tìm kiếm",
194
+ "searchPlaceholder": "Tìm theo từ khoá",
195
+ "dialogTitle": "Chọn",
196
+ "filters": "Bộ lọc",
197
+ "allFilter": "Tất cả",
198
+ "selected": "Đã chọn {count}",
199
+ "loading": "Đang tải",
200
+ "empty": "Không có mục nào khớp",
201
+ "error": "Không tải được",
202
+ "confirm": "Xác nhận",
203
+ "cancel": "Huỷ",
204
+ "clear": "Bỏ chọn",
205
+ "more": "Tải thêm",
206
+ "openDialog": "Chọn từ danh sách"
189
207
  }
190
208
  },
191
209
  "feedback": {
@@ -1129,6 +1129,64 @@ export type SearchSelectOptionProp = {
1129
1129
  group?: string;
1130
1130
  disabled?: boolean;
1131
1131
  };
1132
+ /**
1133
+ * One consumer-declared filter on a RecordPicker dialog (gh#932). The `name` is the key the
1134
+ * picker puts into `loadOptions({ filters })`, so the server reads its own vocabulary back.
1135
+ */
1136
+ export type RecordPickerFilterProp = {
1137
+ name: string;
1138
+ label: string;
1139
+ options: {
1140
+ value: string;
1141
+ label: string;
1142
+ }[];
1143
+ };
1144
+ /**
1145
+ * RecordPicker — a picker whose SHAPE follows the size of the set behind it. Under `threshold`
1146
+ * it IS a `Select`; over it, a dialog with search and consumer-declared filters.
1147
+ */
1148
+ export type RecordPickerProp = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "value" | "defaultValue" | "onChange"> & {
1149
+ /** `single` (default) or `multiple`. Decides the value shape AND whether the dialog confirms. */
1150
+ mode?: "single" | "multiple";
1151
+ value?: string | string[] | null;
1152
+ defaultValue?: string | string[] | null;
1153
+ /** Receives the shape you passed in: an array for `multiple`, a single value (or null) else. */
1154
+ onValueChange?: (value: string | string[] | null) => void;
1155
+ /** Static rows, client-filtered. Provide this OR `loadOptions`. */
1156
+ options?: (SearchSelectOptionProp | SelectOptionGroupProp)[];
1157
+ /** Server fetcher. `filters` carries the consumer's own filter vocabulary. */
1158
+ loadOptions?: (params: {
1159
+ query: string;
1160
+ filters: Record<string, string>;
1161
+ cursor?: string;
1162
+ }) => Promise<{
1163
+ options: SearchSelectOptionProp[];
1164
+ count?: number;
1165
+ nextCursor?: string;
1166
+ }>;
1167
+ /**
1168
+ * Size of the WHOLE set, which only a server knows — a page of results does not. Omitted with
1169
+ * `options`, it is their length; omitted with `loadOptions`, the dialog shape is assumed.
1170
+ */
1171
+ count?: number;
1172
+ /** The dropdown/dialog switch. Default 10. */
1173
+ threshold?: number;
1174
+ /** Filters rendered above the dialog list; their values reach `loadOptions({ filters })`. */
1175
+ filters?: RecordPickerFilterProp[];
1176
+ /**
1177
+ * Labels for values the picker holds but has not loaded — on first render there IS no page. Kept
1178
+ * ahead of anything that loads later, so a chip never renders a raw id and never disappears.
1179
+ */
1180
+ selectedOptions?: SearchSelectOptionProp[];
1181
+ /** A real row meaning "none" (an unassigned owner), pinned first — not a cleared field. */
1182
+ emptyOption?: {
1183
+ value: string;
1184
+ label: string;
1185
+ };
1186
+ placeholder?: string;
1187
+ dialogTitle?: string;
1188
+ size?: "xs" | "sm" | "md" | "lg";
1189
+ };
1132
1190
  export type SearchSelectLoadParamsProp = {
1133
1191
  query: string;
1134
1192
  /** 1-based page for infinite scroll. */
@@ -1,6 +1,6 @@
1
1
  /** Foundation component prop types — @see docs/COMPONENTS.md#foundation */
2
2
  import type * as React from "react";
3
- import type { ActivityAnnounceProp, ActivityVariantProp, AsChildProp, ButtonSizeProp, ButtonVariantProp, ChildrenProp, ClassNameProp, DescriptionProp, DisabledProp, FontWeightProp, HeadingLevelProp, IconSizeProp, IdProp, InViewAmountProp, LabelProp, OnClickProp, OnOpenChangeProp, OpenProp, PendingProp, RevealDelayProp, RevealTriggerProp, ShapeProp, SizeProp, TextAlignProp, TextSizeProp, TextToneProp, TextWhitespaceProp, TitleLevelProp, TypographyActionsConfigProp, TypographyCopyConfigProp, TypographyEditConfigProp, TypographyEllipsisConfigProp, TypographyTypeProp } from "../vocabulary/index.js";
3
+ import type { ActivityAnnounceProp, ActivityVariantProp, AsChildProp, ButtonSizeProp, ButtonVariantProp, ChildrenProp, ClassNameProp, DescriptionProp, DisabledProp, FontWeightProp, HeadingLevelProp, IconSizeProp, IdProp, InViewAmountProp, LabelProp, OnClickProp, OnOpenChangeProp, OpenProp, PendingProp, RevealDelayProp, RevealTriggerProp, ShapeProp, SizeProp, TextAlignProp, TextSizeProp, TextToneProp, TextWhitespaceProp, TextBreakProp, TitleLevelProp, TypographyActionsConfigProp, TypographyCopyConfigProp, TypographyEditConfigProp, TypographyEllipsisConfigProp, TypographyTypeProp } from "../vocabulary/index.js";
4
4
  /**
5
5
  * @see Text — typographic primitive; replaces hand-rolled `<span className="text-[13px] …">`.
6
6
  *
@@ -66,6 +66,20 @@ export type TextProp = Omit<React.HTMLAttributes<HTMLElement>, "color"> & Omit<T
66
66
  * `clamp` composes with it — a clamped pre-wrap block shows its first N real lines.
67
67
  */
68
68
  whitespace?: TextWhitespaceProp;
69
+ /**
70
+ * Where an over-long unbroken token may break. Default `normal` (CSS's own: it stays whole).
71
+ *
72
+ * `anywhere` is for a MACHINE identifier — an email address, a coupon code, a login id, a
73
+ * template key — in a narrow `DataTable` cell or `Descriptions` value: it may be split at any
74
+ * character to fit, so the column shrinks to the viewport instead of scrolling the page. It
75
+ * also releases a `nowrap` it inherited (a table cell's default) back to `normal` — newlines
76
+ * still collapse, because an identifier's whitespace is not content.
77
+ *
78
+ * Independent of `whitespace`: `whitespace="pre-wrap" break="anywhere"` keeps typed line breaks
79
+ * AND splits a long token. `truncate` WINS (one line has nowhere to break to), so the attribute
80
+ * is not emitted under it; `clamp` composes.
81
+ */
82
+ break?: TextBreakProp;
69
83
  /** Tabular figures for aligned numbers. */
70
84
  tabular?: boolean;
71
85
  decoration?: "none" | "underline" | "line-through";
@@ -464,6 +464,11 @@ export declare const VOCABULARY_REGISTRY: {
464
464
  readonly category: "interaction";
465
465
  readonly description: "Whitespace handling normal | pre-wrap: `pre-wrap` keeps the newlines and indentation a person typed (a plain-text note, a pasted log) and still wraps at the container edge; `truncate` outranks it";
466
466
  };
467
+ readonly TextBreakProp: {
468
+ readonly file: "vocabulary/interaction.prop.ts";
469
+ readonly category: "interaction";
470
+ readonly description: "Where an over-long unbroken token may break normal | anywhere: `anywhere` (overflow-wrap: anywhere) lets a machine identifier (email, code, login id) split to fit a narrow table cell; independent of TextWhitespaceProp, and `truncate` outranks it";
471
+ };
467
472
  readonly TypographyTypeProp: {
468
473
  readonly file: "vocabulary/interaction.prop.ts";
469
474
  readonly category: "interaction";
@@ -1802,6 +1807,18 @@ export declare const COMPONENT_PROP_REGISTRY: {
1802
1807
  readonly vocabulary: readonly ["ValueProp", "OnValueChangeProp", "PlaceholderProp", "EmptyMessageProp", "DisabledProp", "NameProp", "IdProp", "ClassNameProp", "OpenProp", "OnOpenChangeProp", "SizeProp", "DefaultOpenProp", "ControlStatusProp", "ControlVariantProp", "AllowClearProp", "NotFoundContentProp", "PopupMatchWidthProp", "PendingProp"];
1803
1808
  readonly note: "Ant-style data-driven form of Select (options|loadOptions + showSearch). One Select for all single-selects.";
1804
1809
  };
1810
+ readonly RecordPickerProp: {
1811
+ readonly group: "data-entry";
1812
+ readonly file: "components/data-entry.prop.ts";
1813
+ readonly vocabulary: readonly ["ValueProp", "OnValueChangeProp", "DisabledProp", "SizeProp", "PlaceholderProp"];
1814
+ readonly note: "One picker whose SHAPE follows the size of the set: Select at or under `threshold`, a searchable Dialog with consumer-declared filters over it (gh#932).";
1815
+ };
1816
+ readonly RecordPickerFilterProp: {
1817
+ readonly group: "data-entry";
1818
+ readonly file: "components/data-entry.prop.ts";
1819
+ readonly vocabulary: readonly ["ValueProp", "LabelProp"];
1820
+ readonly note: "One filter on a RecordPicker dialog. `name` is the key that reaches loadOptions({ filters }), so the server reads its own vocabulary back.";
1821
+ };
1805
1822
  readonly SearchSelectOptionProp: {
1806
1823
  readonly group: "data-entry";
1807
1824
  readonly file: "components/data-entry.prop.ts";
@@ -463,6 +463,11 @@ const VOCABULARY_REGISTRY = {
463
463
  category: "interaction",
464
464
  description: "Whitespace handling normal | pre-wrap: `pre-wrap` keeps the newlines and indentation a person typed (a plain-text note, a pasted log) and still wraps at the container edge; `truncate` outranks it"
465
465
  },
466
+ TextBreakProp: {
467
+ file: "vocabulary/interaction.prop.ts",
468
+ category: "interaction",
469
+ description: "Where an over-long unbroken token may break normal | anywhere: `anywhere` (overflow-wrap: anywhere) lets a machine identifier (email, code, login id) split to fit a narrow table cell; independent of TextWhitespaceProp, and `truncate` outranks it"
470
+ },
466
471
  TypographyTypeProp: {
467
472
  file: "vocabulary/interaction.prop.ts",
468
473
  category: "interaction",
@@ -2138,6 +2143,18 @@ const COMPONENT_PROP_REGISTRY = {
2138
2143
  ],
2139
2144
  note: "Ant-style data-driven form of Select (options|loadOptions + showSearch). One Select for all single-selects."
2140
2145
  },
2146
+ RecordPickerProp: {
2147
+ group: "data-entry",
2148
+ file: "components/data-entry.prop.ts",
2149
+ vocabulary: ["ValueProp", "OnValueChangeProp", "DisabledProp", "SizeProp", "PlaceholderProp"],
2150
+ note: "One picker whose SHAPE follows the size of the set: Select at or under `threshold`, a searchable Dialog with consumer-declared filters over it (gh#932)."
2151
+ },
2152
+ RecordPickerFilterProp: {
2153
+ group: "data-entry",
2154
+ file: "components/data-entry.prop.ts",
2155
+ vocabulary: ["ValueProp", "LabelProp"],
2156
+ note: "One filter on a RecordPicker dialog. `name` is the key that reaches loadOptions({ filters }), so the server reads its own vocabulary back."
2157
+ },
2141
2158
  SearchSelectOptionProp: {
2142
2159
  group: "data-entry",
2143
2160
  file: "components/data-entry.prop.ts",
@@ -2,6 +2,6 @@
2
2
  export type { ClassNameProp, ChildrenProp, IdProp, OpenProp, DefaultOpenProp, OnOpenChangeProp, HandlerProp, PendingProp, RequiredProp, DisabledProp, LabelProp, HelperProp, ErrorProp, ErrorBagProp, PlaceholderProp, NameProp, ValueProp, DefaultValueProp, OnValueChangeProp, OnChangeProp, OnClickProp, AsChildProp, FlushProp, WidthProp, ControlWidthProp, AllowClearProp, MaxTagCountProp, MaxTagPlaceholderProp, NotFoundContentProp, PopupMatchWidthProp, } from "./shared.prop.js";
3
3
  export type { TitleProp, SubtitleProp, StatusProp, DescriptionProp, ExtraProp, FooterProp, ActionProp, IconProp, ConfirmLabelProp, CancelLabelProp, ActionsProp, EmptyMessageProp, } from "./content.prop.js";
4
4
  export type { PageDensityProp, PageContainerVariantProp, CenteredShellWidthProp, CenteredShellAlignProp, CenteredShellPresetProp, ErrorSurfaceModeProp, ErrorSurfaceStatusProp, AuthShellPresetProp, MobileShellHeightProp, MobileShellWidthProp, OrientationProp, TableDensityProp, DensityProp, GapNameProp, PadProp, PadRawProp, PadSides, GapProp, GapStepProp, } from "./layout.prop.js";
5
- export type { ButtonVariantProp, ButtonSizeProp, BadgeVariantProp, AppSettingPickerAppearanceProp, AppSettingToggleAppearanceProp, ShapeProp, AvatarShapeProp, TextSizeProp, TextToneProp, FontWeightProp, HeadingLevelProp, TextAlignProp, TextWhitespaceProp, TypographyTypeProp, TitleLevelProp, TypographyCopyConfigProp, TypographyEditConfigProp, TypographyEllipsisConfigProp, TypographyActionsConfigProp, SizeProp, ControlStatusProp, ControlVariantProp, FormLayoutProp, DescriptionsLayoutProp, BreakpointProp, ConfirmVariantProp, ToneProp, AlertVariantProp, CalloutKindProp, SortDirectionProp, ColumnAlignProp, SortStateProp, RevealDelayProp, RevealTriggerProp, InViewAmountProp, ActivityVariantProp, ActivityAnnounceProp, IconSizeProp, } from "./interaction.prop.js";
5
+ export type { ButtonVariantProp, ButtonSizeProp, BadgeVariantProp, AppSettingPickerAppearanceProp, AppSettingToggleAppearanceProp, ShapeProp, AvatarShapeProp, TextSizeProp, TextToneProp, FontWeightProp, HeadingLevelProp, TextAlignProp, TextWhitespaceProp, TextBreakProp, TypographyTypeProp, TitleLevelProp, TypographyCopyConfigProp, TypographyEditConfigProp, TypographyEllipsisConfigProp, TypographyActionsConfigProp, SizeProp, ControlStatusProp, ControlVariantProp, FormLayoutProp, DescriptionsLayoutProp, BreakpointProp, ConfirmVariantProp, ToneProp, AlertVariantProp, CalloutKindProp, SortDirectionProp, ColumnAlignProp, SortStateProp, RevealDelayProp, RevealTriggerProp, InViewAmountProp, ActivityVariantProp, ActivityAnnounceProp, IconSizeProp, } from "./interaction.prop.js";
6
6
  export type { BreadcrumbItemProp, BreadcrumbProp, BreadcrumbItemMenuProp, BreadcrumbItemMenuEntryProp, BreadcrumbSeparatorProp, BreadcrumbItemRenderProp, } from "./navigation.prop.js";
7
7
  export type { GetRowIdProp, GetRowLabelProp, OnRowClickProp, ColumnDefProp, TablePresetProp, TableColumnPriorityProp, TableCellIndentProp, SelectedIdsProp, OnSelectChangeProp, OnTableDensityChangeProp, TableRowToneProp, RowToneProp, OnSortChangeProp, OnSearchChangeProp, OnClearFiltersProp, HasActiveFiltersProp, StickyProp, ColumnFixedProp, ColumnFilterValueProp, ColumnFilterItemProp, ColumnFilterStateProp, OnColumnFilterChangeProp, ColumnCompareProp, ColumnSorterProp, TableSelectionItemProp, TableRowSelectionProp, TableExpandableProp, TableSummaryProp, TableScrollProp, TableStickyProp, OnRowProp, TablePaginationProp, TablePaginationPositionProp, DescriptionsColumnProp, DescriptionsSpanProp, DescriptionsItemsProp, } from "./data.prop.js";
@@ -96,6 +96,19 @@ export type TextAlignProp = "start" | "center" | "end";
96
96
  * remaining CSS keywords (`pre`, `pre-line`, `nowrap`) are values on the same axis, not more flags.
97
97
  */
98
98
  export type TextWhitespaceProp = "normal" | "pre-wrap";
99
+ /**
100
+ * Where a run of text may break an over-long token that has no break opportunity of its own — an
101
+ * email address, a coupon code, a login id, a template key (gh#927).
102
+ *
103
+ * `normal` is CSS's own behaviour and the default: an unbroken token stays whole and overflows.
104
+ *
105
+ * `anywhere` is `overflow-wrap: anywhere`. It is a SEPARATE axis from {@link TextWhitespaceProp}
106
+ * because the two answer different questions: `whitespace` says whether the line breaks a person
107
+ * typed are content, `break` says whether a machine identifier may be split to fit. Only `anywhere`
108
+ * — not `break-word` — lowers the box's min-content size (CSS Text 3 §5.5), which is what a table
109
+ * cell sizes its column from; `break-word` breaks in a block and still holds a `<td>` open.
110
+ */
111
+ export type TextBreakProp = "normal" | "anywhere";
99
112
  /**
100
113
  * antd `Typography` `type` — its four-value emphasis axis (`BaseType`).
101
114
  *
@@ -657,7 +657,9 @@
657
657
 
658
658
  .ui-carousel-item {
659
659
  position: relative;
660
- min-width: 100%;
660
+ flex-shrink: 0;
661
+ inline-size: 100%;
662
+ min-inline-size: 0;
661
663
  padding-inline: var(--space-4);
662
664
  }
663
665
 
@@ -675,8 +677,9 @@
675
677
  );
676
678
  z-index: 20;
677
679
  display: grid;
678
- width: 2rem;
679
- height: 2rem;
680
+
681
+ inline-size: var(--carousel-arrow-size);
682
+ block-size: var(--carousel-arrow-size);
680
683
  place-items: center;
681
684
  border-radius: var(--radius-pill);
682
685
  background: hsl(var(--background));
@@ -764,3 +764,74 @@
764
764
  text-align: start;
765
765
  }
766
766
  }
767
+
768
+ @layer components {
769
+
770
+ .ui-record-picker-trigger {
771
+ justify-content: space-between;
772
+ inline-size: 100%;
773
+ min-block-size: var(--control-height);
774
+ block-size: auto;
775
+ padding-block: var(--space-1);
776
+ }
777
+
778
+ .ui-record-picker-trigger-label {
779
+ display: flex;
780
+ flex: 1 1 auto;
781
+ min-inline-size: 0;
782
+ text-align: start;
783
+ }
784
+
785
+ .ui-record-picker-list {
786
+ max-block-size: var(--record-picker-list-max-block-size);
787
+ overflow-y: auto;
788
+ }
789
+
790
+ .ui-record-picker-option {
791
+ display: flex;
792
+ inline-size: 100%;
793
+ align-items: center;
794
+ gap: var(--space-2);
795
+ padding: var(--space-2) var(--space-3);
796
+ border-radius: var(--radius-md);
797
+ text-align: start;
798
+ color: inherit;
799
+ }
800
+ .ui-record-picker-option:disabled {
801
+ opacity: var(--disabled-opacity);
802
+ cursor: not-allowed;
803
+ }
804
+
805
+ @media (hover: hover) {
806
+ .ui-record-picker-option:hover {
807
+ background-color: hsl(var(--accent));
808
+ }
809
+ }
810
+ .ui-record-picker-option[data-picked] {
811
+ color: hsl(var(--text-brand, var(--primary)));
812
+ font-weight: var(--font-weight-medium);
813
+ }
814
+ .ui-record-picker-tick {
815
+ display: grid;
816
+ place-items: center;
817
+ inline-size: var(--icon-size-md);
818
+ block-size: var(--icon-size-md);
819
+ flex: 0 0 auto;
820
+ }
821
+ .ui-record-picker-tick svg {
822
+ inline-size: var(--icon-size-md);
823
+ block-size: var(--icon-size-md);
824
+ }
825
+
826
+ .ui-record-picker-option-label {
827
+ display: flex;
828
+ flex-direction: column;
829
+ min-inline-size: 0;
830
+ }
831
+
832
+ .ui-record-picker-status {
833
+ padding: var(--space-4);
834
+ color: hsl(var(--muted-foreground));
835
+ font-size: var(--font-size-sm);
836
+ }
837
+ }
@@ -285,6 +285,14 @@
285
285
  }
286
286
  }
287
287
 
288
+ [data-slot="popover-content"][data-state="closed"],
289
+ [data-slot="dropdown-menu-content"][data-state="closed"],
290
+ [data-slot="dropdown-menu-sub-content"][data-state="closed"],
291
+ [data-slot="hover-card-content"][data-state="closed"],
292
+ [data-slot="tooltip-content"][data-state="closed"] {
293
+ pointer-events: none;
294
+ }
295
+
288
296
  @layer components {
289
297
 
290
298
  .ui-tooltip-content {
@@ -4,6 +4,8 @@
4
4
  :is(
5
5
  .ui-focus-ring,
6
6
  .ui-focus-ring-outline,
7
+ [data-interactive] > [data-slot="table-cell"] a[href],
8
+ [data-interactive] > [data-slot="table-cell"] button,
7
9
  .ui-input,
8
10
  .ui-control,
9
11
  .ui-control-multiline,
@@ -15,6 +15,19 @@
15
15
  border-block-end-width: 0;
16
16
  }
17
17
 
18
+ .ui-table-row[data-interactive] {
19
+ cursor: pointer;
20
+ }
21
+ @media (hover: hover) {
22
+ .ui-table-row[data-interactive]:hover {
23
+ background-color: color-mix(
24
+ in oklab,
25
+ hsl(var(--accent)) var(--table-row-hover-background-alpha, 70%),
26
+ transparent
27
+ );
28
+ }
29
+ }
30
+
18
31
  .ui-table-row[data-tone="primary"] {
19
32
  --table-row-tone-color: var(
20
33
  --mark-primary,
@@ -161,6 +161,14 @@
161
161
  min-inline-size: 0;
162
162
  }
163
163
 
164
+ [data-slot="text"][data-break="anywhere"] {
165
+ overflow-wrap: anywhere;
166
+ min-inline-size: 0;
167
+ }
168
+ [data-slot="text"][data-break="anywhere"]:not([data-whitespace]) {
169
+ white-space: normal;
170
+ }
171
+
164
172
  [data-slot="text"][data-clamp] {
165
173
  display: -webkit-box;
166
174
  -webkit-box-orient: vertical;
@@ -5,6 +5,8 @@
5
5
  --accordion-chevron-size: var(--icon-size-md);
6
6
  --carousel-arrow-icon-size: var(--icon-size-md);
7
7
 
8
+ --carousel-arrow-size: 2rem;
9
+
8
10
  --carousel-arrow-inset-block-start: initial;
9
11
  --carousel-dots-block-size: 0px;
10
12
 
@@ -1,6 +1,9 @@
1
1
 
2
2
 
3
3
  :root {
4
+
5
+ --record-picker-list-max-block-size: 22rem;
6
+
4
7
  --password-strength-score-font-size: var(
5
8
  --font-size-xs,
6
9
  calc(var(--font-size-base) / var(--font-size-ratio))
@@ -3,8 +3,8 @@
3
3
  > Generated by `scripts/frame-coverage.mjs` (issue #163). Do not edit by hand — run `pnpm check:frame-coverage`.
4
4
  > Standard: [FRAME-COVERAGE-STANDARD.md](./FRAME-COVERAGE-STANDARD.md). A missing dimension is **UNTESTED**, never a pass.
5
5
 
6
- - Public components: **172**
7
- - With ≥1 frame: **151** · zero-frame: **21**
6
+ - Public components: **173**
7
+ - With ≥1 frame: **152** · zero-frame: **21**
8
8
  - Fully covered (every contract axis declared): **0**
9
9
 
10
10
  ## UNTESTED — no `/frame/**` route
@@ -106,6 +106,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
106
106
  | Input | ✓ | ✓ | · | · | · | · | · | · | · | · |
107
107
  | NumberInput | ✓ | ✓ | · | · | · | · | · | · | · | · |
108
108
  | SearchInput | ✓ | ✓ | · | · | · | · | · | · | · | · |
109
+ | RecordPicker | ✓ | · | · | · | · | · | · | · | · | · |
109
110
  | Select | ✓ | · | · | · | · | · | · | · | · | · |
110
111
  | Switch | ✓ | ✓ | · | · | · | · | · | · | · | · |
111
112
  | Textarea | ✓ | ✓ | · | · | · | · | · | · | · | · |
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s0" x2="0" y2="1"><stop stop-color="#DFF3FF"/><stop offset="1" stop-color="#BDCAFB"/></linearGradient><linearGradient id="r0" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s0)"/><circle cx="410" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#486F95" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#486F95"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#0F4C5C"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r0)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 01</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s1" x2="0" y2="1"><stop stop-color="#FFF2E7"/><stop offset="1" stop-color="#FFCED1"/></linearGradient><linearGradient id="r1" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s1)"/><circle cx="391" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#AA7BA9" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#AA7BA9"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#625582"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r1)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 02</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s2" x2="0" y2="1"><stop stop-color="#E5F6F0"/><stop offset="1" stop-color="#BDE7E5"/></linearGradient><linearGradient id="r2" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s2)"/><circle cx="372" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#65AAA7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#65AAA7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#326B71"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r2)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 03</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s3" x2="0" y2="1"><stop stop-color="#F2EAFF"/><stop offset="1" stop-color="#DCC4FD"/></linearGradient><linearGradient id="r3" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s3)"/><circle cx="353" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#9784C7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#9784C7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#57578D"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r3)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 04</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s4" x2="0" y2="1"><stop stop-color="#FFF3CF"/><stop offset="1" stop-color="#F4D7BE"/></linearGradient><linearGradient id="r4" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s4)"/><circle cx="334" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#B89599" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#B89599"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#6E6883"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r4)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 05</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s5" x2="0" y2="1"><stop stop-color="#E2EAFB"/><stop offset="1" stop-color="#B9D7ED"/></linearGradient><linearGradient id="r5" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s5)"/><circle cx="315" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#597FAE" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#597FAE"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#214D75"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r5)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 06</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="1200" height="760" viewBox="0 0 1200 760" role="img"><title>Layered Prism original decorative atmosphere</title><defs></defs><rect width="1200" height="760" fill="#F8FAFC"/><ellipse cx="900" cy="170" rx="560" ry="420" fill="#EAF7FF"/><ellipse cx="500" cy="790" rx="660" ry="380" fill="#F2EEFF"/><ellipse cx="1080" cy="650" rx="360" ry="310" fill="#FFF0EF"/><g transform="translate(390 150) rotate(-19 102.5 147.5)"><rect x="-8" y="-8" width="221" height="311" rx="20" fill="white"/><svg width="205" height="295" viewBox="0 0 630 880"><defs><linearGradient id="s1" x2="0" y2="1"><stop stop-color="#FFF2E7"/><stop offset="1" stop-color="#FFCED1"/></linearGradient><linearGradient id="r1" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s1)"/><circle cx="391" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#AA7BA9" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#AA7BA9"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#625582"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r1)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg></g><g transform="translate(640 110) rotate(11 132.5 190.0)"><rect x="-8" y="-8" width="281" height="396" rx="20" fill="white"/><svg width="265" height="380" viewBox="0 0 630 880"><defs><linearGradient id="s3" x2="0" y2="1"><stop stop-color="#F2EAFF"/><stop offset="1" stop-color="#DCC4FD"/></linearGradient><linearGradient id="r3" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s3)"/><circle cx="353" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#9784C7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#9784C7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#57578D"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r3)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg></g><g transform="translate(850 325) rotate(24 102.5 147.5)"><rect x="-8" y="-8" width="221" height="311" rx="20" fill="white"/><svg width="205" height="295" viewBox="0 0 630 880"><defs><linearGradient id="s2" x2="0" y2="1"><stop stop-color="#E5F6F0"/><stop offset="1" stop-color="#BDE7E5"/></linearGradient><linearGradient id="r2" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s2)"/><circle cx="372" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#65AAA7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#65AAA7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#326B71"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r2)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg></g><g stroke="#0F4C5C" stroke-opacity=".12" fill="none"><ellipse cx="740" cy="410" rx="420" ry="190" transform="rotate(-18 740 410)"/></g><path fill="#A78BFA" d="M350 416Q352 438 374 440Q352 442 350 464Q348 442 326 440Q348 438 350 416Z"/><path fill="#FF7B7B" d="M950 113Q952 138 977 140Q952 142 950 167Q948 142 923 140Q948 138 950 113Z"/><path fill="#38B6FF" d="M540 52Q542 68 558 70Q542 72 540 88Q538 72 522 70Q538 68 540 52Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Original abstract landscape 1; not an actual game card</title><defs><linearGradient id="s0" x2="0" y2="1"><stop stop-color="#DFF3FF"/><stop offset="1" stop-color="#BDCAFB"/></linearGradient><linearGradient id="r0" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s0)"/><circle cx="410" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#486F95" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#486F95"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#0F4C5C"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r0)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Original abstract landscape 2; not an actual game card</title><defs><linearGradient id="s1" x2="0" y2="1"><stop stop-color="#FFF2E7"/><stop offset="1" stop-color="#FFCED1"/></linearGradient><linearGradient id="r1" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s1)"/><circle cx="391" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#AA7BA9" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#AA7BA9"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#625582"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r1)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Original abstract landscape 3; not an actual game card</title><defs><linearGradient id="s2" x2="0" y2="1"><stop stop-color="#E5F6F0"/><stop offset="1" stop-color="#BDE7E5"/></linearGradient><linearGradient id="r2" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s2)"/><circle cx="372" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#65AAA7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#65AAA7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#326B71"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r2)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Original abstract landscape 4; not an actual game card</title><defs><linearGradient id="s3" x2="0" y2="1"><stop stop-color="#F2EAFF"/><stop offset="1" stop-color="#DCC4FD"/></linearGradient><linearGradient id="r3" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s3)"/><circle cx="353" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#9784C7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#9784C7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#57578D"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r3)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Original abstract landscape 5; not an actual game card</title><defs><linearGradient id="s4" x2="0" y2="1"><stop stop-color="#FFF3CF"/><stop offset="1" stop-color="#F4D7BE"/></linearGradient><linearGradient id="r4" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s4)"/><circle cx="334" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#B89599" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#B89599"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#6E6883"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r4)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="510" height="150" viewBox="0 0 510 150" role="img"><title>TCG-M horizontal lockup / color</title><defs><linearGradient id="back" x1="0" y1="0" x2=".2" y2="1"><stop stop-color="#FF7B7B"/><stop offset="1" stop-color="#A78BFA"/></linearGradient><linearGradient id="rim" x1="0" y1="0" x2=".3" y2="1"><stop stop-color="#FFC66E"/><stop offset=".5" stop-color="#FF7B7B"/><stop offset="1" stop-color="#A78BFA"/></linearGradient><linearGradient id="left" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#16819A"/><stop offset="1" stop-color="#0F4C5C"/></linearGradient><linearGradient id="right" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#136E88"/><stop offset="1" stop-color="#0F4C5C"/></linearGradient><linearGradient id="spark" x1="0" y1="0" x2="0" y2="1"><stop stop-color="#A78BFA"/><stop offset=".5" stop-color="#FF7B7B"/><stop offset="1" stop-color="#FFC66E"/></linearGradient></defs><g transform="translate(0 0) scale(.55)"><path d="M31 67 Q22 64 25 78 L54 202 Q58 216 64 222 L45 69Z" fill="url(#back)"/><path d="M66 225 L55 68 Q54 53 66 49 L161 16 Q172 12 173 25 L173 31 L72 66Z" fill="url(#rim)"/><path d="M78 72 L181 36 Q192 32 192 45 L192 139 L151 174Z" fill="#38B6FF"/><path d="M204 53 L215 57 Q222 60 222 70 L222 109 L203 126Z" fill="url(#right)"/><path d="M76 87 L143 146 Q153 155 153 168 L153 188 Q153 197 145 191 L116 168 L116 219 L77 233 Q69 236 70 226Z" fill="url(#left)"/><path d="M167 167 Q168 155 177 146 L231 101 Q240 95 241 107 L241 203 L204 218 L204 168 L175 191 Q167 197 167 186Z" fill="url(#right)"/><path d="M161 167 C163 194 169 202 188 209 C169 214 164 221 161 244 C157 220 151 215 134 209 C152 204 157 195 161 167Z" fill="url(#spark)"/></g><g transform="translate(164 44) scale(.92)" fill="#0F4C5C"><path d="M0 0H63V15H40V73H23V15H0Z"/><path d="M138 5L132 22C124 17 119 15 112 15C95 15 86 24 86 37C86 51 96 59 111 59C120 59 126 56 133 51L140 66C131 72 121 76 110 76C84 76 67 60 67 37C67 15 84-2 111-2C122-2 131 0 138 5Z"/><path d="M215 7L206 21C198 16 192 14 183 14C169 14 159 23 159 37C159 50 169 60 183 60C189 60 194 59 199 56V46H181V32H216V65C208 72 195 76 182 76C158 76 142 60 142 37C142 14 159-2 183-2C196-2 207 1 215 7Z"/><path d="M228 31H258V45H228Z"/><path d="M271 0H288L311 32L334 0H351V73H334V28L311 60L288 28V73H271Z"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="264" height="264" viewBox="0 0 264 264" role="img"><title>TCG-M Layered Prism symbol / color</title><defs><linearGradient id="back" x1="0" y1="0" x2=".2" y2="1"><stop stop-color="#FF7B7B"/><stop offset="1" stop-color="#A78BFA"/></linearGradient><linearGradient id="rim" x1="0" y1="0" x2=".3" y2="1"><stop stop-color="#FFC66E"/><stop offset=".5" stop-color="#FF7B7B"/><stop offset="1" stop-color="#A78BFA"/></linearGradient><linearGradient id="left" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#16819A"/><stop offset="1" stop-color="#0F4C5C"/></linearGradient><linearGradient id="right" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#136E88"/><stop offset="1" stop-color="#0F4C5C"/></linearGradient><linearGradient id="spark" x1="0" y1="0" x2="0" y2="1"><stop stop-color="#A78BFA"/><stop offset=".5" stop-color="#FF7B7B"/><stop offset="1" stop-color="#FFC66E"/></linearGradient></defs><path d="M31 67 Q22 64 25 78 L54 202 Q58 216 64 222 L45 69Z" fill="url(#back)"/><path d="M66 225 L55 68 Q54 53 66 49 L161 16 Q172 12 173 25 L173 31 L72 66Z" fill="url(#rim)"/><path d="M78 72 L181 36 Q192 32 192 45 L192 139 L151 174Z" fill="#38B6FF"/><path d="M204 53 L215 57 Q222 60 222 70 L222 109 L203 126Z" fill="url(#right)"/><path d="M76 87 L143 146 Q153 155 153 168 L153 188 Q153 197 145 191 L116 168 L116 219 L77 233 Q69 236 70 226Z" fill="url(#left)"/><path d="M167 167 Q168 155 177 146 L231 101 Q240 95 241 107 L241 203 L204 218 L204 168 L175 191 Q167 197 167 186Z" fill="url(#right)"/><path d="M161 167 C163 194 169 202 188 209 C169 214 164 221 161 244 C157 220 151 215 134 209 C152 204 157 195 161 167Z" fill="url(#spark)"/></svg>