{"version":3,"sources":["../src/ui/theme/theme.ts"],"sourcesContent":["import type { Theme } from \"../tokens/types.js\"\n\nconst STORAGE_KEY = \"cs-theme\"\nconst DATA_ATTR = \"data-theme\"\n\n/**\n * Get the current theme setting.\n * Returns `\"light\"`, `\"dark\"`, or `\"system\"` (when no `data-theme` attribute is set).\n */\nexport function getTheme(): Theme {\n  if (typeof document === \"undefined\") return \"system\"\n  const attr = document.documentElement.getAttribute(DATA_ATTR)\n  if (attr === \"light\" || attr === \"dark\") return attr\n  return \"system\"\n}\n\n/**\n * Set the theme. Applies `data-theme` attribute to `<html>` and\n * persists the choice to `localStorage`.\n *\n * - `\"light\"` or `\"dark\"` sets the attribute explicitly.\n * - `\"system\"` removes the attribute, deferring to `prefers-color-scheme`.\n */\nexport function setTheme(theme: Theme): void {\n  if (typeof document === \"undefined\") return\n\n  if (theme === \"system\") {\n    document.documentElement.removeAttribute(DATA_ATTR)\n  } else {\n    document.documentElement.setAttribute(DATA_ATTR, theme)\n  }\n\n  try {\n    if (typeof localStorage !== \"undefined\") {\n      localStorage.setItem(STORAGE_KEY, theme)\n    }\n  } catch {\n    // localStorage may be unavailable (e.g., iframe sandboxing)\n  }\n}\n\n/**\n * Initialize the theme from `localStorage` on page load.\n * Call this early (e.g., in a `<script>` tag or app init) to\n * prevent a flash of wrong theme.\n */\nexport function initTheme(): void {\n  try {\n    if (typeof localStorage === \"undefined\") return\n    const stored = localStorage.getItem(STORAGE_KEY)\n    if (stored === \"light\" || stored === \"dark\" || stored === \"system\") {\n      setTheme(stored)\n    }\n  } catch {\n    // localStorage may be unavailable\n  }\n}\n\n/**\n * Subscribe to theme changes (both programmatic and OS-level).\n * Returns an unsubscribe function.\n */\nexport function onThemeChange(callback: (theme: Theme) => void): () => void {\n  if (typeof window === \"undefined\") return () => {}\n\n  const observer = new MutationObserver(() => {\n    callback(getTheme())\n  })\n\n  observer.observe(document.documentElement, {\n    attributes: true,\n    attributeFilter: [DATA_ATTR],\n  })\n\n  let mediaQuery: MediaQueryList | undefined\n  const mediaHandler = () => {\n    if (getTheme() === \"system\") {\n      callback(\"system\")\n    }\n  }\n\n  if (typeof window.matchMedia === \"function\") {\n    mediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\")\n    mediaQuery.addEventListener(\"change\", mediaHandler)\n  }\n\n  return () => {\n    observer.disconnect()\n    mediaQuery?.removeEventListener(\"change\", mediaHandler)\n  }\n}\n\n/**\n * Get the resolved effective theme (never `\"system\"`).\n * Useful when you need to know the actual visual appearance.\n */\nexport function getEffectiveTheme(): \"light\" | \"dark\" {\n  const theme = getTheme()\n  if (theme !== \"system\") return theme\n\n  if (typeof window !== \"undefined\" && typeof window.matchMedia === \"function\") {\n    return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\"\n  }\n  return \"light\"\n}\n"],"mappings":";AAEA,IAAM,cAAc;AACpB,IAAM,YAAY;AAMX,SAAS,WAAkB;AAChC,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,QAAM,OAAO,SAAS,gBAAgB,aAAa,SAAS;AAC5D,MAAI,SAAS,WAAW,SAAS,OAAQ,QAAO;AAChD,SAAO;AACT;AASO,SAAS,SAAS,OAAoB;AAC3C,MAAI,OAAO,aAAa,YAAa;AAErC,MAAI,UAAU,UAAU;AACtB,aAAS,gBAAgB,gBAAgB,SAAS;AAAA,EACpD,OAAO;AACL,aAAS,gBAAgB,aAAa,WAAW,KAAK;AAAA,EACxD;AAEA,MAAI;AACF,QAAI,OAAO,iBAAiB,aAAa;AACvC,mBAAa,QAAQ,aAAa,KAAK;AAAA,IACzC;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAOO,SAAS,YAAkB;AAChC,MAAI;AACF,QAAI,OAAO,iBAAiB,YAAa;AACzC,UAAM,SAAS,aAAa,QAAQ,WAAW;AAC/C,QAAI,WAAW,WAAW,WAAW,UAAU,WAAW,UAAU;AAClE,eAAS,MAAM;AAAA,IACjB;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAMO,SAAS,cAAc,UAA8C;AAC1E,MAAI,OAAO,WAAW,YAAa,QAAO,MAAM;AAAA,EAAC;AAEjD,QAAM,WAAW,IAAI,iBAAiB,MAAM;AAC1C,aAAS,SAAS,CAAC;AAAA,EACrB,CAAC;AAED,WAAS,QAAQ,SAAS,iBAAiB;AAAA,IACzC,YAAY;AAAA,IACZ,iBAAiB,CAAC,SAAS;AAAA,EAC7B,CAAC;AAED,MAAI;AACJ,QAAM,eAAe,MAAM;AACzB,QAAI,SAAS,MAAM,UAAU;AAC3B,eAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AAEA,MAAI,OAAO,OAAO,eAAe,YAAY;AAC3C,iBAAa,OAAO,WAAW,8BAA8B;AAC7D,eAAW,iBAAiB,UAAU,YAAY;AAAA,EACpD;AAEA,SAAO,MAAM;AACX,aAAS,WAAW;AACpB,gBAAY,oBAAoB,UAAU,YAAY;AAAA,EACxD;AACF;AAMO,SAAS,oBAAsC;AACpD,QAAM,QAAQ,SAAS;AACvB,MAAI,UAAU,SAAU,QAAO;AAE/B,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,eAAe,YAAY;AAC5E,WAAO,OAAO,WAAW,8BAA8B,EAAE,UAAU,SAAS;AAAA,EAC9E;AACA,SAAO;AACT;","names":[]}