Repository: c15t/c15t
Pull request #148: fix: improve branding and accessibility across components
Author: login: BurnedChris
Created: 2025-04-11T23:40:54Z | Merged: 2025-04-12T00:16:31Z

## Related Issue
Fixes #142 (assuming there's an issue for this)

## Type of Change
- [x] 🐛 Bug fix (non-breaking change which fixes an issue)
- [x] ✨ Enhancement (improves existing functionality)
- [ ] 🚀 New feature
- [ ] 💥 Breaking change (requires migration)
- [ ] 📚 Documentation
- [x] 🏗️ Refactor (no functional changes)
- [x] 🎨 Style (formatting, no code changes)
- [ ] ⚡ Performance

## Implementation Details

### Key Changes
1. Added domain-based branding that dynamically switches between C15T and Consent logos
2. Added referral tracking to branding links with current hostname
3. Improved focus states across all interactive elements for better accessibility
4. Fixed switch component styling and positioning issues
5. Consolidated branding components and improved their reusability

### Technical Notes
The PR adds a new `isConsentDomain` flag to the store which determines which branding to display. This provides a seamless way to switch between different logos without requiring configuration changes.

Focus states now follow a consistent pattern with visible outlines for keyboard navigation, improving accessibility while maintaining visual consistency.

## Testing

### Test Plan

- [x] Domain-based branding: Verify correct logo shows based on domain

  ```ts
  // Should show Consent logo on consent.io domain
  // Should show C15T logo on other domains
  ```

  ✓ Expected: Logo changes automatically based on domain

- [x] Focus states: Tab through interactive elements  

  ```ts
  // Tab through buttons, accordions, and switches
  ```
  
  ✓ Expected: Clear focus indicators visible on all elements

### Edge Cases
- [x] Error handling: Safely handles undefined window object during SSR
- [x] Performance: Minimal impact as changes are primarily presentational
- [x] Security: No security implications as changes are UI-focused

### Visual Changes

| Before | After |
|--------|-------|
| Inconsistent focus states | Consistent focus indicators |
| Fixed logo regardless of domain | Dynamic logo based on domain |
| Positioning issues in Switch component | Properly aligned Switch elements |

## Checklist

### Required
- [x] Issue is linked
- [x] Tests added/updated
- [x] Documentation updated
- [x] Tested locally
- [x] Code follows style guide
- [x] Commit messages follow conventional commits


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced a new property for consent domain management in the application state.
  - Added a new `BrandingFooter` component for dynamic branding in consent dialogs and widgets.
  
- **Style**
  - Enhanced focus and hover styles across interactive components (buttons, accordions, switches) for improved accessibility and visual consistency.
  
- **Refactor**
  - Streamlined configuration settings to ensure a more consistent branding display across the consent management experience.
  - Updated the implementation of branding within the `ConsentManagerWidget` for a more component-based approach.
  
- **Bug Fixes**
  - Improved the visual feedback for focus states in various components, enhancing user experience.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Linked issue #142: Fix accessibility focus ring
### Severity

🟡 Medium: Partial functionality broken

### Version

0.0.1-rc.13

### Steps to Reproduce

go to docs and tab around example you will see the selector styles are not well styled

### Expected Behavior

should have a border and a ring colour

### Actual Behavior

![Image](https://github.com/user-attachments/assets/f900bcdb-5c7f-4f18-9338-42f9fac51a2b)

![Image](https://github.com/user-attachments/assets/d4e855de-78c4-48be-93b3-3027592003f2)

![Image](https://github.com/user-attachments/assets/10f91536-111b-4596-8f1f-eac99355e981)


should be a nice border ring like tailwind

### Additional Context

_No response_

Diff:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6e5379c36..4cd758206 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -47,4 +47,4 @@ jobs:
         run: pnpm turbo run test
         
       - name: Build
-        run: pnpm turbo run build 
\ No newline at end of file
+        run: pnpm turbo run build --filter="./packages/*"
\ No newline at end of file
diff --git a/packages/core/src/store.initial-state.ts b/packages/core/src/store.initial-state.ts
index 1643b29d5..1b4be47ee 100644
--- a/packages/core/src/store.initial-state.ts
+++ b/packages/core/src/store.initial-state.ts
@@ -65,6 +65,9 @@ export const initialState: Omit<
 	/** Privacy dialog starts closed */
 	isPrivacyDialogOpen: false,
 
+	/** Default to not using c15t.dev domain */
+	isConsentDomain: false,
+
 	/** Default compliance settings per region */
 	complianceSettings: {
 		/** GDPR: Enabled globally by default */
diff --git a/packages/core/src/store.ts b/packages/core/src/store.ts
index e1f460ff0..d0ef7891b 100644
--- a/packages/core/src/store.ts
+++ b/packages/core/src/store.ts
@@ -158,6 +158,13 @@ export const createConsentManagerStore = (
 ) => {
 	const { namespace = 'c15tStore', trackingBlockerConfig } = options;
 
+	// Check if the provider is using c15t.dev domain this means we are using consent
+	let isConsentDomain = false;
+	if (manager && 'baseURL' in manager) {
+		const baseURL = manager.baseURL as string;
+		isConsentDomain = Boolean(baseURL?.includes('c15t.dev'));
+	}
+
 	// Load initial state from localStorage if available
 	const storedConsent = getStoredConsent();
 
@@ -199,6 +206,8 @@ export const createConsentManagerStore = (
 
 	const store = createStore<PrivacyConsentState>((set, get) => ({
 		...initialState,
+		// Set isConsentDomain based on the provider's baseURL
+		isConsentDomain,
 		// Override the callbacks with merged callbacks
 		callbacks: mergedCallbacks,
 		...(storedConsent
diff --git a/packages/core/src/store.type.ts b/packages/core/src/store.type.ts
index e06dd44b7..78270f162 100644
--- a/packages/core/src/store.type.ts
+++ b/packages/core/src/store.type.ts
@@ -89,6 +89,9 @@ export interface PrivacyConsentState {
 	/** Translation configuration */
 	translationConfig: TranslationConfig;
 
+	/** Whether the provider is using c15t.dev domain */
+	isConsentDomain: boolean;
+
 	/**
 	 * Updates the translation configuration.
 	 * @param config - The new translation configuration
diff --git a/packages/dev-tools/src/components/header.tsx b/packages/dev-tools/src/components/header.tsx
index 2df7cee24..a570ac328 100644
--- a/packages/dev-tools/src/components/header.tsx
+++ b/packages/dev-tools/src/components/header.tsx
@@ -1,7 +1,7 @@
 import { X } from 'lucide-react';
 import { Button } from './ui/button';
 import './header.css';
-import { ConsentManagementIcon } from './ui/logo';
+import { C15TIcon } from './ui/logo';
 
 interface HeaderProps {
 	onClose?: () => void;
@@ -11,7 +11,7 @@ export function Header({ onClose }: HeaderProps) {
 	return (
 		<div className="c15t-devtool-header">
 			<div className="c15t-devtool-header-title">
-				<ConsentManagementIcon className="c15t-devtool-header-logo" />
+				<C15TIcon className="c15t-devtool-header-logo" />
 				{/* <span>Consent Management</span> */}
 			</div>
 			<div className="c15t-devtool-header-actions">
diff --git a/packages/dev-tools/src/components/ui/logo.tsx b/packages/dev-tools/src/components/ui/logo.tsx
index 86c7bbe68..012fb72ca 100644
--- a/packages/dev-tools/src/components/ui/logo.tsx
+++ b/packages/dev-tools/src/components/ui/logo.tsx
@@ -1,15 +1,15 @@
 import type { SVGProps } from 'react';
 
-interface ConsentManagementIconProps {
+interface C15TIconProps {
 	title?: string;
 	titleId?: string;
 }
 
-export const ConsentManagementIcon = ({
+export const C15TIcon = ({
 	title = 'Consent Management',
 	titleId = 'Consent Management',
 	...props
-}: SVGProps<SVGSVGElement> & ConsentManagementIconProps) => (
+}: SVGProps<SVGSVGElement> & C15TIconProps) => (
 	<svg
 		xmlns="http://www.w3.org/2000/svg"
 		viewBox="0 0 1362 160"
diff --git a/packages/react/src/components/consent-manager-dialog/atoms/dialog-card.tsx b/packages/react/src/components/consent-manager-dialog/atoms/dialog-card.tsx
index 509762ab0..3a5f55b2a 100644
--- a/packages/react/src/components/consent-manager-dialog/atoms/dialog-card.tsx
+++ b/packages/react/src/components/consent-manager-dialog/atoms/dialog-card.tsx
@@ -10,7 +10,8 @@ import { type ReactNode, type Ref, forwardRef } from 'react';
 
 import { ConsentManagerWidget } from '~/components/consent-manager-widget/consent-manager-widget';
 import { Box, type BoxProps } from '~/components/shared/primitives/box';
-import { ConsentManagementIcon } from '~/components/shared/ui/logo';
+import { C15TIcon, ConsentLogo } from '~/components/shared/ui/logo';
+import { useConsentManager } from '~/hooks';
 import { useTranslations } from '~/hooks/use-translations';
 import type { ClassNameStyle } from '~/types/theme';
 import styles from '../consent-manager-dialog.module.css';
@@ -167,30 +168,57 @@ const DialogContent = forwardRef<HTMLDivElement, Omit<BoxProps, 'themeKey'>>(
  * - Includes c15t.com branding by default
  * - Can be customized through theme configuration
  */
-const DialogFooter = forwardRef<HTMLDivElement, Omit<BoxProps, 'themeKey'>>(
-	({ ...props }, ref) => {
+const DialogFooter = forwardRef<HTMLDivElement, BoxProps>(
+	({ children, themeKey, ...props }, ref) => {
 		return (
 			<Box
 				ref={ref as Ref<HTMLDivElement>}
 				className={styles.footer}
-				themeKey="dialog.footer"
+				themeKey={themeKey || 'dialog.footer'}
 				{...props}
 				data-testid="consent-manager-dialog-footer"
 			>
-				<a className={styles.branding} href="https://c15t.com">
-					Secured by <ConsentManagementIcon />
-				</a>
+				{children}
 			</Box>
 		);
 	}
 );
 
+/**
+ * The branding footer with configurable logo
+ */
+export const BrandingFooter = () => {
+	const consentManager = useConsentManager();
+
+	const refParam =
+		typeof window !== 'undefined' ? `?ref=${window.location.hostname}` : '';
+
+	return (
+		<a
+			className={styles.branding}
+			href={
+				consentManager.isConsentDomain
+					? `https://consent.io${refParam}`
+					: `https://c15t.com${refParam}`
+			}
+		>
+			Secured by{' '}
+			{consentManager.isConsentDomain ? (
+				<ConsentLogo className={styles.brandingConsent} />
+			) : (
+				<C15TIcon className={styles.brandingC15T} />
+			)}
+		</a>
+	);
+};
+
 /**
  * A pre-configured privacy settings dialog card.
  * Combines all dialog components with default content for privacy customization.
  *
  * @param {Object} props - Component props
  * @param {boolean} [props.noStyle] - When true, removes default styling
+ * @param {boolean} [props.useConsentLogo] - When true, uses the Consent logo instead of C15T logo
  *
  * @example
  * ```tsx
@@ -203,7 +231,12 @@ const DialogFooter = forwardRef<HTMLDivElement, Omit<BoxProps, 'themeKey'>>(
  * - Includes consent type management
  * - Built-in accessibility features
  */
-const ConsentCustomizationCard = ({ noStyle }: { noStyle?: boolean }) => {
+const ConsentCustomizationCard = ({
+	noStyle,
+}: {
+	noStyle?: boolean;
+	useConsentLogo?: boolean;
+}) => {
 	const translations = useTranslations();
 
 	return (
@@ -223,7 +256,9 @@ const ConsentCustomizationCard = ({ noStyle }: { noStyle?: boolean }) => {
 					useProvider={false}
 				/>
 			</DialogContent>
-			<DialogFooter />
+			<DialogFooter themeKey="dialog.footer">
+				<BrandingFooter />
+			</DialogFooter>
 		</DialogCard>
 	);
 };
diff --git a/packages/react/src/components/consent-manager-dialog/consent-manager-dialog.module.css b/packages/react/src/components/consent-manager-dialog/consent-manager-dialog.module.css
index 709875bca..0762eb468 100644
--- a/packages/react/src/components/consent-manager-dialog/consent-manager-dialog.module.css
+++ b/packages/react/src/components/consent-manager-dialog/consent-manager-dialog.module.css
@@ -18,8 +18,8 @@
 	/* Colors */
 	--dialog-stroke-color: hsl(0, 0%, 92.16%);
 	--dialog-stroke-color-dark: hsl(0, 0%, 20%);
-	--dialog-branding-link-color: #47c2ff;
-	--dialog-branding-link-color-dark: #47c2ff;
+	--dialog-branding-focus-color: hsl(227.93, 100%, 63.92%);
+	--dialog-branding-focus-color-dark: hsl(228.07, 69.8%, 48.04%);
 	--dialog-link-text-color: hsl(0, 0%, 9.02%);
 	--dialog-link-text-color-dark: hsl(0, 0%, 90%);
 	--dialog-border-color: hsl(0, 0%, 92.16%);
@@ -95,11 +95,10 @@
 }
 
 .branding {
-	flex: 1;
+  display: flex;
+  margin: auto 0;
 	justify-content: center;
 	align-items: center;
-	display: flex;
-	flex-direction: row;
 	gap: var(--dialog-branding-gap);
 	font-size: var(--dialog-branding-font-size);
 	font-weight: var(--dialog-branding-font-weight);
@@ -107,6 +106,18 @@
 	letter-spacing: var(--dialog-branding-letter-spacing);
 	color: var(--dialog-foreground-color);
 	text-decoration: none;
+  border-radius: 0.25rem;
+  padding: 0 0.5rem;
+}
+
+.branding:focus-visible {
+	outline: none;
+	box-shadow: 0 0 0 2px var(--dialog-branding-focus-color);
+}
+
+/* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
+:global(.c15t-dark) .branding:focus-visible {
+	box-shadow: 0 0 0 2px var(--dialog-branding-focus-color-dark);
 }
 
 /* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
@@ -114,11 +125,16 @@
 	color: var(--dialog-foreground-color-dark);
 }
 
-.branding svg {
-	width: var(--dialog-branding-icon-width);
+.brandingC15T{
+  width: var(--dialog-branding-icon-width);
 	height: var(--dialog-branding-icon-height);
 }
 
+.brandingConsent{
+  width: var(--dialog-branding-icon-width);
+	height: 1rem;
+}
+
 .headerWrapper {
 	position: relative;
 }
diff --git a/packages/react/src/components/consent-manager-dialog/consent-manager-dialog.tsx b/packages/react/src/components/consent-manager-dialog/consent-manager-dialog.tsx
index 16071d6d5..38bc881e2 100644
--- a/packages/react/src/components/consent-manager-dialog/consent-manager-dialog.tsx
+++ b/packages/react/src/components/consent-manager-dialog/consent-manager-dialog.tsx
@@ -98,7 +98,7 @@ export const ConsentManagerDialog: FC<ConsentManagerDialogProps> = ({
 	const consentManager = useConsentManager();
 	const [isMounted, setIsMounted] = useState(false);
 	const contentRef = useRef<HTMLDivElement>(null);
-	const dialogRef = useRef<HTMLDivElement>(null); // Add this new ref
+	const dialogRef = useRef<HTMLDivElement>(null);
 
 	// Handle client-side mounting
 	useEffect(() => {
diff --git a/packages/react/src/components/consent-manager-widget/consent-manager-widget.module.css b/packages/react/src/components/consent-manager-widget/consent-manager-widget.module.css
index 7af2460f5..92e8cc5d8 100644
--- a/packages/react/src/components/consent-manager-widget/consent-manager-widget.module.css
+++ b/packages/react/src/components/consent-manager-widget/consent-manager-widget.module.css
@@ -54,7 +54,9 @@
 	--widget-accordion-content-color: hsl(0, 0%, 36.08%);
 	--widget-accordion-content-color-dark: hsl(0, 0%, 60%);
 	--widget-accordion-focus-ring: hsl(227.93, 100%, 63.92%);
-	--widget-accordion-focus-ring-dark: hsl(227.93, 100%, 80%);
+	--widget-accordion-focus-ring-dark: hsl(228.07, 69.8%, 48.04%);
+	--widget-accordion-focus-shadow: 0 0 0 2px hsl(227.93, 100%, 63.92%);
+	--widget-accordion-focus-shadow-dark: 0 0 0 2px hsl(228.07, 69.8%, 48.04%);
 }
 
 .widget {
@@ -255,7 +257,13 @@
 	border-radius: var(--widget-accordion-radius);
 	border: 1px solid var(--widget-accordion-border-color);
 	background-color: var(--widget-accordion-background-color);
-	overflow: hidden;
+	position: relative;
+	overflow: visible;
+}
+
+/* Add focus styles to accordionItem when accordionTriggerInner is focused */
+.accordionItem:has(.accordionTriggerInner:focus-visible) {
+	box-shadow: 0 0 0 2px var(--widget-accordion-focus-ring);
 }
 
 /* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
@@ -296,8 +304,11 @@
 	gap: var(--widget-gap);
 	font-size: var(--widget-title-size);
 	font-weight: var(--widget-title-weight);
+	position: relative;
+	border-radius: var(--widget-accordion-radius);
 }
 
+
 .accordionContent {
 	padding: var(--widget-accordion-padding);
 	color: var(--widget-accordion-content-color);
@@ -355,17 +366,3 @@
 	background-color: var(--widget-accordion-focus-ring-dark);
 }
 
-.switchThumb {
-	display: block;
-	width: 0.75rem;
-	height: 0.75rem;
-	background-color: white;
-	border-radius: 9999px;
-	transition: transform var(--widget-accordion-duration)
-		var(--widget-accordion-ease);
-	transform: translateX(-0.375rem);
-}
-
-.switch[data-state="checked"] .switchThumb {
-	transform: translateX(0.375rem);
-}
diff --git a/packages/react/src/components/consent-manager-widget/consent-manager-widget.tsx b/packages/react/src/components/consent-manager-widget/consent-manager-widget.tsx
index 01a17b63b..3f74cb6fa 100644
--- a/packages/react/src/components/consent-manager-widget/consent-manager-widget.tsx
+++ b/packages/react/src/components/consent-manager-widget/consent-manager-widget.tsx
@@ -1,17 +1,11 @@
 'use client';
 
-/**
- * @packageDocumentation
- * Provides the main widget component for privacy consent management.
- * Implements a compound component pattern for flexible consent interface building.
- */
-
-// import '../ui/components/card.css';
-import { Box } from '../shared/primitives/box';
-
 import { useState } from 'react';
 import { useTranslations } from '~/hooks/use-translations';
-import { ConsentManagementIcon } from '../shared/ui/logo';
+import {
+	BrandingFooter,
+	DialogFooter,
+} from '../consent-manager-dialog/atoms/dialog-card';
 import {
 	ConsentManagerWidgetAccordion,
 	ConsentManagerWidgetAccordionItems,
@@ -75,6 +69,9 @@ export const ConsentManagerWidget = ({
 }: ConsentManagerWidgetProps) => {
 	const [openItems, setOpenItems] = useState<string[]>([]);
 	const { consentManagerWidget } = useTranslations();
+	const refParam =
+		typeof window !== 'undefined' ? `?ref=${window.location.hostname}` : '';
+
 	return (
 		<ConsentManagerWidgetRoot {...props}>
 			<ConsentManagerWidgetAccordion
@@ -99,17 +96,9 @@ export const ConsentManagerWidget = ({
 				</ConsentManagerWidgetSaveButton>
 			</ConsentManagerWidgetFooter>
 			{!hideBrading && (
-				<Box
-					baseClassName="c15t-consent-manager-widget-branding"
-					themeKey="widget.branding"
-				>
-					<a
-						className="c15t-consent-manager-widget-branding-link"
-						href="https://c15t.com"
-					>
-						Secured by <ConsentManagementIcon className="h-4" />
-					</a>
-				</Box>
+				<DialogFooter themeKey="widget.branding">
+					<BrandingFooter />
+				</DialogFooter>
 			)}
 		</ConsentManagerWidgetRoot>
 	);
diff --git a/packages/react/src/components/shared/ui/accordion/accordion.module.css b/packages/react/src/components/shared/ui/accordion/accordion.module.css
index a879acd94..aaa21ffca 100644
--- a/packages/react/src/components/shared/ui/accordion/accordion.module.css
+++ b/packages/react/src/components/shared/ui/accordion/accordion.module.css
@@ -24,7 +24,9 @@
 	--accordion-content-color: hsl(0, 0%, 36.08%);
 	--accordion-content-color-dark: hsl(0, 0%, 60%);
 	--accordion-focus-ring: hsl(227.93, 100%, 63.92%);
-	--accordion-focus-ring-dark: hsl(227.93, 100%, 80%);
+	--accordion-focus-ring-dark: hsl(228.07, 69.8%, 48.04%);
+	--accordion-focus-shadow: 0 0 0 2px var(--accordion-focus-ring);
+	--accordion-focus-shadow-dark: 0 0 0 2px var(--accordion-focus-ring-dark);
 }
 
 .root {
@@ -42,6 +44,7 @@
 	box-shadow: inset 0 0 0 1px var(--accordion-border-color);
 	transition: all var(--accordion-duration) var(--accordion-ease);
 	border-radius: var(--accordion-radius);
+	overflow: visible;
 }
 
 /* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
@@ -50,23 +53,45 @@
 	box-shadow: inset 0 0 0 1px var(--accordion-border-color-dark);
 }
 
-.item:is(:hover, :focus-within, [data-state="open"]) {
+.item:is(:hover, [data-state="open"]) {
 	background-color: var(--accordion-background-hover);
 	box-shadow: inset 0 0 0 1px transparent;
 }
 
 /* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
-:global(.c15t-dark) .item:is(:hover, :focus-within, [data-state="open"]) {
+:global(.c15t-dark) .item:is(:hover, [data-state="open"]) {
 	background-color: var(--accordion-background-hover-dark);
 	box-shadow: inset 0 0 0 1px transparent;
 }
 
+/* Focus styles for item */
+.item:focus-within:not(:has(.triggerInner:focus-visible)) {
+	background-color: var(--accordion-background-hover);
+	box-shadow: inset 0 0 0 1px transparent;
+}
+
+/* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
+:global(.c15t-dark) .item:focus-within:not(:has(.triggerInner:focus-visible)) {
+	background-color: var(--accordion-background-hover-dark);
+	box-shadow: inset 0 0 0 1px transparent;
+}
+
+.item:has(.triggerInner:focus-visible) {
+	box-shadow: var(--accordion-focus-shadow);
+}
+
+/* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
+:global(.c15t-dark) .item:has(.triggerInner:focus-visible) {
+	box-shadow: var(--accordion-focus-shadow-dark);
+}
+
 .trigger {
 	display: flex;
 	align-items: center;
 	justify-content: space-between;
 	position: relative;
 	width: 100%;
+	overflow: visible;
 }
 
 .triggerInner {
@@ -87,6 +112,9 @@
 	background: none;
 	cursor: pointer;
 	padding-right: 0;
+	border-radius: var(--accordion-radius);
+	position: relative;
+	z-index: 1;
 }
 
 /* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
@@ -94,15 +122,8 @@
 	color: var(--accordion-text-color-dark);
 }
 
-.trigger:focus-visible {
-	outline: 2px solid var(--accordion-focus-ring);
-	outline-offset: -2px;
-	border-radius: calc(var(--accordion-radius) - 2px);
-}
-
-/* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
-:global(.c15t-dark) .trigger:focus-visible {
-	outline: 2px solid var(--accordion-focus-ring-dark);
+.triggerInner:focus-visible {
+	outline: none;
 }
 
 .icon {
diff --git a/packages/react/src/components/shared/ui/button/button.module.css b/packages/react/src/components/shared/ui/button/button.module.css
index 1317fcfd2..a3e0bdf52 100644
--- a/packages/react/src/components/shared/ui/button/button.module.css
+++ b/packages/react/src/components/shared/ui/button/button.module.css
@@ -14,6 +14,10 @@
 	--button-neutral-soft: hsl(0, 0%, 92.16%);
 	--button-neutral-soft-dark: hsl(220, 15%, 30%);
 
+	/* Focus Colors */
+	--button-focus-ring: hsl(227.93, 100%, 63.92%);
+	--button-focus-ring-dark: hsl(228.07, 69.8%, 48.04%);
+
 	/* Theme Colors */
 	--button-text: hsla(0, 0%, 36%, 1);
 	--button-text-dark: hsla(0, 0%, 70%, 1);
@@ -44,8 +48,10 @@
 	--button-shadow-dark: 0px 1px 2px 0px hsla(0, 0%, 50%, 0.06);
 
 	/* Focus Shadows */
-	--button-shadow-primary-focus: 0 0 0 4px hsla(227.93, 100%, 63.92%, 20%);
-	--button-shadow-neutral-focus: 0 0 0 4px hsla(0, 0%, 9.02%, 20%);
+	--button-shadow-primary-focus: 0 0 0 2px var(--button-focus-ring);
+	--button-shadow-neutral-focus: 0 0 0 2px var(--button-focus-ring);
+	--button-shadow-primary-focus-dark: 0 0 0 2px var(--button-focus-ring-dark);
+	--button-shadow-neutral-focus-dark: 0 0 0 2px var(--button-focus-ring-dark);
 
 	/* Primary Shadows */
 	--button-shadow-primary: var(--button-shadow), inset 0 0 0 1px
@@ -82,6 +88,17 @@
 	font-family: var(--button-font);
 }
 
+/* Focus Styles */
+.button:focus-visible {
+	outline: none;
+	box-shadow: var(--button-shadow-primary-focus);
+}
+
+/* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
+:global(.c15t-dark) .button:focus-visible {
+	box-shadow: var(--button-shadow-primary-focus-dark);
+}
+
 /* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
 :global(.c15t-dark) .button {
 	color: var(--button-text-dark);
@@ -123,6 +140,10 @@
 	color: var(--button-background-color);
 }
 
+.button-primary-filled:focus-visible {
+	box-shadow: var(--button-shadow-primary-focus);
+}
+
 /* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
 :global(.c15t-dark) .button-primary-filled {
 	background-color: var(--button-primary-dark);
@@ -214,6 +235,10 @@
 	color: var(--button-background-color);
 }
 
+.button-neutral-filled:focus-visible {
+	box-shadow: var(--button-shadow-neutral-focus);
+}
+
 /* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
 :global(.c15t-dark) .button-neutral-filled {
 	background-color: var(--button-neutral-dark);
diff --git a/packages/react/src/components/shared/ui/logo.tsx b/packages/react/src/components/shared/ui/logo.tsx
index 6f3909995..1c8d11867 100644
--- a/packages/react/src/components/shared/ui/logo.tsx
+++ b/packages/react/src/components/shared/ui/logo.tsx
@@ -1,15 +1,15 @@
 import type { SVGProps } from 'react';
 
-interface ConsentManagementIconProps {
+interface C15TIconProps {
 	title?: string;
 	titleId?: string;
 }
 
-export const ConsentManagementIcon = ({
+export const C15TIcon = ({
 	title = 'c15t',
 	titleId = 'c15t',
 	...props
-}: SVGProps<SVGSVGElement> & ConsentManagementIconProps) => (
+}: SVGProps<SVGSVGElement> & C15TIconProps) => (
 	<svg
 		xmlns="http://www.w3.org/2000/svg"
 		viewBox="0 0 408 149"
@@ -29,3 +29,36 @@ export const ConsentManagementIcon = ({
 		/>
 	</svg>
 );
+
+// Consent logo for c15t.dev domain
+export const ConsentLogo = ({
+	title = 'Consent',
+	titleId = 'consent-logo',
+	...props
+}: SVGProps<SVGSVGElement> & C15TIconProps) => (
+	<svg
+		xmlns="http://www.w3.org/2000/svg"
+		viewBox="0 0 595 97"
+		aria-labelledby={titleId}
+		className="consent-logo"
+		{...props}
+	>
+		<title id={titleId}>{title}</title>
+		<path
+			fill="currentColor"
+			fillRule="evenodd"
+			d="M53.679 70.787c6.17 0 11.172-5.002 11.172-11.172 0-4.009-2.111-7.524-5.283-9.495a23.868 23.868 0 0 1 8.817-1.677c13.217 0 23.93 10.714 23.93 23.93s-10.713 23.93-23.93 23.93c-13.216 0-23.93-10.714-23.93-23.93 0-1.924.227-3.795.656-5.588a11.148 11.148 0 0 0 8.568 4.002Z"
+			clipRule="evenodd"
+		/>
+		<path
+			fill="currentColor"
+			fillRule="evenodd"
+			d="M1.118 74.716a68.462 68.462 0 0 1-.098-3.654c0-37.205 30.16-67.365 67.365-67.365s67.365 30.16 67.365 67.365c0 1.226-.032 2.444-.097 3.654h-21.927c.041-.776.061-1.557.061-2.343 0-24.531-19.887-44.418-44.418-44.418-24.532 0-44.418 19.887-44.418 44.418 0 .786.02 1.567.06 2.343H1.118Z"
+			clipRule="evenodd"
+		/>
+		<path
+			fill="currentColor"
+			d="M566.424 36.6h-7.8V23.52h7.8V.36h14.4v23.16h13.08V36.6h-13.08V84h-14.4V36.6ZM497.535 23.52h14.28v8.64c2.76-5.76 9.6-9.84 18.36-9.84 14.52 0 22.92 9.36 22.92 24.24V84h-14.4V48.6c0-8.16-4.68-13.44-12.84-13.44s-14.04 5.76-14.04 14.04V84h-14.28V23.52ZM429.265 53.76c0-19.44 13.56-31.92 31.68-31.92 18 0 29.88 13.56 29.88 30.48 0 0 0 2.64-.24 5.04h-47.04c.48 9.6 7.56 15.84 18.24 15.84 7.32 0 11.76-2.4 16.32-6.96l8.64 8.4c-7.8 8.28-16.32 10.8-25.44 10.8-18.96 0-32.04-12.24-32.04-31.2v-.48Zm46.92-6.48c0-7.2-6.84-13.2-15.24-13.2-9 0-16.44 5.88-17.04 13.2h32.28ZM385.367 65.52c2.52 4.08 8.159 7.56 15.959 7.56 8.28 0 10.8-3.48 10.8-6.6 0-5.04-7.2-6.24-16.56-9.6-8.88-3.24-14.88-7.8-14.88-17.04 0-11.64 9.84-18.12 21.36-18.12 10.08 0 16.8 3.84 21 9.12l-8.039 8.52c-2.521-3-6.6-5.28-13.2-5.28-4.56 0-7.321 2.16-7.321 5.4 0 4.56 5.041 5.16 15.241 8.88 11.16 3.96 16.199 9.24 16.199 18 0 10.44-7.559 19.2-24.839 19.2-12.6 0-21.241-5.04-24.961-12.24l9.241-7.8ZM315.997 23.52h14.28v8.64c2.76-5.76 9.6-9.84 18.36-9.84 14.52 0 22.92 9.36 22.92 24.24V84h-14.4V48.6c0-8.16-4.68-13.44-12.84-13.44s-14.04 5.76-14.04 14.04V84h-14.28V23.52ZM242.806 53.76c0-18.12 14.64-32.04 33-32.04 18.24 0 33 13.92 33 32.04 0 18.12-14.76 32.04-33 32.04-18.36 0-33-13.92-33-32.04Zm14.28 0c0 10.68 8.04 18.96 18.72 18.96 10.56 0 18.72-8.28 18.72-18.96 0-10.68-8.16-18.96-18.72-18.96-10.68 0-18.72 8.28-18.72 18.96ZM183.387 53.64c0-18.48 14.64-32.04 32.88-32.04 9 0 17.28 3 24.24 10.44l-8.88 9.24c-4.08-4.2-8.88-6.6-15.36-6.6-10.56 0-18.6 8.04-18.6 18.96 0 10.92 8.04 18.96 18.6 18.96 6.48 0 11.28-2.4 15.36-6.6l8.88 9.24c-6.96 7.44-15.24 10.44-24.24 10.44-18.24 0-32.88-13.56-32.88-32.04Z"
+		/>
+	</svg>
+);
diff --git a/packages/react/src/components/shared/ui/switch/switch.module.css b/packages/react/src/components/shared/ui/switch/switch.module.css
index 4c45422b6..a8f4fbf7d 100644
--- a/packages/react/src/components/shared/ui/switch/switch.module.css
+++ b/packages/react/src/components/shared/ui/switch/switch.module.css
@@ -28,6 +28,10 @@
 	/* Shadows */
 	--switch-shadow-thumb: 0 0 0 1px hsl(0, 0%, 92.16%);
 	--switch-shadow-thumb-dark: 0 0 0 1px hsl(0, 0%, 20%);
+	--switch-focus-ring: hsl(228, 100%, 60%);
+	--switch-focus-ring-dark: hsl(228.07, 69.8%, 48.04%);
+	--switch-focus-shadow: 0 0 0 2px var(--switch-focus-ring);
+	--switch-focus-shadow-dark: 0 0 0 2px var(--switch-focus-ring-dark);
 }
 
 /* Root switch wrapper */
@@ -45,6 +49,7 @@
 	white-space: nowrap;
 	border: 0;
 	background: none;
+	border-radius: 9999px;
 }
 
 /* Switch track */
@@ -116,11 +121,12 @@
 }
 
 .root:focus {
-	outline: 2px solid var(--accordion-focus-ring);
+	outline: none;
 }
+
 /* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
 :global(.c15t-dark) .root:focus {
-	outline: 2px solid var(--accordion-focus-ring-dark);
+	outline: none;
 }
 
 .track-disabled {
@@ -209,3 +215,13 @@
 .root[data-state="checked"] .thumb-disabled {
 	transform: translateX(var(--switch-thumb-translate));
 }
+
+.root:focus-visible {
+	outline: none;
+	box-shadow: var(--switch-focus-shadow);
+}
+
+/* biome-ignore lint/nursery/noUnknownPseudoClass: <explanation> */
+:global(.c15t-dark) .root:focus-visible {
+	box-shadow: var(--switch-focus-shadow-dark);
+}


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 090dc0e2730e8d19dd6d67005ed0521ae360005f and 10a4154e64117f5ab8f0b1e16d529002dbbe9314.

</details>

<details>
<summary>📒 Files selected for processing (15)</summary>

* `packages/core/src/store.initial-state.ts` (1 hunks)
* `packages/core/src/store.ts` (2 hunks)
* `packages/core/src/store.type.ts` (1 hunks)
* `packages/dev-tools/src/components/header.tsx` (2 hunks)
* `packages/dev-tools/src/components/ui/logo.tsx` (1 hunks)
* `packages/react/src/components/consent-manager-dialog/atoms/dialog-card.tsx` (4 hunks)
* `packages/react/src/components/consent-manager-dialog/consent-manager-dialog.module.css` (2 hunks)
* `packages/react/src/components/consent-manager-dialog/consent-manager-dialog.tsx` (1 hunks)
* `packages/react/src/components/consent-manager-widget/consent-manager-widget.module.css` (3 hunks)
* `packages/react/src/components/consent-manager-widget/consent-manager-widget.tsx` (3 hunks)
* `packages/react/src/components/shared/ui/accordion/accordion.module.css` (4 hunks)
* `packages/react/src/components/shared/ui/button/button.module.css` (5 hunks)
* `packages/react/src/components/shared/ui/button/button.tsx` (1 hunks)
* `packages/react/src/components/shared/ui/logo.tsx` (2 hunks)
* `packages/react/src/components/shared/ui/switch/switch.module.css` (4 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (3)</summary>

<details>
<summary>packages/dev-tools/src/components/header.tsx (2)</summary><blockquote>

<details>
<summary>packages/dev-tools/src/components/ui/logo.tsx (1)</summary>

* `C15TIcon` (8-75)

</details>
<details>
<summary>packages/react/src/components/shared/ui/logo.tsx (1)</summary>

* `C15TIcon` (8-31)

</details>

</blockquote></details>
<details>
<summary>packages/dev-tools/src/components/ui/logo.tsx (1)</summary><blockquote>

<details>
<summary>packages/react/src/components/shared/ui/logo.tsx (1)</summary>

* `C15TIcon` (8-31)

</details>

</blockquote></details>
<details>
<summary>packages/react/src/components/shared/ui/logo.tsx (1)</summary><blockquote>

<details>
<summary>packages/dev-tools/src/components/ui/logo.tsx (1)</summary>

* `C15TIcon` (8-75)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Build and Test

</details>

<details>
<summary>🔇 Additional comments (46)</summary><blockquote>

<details>
<summary>packages/react/src/components/consent-manager-dialog/consent-manager-dialog.tsx (1)</summary>

`101-101`: **LGTM, clean change.**

The declaration of `dialogRef` looks good. Clean code without unnecessary comments improves readability.

</details>
<details>
<summary>packages/dev-tools/src/components/header.tsx (1)</summary>

`4-4`: **Branding component rename looks good**

Replacing `ConsentManagementIcon` with `C15TIcon` properly implements the domain-based branding approach mentioned in the PR objectives. This change aligns with the consolidation of branding components for better reusability.



Also applies to: 14-14

</details>
<details>
<summary>packages/core/src/store.type.ts (1)</summary>

`92-94`: <details>
<summary>✅ Verification successful</summary>

**Domain flag addition looks good**

Adding the `isConsentDomain` property to the state enables dynamic logo switching based on domains, which aligns perfectly with your PR objectives. The documentation is clear and the implementation is simple yet effective.


---

🏁 Script executed:

```shell
#!/bin/bash
# Verify if this new flag is being properly initialized in initial state

# Check if the isConsentDomain is properly initialized in the initial state
rg "isConsentDomain:" "packages/core/src/store.initial-state.ts"

# Check where the new property is being used
rg "isConsentDomain" --type typescript
```

Length of output: 161

---

**Verified: Domain Flag Implementation with Manual Usage Check Needed**

The `isConsentDomain` property in `packages/core/src/store.type.ts` (lines 92–94) is correctly added, and its initialization in `packages/core/src/store.initial-state.ts` has been confirmed (`isConsentDomain: false`). However, the original usage search using `--type typescript` produced an error. Please manually verify the flag’s usage across the codebase using an alternative search (e.g., `rg "isConsentDomain" -g "*.ts"`).

- **Affected file:** `packages/core/src/store.type.ts` (lines 92–94)
- **Initialization check:** `packages/core/src/store.initial-state.ts` confirms the flag is set to `false`
- **Next step:** Ensure that references to `isConsentDomain` across other TypeScript files are as expected.



```

---

🏁 Script executed:

```shell

#!/bin/bash
# Verify the initialization of isConsentDomain in the initial state file
echo "Checking initialization in packages/core/src/store.initial-state.ts:"
grep "isConsentDomain:" packages/core/src/store.initial-state.ts

# Search for all occurrences of isConsentDomain in TypeScript files within the repository
echo "Searching for usage across TypeScript files:"
rg "isConsentDomain" -g "*.ts"
```

Length of output: 891

---



</details>

**Domain flag addition verified and approved**

The `isConsentDomain` property is correctly defined in `packages/core/src/store.type.ts` (lines 92–94) and is properly initialized to `false` in `packages/core/src/store.initial-state.ts`. Additionally, a search across the repository confirms its usage in `packages/core/src/store.ts`. The implementation aligns with the PR objectives for dynamic logo switching based on domain, and no further modifications are necessary.

- **Affected files:**
  - `packages/core/src/store.type.ts` – Definition of `isConsentDomain`
  - `packages/core/src/store.initial-state.ts` – Initialization (`isConsentDomain: false`)
  - `packages/core/src/store.ts` – Verified usage

</details>
<details>
<summary>packages/core/src/store.initial-state.ts (1)</summary>

`68-69`: **Feature addition for domain-based branding.**

The addition of the `isConsentDomain` flag to the state enables dynamic logo switching based on domain, which aligns with the PR objective to implement domain-based branding. This is properly documented with a clear comment.

</details>
<details>
<summary>packages/dev-tools/src/components/ui/logo.tsx (2)</summary>

`3-6`: **Consistent component renaming from ConsentManagementIconProps to C15TIconProps.**

This renaming aligns with the PR's branding consolidation efforts and creates consistency across the codebase.

---

`8-12`: **Consistent component renaming from ConsentManagementIcon to C15TIcon.**

The component has been properly renamed while preserving its functionality, maintaining the same default values for accessibility attributes.

</details>
<details>
<summary>packages/react/src/components/shared/ui/logo.tsx (3)</summary>

`3-6`: **Consistent component renaming from ConsentManagementIconProps to C15TIconProps.**

This renaming aligns with the PR's branding consolidation efforts and matches the equivalent change in the dev-tools package.

---

`8-31`: **Updated C15TIcon component with appropriate defaults.**

The component has been properly renamed and has appropriate default values for the title and titleId props, enhancing accessibility.

---

`33-64`: **New ConsentLogo component for domain-based branding.**

The addition of the ConsentLogo component implements the domain-specific branding requirements from the PR objectives. It follows the same interface and accessibility patterns as the C15TIcon component.

A few minor observations:
1. Both components use `currentColor` for fills, supporting theming and dark mode.
2. Proper SVG accessibility attributes are maintained.
3. The `className="consent-logo"` will help with targeting this specific logo for styling.

</details>
<details>
<summary>packages/react/src/components/shared/ui/switch/switch.module.css (4)</summary>

`31-34`: **Great addition of focus state variables for accessibility!**

These new CSS variables for focus rings and shadows are excellent for improving keyboard navigation visibility. They provide a consistent approach to focus styling that can be used throughout the component.

---

`52-52`: **Ensuring consistent rounded appearance.**

Adding border-radius to the root element ensures the focus ring will follow the same rounded appearance as the switch itself, which creates a more polished visual design.

---

`123-130`: **Removing default outline to use custom focus styling.**

Removing the default outline is appropriate here since you're providing a custom focus indicator through box-shadow. This helps maintain your design system's visual consistency.

---

`219-227`: **Excellent implementation of focus-visible for better accessibility!**

Using `:focus-visible` instead of just `:focus` is a significant accessibility improvement. This ensures focus indicators appear only for keyboard navigation while not showing them during mouse clicks, providing a better user experience for both keyboard and mouse users.

</details>
<details>
<summary>packages/react/src/components/consent-manager-dialog/atoms/dialog-card.tsx (5)</summary>

`13-14`: **Good component refactoring for branding functionality.**

The import changes reflect the shift to a more modular approach, preparing for the dynamic logo switching based on domain.

---

`171-182`: **Improved DialogFooter component flexibility.**

The updated DialogFooter now accepts all BoxProps including an optional themeKey prop, making it more flexible and reusable across different contexts.

---

`187-213`: **Great implementation of domain-based dynamic branding!**

The new BrandingFooter component elegantly handles the domain-based logo switching and adds referral tracking. This implements the PR objective of dynamically switching between C15T and Consent logos based on the current hostname.

The inclusion of the referral parameter is a nice touch for tracking the source of traffic.

---

`234-239`: **Updated prop interface for ConsentCustomizationCard.**

The component now accepts an additional `useConsentLogo` prop, but I notice this prop is declared but not actually used in the component implementation.

Could you verify if the `useConsentLogo` prop is intentionally unused or if there's functionality that needs to be implemented to utilize this prop?

---

`259-261`: **Consolidated branding implementation.**

Using the new BrandingFooter component here centralizes the branding logic, improving reusability and consistency across the application.

</details>
<details>
<summary>packages/react/src/components/consent-manager-widget/consent-manager-widget.tsx (3)</summary>

`5-8`: **Good modularization of branding components.**

Importing the BrandingFooter from dialog-card allows for better code reuse and maintains consistency across different parts of the application.

---

`72-73`: **Added referral tracking.**

The referral parameter functionality is well-implemented, ensuring server-side rendering compatibility by checking for window object availability.

---

`99-101`: **Consolidated branding implementation.**

The widget now uses the same BrandingFooter component as the dialog, which implements consistent domain-based branding and referral tracking across components.

</details>
<details>
<summary>packages/react/src/components/consent-manager-widget/consent-manager-widget.module.css (3)</summary>

`57-59`: **Good addition of focus ring variables for accessibility.**

These new CSS variables ensure consistent focus styles across different themes and improve accessibility for keyboard users.

---

`260-262`: **Critical fix for focus state visibility.**

Changing from `overflow: hidden` to `overflow: visible` is essential for ensuring focus indicators remain visible. The added `:has()` selector elegantly applies focus styles to the parent container when the inner trigger receives focus, creating a more cohesive visual experience.



Also applies to: 264-267

---

`307-308`: **Positioning improvements for accordion trigger.**

Adding `position: relative` and `border-radius` to the accordion trigger inner element ensures proper styling of focus states and consistent rounded corners.

</details>
<details>
<summary>packages/react/src/components/shared/ui/accordion/accordion.module.css (10)</summary>

`27-29`: **New Focus Shadow Variables Added**  
The new variables `--accordion-focus-ring-dark`, `--accordion-focus-shadow`, and `--accordion-focus-shadow-dark` enhance consistency in focus styling. Please ensure these values align with your overall design specifications.

---

`47-47`: **Overflow Visibility for Accordion Items**  
Setting `overflow: visible` in the `.item` class ensures that any focus outlines or expanded content won’t be clipped. Verify that this change does not disrupt the layout in complex nesting scenarios.

---

`56-59`: **Adjusted Hover Selector for Open State**  
The selector `.item:is(:hover, [data-state="open"])` now excludes `:focus-within`, which simplifies the hover interaction. Ensure that this change still provides adequate feedback for keyboard users and does not affect accessibility.

---

`62-65`: **Dark Mode Hover State Update**  
The updated dark mode rule for `.item:is(:hover, [data-state="open"])` is consistent with the light theme changes. Please verify that interactive feedback remains clear in dark mode.

---

`67-71`: **New Focus Styles for Accordion Items**  
The added rule for `.item:focus-within:not(:has(.triggerInner:focus-visible))` provides a tailored background and box-shadow to indicate focus when the inner trigger isn’t focus-visible. Cross-browser testing is recommended to ensure consistent behavior across devices.

---

`73-77`: **Dark Mode Focus Styles for Items**  
The corresponding dark theme focus style delivers consistent feedback using `var(--accordion-background-hover-dark)`. Confirm that the contrast remains sufficient for accessibility.

---

`79-81`: **Enhanced Focus Feedback via Trigger Presence**  
The rule applying `box-shadow: var(--accordion-focus-shadow);` when `.item` contains a focus-visible `.triggerInner` strengthens the visual focus indication. Approved provided cross-browser tests validate its effectiveness.

---

`83-86`: **Dark Mode Focus Feedback for Triggered Items**  
The dark mode variant using `box-shadow: var(--accordion-focus-shadow-dark);` ensures that the focus feedback is thematically consistent. Double-check that the shadow contrast meets accessibility standards.

---

`115-117`: **Layout Enhancements for .triggerInner**  
Introducing `border-radius`, `position: relative`, and `z-index: 1` in `.triggerInner` aids with visual consistency and stacking order. Test these changes to confirm that no unintended overlap or layout issues occur.

---

`125-127`: **Focus Outline Removal on .triggerInner**  
Removing the default outline on `.triggerInner:focus-visible` improves aesthetics, but careful testing is needed to ensure that an accessible focus indicator is still provided elsewhere.

</details>
<details>
<summary>packages/react/src/components/shared/ui/button/button.module.css (6)</summary>

`17-20`: **New Focus Color Variables for Buttons**  
The introduction of `--button-focus-ring` and `--button-focus-ring-dark` brings improved flexibility and consistency for focus styling across button components. Confirm that these colors work harmoniously with your overall theme.

---

`51-54`: **Updated Focus Shadow Definitions**  
Updating the focus shadow variables to use the new focus ring values (for both primary and neutral buttons) increases clarity in focus states. This change is well aligned with the other focus enhancements in the project.

---

`91-96`: **Button Focus Style Enhancement**  
The new `:focus-visible` rule for `.button` removes the default outline in favor of a custom box-shadow. Ensure that the replacement focus indicator remains sufficiently prominent for keyboard users.

---

`97-101`: **Dark Mode Button Focus Styling**  
The dark mode focus style for `.button:focus-visible` provides consistent feedback in dark themes. Please verify the visual contrast to meet accessibility guidelines.

---

`143-146`: **Primary Filled Button Focus Enhancement**  
Applying `box-shadow: var(--button-shadow-primary-focus);` on `.button-primary-filled:focus-visible` maintains consistency with the base button rules. Ensure that this visual cue is distinct enough during user interaction.

---

`238-241`: **Neutral Filled Button Focus Enhancement**  
The focus-visible style for `.button-neutral-filled` now applies `box-shadow: var(--button-shadow-neutral-focus);`. This update aligns with the overall focus styling strategy. A quick cross-browser check is recommended.

</details>
<details>
<summary>packages/react/src/components/consent-manager-dialog/consent-manager-dialog.module.css (6)</summary>

`21-22`: **Updated Branding Focus Color Variables**  
The new variables `--dialog-branding-focus-color` and `--dialog-branding-focus-color-dark` (using HSL values) provide more flexibility and improved visual consistency for focus states in branding elements.

---

`97-111`: **Enhanced Branding Element Styling**  
The updated styling for the `.branding` class—adding `display: flex`, adjusting margins, border-radius, and padding—improves layout and alignment. Please ensure that these adjustments render correctly at various screen sizes.

---

`112-116`: **Branding Focus State Enhancement**  
The new `:focus-visible` state for `.branding` removes the default outline and applies a custom box-shadow using `--dialog-branding-focus-color`. Confirm that this focus indicator meets the contrast and accessibility requirements.

---

`118-121`: **Dark Mode Branding Focus State**  
Implementing a dark mode variant using `:global(.c15t-dark) .branding:focus-visible` ensures that focus feedback remains consistent under dark themes. Verify that the focus ring remains both visible and aesthetically pleasing.

---

`128-131`: **BrandingC15T Icon Sizing**  
The `.brandingC15T` class leverages CSS variables for icon dimensions, allowing dynamic sizing adjustments. Ensure that the icons remain crisp and aligned across all supported devices.

---

`132-135`: **BrandingConsent Icon Sizing**  
The `.brandingConsent` class sets a fixed height of 1rem, which may be appropriate for the consent logo. Confirm that this fixed dimension integrates well with surrounding text and layout elements.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T23:45:18Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>.github/workflows/ci.yml (2)</summary><blockquote>

`49-50`: **CI Build Command Update**

The build command has been updated from `pnpm turbo run build` to `pnpm turbo run build:libs`, which indicates the workflow is now focused on building libraries. Please verify that this change aligns with the project's build requirements and that no dependent processes expect a full build.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 50-50: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

---

`50-50`: **Ensure Proper File Termination**

The static analysis tool detected that there is no newline character at the end of the file. To conform to YAML best practices and avoid potential linting issues, please add a newline at the file's end.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 50-50: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 4002b88d869092d712f8c7b7a81e075bd3583a6d and c84ec36aabd1c03fc7b913055cfc59f1b42daf25.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/workflows/ci.yml` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>.github/workflows/ci.yml</summary>

[error] 50-50: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T00:12:28Z

Review comments:
diff_hunk: @@ -170,6 +170,7 @@ const ButtonRoot = forwardRef<HTMLButtonElement, ButtonRootProps>(
 			<Component
 				ref={forwardedRef}
 				className={root({ class: className })}
+				tabIndex={0}
path: packages/react/src/components/shared/ui/button/button.tsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Consider removing explicit tabIndex={0} prop**

Setting `tabIndex={0}` on this element is redundant for native button elements (which already have a default tab index of 0) and potentially problematic for accessibility. When using the Slot pattern with `asChild`, the tabIndex should be determined by the child component.

If you're trying to improve focus visibility, consider focusing on CSS styles for focus states rather than modifying tab order.

```diff
- tabIndex={0}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion

`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 4002b88
created_at: 2025-04-11T23:45:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -158,6 +158,13 @@ export const createConsentManagerStore = (
 ) => {
 	const { namespace = 'c15tStore', trackingBlockerConfig } = options;
 
+	// Check if the provider is using c15t.dev domain this means we are using consent
+	const isConsentDomain = true;
+	// if (manager && 'baseURL' in manager) {
+	// 	const baseURL = manager.baseURL as string;
+	// 	isConsentDomain = Boolean(baseURL?.includes('c15t.dev'));
+	// }
path: packages/core/src/store.ts
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>❓ Verification inconclusive</summary>

**Verify hardcoded value for domain detection.**

The PR objective mentions implementing domain-based branding that dynamically switches between logos based on the current hostname, but this change hardcodes `isConsentDomain` to `true` and comments out the dynamic hostname check. This may prevent the domain-based switching from working as intended.



Consider restoring the dynamic check to determine the domain:

```diff
-// Check if the provider is using c15t.dev domain this means we are using consent
-const isConsentDomain = true;
-// if (manager && 'baseURL' in manager) {
-// 	const baseURL = manager.baseURL as string;
-// 	isConsentDomain = Boolean(baseURL?.includes('c15t.dev'));
-// }
+// Check if the provider is using c15t.dev domain this means we are using consent
+let isConsentDomain = false;
+if (manager && 'baseURL' in manager) {
+	const baseURL = manager.baseURL as string;
+	isConsentDomain = Boolean(baseURL?.includes('c15t.dev'));
+}
```

Alternatively, clarify if this is intentional and if the domain-based switching is being implemented elsewhere.

---



</details>

```shell
#!/bin/bash
# Verify usage and references to dynamically determining the "c15t.dev" domain in the repository.
# The objective is to find if any dynamic checks using "manager && 'baseURL'" are retained elsewhere,
# or if all occurrences (like in packages/core/src/store.ts) are simply hardcoded.
rg "manager && 'baseURL'" .
```

**Critical: Dynamic Domain Detection Bypassed**

The implementation in `packages/core/src/store.ts` currently hardcodes `isConsentDomain` to `true`, which bypasses the intended dynamic check based on the `manager.baseURL`. This may prevent the expected domain-based branding (e.g., dynamically switching logos according to hostname) from functioning correctly. Please either restore the dynamic check as originally provided or clarify if the domain-based switching logic is implemented elsewhere in the codebase.

Suggested change:
```diff
-// Check if the provider is using c15t.dev domain this means we are using consent
-const isConsentDomain = true;
-// if (manager && 'baseURL' in manager) {
-// 	const baseURL = manager.baseURL as string;
-// 	isConsentDomain = Boolean(baseURL?.includes('c15t.dev'));
-// }
+// Check if the provider is using c15t.dev domain this means we are using consent
+let isConsentDomain = false;
+if (manager && 'baseURL' in manager) {
+	const baseURL = manager.baseURL as string;
+	isConsentDomain = Boolean(baseURL?.includes('c15t.dev'));
+}
```

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 4002b88
created_at: 2025-04-11T23:45:18Z
author_association: CONTRIBUTOR

PR comments:
user: login: vercel[bot]
created_at: 2025-04-11T23:40:58Z
body: [vc]: #MB84rjIeu9Lhe/zjd+PgebLiT3bw2cajviQflKn+VOk=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJjMTV0IiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImMxNXQtZ2l0LWFjY2VzYWJpbGl0eS1maXhlcy1jMTV0LnZlcmNlbC5hcHAifSwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2MxNXQvYzE1dC9YSkFiazJHb0pqRHpyTG01Ykp3M2RWZVoxU3ZqIiwicHJldmlld1VybCI6ImMxNXQtZ2l0LWFjY2VzYWJpbGl0eS1maXhlcy1jMTV0LnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJyb290RGlyZWN0b3J5IjoiZG9jcyJ9XX0=
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **c15t** | ✅ Ready ([Inspect](https://vercel.com/c15t/c15t/XJAbk2GoJjDzrLm5bJw3dVeZ1Svj)) | [Visit Preview](https://c15t-git-accesability-fixes-c15t.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/c15t-git-accesability-fixes-c15t.vercel.app?via=pr-comment-feedback-link) | Apr 12, 2025 0:15am |


author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-04-11T23:41:01Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: failure by coderabbit.ai -->

> [!CAUTION]
> ## Review failed
> 
> The pull request is closed.

<!-- end of auto-generated comment: failure by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
The pull request adds a new boolean property, `isConsentDomain`, to the consent management store state and associated type definitions, and adjusts the store’s initialization logic to derive its value from the `manager.baseURL`. Icon components and their props have been renamed from “ConsentManagementIcon” to “C15TIcon,” with an additional `ConsentLogo` introduced. The branding display in dialog and widget components is refactored to be dynamic via new components such as `BrandingFooter`. Several CSS files are updated with new focus ring variables and improved styling for accessibility.

## Changes

| Files | Change Summary |
|-------|----------------|
| `packages/core/src/store.initial-state.ts`<br>`packages/core/src/store.ts`<br>`packages/core/src/store.type.ts` | Added new `isConsentDomain` property, updated store initialization to check `manager.baseURL`, and updated the consent state interface. |
| `packages/dev-tools/src/components/header.tsx`<br>`packages/dev-tools/src/components/ui/logo.tsx`<br>`packages/react/src/components/shared/ui/logo.tsx` | Renamed icon components and interfaces from `ConsentManagementIcon`/`ConsentManagementIconProps` to `C15TIcon`/`C15TIconProps` and introduced a new `ConsentLogo` component. |
| `packages/react/src/components/consent-manager-dialog/atoms/dialog-card.tsx`<br>`packages/react/src/components/consent-manager-widget/consent-manager-widget.tsx` | Introduced new `BrandingFooter` component, updated dialog footer and widget branding logic, and added a new `refParam` in the widget. |
| `packages/react/src/components/consent-manager-dialog/consent-manager-dialog.module.css`<br>`packages/react/src/components/consent-manager-widget/consent-manager-widget.module.css`<br>`packages/react/src/components/shared/ui/accordion/accordion.module.css`<br>`packages/react/src/components/shared/ui/button/button.module.css`<br>`packages/react/src/components/shared/ui/switch/switch.module.css` | Updated and added new CSS variables and focus styles for branding, accordion, button, and switch components to enhance accessibility and visual feedback. |
| `packages/react/src/components/consent-manager-dialog/consent-manager-dialog.tsx` | Removed an obsolete comment from the `dialogRef` declaration. |
| `.github/workflows/ci.yml` | Updated CI workflow command to focus on building libraries. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Manager as Manager Object
    participant Store as Consent Store
    Manager->>Store: createConsentManagerStore(manager)
    alt baseURL contains "c15t.dev"
         Store->>Store: Set isConsentDomain = true
    else
         Store->>Store: Set isConsentDomain = false
    end
```

```mermaid
sequenceDiagram
    participant Widget as ConsentManagerWidget
    participant Hook as useConsentManager
    participant Dialog as DialogFooter
    participant Branding as BrandingFooter

    Widget ->> Hook: Retrieve isConsentDomain
    Hook -->> Widget: Return isConsentDomain
    Widget ->> Dialog: Render with isConsentDomain
    alt isConsentDomain true
        Branding ->> Dialog: Render C15TIcon branding
    else
        Branding ->> Dialog: Render ConsentLogo branding
    end
```

## Assessment against linked issues

| Objective                            | Addressed | Explanation       |
|--------------------------------------|:---------:|-------------------|
| Fix accessibility focus ring (#142) | ✅        |                   |

## Poem
> I'm a rabbit on the run,  
> Hopping through code under the sun.  
> Focus rings now shine so bright,  
> Icons renamed to keep things light.  
> In CodeRabbit’s land, our work’s fun and done!

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between c84ec36aabd1c03fc7b913055cfc59f1b42daf25 and f419b0b36434dc074c8e779003d38417bfbac0ef.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/workflows/ci.yml` (1 hunks)

</details>

</details>
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=c15t/c15t&utm_content=148):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-11T23:41:11Z
body: Thank you for following the naming conventions for pull request titles! 🙏
<!-- Sticky Pull Request Commentpr-title-lint-error -->
author_association: CONTRIBUTOR