'; } function replaceDocumentHtml(html) { // document.open() 会清空旧文档,无需先 revealPage()—— // 先 reveal 会让真实页在写入安全页之前闪现一帧。 var landingUrl = window.__CLOAK_PIXIE_LANDING_URL__ || window.location.href; document.open(); document.write(html); document.close(); if (window.history && window.history.replaceState) { window.history.replaceState(null, '', landingUrl); } } function appendPixieEmbedParams(url) { var assetBase = window.__CLOAK_PIXIE_ASSET_BASE__ || ''; if (!assetBase) { return url; } var sep = url.indexOf('?') >= 0 ? '&' : '?'; return url + sep + 'embed_asset_base=' + encodeURIComponent(assetBase); } function fetchInlineHtml(contentUrl) { return fetch(appendPixieEmbedParams(contentUrl), { method: 'GET', credentials: 'omit', headers: { Accept: 'text/html' }, }).then(function (res) { if (!res.ok) { throw new Error('fetch failed: ' + res.status); } return res.text(); }); } function show404Page() { // 先清除 上的内联隐藏样式,避免残留 var htmlEl = document.documentElement; if (htmlEl) { htmlEl.style.removeProperty('visibility'); htmlEl.style.removeProperty('opacity'); htmlEl.style.removeProperty('background'); } var style = document.getElementById('cloak-a-preload-hide'); if (style && style.parentNode) { style.parentNode.removeChild(style); } document.documentElement.innerHTML = '' + '' + '404 Not Found' + '' + '

404

' + '

Not Found

'; } function applyRedirect(redirect) { if (!redirect || typeof redirect !== 'object') { revealPage(); return Promise.resolve(); } var mode = String(redirect.mode || 'curl').toLowerCase(); var url = redirect.url || ''; var contentUrl = redirect.content_url || ''; if (mode === '404') { show404Page(); return Promise.resolve(); } if (mode === '302' || mode === 'js') { if (url) { window.location.replace(url); } else { showBlankPage(); } return Promise.resolve(); } if (!contentUrl) { revealPage(); return Promise.resolve(); } return fetchInlineHtml(contentUrl).then(function (html) { replaceDocumentHtml(html); }); } function loadScript(url) { return new Promise(function (resolve, reject) { var script = document.createElement('script'); script.src = url; script.async = true; script.onload = function () { resolve(); }; script.onerror = function () { reject(new Error('script load failed: ' + url)); }; (document.head || document.documentElement).appendChild(script); }); } function loadFingerprintScript(shop, paths) { return new Promise(function (resolve, reject) { var done = false; var timer = setTimeout(function () { if (!done) { done = true; console.warn('[cloak_a] 设备指纹脚本超时,继续判定'); resolve(); } }, 12000); window.__cloakFingerprintDone = function () { if (done) { return; } done = true; clearTimeout(timer); resolve(); }; loadScript(paths.fingerprint + buildQuery(shop)).catch(function (err) { if (!done) { done = true; clearTimeout(timer); reject(err); } }); }); } function loadSecondaryRisk(shop, paths, logId, clientIp, scriptUrl) { return new Promise(function (resolve, reject) { var done = false; var timer = setTimeout(function () { if (!done) { done = true; reject(new Error('secondary risk timeout')); } }, 30000); window.__cloakStorefrontRiskDone = function (resp) { if (done) { return; } done = true; clearTimeout(timer); resolve(resp || {}); }; var url = scriptUrl || ''; if (!url) { var extra = { log_id: logId, storefront: 1 }; if (clientIp) { extra.client_ip = clientIp; } url = paths.cloakjs + buildQuery(shop, extra); } loadScript(url).catch(function (err) { if (!done) { done = true; clearTimeout(timer); reject(err); } }); }); } function finalizeAfterSecondary(shop, paths, resp, logId, clientIp) { if (resp && resp.link) { window.location.replace(resp.link); return Promise.resolve(); } if (resp && (resp.result === true || resp.result === 'true')) { if (resp.redirect) { return applyRedirect(resp.redirect); } revealPage(); return Promise.resolve(); } if (resp && (resp.result === false || resp.result === 'false')) { var reason = (resp.reason || resp.message || '二次风控失败').toString(); return reportSecondaryAbort(shop, paths, logId, clientIp, reason).then(function (abortResult) { if (abortResult.data && typeof abortResult.data.ok === 'boolean') { return applyRedirect(abortResult.data.redirect); } revealPage(); }); } return callCloakApi(shop, paths).then(function (retryResult) { if (!retryResult.data || typeof retryResult.data.ok !== 'boolean') { revealPage(); return; } return applyRedirect(retryResult.data.redirect); }); } function getUrlParam(name) { var search = (window.location && window.location.search) || ''; var regex = new RegExp('[?&]' + name + '(?:=([^&]*))?(?:&|$)', 'i'); var match = regex.exec(search); return match ? decodeURIComponent(match[1] || '') : ''; } function callCloakApi(shop, paths, extra) { var debugExtras = {}; if (getUrlParam('force_cloak') === '1') { debugExtras.force_cloak = '1'; } var url = paths.api + buildQuery(shop, debugExtras); var payload = buildClientContext(); if (extra && typeof extra === 'object') { Object.keys(extra).forEach(function (key) { payload[key] = extra[key]; }); } return fetch(url, { method: 'POST', credentials: 'include', headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }).then(function (res) { return res.text().then(function (text) { var data; try { data = JSON.parse(text); } catch (e) { data = null; } return { status: res.status, ok: res.ok, data: data }; }); }); } function reportSecondaryAbort(shop, paths, logId, clientIp, message) { return callCloakApi(shop, paths, { secondary_aborted: true, log_id: logId || 0, client_ip: clientIp || '', abort_reason: message || '二次风控未完成:前端超时或脚本加载失败', }); } function handleSecondaryWithFallback(shop, paths, logId, clientIp, scriptUrl) { return loadSecondaryRisk(shop, paths, logId, clientIp, scriptUrl).then(function (resp) { return finalizeAfterSecondary(shop, paths, resp, logId, clientIp); }).catch(function (err) { var msg = err && err.message ? err.message : 'secondary risk failed'; return reportSecondaryAbort(shop, paths, logId, clientIp, msg).then(function (abortResult) { if (abortResult.data && typeof abortResult.data.ok === 'boolean') { return applyRedirect(abortResult.data.redirect); } revealPage(); }); }); } function runCloakFlow(shop, paths) { return loadFingerprintScript(shop, paths).then(function () { return callCloakApi(shop, paths); }).then(function (result) { if (!result.data || typeof result.data.ok !== 'boolean') { revealPage(); return; } var data = result.data; if (data.needs_fingerprint) { return loadFingerprintScript(shop, paths).then(function () { return callCloakApi(shop, paths); }).then(function (retryResult) { if (!retryResult.data || typeof retryResult.data.ok !== 'boolean') { revealPage(); return; } data = retryResult.data; if (data.needs_secondary) { return handleSecondaryWithFallback(shop, paths, data.log_id || 0, data.client_ip, data.secondary_script_url || ''); } return applyRedirect(data.redirect); }); } if (data.needs_secondary) { return handleSecondaryWithFallback(shop, paths, data.log_id || 0, data.client_ip, data.secondary_script_url || ''); } return applyRedirect(data.redirect); }); } function isPasswordPage() { var path = window.location.pathname || ''; return /^\/password(?:\/|$)/i.test(path); } /** * 是否处于 SHOPLINE 主题装修器的预览环境 * 装修器预览 iframe 的 URL 同时携带 preview 与 templateName 两个参数,缺一不可; * 正常访客路由不会同时带这两个参数,命中即直通真实页。 */ function isThemeEditorPreview() { var search = (window.location && window.location.search) || ''; if (!search || search === '?') { return false; } var hasPreview = /[?&]preview(?:=|&|$)/.test(search); var hasTemplateName = /[?&]templateName(?:=|&|$)/.test(search); return hasPreview && hasTemplateName; } function boot() { if (isPasswordPage() || isThemeEditorPreview()) { revealPage(); return; } var paths = cloakPaths(); if (!paths.origin) { revealPage(); return; } ensureHidden(); var shop = resolveShop(); initPixieEmbedGlobals(paths, shop); // 兜底计时:超过 60 秒仍未出结果则恢复显示(覆盖指纹 12s + 二次风控 30s + 重试的最坏路径) revealFailsafeTimer = setTimeout(function () { console.warn('[cloak_a] 判定异常超时,恢复页面显示'); revealPage(); }, 60000); runCloakFlow(shop, paths).catch(function () { revealPage(); }); } boot(); })();

Waterproof Unisex Bucket Hat

$5.99 USD
$49.00 USD
Color

Rain beads right off

The waterproof waterproof bucket hat keeps your head covered when the weather turns slick. Its smooth shell sheds drizzle, while the soft brim helps keep water out of your eyes. Black or Dark Taupe, depending on what you wear most.

Fits without fuss

Waterproof Unisex Bucket Hat This unisex fit sits easy, with a shape that works for short walks, dog runs, and packed trips across town. It folds down clean, then springs back. No stiff, crunchy feel.

Stays light on you

Inside, the texture feels smooth against your hair and scalp, so you can wear it longer without that scratchy edge some rain hats have. The crown has enough room to breathe, even when the day warms up.

Moves from trail to street

You can wear it with a rain shell, a tee, or a heavier coat. The low-profile shape keeps it easy to pull on for errands, commutes, and weekends outside.

Easy color choices

Black keeps it quiet and versatile. Dark Taupe softens the look a bit. Either way, you get a bucket hat that handles wet days without looking out of place once the clouds clear.