> ## Documentation Index
> Fetch the complete documentation index at: https://www.beeq.design/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Theme

> This guide walks you through creating and applying a custom theme across your app or project.

export const CodeLivePreview = ({code, children, height, removePadding = false, mode = 'shadow'}) => {
  const previewRef = useRef(null);
  const BEEQ_ESM_URL = 'https://esm.sh/@beeq/core/dist/beeq/beeq.esm.js';
  const BEEQ_CSS_URL = 'https://esm.sh/@beeq/core/dist/beeq/beeq.css';
  const BEEQ_ICONS_URL = 'https://esm.sh/@beeq/core/dist/beeq/svg';
  const ensureParentBeeqRuntime = () => {
    if (document.querySelector('script[data-beeq-parent-runtime]')) return;
    const script = document.createElement('script');
    script.type = 'module';
    script.src = BEEQ_ESM_URL;
    script.dataset.beeqParentRuntime = BEEQ_ICONS_URL;
    document.head.appendChild(script);
  };
  const executeSnippetScripts = (root, runtimeWindow, previewRootArg, skipAttr) => {
    root.querySelectorAll('script').forEach(oldScript => {
      if (skipAttr && oldScript.hasAttribute(skipAttr)) return;
      if (oldScript.src) {
        const newScript = runtimeWindow.document.createElement('script');
        newScript.src = oldScript.src;
        oldScript.replaceWith(newScript);
        return;
      }
      runtimeWindow.Function('previewRoot', oldScript.textContent || '')(previewRootArg);
      oldScript.remove();
    });
  };
  const syncIframeMode = iframeDoc => {
    const root = document.documentElement;
    const explicitMode = root.getAttribute('bq-mode');
    const isDark = root.classList.contains('dark');
    const resolvedMode = explicitMode || (isDark ? 'dark' : 'light');
    iframeDoc.documentElement.setAttribute('bq-mode', resolvedMode);
    iframeDoc.body.setAttribute('bq-mode', resolvedMode);
  };
  useEffect(() => {
    if (mode === 'shadow') ensureParentBeeqRuntime();
  }, [mode]);
  useEffect(() => {
    const container = previewRef.current;
    if (!container) return;
    if (removePadding) container.style.padding = '0';
    container.innerHTML = '';
    if (mode === 'iframe') {
      const iframe = document.createElement('iframe');
      iframe.className = 'preview-iframe';
      iframe.style.width = '100%';
      iframe.style.border = '0';
      iframe.style.display = 'block';
      iframe.style.minHeight = height ?? '0px';
      iframe.setAttribute('title', 'Live code preview');
      iframe.setAttribute('loading', 'lazy');
      iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
      container.appendChild(iframe);
      const iframeDoc = iframe.contentDocument;
      const iframeWin = iframe.contentWindow;
      if (!iframeDoc || !iframeWin) return;
      iframeDoc.open();
      iframeDoc.write(['<!doctype html>', '<html>', '<head>', '  <meta charset="utf-8" />', '  <meta name="viewport" content="width=device-width, initial-scale=1" />', '  <style>html,body{margin:0;padding:0;min-height:100%;}</style>', `  <link rel="stylesheet" href="${BEEQ_CSS_URL}" />`, `  <script type="module" src="${BEEQ_ESM_URL}" data-beeq-iframe-runtime="${BEEQ_ICONS_URL}"></script>`, '</head>', '<body>', code, '</body>', '</html>'].join('\n'));
      iframeDoc.close();
      syncIframeMode(iframeDoc);
      const modeObserver = new MutationObserver(() => syncIframeMode(iframeDoc));
      modeObserver.observe(document.documentElement, {
        attributes: true,
        attributeFilter: ['class', 'bq-mode']
      });
      executeSnippetScripts(iframeDoc, iframeWin, iframeDoc, 'data-beeq-iframe-runtime');
      return () => modeObserver.disconnect();
    }
    const shadowRoot = container.shadowRoot ?? container.attachShadow({
      mode: 'open'
    });
    if (!shadowRoot.adoptedStyleSheets.length) {
      const fixSheet = new CSSStyleSheet();
      fixSheet.replaceSync(`
        bq-dropdown::part(panel),
        bq-panel::part(panel),
        bq-select::part(panel),
        bq-date-picker::part(panel) { z-index: 9999; }
        bq-tooltip::part(panel) { position: absolute; }
      `);
      shadowRoot.adoptedStyleSheets = [fixSheet];
    }
    shadowRoot.innerHTML = [`<link rel="stylesheet" href="${BEEQ_CSS_URL}">`, code].join('');
    executeSnippetScripts(shadowRoot, window, shadowRoot);
    return undefined;
  }, [code, mode, height]);
  return <div className="code-live-preview not-prose">
      {}
      <div className="preview" ref={previewRef} style={{
    minHeight: height
  }} />

      {}
      {children && <div className="code">{children}</div>}
    </div>;
};

To create a custom theme, define your own set of CSS variables that override the base theme variables and declarative colors for both light and dark modes.

<Note>
  Namespace your theme using the `bq-theme` attribute (e.g., `bq-theme="my-custom-theme"`) or a matching CSS class (e.g., `.my-custom-theme`).
</Note>

***

## Step-by-step guide

<Steps>
  <Step title="Define base theme variables">
    Create a CSS file for your custom theme (e.g., `custom-theme.css`) and set the base design tokens:

    ```css theme={"theme":{"light":"one-light","dark":"night-owl"}}
    [bq-theme="my-custom-theme"],
    .my-custom-theme {
      /* Override font family */
      --bq-font-family: 'Inter', sans-serif;

      /* Define brand colors using any primitive color from the palette */
      --bq-brand-light: var(--bq-blue-100);
      --bq-brand:       var(--bq-blue-600);
      --bq-brand-dark:  var(--bq-blue-1000);

      /* Define accent colors */
      --bq-accent-light: var(--bq-purple-100);
      --bq-accent:       var(--bq-purple-600);
      --bq-accent-dark:  var(--bq-purple-1000);

      /* Override neutral scale if needed */
      --bq-neutral-50:  var(--bq-grey-50);
      --bq-neutral-100: var(--bq-grey-100);
      /* ... continue with other neutrals ... */

      /* Define semantic colors */
      --bq-success: var(--bq-teal-600);
      --bq-danger:  var(--bq-red-600);
      --bq-warning: var(--bq-gold-600);
      --bq-info:    var(--bq-blue-600);
      --bq-focus:   var(--bq-blue-600);

      /* Interactive state overlays */
      --bq-state--hover:  rgba(0, 0, 0, 0.08);  /* Subtle hover overlay (light mode) */
      --bq-state--active: rgba(0, 0, 0, 0.12); /* Pressed state overlay (light mode) */
    }
    ```

    <Tip>
      Override `--bq-state--hover` and `--bq-state--active` for each mode. In dark mode, use light
      overlays (e.g. `rgba(255, 255, 255, 0.1)`) instead of dark ones.
    </Tip>
  </Step>

  <Step title="Define light mode theme">
    Define the declarative color tokens for the light mode:

    ```css theme={"theme":{"light":"one-light","dark":"night-owl"}}
    [bq-theme="my-custom-theme"]:not([bq-mode]),    /* Default — no mode specified */
    [bq-theme="my-custom-theme"][bq-mode="light"],  /* Explicit light mode (via attributes) */
    .my-custom-theme:not([bq-mode]),                /* Default — no mode (via CSS class) */
    .my-custom-theme.light {                        /* Explicit light mode (via CSS classes) */

      /* Background colors */
      --bq-background--primary:   var(--bq-white);
      --bq-background--secondary: var(--bq-neutral-100);
      --bq-background--tertiary:  var(--bq-neutral-200);
      --bq-background--alt:       var(--bq-neutral-300);
      --bq-background--inverse:   var(--bq-neutral-900);
      --bq-background--brand:     var(--bq-brand);
      --bq-background--overlay:   var(--bq-neutral-900);

      /* Icon colors */
      --bq-icon--primary:   var(--bq-neutral-800);
      --bq-icon--secondary: var(--bq-neutral-600);
      --bq-icon--inverse:   var(--bq-neutral-50);
      --bq-icon--brand:     var(--bq-brand);
      --bq-icon--alt:       var(--bq-white);
      --bq-icon--info:      var(--bq-info);
      --bq-icon--success:   var(--bq-success);
      --bq-icon--warning:   var(--bq-warning);
      --bq-icon--danger:    var(--bq-danger);

      /* Stroke colors */
      --bq-stroke--primary:   var(--bq-neutral-200);
      --bq-stroke--secondary: var(--bq-neutral-600);
      --bq-stroke--tertiary:  var(--bq-neutral-900);
      --bq-stroke--inverse:   var(--bq-white);
      --bq-stroke--brand:     var(--bq-brand);
      --bq-stroke--alt:       var(--bq-neutral-50);
      --bq-stroke--success:   var(--bq-success);
      --bq-stroke--warning:   var(--bq-warning);
      --bq-stroke--danger:    var(--bq-danger);

      /* Text colors */
      --bq-text--primary:   var(--bq-neutral-800);
      --bq-text--secondary: var(--bq-neutral-600);
      --bq-text--inverse:   var(--bq-neutral-50);
      --bq-text--brand:     var(--bq-brand);
      --bq-text--alt:       var(--bq-white);
      --bq-text--info:      var(--bq-info);
      --bq-text--success:   var(--bq-success);
      --bq-text--warning:   var(--bq-warning);
      --bq-text--danger:    var(--bq-danger);

      /* UI colors */
      --bq-ui--primary:      var(--bq-white);
      --bq-ui--secondary:    var(--bq-neutral-100);
      --bq-ui--tertiary:     var(--bq-neutral-500);
      --bq-ui--inverse:      var(--bq-neutral-900);
      --bq-ui--brand:        var(--bq-brand);
      --bq-ui--brand-alt:    var(--bq-brand-light);
      --bq-ui--alt:          var(--bq-neutral-50);
      --bq-ui--success:      var(--bq-success);
      --bq-ui--success-alt:  var(--bq-success-light);
      --bq-ui--warning:      var(--bq-warning);
      --bq-ui--warning-alt:  var(--bq-warning-light);
      --bq-ui--danger:       var(--bq-danger);
      --bq-ui--danger-alt:   var(--bq-danger-light);
    }
    ```
  </Step>

  <Step title="Define dark mode theme">
    Define the declarative color tokens for the dark mode:

    ```css theme={"theme":{"light":"one-light","dark":"night-owl"}}
    [bq-theme="my-custom-theme"][bq-mode="dark"],  /* Explicit dark mode (via attributes) */
    .my-custom-theme.dark {                        /* Explicit dark mode (via CSS classes) */

      /* Background colors */
      --bq-background--primary:   var(--bq-neutral-1000);
      --bq-background--secondary: var(--bq-neutral-950);
      --bq-background--tertiary:  var(--bq-neutral-800);
      --bq-background--alt:       var(--bq-neutral-700);
      --bq-background--inverse:   var(--bq-neutral-600);
      --bq-background--brand:     var(--bq-brand);
      --bq-background--overlay:   var(--bq-neutral-900);

      /* Icon colors */
      --bq-icon--primary:   var(--bq-neutral-100);
      --bq-icon--secondary: var(--bq-neutral-400);
      --bq-icon--inverse:   var(--bq-neutral-800);
      --bq-icon--brand:     var(--bq-brand);
      --bq-icon--alt:       var(--bq-white);
      --bq-icon--info:      var(--bq-info);
      --bq-icon--success:   var(--bq-success);
      --bq-icon--warning:   var(--bq-warning);
      --bq-icon--danger:    var(--bq-danger);

      /* Stroke colors */
      --bq-stroke--primary:   var(--bq-neutral-900);
      --bq-stroke--secondary: var(--bq-neutral-700);
      --bq-stroke--tertiary:  var(--bq-neutral-400);
      --bq-stroke--inverse:   var(--bq-neutral-950);
      --bq-stroke--brand:     var(--bq-brand);
      --bq-stroke--alt:       var(--bq-neutral-1000);
      --bq-stroke--success:   var(--bq-success);
      --bq-stroke--warning:   var(--bq-warning);
      --bq-stroke--danger:    var(--bq-danger);

      /* Text colors */
      --bq-text--primary:   var(--bq-neutral-100);
      --bq-text--secondary: var(--bq-neutral-400);
      --bq-text--inverse:   var(--bq-neutral-800);
      --bq-text--brand:     var(--bq-brand);
      --bq-text--alt:       var(--bq-white);
      --bq-text--info:      var(--bq-info);
      --bq-text--success:   var(--bq-success);
      --bq-text--warning:   var(--bq-warning);
      --bq-text--danger:    var(--bq-danger);

      /* UI colors */
      --bq-ui--primary:      var(--bq-neutral-900);
      --bq-ui--secondary:    var(--bq-neutral-950);
      --bq-ui--tertiary:     var(--bq-neutral-700);
      --bq-ui--inverse:      var(--bq-neutral-100);
      --bq-ui--brand:        var(--bq-brand);
      --bq-ui--brand-alt:    var(--bq-brand-dark);
      --bq-ui--alt:          var(--bq-neutral-950);
      --bq-ui--success:      var(--bq-success);
      --bq-ui--success-alt:  var(--bq-success-dark);
      --bq-ui--warning:      var(--bq-warning);
      --bq-ui--warning-alt:  var(--bq-warning-dark);
      --bq-ui--danger:       var(--bq-danger);
      --bq-ui--danger-alt:   var(--bq-danger-dark);
    }
    ```
  </Step>

  <Step title="Apply your custom theme">
    Include your custom theme CSS file in your project and set the `bq-theme` and `bq-mode` attributes on the `<html>` element:

    <Note>
      Always load `beeq.css` **before** your custom theme CSS so that your variables correctly override the defaults.
    </Note>

    ```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <!DOCTYPE html>
    <html lang="en" bq-theme="my-custom-theme" bq-mode="light">
      <head>
        <link rel="stylesheet" href="path/to/beeq.css">
        <link rel="stylesheet" href="path/to/custom-theme.css">
      </head>
      <body>
        <!-- Your components will automatically use the custom theme -->
        <bq-button>Click me</bq-button>
      </body>
    </html>
    ```

    To switch to dark mode, change the `bq-mode` attribute:

    ```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <html lang="en" bq-theme="my-custom-theme" bq-mode="dark">
    ```

    You can also use CSS classes instead of HTML attributes:

    ```html theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <body class="my-custom-theme light"> ... </body>
    <!-- or -->
    <body class="my-custom-theme dark"> ... </body>
    ```
  </Step>
</Steps>

***

## Full example: TechFlow theme

Here is an almost production-ready custom theme called **TechFlow** — a theme with vibrant teal accents and a sleek design aesthetic.

<CodeLivePreview
  mode="shadow"
  code={`
<style>
/* TechFlow — Base variables */

:host {
  --bq-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --bq-radius--none: 0;
  --bq-radius--xs2: 0.0625rem;
  --bq-radius--xs: 0.125rem;
  --bq-radius--s: 0.25rem;
  --bq-radius--m: 0.5rem;
  --bq-radius--l: 1rem;
  --bq-radius--full: 9999px;

  --bq-brand-light: #a8f0e6;
  --bq-brand: #00836e;
  --bq-brand-dark: #005a4f;

  --bq-accent-light: #e8d5f2;
  --bq-accent: #9d4edd;
  --bq-accent-dark: #5a189a;

  --bq-success-light: #a1e4cb;
  --bq-success: #05b981;
  --bq-success-dark: #047857;

  --bq-danger-light: #fecaca;
  --bq-danger: #ef4444;
  --bq-danger-dark: #991b1b;

  --bq-warning-light: #fef3c7;
  --bq-warning: #f59e0b;
  --bq-warning-dark: #92400e;

  --bq-info-light: #bfdbfe;
  --bq-info: #3b82f6;
  --bq-info-dark: #1e3a8a;

  --bq-focus: #00d9c4;

  --bq-white: #ffffff;
  --bq-black: #000000;

  --bq-neutral-50: #f9fafb;
  --bq-neutral-100: #f3f4f6;
  --bq-neutral-200: #e5e7eb;
  --bq-neutral-300: #d1d5db;
  --bq-neutral-400: #9ca3af;
  --bq-neutral-500: #6b7280;
  --bq-neutral-600: #4b5563;
  --bq-neutral-700: #374151;
  --bq-neutral-800: #1f2937;
  --bq-neutral-900: #111827;
  --bq-neutral-950: #0f172a;
  --bq-neutral-1000: #030712;
}

/* TechFlow — Light mode declarative tokens */

:host([bq-theme="techflow"]),
:host(.techflow) {

  --bq-background--primary: #030712;
  --bq-background--secondary: #0f172a;
  --bq-background--tertiary: #1f2937;
  --bq-background--alt: #374151;
  --bq-background--inverse: #f9fafb;
  --bq-background--brand: #009b88;
  --bq-background--overlay: rgba(0, 0, 0, 0.7);
  --bq-icon--primary: #f3f4f6;
  --bq-icon--secondary: #9ca3af;
  --bq-icon--inverse: #1f2937;
  --bq-icon--brand: #00d9c4;
  --bq-icon--alt: #ffffff;
  --bq-icon--info: #60a5fa;
  --bq-icon--success: #34d399;
  --bq-icon--warning: #fbbf24;
  --bq-icon--danger: #f87171;
  --bq-stroke--primary: #374151;
  --bq-stroke--secondary: #4b5563;
  --bq-stroke--tertiary: #9ca3af;
  --bq-stroke--inverse: #0f172a;
  --bq-stroke--brand: #00d9c4;
  --bq-stroke--alt: #1f2937;
  --bq-stroke--success: #34d399;
  --bq-stroke--warning: #fbbf24;
  --bq-stroke--danger: #f87171;
  --bq-text--primary: #f9fafb;
  --bq-text--secondary: #9ca3af;
  --bq-text--inverse: #1f2937;
  --bq-text--brand: #00d9c4;
  --bq-text--alt: #ffffff;
  --bq-text--info: #60a5fa;
  --bq-text--success: #34d399;
  --bq-text--warning: #fbbf24;
  --bq-text--danger: #f87171;
  --bq-ui--primary: #1f2937;
  --bq-ui--secondary: #374151;
  --bq-ui--tertiary: #4b5563;
  --bq-ui--inverse: #f9fafb;
  --bq-ui--brand: #00d9c4;
  --bq-ui--brand-alt: #009b88;
  --bq-ui--alt: #0f172a;
  --bq-ui--success: #34d399;
  --bq-ui--success-alt: #10b981;
  --bq-ui--warning: #fbbf24;
  --bq-ui--warning-alt: #f59e0b;
  --bq-ui--danger: #f87171;
  --bq-ui--danger-alt: #ef4444;

  --bq-state--hover: rgba(255, 255, 255, 0.1);
  --bq-state--active: rgba(255, 255, 255, 0.15);
}

/* TechFlow — Dark mode declarative tokens */

:host([bq-theme="techflow"][bq-mode="dark"]),
:host(.techflow.dark) {
  --bq-background--primary: #ffffff;
  --bq-background--secondary: #f9fafb;
  --bq-background--tertiary: #f3f4f6;
  --bq-background--alt: #e5e7eb;
  --bq-background--inverse: #111827;
  --bq-background--brand: #a8f0e6;
  --bq-background--overlay: rgba(0, 0, 0, 0.5);

  --bq-icon--primary: #1f2937;
  --bq-icon--secondary: #6b7280;
  --bq-icon--inverse: #f9fafb;
  --bq-icon--brand: #00836e;
  --bq-icon--alt: #ffffff;
  --bq-icon--info: #1d4ed8;
  --bq-icon--success: #047857;
  --bq-icon--warning: #92400e;
  --bq-icon--danger: #b91c1c;

  --bq-stroke--primary: #e5e7eb;
  --bq-stroke--secondary: #d1d5db;
  --bq-stroke--tertiary: #9ca3af;
  --bq-stroke--inverse: #ffffff;
  --bq-stroke--brand: #00836e;
  --bq-stroke--alt: #f3f4f6;
  --bq-stroke--success: #047857;
  --bq-stroke--warning: #92400e;
  --bq-stroke--danger: #b91c1c;

  --bq-text--primary: #111827;
  --bq-text--secondary: #6b7280;
  --bq-text--inverse: #f9fafb;
  --bq-text--brand: #00836e;
  --bq-text--alt: #ffffff;
  --bq-text--info: #1d4ed8;
  --bq-text--success: #047857;
  --bq-text--warning: #92400e;
  --bq-text--danger: #b91c1c;

  --bq-ui--primary: #ffffff;
  --bq-ui--secondary: #f3f4f6;
  --bq-ui--tertiary: #e5e7eb;
  --bq-ui--inverse: #111827;
  --bq-ui--brand: #00d9c4;
  --bq-ui--brand-alt: #a8f0e6;
  --bq-ui--alt: #f9fafb;
  --bq-ui--success: #05b981;
  --bq-ui--success-alt: #a1e4cb;
  --bq-ui--warning: #f59e0b;
  --bq-ui--warning-alt: #fef3c7;
  --bq-ui--danger: #ef4444;
  --bq-ui--danger-alt: #fecaca;

  --bq-state--hover: rgba(0, 0, 0, 0.08);
  --bq-state--active: rgba(0, 0, 0, 0.12);
}

:host {
  align-items: stretch !important;
  flex-direction: column !important;
  flex-flow: column nowrap !important;

  color: var(--bq-text--primary);
}

.toolbar {
  display: flex;
  justify-content: flex-end;
  margin-block-end: var(--bq-spacing-m);
}

.tab-panel {
  display: none;
  padding: var(--bq-spacing-l);

  &.active {
    display: block;
  }

  section {
    margin-block-start: var(--bq-spacing-l);
  }

  section h1,
  section h2 {
    margin-block-end: var(--bq-spacing-m);
  }
}
</style>

<div class="toolbar">
<bq-button id="theme-toggle" appearance="secondary" label="Toggle theme" only-icon>
  <bq-icon id="toggle-icon" name="sun"></bq-icon>
</bq-button>
</div>

<bq-tab-group value="home">
<bq-tab tab-id="home">
  <bq-icon name="house-line" slot="icon"></bq-icon>
  Home
</bq-tab>
<bq-tab tab-id="profile">
  <bq-icon name="user" slot="icon"></bq-icon>
  Profile
</bq-tab>
<bq-tab tab-id="settings">
  <bq-icon name="gear" slot="icon"></bq-icon>
  Settings
</bq-tab>
</bq-tab-group>

<div class="tab-panel active" id="home">
<h1>Hello BEEQ(ers)!</h1>
<p>
  This example shows how to create and apply a custom theme to
  <a class="bq-link" href="https://beeq.design/" target="_blank" rel="noopener noreferrer">
    BEEQ components
  </a>
  using CSS variables.
  Try toggling the theme and switching between tabs to see how the colors adapt across components and modes.
</p>
<section>
  <h2>Buttons</h2>
  <bq-button appearance="primary">Primary Button</bq-button>
  <bq-button appearance="secondary">Secondary Button</bq-button>
  <bq-button variant="danger">Delete</bq-button>
  <bq-button variant="ghost">Ghost</bq-button>
</section>
<section>
  <h2>Input</h2>
  <bq-input placeholder="Placeholder">
    <label slot="label">Input label</label>
  </bq-input>
</section>
</div>

<div class="tab-panel" id="profile">
<h1>Profile tab!</h1>
<span>
  You can check the logic added to the Tab component in the
  <code>index.ts</code> file.
</span>
</div>

<div class="tab-panel" id="settings">
<h1>Settings tab!</h1>
</div>

<script>
(() => {
  const hostBody = previewRoot.host;
  hostBody.setAttribute('bq-theme', 'techflow');
  hostBody.setAttribute('bq-mode', 'dark');

  const TAB_ACTIVE_CLASS = 'active';
  const bqTabElem = previewRoot.querySelector('bq-tab-group');
  const tabPanels = previewRoot.querySelectorAll('.tab-panel');

  const toggleBtn = previewRoot.querySelector('#theme-toggle');
  const toggleIcon = previewRoot.querySelector('#toggle-icon');

  bqTabElem?.addEventListener('bqChange', (event) => {
    if (!tabPanels.length) return;

    const activeTab = event.detail.value;
    if (!activeTab) return;

    tabPanels.forEach((tabPanel) => {
      tabPanel.classList.remove(TAB_ACTIVE_CLASS);
      if (tabPanel.id === activeTab) tabPanel.classList.add(TAB_ACTIVE_CLASS);
    });
  });

  toggleBtn?.addEventListener('bqClick', () => {
    const isDark = hostBody.getAttribute('bq-mode') === 'dark';
    hostBody.setAttribute('bq-mode', isDark ? 'light' : 'dark');

    if (!toggleIcon) return;

    toggleIcon.setAttribute('name', isDark ? 'moon' : 'sun');
  });
})();
</script>
`}
>
  <CodeGroup>
    ```css styles.css icon="css" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    /* -------------------------------------------------------------------------- */
    /* BASE THEME VARIABLES                                                       */
    /* -------------------------------------------------------------------------- */
    [bq-theme="techflow"],
    .techflow {
      --bq-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      --bq-brand-light: #a8f0e6;
      --bq-brand:       #00836e;
      --bq-brand-dark:  #005a4f;
      --bq-accent-light: #e8d5f2;
      --bq-accent:       #9d4edd;
      --bq-accent-dark:  #5a189a;
      --bq-success-light: #a1e4cb;
      --bq-success:       #05b981;
      --bq-success-dark:  #047857;
      --bq-danger-light:  #fecaca;
      --bq-danger:        #ef4444;
      --bq-danger-dark:   #991b1b;
      --bq-warning-light: #fef3c7;
      --bq-warning:       #f59e0b;
      --bq-warning-dark:  #92400e;
      --bq-info-light:    #bfdbfe;
      --bq-info:          #3b82f6;
      --bq-info-dark:     #1e3a8a;
      --bq-focus:         #00836e;
      --bq-white:         #ffffff;
      --bq-black:         #000000;
      --bq-neutral-50:    #f9fafb;
      --bq-neutral-100:   #f3f4f6;
      --bq-neutral-200:   #e5e7eb;
      --bq-neutral-300:   #d1d5db;
      --bq-neutral-400:   #9ca3af;
      --bq-neutral-500:   #6b7280;
      --bq-neutral-600:   #4b5563;
      --bq-neutral-700:   #374151;
      --bq-neutral-800:   #1f2937;
      --bq-neutral-900:   #111827;
      --bq-neutral-950:   #0f172a;
      --bq-neutral-1000:  #030712;
    }

    /* -------------------------------------------------------------------------- */
    /* LIGHT MODE                                                                 */
    /* -------------------------------------------------------------------------- */
    [bq-theme="techflow"]:not([bq-mode]),
    [bq-theme="techflow"][bq-mode="light"],
    .techflow:not([bq-mode]),
    .techflow.light {
      --bq-background--primary:   #ffffff;
      --bq-background--secondary: #f9fafb;
      --bq-background--tertiary:  #f3f4f6;
      --bq-background--alt:       #e5e7eb;
      --bq-background--inverse:   #111827;
      --bq-background--brand:     #a8f0e6;
      --bq-background--overlay:   rgba(0, 0, 0, 0.5);
      --bq-icon--primary:   #1f2937;
      --bq-icon--secondary: #6b7280;
      --bq-icon--inverse:   #f9fafb;
      --bq-icon--brand:     #00836e;
      --bq-icon--alt:       #ffffff;
      --bq-icon--info:      #1d4ed8;
      --bq-icon--success:   #047857;
      --bq-icon--warning:   #92400e;
      --bq-icon--danger:    #b91c1c;
      --bq-stroke--primary:   #e5e7eb;
      --bq-stroke--secondary: #d1d5db;
      --bq-stroke--tertiary:  #9ca3af;
      --bq-stroke--inverse:   #ffffff;
      --bq-stroke--brand:     #00836e;
      --bq-stroke--alt:       #f3f4f6;
      --bq-stroke--success:   #047857;
      --bq-stroke--warning:   #92400e;
      --bq-stroke--danger:    #b91c1c;
      --bq-text--primary:   #111827;
      --bq-text--secondary: #6b7280;
      --bq-text--inverse:   #f9fafb;
      --bq-text--brand:     #00836e;
      --bq-text--alt:       #ffffff;
      --bq-text--info:      #1d4ed8;
      --bq-text--success:   #047857;
      --bq-text--warning:   #92400e;
      --bq-text--danger:    #b91c1c;
      --bq-ui--primary:     #ffffff;
      --bq-ui--secondary:   #f3f4f6;
      --bq-ui--tertiary:    #e5e7eb;
      --bq-ui--inverse:     #111827;
      --bq-ui--brand:       #00836e;
      --bq-ui--brand-alt:   #a8f0e6;
      --bq-ui--alt:         #f9fafb;
      --bq-ui--success:     #047857;
      --bq-ui--success-alt: #a1e4cb;
      --bq-ui--warning:     #92400e;
      --bq-ui--warning-alt: #fef3c7;
      --bq-ui--danger:      #b91c1c;
      --bq-ui--danger-alt:  #fecaca;
      --bq-state--hover:    rgba(0, 0, 0, 0.08);
      --bq-state--active:   rgba(0, 0, 0, 0.12);
    }

    /* -------------------------------------------------------------------------- */
    /* DARK MODE                                                                  */
    /* -------------------------------------------------------------------------- */
    [bq-theme="techflow"][bq-mode="dark"],
    .techflow.dark {
      --bq-background--primary:   #030712;
      --bq-background--secondary: #0f172a;
      --bq-background--tertiary:  #1f2937;
      --bq-background--alt:       #374151;
      --bq-background--inverse:   #f9fafb;
      --bq-background--brand:     #009b88;
      --bq-background--overlay:   rgba(0, 0, 0, 0.7);
      --bq-icon--primary:   #f3f4f6;
      --bq-icon--secondary: #9ca3af;
      --bq-icon--inverse:   #1f2937;
      --bq-icon--brand:     #00d9c4;
      --bq-icon--alt:       #ffffff;
      --bq-icon--info:      #60a5fa;
      --bq-icon--success:   #34d399;
      --bq-icon--warning:   #fbbf24;
      --bq-icon--danger:    #f87171;
      --bq-stroke--primary:   #374151;
      --bq-stroke--secondary: #4b5563;
      --bq-stroke--tertiary:  #9ca3af;
      --bq-stroke--inverse:   #0f172a;
      --bq-stroke--brand:     #00d9c4;
      --bq-stroke--alt:       #1f2937;
      --bq-stroke--success:   #34d399;
      --bq-stroke--warning:   #fbbf24;
      --bq-stroke--danger:    #f87171;
      --bq-text--primary:   #f9fafb;
      --bq-text--secondary: #9ca3af;
      --bq-text--inverse:   #1f2937;
      --bq-text--brand:     #00d9c4;
      --bq-text--alt:       #ffffff;
      --bq-text--info:      #60a5fa;
      --bq-text--success:   #34d399;
      --bq-text--warning:   #fbbf24;
      --bq-text--danger:    #f87171;
      --bq-ui--primary:     #1f2937;
      --bq-ui--secondary:   #374151;
      --bq-ui--tertiary:    #4b5563;
      --bq-ui--inverse:     #f9fafb;
      --bq-ui--brand:       #00d9c4;
      --bq-ui--brand-alt:   #009b88;
      --bq-ui--alt:         #0f172a;
      --bq-ui--success:     #34d399;
      --bq-ui--success-alt: #10b981;
      --bq-ui--warning:     #fbbf24;
      --bq-ui--warning-alt: #f59e0b;
      --bq-ui--danger:      #f87171;
      --bq-ui--danger-alt:  #ef4444;
      --bq-state--hover:    rgba(255, 255, 255, 0.10);
      --bq-state--active:   rgba(255, 255, 255, 0.15);
    }
    ```

    ```html HTML icon="html5" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <!DOCTYPE html>
    <html lang="en" bq-theme="techflow" bq-mode="dark">
      <head>
        <link rel="stylesheet" href="path/to/beeq.css">
        <link rel="stylesheet" href="styles.css">
      </head>
      <body>
        <div class="toolbar">
          <bq-button appearance="secondary" label="Toggle theme" only-icon id="theme-toggle">
            <bq-icon id="toggle-icon" name="sun"></bq-icon>
          </bq-button>
        </div>

        <bq-tab-group value="home" id="tabs">
          <bq-tab tab-id="home">
            <bq-icon name="house-line" slot="icon"></bq-icon>
            Home
          </bq-tab>
          <bq-tab tab-id="profile">
            <bq-icon name="user" slot="icon"></bq-icon>
            Profile
          </bq-tab>
          <bq-tab tab-id="settings">
            <bq-icon name="gear" slot="icon"></bq-icon>
            Settings
          </bq-tab>
        </bq-tab-group>

        <div class="tab-panel active" id="home">
          <h1>Hello BEEQ(ers)!</h1>
          <p>
            This example shows how to create and apply a custom theme to
            <a class="bq-link" href="https://beeq.design/" target="_blank" rel="noopener noreferrer">
              BEEQ components
            </a>
            using CSS variables. Try toggling the theme and switching between tabs to see how the
            colors adapt across components and modes.
          </p>
          <section style="margin-block-start: var(--bq-spacing-l);">
            <h2>Buttons</h2>
            <bq-button appearance="primary">Primary Button</bq-button>
            <bq-button appearance="secondary">Secondary Button</bq-button>
            <bq-button variant="danger">Delete</bq-button>
            <bq-button variant="ghost">Ghost</bq-button>
          </section>
          <section style="margin-block-start: var(--bq-spacing-l);">
            <h2>Input</h2>
            <bq-input placeholder="Placeholder">
              <label slot="label">Input label</label>
            </bq-input>
          </section>
        </div>
        <div class="tab-panel" id="profile">
          <h1>Profile tab!</h1>
          <span>You can check the logic added to the Tab component in the <code>index.ts</code> file.</span>
        </div>
        <div class="tab-panel" id="settings">
          <h1>Settings tab!</h1>
        </div>

        <script type="module">
          const TAB_ACTIVE_CLASS = 'active';
          const bqTabElem = document.getElementById('tabs');
          const tabPanels = document.querySelectorAll('.tab-panel');
          const toggleBtn = document.getElementById('theme-toggle');
          const toggleIcon = document.getElementById('toggle-icon');

          bqTabElem?.addEventListener('bqChange', (event) => {
            const activeTab = event.detail.value;
            tabPanels.forEach((panel) => {
              panel.classList.toggle(TAB_ACTIVE_CLASS, panel.id === activeTab);
            });
          });

          toggleBtn?.addEventListener('bqClick', () => {
            const isNowLight = document.documentElement.getAttribute('bq-mode') !== 'light';
            document.documentElement.setAttribute('bq-mode', isNowLight ? 'light' : 'dark');
            if (toggleIcon) toggleIcon.setAttribute('name', isNowLight ? 'moon' : 'sun');
          });
        </script>
      </body>
    </html>
    ```

    ```tsx React icon="react" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { useState, useEffect } from "react";
    import { BqTabGroup, BqTab, BqIcon, BqButton, BqInput } from "@beeq/react";
    import "./styles.css";

    // In main.tsx, apply the TechFlow theme:
    // document.documentElement.setAttribute('bq-theme', 'techflow');

    export function TechFlowDemo() {
      const [activeTab, setActiveTab] = useState("home");
      const [isDark, setIsDark] = useState(true);

      useEffect(() => {
        document.documentElement.setAttribute("bq-mode", isDark ? "dark" : "light");
      }, [isDark]);

      function toggleTheme() {
        setIsDark((prev) => !prev);
      }

      return (
        <>
          <div className="toolbar">
            <BqButton appearance="secondary" label="Toggle theme" onlyIcon onBqClick={toggleTheme}>
              <BqIcon name={isDark ? "sun" : "moon"} />
            </BqButton>
          </div>

          <BqTabGroup
            value="home"
            onBqChange={(e: CustomEvent<{ value: string }>) => setActiveTab(e.detail.value)}
          >
            <BqTab tabId="home">
              <BqIcon name="house-line" slot="icon" />
              Home
            </BqTab>
            <BqTab tabId="profile">
              <BqIcon name="user" slot="icon" />
              Profile
            </BqTab>
            <BqTab tabId="settings">
              <BqIcon name="gear" slot="icon" />
              Settings
            </BqTab>
          </BqTabGroup>

          {activeTab === "home" && (
            <section>
              <h1>Hello BEEQ(ers)!</h1>
              <p>
                This example shows how to create and apply a custom theme to{" "}
                <a className="bq-link" href="https://beeq.design/" target="_blank" rel="noopener noreferrer">
                  BEEQ components
                </a>{" "}
                using CSS variables. Try toggling the theme and switching between tabs to see how the
                colors adapt across components and modes.
              </p>
              <section style={{ marginBlockStart: "var(--bq-spacing-l)" }}>
                <h2>Buttons</h2>
                <BqButton appearance="primary">Primary Button</BqButton>
                <BqButton appearance="secondary">Secondary Button</BqButton>
                <BqButton variant="danger">Delete</BqButton>
                <BqButton variant="ghost">Ghost</BqButton>
              </section>
              <section style={{ marginBlockStart: "var(--bq-spacing-l)" }}>
                <h2>Input</h2>
                <BqInput placeholder="Placeholder">
                  <label slot="label">Input label</label>
                </BqInput>
              </section>
            </section>
          )}
          {activeTab === "profile" && (
            <section>
              <h1>Profile tab!</h1>
              <span>
                You can check the logic added to the Tab component in the{" "}
                <code>index.ts</code> file.
              </span>
            </section>
          )}
          {activeTab === "settings" && <h1>Settings tab!</h1>}
        </>
      );
    }
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component, effect, inject, signal } from "@angular/core";
    import { DOCUMENT } from "@angular/common";
    import { BqTabGroup, BqTab, BqIcon, BqButton, BqInput } from "@beeq/angular/standalone";

    // Apply the TechFlow theme in main.ts:
    // document.documentElement.setAttribute('bq-theme', 'techflow');

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqTabGroup, BqTab, BqIcon, BqButton, BqInput],
      template: `
        <div class="toolbar">
          <bq-button appearance="secondary" label="Toggle theme" only-icon (bqClick)="toggleTheme()">
            <bq-icon [attr.name]="isDark() ? 'sun' : 'moon'"></bq-icon>
          </bq-button>
        </div>

        <bq-tab-group value="home" (bqChange)="onTabChange($event)">
          <bq-tab tab-id="home">
            <bq-icon name="house-line" slot="icon"></bq-icon>
            Home
          </bq-tab>
          <bq-tab tab-id="profile">
            <bq-icon name="user" slot="icon"></bq-icon>
            Profile
          </bq-tab>
          <bq-tab tab-id="settings">
            <bq-icon name="gear" slot="icon"></bq-icon>
            Settings
          </bq-tab>
        </bq-tab-group>

        @if (activeTab() === 'home') {
          <section>
            <h1>Hello BEEQ(ers)!</h1>
            <p>
              This example shows how to create and apply a custom theme to
              <a class="bq-link" href="https://beeq.design/" target="_blank" rel="noopener noreferrer">
                BEEQ components
              </a>
              using CSS variables. Try toggling the theme and switching between tabs to see how the
              colors adapt across components and modes.
            </p>
            <section style="margin-block-start: var(--bq-spacing-l);">
              <h2>Buttons</h2>
              <bq-button appearance="primary">Primary Button</bq-button>
              <bq-button appearance="secondary">Secondary Button</bq-button>
              <bq-button variant="danger">Delete</bq-button>
              <bq-button variant="ghost">Ghost</bq-button>
            </section>
            <section style="margin-block-start: var(--bq-spacing-l);">
              <h2>Input</h2>
              <bq-input placeholder="Placeholder">
                <label slot="label">Input label</label>
              </bq-input>
            </section>
          </section>
        }
        @if (activeTab() === 'profile') {
          <section>
            <h1>Profile tab!</h1>
            <span>You can check the logic added to the Tab component in the <code>index.ts</code> file.</span>
          </section>
        }
        @if (activeTab() === 'settings') {
          <h1>Settings tab!</h1>
        }
      `,
      styles: [`
        /* -------------------------------------------------------------------------- */
        /* BASE THEME VARIABLES                                                       */
        /* -------------------------------------------------------------------------- */
        [bq-theme="techflow"],
        .techflow {
          --bq-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
          --bq-brand-light: #a8f0e6;
          --bq-brand:       #00836e;
          --bq-brand-dark:  #005a4f;
          --bq-accent-light: #e8d5f2;
          --bq-accent:       #9d4edd;
          --bq-accent-dark:  #5a189a;
          --bq-success-light: #a1e4cb;
          --bq-success:       #05b981;
          --bq-success-dark:  #047857;
          --bq-danger-light:  #fecaca;
          --bq-danger:        #ef4444;
          --bq-danger-dark:   #991b1b;
          --bq-warning-light: #fef3c7;
          --bq-warning:       #f59e0b;
          --bq-warning-dark:  #92400e;
          --bq-info-light:    #bfdbfe;
          --bq-info:          #3b82f6;
          --bq-info-dark:     #1e3a8a;
          --bq-focus:         #00836e;
          --bq-white:         #ffffff;
          --bq-black:         #000000;
          --bq-neutral-50:    #f9fafb;
          --bq-neutral-100:   #f3f4f6;
          --bq-neutral-200:   #e5e7eb;
          --bq-neutral-300:   #d1d5db;
          --bq-neutral-400:   #9ca3af;
          --bq-neutral-500:   #6b7280;
          --bq-neutral-600:   #4b5563;
          --bq-neutral-700:   #374151;
          --bq-neutral-800:   #1f2937;
          --bq-neutral-900:   #111827;
          --bq-neutral-950:   #0f172a;
          --bq-neutral-1000:  #030712;
        }

        /* -------------------------------------------------------------------------- */
        /* LIGHT MODE                                                                 */
        /* -------------------------------------------------------------------------- */
        [bq-theme="techflow"]:not([bq-mode]),
        [bq-theme="techflow"][bq-mode="light"],
        .techflow:not([bq-mode]),
        .techflow.light {
          --bq-background--primary:   #ffffff;
          --bq-background--secondary: #f9fafb;
          --bq-background--tertiary:  #f3f4f6;
          --bq-background--alt:       #e5e7eb;
          --bq-background--inverse:   #111827;
          --bq-background--brand:     #a8f0e6;
          --bq-background--overlay:   rgba(0, 0, 0, 0.5);
          --bq-icon--primary:   #1f2937;
          --bq-icon--secondary: #6b7280;
          --bq-icon--inverse:   #f9fafb;
          --bq-icon--brand:     #00836e;
          --bq-icon--alt:       #ffffff;
          --bq-icon--info:      #1d4ed8;
          --bq-icon--success:   #047857;
          --bq-icon--warning:   #92400e;
          --bq-icon--danger:    #b91c1c;
          --bq-stroke--primary:   #e5e7eb;
          --bq-stroke--secondary: #d1d5db;
          --bq-stroke--tertiary:  #9ca3af;
          --bq-stroke--inverse:   #ffffff;
          --bq-stroke--brand:     #00836e;
          --bq-stroke--alt:       #f3f4f6;
          --bq-stroke--success:   #047857;
          --bq-stroke--warning:   #92400e;
          --bq-stroke--danger:    #b91c1c;
          --bq-text--primary:   #111827;
          --bq-text--secondary: #6b7280;
          --bq-text--inverse:   #f9fafb;
          --bq-text--brand:     #00836e;
          --bq-text--alt:       #ffffff;
          --bq-text--info:      #1d4ed8;
          --bq-text--success:   #047857;
          --bq-text--warning:   #92400e;
          --bq-text--danger:    #b91c1c;
          --bq-ui--primary:     #ffffff;
          --bq-ui--secondary:   #f3f4f6;
          --bq-ui--tertiary:    #e5e7eb;
          --bq-ui--inverse:     #111827;
          --bq-ui--brand:       #00836e;
          --bq-ui--brand-alt:   #a8f0e6;
          --bq-ui--alt:         #f9fafb;
          --bq-ui--success:     #047857;
          --bq-ui--success-alt: #a1e4cb;
          --bq-ui--warning:     #92400e;
          --bq-ui--warning-alt: #fef3c7;
          --bq-ui--danger:      #b91c1c;
          --bq-ui--danger-alt:  #fecaca;
          --bq-state--hover:    rgba(0, 0, 0, 0.08);
          --bq-state--active:   rgba(0, 0, 0, 0.12);
        }

        /* -------------------------------------------------------------------------- */
        /* DARK MODE                                                                  */
        /* -------------------------------------------------------------------------- */
        [bq-theme="techflow"][bq-mode="dark"],
        .techflow.dark {
          --bq-background--primary:   #030712;
          --bq-background--secondary: #0f172a;
          --bq-background--tertiary:  #1f2937;
          --bq-background--alt:       #374151;
          --bq-background--inverse:   #f9fafb;
          --bq-background--brand:     #009b88;
          --bq-background--overlay:   rgba(0, 0, 0, 0.7);
          --bq-icon--primary:   #f3f4f6;
          --bq-icon--secondary: #9ca3af;
          --bq-icon--inverse:   #1f2937;
          --bq-icon--brand:     #00d9c4;
          --bq-icon--alt:       #ffffff;
          --bq-icon--info:      #60a5fa;
          --bq-icon--success:   #34d399;
          --bq-icon--warning:   #fbbf24;
          --bq-icon--danger:    #f87171;
          --bq-stroke--primary:   #374151;
          --bq-stroke--secondary: #4b5563;
          --bq-stroke--tertiary:  #9ca3af;
          --bq-stroke--inverse:   #0f172a;
          --bq-stroke--brand:     #00d9c4;
          --bq-stroke--alt:       #1f2937;
          --bq-stroke--success:   #34d399;
          --bq-stroke--warning:   #fbbf24;
          --bq-stroke--danger:    #f87171;
          --bq-text--primary:   #f9fafb;
          --bq-text--secondary: #9ca3af;
          --bq-text--inverse:   #1f2937;
          --bq-text--brand:     #00d9c4;
          --bq-text--alt:       #ffffff;
          --bq-text--info:      #60a5fa;
          --bq-text--success:   #34d399;
          --bq-text--warning:   #fbbf24;
          --bq-text--danger:    #f87171;
          --bq-ui--primary:     #1f2937;
          --bq-ui--secondary:   #374151;
          --bq-ui--tertiary:    #4b5563;
          --bq-ui--inverse:     #f9fafb;
          --bq-ui--brand:       #00d9c4;
          --bq-ui--brand-alt:   #009b88;
          --bq-ui--alt:         #0f172a;
          --bq-ui--success:     #34d399;
          --bq-ui--success-alt: #10b981;
          --bq-ui--warning:     #fbbf24;
          --bq-ui--warning-alt: #f59e0b;
          --bq-ui--danger:      #f87171;
          --bq-ui--danger-alt:  #ef4444;
          --bq-state--hover:    rgba(255, 255, 255, 0.10);
          --bq-state--active:   rgba(255, 255, 255, 0.15);
        }
      `],
    })
    export class AppComponent {
      private readonly document = inject(DOCUMENT);
      readonly activeTab = signal('home');
      readonly isDark = signal(true);

      constructor() {
        effect(() => {
          this.document.documentElement.setAttribute('bq-mode', this.isDark() ? 'dark' : 'light');
        });
      }

      onTabChange(event: CustomEvent<{ value: string }>) {
        this.activeTab.set(event.detail.value);
      }

      toggleTheme() {
        this.isDark.update((prev) => !prev);
      }
    }
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
      import { ref, watchEffect } from "vue";
      import { BqTabGroup, BqTab, BqIcon, BqButton, BqInput } from "@beeq/vue";

      // In main.ts, apply the TechFlow theme:
      // document.documentElement.setAttribute('bq-theme', 'techflow');

      const activeTab = ref("home");
      const isDark = ref(true);

      watchEffect(() => {
        document.documentElement.setAttribute("bq-mode", isDark.value ? "dark" : "light");
      });

      function onTabChange(event: CustomEvent<{ value: string }>) {
        activeTab.value = event.detail.value;
      }

      function toggleTheme() {
        isDark.value = !isDark.value;
      }
    </script>

    <template>
      <div class="toolbar">
        <BqButton appearance="secondary" label="Toggle theme" only-icon @bqClick="toggleTheme">
          <BqIcon :name="isDark ? 'sun' : 'moon'" />
        </BqButton>
      </div>

      <BqTabGroup value="home" @bqChange="onTabChange">
        <BqTab tabId="home">
          <BqIcon name="house-line" slot="icon" />
          Home
        </BqTab>
        <BqTab tabId="profile">
          <BqIcon name="user" slot="icon" />
          Profile
        </BqTab>
        <BqTab tabId="settings">
          <BqIcon name="gear" slot="icon" />
          Settings
        </BqTab>
      </BqTabGroup>

      <section v-if="activeTab === 'home'">
        <h1>Hello BEEQ(ers)!</h1>
        <p>
          This example shows how to create and apply a custom theme to
          <a class="bq-link" href="https://beeq.design/" target="_blank" rel="noopener noreferrer">
            BEEQ components
          </a>
          using CSS variables. Try toggling the theme and switching between tabs to see how the
          colors adapt across components and modes.
        </p>
        <section style="margin-block-start: var(--bq-spacing-l);">
          <h2>Buttons</h2>
          <BqButton appearance="primary">Primary Button</BqButton>
          <BqButton appearance="secondary">Secondary Button</BqButton>
          <BqButton variant="danger">Delete</BqButton>
          <BqButton variant="ghost">Ghost</BqButton>
        </section>
        <section style="margin-block-start: var(--bq-spacing-l);">
          <h2>Input</h2>
          <BqInput placeholder="Placeholder">
            <label slot="label">Input label</label>
          </BqInput>
        </section>
      </section>
      <section v-if="activeTab === 'profile'">
        <h1>Profile tab!</h1>
        <span>You can check the logic added to the Tab component in the <code>index.ts</code> file.</span>
      </section>
      <h1 v-if="activeTab === 'settings'">Settings tab!</h1>
    </template>

    <style>
      /* -------------------------------------------------------------------------- */
      /* BASE THEME VARIABLES                                                       */
      /* -------------------------------------------------------------------------- */
      [bq-theme="techflow"],
      .techflow {
        --bq-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
        --bq-brand-light: #a8f0e6;
        --bq-brand:       #00836e;
        --bq-brand-dark:  #005a4f;
        --bq-accent-light: #e8d5f2;
        --bq-accent:       #9d4edd;
        --bq-accent-dark:  #5a189a;
        --bq-success-light: #a1e4cb;
        --bq-success:       #05b981;
        --bq-success-dark:  #047857;
        --bq-danger-light:  #fecaca;
        --bq-danger:        #ef4444;
        --bq-danger-dark:   #991b1b;
        --bq-warning-light: #fef3c7;
        --bq-warning:       #f59e0b;
        --bq-warning-dark:  #92400e;
        --bq-info-light:    #bfdbfe;
        --bq-info:          #3b82f6;
        --bq-info-dark:     #1e3a8a;
        --bq-focus:         #00836e;
        --bq-white:         #ffffff;
        --bq-black:         #000000;
        --bq-neutral-50:    #f9fafb;
        --bq-neutral-100:   #f3f4f6;
        --bq-neutral-200:   #e5e7eb;
        --bq-neutral-300:   #d1d5db;
        --bq-neutral-400:   #9ca3af;
        --bq-neutral-500:   #6b7280;
        --bq-neutral-600:   #4b5563;
        --bq-neutral-700:   #374151;
        --bq-neutral-800:   #1f2937;
        --bq-neutral-900:   #111827;
        --bq-neutral-950:   #0f172a;
        --bq-neutral-1000:  #030712;
      }

      /* -------------------------------------------------------------------------- */
      /* LIGHT MODE                                                                 */
      /* -------------------------------------------------------------------------- */
      [bq-theme="techflow"]:not([bq-mode]),
      [bq-theme="techflow"][bq-mode="light"],
      .techflow:not([bq-mode]),
      .techflow.light {
        --bq-background--primary:   #ffffff;
        --bq-background--secondary: #f9fafb;
        --bq-background--tertiary:  #f3f4f6;
        --bq-background--alt:       #e5e7eb;
        --bq-background--inverse:   #111827;
        --bq-background--brand:     #a8f0e6;
        --bq-background--overlay:   rgba(0, 0, 0, 0.5);
        --bq-icon--primary:   #1f2937;
        --bq-icon--secondary: #6b7280;
        --bq-icon--inverse:   #f9fafb;
        --bq-icon--brand:     #00836e;
        --bq-icon--alt:       #ffffff;
        --bq-icon--info:      #1d4ed8;
        --bq-icon--success:   #047857;
        --bq-icon--warning:   #92400e;
        --bq-icon--danger:    #b91c1c;
        --bq-stroke--primary:   #e5e7eb;
        --bq-stroke--secondary: #d1d5db;
        --bq-stroke--tertiary:  #9ca3af;
        --bq-stroke--inverse:   #ffffff;
        --bq-stroke--brand:     #00836e;
        --bq-stroke--alt:       #f3f4f6;
        --bq-stroke--success:   #047857;
        --bq-stroke--warning:   #92400e;
        --bq-stroke--danger:    #b91c1c;
        --bq-text--primary:   #111827;
        --bq-text--secondary: #6b7280;
        --bq-text--inverse:   #f9fafb;
        --bq-text--brand:     #00836e;
        --bq-text--alt:       #ffffff;
        --bq-text--info:      #1d4ed8;
        --bq-text--success:   #047857;
        --bq-text--warning:   #92400e;
        --bq-text--danger:    #b91c1c;
        --bq-ui--primary:     #ffffff;
        --bq-ui--secondary:   #f3f4f6;
        --bq-ui--tertiary:    #e5e7eb;
        --bq-ui--inverse:     #111827;
        --bq-ui--brand:       #00836e;
        --bq-ui--brand-alt:   #a8f0e6;
        --bq-ui--alt:         #f9fafb;
        --bq-ui--success:     #047857;
        --bq-ui--success-alt: #a1e4cb;
        --bq-ui--warning:     #92400e;
        --bq-ui--warning-alt: #fef3c7;
        --bq-ui--danger:      #b91c1c;
        --bq-ui--danger-alt:  #fecaca;
        --bq-state--hover:    rgba(0, 0, 0, 0.08);
        --bq-state--active:   rgba(0, 0, 0, 0.12);
      }

      /* -------------------------------------------------------------------------- */
      /* DARK MODE                                                                  */
      /* -------------------------------------------------------------------------- */
      [bq-theme="techflow"][bq-mode="dark"],
      .techflow.dark {
        --bq-background--primary:   #030712;
        --bq-background--secondary: #0f172a;
        --bq-background--tertiary:  #1f2937;
        --bq-background--alt:       #374151;
        --bq-background--inverse:   #f9fafb;
        --bq-background--brand:     #009b88;
        --bq-background--overlay:   rgba(0, 0, 0, 0.7);
        --bq-icon--primary:   #f3f4f6;
        --bq-icon--secondary: #9ca3af;
        --bq-icon--inverse:   #1f2937;
        --bq-icon--brand:     #00d9c4;
        --bq-icon--alt:       #ffffff;
        --bq-icon--info:      #60a5fa;
        --bq-icon--success:   #34d399;
        --bq-icon--warning:   #fbbf24;
        --bq-icon--danger:    #f87171;
        --bq-stroke--primary:   #374151;
        --bq-stroke--secondary: #4b5563;
        --bq-stroke--tertiary:  #9ca3af;
        --bq-stroke--inverse:   #0f172a;
        --bq-stroke--brand:     #00d9c4;
        --bq-stroke--alt:       #1f2937;
        --bq-stroke--success:   #34d399;
        --bq-stroke--warning:   #fbbf24;
        --bq-stroke--danger:    #f87171;
        --bq-text--primary:   #f9fafb;
        --bq-text--secondary: #9ca3af;
        --bq-text--inverse:   #1f2937;
        --bq-text--brand:     #00d9c4;
        --bq-text--alt:       #ffffff;
        --bq-text--info:      #60a5fa;
        --bq-text--success:   #34d399;
        --bq-text--warning:   #fbbf24;
        --bq-text--danger:    #f87171;
        --bq-ui--primary:     #1f2937;
        --bq-ui--secondary:   #374151;
        --bq-ui--tertiary:    #4b5563;
        --bq-ui--inverse:     #f9fafb;
        --bq-ui--brand:       #00d9c4;
        --bq-ui--brand-alt:   #009b88;
        --bq-ui--alt:         #0f172a;
        --bq-ui--success:     #34d399;
        --bq-ui--success-alt: #10b981;
        --bq-ui--warning:     #fbbf24;
        --bq-ui--warning-alt: #f59e0b;
        --bq-ui--danger:      #f87171;
        --bq-ui--danger-alt:  #ef4444;
        --bq-state--hover:    rgba(255, 255, 255, 0.10);
        --bq-state--active:   rgba(255, 255, 255, 0.15);
      }
    </style>
    ```
  </CodeGroup>
</CodeLivePreview>
