{"version":3,"file":"consent.js","mappings":"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","sources":["webpack:///./node_modules/@babel/runtime/helpers/asyncToGenerator.js","webpack:///./node_modules/@babel/runtime/helpers/interopRequireDefault.js","webpack:///./src/consent/consent.ts","webpack:///./src/consent/consentBanner.ts","webpack:///./src/consent/trackers.ts","webpack:///webpack/bootstrap","webpack:///./src/consent/consentEntry.ts"],"sourcesContent":["function asyncGeneratorStep(n, t, e, r, o, a, c) {\n  try {\n    var i = n[a](c),\n      u = i.value;\n  } catch (n) {\n    return void e(n);\n  }\n  i.done ? t(u) : Promise.resolve(u).then(r, o);\n}\nfunction _asyncToGenerator(n) {\n  return function () {\n    var t = this,\n      e = arguments;\n    return new Promise(function (r, o) {\n      var a = n.apply(t, e);\n      function _next(n) {\n        asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n);\n      }\n      function _throw(n) {\n        asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n);\n      }\n      _next(void 0);\n    });\n  };\n}\nmodule.exports = _asyncToGenerator, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","function _interopRequireDefault(e) {\n  return e && e.__esModule ? e : {\n    \"default\": e\n  };\n}\nmodule.exports = _interopRequireDefault, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","export type IConsentMode = \"optin\" | \"optout\" | \"none\";\n\nexport interface IConsentCategories {\n  analytics: boolean;\n  advertising: boolean;\n}\n\nexport interface IConsentDecision extends IConsentCategories {\n  needsBanner: boolean;\n}\n\ninterface IStoredConsent extends IConsentCategories {\n  v: number;\n  ts: number;\n}\n\nconst STORAGE_KEY = \"lft_consent_v1\";\nconst GEO_CACHE_KEY = \"lft_consent_geo\";\nconst CONSENT_VERSION = 1;\nconst GEO_CACHE_MS = 7 * 24 * 60 * 60 * 1000;\n\nexport function Consent_getStored(): IConsentCategories | undefined {\n  try {\n    const raw = window.localStorage.getItem(STORAGE_KEY);\n    if (!raw) {\n      return undefined;\n    }\n    const parsed = JSON.parse(raw) as IStoredConsent;\n    if (parsed.v !== CONSENT_VERSION) {\n      return undefined;\n    }\n    return { analytics: !!parsed.analytics, advertising: !!parsed.advertising };\n  } catch {\n    return undefined;\n  }\n}\n\nexport function Consent_store(categories: IConsentCategories): void {\n  try {\n    const value: IStoredConsent = { v: CONSENT_VERSION, ts: Date.now(), ...categories };\n    window.localStorage.setItem(STORAGE_KEY, JSON.stringify(value));\n  } catch {\n    // ignore - storage may be unavailable (private mode); consent just won't persist\n  }\n}\n\nexport function Consent_hasGPC(): boolean {\n  return (navigator as unknown as { globalPrivacyControl?: boolean }).globalPrivacyControl === true;\n}\n\nexport async function Consent_getMode(): Promise<IConsentMode> {\n  try {\n    const cachedRaw = window.localStorage.getItem(GEO_CACHE_KEY);\n    if (cachedRaw) {\n      const cached = JSON.parse(cachedRaw) as { mode: IConsentMode; ts: number };\n      if (Date.now() - cached.ts < GEO_CACHE_MS) {\n        return cached.mode;\n      }\n    }\n  } catch {\n    // fall through to fetch\n  }\n  try {\n    const res = await fetch(\"/api/geo\", { credentials: \"omit\" });\n    const json = (await res.json()) as { consentMode: IConsentMode };\n    const mode = json.consentMode === \"optin\" || json.consentMode === \"none\" ? json.consentMode : \"optout\";\n    try {\n      window.localStorage.setItem(GEO_CACHE_KEY, JSON.stringify({ mode, ts: Date.now() }));\n    } catch {\n      // ignore\n    }\n    return mode;\n  } catch {\n    return \"optout\";\n  }\n}\n\nexport function Consent_resolve(\n  mode: IConsentMode,\n  stored: IConsentCategories | undefined,\n  gpc: boolean\n): IConsentDecision {\n  if (stored) {\n    return { analytics: stored.analytics, advertising: stored.advertising && !gpc, needsBanner: false };\n  }\n  if (mode === \"optin\") {\n    return { analytics: false, advertising: false, needsBanner: true };\n  }\n  // optout / none: trackers default on, but GPC opts out of advertising and no banner blocks the page.\n  return { analytics: true, advertising: !gpc, needsBanner: false };\n}\n","import { IConsentCategories, IConsentMode } from \"./consent\";\n\n// Self-contained vanilla DOM so it behaves identically on SSR pages and the /app PWA and can't be\n// blocked by React hydration timing. Styling is intentionally minimal/inline - design later.\n\ntype IChoiceHandler = (categories: IConsentCategories) => void;\n\nconst Z = 2147483600;\n\nfunction el(tag: string, style: Partial<CSSStyleDeclaration>, text?: string): HTMLElement {\n  const node = document.createElement(tag);\n  Object.assign(node.style, style);\n  if (text != null) {\n    node.textContent = text;\n  }\n  return node;\n}\n\nfunction button(label: string, primary: boolean): HTMLButtonElement {\n  return el(\n    \"button\",\n    {\n      cursor: \"pointer\",\n      padding: \"10px 16px\",\n      borderRadius: \"8px\",\n      fontSize: \"14px\",\n      fontWeight: \"600\",\n      border: primary ? \"none\" : \"1px solid var(--color-border-prominent)\",\n      background: primary ? \"var(--color-button-primarybackground)\" : \"var(--color-button-secondarybackground)\",\n      color: primary ? \"var(--color-button-primarylabel)\" : \"var(--color-text-primary)\",\n    },\n    label\n  ) as HTMLButtonElement;\n}\n\nfunction remove(node: HTMLElement | null): void {\n  if (node && node.parentNode) {\n    node.parentNode.removeChild(node);\n  }\n}\n\nfunction buildPreferences(current: IConsentCategories, onSave: IChoiceHandler): HTMLElement {\n  const overlay = el(\"div\", {\n    position: \"fixed\",\n    inset: \"0\",\n    background: \"rgba(0,0,0,0.4)\",\n    zIndex: String(Z + 1),\n    display: \"flex\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    padding: \"16px\",\n  });\n  const card = el(\"div\", {\n    background: \"var(--color-background-default)\",\n    borderRadius: \"12px\",\n    border: \"1px solid var(--color-border-prominent)\",\n    maxWidth: \"440px\",\n    width: \"100%\",\n    padding: \"20px\",\n    boxShadow: \"0 10px 40px rgba(0,0,0,0.2)\",\n    fontFamily: \"sans-serif\",\n    color: \"var(--color-text-primary)\",\n  });\n  card.addEventListener(\"click\", (e) => e.stopPropagation());\n  overlay.addEventListener(\"click\", () => remove(overlay));\n\n  const header = el(\"div\", {\n    display: \"flex\",\n    alignItems: \"center\",\n    justifyContent: \"space-between\",\n    marginBottom: \"8px\",\n  });\n  header.appendChild(el(\"div\", { fontSize: \"18px\", fontWeight: \"700\" }, \"Privacy preferences\"));\n  const close = el(\n    \"button\",\n    {\n      background: \"none\",\n      border: \"none\",\n      fontSize: \"22px\",\n      lineHeight: \"1\",\n      cursor: \"pointer\",\n      color: \"var(--color-text-secondary)\",\n      padding: \"0 4px\",\n    },\n    \"×\"\n  );\n  close.setAttribute(\"aria-label\", \"Close\");\n  close.addEventListener(\"click\", () => remove(overlay));\n  header.appendChild(close);\n  card.appendChild(header);\n\n  const state: IConsentCategories = { analytics: current.analytics, advertising: current.advertising };\n  const rows: Array<{ key: \"analytics\" | \"advertising\"; title: string; desc: string }> = [\n    {\n      key: \"analytics\",\n      title: \"Analytics\",\n      desc: \"Helps us understand usage and how people find us (Google Analytics).\",\n    },\n    {\n      key: \"advertising\",\n      title: \"Advertising\",\n      desc: \"Measures how ads bring people to the app (Reddit Ads, Google Ads, etc).\",\n    },\n  ];\n  for (const row of rows) {\n    const wrap = el(\"label\", {\n      display: \"flex\",\n      gap: \"10px\",\n      alignItems: \"flex-start\",\n      padding: \"10px 0\",\n      borderTop: \"1px solid var(--color-border-subtle)\",\n      cursor: \"pointer\",\n    });\n    const cb = el(\"input\", { marginTop: \"3px\" }) as HTMLInputElement;\n    cb.type = \"checkbox\";\n    cb.checked = state[row.key];\n    cb.addEventListener(\"change\", () => {\n      state[row.key] = cb.checked;\n    });\n    const txt = el(\"div\", {});\n    txt.appendChild(el(\"div\", { fontWeight: \"600\", fontSize: \"14px\" }, row.title));\n    txt.appendChild(el(\"div\", { fontSize: \"12px\", color: \"var(--color-text-secondary)\" }, row.desc));\n    wrap.appendChild(cb);\n    wrap.appendChild(txt);\n    card.appendChild(wrap);\n  }\n\n  const actions = el(\"div\", { display: \"flex\", gap: \"8px\", justifyContent: \"flex-end\", marginTop: \"16px\" });\n  const save = button(\"Save choices\", true);\n  save.addEventListener(\"click\", () => {\n    remove(overlay);\n    onSave(state);\n  });\n  actions.appendChild(save);\n  card.appendChild(actions);\n  overlay.appendChild(card);\n  return overlay;\n}\n\nexport function ConsentBanner_openPreferences(current: IConsentCategories, onSave: IChoiceHandler): void {\n  document.body.appendChild(buildPreferences(current, onSave));\n}\n\nexport function ConsentBanner_showBanner(mode: IConsentMode, onChoice: IChoiceHandler): void {\n  const bar = el(\"div\", {\n    position: \"fixed\",\n    left: \"0\",\n    right: \"0\",\n    bottom: \"0\",\n    zIndex: String(Z),\n    background: \"var(--color-background-default)\",\n    borderTop: \"1px solid var(--color-border-prominent)\",\n    boxShadow: \"0 -4px 20px rgba(0,0,0,0.1)\",\n    padding: \"16px\",\n    display: \"flex\",\n    flexWrap: \"wrap\",\n    gap: \"12px\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    fontFamily: \"sans-serif\",\n  });\n  const text = el(\n    \"div\",\n    { flex: \"1 1 280px\", minWidth: \"240px\", fontSize: \"13px\", color: \"var(--color-text-primary)\", lineHeight: \"1.4\" },\n    \"Liftosaur uses cookies for analytics and to measure how our pages and ads bring people to the app. \"\n  );\n  const links = el(\"span\", {});\n  const policy = el(\n    \"a\",\n    { color: \"var(--color-text-link)\", textDecoration: \"underline\" },\n    \"Privacy Policy\"\n  ) as HTMLAnchorElement;\n  policy.href = \"/privacy.html\";\n  links.appendChild(policy);\n  text.appendChild(links);\n\n  const actions = el(\"div\", { display: \"flex\", gap: \"8px\", flexWrap: \"wrap\" });\n  const reject = button(\"Reject all\", false);\n  const manage = button(\"Manage\", false);\n  const accept = button(\"Accept all\", true);\n  reject.addEventListener(\"click\", () => {\n    remove(bar);\n    onChoice({ analytics: false, advertising: false });\n  });\n  accept.addEventListener(\"click\", () => {\n    remove(bar);\n    onChoice({ analytics: true, advertising: true });\n  });\n  manage.addEventListener(\"click\", () => {\n    ConsentBanner_openPreferences({ analytics: false, advertising: false }, (cats) => {\n      remove(bar);\n      onChoice(cats);\n    });\n  });\n  actions.appendChild(reject);\n  actions.appendChild(manage);\n  actions.appendChild(accept);\n\n  bar.appendChild(text);\n  bar.appendChild(actions);\n  document.body.appendChild(bar);\n}\n","// Activates the trackers held back until consent. gtag's library is always loaded (with Consent Mode\n// defaulted to denied in the page head), so consent is a gtag \"update\". Analytics covers GA and the\n// first-party landing-page cookie; advertising covers the Reddit pixel, Google Ads signals, and UTM.\n\nimport { IConsentCategories } from \"./consent\";\n\ninterface IGtagWindow {\n  gtag?: (...args: unknown[]) => void;\n  rdt?: (...args: unknown[]) => void;\n}\n\nexport function Trackers_applyAnalytics(granted: boolean): void {\n  const w = window as unknown as IGtagWindow;\n  if (!granted) {\n    return;\n  }\n  if (w.gtag) {\n    w.gtag(\"consent\", \"update\", { analytics_storage: \"granted\" });\n  }\n  setLandingPageCookie();\n}\n\nlet redditLoaded = false;\n\nfunction loadRedditPixel(): void {\n  if (redditLoaded) {\n    return;\n  }\n  redditLoaded = true;\n  const w = window as unknown as IGtagWindow;\n  const d = document;\n  if (!w.rdt) {\n    const p = (w.rdt = function (...args: unknown[]): void {\n      const rdt = w.rdt as unknown as { sendEvent?: (...a: unknown[]) => void; callQueue: unknown[] };\n      if (rdt.sendEvent) {\n        rdt.sendEvent.apply(rdt, args);\n      } else {\n        rdt.callQueue.push(args);\n      }\n    });\n    (p as unknown as { callQueue: unknown[] }).callQueue = [];\n    const t = d.createElement(\"script\");\n    t.src = \"https://www.redditstatic.com/ads/pixel.js\";\n    t.async = true;\n    const s = d.getElementsByTagName(\"script\")[0];\n    s.parentNode?.insertBefore(t, s);\n  }\n  w.rdt?.(\"init\", \"t2_hoob2\");\n  w.rdt?.(\"track\", \"PageVisit\");\n}\n\nfunction setLandingPageCookie(): void {\n  try {\n    if (/(?:^|;\\s*)lft_landing=/.test(document.cookie)) {\n      return;\n    }\n    const path = window.location.pathname || \"/\";\n    document.cookie =\n      \"lft_landing=\" + encodeURIComponent(path) + \"; path=/; domain=.liftosaur.com; max-age=31536000; samesite=lax\";\n  } catch {\n    // ignore\n  }\n}\n\nfunction storeUtm(): void {\n  try {\n    const params = new URL(window.location.href).searchParams;\n    [\"utm_source\", \"utm_medium\", \"utm_campaign\", \"utm_content\", \"utm_term\"].forEach((param) => {\n      const value = params.get(param);\n      if (value) {\n        window.localStorage.setItem(param, value);\n      }\n    });\n  } catch {\n    // ignore\n  }\n}\n\nexport function Trackers_applyAdvertising(granted: boolean): void {\n  const w = window as unknown as IGtagWindow;\n  if (!granted) {\n    return;\n  }\n  if (w.gtag) {\n    w.gtag(\"consent\", \"update\", {\n      ad_storage: \"granted\",\n      ad_user_data: \"granted\",\n      ad_personalization: \"granted\",\n    });\n  }\n  loadRedditPixel();\n  storeUtm();\n}\n\n// Syncs only gtag's Consent Mode signals to the stored categories, without loading any of the other\n// trackers. Used on /app, which has gtag but never had the Reddit pixel / landing cookie / UTM, so we\n// respect the saved choice there without expanding what /app tracks (and without a banner).\nexport function Trackers_applyGtagConsent(categories: IConsentCategories): void {\n  const w = window as unknown as IGtagWindow;\n  if (!w.gtag) {\n    return;\n  }\n  w.gtag(\"consent\", \"update\", {\n    analytics_storage: categories.analytics ? \"granted\" : \"denied\",\n    ad_storage: categories.advertising ? \"granted\" : \"denied\",\n    ad_user_data: categories.advertising ? \"granted\" : \"denied\",\n    ad_personalization: categories.advertising ? \"granted\" : \"denied\",\n  });\n}\n\n// We can't read the domain/path a cookie was set with, so expire the name across the combos our\n// trackers use (current host and the registrable domain, path /).\nfunction expireCookie(name: string): void {\n  const expires = \"expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n  const host = window.location.hostname;\n  const domains = [\"\", host, \".\" + host, \".liftosaur.com\"];\n  for (const d of domains) {\n    document.cookie = `${name}=; ${expires}; path=/` + (d ? `; domain=${d}` : \"\");\n  }\n}\n\nfunction clearCookiesByPrefix(prefixes: string[]): void {\n  const names = document.cookie\n    .split(\";\")\n    .map((c) => c.split(\"=\")[0].trim())\n    .filter(Boolean);\n  for (const name of names) {\n    if (prefixes.some((p) => name.startsWith(p))) {\n      expireCookie(name);\n    }\n  }\n}\n\n// Deletes already-set cookies/storage for any category the user has now denied, so a revoke is a clean\n// opt-out rather than just halting future tracking. (gtag goes back to denied on the next load.)\nexport function Trackers_revoke(categories: IConsentCategories): void {\n  if (!categories.analytics) {\n    clearCookiesByPrefix([\"_ga\", \"_gid\"]);\n    expireCookie(\"lft_landing\");\n  }\n  if (!categories.advertising) {\n    clearCookiesByPrefix([\"_gcl\", \"_rdt\"]);\n    try {\n      [\"utm_source\", \"utm_medium\", \"utm_campaign\", \"utm_content\", \"utm_term\"].forEach((k) =>\n        window.localStorage.removeItem(k)\n      );\n    } catch {\n      // ignore\n    }\n  }\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","import {\n  Consent_getMode,\n  Consent_getStored,\n  Consent_hasGPC,\n  Consent_resolve,\n  Consent_store,\n  IConsentCategories,\n  IConsentMode,\n} from \"./consent\";\nimport { ConsentBanner_openPreferences, ConsentBanner_showBanner } from \"./consentBanner\";\nimport {\n  Trackers_applyAdvertising,\n  Trackers_applyAnalytics,\n  Trackers_applyGtagConsent,\n  Trackers_revoke,\n} from \"./trackers\";\n\n// Surfaces can opt out of the banner and limit gating to gtag only (set in the page before consent.js\n// loads). /app uses { showBanner: false, gtagOnly: true } so it respects the saved choice but never\n// shows a banner - older native WebView clients render /app and a banner overlay could break them.\ninterface ILftConsentConfig {\n  showBanner?: boolean;\n  gtagOnly?: boolean;\n}\n\nfunction getConfig(): ILftConsentConfig {\n  return (window as unknown as { lftConsentConfig?: ILftConsentConfig }).lftConsentConfig ?? {};\n}\n\nfunction applyConsent(categories: IConsentCategories): void {\n  const advertising = categories.advertising && !Consent_hasGPC();\n  if (getConfig().gtagOnly) {\n    Trackers_applyGtagConsent({ analytics: categories.analytics, advertising });\n    return;\n  }\n  Trackers_applyAnalytics(categories.analytics);\n  Trackers_applyAdvertising(advertising);\n}\n\nfunction effectiveCurrent(mode: IConsentMode): IConsentCategories {\n  const decision = Consent_resolve(mode, Consent_getStored(), Consent_hasGPC());\n  return { analytics: decision.analytics, advertising: decision.advertising };\n}\n\n// QA helper: ?lftconsent=optin|optout|none forces the mode and re-prompts, so all three flows can be\n// tested without an EU IP. Ignored on production so it can't be used to bypass the banner for others.\nfunction getDevOverride(): IConsentMode | undefined {\n  try {\n    if (window.location.hostname === \"www.liftosaur.com\") {\n      return undefined;\n    }\n    const v = new URL(window.location.href).searchParams.get(\"lftconsent\");\n    return v === \"optin\" || v === \"optout\" || v === \"none\" ? v : undefined;\n  } catch {\n    return undefined;\n  }\n}\n\nasync function boot(): Promise<void> {\n  const override = getDevOverride();\n  const mode = override ?? (await Consent_getMode());\n\n  // Persistent control to change/withdraw consent at any time (required) - the footer \"Privacy\n  // Settings\" link calls this. Reload on change so revoking actually unloads trackers.\n  const openPreferences = (): void => {\n    ConsentBanner_openPreferences(effectiveCurrent(mode), (categories) => {\n      Consent_store(categories);\n      Trackers_revoke(categories);\n      window.location.reload();\n    });\n  };\n  (window as unknown as { lftConsent?: { open: () => void } }).lftConsent = { open: openPreferences };\n\n  if (Consent_hasGPC()) {\n    Trackers_revoke({ analytics: true, advertising: false });\n  }\n\n  const decision = Consent_resolve(mode, override ? undefined : Consent_getStored(), Consent_hasGPC());\n  if (decision.needsBanner && getConfig().showBanner !== false) {\n    ConsentBanner_showBanner(mode, (categories) => {\n      Consent_store(categories);\n      Trackers_revoke(categories);\n      applyConsent(categories);\n    });\n  } else {\n    applyConsent(decision);\n  }\n}\n\nif (document.readyState === \"loading\") {\n  document.addEventListener(\"DOMContentLoaded\", () => {\n    boot();\n  });\n} else {\n  boot();\n}\n"],"names":["asyncGeneratorStep","n","t","e","r","o","a","c","i","u","value","done","Promise","resolve","then","module","exports","this","arguments","apply","_next","_throw","__esModule","_Consent_getMode","raw","window","localStorage","getItem","STORAGE_KEY","parsed","JSON","parse","v","analytics","advertising","navigator","globalPrivacyControl","mode","stored","gpc","needsBanner","categories","ts","Date","now","setItem","stringify","GEO_CACHE_KEY","_asyncToGenerator2","default","cachedRaw","cached","res","fetch","credentials","json","consentMode","onChoice","bar","el","position","left","right","bottom","zIndex","String","Z","background","borderTop","boxShadow","padding","display","flexWrap","gap","alignItems","justifyContent","fontFamily","text","flex","minWidth","fontSize","color","lineHeight","links","policy","textDecoration","href","appendChild","actions","reject","button","manage","accept","addEventListener","remove","ConsentBanner_openPreferences","cats","document","body","tag","style","node","createElement","Object","assign","textContent","label","primary","cursor","borderRadius","fontWeight","border","parentNode","removeChild","current","onSave","overlay","inset","card","maxWidth","width","stopPropagation","header","marginBottom","close","setAttribute","state","_loop","row","wrap","cb","marginTop","type","checked","key","txt","title","desc","save","buildPreferences","granted","w","gtag","ad_storage","ad_user_data","ad_personalization","redditLoaded","d","rdt","args","sendEvent","callQueue","push","src","async","s","getElementsByTagName","insertBefore","loadRedditPixel","params","URL","location","searchParams","forEach","param","get","storeUtm","analytics_storage","test","cookie","path","pathname","encodeURIComponent","setLandingPageCookie","clearCookiesByPrefix","expireCookie","k","removeItem","name","host","hostname","domains","prefixes","names","split","map","trim","filter","Boolean","some","p","startsWith","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","_consent","require","_consentBanner","_trackers","getConfig","lftConsentConfig","applyConsent","Consent_hasGPC","gtagOnly","Trackers_applyGtagConsent","Trackers_applyAnalytics","Trackers_applyAdvertising","boot","_boot","override","getDevOverride","Consent_getMode","lftConsent","open","openPreferences","decision","Consent_resolve","Consent_getStored","effectiveCurrent","Consent_store","Trackers_revoke","reload","showBanner","ConsentBanner_showBanner","readyState"],"sourceRoot":""}