1<!DOCTYPE html> 2<html lang="en" class="masked"> 3 <head> 4 <meta charset="UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 <title></title> 7 <meta name="robots" content="index,follow"> 8 <link href="https://d3mmydk2yvkj9n.cloudfront.net/prod" rel="dns-prefetch" /> 9 <link href="https://d3mmydk2yvkj9n.cloudfront.net/prod" rel="preconnect" crossorigin /> 10 <link href="https://d1bdh2kfvnydei.cloudfront.net" rel="dns-prefetch" /> 11 <link href="https://d1bdh2kfvnydei.cloudfront.net" rel="preconnect" crossorigin /> 12 13
13<script> 14 (() => { 15 window.__modulePreloadUtils = { 16 supportsModulePreload() { 17 const link = document.createElement('link'); 18 return link.relList?.supports?.('modulepreload'); 19 }, 20 21 resolveModuleUrl(modulePath, cdnBasePath) { 22 const devQaMatch = window.location.hostname.match(/^(dev-[^.]+|qa\d{2}-[^.]+)(?:\.dev|\.qa\d{2})?\.member/); 23 24 if (!devQaMatch) return `${cdnBasePath}/${modulePath}`; 25 26 const workspace = devQaMatch[1].replace(/^qa([0-9]{2})/, 'qa-$1'); 27 const cdnOriginMatch = cdnBasePath.match(/^(https:\/\/[^/]+)\//); 28 29 return cdnOriginMatch 30 ? `${cdnOriginMatch[1]}/${workspace}/${modulePath}` 31 : `${cdnBasePath}/${modulePath}`; 32 }, 33 34 createPreloadLink(href) { 35 const link = document.createElement('link'); 36 link.rel = 'modulepreload'; 37 link.href = href; 38 link.crossOrigin = ''; 39 return link; 40 }, 41 42 appendLinks(links) { 43 const fragment = document.createDocumentFragment(); 44 for (const link of links) fragment.appendChild(link); 45 document.head.appendChild(fragment); 46 } 47 }; 48 })(); 49 </script>
49 50 51
51<script> 52 (() => { 53 const utils = window.__modulePreloadUtils; 54 const CDN_BASE = 'https://d3mmydk2yvkj9n.cloudfront.net/prod'; 55 56 // Global preloads: host app shared deps and shell components (every route) 57 const GLOBAL_PRELOAD_CONFIG = { 58 manifests: { 59 'app-member-host': { all: true, exclude: ['photoHelpers', 'formatHelpers', 'prompts', 'deviceHelpers', 'prefetcher', 'memberApiStore', 'memberApiForm', 'panelService', 'MagazineWrapper', 'NotFound'] }, 60 'vue3-shared': ['Copy', 'Heading', 'Button', 'Theme'] 61 } 62 }; 63 64 const ROUTE_PRELOAD_CONFIG = { 65 login: { 66 remoteEntries: ['app-auth', 'vue3-shared', 'app-member-host'], 67 manifests: { 68 'app-auth': ['SignIn'], 69 'vue3-shared': ['TextInput', 'Alert', 'Checkbox', 'Label', 'SubLabel', 'IconWarning', 'IconExclamationCircle'] 70 }, 71 copyGroups: ['member-login', 'member-nav'] 72 } 73 }; 74 75 const detectRoute = () => window.location.pathname.split('/')[2] || ''; 76 77 const getBrand = () => window.location.hostname.includes('healthprofs') ? 'healthprofs' : 'psychologytoday'; 78 79 const getLocaleInfo = () => { 80 const parts = (window.location.pathname.split('/')[1] || 'us').split('-'); 81 if (parts.length === 2) { 82 return { country: parts[1].toUpperCase(), language: parts[0] }; 83 } 84 const country = parts[0].toUpperCase(); 85 const defaultLanguages = getBrand() === 'healthprofs' 86 ? JSON.parse('\{\"CA\":\"en\"\,\"US\":\"en\"\}') 87 : JSON.parse('\{\"AR\":\"es\"\,\"AT\":\"de\"\,\"AU\":\"en\"\,\"BE\":\"fr\"\,\"CA\":\"en\"\,\"CH\":\"de\"\,\"CL\":\"es\"\,\"CO\":\"es\"\,\"CR\":\"es\"\,\"DE\":\"en\"\,\"DK\":\"da\"\,\"ES\":\"es\"\,\"FR\":\"fr\"\,\"GB\":\"en\"\,\"GT\":\"es\"\,\"HK\":\"en\"\,\"IE\":\"en\"\,\"IN\":\"en\"\,\"MX\":\"es\"\,\"NZ\":\"en\"\,\"PA\":\"es\"\,\"PE\":\"es\"\,\"PR\":\"es\"\,\"SE\":\"sv\"\,\"SG\":\"en\"\,\"US\":\"en\"\,\"UY\":\"es\"\,\"ZA\":\"en\"\}'); 88 return { country, language: defaultLanguages[country] || 'en' }; 89 }; 90 91 const PSICOLOGIA_HOY_COUNTRIES = ['AR', 'CL', 'CO', 'CR', 'ES', 'GT', 'MX', 'PA', 'PE', 'PR', 'UY']; 92 93 const getFaviconIcon = (brand, country, isLoginRoute) => 94 isLoginRoute && brand === 'psychologytoday' && PSICOLOGIA_HOY_COUNTRIES.includes(country) ? 'psicologiahoy' : brand; 95 96 const preloadRemoteEntries = (entries) => { 97 if (!utils.supportsModulePreload()) return; 98 99 const links = entries.map(name => { 100 const url = utils.resolveModuleUrl(`${name}/latest/assets/remoteEntry.js`, CDN_BASE); 101 return utils.createPreloadLink(url); 102 }); 103 104 utils.appendLinks(links); 105 }; 106 107 const manifestCache = {}; 108 window.__manifestCache = manifestCache; 109 110 const fetchManifest = (url) => { 111 if (!manifestCache[url]) { 112 manifestCache[url] = fetch(url).then(r => r.json()); 113 } 114 return manifestCache[url]; 115 }; 116 117 const preloadManifests = (manifests) => { 118 for (const [projectName, components] of Object.entries(manifests)) { 119 const baseUrl = utils.resolveModuleUrl(`${projectName}/latest`, CDN_BASE); 120 121 fetchManifest(`${baseUrl}/manifest.json`) 122 .then(manifest => { 123 const filesToLoad = new Set(); 124 const visited = new Set(); 125 126 const excludes = (components?.exclude || []); 127 const isExcluded = (key) => excludes.length > 0 && excludes.some(name => 128 key.endsWith(`/${name}.vue`) || key.endsWith(`/${name}.ts`) 129 ); 130 131 const traverse = (key) => { 132 if (visited.has(key) || !manifest[key] || isExcluded(key)) return; 133 visited.add(key); 134 135 const entry = manifest[key]; 136 if (entry.file) filesToLoad.add(entry.file);
137 (entry.imports || []).forEach(traverse); 138 }; 139 140 if (components === '__all__' || components?.all) { 141 Object.keys(manifest).forEach(traverse); 142 } else { 143 for (const name of components) { 144 for (const key of Object.keys(manifest)) { 145 if (key.endsWith(`/${name}.vue`) || key.endsWith(`/${name}.ts`)) { 146 traverse(key); 147 } 148 } 149 } 150 // Also pick up standalone CSS entries (e.g. style.css) 151 for (const key of Object.keys(manifest)) { 152 const file = manifest[key].file; 153 if (file && file.endsWith('.css')) filesToLoad.add(file); 154 } 155 } 156 157 const isAllMode = components === '__all__' || components?.all; 158 const links = []; 159 for (const file of filesToLoad) { 160 if (file.endsWith('.css')) { 161 // Only preload CSS for remote manifests (named component lists). 162 // The host's own CSS is already in index.html as a <link>. 163 if (!isAllMode) { 164 const link = document.createElement('link'); 165 link.rel = 'preload'; 166 link.as = 'style'; 167 link.href = `${baseUrl}/${file}`; 168 links.push(link); 169 } 170 } else { 171 links.push(utils.createPreloadLink(`${baseUrl}/${file}`)); 172 } 173 } 174 utils.appendLinks(links); 175 }) 176 .catch(err => { 177 console.error(`Failed to preload ${projectName}:`, err); 178 }); 179 } 180 }; 181 182 const preloadCopyGroups = (groups) => { 183 const brand = getBrand(); 184 const locale = getLocaleInfo(); 185 const cdnUrl = 'https://d35kml8zmh6y3i.cloudfront.net'; 186 187 window.__preloadedCopyGroups = window.__preloadedCopyGroups || {}; 188 189 for (const group of groups) { 190 const url = [cdnUrl, group, brand, brand, 'published', locale.country, locale.language].join('/').toLowerCase() + '.json'; 191 192 window.__preloadedCopyGroups[group] = fetch(url) 193 .then(response => { 194 if (!response.ok) throw new Error(`HTTP ${response.status}`); 195 return response.json(); 196 }) 197 .then(entries => { 198 const result = {}; 199 for (const { key, value } of entries) { 200 result[key] = value; 201 } 202 return result; 203 }) 204 .catch(err => { 205 console.error(`Failed to preload copy group ${group}:`, err); 206 return null; 207 }); 208 } 209 }; 210 211 preloadManifests(GLOBAL_PRELOAD_CONFIG.manifests); 212 213 const config = ROUTE_PRELOAD_CONFIG[detectRoute()]; 214 if (config) { 215 preloadRemoteEntries(config.remoteEntries); 216 preloadManifests(config.manifests); 217 preloadCopyGroups(config.copyGroups); 218 } 219 220 // Preload the country flag SVG â it's used by the footer and loaded late 221 // when the component renders. We know the country from the URL path. 222 const STATIC_CDN = 'https://d1bdh2kfvnydei.cloudfront.net'; 223 const locale = getLocaleInfo(); 224 const flagLink = document.createElement('link'); 225 flagLink.rel = 'preload'; 226 flagLink.as = 'image'; 227 flagLink.href = `${STATIC_CDN}/flags/flag-${locale.country.toLowerCase()}.svg`; 228 document.head.appendChild(flagLink); 229 230 const faviconIcon = getFaviconIcon(getBrand(), locale.country, detectRoute() === 'login'); 231 const faviconIcoLink = document.createElement('link'); 232 faviconIcoLink.rel = 'icon'; 233 faviconIcoLink.type = 'image/x-icon'; 234 faviconIcoLink.setAttribute('sizes', 'any'); 235 faviconIcoLink.href = `${STATIC_CDN}/favicon-${faviconIcon}.ico`; 236 const faviconSvgLink = document.createElement('link'); 237 faviconSvgLink.rel = 'icon'; 238 faviconSvgLink.type = 'image/svg+xml'; 239 faviconSvgLink.href = `${STATIC_CDN}/favicon-${faviconIcon}.svg`; 240 utils.appendLinks([faviconIcoLink, faviconSvgLink]); 241 })(); 242 </script>
242 243 244
244<script type="text/javascript" src="https://www.datadoghq-browser-agent.com/us1/v6/datadog-logs.js"></script>
244 245
245<script> 246 // on login, don't load Stripe right away â main.ts triggers it after router is ready 247 (() => { 248 const loadStripe = () => { 249 const s = document.createElement('script'); 250 s.src = 'https://js.stripe.com/v3/'; 251 s.async = true; 252 document.head.appendChild(s); 253 }; 254 255 const route = window.location.pathname.split('/')[2] || ''; 256 if (route !== 'login') { 257 loadStripe(); 258 } else { 259 window.__deferredStripeLoad = () => { 260 if (!window.Stripe) loadStripe(); 261 }; 262 } 263 })(); 264 </script>
264 265 <style> 266 @font-face { 267 font-family: 'Proxima Nova Regular'; 268 src: url('https://d1bdh2kfvnydei.cloudfront.net/proxima-nova-regular.woff2') format('woff2'); 269 font-weight: normal; 270 font-style: normal; 271 font-display: swap; 272 } 273 @font-face { 274 font-family: 'Proxima Nova Semi Bold'; 275 src: url('https://d1bdh2kfvnydei.cloudfront.net/proxima-nova-semibold.woff2') format('woff2'); 276 font-weight: normal; 277 font-style: normal; 278 font-display: swap; 279 } 280 @font-face { 281 font-family: 'Proxima Nova Bold'; 282 src: url('https://d1bdh2kfvnydei.cloudfront.net/proxima-nova-bold.woff2') format('woff2'); 283 font-weight: normal; 284 font-style: normal; 285 font-display: swap; 286 } 287 @font-face { 288 font-family: 'Lato Italic'; 289 src: url('https://d1bdh2kfvnydei.cloudfront.net/lato-italic.woff2') format('woff2'); 290 font-weight: normal; 291 font-style: normal; 292 font-display: swap; 293 } 294 .masked { 295 overflow: hidden; 296 touch-action: none; 297 } 298 .masked body { 299 position: fixed; 300 width: 100vw; 301 } 302 303 #html-loading-mask { 304 position: fixed; 305 top: 0; 306 left: 0; 307 width: 100%; 308 height: 100%; 309 background: rgba(255, 255, 255, 1); 310 display: flex; 311 justify-content: center; 312 align-items: center; 313 z-index: 2147483647; 314 transition: opacity 0.5s; 315 box-sizing: unset; 316 } 317 318 #html-loading-mask * { 319 box-sizing: unset; 320 } 321 322 .spinner { 323 position: relative; 324 width: 68px; 325 height: 68px; 326 display: flex; 327 justify-content: center; 328 align-items: center; 329 } 330 331 .inner-circle { 332 width: 64px; 333 height: 64px; 334 border-radius: 50%; 335 display: flex; 336 justify-content: center; 337 align-items: center; 338 } 339 340 .outer-spinner, 341 .outer-spinner-overlay { 342 position: absolute; 343 width: 68px; 344 height: 68px; 345 border-radius: 50%; 346 } 347 348 .outer-spinner { 349 border: 2px solid transparent; 350 border-top-color: var(--header-backgroundColor, #477be4); 351 animation: rotate 1s linear infinite; 352 } 353 354 .outer-spinner-overlay { 355 border: 2px solid var(--header-backgroundColor, #477be4); 356 opacity: 0.4; 357 } 358 359 @keyframes rotate { 360 0% { 361 transform: rotate(0deg); 362 } 363 100% { 364 transform: rotate(360deg); 365 } 366 } 367 368 .brand-icon { 369 display: flex; 370 justify-content: center; 371 align-items: center; 372 } 373 374 .brand-icon svg { 375 width: 64px; 376 height: 64px; 377 } 378 379 .healthprofs-icon { 380 display: none; 381 } 382 383 .fade-enter-active, 384 .fade-leave-active { 385 transition: opacity 0.5s; 386 } 387 388 .fade-enter, 389 .fade-leave-to { 390 opacity: 0; 391 } 392 </style> 393
393<script type="module" crossorigin src="https://d3mmydk2yvkj9n.cloudfront.net/prod/app-member-host/latest/assets/index.js"></script>
393 394 <link rel="modulepreload" crossorigin href="https://d3mmydk2yvkj9n.cloudfront.net/prod/app-member-host/latest/assets/preload-helper-1790189911316.js"> 395 <link rel="stylesheet" href="https://d3mmydk2yvkj9n.cloudfront.net/prod/app-member-host/latest/assets/style.b83b8336.css"> 396 </head> 397 <body> 398 <div id="html-loading-mask" data-testid="html-loading-mask"> 399 <div class="spinner"> 400 <div class="inner-circle"> 401 <div class="brand-icon"> 402 <!-- Psychology Today Icon --> 403 <svg 404 class="psychologytoday-icon" 405 width="64" 406 height="64" 407 viewBox="0 0 64 64" 408 fill="none" 409 xmlns="http://www.w3.org/2000/svg" 410 > 411 <rect y="0" width="64" height="64" rx="32" fill="#477BE4" /> 412 <rect y="0" width="64" height="64" rx="32" fill="#477BE4" /> 413 <g filter="url(#filter0_d_6568_4500)"> 414 <path 415 d="M21.4193 39.2751C21.4193 38.8212 21.7873 38.4533 22.2411 38.4533H23.6581C27.8639 38.4533 29.831 36.8731 29.831 33.6259V22.8093C29.831 19.5653 27.8721 17.9819 23.6581 17.9819H15.2904C14.8366 17.9819 14.4686 18.3499 14.4686 18.8037V47.8398C14.4686 48.2937 14.8366 48.6616 15.2904 48.6616H20.5976C21.0514 48.6616 21.4193 48.2937 21.4193 47.8398V39.2751ZM22.9297 22.893V33.5422C22.9297 33.864 22.7609 33.9799 22.37 33.9799H22.2411C21.7873 33.9799 21.4193 33.612 21.4193 33.1581V23.2803C21.4193 22.8264 21.7873 22.4585 22.2411 22.4585H22.37C22.7609 22.4585 22.9297 22.5905 22.9297 22.8962V22.893Z" 416 fill="white" 417 /> 418 <path 419 d="M43.5424 48.6616C43.9963 48.6616 44.3642 48.2937 44.3642 47.8398V25.6391C44.3642 25.1852 44.7321 24.8173 45.186 24.8173H46.9477H48.7095C49.1633 24.8173 49.5312 24.4494 49.5312 23.9955V18.8037C49.5312 18.3499 49.1633 17.9819 48.7095 17.9819H33.0905C32.6366 17.9819 32.2687 18.3499 32.2687 18.8037V23.9955C32.2687 24.4494 32.6366 24.8173 33.0905 24.8173H34.8501H36.6098C37.0637 24.8173 37.4316 25.1852 37.4316 25.6391V47.8398C37.4316 48.2937 37.7995 48.6616 38.2534 48.6616H43.5424Z" 420 fill="white" 421 /> 422 </g> 423 <defs> 424 <filter 425 id="filter0_d_6568_4500" 426 x="14.4686" 427 y="17.9819" 428 width="35.6105" 429 height="31.2275" 430 filterUnits="userSpaceOnUse" 431 color-interpolation-filters="sRGB" 432 > 433 <feFlood flood-opacity="0" result="BackgroundImageFix" /> 434 <feColorMatrix 435 in="SourceAlpha" 436 type="matrix" 437 values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" 438 result="hardAlpha" 439 /> 440 <feOffset dx="0.547851" dy="0.547851" /> 441 <feColorMatrix type="matrix" values="0 0 0 0 0.243137 0 0 0 0 0.419608 0 0 0 0 0.835294 0 0 0 1 0" /> 442 <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_6568_4500" /> 443 <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_6568_4500" result="shape" /> 444 </filter> 445 </defs> 446 </svg> 447 448 <!-- HealthProfs Icon --> 449 <svg 450 class="healthprofs-icon" 451 width="64" 452 height="64"
453 viewBox="0 0 64 64" 454 fill="none" 455 xmlns="http://www.w3.org/2000/svg" 456 > 457 <g clip-path="url(#clip0_8465_5167)"> 458 <path 459 d="M64 32C64 14.3269 49.6731 0 32 0C14.3269 0 0 14.3269 0 32C0 49.6731 14.3269 64 32 64C49.6731 64 64 49.6731 64 32Z" 460 fill="#477BE4" 461 /> 462 <path 463 d="M64 32C64 14.3269 49.6731 0 32 0C14.3269 0 0 14.3269 0 32C0 49.6731 14.3269 64 32 64C49.6731 64 64 49.6731 64 32Z" 464 fill="#63B448" 465 /> 466 <path 467 d="M17.957 17.9819H22.09V29.9835H28.1505V17.9819H32.2835V48.6616H28.1505V33.4807H22.09V48.6616H17.957V17.9819Z" 468 fill="white" 469 /> 470 <path 471 d="M37.0325 17.9819H42.4769C45.0998 17.9819 47.0074 18.6442 48.1996 19.9689C49.3918 21.3068 49.9879 23.4263 49.9879 26.3274C49.9879 30.4074 48.7891 33.0435 46.3914 34.2357C45.1859 34.7789 43.444 35.0504 41.1655 35.0504V48.6616H37.0325V17.9819ZM41.1655 31.5135C42.8743 31.5135 44.0533 31.1691 44.7024 30.4803C45.3647 29.7782 45.6959 28.533 45.6959 26.7447C45.6959 24.9166 45.378 23.5787 44.7421 22.7309C44.1063 21.8831 43.1062 21.4592 41.7417 21.4592H41.1655V31.5135Z" 472 fill="white" 473 /> 474 </g> 475 <defs> 476 <clipPath id="clip0_8465_5167"> 477 <rect width="64" height="64" fill="white" /> 478 </clipPath> 479 </defs> 480 </svg> 481 </div> 482 </div> 483 <div class="outer-spinner"></div> 484 <div class="outer-spinner-overlay"></div> 485 </div> 486 </div> 487 <div id="app"></div> 488
488<script> 489 const { hostname } = window.location; 490 const brand = hostname.includes("healthprofs") ? "healthprofs" : "psychologytoday"; 491 if (brand === "healthprofs") { 492 document.querySelector(".psychologytoday-icon").style.display = "none"; 493 document.querySelector(".healthprofs-icon").style.display = "block"; 494 document.documentElement.style.setProperty("--header-backgroundColor", "#63B448"); 495 } else { 496 document.documentElement.style.setProperty("--header-backgroundColor", "#477BE4"); 497 } 498 </script>
498 499 500 </body> 501</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.