Skip to content

update theme and skill card refs#4235

Merged
burieberry merged 3 commits intomainfrom
update-catalog-theme-refs
Mar 24, 2026
Merged

update theme and skill card refs#4235
burieberry merged 3 commits intomainfrom
update-catalog-theme-refs

Conversation

@burieberry
Copy link
Contributor

No description provided.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 859d062059

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@github-actions
Copy link

github-actions bot commented Mar 23, 2026

Host Test Results

    1 files  ±0      1 suites  ±0   2h 6m 17s ⏱️ - 1m 18s
2 030 tests ±0  2 015 ✅ ±0  15 💤 ±0  0 ❌ ±0 
2 045 runs  ±0  2 030 ✅ ±0  15 💤 ±0  0 ❌ ±0 

Results for commit 835cbc1. ± Comparison against base commit 55a0f23.

♻️ This comment has been updated with latest results.

@burieberry burieberry requested a review from a team March 23, 2026 21:32
@habdelra habdelra requested a review from Copilot March 23, 2026 22:40
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates theme references to point at the canonical Base realm Theme cards (not app.boxel.ai catalog URLs / in-realm relative theme paths), and removes/realigns Catalog realm “Skill*” card implementations in favor of the packages/base versions.

Changes:

  • Update multiple card instances/docs to use https://cardstack.com/base/Theme/cardstack-brand-guide (and Boxel’s brand guide) as the default theme link.
  • Remove Catalog realm implementations of skill-plus, skill-set, and skill-reference (now present under packages/base).
  • Refresh theme/theming documentation and update SkillPlusMarkdown spec metadata.

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/software-factory/experiment_1/realms/guidance-tasks/Ticket/ticket-001.json Update default theme relationship link to Base realm theme.
packages/software-factory/experiment_1/realms/guidance-tasks/Project/demo-project.json Update default theme relationship link to Base realm theme.
packages/software-factory/experiment_1/realms/guidance-tasks/KnowledgeArticle/agent-onboarding.json Update default theme relationship link to Base realm theme.
packages/software-factory/experiment_1/.agents/skills/boxel-development/references/dev-theme-design-system.md Update theme URL + refresh theme docs/examples.
packages/software-factory/.agents/skills/boxel-development/references/dev-theme-design-system.md Same documentation updates as experiment_1 copy.
packages/realm-server/scripts/migrate-realm-references.sh Update comment examples for reference migration script.
packages/experiments-realm/ProductCatalog/main.json Update default theme relationship link to Base realm theme.
packages/catalog-realm/skill-set.gts Remove catalog-realm SkillSet implementation (now in Base).
packages/catalog-realm/skill-reference.gts Remove catalog-realm SkillReference implementation (now in Base).
packages/catalog-realm/skill-plus.gts Remove catalog-realm SkillPlus implementation (now in Base).
packages/catalog-realm/ThemeListing/f87667d9-7616-4baf-b2fe-8ce5d393f676.json Point theme example/theme relationship to Base realm cardstack brand guide.
packages/catalog-realm/ThemeListing/d7691256-67a2-48dc-91f6-2d76db7a0941.json Remove a ThemeListing entry (old Cardstack theme listing).
packages/catalog-realm/ThemeListing/4d6390f1-3bae-4e75-a95d-4309010e03e4.json Point theme example/theme relationship to Base realm boxel brand guide.
packages/catalog-realm/Theme/winter-wonderland.json Remove theme card JSON (catalog realm cleanup).
packages/catalog-realm/Theme/modern-blue.json Remove theme card JSON (catalog realm cleanup).
packages/catalog-realm/Theme/mint-method.json Remove theme card JSON (catalog realm cleanup).
packages/catalog-realm/Theme/luxury-auction.json Remove theme card JSON (catalog realm cleanup).
packages/catalog-realm/Theme/literary-review.json Remove theme card JSON (catalog realm cleanup).
packages/catalog-realm/Theme/kitchen-editorial.json Remove theme card JSON (catalog realm cleanup).
packages/catalog-realm/Theme/funkadelic-fever.json Remove theme card JSON (catalog realm cleanup).
packages/catalog-realm/Theme/cardstack.json Remove old Theme card JSON (replaced by Base realm brand guide).
packages/catalog-realm/Theme/cardstack-brand-guide.json Remove old Brand Guide theme JSON (now under packages/base/Theme/).
packages/catalog-realm/Theme/boxel-brand-guide.json Remove old Brand Guide theme JSON (now under Base realm).
packages/catalog-realm/Theme/botanical.json Remove theme card JSON (catalog realm cleanup).
packages/catalog-realm/SubmissionCardPortal/b535d5fb-8eef-44a6-8114-4bce6929b95a.json Update theme relationship from in-realm theme to Base realm brand guide.
packages/catalog-realm/Statement/theming-system.json Rewrite theming guidance content + adjust cardInfo metadata.
packages/catalog-realm/Spec/skill-set.json Remove catalog-realm SkillSet spec card (exists under packages/base/cards/skill-set.json).
packages/base/cards/skill-plus-markdown.json Update SkillPlusMarkdown spec metadata/module reference.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

"name": "[card title here]",
"summary": "[brief card description here]",
"cardThumbnailURL": "[card thumbnail url here]"
},
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The json snippet under “cardInfo properties” is not valid JSON: it has a trailing comma after the cardInfo object and is missing the closing } for the attributes object. Since this is meant to be copy/pasteable, please make the example valid JSON (or change the code fence to a format that allows trailing commas).

Suggested change
},
}

Copilot uses AI. Check for mistakes.
"name": "[card title here]",
"summary": "[brief card description here]",
"cardThumbnailURL": "[card thumbnail url here]"
},
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The json snippet under “cardInfo properties” is not valid JSON: it has a trailing comma after the cardInfo object and is missing the closing } for the attributes object. Since this is meant to be copy/pasteable, please make the example valid JSON (or change the code fence to a format that allows trailing commas).

Suggested change
},
}

Copilot uses AI. Check for mistakes.
"type": "card",
"attributes": {
"content": "# Theming System and CSS Variables\n\nBoxel uses CSS custom properties (variables) for theming. When creating fields, use these variables with appropriate fallbacks that match your field's design system.\n\n## Available Theme Variables\n\n### Shadcn Design System Variables\n\n**Colors:**\n- `--foreground`, `--background`\n- `--primary`, `--primary-foreground`\n- `--secondary`, `--secondary-foreground`\n- `--muted`, `--muted-foreground`\n- `--accent`, `--accent-foreground`\n- `--card`, `--card-foreground`\n- `--popover`, `--popover-foreground`\n- `--destructive`, `--destructive-foreground`\n- `--input`, `--ring`, `--border`\n\n**Charts:** `--chart1`, `--chart2`, `--chart3`, `--chart4`, `--chart5`\n\n**Sidebar:**\n- `--sidebar`, `--sidebar-foreground`\n- `--sidebar-primary`, `--sidebar-primary-foreground`\n- `--sidebar-accent`, `--sidebar-accent-foreground`\n- `--sidebar-border`, `--sidebar-ring`\n\n**Typography:** `--font-sans`, `--font-serif`, `--font-mono`, `--tracking-normal`\n\n**Layout:** `--radius`, `--spacing`\n\n**Shadows:** `--shadow2xs`, `--shadow-xs`, `--shadow-sm`, `--shadow`, `--shadow-md`, `--shadow-lg`, `--shadow-xl`, `--shadow2xl`\n\n### Brand Variables\n\n**Brand Colors:**\n- `--brand-primary`, `--brand-secondary`, `--brand-accent`\n- `--brand-neutral`, `--brand-light`, `--brand-dark`\n- `--brand-border`\n\n**Brand Layout:**\n- `--brand-radius`\n- `--brand-spacing`\n\n**Brand Typography:**\n- `--brand-heading-font-family`, `--brand-heading-font-size`, `--brand-heading-font-weight`, `--brand-heading-line-height`\n- `--brand-body-font-family`, `--brand-body-font-size`, `--brand-body-font-weight`, `--brand-body-line-height`\n\n**Brand Logos & Icons:**\n- Primary Mark: `--brand-primary-mark1`, `--brand-primary-mark2`, `--brand-primary-mark-greyscale1`, `--brand-primary-mark-greyscale2`, `--brand-primary-mark-clearance-ratio`, `--brand-primary-mark-min-height`\n- Secondary Mark: `--brand-secondary-mark1`, `--brand-secondary-mark2`, `--brand-secondary-mark-greyscale1`, `--brand-secondary-mark-greyscale2`, `--brand-secondary-mark-clearance-ratio`, `--brand-secondary-mark-min-height`\n- `--brand-social-media-profile-icon`\n\n### Brand to Shadcn Mapping\n\nThe system automatically maps brand variables to shadcn variables:\n\n```css\n--primary: var(--brand-primary);\n--secondary: var(--brand-secondary);\n--muted: var(--brand-neutral);\n--accent: var(--brand-accent);\n--background: var(--brand-light);\n--foreground: var(--brand-dark);\n--border: var(--brand-border);\n--radius: var(--brand-radius);\n--spacing: calc(var(--brand-spacing) / 4);\n```\n\nForeground colors (`--primary-foreground`, `--secondary-foreground`, `--muted-foreground`, `--accent-foreground`) are automatically determined based on contrast using `--brand-light` and `--brand-dark`.\n\n## Usage Pattern\n\n**Always provide fallbacks matching your field's design:**\n\n```gts\nexport class CustomField extends FieldDef {\n static edit = class Edit extends Component<typeof this> {\n <template>\n <input class=\"custom-input\" type=\"text\" />\n \n <style scoped>\n .custom-input {\n /* Theme variable with design-appropriate fallback */\n background: var(--input, #f5f5f5);\n color: var(--foreground, #1a1a1a);\n border: 1px solid var(--border, #e0e0e0);\n border-radius: var(--radius, 0.375rem);\n padding: calc(var(--spacing, 0.25rem) * 2);\n font-family: var(--font-sans, system-ui, sans-serif);\n }\n \n .custom-input:focus {\n outline: 2px solid var(--ring, #3b82f6);\n outline-offset: 2px;\n }\n \n .custom-input::placeholder {\n color: var(--muted-foreground, #9ca3af);\n }\n </style>\n </template>\n };\n}\n```\n\n## State Examples\n\n**Interactive states:**\n```css\n.button {\n background: var(--primary, #3b82f6);\n color: var(--primary-foreground, #ffffff);\n}\n\n.button:hover {\n background: var(--accent, #60a5fa);\n color: var(--accent-foreground, #1e293b);\n}\n\n.button:disabled {\n background: var(--muted, #f1f5f9);\n color: var(--muted-foreground, #94a3b8);\n opacity: 0.6;\n}\n```\n\n**Error states:**\n```css\n.input-error {\n border-color: var(--destructive, #ef4444);\n}\n\n.error-message {\n color: var(--destructive, #ef4444);\n font-size: 0.875rem;\n}\n```\n\n## Layout Patterns\n\n**Spacing:**\n```css\n.container {\n padding: calc(var(--spacing) * 4); /* 1rem */\n gap: calc(var(--spacing) * 2); /* 0.5rem */\n}\n```\n\n**Shadows:**\n```css\n.card {\n box-shadow: var(--shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1));\n}\n\n.elevated {\n box-shadow: var(--shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));\n}\n```\n\n**Charts:**\n```css\n.chart-bar:nth-child(1) { background: var(--chart1, #3b82f6); }\n.chart-bar:nth-child(2) { background: var(--chart2, #10b981); }\n.chart-bar:nth-child(3) { background: var(--chart3, #f59e0b); }\n```\n\n**Brand Typography:**\n```css\n.heading {\n font-family: var(--brand-heading-font-family, var(--font-sans, system-ui));\n font-size: var(--brand-heading-font-size, 2rem);\n font-weight: var(--brand-heading-font-weight, 700);\n line-height: var(--brand-heading-line-height, 1.2);\n}\n\n.body-text {\n font-family: var(--brand-body-font-family, var(--font-sans, system-ui));\n font-size: var(--brand-body-font-size, 1rem);\n font-weight: var(--brand-body-font-weight, 400);\n line-height: var(--brand-body-line-height, 1.5);\n}\n```\n\n## Complete Example\n\n```gts\nimport { FieldDef, Component } from 'https://cardstack.com/base/card-api';\nimport { tracked } from '@glimmer/tracking';\nimport { action } from '@ember/object';\n\nexport class ThemedField extends FieldDef {\n static edit = class Edit extends Component<typeof this> {\n @tracked isOpen = false;\n \n <template>\n <div class=\"field-wrapper\">\n <label>Select Option</label>\n <button class=\"trigger\" {{on \"click\" (fn (mut this.isOpen) (not this.isOpen))}}>\n {{@model.value ?? \"Choose...\"}}\n </button>\n \n {{#if this.isOpen}}\n <div class=\"dropdown\">\n {{#each @model.options as |option|}}\n <button class=\"option\">{{option}}</button>\n {{/each}}\n </div>\n {{/if}}\n </div>\n \n <style scoped>\n .field-wrapper {\n display: flex;\n flex-direction: column;\n gap: calc(var(--spacing) * 2);\n }\n \n label {\n font-family: var(--font-sans, system-ui);\n font-weight: 600;\n font-size: 0.875rem;\n color: var(--foreground, #1a1a1a);\n }\n \n .trigger {\n background: var(--input, #f5f5f5);\n color: var(--foreground, #1a1a1a);\n border: 1px solid var(--border, #e0e0e0);\n border-radius: var(--radius, 0.375rem);\n padding: calc(var(--spacing) * 2);\n cursor: pointer;\n }\n \n .trigger:hover {\n background: var(--accent, #f0f9ff);\n }\n \n .trigger:focus {\n outline: 2px solid var(--ring, #3b82f6);\n outline-offset: 2px;\n }\n \n .dropdown {\n background: var(--popover, #ffffff);\n border: 1px solid var(--border, #e0e0e0);\n border-radius: var(--radius, 0.375rem);\n box-shadow: var(--shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));\n margin-top: calc(var(--spacing) * 2);\n }\n \n .option {\n width: 100%;\n padding: calc(var(--spacing) * 2);\n background: transparent;\n border: none;\n color: var(--popover-foreground, #1a1a1a);\n text-align: left;\n cursor: pointer;\n }\n \n .option:hover {\n background: var(--accent, #f0f9ff);\n }\n </style>\n </template>\n };\n}\n```\n\n## Key Principles\n\n1. **Always use `var(--variable, fallback)` syntax** - Never use variables without fallbacks\n2. **Choose fallbacks that match your field's design** - Don't copy example values blindly\n3. **Use semantic variable names** - `--primary`, not hard-coded colors\n4. **Respect spacing system** - Use `calc(var(--spacing) * n)` for consistency\n5. **Apply focus states** - Use `--ring` for accessibility\n6. **Test without theme** - Ensure fallbacks create a cohesive design\n7. **Leverage brand variables** - Use brand variables for consistent theming across your application",
"content": "# Theming System and CSS Variables\n\nBoxel uses CSS custom properties (variables) for theming. When creating fields, use these variables. \n\nFallback values break with dark mode and custom themes. If fallbacks are needed, define them once on the parent container class rather than repeating them throughout child selectors.\n\n- You must link to a `Theme` card (instances of `https://cardstack.com/base/structured-theme` or its subclasses) to see the theming. Default theme to link to:\n\n```json\n\"relationships\": {\n \"cardInfo.theme\": {\n \"links\": {\n \"self\": \"https://cardstack.com/base/Theme/cardstack-brand-guide\"\n }\n }\n}\n```\n\n- Never hardcode colors. Always use CSS custom properties.\n\n**Wrong:**\n```css\nlinear-gradient(180deg, #fef7ed 0%, #fed7aa 100%)\n```\n\n**Correct:**\n```css\nlinear-gradient(180deg, var(--muted) 0%, var(--accent) 100%)\n```\n\n- Do not use rgba() values. Use color-mix() to derive semi-transparent variants from semantic tokens:\n\n- `rgba(255,255,255,0.25)` on primary background → `color-mix(in oklch, var(--primary-foreground) 25%, transparent)`\n\n- Icons and SVGs must not use hardcoded hex fills — use theme color tokens via CSS\n\n## Available Theme Variables\n\n### Shadcn Design System Variables\n\n**Colors:**\n- `--foreground`, `--background`\n- `--primary`, `--primary-foreground`\n- `--secondary`, `--secondary-foreground`\n- `--muted`, `--muted-foreground`\n- `--accent`, `--accent-foreground`\n- `--card`, `--card-foreground`\n- `--popover`, `--popover-foreground`\n- `--destructive`, `--destructive-foreground`\n- `--input`, `--ring`, `--border`\n\n**Charts:** `--chart1`, `--chart2`, `--chart3`, `--chart4`, `--chart5`\n\n**Sidebar:**\n- `--sidebar`, `--sidebar-foreground`\n- `--sidebar-primary`, `--sidebar-primary-foreground`\n- `--sidebar-accent`, `--sidebar-accent-foreground`\n- `--sidebar-border`, `--sidebar-ring`\n\n**Typography:** `--font-sans`, `--font-serif`, `--font-mono`, `--tracking-normal`\n\n#### Note: \n\nFor all cards with Themes linked in their `cardInfo.theme`:\n\n- Font-family defaults to `var(--font-sans, 'IBM Plex, sans-serif)'`\n- Font-size defaults to `var(--boxel-font-size-sm)` which is `0.875rem`\n- Letter-spacing is set to `var(--tracking-normal)`\n- Line-height defaults to `var(--boxel-line-height-sm)` which is `~1.385`\n\n**Layout:** `--radius`, `--spacing`\n\nNote: Radius and spacing are mapped to boxel variables:\n```css\n--boxel-sp: var(calc(--spacing * 4), 1rem);\n/* --boxel-sp-*[6xs to 6xl] recalculated based on Perfect Fourth scale */\n\n--boxel-border-radius: var(--radius, 0.625rem);\n/* --boxel-border-radius-*[xxs to xxl] recalculated accordingly */\n```\n\n**Shadows:** `--shadow2xs`, `--shadow-xs`, `--shadow-sm`, `--shadow`, `--shadow-md`, `--shadow-lg`, `--shadow-xl`, `--shadow2xl`\n\n### Brand Variables\n\n#### Brand Logos & Icons\n\n- Primary Logo (On light background):\n```css\n--brand-primary-mark-1\n--brand-primary-mark-greyscale-1\n```\n- Primary Logo (On dark background):\n```css\n--brand-primary-mark-2\n--brand-primary-mark-greyscale-2\n```\n- Primary logo padding ratio and min-height requirements:\n```css\n--brand-primary-mark-clearance-ratio\n--brand-primary-mark-min-height\n```\n\n- Secondary Logo (On light background):\n```css\n--brand-secondary-mark-1\n--brand-secondary-mark-greyscale-1\n```\n- Secondary Logo (On dark background):\n```css\n--brand-secondary-mark-2\n--brand-secondary-mark-greyscale-2\n```\n- Secondary logo padding ratio and min-height requirements:\n```css\n--brand-secondary-mark-clearance-ratio\n--brand-secondary-mark-min-height\n```\n\n- Social media icon: `--brand-social-media-profile-icon`\n\n#### Brand colors and Brand to Boxel/Shadcn Mapping\n\nAll css variables above are valid and recalculated based on brand values. In addition, brands can define their own custom css variables in the Brand Guide, linked via `cardInfo.theme`.\n\nThe system automatically maps brand variables to shadcn and Boxel variables:\n\n```css\n--primary: var(--brand-primary);\n--secondary: var(--brand-secondary);\n--muted: var(--brand-neutral);\n--accent: var(--brand-accent);\n--background: var(--brand-light);\n--foreground: var(--brand-dark);\n--border: var(--brand-border);\n\n--boxel-border-radius: var(--radius, 0.625rem);\n/* --boxel-border-radius-*[xxs to xxl] recalculated accordingly */\n\n--boxel-sp: var(calc(--spacing * 4), 1rem);\n/* --boxel-sp-*[6xs to 6xl] recalculated based on Perfect Fourth scale */\n\n--boxel-font-size: var(--brand-body-font-size, 0.875rem);\n/* --boxel-font-size-*[2xl to 2xs] recalculated */\n\n/* Heading (h1) */\n--boxel-heading-font-family: var(--brand-heading-font-family, var(--boxel-font-family));\n--boxel-heading-font-size: var(--brand-heading-font-size, var(--boxel-font-size-lg));\n--boxel-heading-font-weight: var(--brand-heading-font-weight, 700);\n--boxel-heading-line-height: var(--brand-heading-line-height, var(--boxel-line-height-lg));\n\n/* Section heading (h2) */\n--boxel-section-heading-font-family: var(--brand-section-heading-font-family, var(--boxel-font-family));\n--boxel-section-heading-font-size: var(--brand-section-heading-font-size, var(--boxel-font-size-md));\n--boxel-section-heading-font-weight: var(--brand-section-heading-font-weight, 500);\n--boxel-section-heading-line-height: var(--brand-section-heading-line-height, var(--boxel-line-height-md));\n\n/* Subheading (h3) */\n--boxel-subheading-font-family: var(--brand-subheading-font-family, var(--boxel-font-family);\n--boxel-subheading-font-size: var(--brand-subheading-font-size, var(--boxel-font-size));\n--boxel-subheading-font-weight: var(--brand-subheading-font-weight, 500);\n--boxel-subheading-line-height: var(--brand-subheading-line-height, var(--boxel-line-height));\n\n/* Body (p) */\n--boxel-body-font-family: var(--brand-body-font-family, var(--boxel-font-family));\n--boxel-body-font-size: var(--brand-body-font-size, var(--boxel-font-size-sm));\n--boxel-body-font-weight: var(--brand-body-font-weight, 400);\n--boxel-body-line-height: var(--brand-body-line-height, var(--boxel-line-height-sm));\n\n/* Caption (small) */\n--boxel-caption-font-family: var(--brand-caption-font-family, var(--boxel-font-family));\n--boxel-caption-font-size: var(--brand-caption-font-size, var(--boxel-font-size-xs));\n--boxel-caption-font-weight: var(--brand-caption-font-weight, 500);\n--boxel-caption-line-height: var(--brand-caption-line-height, var(--boxel-line-height-xs));\n```\n\nIf foreground colors were not manually set, they (`--primary-foreground`, `--secondary-foreground`, `--muted-foreground`, `--accent-foreground`) are automatically determined based on contrast using `--brand-light` and `--brand-dark`.\n\n## Complete Example\n\n```gts\n <template>\n <article class='my-card' aria-labelledby='mc-title'>\n <header class='mc-header'>\n <h1 class='mc-title' id='mc-title'><@fields.cardTitle /></h1>\n <p class='mc-summary'><@fields.cardDescription /></p>\n </header>\n\n <div class='mc-body'>\n <div class='mc-main'>\n <section aria-labelledby='mc-section-1'>\n <h2 class='mc-section-heading' id='mc-section-1'>Section 1 Title</h2>\n <p class='mc-prose'>Paragraph</p>\n <ul class='items-grid'>\n <li class='section-item'>\n <h3 class='item-title'>Item 1</h3>\n <p class='item-content'>Item 1 content</p>\n </li>\n <li class='section-item'>\n <h3 class='item-title'>Item 2</h3>\n <p class='item-content'>Item 2 content</p>\n </li>\n <li class='section-item'>\n <h3 class='item-title'>Item 3</h3>\n <p class='item-content'>Item 3 content</p>\n </li>\n </ul>\n </section>\n <section aria-labelledby='mc-section-2'>\n <h2 class='mc-section-heading' id='mc-section-2'>Section 2 Title</h2>\n <p class='mc-prose'>Paragraph</p>\n </section>\n </div>\n\n <aside class='mc-sidebar'>\n <section\n class='sidebar-section'\n aria-labelledby='sidebar-heading-1'\n >\n <h2 class='sidebar-heading' id='sidebar-heading-1'>Sidebar Title 1</h2>\n <ul class='sidebar-list'>\n <li class='sidebar-item'>\n <span>Sidebar item 1</span>\n </li>\n <li class='sidebar-item'>\n <span>Sidebar item 2</span>\n </li>\n <li class='sidebar-item'>\n <span>Sidebar item 3</span>\n </li>\n </ul>\n </section>\n\n <section\n class='sidebar-section'\n aria-labelledby='sidebar-heading-2'\n >\n <h2 class='sidebar-heading' id='sidebar-heading-2'>Sidebar Title 2</h2>\n <dl class='sidebar-dl'>\n <div class='sidebar-dl-row'>\n <dt>Sidebar item 1</dt>\n <dd>Content</dd>\n </div>\n <div class='sidebar-dl-row'>\n <dt>Sidebar item 2</dt>\n <dd>Content</dd>\n </div>\n </dl>\n </section>\n </aside>\n </div>\n\n <footer class='mc-footer'>\n <p>Footer text</p>\n <nav aria-label='Footer links'>\n <ul class='footer-links'>\n <li><a href='#'>Link 1</a></li>\n <li><a href='#'>Link 2</a></li>\n <li><a href='#'>Link 3</a></li>\n </ul>\n </nav>\n </footer>\n </article>\n <style scoped>\n .my-card {\n container-type: inline-size;\n container-name: mc-container;\n height: 100%;\n overflow-y: auto;\n padding: var(--boxel-sp-xl);\n background-color: var(--background);\n color: var(--foreground);\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-lg);\n box-sizing: border-box;\n }\n\n /* Header */\n .mc-header {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xs);\n border-bottom: 1px solid var(--border);\n padding-bottom: var(--boxel-sp-lg);\n }\n .mc-title {\n font-size: var(--boxel-font-size-xl);\n font-weight: 700;\n letter-spacing: var(--boxel-lsp-xs);\n margin: 0;\n }\n .mc-summary {\n font-size: var(--boxel-font-size-sm);\n line-height: var(--boxel-line-height-sm);\n color: var(--muted-foreground);\n margin: 0;\n }\n\n /* Body: main + sidebar */\n .mc-body {\n display: grid;\n grid-template-columns: 1fr 16rem;\n gap: var(--boxel-sp-lg);\n align-items: start;\n }\n\n /* Main column */\n .mc-main {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xl);\n }\n .mc-main section {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-sm);\n }\n .mc-prose {\n font-size: var(--boxel-font-size-sm);\n line-height: var(--boxel-line-height);\n color: var(--foreground);\n margin: 0;\n }\n .mc-section-heading {\n font-size: var(--boxel-font-size-lg);\n font-weight: 600;\n margin: 0;\n }\n\n /* Items grid */\n .items-grid {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));\n gap: var(--boxel-sp);\n }\n .section-item {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xs);\n background-color: var(--card);\n color: var(--card-foreground);\n padding: var(--boxel-sp);\n border: 1px solid var(--border);\n border-radius: var(--boxel-border-radius);\n box-shadow: var(--shadow);\n }\n .item-title {\n font-size: var(--boxel-font-size-sm);\n font-weight: 600;\n margin: 0;\n }\n .item-content {\n font-size: var(--boxel-font-size-xs);\n color: var(--muted-foreground);\n margin: 0;\n line-height: var(--boxel-line-height-sm);\n }\n\n /* Sidebar */\n .mc-sidebar {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp);\n background-color: var(--sidebar);\n color: var(--sidebar-foreground);\n border: 1px solid var(--sidebar-border);\n border-radius: var(--boxel-border-radius);\n padding: var(--boxel-sp);\n }\n .sidebar-section {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xs);\n }\n .sidebar-section + .sidebar-section {\n border-top: 1px solid var(--sidebar-border);\n padding-top: var(--boxel-sp);\n }\n .sidebar-heading {\n font-size: var(--boxel-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: var(--boxel-lsp-lg);\n margin: 0;\n }\n .sidebar-list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-5xs);\n }\n .sidebar-item {\n display: flex;\n align-items: center;\n gap: var(--boxel-sp-5xs);\n font-size: var(--boxel-font-size-sm);\n }\n\n /* Definition list */\n .sidebar-dl {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-5xs);\n margin: 0;\n }\n .sidebar-dl-row {\n display: flex;\n justify-content: space-between;\n font-size: var(--boxel-font-size-xs);\n }\n .sidebar-dl-row dt {\n color: var(--muted-foreground);\n }\n .sidebar-dl-row dd {\n margin: 0;\n font-weight: 500;\n }\n\n /* Footer */\n .mc-footer {\n border-top: 1px solid var(--border);\n padding-top: var(--boxel-sp-sm);\n font-size: var(--boxel-font-size-xs);\n color: var(--muted-foreground);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: var(--boxel-sp-xs);\n }\n .mc-footer p {\n font-size: inherit;\n margin: 0;\n }\n .footer-links {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n align-items: center;\n gap: 0;\n }\n .footer-links li + li::before {\n content: '·';\n margin-inline: var(--boxel-sp-xs);\n }\n .mc-footer a {\n color: var(--muted-foreground);\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n .mc-footer a:hover {\n color: var(--foreground);\n }\n\n /* Responsive: stack on narrow containers */\n @container mc-container (max-width: 600px) {\n .mc-body {\n grid-template-columns: 1fr;\n }\n }\n </style>\n </template>\n```\n\n## Key Principles\n\n1. No hard-coded colors — use CSS custom properties\n2. Respect spacing system — Use `calc(var(--spacing) * n)` or `boxel-sp-* [6xs to 6xl]` for consistency\n3. Always prefer boxel-ui components over raw HTML elements. Read the component API in the monorepo.\n4. No `@import url(...)` inside style tag. Font-families are imported automatically by the linked theme.",
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The content text includes several CSS snippets that are syntactically invalid and/or don’t match how Boxel derives theme variables. For example, --boxel-sp: var(calc(--spacing * 4), 1rem); is not valid CSS (var() can’t wrap calc() like that, and --spacing needs var(--spacing)), and the --boxel-subheading-font-family example is missing a closing parenthesis. Please update these snippets to reflect the actual mappings used by boxel-ui (e.g., --_theme-spacing: calc(var(--spacing) * 4);, --boxel-spacing: var(--_theme-spacing, ...), --boxel-sp: var(--boxel-spacing)).

Suggested change
"content": "# Theming System and CSS Variables\n\nBoxel uses CSS custom properties (variables) for theming. When creating fields, use these variables. \n\nFallback values break with dark mode and custom themes. If fallbacks are needed, define them once on the parent container class rather than repeating them throughout child selectors.\n\n- You must link to a `Theme` card (instances of `https://cardstack.com/base/structured-theme` or its subclasses) to see the theming. Default theme to link to:\n\n```json\n\"relationships\": {\n \"cardInfo.theme\": {\n \"links\": {\n \"self\": \"https://cardstack.com/base/Theme/cardstack-brand-guide\"\n }\n }\n}\n```\n\n- Never hardcode colors. Always use CSS custom properties.\n\n**Wrong:**\n```css\nlinear-gradient(180deg, #fef7ed 0%, #fed7aa 100%)\n```\n\n**Correct:**\n```css\nlinear-gradient(180deg, var(--muted) 0%, var(--accent) 100%)\n```\n\n- Do not use rgba() values. Use color-mix() to derive semi-transparent variants from semantic tokens:\n\n- `rgba(255,255,255,0.25)` on primary background → `color-mix(in oklch, var(--primary-foreground) 25%, transparent)`\n\n- Icons and SVGs must not use hardcoded hex fills — use theme color tokens via CSS\n\n## Available Theme Variables\n\n### Shadcn Design System Variables\n\n**Colors:**\n- `--foreground`, `--background`\n- `--primary`, `--primary-foreground`\n- `--secondary`, `--secondary-foreground`\n- `--muted`, `--muted-foreground`\n- `--accent`, `--accent-foreground`\n- `--card`, `--card-foreground`\n- `--popover`, `--popover-foreground`\n- `--destructive`, `--destructive-foreground`\n- `--input`, `--ring`, `--border`\n\n**Charts:** `--chart1`, `--chart2`, `--chart3`, `--chart4`, `--chart5`\n\n**Sidebar:**\n- `--sidebar`, `--sidebar-foreground`\n- `--sidebar-primary`, `--sidebar-primary-foreground`\n- `--sidebar-accent`, `--sidebar-accent-foreground`\n- `--sidebar-border`, `--sidebar-ring`\n\n**Typography:** `--font-sans`, `--font-serif`, `--font-mono`, `--tracking-normal`\n\n#### Note: \n\nFor all cards with Themes linked in their `cardInfo.theme`:\n\n- Font-family defaults to `var(--font-sans, 'IBM Plex, sans-serif)'`\n- Font-size defaults to `var(--boxel-font-size-sm)` which is `0.875rem`\n- Letter-spacing is set to `var(--tracking-normal)`\n- Line-height defaults to `var(--boxel-line-height-sm)` which is `~1.385`\n\n**Layout:** `--radius`, `--spacing`\n\nNote: Radius and spacing are mapped to boxel variables:\n```css\n--boxel-sp: var(calc(--spacing * 4), 1rem);\n/* --boxel-sp-*[6xs to 6xl] recalculated based on Perfect Fourth scale */\n\n--boxel-border-radius: var(--radius, 0.625rem);\n/* --boxel-border-radius-*[xxs to xxl] recalculated accordingly */\n```\n\n**Shadows:** `--shadow2xs`, `--shadow-xs`, `--shadow-sm`, `--shadow`, `--shadow-md`, `--shadow-lg`, `--shadow-xl`, `--shadow2xl`\n\n### Brand Variables\n\n#### Brand Logos & Icons\n\n- Primary Logo (On light background):\n```css\n--brand-primary-mark-1\n--brand-primary-mark-greyscale-1\n```\n- Primary Logo (On dark background):\n```css\n--brand-primary-mark-2\n--brand-primary-mark-greyscale-2\n```\n- Primary logo padding ratio and min-height requirements:\n```css\n--brand-primary-mark-clearance-ratio\n--brand-primary-mark-min-height\n```\n\n- Secondary Logo (On light background):\n```css\n--brand-secondary-mark-1\n--brand-secondary-mark-greyscale-1\n```\n- Secondary Logo (On dark background):\n```css\n--brand-secondary-mark-2\n--brand-secondary-mark-greyscale-2\n```\n- Secondary logo padding ratio and min-height requirements:\n```css\n--brand-secondary-mark-clearance-ratio\n--brand-secondary-mark-min-height\n```\n\n- Social media icon: `--brand-social-media-profile-icon`\n\n#### Brand colors and Brand to Boxel/Shadcn Mapping\n\nAll css variables above are valid and recalculated based on brand values. In addition, brands can define their own custom css variables in the Brand Guide, linked via `cardInfo.theme`.\n\nThe system automatically maps brand variables to shadcn and Boxel variables:\n\n```css\n--primary: var(--brand-primary);\n--secondary: var(--brand-secondary);\n--muted: var(--brand-neutral);\n--accent: var(--brand-accent);\n--background: var(--brand-light);\n--foreground: var(--brand-dark);\n--border: var(--brand-border);\n\n--boxel-border-radius: var(--radius, 0.625rem);\n/* --boxel-border-radius-*[xxs to xxl] recalculated accordingly */\n\n--boxel-sp: var(calc(--spacing * 4), 1rem);\n/* --boxel-sp-*[6xs to 6xl] recalculated based on Perfect Fourth scale */\n\n--boxel-font-size: var(--brand-body-font-size, 0.875rem);\n/* --boxel-font-size-*[2xl to 2xs] recalculated */\n\n/* Heading (h1) */\n--boxel-heading-font-family: var(--brand-heading-font-family, var(--boxel-font-family));\n--boxel-heading-font-size: var(--brand-heading-font-size, var(--boxel-font-size-lg));\n--boxel-heading-font-weight: var(--brand-heading-font-weight, 700);\n--boxel-heading-line-height: var(--brand-heading-line-height, var(--boxel-line-height-lg));\n\n/* Section heading (h2) */\n--boxel-section-heading-font-family: var(--brand-section-heading-font-family, var(--boxel-font-family));\n--boxel-section-heading-font-size: var(--brand-section-heading-font-size, var(--boxel-font-size-md));\n--boxel-section-heading-font-weight: var(--brand-section-heading-font-weight, 500);\n--boxel-section-heading-line-height: var(--brand-section-heading-line-height, var(--boxel-line-height-md));\n\n/* Subheading (h3) */\n--boxel-subheading-font-family: var(--brand-subheading-font-family, var(--boxel-font-family);\n--boxel-subheading-font-size: var(--brand-subheading-font-size, var(--boxel-font-size));\n--boxel-subheading-font-weight: var(--brand-subheading-font-weight, 500);\n--boxel-subheading-line-height: var(--brand-subheading-line-height, var(--boxel-line-height));\n\n/* Body (p) */\n--boxel-body-font-family: var(--brand-body-font-family, var(--boxel-font-family));\n--boxel-body-font-size: var(--brand-body-font-size, var(--boxel-font-size-sm));\n--boxel-body-font-weight: var(--brand-body-font-weight, 400);\n--boxel-body-line-height: var(--brand-body-line-height, var(--boxel-line-height-sm));\n\n/* Caption (small) */\n--boxel-caption-font-family: var(--brand-caption-font-family, var(--boxel-font-family));\n--boxel-caption-font-size: var(--brand-caption-font-size, var(--boxel-font-size-xs));\n--boxel-caption-font-weight: var(--brand-caption-font-weight, 500);\n--boxel-caption-line-height: var(--brand-caption-line-height, var(--boxel-line-height-xs));\n```\n\nIf foreground colors were not manually set, they (`--primary-foreground`, `--secondary-foreground`, `--muted-foreground`, `--accent-foreground`) are automatically determined based on contrast using `--brand-light` and `--brand-dark`.\n\n## Complete Example\n\n```gts\n <template>\n <article class='my-card' aria-labelledby='mc-title'>\n <header class='mc-header'>\n <h1 class='mc-title' id='mc-title'><@fields.cardTitle /></h1>\n <p class='mc-summary'><@fields.cardDescription /></p>\n </header>\n\n <div class='mc-body'>\n <div class='mc-main'>\n <section aria-labelledby='mc-section-1'>\n <h2 class='mc-section-heading' id='mc-section-1'>Section 1 Title</h2>\n <p class='mc-prose'>Paragraph</p>\n <ul class='items-grid'>\n <li class='section-item'>\n <h3 class='item-title'>Item 1</h3>\n <p class='item-content'>Item 1 content</p>\n </li>\n <li class='section-item'>\n <h3 class='item-title'>Item 2</h3>\n <p class='item-content'>Item 2 content</p>\n </li>\n <li class='section-item'>\n <h3 class='item-title'>Item 3</h3>\n <p class='item-content'>Item 3 content</p>\n </li>\n </ul>\n </section>\n <section aria-labelledby='mc-section-2'>\n <h2 class='mc-section-heading' id='mc-section-2'>Section 2 Title</h2>\n <p class='mc-prose'>Paragraph</p>\n </section>\n </div>\n\n <aside class='mc-sidebar'>\n <section\n class='sidebar-section'\n aria-labelledby='sidebar-heading-1'\n >\n <h2 class='sidebar-heading' id='sidebar-heading-1'>Sidebar Title 1</h2>\n <ul class='sidebar-list'>\n <li class='sidebar-item'>\n <span>Sidebar item 1</span>\n </li>\n <li class='sidebar-item'>\n <span>Sidebar item 2</span>\n </li>\n <li class='sidebar-item'>\n <span>Sidebar item 3</span>\n </li>\n </ul>\n </section>\n\n <section\n class='sidebar-section'\n aria-labelledby='sidebar-heading-2'\n >\n <h2 class='sidebar-heading' id='sidebar-heading-2'>Sidebar Title 2</h2>\n <dl class='sidebar-dl'>\n <div class='sidebar-dl-row'>\n <dt>Sidebar item 1</dt>\n <dd>Content</dd>\n </div>\n <div class='sidebar-dl-row'>\n <dt>Sidebar item 2</dt>\n <dd>Content</dd>\n </div>\n </dl>\n </section>\n </aside>\n </div>\n\n <footer class='mc-footer'>\n <p>Footer text</p>\n <nav aria-label='Footer links'>\n <ul class='footer-links'>\n <li><a href='#'>Link 1</a></li>\n <li><a href='#'>Link 2</a></li>\n <li><a href='#'>Link 3</a></li>\n </ul>\n </nav>\n </footer>\n </article>\n <style scoped>\n .my-card {\n container-type: inline-size;\n container-name: mc-container;\n height: 100%;\n overflow-y: auto;\n padding: var(--boxel-sp-xl);\n background-color: var(--background);\n color: var(--foreground);\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-lg);\n box-sizing: border-box;\n }\n\n /* Header */\n .mc-header {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xs);\n border-bottom: 1px solid var(--border);\n padding-bottom: var(--boxel-sp-lg);\n }\n .mc-title {\n font-size: var(--boxel-font-size-xl);\n font-weight: 700;\n letter-spacing: var(--boxel-lsp-xs);\n margin: 0;\n }\n .mc-summary {\n font-size: var(--boxel-font-size-sm);\n line-height: var(--boxel-line-height-sm);\n color: var(--muted-foreground);\n margin: 0;\n }\n\n /* Body: main + sidebar */\n .mc-body {\n display: grid;\n grid-template-columns: 1fr 16rem;\n gap: var(--boxel-sp-lg);\n align-items: start;\n }\n\n /* Main column */\n .mc-main {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xl);\n }\n .mc-main section {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-sm);\n }\n .mc-prose {\n font-size: var(--boxel-font-size-sm);\n line-height: var(--boxel-line-height);\n color: var(--foreground);\n margin: 0;\n }\n .mc-section-heading {\n font-size: var(--boxel-font-size-lg);\n font-weight: 600;\n margin: 0;\n }\n\n /* Items grid */\n .items-grid {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));\n gap: var(--boxel-sp);\n }\n .section-item {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xs);\n background-color: var(--card);\n color: var(--card-foreground);\n padding: var(--boxel-sp);\n border: 1px solid var(--border);\n border-radius: var(--boxel-border-radius);\n box-shadow: var(--shadow);\n }\n .item-title {\n font-size: var(--boxel-font-size-sm);\n font-weight: 600;\n margin: 0;\n }\n .item-content {\n font-size: var(--boxel-font-size-xs);\n color: var(--muted-foreground);\n margin: 0;\n line-height: var(--boxel-line-height-sm);\n }\n\n /* Sidebar */\n .mc-sidebar {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp);\n background-color: var(--sidebar);\n color: var(--sidebar-foreground);\n border: 1px solid var(--sidebar-border);\n border-radius: var(--boxel-border-radius);\n padding: var(--boxel-sp);\n }\n .sidebar-section {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xs);\n }\n .sidebar-section + .sidebar-section {\n border-top: 1px solid var(--sidebar-border);\n padding-top: var(--boxel-sp);\n }\n .sidebar-heading {\n font-size: var(--boxel-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: var(--boxel-lsp-lg);\n margin: 0;\n }\n .sidebar-list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-5xs);\n }\n .sidebar-item {\n display: flex;\n align-items: center;\n gap: var(--boxel-sp-5xs);\n font-size: var(--boxel-font-size-sm);\n }\n\n /* Definition list */\n .sidebar-dl {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-5xs);\n margin: 0;\n }\n .sidebar-dl-row {\n display: flex;\n justify-content: space-between;\n font-size: var(--boxel-font-size-xs);\n }\n .sidebar-dl-row dt {\n color: var(--muted-foreground);\n }\n .sidebar-dl-row dd {\n margin: 0;\n font-weight: 500;\n }\n\n /* Footer */\n .mc-footer {\n border-top: 1px solid var(--border);\n padding-top: var(--boxel-sp-sm);\n font-size: var(--boxel-font-size-xs);\n color: var(--muted-foreground);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: var(--boxel-sp-xs);\n }\n .mc-footer p {\n font-size: inherit;\n margin: 0;\n }\n .footer-links {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n align-items: center;\n gap: 0;\n }\n .footer-links li + li::before {\n content: '·';\n margin-inline: var(--boxel-sp-xs);\n }\n .mc-footer a {\n color: var(--muted-foreground);\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n .mc-footer a:hover {\n color: var(--foreground);\n }\n\n /* Responsive: stack on narrow containers */\n @container mc-container (max-width: 600px) {\n .mc-body {\n grid-template-columns: 1fr;\n }\n }\n </style>\n </template>\n```\n\n## Key Principles\n\n1. No hard-coded colors — use CSS custom properties\n2. Respect spacing system — Use `calc(var(--spacing) * n)` or `boxel-sp-* [6xs to 6xl]` for consistency\n3. Always prefer boxel-ui components over raw HTML elements. Read the component API in the monorepo.\n4. No `@import url(...)` inside style tag. Font-families are imported automatically by the linked theme.",
"content": "# Theming System and CSS Variables\n\nBoxel uses CSS custom properties (variables) for theming. When creating fields, use these variables. \n\nFallback values break with dark mode and custom themes. If fallbacks are needed, define them once on the parent container class rather than repeating them throughout child selectors.\n\n- You must link to a `Theme` card (instances of `https://cardstack.com/base/structured-theme` or its subclasses) to see the theming. Default theme to link to:\n\n```json\n\"relationships\": {\n \"cardInfo.theme\": {\n \"links\": {\n \"self\": \"https://cardstack.com/base/Theme/cardstack-brand-guide\"\n }\n }\n}\n```\n\n- Never hardcode colors. Always use CSS custom properties.\n\n**Wrong:**\n```css\nlinear-gradient(180deg, #fef7ed 0%, #fed7aa 100%)\n```\n\n**Correct:**\n```css\nlinear-gradient(180deg, var(--muted) 0%, var(--accent) 100%)\n```\n\n- Do not use rgba() values. Use color-mix() to derive semi-transparent variants from semantic tokens:\n\n- `rgba(255,255,255,0.25)` on primary background → `color-mix(in oklch, var(--primary-foreground) 25%, transparent)`\n\n- Icons and SVGs must not use hardcoded hex fills — use theme color tokens via CSS\n\n## Available Theme Variables\n\n### Shadcn Design System Variables\n\n**Colors:**\n- `--foreground`, `--background`\n- `--primary`, `--primary-foreground`\n- `--secondary`, `--secondary-foreground`\n- `--muted`, `--muted-foreground`\n- `--accent`, `--accent-foreground`\n- `--card`, `--card-foreground`\n- `--popover`, `--popover-foreground`\n- `--destructive`, `--destructive-foreground`\n- `--input`, `--ring`, `--border`\n\n**Charts:** `--chart1`, `--chart2`, `--chart3`, `--chart4`, `--chart5`\n\n**Sidebar:**\n- `--sidebar`, `--sidebar-foreground`\n- `--sidebar-primary`, `--sidebar-primary-foreground`\n- `--sidebar-accent`, `--sidebar-accent-foreground`\n- `--sidebar-border`, `--sidebar-ring`\n\n**Typography:** `--font-sans`, `--font-serif`, `--font-mono`, `--tracking-normal`\n\n#### Note: \n\nFor all cards with Themes linked in their `cardInfo.theme`:\n\n- Font-family defaults to `var(--font-sans, 'IBM Plex, sans-serif')`\n- Font-size defaults to `var(--boxel-font-size-sm)` which is `0.875rem`\n- Letter-spacing is set to `var(--tracking-normal)`\n- Line-height defaults to `var(--boxel-line-height-sm)` which is `~1.385`\n\n**Layout:** `--radius`, `--spacing`\n\nNote: Radius and spacing are mapped to boxel variables:\n```css\n--_theme-spacing: calc(var(--spacing) * 4);\n--boxel-spacing: var(--_theme-spacing, 1rem);\n--boxel-sp: var(--boxel-spacing);\n/* --boxel-sp-*[6xs to 6xl] recalculated based on Perfect Fourth scale */\n\n--boxel-border-radius: var(--radius, 0.625rem);\n/* --boxel-border-radius-*[xxs to xxl] recalculated accordingly */\n```\n\n**Shadows:** `--shadow2xs`, `--shadow-xs`, `--shadow-sm`, `--shadow`, `--shadow-md`, `--shadow-lg`, `--shadow-xl`, `--shadow2xl`\n\n### Brand Variables\n\n#### Brand Logos & Icons\n\n- Primary Logo (On light background):\n```css\n--brand-primary-mark-1\n--brand-primary-mark-greyscale-1\n```\n- Primary Logo (On dark background):\n```css\n--brand-primary-mark-2\n--brand-primary-mark-greyscale-2\n```\n- Primary logo padding ratio and min-height requirements:\n```css\n--brand-primary-mark-clearance-ratio\n--brand-primary-mark-min-height\n```\n\n- Secondary Logo (On light background):\n```css\n--brand-secondary-mark-1\n--brand-secondary-mark-greyscale-1\n```\n- Secondary Logo (On dark background):\n```css\n--brand-secondary-mark-2\n--brand-secondary-mark-greyscale-2\n```\n- Secondary logo padding ratio and min-height requirements:\n```css\n--brand-secondary-mark-clearance-ratio\n--brand-secondary-mark-min-height\n```\n\n- Social media icon: `--brand-social-media-profile-icon`\n\n#### Brand colors and Brand to Boxel/Shadcn Mapping\n\nAll css variables above are valid and recalculated based on brand values. In addition, brands can define their own custom css variables in the Brand Guide, linked via `cardInfo.theme`.\n\nThe system automatically maps brand variables to shadcn and Boxel variables:\n\n```css\n--primary: var(--brand-primary);\n--secondary: var(--brand-secondary);\n--muted: var(--brand-neutral);\n--accent: var(--brand-accent);\n--background: var(--brand-light);\n--foreground: var(--brand-dark);\n--border: var(--brand-border);\n\n--boxel-border-radius: var(--radius, 0.625rem);\n/* --boxel-border-radius-*[xxs to xxl] recalculated accordingly */\n\n--_theme-spacing: calc(var(--spacing) * 4);\n--boxel-spacing: var(--_theme-spacing, 1rem);\n--boxel-sp: var(--boxel-spacing);\n/* --boxel-sp-*[6xs to 6xl] recalculated based on Perfect Fourth scale */\n\n--boxel-font-size: var(--brand-body-font-size, 0.875rem);\n/* --boxel-font-size-*[2xl to 2xs] recalculated */\n\n/* Heading (h1) */\n--boxel-heading-font-family: var(--brand-heading-font-family, var(--boxel-font-family));\n--boxel-heading-font-size: var(--brand-heading-font-size, var(--boxel-font-size-lg));\n--boxel-heading-font-weight: var(--brand-heading-font-weight, 700);\n--boxel-heading-line-height: var(--brand-heading-line-height, var(--boxel-line-height-lg));\n\n/* Section heading (h2) */\n--boxel-section-heading-font-family: var(--brand-section-heading-font-family, var(--boxel-font-family));\n--boxel-section-heading-font-size: var(--brand-section-heading-font-size, var(--boxel-font-size-md));\n--boxel-section-heading-font-weight: var(--brand-section-heading-font-weight, 500);\n--boxel-section-heading-line-height: var(--brand-section-heading-line-height, var(--boxel-line-height-md));\n\n/* Subheading (h3) */\n--boxel-subheading-font-family: var(--brand-subheading-font-family, var(--boxel-font-family));\n--boxel-subheading-font-size: var(--brand-subheading-font-size, var(--boxel-font-size));\n--boxel-subheading-font-weight: var(--brand-subheading-font-weight, 500);\n--boxel-subheading-line-height: var(--brand-subheading-line-height, var(--boxel-line-height));\n\n/* Body (p) */\n--boxel-body-font-family: var(--brand-body-font-family, var(--boxel-font-family));\n--boxel-body-font-size: var(--brand-body-font-size, var(--boxel-font-size-sm));\n--boxel-body-font-weight: var(--brand-body-font-weight, 400);\n--boxel-body-line-height: var(--brand-body-line-height, var(--boxel-line-height-sm));\n\n/* Caption (small) */\n--boxel-caption-font-family: var(--brand-caption-font-family, var(--boxel-font-family));\n--boxel-caption-font-size: var(--brand-caption-font-size, var(--boxel-font-size-xs));\n--boxel-caption-font-weight: var(--brand-caption-font-weight, 500);\n--boxel-caption-line-height: var(--brand-caption-line-height, var(--boxel-line-height-xs));\n```\n\nIf foreground colors were not manually set, they (`--primary-foreground`, `--secondary-foreground`, `--muted-foreground`, `--accent-foreground`) are automatically determined based on contrast using `--brand-light` and `--brand-dark`.\n\n## Complete Example\n\n```gts\n <template>\n <article class='my-card' aria-labelledby='mc-title'>\n <header class='mc-header'>\n <h1 class='mc-title' id='mc-title'><@fields.cardTitle /></h1>\n <p class='mc-summary'><@fields.cardDescription /></p>\n </header>\n\n <div class='mc-body'>\n <div class='mc-main'>\n <section aria-labelledby='mc-section-1'>\n <h2 class='mc-section-heading' id='mc-section-1'>Section 1 Title</h2>\n <p class='mc-prose'>Paragraph</p>\n <ul class='items-grid'>\n <li class='section-item'>\n <h3 class='item-title'>Item 1</h3>\n <p class='item-content'>Item 1 content</p>\n </li>\n <li class='section-item'>\n <h3 class='item-title'>Item 2</h3>\n <p class='item-content'>Item 2 content</p>\n </li>\n <li class='section-item'>\n <h3 class='item-title'>Item 3</h3>\n <p class='item-content'>Item 3 content</p>\n </li>\n </ul>\n </section>\n <section aria-labelledby='mc-section-2'>\n <h2 class='mc-section-heading' id='mc-section-2'>Section 2 Title</h2>\n <p class='mc-prose'>Paragraph</p>\n </section>\n </div>\n\n <aside class='mc-sidebar'>\n <section\n class='sidebar-section'\n aria-labelledby='sidebar-heading-1'\n >\n <h2 class='sidebar-heading' id='sidebar-heading-1'>Sidebar Title 1</h2>\n <ul class='sidebar-list'>\n <li class='sidebar-item'>\n <span>Sidebar item 1</span>\n </li>\n <li class='sidebar-item'>\n <span>Sidebar item 2</span>\n </li>\n <li class='sidebar-item'>\n <span>Sidebar item 3</span>\n </li>\n </ul>\n </section>\n\n <section\n class='sidebar-section'\n aria-labelledby='sidebar-heading-2'\n >\n <h2 class='sidebar-heading' id='sidebar-heading-2'>Sidebar Title 2</h2>\n <dl class='sidebar-dl'>\n <div class='sidebar-dl-row'>\n <dt>Sidebar item 1</dt>\n <dd>Content</dd>\n </div>\n <div class='sidebar-dl-row'>\n <dt>Sidebar item 2</dt>\n <dd>Content</dd>\n </div>\n </dl>\n </section>\n </aside>\n </div>\n\n <footer class='mc-footer'>\n <p>Footer text</p>\n <nav aria-label='Footer links'>\n <ul class='footer-links'>\n <li><a href='#'>Link 1</a></li>\n <li><a href='#'>Link 2</a></li>\n <li><a href='#'>Link 3</a></li>\n </ul>\n </nav>\n </footer>\n </article>\n <style scoped>\n .my-card {\n container-type: inline-size;\n container-name: mc-container;\n height: 100%;\n overflow-y: auto;\n padding: var(--boxel-sp-xl);\n background-color: var(--background);\n color: var(--foreground);\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-lg);\n box-sizing: border-box;\n }\n\n /* Header */\n .mc-header {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xs);\n border-bottom: 1px solid var(--border);\n padding-bottom: var(--boxel-sp-lg);\n }\n .mc-title {\n font-size: var(--boxel-font-size-xl);\n font-weight: 700;\n letter-spacing: var(--boxel-lsp-xs);\n margin: 0;\n }\n .mc-summary {\n font-size: var(--boxel-font-size-sm);\n line-height: var(--boxel-line-height-sm);\n color: var(--muted-foreground);\n margin: 0;\n }\n\n /* Body: main + sidebar */\n .mc-body {\n display: grid;\n grid-template-columns: 1fr 16rem;\n gap: var(--boxel-sp-lg);\n align-items: start;\n }\n\n /* Main column */\n .mc-main {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xl);\n }\n .mc-main section {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-sm);\n }\n .mc-prose {\n font-size: var(--boxel-font-size-sm);\n line-height: var(--boxel-line-height);\n color: var(--foreground);\n margin: 0;\n }\n .mc-section-heading {\n font-size: var(--boxel-font-size-lg);\n font-weight: 600;\n margin: 0;\n }\n\n /* Items grid */\n .items-grid {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));\n gap: var(--boxel-sp);\n }\n .section-item {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xs);\n background-color: var(--card);\n color: var(--card-foreground);\n padding: var(--boxel-sp);\n border: 1px solid var(--border);\n border-radius: var(--boxel-border-radius);\n box-shadow: var(--shadow);\n }\n .item-title {\n font-size: var(--boxel-font-size-sm);\n font-weight: 600;\n margin: 0;\n }\n .item-content {\n font-size: var(--boxel-font-size-xs);\n color: var(--muted-foreground);\n margin: 0;\n line-height: var(--boxel-line-height-sm);\n }\n\n /* Sidebar */\n .mc-sidebar {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp);\n background-color: var(--sidebar);\n color: var(--sidebar-foreground);\n border: 1px solid var(--sidebar-border);\n border-radius: var(--boxel-border-radius);\n padding: var(--boxel-sp);\n }\n .sidebar-section {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-xs);\n }\n .sidebar-section + .sidebar-section {\n border-top: 1px solid var(--sidebar-border);\n padding-top: var(--boxel-sp);\n }\n .sidebar-heading {\n font-size: var(--boxel-font-size-xs);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: var(--boxel-lsp-lg);\n margin: 0;\n }\n .sidebar-list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-5xs);\n }\n .sidebar-item {\n display: flex;\n align-items: center;\n gap: var(--boxel-sp-5xs);\n font-size: var(--boxel-font-size-sm);\n }\n\n /* Definition list */\n .sidebar-dl {\n display: flex;\n flex-direction: column;\n gap: var(--boxel-sp-5xs);\n margin: 0;\n }\n .sidebar-dl-row {\n display: flex;\n justify-content: space-between;\n font-size: var(--boxel-font-size-xs);\n }\n .sidebar-dl-row dt {\n color: var(--muted-foreground);\n }\n .sidebar-dl-row dd {\n margin: 0;\n font-weight: 500;\n }\n\n /* Footer */\n .mc-footer {\n border-top: 1px solid var(--border);\n padding-top: var(--boxel-sp-sm);\n font-size: var(--boxel-font-size-xs);\n color: var(--muted-foreground);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: var(--boxel-sp-xs);\n }\n .mc-footer p {\n font-size: inherit;\n margin: 0;\n }\n .footer-links {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n align-items: center;\n gap: 0;\n }\n .footer-links li + li::before {\n content: '·';\n margin-inline: var(--boxel-sp-xs);\n }\n .mc-footer a {\n color: var(--muted-foreground);\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n .mc-footer a:hover {\n color: var(--foreground);\n }\n\n /* Responsive: stack on narrow containers */\n @container mc-container (max-width: 600px) {\n .mc-body {\n grid-template-columns: 1fr;\n }\n }\n </style>\n </template>\n```\n\n## Key Principles\n\n1. No hard-coded colors — use CSS custom properties\n2. Respect spacing system — Use `calc(var(--spacing) * n)` or `boxel-sp-* [6xs to 6xl]` for consistency\n3. Always prefer boxel-ui components over raw HTML elements. Read the component API in the monorepo.\n4. No `@import url(...)` inside style tag. Font-families are imported automatically by the linked theme.",

Copilot uses AI. Check for mistakes.
"position": {
"type": null,
"referenceId": null
"referenceId": ""
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

position.referenceId is set to an empty string here, but other Statement cards in this repo consistently use null when there is no reference id. If the intent is “no reference id”, please keep this as null to avoid treating the empty string as a meaningful identifier.

Suggested change
"referenceId": ""
"referenceId": null

Copilot uses AI. Check for mistakes.
@burieberry burieberry merged commit f62c096 into main Mar 24, 2026
209 of 211 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants