@ciderpress/ui 1.0.0-rc.11 → 1.0.0-rc.14

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/dist/head/css/themes/honeycrisp.css +1 -1
  2. package/dist/node.mjs +719 -26
  3. package/dist/plugins/mermaid/MermaidRenderer.tsx +2 -2
  4. package/dist/theme/components/home/hero-banner.tsx +225 -0
  5. package/dist/theme/components/home/hero-demo.css +492 -61
  6. package/dist/theme/components/home/hero-demo.test.tsx +159 -0
  7. package/dist/theme/components/home/hero-demo.tsx +335 -32
  8. package/dist/theme/components/home/hero.css +142 -9
  9. package/dist/theme/components/home/hero.test.tsx +105 -0
  10. package/dist/theme/components/home/hero.tsx +201 -4
  11. package/dist/theme/components/home/home-visual.css +98 -0
  12. package/dist/theme/components/home/home-visual.test.tsx +27 -0
  13. package/dist/theme/components/home/home-visual.tsx +20 -13
  14. package/dist/theme/components/home/layout.tsx +125 -1
  15. package/dist/theme/components/home/split.css +2 -2
  16. package/dist/theme/components/home/tabs.css +1 -1
  17. package/dist/theme/components/home/trust-strip.css +12 -0
  18. package/dist/theme/components/home/trust-strip.test.tsx +33 -0
  19. package/dist/theme/components/home/trust-strip.tsx +76 -15
  20. package/dist/theme/components/nav/layout.tsx +10 -14
  21. package/dist/theme/components/nav/nav-logo.tsx +2 -3
  22. package/dist/theme/components/seo-head-data.test.ts +196 -0
  23. package/dist/theme/components/seo-head-data.ts +490 -0
  24. package/dist/theme/components/seo-head.tsx +102 -0
  25. package/dist/theme/components/shared/IssueLinkIcon.tsx +42 -0
  26. package/dist/theme/components/shared/issue-link.css +74 -0
  27. package/dist/theme/components/sidebar/sidebar-filter.test.ts +49 -9
  28. package/dist/theme/components/sidebar/sidebar-filter.ts +24 -4
  29. package/dist/theme/index.tsx +9 -1
  30. package/dist/theme/lib/rich-text-parse.ts +0 -2
  31. package/dist/theme/lib/seo-url.ts +28 -0
  32. package/dist/theme/lib/theme-favicon.ts +0 -3
  33. package/dist/theme/styles/themes/honeycrisp.css +20 -20
  34. package/package.json +23 -21
  35. package/src/theme/components/home/hero-banner.tsx +225 -0
  36. package/src/theme/components/home/hero-demo.css +492 -61
  37. package/src/theme/components/home/hero-demo.test.tsx +159 -0
  38. package/src/theme/components/home/hero-demo.tsx +335 -32
  39. package/src/theme/components/home/hero.css +142 -9
  40. package/src/theme/components/home/hero.test.tsx +105 -0
  41. package/src/theme/components/home/hero.tsx +201 -4
  42. package/src/theme/components/home/home-visual.css +98 -0
  43. package/src/theme/components/home/home-visual.test.tsx +27 -0
  44. package/src/theme/components/home/home-visual.tsx +20 -13
  45. package/src/theme/components/home/layout.tsx +125 -1
  46. package/src/theme/components/home/split.css +2 -2
  47. package/src/theme/components/home/tabs.css +1 -1
  48. package/src/theme/components/home/trust-strip.css +12 -0
  49. package/src/theme/components/home/trust-strip.test.tsx +33 -0
  50. package/src/theme/components/home/trust-strip.tsx +76 -15
  51. package/src/theme/components/nav/layout.tsx +10 -14
  52. package/src/theme/components/nav/nav-logo.tsx +2 -3
  53. package/src/theme/components/seo-head-data.test.ts +196 -0
  54. package/src/theme/components/seo-head-data.ts +490 -0
  55. package/src/theme/components/seo-head.tsx +102 -0
  56. package/src/theme/components/shared/IssueLinkIcon.tsx +42 -0
  57. package/src/theme/components/shared/issue-link.css +74 -0
  58. package/src/theme/components/sidebar/sidebar-filter.test.ts +49 -9
  59. package/src/theme/components/sidebar/sidebar-filter.ts +24 -4
  60. package/src/theme/index.tsx +9 -1
  61. package/src/theme/lib/rich-text-parse.ts +0 -2
  62. package/src/theme/lib/seo-url.ts +28 -0
  63. package/src/theme/lib/theme-favicon.ts +0 -3
  64. package/src/theme/styles/themes/honeycrisp.css +20 -20
@@ -0,0 +1,102 @@
1
+ import { Head, useFrontmatter, useLocation, usePageData, useSite } from '@rspress/core/runtime'
2
+ import { match } from 'massaman/match'
3
+ import { isNil, isNotNil } from 'massaman/predicate'
4
+
5
+ import type { SeoThemeConfig } from '../../seo-theme-config'
6
+ import type { ResolvedSeoHeadData } from './seo-head-data'
7
+ import { resolveSeoHeadData } from './seo-head-data'
8
+
9
+ type SeoMetaEntry = readonly ['name' | 'property', string, string | undefined]
10
+ type ResolvedSeoMetaEntry = readonly ['name' | 'property', string, string]
11
+
12
+ /**
13
+ * Adds canonical, robots, Open Graph, and Twitter metadata on top of Rspress defaults.
14
+ *
15
+ * @returns Route-aware metadata for the current page, or `null` when SEO is not configured
16
+ */
17
+ export default function SeoHead(): React.ReactElement | null {
18
+ const { site } = useSite()
19
+ const { page } = usePageData()
20
+ const { frontmatter } = useFrontmatter()
21
+ const { pathname } = useLocation()
22
+ const themeConfig = site.themeConfig as SeoThemeConfig
23
+ const siteSeo = themeConfig.seo
24
+ const seoBase = themeConfig.seoBase
25
+
26
+ if (isNil(siteSeo) || isNil(seoBase)) {
27
+ return null
28
+ }
29
+
30
+ const metadata = resolveSeoHeadData({
31
+ siteSeo,
32
+ base: seoBase,
33
+ siteDescription: site.description,
34
+ page,
35
+ pathname,
36
+ frontmatter,
37
+ })
38
+ const metaTags = resolveMetaTags(metadata)
39
+
40
+ return (
41
+ <Head>
42
+ {isNotNil(metadata.title) && <title>{metadata.title}</title>}
43
+ {isNotNil(metadata.canonical) && <link rel="canonical" href={metadata.canonical} />}
44
+ {metaTags.map(renderMetaTag)}
45
+ </Head>
46
+ )
47
+ }
48
+
49
+ /**
50
+ * Converts resolved SEO data into typed HTML meta-tag attributes.
51
+ *
52
+ * @private
53
+ */
54
+ function resolveMetaTags(metadata: ResolvedSeoHeadData): readonly ResolvedSeoMetaEntry[] {
55
+ const entries: readonly SeoMetaEntry[] = [
56
+ ['name', 'description', metadata.description],
57
+ ['name', 'robots', metadata.robots],
58
+ ...match(metadata.openGraph)
59
+ .with(false, () => [])
60
+ .otherwise((openGraph): readonly SeoMetaEntry[] => [
61
+ ['property', 'og:url', openGraph.url],
62
+ ['property', 'og:title', openGraph.title],
63
+ ['property', 'og:description', openGraph.description],
64
+ ['property', 'og:type', openGraph.type],
65
+ ['property', 'og:site_name', openGraph.siteName],
66
+ ['property', 'og:locale', openGraph.locale],
67
+ ['property', 'og:image', openGraph.image],
68
+ ]),
69
+ ...match(metadata.twitter)
70
+ .with(false, () => [])
71
+ .otherwise((twitter): readonly SeoMetaEntry[] => [
72
+ ['name', 'twitter:card', twitter.card],
73
+ ['name', 'twitter:title', twitter.title],
74
+ ['name', 'twitter:description', twitter.description],
75
+ ['name', 'twitter:site', twitter.site],
76
+ ['name', 'twitter:creator', twitter.creator],
77
+ ['name', 'twitter:image', twitter.image],
78
+ ]),
79
+ ]
80
+ return entries.filter(isResolvedMetaEntry)
81
+ }
82
+
83
+ /**
84
+ * Narrows a meta entry after missing content is filtered out.
85
+ *
86
+ * @private
87
+ */
88
+ function isResolvedMetaEntry(entry: SeoMetaEntry): entry is ResolvedSeoMetaEntry {
89
+ return isNotNil(entry[2])
90
+ }
91
+
92
+ /**
93
+ * Renders one typed meta-tag descriptor.
94
+ *
95
+ * @private
96
+ */
97
+ function renderMetaTag([attribute, key, content]: ResolvedSeoMetaEntry): React.ReactElement {
98
+ return match(attribute)
99
+ .with('name', () => <meta key={key} name={key} content={content} />)
100
+ .with('property', () => <meta key={key} property={key} content={content} />)
101
+ .exhaustive()
102
+ }
@@ -0,0 +1,42 @@
1
+ import type React from 'react'
2
+
3
+ import type { IssueLinkProvider } from '../../../plugins/issue-links/remark-issue-links.ts'
4
+ import { Icon } from './icon.tsx'
5
+
6
+ const PROVIDER_ICONS = {
7
+ asana: 'logos:asana-icon',
8
+ bitbucket: 'devicon:bitbucket',
9
+ clickup: 'simple-icons:clickup',
10
+ confluence: 'devicon:confluence',
11
+ dash0: 'simple-icons:dash0',
12
+ datadog: 'logos:datadog',
13
+ figma: 'devicon:figma',
14
+ github: 'simple-icons:github',
15
+ gitlab: 'logos:gitlab-icon',
16
+ 'google-docs': 'mdi:file-document',
17
+ 'google-drive': 'logos:google-drive',
18
+ 'google-sheets': 'mdi:google-spreadsheet',
19
+ jira: 'devicon:jira',
20
+ launchdarkly: 'logos:launchdarkly-icon',
21
+ linear: 'simple-icons:linear',
22
+ loom: 'logos:loom-icon',
23
+ notion: 'simple-icons:notion',
24
+ npm: 'logos:npm-icon',
25
+ postman: 'logos:postman-icon',
26
+ posthog: 'logos:posthog-icon',
27
+ pulumi: 'logos:pulumi-icon',
28
+ pagerduty: 'logos:pagerduty',
29
+ sentry: 'simple-icons:sentry',
30
+ slack: 'logos:slack-icon',
31
+ trello: 'logos:trello',
32
+ vercel: 'simple-icons:vercel',
33
+ } as const satisfies Record<IssueLinkProvider, string>
34
+
35
+ interface IssueLinkIconProps {
36
+ readonly provider: IssueLinkProvider
37
+ }
38
+
39
+ /** Render a URL badge's provider mark through the shared Iconify pipeline. */
40
+ export default function IssueLinkIcon({ provider }: IssueLinkIconProps): React.ReactElement {
41
+ return <Icon aria-hidden="true" className="cp-issue-link__icon" icon={PROVIDER_ICONS[provider]} />
42
+ }
@@ -0,0 +1,74 @@
1
+ /** URL-derived resource badges with provider-specific icons. */
2
+
3
+ .rp-doc a.rp-link.cp-issue-link {
4
+ display: inline-flex;
5
+ gap: 0.35em;
6
+ align-items: center;
7
+ padding: 0.14em 0.55em;
8
+ border: 1px solid var(--cp-c-border);
9
+ border-radius: var(--cp-radius-pill);
10
+ background: var(--cp-c-bg-soft);
11
+ background-image: none;
12
+ color: var(--cp-c-text-2);
13
+ font-size: 0.82em;
14
+ font-weight: 600;
15
+ line-height: 1.35;
16
+ text-decoration: none;
17
+ text-shadow: none;
18
+ vertical-align: 0.08em;
19
+ white-space: nowrap;
20
+ }
21
+
22
+ .rp-doc a.rp-link.cp-issue-link:hover {
23
+ border-color: var(--cp-c-text-3);
24
+ background: color-mix(in srgb, var(--cp-c-bg-soft) 82%, var(--cp-c-text-1));
25
+ background-image: none;
26
+ color: var(--cp-c-text-1);
27
+ opacity: 1;
28
+ text-decoration: none;
29
+ text-shadow: none;
30
+ }
31
+
32
+ .rp-doc a.rp-link.cp-issue-link[target='_blank']::after {
33
+ content: none;
34
+ }
35
+
36
+ .rp-doc a.rp-link.cp-issue-link:focus-visible {
37
+ outline: 2px solid var(--cp-c-brand-1);
38
+ outline-offset: 2px;
39
+ }
40
+
41
+ .cp-issue-link__icon {
42
+ display: inline-block;
43
+ width: 1em;
44
+ height: 1em;
45
+ flex: none;
46
+ }
47
+
48
+ .cp-issue-link__reference {
49
+ color: var(--cp-c-text-3);
50
+ font-size: 0.92em;
51
+ font-weight: 650;
52
+ font-variant-numeric: tabular-nums;
53
+ }
54
+
55
+ .cp-issue-link--github .cp-issue-link__icon,
56
+ .cp-issue-link--notion .cp-issue-link__icon,
57
+ .cp-issue-link--sentry .cp-issue-link__icon {
58
+ color: var(--cp-c-text-1);
59
+ }
60
+
61
+ .cp-issue-link--google-docs .cp-issue-link__icon {
62
+ color: #4285f4;
63
+ }
64
+
65
+ .cp-issue-link--google-sheets .cp-issue-link__icon {
66
+ color: #0f9d58;
67
+ }
68
+
69
+ html[data-cp-variant='dark'] .cp-issue-link--linear .cp-issue-link__icon,
70
+ html[data-cp-variant='dark'] .cp-issue-link--launchdarkly .cp-issue-link__icon,
71
+ html[data-cp-variant='dark'] .cp-issue-link--vercel .cp-issue-link__icon {
72
+ color: #fff;
73
+ fill: #fff;
74
+ }
@@ -43,6 +43,22 @@ const groupWithoutLink: SidebarData[number] = {
43
43
  items: [{ text: 'Deep Page', link: '/packages/deep/page' }],
44
44
  }
45
45
 
46
+ const launchpad: SidebarData[number] = {
47
+ text: 'Launchpad',
48
+ link: '/launchpad',
49
+ collapsible: true,
50
+ collapsed: true,
51
+ items: [
52
+ {
53
+ text: 'Concepts',
54
+ collapsible: true,
55
+ collapsed: false,
56
+ items: [{ text: 'Architecture', link: '/launchpad/concepts/architecture' }],
57
+ },
58
+ { text: 'Getting Started', link: '/launchpad/getting-started' },
59
+ ],
60
+ }
61
+
46
62
  const fullSidebar: SidebarData = [gettingStarted, packages, contributing]
47
63
  const scopes: readonly string[] = ['/packages', '/contributing']
48
64
 
@@ -60,25 +76,49 @@ describe('resolveScopedSidebar()', () => {
60
76
  expect(result[0]).toMatchObject({ text: 'Getting Started' })
61
77
  })
62
78
 
63
- it('should show only the matching standalone section on an exact scope path', () => {
79
+ it('should flatten the matching standalone section on an exact scope path', () => {
64
80
  const result = resolveScopedSidebar(fullSidebar, '/packages', scopes)
65
81
 
66
- expect(result).toHaveLength(1)
67
- expect(result[0]).toMatchObject({ text: 'Packages' })
82
+ expect(result).toStrictEqual([
83
+ { text: 'Packages', link: '/packages' },
84
+ { text: 'CLI', link: '/packages/cli' },
85
+ { text: 'Core', link: '/packages/core' },
86
+ ])
68
87
  })
69
88
 
70
- it('should show only the matching standalone section on a nested scope path', () => {
89
+ it('should flatten the matching standalone section on a nested scope path', () => {
71
90
  const result = resolveScopedSidebar(fullSidebar, '/packages/cli', scopes)
72
91
 
73
- expect(result).toHaveLength(1)
74
- expect(result[0]).toMatchObject({ text: 'Packages' })
92
+ expect(result).toStrictEqual([
93
+ { text: 'Packages', link: '/packages' },
94
+ { text: 'CLI', link: '/packages/cli' },
95
+ { text: 'Core', link: '/packages/core' },
96
+ ])
75
97
  })
76
98
 
77
- it('should show only contributing items on the contributing scope', () => {
99
+ it('should flatten contributing items on the contributing scope', () => {
78
100
  const result = resolveScopedSidebar(fullSidebar, '/contributing/guides', scopes)
79
101
 
80
- expect(result).toHaveLength(1)
81
- expect(result[0]).toMatchObject({ text: 'Contributing' })
102
+ expect(result).toStrictEqual([
103
+ { text: 'Contributing', link: '/contributing' },
104
+ { text: 'Guides', link: '/contributing/guides' },
105
+ { text: 'Standards', link: '/contributing/standards' },
106
+ ])
107
+ })
108
+
109
+ it('should promote an island page before its preserved nested groups', () => {
110
+ const result = resolveScopedSidebar([launchpad], '/launchpad', ['/launchpad'])
111
+
112
+ expect(result).toStrictEqual([
113
+ { text: 'Launchpad', link: '/launchpad' },
114
+ {
115
+ text: 'Concepts',
116
+ collapsible: true,
117
+ collapsed: false,
118
+ items: [{ text: 'Architecture', link: '/launchpad/concepts/architecture' }],
119
+ },
120
+ { text: 'Getting Started', link: '/launchpad/getting-started' },
121
+ ])
82
122
  })
83
123
 
84
124
  it('should not mutate the original sidebar data', () => {
@@ -19,9 +19,9 @@ type SidebarDataItem = SidebarData[number]
19
19
  * Resolve the sidebar items visible for the current scope.
20
20
  *
21
21
  * When the current pathname matches a standalone scope (e.g. `/packages`),
22
- * only that section's sidebar items are returned. For all other paths,
23
- * standalone sections are excluded and the remaining sections form a
24
- * unified sidebar.
22
+ * a linked section is promoted to a sidebar root before its children. An
23
+ * unlinked section returns only its children. For all other paths, standalone
24
+ * sections are excluded and the remaining sections form a unified sidebar.
25
25
  *
26
26
  * @param items - Full unified sidebar items
27
27
  * @param pathname - Current decoded URL pathname
@@ -44,7 +44,7 @@ export function resolveScopedSidebar(
44
44
  const all = [...items]
45
45
 
46
46
  if (standaloneMatch) {
47
- return all.filter((item) => belongsToScope(item, standaloneMatch))
47
+ return all.filter((item) => belongsToScope(item, standaloneMatch)).flatMap(flattenScopeRoot)
48
48
  }
49
49
 
50
50
  return all.filter((item) => !scopes.some((scope) => belongsToScope(item, scope)))
@@ -77,3 +77,23 @@ export function belongsToScope(item: SidebarDataItem, scope: string): boolean {
77
77
  }
78
78
  return false
79
79
  }
80
+
81
+ /**
82
+ * Convert a standalone section wrapper into a normal root page followed by
83
+ * its nested sidebar structure.
84
+ *
85
+ * @private
86
+ * @param item - Matching standalone sidebar root
87
+ * @returns The root page and children, or the root itself when it has no children
88
+ */
89
+ function flattenScopeRoot(item: SidebarDataItem): readonly SidebarDataItem[] {
90
+ if (Object.hasOwn(item, 'items')) {
91
+ const { items } = item as { readonly items: readonly SidebarDataItem[] }
92
+ if (Object.hasOwn(item, 'text') && Object.hasOwn(item, 'link')) {
93
+ const { text, link } = item as { readonly text: string; readonly link: string }
94
+ return [{ text, link }, ...items]
95
+ }
96
+ return items
97
+ }
98
+ return [item]
99
+ }
@@ -73,6 +73,7 @@ import './components/openapi/openapi.css'
73
73
  import './components/shared/accordion.css'
74
74
  import './components/shared/columns.css'
75
75
  import './components/shared/status-badge.css'
76
+ import './components/shared/issue-link.css'
76
77
  import './components/shared/frame.css'
77
78
  import './components/shared/tooltip.css'
78
79
  import './components/shared/prompt.css'
@@ -101,7 +102,14 @@ export type { FeatureCardProps, FeatureItem } from './components/home/feature-ca
101
102
  export { PageRail } from './components/home/page-rail'
102
103
  export type { PageRailProps } from './components/home/page-rail'
103
104
  export { Hero } from './components/home/hero'
104
- export type { HeroProps, HeroAction } from './components/home/hero'
105
+ export type {
106
+ HeroProps,
107
+ HeroAction,
108
+ HeroBackground,
109
+ HeroBackgroundImage,
110
+ HeroBackgroundSource,
111
+ HeroBackgroundVariants,
112
+ } from './components/home/hero'
105
113
  export { HeroDemo } from './components/home/hero-demo'
106
114
  export { TrustStrip } from './components/home/trust-strip'
107
115
  export type { TrustStripProps } from './components/home/trust-strip'
@@ -82,10 +82,8 @@ export const MARK_CLASS = 'cp-mark'
82
82
  // to 128k chars (0.19ms -> 0.45ms) across tag-name runs, attribute runs,
83
83
  // quote runs, unbalanced parens, and unterminated quotes. The pattern this
84
84
  // replaced *was* quadratic (2ms -> 427ms over the same range).
85
- /* oxlint-disable security/detect-unsafe-regex -- disjoint alternations, measured linear */
86
85
  const TOKEN_PATTERN =
87
86
  /(?:\\([*=`[\]<\\]))|(?:`([^`]+)`)|(?:\*\*([\s\S]+?)\*\*)|(?:==([\s\S]+?)==)|(?:(?<!\*)\*(?=[^\s*])([^*\n]+?)(?<=[^\s*])\*(?!\*))|(?:\[([^\]]*)\]\(((?:[^()\s]|\([^()\s]*\))+)\))|(?:<(\/?)\s*([a-zA-Z][a-zA-Z0-9-]*)(?=[\s/>])((?:"[^"]*"|'[^']*'|[^>"'])*)>)/
88
- /* oxlint-enable security/detect-unsafe-regex */
89
87
 
90
88
  const ATTR_PATTERN = /([a-zA-Z-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g
91
89
 
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Resolves the production root URL for a base-mounted documentation site.
3
+ *
4
+ * @param params - Production origin and resolved Rspress base path
5
+ * @returns Absolute URL for the deployed site root
6
+ */
7
+ export function resolveSeoSiteUrl(params: {
8
+ readonly origin: string
9
+ readonly base: string
10
+ }): string {
11
+ return new URL(params.base, params.origin).href
12
+ }
13
+
14
+ /**
15
+ * Resolves a basename-stripped router pathname against the deployed site root.
16
+ *
17
+ * @param params - Production origin, resolved Rspress base, and router pathname
18
+ * @returns Absolute production URL for the page
19
+ */
20
+ export function resolveSeoPageUrl(params: {
21
+ readonly origin: string
22
+ readonly base: string
23
+ readonly pathname: string
24
+ }): string {
25
+ const siteUrl = resolveSeoSiteUrl(params)
26
+ const relativePathname = params.pathname.replace(/^\/+/, '')
27
+ return new URL(relativePathname, siteUrl).href
28
+ }
@@ -23,9 +23,7 @@ export function syncThemeFavicon(html: HTMLElement): void {
23
23
  const surface = resolveSurfaceColor(html)
24
24
  const dataUri = buildIconDataUri(brand, shadow, surface)
25
25
  const link = ensureFaviconLink()
26
- // oxlint-disable-next-line functional/immutable-data -- boundary mutation: updating link element href
27
26
  link.type = 'image/svg+xml'
28
- // oxlint-disable-next-line functional/immutable-data -- boundary mutation: updating link element href
29
27
  link.href = dataUri
30
28
  }
31
29
 
@@ -118,7 +116,6 @@ function ensureFaviconLink(): HTMLLinkElement {
118
116
  return existing
119
117
  }
120
118
  const link = globalThis.document.createElement('link')
121
- // oxlint-disable-next-line functional/immutable-data -- boundary mutation: initialising newly created link element
122
119
  link.rel = 'icon'
123
120
  globalThis.document.head.append(link)
124
121
  return link
@@ -288,7 +288,7 @@ html[data-cp-theme='honeycrisp'][data-cp-variant='dark'] {
288
288
  }
289
289
 
290
290
  html[data-cp-theme='honeycrisp'][data-cp-variant='light'] {
291
- --cp-c-brand-1: #dc2626;
291
+ --cp-c-brand-1: #d02020;
292
292
  --cp-c-brand-2: #b91c1c;
293
293
  --cp-c-brand-3: #7f1d1d;
294
294
  --cp-c-brand-fg: #ffffff;
@@ -301,15 +301,15 @@ html[data-cp-theme='honeycrisp'][data-cp-variant='light'] {
301
301
  --cp-c-warn: #d97706;
302
302
  --cp-c-info: #2563eb;
303
303
  --cp-c-muted: #888888;
304
- --cp-c-bg: #ffffff;
305
- --cp-c-bg-alt: #f9f9f9;
306
- --cp-c-bg-elv: #f5f5f5;
307
- --cp-c-bg-soft: #f0f0f0;
308
- --cp-c-bg-icon: #cccccc;
309
- --cp-c-home-bg: #ffffff;
304
+ --cp-c-bg: #f7f5f0;
305
+ --cp-c-bg-alt: #f1eee7;
306
+ --cp-c-bg-elv: #fffdf8;
307
+ --cp-c-bg-soft: #ebe7dc;
308
+ --cp-c-bg-icon: #d5cebe;
309
+ --cp-c-home-bg: #f7f5f0;
310
310
  --cp-c-overlay-faint: rgba(0, 0, 0, 0.1);
311
- --cp-c-gutter: #f5f5f5;
312
- --cp-code-block-bg: #f5f5f5;
311
+ --cp-c-gutter: #f1eee7;
312
+ --cp-code-block-bg: #f1eee7;
313
313
  --cp-c-text-1: #1a1a1a;
314
314
  --cp-c-text-2: rgba(26, 26, 26, 0.72);
315
315
  --cp-c-text-3: rgba(26, 26, 26, 0.48);
@@ -384,7 +384,7 @@ html[data-cp-theme='honeycrisp'][data-cp-variant='light'] {
384
384
  --cp-oas-deprecated: var(--cp-c-text-3);
385
385
  --cp-oas-required: #dc2626;
386
386
  --cp-button-brand-bg: #b91c1c;
387
- --cp-button-brand-hover-bg: #dc2626;
387
+ --cp-button-brand-hover-bg: #d02020;
388
388
  --cp-button-brand-active-bg: #7f1d1d;
389
389
  --cp-button-brand-text: #ffffff;
390
390
  --cp-s-1: 1px;
@@ -535,12 +535,12 @@ html[data-cp-theme='honeycrisp'][data-cp-variant='light'] {
535
535
  --cp-blur-base: 8px;
536
536
  --cp-gradient-brand: linear-gradient(135deg, var(--cp-c-brand-1), var(--cp-c-brand-3));
537
537
  --cp-gradient-hero-title: linear-gradient(135deg, var(--cp-c-brand-1), var(--cp-c-brand-light));
538
- --rp-c-bg: #ffffff;
539
- --rp-c-bg-alt: #f9f9f9;
540
- --rp-c-bg-dark: #f5f5f5;
541
- --rp-c-bg-mute: #ffffff;
542
- --rp-c-bg-soft: #f0f0f0;
543
- --rp-c-brand: #dc2626;
538
+ --rp-c-bg: #f7f5f0;
539
+ --rp-c-bg-alt: #f1eee7;
540
+ --rp-c-bg-dark: #f1eee7;
541
+ --rp-c-bg-mute: #f7f5f0;
542
+ --rp-c-bg-soft: #ebe7dc;
543
+ --rp-c-brand: #d02020;
544
544
  --rp-c-brand-light: #ef4444;
545
545
  --rp-c-brand-lighter: #fca5a5;
546
546
  --rp-c-brand-dark: #b91c1c;
@@ -549,15 +549,15 @@ html[data-cp-theme='honeycrisp'][data-cp-variant='light'] {
549
549
  --rp-c-divider: #e2e2e2;
550
550
  --rp-c-divider-dark: #d0d0d0;
551
551
  --rp-c-divider-light: #e2e2e2;
552
- --rp-c-link: #dc2626;
552
+ --rp-c-link: #d02020;
553
553
  --rp-c-text-1: #1a1a1a;
554
554
  --rp-c-text-2: rgba(26, 26, 26, 0.72);
555
555
  --rp-c-text-3: rgba(26, 26, 26, 0.48);
556
556
  --rp-c-text-4: rgba(26, 26, 26, 0.48);
557
557
  --rp-c-text-code: #1a1a1a;
558
- --rp-code-block-bg: #f5f5f5;
559
- --rp-home-background-bg: #ffffff;
560
- --rp-home-feature-bg: #f0f0f0;
558
+ --rp-code-block-bg: #f1eee7;
559
+ --rp-home-background-bg: #f7f5f0;
560
+ --rp-home-feature-bg: #ebe7dc;
561
561
  --rp-home-hero-secondary-color: rgba(26, 26, 26, 0.72);
562
562
  --rp-home-hero-title-color: #1a1a1a;
563
563
  --rp-font-family-base: