cookiecraft 1.0.7 → 1.0.8

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.
package/README.md CHANGED
@@ -1,86 +1,73 @@
1
1
  # CookieCraft
2
2
 
3
- 🍪 **Lightweight GDPR-compliant cookie consent library for any website**
3
+ [![npm version](https://img.shields.io/npm/v/cookiecraft.svg)](https://www.npmjs.com/package/cookiecraft)
4
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/cookiecraft)](https://bundlephobia.com/package/cookiecraft)
5
+ [![license](https://img.shields.io/npm/l/cookiecraft.svg)](https://github.com/Fz3dev/cookiecraft/blob/main/LICENSE)
4
6
 
5
- Open-source cookie consent library with modern UI, full RGPD compliance, and Google Consent Mode v2 support. Perfect for Webflow, WordPress, Shopify, or any website.
7
+ **Lightweight GDPR-compliant cookie consent library for any website.**
8
+
9
+ Zero dependencies. Modern UI. Google Consent Mode v2 built-in. Works on Webflow, WordPress, Shopify, or any site.
10
+
11
+ [Live Configurator](https://fz3dev.github.io/cookiecraft/settings.html) | [Demo](https://fz3dev.github.io/cookiecraft/)
6
12
 
7
13
  ## Features
8
14
 
9
- - **GDPR Compliant** - Full opt-in, cookie blocking before consent
10
- - 🎨 **Modern UI** - Beautiful, professional design
11
- - **Lightweight** - < 15KB total (JS + CSS minified)
12
- - 🚀 **Zero Dependencies** - Pure Vanilla JavaScript
13
- - 🎯 **Universal** - Works on any website (Webflow, WordPress, Shopify, custom sites)
14
- - 📱 **Responsive** - Mobile-first design
15
- - **Accessible** - WCAG 2.2 AA compliant
16
- - 🔌 **GTM Ready** - Google Consent Mode v2 built-in
17
- - 🎨 **Customizable** - CSS variables for easy theming
18
- - 🌐 **i18n Ready** - Multi-language support
15
+ - **GDPR Compliant** Full opt-in mode, script blocking before consent, cookie purge on rejection
16
+ - **Lightweight** < 15KB total (JS + CSS), zero runtime dependencies
17
+ - **Modern UI** Clean design, dark/light/auto themes, smooth animations
18
+ - **GTM Ready** — Google Consent Mode v2 built-in (ad_storage, analytics_storage, etc.)
19
+ - **Accessible** WCAG 2.2 AA, focus trapping, keyboard navigation, ARIA attributes
20
+ - **Customizable** Primary color, layouts, positions, translations, CSS variables
21
+ - **Universal** Works on any website via CDN (Webflow, WordPress, Shopify, custom)
22
+ - **Script Blocking** Prevents tracking scripts from firing before consent
23
+ - **Floating Widget** Persistent button for users to update preferences anytime
24
+ - **Visual Configurator** — No-code setup tool that generates ready-to-paste code
19
25
 
20
26
  ## Quick Start
21
27
 
22
- ### For Webflow
23
-
24
- Add this code in **Site Settings > Custom Code > Footer**:
28
+ Add this before `</body>` on your site:
25
29
 
26
30
  ```html
27
- <!-- CSS -->
28
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cookiecraft@1/dist/cookiecraft.min.css">
29
-
30
- <!-- JavaScript -->
31
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cookiecraft@1/dist/cookiecraft.css">
31
32
  <script src="https://cdn.jsdelivr.net/npm/cookiecraft@1/dist/cookiecraft.min.js"></script>
32
33
 
33
- <!-- Initialize -->
34
34
  <script>
35
- const cookieConsent = new CookieCraft.CookieConsent({
36
- mode: 'opt-in',
37
- autoShow: true,
38
- revision: 1,
39
-
40
- categories: {
41
- necessary: {
42
- enabled: true,
43
- readOnly: true,
44
- label: 'Essentiels',
45
- description: 'Nécessaires au bon fonctionnement du site'
46
- },
47
- analytics: {
48
- enabled: false,
49
- readOnly: false,
50
- label: 'Statistiques',
51
- description: 'Pour comprendre comment vous utilisez notre site'
52
- },
53
- marketing: {
54
- enabled: false,
55
- readOnly: false,
56
- label: 'Marketing',
57
- description: 'Pour vous proposer du contenu personnalisé'
58
- }
59
- },
60
-
61
- theme: 'auto',
62
- primaryColor: '#0066cc'
63
- });
64
-
65
- cookieConsent.init();
35
+ new CookieCraft.CookieConsent({
36
+ primaryColor: '#0066cc',
37
+ categories: {
38
+ necessary: { enabled: true, readOnly: true, label: 'Essential', description: 'Required for the website to function.' },
39
+ analytics: { enabled: true, readOnly: false, label: 'Analytics', description: 'Help us understand how you use our site.' },
40
+ marketing: { enabled: true, readOnly: false, label: 'Marketing', description: 'Used to deliver relevant ads.' }
41
+ },
42
+ translations: {
43
+ title: 'Your privacy matters',
44
+ description: 'We use cookies to improve your experience. You choose which ones you accept.'
45
+ }
46
+ }).init();
66
47
  </script>
67
48
  ```
68
49
 
69
- ### Block Third-Party Scripts
50
+ Or use the **[Visual Configurator](https://fz3dev.github.io/cookiecraft/settings.html)** to generate your code without writing anything.
51
+
52
+ ### Platform-specific instructions
53
+
54
+ **Webflow** — Paste in Site Settings > Custom Code > Footer Code.
55
+
56
+ **WordPress** — Paste in your theme's `footer.php` before `</body>`, or use a "Insert Headers and Footers" plugin.
70
57
 
71
- Change your tracking scripts to use `type="text/plain"` and `data-cookieconsent` attribute:
58
+ **Shopify** Paste in Online Store > Themes > Edit Code > `theme.liquid` before `</body>`.
59
+
60
+ ## Script Blocking
61
+
62
+ Change tracking scripts to `type="text/plain"` with a `data-cookieconsent` attribute. CookieCraft blocks them until the user consents:
72
63
 
73
64
  ```html
74
- <!-- Google Analytics - Blocked until analytics consent -->
75
- <script type="text/plain" data-cookieconsent="analytics">
76
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;...})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
77
- ga('create', 'UA-XXXXX-Y', 'auto');
78
- ga('send', 'pageview');
79
- </script>
65
+ <!-- Google Analytics blocked until analytics consent -->
66
+ <script type="text/plain" data-cookieconsent="analytics"
67
+ src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXX"></script>
80
68
 
81
- <!-- Facebook Pixel - Blocked until marketing consent -->
69
+ <!-- Facebook Pixel blocked until marketing consent -->
82
70
  <script type="text/plain" data-cookieconsent="marketing">
83
- !function(f,b,e,v,n,t,s){...}
84
71
  fbq('init', 'YOUR_PIXEL_ID');
85
72
  fbq('track', 'PageView');
86
73
  </script>
@@ -88,160 +75,56 @@ Change your tracking scripts to use `type="text/plain"` and `data-cookieconsent`
88
75
 
89
76
  ## Layout Options
90
77
 
91
- Choose from multiple banner styles and positions to match your site's design:
92
-
93
78
  ### Banner Layouts
94
79
 
95
- - **`bar`** (default) - Full-width banner at top or bottom
96
- - **`box`** - Compact modal in corner or center
97
- - **`floating`** - Small notification-style banner
80
+ | Layout | Description |
81
+ |---|---|
82
+ | `bar` | Full-width banner at top or bottom |
83
+ | `box` | Compact modal in corner or center |
84
+ | `floating` | Small notification-style banner |
98
85
 
99
- ### Banner Positions
86
+ ### Positions
100
87
 
101
- - **`bottom`** (default) - Bottom of the screen
102
- - **`top`** - Top of the screen
103
- - **`center`** - Centered modal with overlay
104
- - **`bottom-left`** - Bottom left corner
105
- - **`bottom-right`** - Bottom right corner
88
+ `bottom` (default), `top`, `center`, `bottom-left`, `bottom-right`
106
89
 
107
90
  ### Floating Widget
108
91
 
109
- A permanent button that stays visible after consent, allowing users to modify preferences anytime:
92
+ A permanent button that stays visible after consent, letting users modify preferences:
110
93
 
111
- - **`showWidget`** (default: `true`) - Show/hide the floating widget
112
- - **`widgetPosition`** (default: `'bottom-right'`) - Widget position: `'bottom-left'`, `'bottom-right'`, `'top-left'`, `'top-right'`
94
+ ```javascript
95
+ new CookieCraft.CookieConsent({
96
+ showWidget: true, // default: true
97
+ widgetPosition: 'bottom-left', // default: 'bottom-left'
98
+ widgetStyle: 'compact', // 'compact' or 'full'
99
+ });
100
+ ```
113
101
 
114
102
  ### Examples
115
103
 
116
104
  ```javascript
117
105
  // Full-width bar at bottom (classic)
118
- const consent = new CookieCraft.CookieConsent({
119
- layout: 'bar',
120
- position: 'bottom',
121
- showWidget: true,
122
- widgetPosition: 'bottom-right'
123
- });
106
+ new CookieCraft.CookieConsent({ layout: 'bar', position: 'bottom' }).init();
124
107
 
125
- // Small modal in bottom-right corner (modern)
126
- const consent = new CookieCraft.CookieConsent({
127
- layout: 'box',
128
- position: 'bottom-right',
129
- showWidget: true,
130
- widgetPosition: 'bottom-left' // Widget on opposite side
131
- });
132
-
133
- // Compact floating notification (minimal)
134
- const consent = new CookieCraft.CookieConsent({
135
- layout: 'floating',
136
- position: 'bottom-right',
137
- showWidget: false // No widget needed, already compact
138
- });
108
+ // Compact box in bottom-right (modern)
109
+ new CookieCraft.CookieConsent({ layout: 'box', position: 'bottom-right' }).init();
139
110
 
140
111
  // Centered modal with overlay (maximum attention)
141
- const consent = new CookieCraft.CookieConsent({
112
+ new CookieCraft.CookieConsent({
142
113
  layout: 'box',
143
114
  position: 'center',
144
- disablePageInteraction: true, // Block page until choice
145
- showWidget: true
146
- });
115
+ disablePageInteraction: true
116
+ }).init();
147
117
  ```
148
118
 
149
- ## Configuration
119
+ ## GTM Consent Mode v2
150
120
 
151
- ### Basic Options
152
-
153
- ```typescript
154
- interface ConsentConfig {
155
- // Core settings
156
- mode: 'opt-in' | 'opt-out'; // GDPR requires 'opt-in'
157
- autoShow: boolean; // Show banner on first visit
158
- revision: number; // Policy version (increment to re-ask)
159
-
160
- // Categories
161
- categories: {
162
- necessary: CategoryConfig;
163
- analytics: CategoryConfig;
164
- marketing: CategoryConfig;
165
- preferences?: CategoryConfig;
166
- };
167
-
168
- // UI customization
169
- theme?: 'light' | 'dark' | 'auto';
170
- layout?: 'bar' | 'box' | 'floating'; // Banner layout style
171
- position?: 'bottom' | 'top' | 'center' | 'bottom-left' | 'bottom-right';
172
- primaryColor?: string; // Hex color
173
- backdropBlur?: boolean; // Backdrop blur effect
174
- animationStyle?: 'smooth' | 'minimal';
175
-
176
- // Floating widget
177
- showWidget?: boolean; // Show permanent settings button
178
- widgetPosition?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
179
-
180
- // Content
181
- translations?: Translation;
182
-
183
- // Integration
184
- gtmConsentMode?: boolean; // Enable GTM Consent Mode v2
185
-
186
- // Accessibility
187
- disablePageInteraction?: boolean; // Block page until consent
188
-
189
- // Callbacks
190
- onAccept?: (categories) => void;
191
- onChange?: (categories) => void;
192
- onReject?: () => void;
193
- }
194
- ```
195
-
196
- ### Category Configuration
197
-
198
- ```typescript
199
- interface CategoryConfig {
200
- enabled: boolean; // Default state
201
- readOnly: boolean; // If true, user cannot toggle
202
- label: string; // Display name
203
- description: string; // Explanation
204
- }
205
- ```
206
-
207
- ### Customization Examples
208
-
209
- #### Custom Colors
210
-
211
- ```javascript
212
- const cookieConsent = new CookieCraft.CookieConsent({
213
- primaryColor: '#ff6b6b', // Red theme
214
- theme: 'dark',
215
- // ...
216
- });
217
- ```
218
-
219
- #### Custom Text
220
-
221
- ```javascript
222
- const cookieConsent = new CookieCraft.CookieConsent({
223
- translations: {
224
- title: 'Nous respectons votre vie privée',
225
- description: 'Choisissez les cookies que vous acceptez',
226
- acceptAll: 'Tout accepter',
227
- rejectAll: 'Tout refuser',
228
- customize: 'Personnaliser',
229
- savePreferences: 'Enregistrer',
230
- cookieSettings: 'Paramètres cookies', // Floating widget tooltip
231
- cookies: 'Cookies', // Floating widget text
232
- },
233
- // ...
234
- });
235
- ```
236
-
237
- #### With GTM Consent Mode v2
121
+ CookieCraft natively supports Google Consent Mode v2. Just enable it:
238
122
 
239
123
  ```html
240
- <!-- In HEAD, BEFORE GTM -->
124
+ <!-- In HEAD, before GTM -->
241
125
  <script>
242
126
  window.dataLayer = window.dataLayer || [];
243
127
  function gtag(){dataLayer.push(arguments);}
244
-
245
128
  gtag('consent', 'default', {
246
129
  'ad_storage': 'denied',
247
130
  'analytics_storage': 'denied',
@@ -253,166 +136,150 @@ const cookieConsent = new CookieCraft.CookieConsent({
253
136
  <!-- Google Tag Manager -->
254
137
  <script>(function(w,d,s,l,i){...})(window,document,'script','dataLayer','GTM-XXXX');</script>
255
138
 
256
- <!-- In FOOTER -->
139
+ <!-- In FOOTER, with CookieCraft -->
257
140
  <script>
258
- const cookieConsent = new CookieCraft.CookieConsent({
259
- gtmConsentMode: true, // Enable GTM integration
260
- // ...
261
- });
262
- cookieConsent.init();
141
+ new CookieCraft.CookieConsent({
142
+ gtmConsentMode: true,
143
+ // ...
144
+ }).init();
263
145
  </script>
264
146
  ```
265
147
 
266
- ## API
148
+ CookieCraft automatically maps categories to GTM signals:
267
149
 
268
- ### Methods
150
+ | Category | GTM Signals |
151
+ |---|---|
152
+ | `marketing` | `ad_storage`, `ad_user_data`, `ad_personalization` |
153
+ | `analytics` | `analytics_storage` |
154
+ | `preferences` | `functionality_storage`, `personalization_storage` |
269
155
 
270
- ```javascript
271
- // Initialize
272
- cookieConsent.init();
156
+ ## Configuration
273
157
 
274
- // Show banner
275
- cookieConsent.show();
158
+ ```typescript
159
+ interface ConsentConfig {
160
+ // Core
161
+ mode?: 'opt-in' | 'opt-out'; // default: 'opt-in'
162
+ autoShow?: boolean; // default: true
163
+ revision?: number; // increment to re-ask consent
276
164
 
277
- // Hide banner
278
- cookieConsent.hide();
165
+ // Categories
166
+ categories?: Record<string, {
167
+ enabled: boolean;
168
+ readOnly: boolean;
169
+ label: string;
170
+ description: string;
171
+ }>;
172
+
173
+ // Appearance
174
+ theme?: 'light' | 'dark' | 'auto'; // default: 'light'
175
+ layout?: 'bar' | 'box' | 'floating'; // default: 'box'
176
+ position?: string; // default: 'bottom-left'
177
+ primaryColor?: string; // hex color
178
+ backdropBlur?: boolean;
179
+ animationStyle?: 'smooth' | 'minimal';
279
180
 
280
- // Show preferences modal
281
- cookieConsent.showPreferences();
181
+ // Widget
182
+ showWidget?: boolean; // default: true
183
+ widgetPosition?: string; // default: 'bottom-left'
184
+ widgetStyle?: 'compact' | 'full'; // default: 'compact'
282
185
 
283
- // Get current consent
284
- const consent = cookieConsent.getConsent();
285
- // Returns: { version, timestamp, categories, expiresAt }
186
+ // Content
187
+ translations?: Translation;
286
188
 
287
- // Reset (clear and re-show)
288
- cookieConsent.reset();
189
+ // GTM
190
+ gtmConsentMode?: boolean; // default: false
289
191
 
290
- // Event listeners
291
- cookieConsent.on('consent:accept', (categories) => {
292
- console.log('Accepted:', categories);
293
- });
192
+ // Accessibility
193
+ disablePageInteraction?: boolean; // default: false
294
194
 
295
- cookieConsent.on('consent:update', (categories) => {
296
- console.log('Updated:', categories);
297
- });
195
+ // Callbacks
196
+ onAccept?: (categories) => void;
197
+ onChange?: (categories) => void;
198
+ onReject?: () => void;
199
+ }
298
200
  ```
299
201
 
300
- ### Events
301
-
302
- - `consent:init` - Library initialized
303
- - `consent:show` - Banner shown
304
- - `consent:accept` - All accepted
305
- - `consent:reject` - All rejected
306
- - `consent:update` - Consent changed
307
- - `consent:load` - Stored consent loaded
308
- - `preferences:show` - Preferences modal shown
309
- - `script:activated` - Script unblocked
310
-
311
- ### Cookie Settings Access
312
-
313
- #### Option 1: Floating Widget (Automatic)
314
-
315
- The library automatically shows a permanent floating button after consent (enabled by default):
202
+ ## API
316
203
 
317
204
  ```javascript
318
- const cookieConsent = new CookieCraft.CookieConsent({
319
- showWidget: true, // Show floating widget (default)
320
- widgetPosition: 'bottom-right', // Position
321
- // ...
322
- });
205
+ const cc = new CookieCraft.CookieConsent({ /* config */ });
206
+
207
+ cc.init(); // Initialize and show banner if needed
208
+ cc.show(); // Show banner manually
209
+ cc.hide(); // Hide banner
210
+ cc.showPreferences(); // Open preferences modal
211
+ cc.getConsent(); // Get current consent record
212
+ cc.reset(); // Clear consent and re-show banner
213
+ cc.destroy(); // Remove all UI elements
214
+
215
+ // Events
216
+ cc.on('consent:accept', (categories) => { /* ... */ });
217
+ cc.on('consent:reject', (categories) => { /* ... */ });
218
+ cc.on('consent:update', (categories) => { /* ... */ });
219
+ cc.on('preferences:show', () => { /* ... */ });
220
+ cc.on('script:activated', (script) => { /* ... */ });
323
221
  ```
324
222
 
325
- #### Option 2: Custom Button (Manual)
223
+ ### All Events
326
224
 
327
- In Webflow Designer, add your own button and connect it:
328
-
329
- ```html
330
- <script>
331
- document.getElementById('cookie-settings')?.addEventListener('click', () => {
332
- window.cookieConsent?.showPreferences();
333
- });
334
- </script>
335
- ```
225
+ | Event | Payload | Description |
226
+ |---|---|---|
227
+ | `consent:init` | — | Library initialized |
228
+ | `consent:show` | — | Banner shown |
229
+ | `consent:accept` | `categories` | User accepted all |
230
+ | `consent:reject` | `categories` | User rejected non-essential |
231
+ | `consent:update` | `categories` | Consent changed via preferences |
232
+ | `consent:load` | `record` | Stored consent loaded |
233
+ | `preferences:show` | — | Preferences modal opened |
234
+ | `preferences:hide` | — | Preferences modal closed |
235
+ | `script:activated` | `element` | Blocked script re-enabled |
336
236
 
337
237
  ## Styling
338
238
 
339
- ### CSS Variables
340
-
341
- Customize appearance using CSS variables:
239
+ Override any style with CSS variables:
342
240
 
343
241
  ```css
344
242
  :root {
345
- /* Colors */
346
243
  --cc-primary: #0066cc;
347
244
  --cc-bg: #ffffff;
348
245
  --cc-text: #1a1a1a;
349
246
  --cc-text-secondary: #666666;
350
-
351
- /* Spacing */
352
247
  --cc-padding: 1.5rem;
353
248
  --cc-gap: 0.75rem;
354
-
355
- /* Borders */
356
249
  --cc-border-radius: 12px;
357
250
  --cc-shadow: 0 -4px 24px rgba(0, 0, 0, 0.12);
358
-
359
- /* Animations */
360
251
  --cc-transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
361
252
  }
362
253
  ```
363
254
 
364
255
  ## Browser Support
365
256
 
366
- - Chrome/Edge (last 2 versions)
367
- - Firefox (last 2 versions)
368
- - Safari (last 2 versions)
369
- - iOS Safari (last 2 versions)
370
- - Chrome Android (last 2 versions)
371
-
372
- ## Development
373
-
374
- ```bash
375
- # Install dependencies
376
- npm install
377
-
378
- # Dev mode with watch
379
- npm run dev
257
+ Chrome, Edge, Firefox, Safari (last 2 versions), iOS Safari, Chrome Android.
380
258
 
381
- # Build
382
- npm run build
259
+ ## Why CookieCraft?
383
260
 
384
- # Run tests
385
- npm test
261
+ | | CookieCraft | Cookiebot | OneTrust |
262
+ |---|---|---|---|
263
+ | **Price** | Free | From 12/mo | From 200/mo |
264
+ | **Size** | ~15KB | ~100KB+ | ~150KB+ |
265
+ | **Dependencies** | 0 | Multiple | Multiple |
266
+ | **Self-hosted** | Yes | No | No |
267
+ | **GTM Consent Mode v2** | Yes | Yes | Yes |
268
+ | **Visual Configurator** | Yes | Dashboard | Dashboard |
269
+ | **Open Source** | MIT | No | No |
386
270
 
387
- # Type check
388
- npm run type-check
271
+ ## Development
389
272
 
390
- # Check bundle size
391
- npm run size
273
+ ```bash
274
+ npm install # Install dependencies
275
+ npm run dev # Watch mode
276
+ npm run build # Production build
277
+ npm test # Run tests
278
+ npm run lint # Lint
279
+ npm run type-check # TypeScript check
280
+ npm run size # Bundle size check
392
281
  ```
393
282
 
394
- ## Why This Library?
395
-
396
- ### vs Premium Solutions
397
-
398
- - **Cost**: Free vs €39+/month
399
- - **Performance**: 10-15KB vs 50-100KB+
400
- - **Privacy**: Self-hosted option vs SaaS only
401
- - **Flexibility**: Full code access vs black box
402
-
403
- ## Contributing
404
-
405
- Contributions are welcome! Please feel free to submit a Pull Request.
406
-
407
283
  ## License
408
284
 
409
- MIT © 2026
410
-
411
- ## Credits
412
-
413
- Inspired by:
414
- - [vanilla-cookieconsent](https://github.com/orestbida/cookieconsent) - Technical patterns
415
-
416
- ---
417
-
418
- Made with ❤️ for the open web
285
+ MIT
@@ -1 +1 @@
1
- .cc-banner,.cc-modal,.cc-widget{--cc-primary:#1a1a1a;--cc-primary-hover:#333;--cc-primary-glow:color-mix(in srgb,var(--cc-primary) 30%,transparent);--cc-bg:#fff;--cc-text:#1a1a1a;--cc-text-secondary:#666;--cc-border:#e5e7eb;--cc-overlay:rgba(0,0,0,.4);--cc-padding:1.125rem;--cc-gap:0.5rem;--cc-border-radius:12px;--cc-shadow:0 -4px 24px rgba(0,0,0,.12);--cc-transition:0.3s cubic-bezier(0.4,0,0.2,1);--cc-backdrop-blur:10px;--cc-font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}.cc-banner *,.cc-modal *,.cc-widget *{box-sizing:border-box;margin:0;padding:0}.cc-banner{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:var(--cc-bg);bottom:0;box-shadow:var(--cc-shadow);font-family:var(--cc-font-family);left:0;padding:var(--cc-padding);position:fixed;right:0;transform:translateY(100%);transition:transform var(--cc-transition);z-index:9999}.cc-banner.cc-backdrop-blur{backdrop-filter:blur(var(--cc-backdrop-blur));background:hsla(0,0%,100%,.95)}.cc-banner.is-visible{transform:translateY(0)}.cc-banner__container{margin:0 auto;max-width:1200px}.cc-banner__content{margin-bottom:1rem}.cc-banner__title{color:var(--cc-text);font-size:.9375rem;font-weight:600;letter-spacing:-.01em;line-height:1.3;margin:0 0 .375rem}.cc-banner__description{color:var(--cc-text-secondary);font-size:.8125rem;line-height:1.5;margin:0}.cc-banner__description a{color:var(--cc-primary);font-weight:500;text-decoration:none;transition:all .2s ease}.cc-banner__description a:hover{color:var(--cc-primary-hover);text-decoration:underline}.cc-banner__actions{display:flex;flex-wrap:wrap;gap:var(--cc-gap)}.cc-btn{align-items:center;border:none;border-radius:8px;cursor:pointer;display:inline-flex;font-family:inherit;font-size:.8125rem;font-weight:500;justify-content:center;letter-spacing:-.01em;min-height:36px;min-width:36px;padding:.5rem 1.125rem;text-decoration:none;transition:all .2s ease}.cc-btn:focus-visible{outline:3px solid var(--cc-primary);outline-offset:2px}.cc-btn:disabled{cursor:not-allowed;opacity:.6}.cc-btn--accept{background:var(--cc-primary);color:#fff}.cc-btn--accept:hover:not(:disabled){background:var(--cc-primary-hover);box-shadow:0 4px 12px var(--cc-primary-glow);transform:translateY(-1px)}.cc-btn--accept:active:not(:disabled){transform:translateY(0)}.cc-btn--ghost{background:transparent;color:var(--cc-text-secondary);font-size:.75rem;padding:.5rem .75rem}.cc-btn--ghost:hover:not(:disabled){color:var(--cc-text);text-decoration:underline}.cc-btn--ghost:active:not(:disabled){transform:translateY(0)}.cc-btn--primary{background:var(--cc-primary);color:#fff}.cc-btn--primary:hover:not(:disabled){background:var(--cc-primary-hover);box-shadow:0 4px 12px var(--cc-primary-glow);transform:translateY(-1px)}.cc-btn--primary:active:not(:disabled){transform:translateY(0)}.cc-btn--secondary{background:#f3f4f6;color:var(--cc-text)}.cc-btn--secondary:hover:not(:disabled){background:#e5e7eb;transform:translateY(-1px)}.cc-btn--secondary:active:not(:disabled){transform:translateY(0)}.cc-btn--tertiary{background:transparent;border:1px solid var(--cc-border);color:var(--cc-text-secondary)}.cc-btn--tertiary:hover:not(:disabled){background:rgba(0,0,0,.03);color:var(--cc-text);transform:translateY(-1px)}.cc-btn--tertiary:active:not(:disabled){transform:translateY(0)}@media (min-width:768px){.cc-banner--bar .cc-banner__container{align-items:center;display:flex;gap:2rem;justify-content:space-between}.cc-banner--bar .cc-banner__content{flex:1;margin-bottom:0}.cc-banner--bar .cc-banner__actions{flex-shrink:0}}.cc-banner--top{bottom:auto;box-shadow:0 4px 24px rgba(0,0,0,.12);top:0;transform:translateY(-100%)}.cc-banner--top.is-visible{transform:translateY(0)}.cc-banner--center{border-radius:var(--cc-border-radius);bottom:auto;left:50%;max-width:600px;opacity:0;right:auto;top:50%;transform:translate(-50%,-50%) scale(.9)}.cc-banner--center.is-visible{opacity:1;transform:translate(-50%,-50%) scale(1)}.cc-banner--bottom-right{border-radius:var(--cc-border-radius);bottom:1.5rem;left:auto;max-width:420px;right:1.5rem;transform:translateX(calc(100% + 2rem))}.cc-banner--bottom-right.is-visible{transform:translateX(0)}.cc-banner--bottom-left{border-radius:var(--cc-border-radius);bottom:1.5rem;left:1.5rem;max-width:420px;right:auto;transform:translateX(calc(-100% - 2rem))}.cc-banner--bottom-left.is-visible{transform:translateX(0)}.cc-banner--box{border-radius:var(--cc-border-radius);max-width:420px}.cc-banner--box .cc-banner__container{display:block}.cc-banner--box .cc-banner__actions{flex-direction:column;margin-top:1rem}.cc-banner--box .cc-banner__actions .cc-btn{width:100%}.cc-banner--floating{border-radius:var(--cc-border-radius);box-shadow:0 8px 32px rgba(0,0,0,.2);max-width:380px}.cc-banner--floating .cc-banner__container{display:block}.cc-banner--floating .cc-banner__title{font-size:1rem}.cc-banner--floating .cc-banner__description{font-size:.8125rem}.cc-banner--floating .cc-banner__actions{flex-direction:column;margin-top:1rem}.cc-banner--floating .cc-banner__actions .cc-btn{font-size:.8125rem;padding:.625rem 1rem;width:100%}@media (prefers-color-scheme:dark){.cc-banner[data-theme=auto]{--cc-bg:#1a1a1a;--cc-text:#fff;--cc-text-secondary:#a0a0a0;--cc-border:#333}.cc-banner[data-theme=auto].cc-backdrop-blur{background:rgba(26,26,26,.95)}.cc-banner[data-theme=auto] .cc-btn--secondary{background:#2a2a2a;color:#fff}.cc-banner[data-theme=auto] .cc-btn--secondary:hover:not(:disabled){background:#333}.cc-banner[data-theme=auto] .cc-btn--reject{background:#fff;color:#1a1a1a}.cc-banner[data-theme=auto] .cc-btn--tertiary{border-color:#555;color:#a0a0a0}}.cc-banner[data-theme=dark]{--cc-bg:#1a1a1a;--cc-text:#fff;--cc-text-secondary:#a0a0a0;--cc-border:#333}.cc-banner[data-theme=dark].cc-backdrop-blur{background:rgba(26,26,26,.95)}.cc-banner[data-theme=dark] .cc-btn--secondary{background:#2a2a2a;color:#fff}.cc-banner[data-theme=dark] .cc-btn--secondary:hover:not(:disabled){background:#333}.cc-banner[data-theme=dark] .cc-btn--reject{background:#fff;color:#1a1a1a}.cc-banner[data-theme=dark] .cc-btn--tertiary{border-color:#555;color:#a0a0a0}@keyframes cc-fadeIn{0%{opacity:0}to{opacity:1}}@keyframes cc-slideUp{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes cc-slideDown{0%{opacity:0;transform:translateY(-100%)}to{opacity:1;transform:translateY(0)}}@keyframes cc-scaleIn{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}@keyframes cc-backdropFadeIn{0%{opacity:0}to{opacity:1}}.cc-animate-fadeIn{animation:cc-fadeIn .3s ease-out}.cc-animate-slideUp{animation:cc-slideUp .4s cubic-bezier(.4,0,.2,1)}.cc-animate-slideDown{animation:cc-slideDown .4s cubic-bezier(.4,0,.2,1)}.cc-animate-scaleIn{animation:cc-scaleIn .3s cubic-bezier(.4,0,.2,1)}@media (prefers-reduced-motion:reduce){.cc-banner{transition:none}.cc-animate-fadeIn,.cc-animate-scaleIn,.cc-animate-slideDown,.cc-animate-slideUp{animation:none}.cc-btn{transition:none}}.cc-modal{align-items:center;bottom:0;display:flex;justify-content:center;left:0;opacity:0;padding:1rem;pointer-events:none;position:fixed;right:0;top:0;transition:opacity var(--cc-transition);z-index:10000}.cc-modal.is-visible{opacity:1;pointer-events:all}.cc-modal__overlay{background:var(--cc-overlay);bottom:0;cursor:pointer;left:0;position:absolute;right:0;top:0}.cc-modal__content{background:var(--cc-bg);border-radius:var(--cc-border-radius);box-shadow:0 16px 48px rgba(0,0,0,.18),0 4px 12px rgba(0,0,0,.08);display:flex;flex-direction:column;max-height:90vh;max-width:480px;overflow:hidden;position:relative;transform:scale(.9);transition:transform var(--cc-transition);width:100%}.cc-modal.is-visible .cc-modal__content{transform:scale(1)}.cc-modal__header{align-items:center;background:linear-gradient(135deg,var(--cc-primary) 0,var(--cc-primary-hover) 100%);display:flex;flex-shrink:0;justify-content:space-between;padding:1.125rem 1.25rem}.cc-modal__header h2{color:#fff;font-size:.95rem;font-weight:600;letter-spacing:-.01em;margin:0}.cc-modal__close{align-items:center;background:hsla(0,0%,100%,.15);border:none;border-radius:6px;color:#fff;cursor:pointer;display:flex;justify-content:center;padding:.375rem;transition:all .2s ease}.cc-modal__close svg{height:18px;width:18px}.cc-modal__close:hover{background:hsla(0,0%,100%,.3);transform:scale(1.05)}.cc-modal__close:focus-visible{outline:2px solid hsla(0,0%,100%,.5);outline-offset:2px}.cc-modal__body{flex:1;overflow-y:auto;padding:1rem 1.25rem}.cc-category{border-bottom:1px solid var(--cc-border);padding:.75rem 0}.cc-category:last-child{border-bottom:none}.cc-category__header{align-items:center;display:flex;gap:.75rem}.cc-category__info{flex:1}.cc-category__info h3{color:var(--cc-text);font-size:.8125rem;font-weight:600;letter-spacing:-.01em;margin:0 0 .125rem}.cc-category__info p{color:var(--cc-text-secondary);font-size:.75rem;line-height:1.4;margin:0}.cc-toggle{align-items:center;cursor:pointer;display:inline-flex;flex-shrink:0;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none}.cc-toggle input{height:0;opacity:0;position:absolute;width:0}.cc-toggle__slider{background:#d1d5db;border-radius:10px;height:20px;position:relative;transition:background-color .2s ease;width:36px}.cc-toggle__slider:before{background:#fff;border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,.15);content:"";height:16px;left:2px;position:absolute;top:2px;transition:transform .2s ease;width:16px}.cc-toggle input:checked+.cc-toggle__slider{background:var(--cc-primary)}.cc-toggle input:checked+.cc-toggle__slider:before{transform:translateX(16px)}.cc-toggle input:focus-visible+.cc-toggle__slider{outline:2px solid var(--cc-primary);outline-offset:2px}.cc-toggle--disabled{cursor:not-allowed;opacity:.6}.cc-toggle--disabled input:checked+.cc-toggle__slider{background:#9ca3af}.cc-modal__footer{align-items:center;border-top:1px solid var(--cc-border);display:flex;flex-shrink:0;gap:var(--cc-gap);justify-content:space-between;padding:1rem 1.25rem}.cc-modal__footer-links{align-items:center;display:flex;gap:.5rem}.cc-modal__footer-actions{display:flex;gap:var(--cc-gap)}.cc-privacy-link{align-items:center;color:var(--cc-text-secondary);display:inline-flex;font-size:.875rem;gap:.25rem;text-decoration:none;transition:color .2s ease}.cc-privacy-link:hover{color:var(--cc-primary);text-decoration:underline}@media (prefers-color-scheme:dark){.cc-modal[data-theme=auto] .cc-modal__content{background:#1a1a1a}.cc-modal[data-theme=auto] .cc-category__info h3{color:#fff}.cc-modal[data-theme=auto] .cc-category__info p{color:#a0a0a0}.cc-modal[data-theme=auto] .cc-category,.cc-modal[data-theme=auto] .cc-modal__footer{border-color:#333}.cc-modal[data-theme=auto] .cc-toggle__slider{background:#444}.cc-modal[data-theme=auto] .cc-btn--secondary{background:#2a2a2a;color:#fff}.cc-modal[data-theme=auto] .cc-btn--secondary:hover:not(:disabled){background:#333}.cc-modal[data-theme=auto] .cc-modal__close:hover{background:hsla(0,0%,100%,.1)}}.cc-modal[data-theme=dark] .cc-modal__content{background:#1a1a1a}.cc-modal[data-theme=dark] .cc-category__info h3{color:#fff}.cc-modal[data-theme=dark] .cc-category__info p{color:#a0a0a0}.cc-modal[data-theme=dark] .cc-category,.cc-modal[data-theme=dark] .cc-modal__footer{border-color:#333}.cc-modal[data-theme=dark] .cc-toggle__slider{background:#444}.cc-modal[data-theme=dark] .cc-btn--secondary{background:#2a2a2a;color:#fff}.cc-modal[data-theme=dark] .cc-btn--secondary:hover:not(:disabled){background:#333}.cc-modal[data-theme=dark] .cc-modal__close:hover{background:hsla(0,0%,100%,.1)}.cc-modal--bottom-right{align-items:flex-end;justify-content:flex-end;padding:1.5rem}.cc-modal--bottom-right .cc-modal__content{max-width:450px;transform:translateX(100%)}.cc-modal--bottom-right.is-visible .cc-modal__content{transform:translateX(0)}.cc-modal--bottom-left{align-items:flex-end;justify-content:flex-start;padding:1.5rem}.cc-modal--bottom-left .cc-modal__content{max-width:450px;transform:translateX(-100%)}.cc-modal--bottom-left.is-visible .cc-modal__content{transform:translateX(0)}.cc-modal--top-right{align-items:flex-start;justify-content:flex-end;padding:1.5rem}.cc-modal--top-right .cc-modal__content{max-width:450px;transform:translateX(100%)}.cc-modal--top-right.is-visible .cc-modal__content{transform:translateX(0)}.cc-modal--top-left{align-items:flex-start;justify-content:flex-start;padding:1.5rem}.cc-modal--top-left .cc-modal__content{max-width:450px;transform:translateX(-100%)}.cc-modal--top-left.is-visible .cc-modal__content{transform:translateX(0)}@media (max-width:640px){.cc-modal{align-items:flex-end;padding:0}.cc-modal__content{border-radius:16px 16px 0 0;max-height:85vh;max-width:100%;transform:translateY(100%);width:100%}.cc-modal.is-visible .cc-modal__content{transform:translateY(0)}.cc-modal__body{padding:1rem 1.25rem}.cc-modal__footer{align-items:stretch;flex-direction:column;padding:1rem 1.25rem 1.5rem}.cc-modal__footer-links{justify-content:center;margin-top:.75rem;order:2}.cc-modal__footer-actions{flex-direction:column;order:1;width:100%}.cc-modal__footer .cc-btn{width:100%}}.cc-widget{align-items:center;background:#fff;border:1.5px solid var(--cc-primary);border-radius:50px;box-shadow:0 2px 8px rgba(0,0,0,.08);color:var(--cc-primary);cursor:pointer;display:flex;font-family:var(--cc-font-family);gap:.5rem;min-height:40px;opacity:0;padding:.625rem .875rem;position:fixed;transform:scale(0);transition:all .3s cubic-bezier(.4,0,.2,1);-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:9998}.cc-widget.is-visible{opacity:1;transform:scale(1)}.cc-widget:hover{background:var(--cc-primary);box-shadow:0 4px 16px rgba(0,0,0,.12);color:#fff;transform:scale(1.05)}.cc-widget:active{transform:scale(.98)}.cc-widget:focus-visible{outline:3px solid #fff;outline-offset:2px}.cc-widget__icon{flex-shrink:0;height:20px;width:20px}.cc-widget__text{color:inherit;font-size:.8125rem;font-weight:500;white-space:nowrap}.cc-widget--bottom-right{bottom:1.5rem;right:1.5rem}.cc-widget--bottom-left{bottom:1.5rem;left:1.5rem}.cc-widget--top-right{right:1.5rem;top:1.5rem}.cc-widget--top-left{left:1.5rem;top:1.5rem}.cc-widget--compact{border-radius:50%;height:42px;justify-content:center;padding:.625rem;width:42px}.cc-widget--compact .cc-widget__text{display:none}@media (max-width:640px){.cc-widget--full .cc-widget__text{display:none}.cc-widget--full{border-radius:50%;height:44px;justify-content:center;padding:.625rem;width:44px}}@keyframes cc-widget-bounce{0%{transform:scale(0)}50%{transform:scale(1.1)}to{transform:scale(1)}}.cc-widget.is-visible{animation:cc-widget-bounce .4s cubic-bezier(.4,0,.2,1)}.cc-widget[data-theme=dark]{background:#1a1a1a;border-color:var(--cc-primary);color:var(--cc-primary)}.cc-widget[data-theme=dark]:hover{background:var(--cc-primary);color:#fff}@media (prefers-color-scheme:dark){.cc-widget[data-theme=auto]{background:#1a1a1a;border-color:var(--cc-primary);color:var(--cc-primary)}.cc-widget[data-theme=auto]:hover{background:var(--cc-primary);color:#fff}}@media (prefers-reduced-motion:reduce){.cc-widget{transition:none}.cc-widget.is-visible{animation:none}.cc-widget:hover{transform:none}}
1
+ .cc-banner,.cc-modal,.cc-widget{--cc-primary:#1a1a1a;--cc-primary-hover:#333;--cc-primary-glow:rgba(0,0,0,.12);--cc-bg:#fff;--cc-text:#1a1a1a;--cc-text-secondary:#666;--cc-border:#e5e7eb;--cc-overlay:rgba(0,0,0,.4);--cc-padding:1.125rem;--cc-gap:0.5rem;--cc-border-radius:12px;--cc-shadow:0 -4px 24px rgba(0,0,0,.12);--cc-transition:0.3s cubic-bezier(0.4,0,0.2,1);--cc-backdrop-blur:10px;--cc-font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif}.cc-banner *,.cc-modal *,.cc-widget *{box-sizing:border-box;margin:0;padding:0}.cc-banner{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:var(--cc-bg);bottom:0;box-shadow:var(--cc-shadow);font-family:var(--cc-font-family);left:0;padding:var(--cc-padding);position:fixed;right:0;transform:translateY(100%);transition:transform var(--cc-transition);z-index:2147483647}.cc-banner.cc-backdrop-blur{backdrop-filter:blur(var(--cc-backdrop-blur));background:hsla(0,0%,100%,.95)}.cc-banner.is-visible{transform:translateY(0)}.cc-banner__container{margin:0 auto;max-width:1200px}.cc-banner__content{margin-bottom:1rem}.cc-banner__title{color:var(--cc-text);font-size:.9375rem;font-weight:600;letter-spacing:-.01em;line-height:1.3;margin:0 0 .375rem}.cc-banner__description{color:var(--cc-text-secondary);font-size:.8125rem;line-height:1.5;margin:0}.cc-banner__description a{color:var(--cc-primary);font-weight:500;text-decoration:none;transition:all .2s ease}.cc-banner__description a:hover{color:var(--cc-primary-hover);text-decoration:underline}.cc-banner__actions{display:flex;flex-wrap:wrap;gap:var(--cc-gap)}.cc-btn{align-items:center;border:none;border-radius:8px;cursor:pointer;display:inline-flex;font-family:inherit;font-size:.8125rem;font-weight:500;justify-content:center;letter-spacing:-.01em;min-height:36px;min-width:36px;padding:.5rem 1.125rem;text-decoration:none;transition:all .2s ease}.cc-btn:focus-visible{outline:3px solid var(--cc-primary);outline-offset:2px}.cc-btn:disabled{cursor:not-allowed;opacity:.6}.cc-btn--accept{background:var(--cc-primary);color:#fff}.cc-btn--accept:hover:not(:disabled){background:var(--cc-primary-hover);box-shadow:0 4px 12px var(--cc-primary-glow);transform:translateY(-1px)}.cc-btn--accept:active:not(:disabled){transform:translateY(0)}.cc-btn--ghost{background:transparent;color:var(--cc-text-secondary);font-size:.75rem;padding:.5rem .75rem}.cc-btn--ghost:hover:not(:disabled){color:var(--cc-text);text-decoration:underline}.cc-btn--ghost:active:not(:disabled){transform:translateY(0)}.cc-btn--primary{background:var(--cc-primary);color:#fff}.cc-btn--primary:hover:not(:disabled){background:var(--cc-primary-hover);box-shadow:0 4px 12px var(--cc-primary-glow);transform:translateY(-1px)}.cc-btn--primary:active:not(:disabled){transform:translateY(0)}.cc-btn--secondary{background:#f3f4f6;color:var(--cc-text)}.cc-btn--secondary:hover:not(:disabled){background:#e5e7eb;transform:translateY(-1px)}.cc-btn--secondary:active:not(:disabled){transform:translateY(0)}.cc-btn--tertiary{background:transparent;border:1px solid var(--cc-border);color:var(--cc-text-secondary)}.cc-btn--tertiary:hover:not(:disabled){background:rgba(0,0,0,.03);color:var(--cc-text);transform:translateY(-1px)}.cc-btn--tertiary:active:not(:disabled){transform:translateY(0)}@media (min-width:768px){.cc-banner--bar .cc-banner__container{align-items:center;display:flex;gap:2rem;justify-content:space-between}.cc-banner--bar .cc-banner__content{flex:1;margin-bottom:0}.cc-banner--bar .cc-banner__actions{flex-shrink:0}}.cc-banner--top{bottom:auto;box-shadow:0 4px 24px rgba(0,0,0,.12);top:0;transform:translateY(-100%)}.cc-banner--top.is-visible{transform:translateY(0)}.cc-banner--center{border-radius:var(--cc-border-radius);bottom:auto;left:50%;max-width:600px;opacity:0;right:auto;top:50%;transform:translate(-50%,-50%) scale(.9)}.cc-banner--center.is-visible{opacity:1;transform:translate(-50%,-50%) scale(1)}.cc-banner--bottom-right{border-radius:var(--cc-border-radius);bottom:1.5rem;left:auto;max-width:420px;right:1.5rem;transform:translateX(calc(100% + 2rem))}.cc-banner--bottom-right.is-visible{transform:translateX(0)}.cc-banner--bottom-left{border-radius:var(--cc-border-radius);bottom:1.5rem;left:1.5rem;max-width:420px;right:auto;transform:translateX(calc(-100% - 2rem))}.cc-banner--bottom-left.is-visible{transform:translateX(0)}.cc-banner--box{border-radius:var(--cc-border-radius);max-width:420px}.cc-banner--box .cc-banner__container{display:block}.cc-banner--box .cc-banner__actions{flex-direction:column;margin-top:1rem}.cc-banner--box .cc-banner__actions .cc-btn{width:100%}.cc-banner--floating{border-radius:var(--cc-border-radius);box-shadow:0 8px 32px rgba(0,0,0,.2);max-width:380px}.cc-banner--floating .cc-banner__container{display:block}.cc-banner--floating .cc-banner__title{font-size:1rem}.cc-banner--floating .cc-banner__description{font-size:.8125rem}.cc-banner--floating .cc-banner__actions{flex-direction:column;margin-top:1rem}.cc-banner--floating .cc-banner__actions .cc-btn{font-size:.8125rem;padding:.625rem 1rem;width:100%}@media (prefers-color-scheme:dark){.cc-banner[data-theme=auto]{--cc-bg:#1a1a1a;--cc-text:#fff;--cc-text-secondary:#a0a0a0;--cc-border:#333}.cc-banner[data-theme=auto].cc-backdrop-blur{background:rgba(26,26,26,.95)}.cc-banner[data-theme=auto] .cc-btn--secondary{background:#2a2a2a;color:#fff}.cc-banner[data-theme=auto] .cc-btn--secondary:hover:not(:disabled){background:#333}.cc-banner[data-theme=auto] .cc-btn--tertiary{border-color:#555;color:#a0a0a0}}.cc-banner[data-theme=dark]{--cc-bg:#1a1a1a;--cc-text:#fff;--cc-text-secondary:#a0a0a0;--cc-border:#333}.cc-banner[data-theme=dark].cc-backdrop-blur{background:rgba(26,26,26,.95)}.cc-banner[data-theme=dark] .cc-btn--secondary{background:#2a2a2a;color:#fff}.cc-banner[data-theme=dark] .cc-btn--secondary:hover:not(:disabled){background:#333}.cc-banner[data-theme=dark] .cc-btn--tertiary{border-color:#555;color:#a0a0a0}@keyframes cc-fadeIn{0%{opacity:0}to{opacity:1}}@keyframes cc-slideUp{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes cc-slideDown{0%{opacity:0;transform:translateY(-100%)}to{opacity:1;transform:translateY(0)}}@keyframes cc-scaleIn{0%{opacity:0;transform:scale(.9)}to{opacity:1;transform:scale(1)}}@keyframes cc-backdropFadeIn{0%{opacity:0}to{opacity:1}}.cc-animate-fadeIn{animation:cc-fadeIn .3s ease-out}.cc-animate-slideUp{animation:cc-slideUp .4s cubic-bezier(.4,0,.2,1)}.cc-animate-slideDown{animation:cc-slideDown .4s cubic-bezier(.4,0,.2,1)}.cc-animate-scaleIn{animation:cc-scaleIn .3s cubic-bezier(.4,0,.2,1)}@media (prefers-reduced-motion:reduce){.cc-banner{transition:none}.cc-animate-fadeIn,.cc-animate-scaleIn,.cc-animate-slideDown,.cc-animate-slideUp{animation:none}.cc-btn{transition:none}}.cc-modal{align-items:center;bottom:0;display:flex;justify-content:center;left:0;opacity:0;padding:1rem;pointer-events:none;position:fixed;right:0;top:0;transition:opacity var(--cc-transition);z-index:10000}.cc-modal.is-visible{opacity:1;pointer-events:all}.cc-modal__overlay{background:var(--cc-overlay);bottom:0;cursor:pointer;left:0;position:absolute;right:0;top:0}.cc-modal__content{background:var(--cc-bg);border-radius:var(--cc-border-radius);box-shadow:0 16px 48px rgba(0,0,0,.18),0 4px 12px rgba(0,0,0,.08);display:flex;flex-direction:column;max-height:90vh;max-width:480px;overflow:hidden;position:relative;transform:scale(.9);transition:transform var(--cc-transition);width:100%}.cc-modal.is-visible .cc-modal__content{transform:scale(1)}.cc-modal__header{align-items:center;background:linear-gradient(135deg,var(--cc-primary) 0,var(--cc-primary-hover) 100%);display:flex;flex-shrink:0;justify-content:space-between;padding:1.125rem 1.25rem}.cc-modal__header h2{color:#fff;font-size:.95rem;font-weight:600;letter-spacing:-.01em;margin:0}.cc-modal__body{flex:1;overflow-y:auto;padding:1rem 1.25rem}.cc-category{border-bottom:1px solid var(--cc-border);padding:.75rem 0}.cc-category:last-child{border-bottom:none}.cc-category__header{align-items:center;display:flex;gap:.75rem}.cc-category__info{flex:1}.cc-category__info h3{color:var(--cc-text);font-size:.8125rem;font-weight:600;letter-spacing:-.01em;margin:0 0 .125rem}.cc-category__info p{color:var(--cc-text-secondary);font-size:.75rem;line-height:1.4;margin:0}.cc-toggle{align-items:center;cursor:pointer;display:inline-flex;flex-shrink:0;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none}.cc-toggle input{height:0;opacity:0;position:absolute;width:0}.cc-toggle__slider{background:#d1d5db;border-radius:10px;height:20px;position:relative;transition:background-color .2s ease;width:36px}.cc-toggle__slider:before{background:#fff;border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,.15);content:"";height:16px;left:2px;position:absolute;top:2px;transition:transform .2s ease;width:16px}.cc-toggle input:checked+.cc-toggle__slider{background:var(--cc-primary)}.cc-toggle input:checked+.cc-toggle__slider:before{transform:translateX(16px)}.cc-toggle input:focus-visible+.cc-toggle__slider{outline:2px solid var(--cc-primary);outline-offset:2px}.cc-toggle--disabled{cursor:not-allowed;opacity:.6}.cc-toggle--disabled input:checked+.cc-toggle__slider{background:#9ca3af}.cc-modal__footer{align-items:center;border-top:1px solid var(--cc-border);display:flex;flex-shrink:0;gap:var(--cc-gap);justify-content:space-between;padding:1rem 1.25rem}.cc-modal__footer-links{align-items:center;display:flex;gap:.5rem}.cc-modal__footer-actions{display:flex;gap:var(--cc-gap)}.cc-privacy-link{align-items:center;color:var(--cc-text-secondary);display:inline-flex;font-size:.875rem;gap:.25rem;text-decoration:none;transition:color .2s ease}.cc-privacy-link:hover{color:var(--cc-primary);text-decoration:underline}@media (prefers-color-scheme:dark){.cc-modal[data-theme=auto] .cc-modal__content{background:#1a1a1a}.cc-modal[data-theme=auto] .cc-category__info h3{color:#fff}.cc-modal[data-theme=auto] .cc-category__info p{color:#a0a0a0}.cc-modal[data-theme=auto] .cc-category,.cc-modal[data-theme=auto] .cc-modal__footer{border-color:#333}.cc-modal[data-theme=auto] .cc-toggle__slider{background:#444}.cc-modal[data-theme=auto] .cc-btn--secondary{background:#2a2a2a;color:#fff}.cc-modal[data-theme=auto] .cc-btn--secondary:hover:not(:disabled){background:#333}}.cc-modal[data-theme=dark] .cc-modal__content{background:#1a1a1a}.cc-modal[data-theme=dark] .cc-category__info h3{color:#fff}.cc-modal[data-theme=dark] .cc-category__info p{color:#a0a0a0}.cc-modal[data-theme=dark] .cc-category,.cc-modal[data-theme=dark] .cc-modal__footer{border-color:#333}.cc-modal[data-theme=dark] .cc-toggle__slider{background:#444}.cc-modal[data-theme=dark] .cc-btn--secondary{background:#2a2a2a;color:#fff}.cc-modal[data-theme=dark] .cc-btn--secondary:hover:not(:disabled){background:#333}.cc-modal--bottom-right{align-items:flex-end;justify-content:flex-end;padding:1.5rem}.cc-modal--bottom-right .cc-modal__content{max-width:450px;transform:translateX(100%)}.cc-modal--bottom-right.is-visible .cc-modal__content{transform:translateX(0)}.cc-modal--bottom-left{align-items:flex-end;justify-content:flex-start;padding:1.5rem}.cc-modal--bottom-left .cc-modal__content{max-width:450px;transform:translateX(-100%)}.cc-modal--bottom-left.is-visible .cc-modal__content{transform:translateX(0)}.cc-modal--top-right{align-items:flex-start;justify-content:flex-end;padding:1.5rem}.cc-modal--top-right .cc-modal__content{max-width:450px;transform:translateX(100%)}.cc-modal--top-right.is-visible .cc-modal__content{transform:translateX(0)}.cc-modal--top-left{align-items:flex-start;justify-content:flex-start;padding:1.5rem}.cc-modal--top-left .cc-modal__content{max-width:450px;transform:translateX(-100%)}.cc-modal--top-left.is-visible .cc-modal__content{transform:translateX(0)}@media (max-width:640px){.cc-modal{align-items:flex-end;padding:0}.cc-modal__content{border-radius:16px 16px 0 0;max-height:85vh;max-width:100%;transform:translateY(100%);width:100%}.cc-modal.is-visible .cc-modal__content{transform:translateY(0)}.cc-modal__body{padding:1rem 1.25rem}.cc-modal__footer{align-items:stretch;flex-direction:column;padding:1rem 1.25rem 1.5rem}.cc-modal__footer-links{justify-content:center;margin-top:.75rem;order:2}.cc-modal__footer-actions{flex-direction:column;order:1;width:100%}.cc-modal__footer .cc-btn{width:100%}}.cc-widget{align-items:center;background:#fff;border:1.5px solid var(--cc-primary);border-radius:50px;box-shadow:0 2px 8px rgba(0,0,0,.08);color:var(--cc-primary);cursor:pointer;display:flex;font-family:var(--cc-font-family);gap:.5rem;min-height:40px;opacity:0;padding:.625rem .875rem;position:fixed;transform:scale(0);transition:all .3s cubic-bezier(.4,0,.2,1);-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:9998}.cc-widget.is-visible{opacity:1;transform:scale(1)}.cc-widget:hover{background:var(--cc-primary);box-shadow:0 4px 16px rgba(0,0,0,.12);color:#fff;transform:scale(1.05)}.cc-widget:active{transform:scale(.98)}.cc-widget:focus-visible{outline:3px solid var(--cc-primary);outline-offset:2px}.cc-widget__icon{flex-shrink:0;height:20px;width:20px}.cc-widget__text{color:inherit;font-size:.8125rem;font-weight:500;white-space:nowrap}.cc-widget--bottom-right{bottom:1.5rem;right:1.5rem}.cc-widget--bottom-left{bottom:1.5rem;left:1.5rem}.cc-widget--top-right{right:1.5rem;top:1.5rem}.cc-widget--top-left{left:1.5rem;top:1.5rem}.cc-widget--compact{border-radius:50%;height:42px;justify-content:center;padding:.625rem;width:42px}.cc-widget--compact .cc-widget__text{display:none}@media (max-width:640px){.cc-widget--full .cc-widget__text{display:none}.cc-widget--full{border-radius:50%;height:44px;justify-content:center;padding:.625rem;width:44px}}@keyframes cc-widget-bounce{0%{transform:scale(0)}50%{transform:scale(1.1)}to{transform:scale(1)}}.cc-widget.is-visible{animation:cc-widget-bounce .4s cubic-bezier(.4,0,.2,1)}.cc-widget[data-theme=dark]{background:#1a1a1a;border-color:var(--cc-primary);color:var(--cc-primary)}.cc-widget[data-theme=dark]:hover{background:var(--cc-primary);color:#fff}@media (prefers-color-scheme:dark){.cc-widget[data-theme=auto]{background:#1a1a1a;border-color:var(--cc-primary);color:var(--cc-primary)}.cc-widget[data-theme=auto]:hover{background:var(--cc-primary);color:#fff}}@media (prefers-reduced-motion:reduce){.cc-widget{transition:none}.cc-widget.is-visible{animation:none}.cc-widget:hover{transform:none}}