{"schema":"barkday.ai-pack-everything.v1","repo":"CandidQuality/Barkday","commit":"9e38500d723ed1e8e1ca93eb8ae821c831f1414d","updated_utc":"2026-05-05T03:48:27.039Z","count":189,"items":[{"path":".githooks/pre-commit.cmd","size":105,"sha":"45fc3539bfa99753ba69de848077eede39bc9eda","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.githooks/pre-commit.cmd","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.githooks/pre-commit.cmd","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"QGVjaG8gb2ZmCnBvd2Vyc2hlbGwgLU5vUHJvZmlsZSAtRXhlY3V0aW9uUG9saWN5IEJ5cGFzcyAtRmlsZSAiJX5kcDBwcmUtY29tbWl0LnBzMSIKZXhpdCAvYiAlZXJyb3JsZXZlbCUK","inline_bytes":140,"content_sha256":"2ef27653e37b05bf66e03c400d84c18d1622c671c2988ed13cb0a1cf821c2fa1"},{"path":".githooks/pre-commit.ps1","size":669,"sha":"878642132238750832ff01ddd63b98e256155b38","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.githooks/pre-commit.ps1","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.githooks/pre-commit.ps1","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"JEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICJTdG9wIgoKZnVuY3Rpb24gRmFpbCgkbXNnKSB7CiAgV3JpdGUtSG9zdCAiIgogIFdyaXRlLUhvc3QgIlBSRS1DT01NSVQgQkxPQ0tFRDogJG1zZyIKICBXcml0ZS1Ib3N0ICIiCiAgZXhpdCAxCn0KCiMgMSkgVmVyaWZpY2F0aW9uIG11c3QgcGFzcwpwb3dlcnNoZWxsIC1Ob1Byb2ZpbGUgLUV4ZWN1dGlvblBvbGljeSBCeXBhc3MgLUZpbGUgdG9vbHMvdmVyaWZ5LnBzMQppZiAoJExBU1RFWElUQ09ERSAtbmUgMCkgeyBGYWlsICJ0b29scy92ZXJpZnkucHMxIGZhaWxlZC4iIH0KCiMgMikgQSBkZWNpc2lvbiByZWNvcmQgbXVzdCBiZSBzdGFnZWQgKG5vdCBqdXN0IHByZXNlbnQpCiRzdGFnZWQgPSBnaXQgZGlmZiAtLWNhY2hlZCAtLW5hbWUtb25seQokaGFzRGVjaXNpb24gPSAkZmFsc2UKCmZvcmVhY2ggKCRmIGluICRzdGFnZWQpIHsKICBpZiAoJGYgLW1hdGNoICdeZG9jcy9kZWNpc2lvbnMvREVDLVxkezh9LVxkezJ9LS4rXC5tZCQnKSB7ICRoYXNEZWNpc2lvbiA9ICR0cnVlIH0KfQoKaWYgKC1ub3QgJGhhc0RlY2lzaW9uKSB7CiAgRmFpbCAiTm8gc3RhZ2VkIGRlY2lzaW9uIHJlY29yZCBmb3VuZC4gU3RhZ2UgZG9jcy9kZWNpc2lvbnMvREVDLVlZWVlNTURELVhYLSoubWQgYmVmb3JlIGNvbW1pdHRpbmcuIgp9CgpleGl0IDAK","inline_bytes":892,"content_sha256":"c3209476b9cbba3a9aeea55c07c6d687fe605756dc715a53f260016d26a396e7"},{"path":".github/workflows/ai-health.yml","size":5105,"sha":"de4461f4a1835e5042644d931fb59473377a77cc","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/ai-health.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/ai-health.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: AI Health Checks\r\n\r\non:\r\n # keep nightly, plus allow manual runs; add push-on-gifts for fast feedback\n schedule:\r\n - cron: \"17 3 * * *\"\r\n workflow_dispatch:\r\n push:\n paths:\n - 'data/dog-gifts-merged.json'\n - 'docs/**'\n - '.github/workflows/ai-health.yml'\n\r\npermissions:\r\n contents: read\r\n\r\njobs:\r\n nightly:\r\n runs-on: ubuntu-latest\r\n timeout-minutes: 20\r\n steps:\r\n - name: Check gift links via pack endpoint\r\n run: |\r\n node - <<'JS'\r\n const fetch = global.fetch; // Node 20\r\n const PACK_URL = 'https://candidquality.github.io/Barkday/data/dog-gifts-merged.json';\n\r\n // Friendly headers help a lot with CDNs\r\n const UA = 'Barkday-CI/1.0 (+https://candidquality.github.io/Barkday/)';\r\n const HEADERS = { 'User-Agent': UA, 'Accept': '*/*', 'Accept-Language': 'en' };\r\n\r\n // Domains that commonly soft-block bots; warn instead of failing\r\n const SOFT_DOMAINS = [\r\n /(^|\\.)(amazon\\.com|m\\.media-amazon\\.com|images-na\\.ssl-images-amazon\\.com)$/i,\r\n /(^|\\.)(chewy\\.com|img\\.chewy\\.com|images\\.chewy\\.com)$/i,\r\n /(^|\\.)(cloudfront\\.net)$/i\r\n ];\r\n\r\n (async () => {\r\n // Load the live v2 runtime gifts feed published with Pages\n const res = await fetch(PACK_URL, { headers: { ...HEADERS, 'Accept': 'application/json' } });\n if (!res.ok) throw new Error('Fetch gifts failed: ' + res.status);\n const feed = await res.json();\n const gifts = Array.isArray(feed) ? feed : (Array.isArray(feed.items) ? feed.items : []);\n if (!gifts.length) throw new Error('Gift feed did not contain any items');\n\n // Collect unique URLs\n const urls = new Set();\n for (const g of gifts) {\n if (g.url) urls.add(g.url);\n if (g.affiliate && g.affiliate.url) urls.add(g.affiliate.url);\n if (g.image) urls.add(g.image);\n if (Array.isArray(g.images)) for (const u of g.images) urls.add(u);\n }\n const list = Array.from(urls).filter(u => /^https?:\\/\\//i.test(u));\n console.log(`Checking ${list.length} URLs from data/dog-gifts-merged.json…`);\n\r\n const MAX = 8; // concurrency\r\n const REQ_TIMEOUT = 15000; // per request\r\n let i = 0, hard = [], soft = [], okCount = 0;\r\n\r\n const isSoftDomain = (u) => {\r\n try { return SOFT_DOMAINS.some(rx => rx.test(new URL(u).hostname)); }\r\n catch { return false; }\r\n };\r\n\r\n async function probe(u, method) {\r\n const ctrl = new AbortController();\r\n const timer = setTimeout(() => ctrl.abort(), REQ_TIMEOUT);\r\n try {\r\n const res = await fetch(u, { method, redirect: 'follow', signal: ctrl.signal, headers: HEADERS });\r\n clearTimeout(timer);\r\n return res;\r\n } catch (e) {\r\n clearTimeout(timer);\r\n throw e;\r\n }\r\n }\r\n\r\n async function check(u) {\r\n const looksImage = /\\.(png|jpe?g|webp|gif|svg)(\\?|$)/i.test(u) || /images?-/.test(u);\r\n let res;\r\n try {\r\n // Prefer HEAD; but GET for images (some CDNs 405 on HEAD for binaries)\r\n res = await probe(u, looksImage ? 'GET' : 'HEAD');\r\n // Fallback to GET on method/security blocks\r\n if (!res.ok && [401,403,405].includes(res.status)) {\r\n res = await probe(u, 'GET');\r\n }\r\n } catch (e) {\r\n const rec = { url: u, status: 'ERR ' + (e.name || 'error') };\r\n (isSoftDomain(u) ? soft : hard).push(rec);\r\n return;\r\n }\r\n\r\n const okish = res.ok || (res.status >= 200 && res.status < 400);\r\n if (okish) { okCount++; return; }\r\n\r\n const rec = { url: u, status: res.status };\r\n (isSoftDomain(u) || res.status === 429 ? soft : hard).push(rec);\r\n }\r\n\r\n await Promise.all(\r\n Array.from({ length: Math.min(MAX, list.length) }, async () => {\r\n while (i < list.length) {\r\n const u = list[i++]; await check(u);\r\n }\r\n })\r\n );\r\n\r\n console.log(`OK: ${okCount}, soft-warn: ${soft.length}, hard-fail: ${hard.length}`);\r\n if (soft.length) {\r\n console.warn('Soft-blocked URLs (likely CDN anti-bot; not failing build):');\r\n for (const b of soft) console.warn('-', b.status, b.url);\r\n }\r\n if (hard.length) {\r\n console.error('Broken/blocked URLs:');\r\n for (const b of hard) console.error('-', b.status, b.url);\r\n process.exit(1);\r\n }\r\n console.log('All gift and image links look reachable.');\r\n })().catch(e => { console.error(e); process.exit(1); });\r\n JS\r\n","inline_bytes":5103,"content_sha256":"1d211034e2e61acbe441e5fba06bfa9b6734512b1d302fcdd2f3b16148dc95d5"},{"path":".github/workflows/ai-index.yml","size":2284,"sha":"61936536f95990f5a7050eb1cab9a1ef36e6372c","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/ai-index.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/ai-index.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: Build AI Index and Packs\r\n\r\non:\r\n workflow_dispatch:\r\n push:\r\n branches: [ main ]\r\n # Prevent loops when we commit docs/*\r\n paths-ignore:\r\n - 'docs/**'\r\n\r\npermissions:\r\n contents: write\r\n\r\nconcurrency:\r\n group: ai-index-${{ github.ref }}\r\n cancel-in-progress: true\r\n\r\njobs:\r\n build:\r\n runs-on: ubuntu-latest\r\n steps:\r\n - name: Checkout\r\n uses: actions/checkout@v4\r\n with:\r\n fetch-depth: 0\r\n ref: main\r\n\r\n # Always sync to the latest main so our push is fast-forward\r\n - name: Sync to latest main\r\n run: |\r\n git fetch origin main\r\n git checkout main\r\n git pull --rebase origin main\r\n\r\n # Make sure the script sees the current HEAD sha (not the original GITHUB_SHA)\r\n - name: Set GITHUB_SHA to current HEAD\r\n run: echo \"GITHUB_SHA=$(git rev-parse HEAD)\" >> $GITHUB_ENV\r\n\r\n - name: Use Node\r\n uses: actions/setup-node@v4\r\n with:\r\n node-version: '20'\r\n\r\n - name: Build indices and packs\r\n run: node scripts/build_ai_index.mjs\r\n\r\n - name: Verify outputs exist\r\n run: |\r\n ls -la docs | sed -n '1,200p'\r\n test -f docs/ai-index.min.json\r\n test -f docs/ai-docs-list.min.json\r\n test -f docs/ai-pack-all.min.json\r\n test -f docs/ai-pack-everything.manifest.min.json\r\n test -f docs/ai-pack-catalog.min.json\r\n\r\n # Commit and robust push with a rebase retry if main moved again\r\n - name: Commit docs if changed\r\n run: |\r\n if [[ -n \"$(git status --porcelain docs)\" ]]; then\r\n git config user.name \"github-actions[bot]\"\r\n git config user.email \"41898282+github-actions[bot]@users.noreply.github.com\"\r\n git add -A docs\r\n git commit -m \"build(ai): regenerate ai-index and packs\"\r\n\r\n # Try push; if behind, rebase and retry\r\n for i in 1 2 3; do\r\n git push origin HEAD:main && break\r\n echo \"Push failed, rebasing onto origin/main (attempt $i)...\"\r\n git fetch origin main\r\n git rebase origin/main || { git rebase --abort; exit 1; }\r\n done\r\n else\r\n echo \"No changes in docs/\"\r\n fi\r\n\r\n\r\n","inline_bytes":2284,"content_sha256":"975dbc5cce94ccae2ceaaf5de1ab5f7c9b11f457c217dc72febbb40f5cf2720a"},{"path":".github/workflows/ai-pack-validate.yml","size":6675,"sha":"fb165b953073a07d07ebb165cf47808dc86084cb","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/ai-pack-validate.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/ai-pack-validate.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: Validate AI Pack Endpoints\r\n\r\non:\r\n push:\r\n branches: [ main ]\r\n paths:\r\n - '.github/workflows/ai-pack-validate.yml'\r\n - 'docs/**'\r\n - 'scripts/build_ai_index.mjs'\r\n workflow_dispatch:\r\n schedule:\r\n - cron: '0 7 * * *' # daily 07:00 UTC\r\n\r\npermissions:\r\n contents: read\r\n\r\njobs:\r\n validate:\r\n runs-on: ubuntu-latest\r\n timeout-minutes: 10\r\n steps:\r\n - uses: actions/checkout@v4\r\n\r\n - uses: actions/setup-node@v4\r\n with:\r\n node-version: 20\r\n\r\n - name: Validate AI pack endpoints\r\n env:\r\n PAGES_OWNER: ${{ github.repository_owner }}\r\n REPO: ${{ github.repository }}\r\n FALLBACK_ROOT: https://candidquality.github.io/Barkday/\r\n run: |\r\n node - <<'JS'\r\n const fetch = global.fetch;\r\n\r\n const env = process.env;\r\n const owner = (env.PAGES_OWNER || '').toLowerCase();\r\n const repo = (env.REPO || '').split('/')[1] || 'Barkday';\r\n const fallback = env.FALLBACK_ROOT;\r\n const ROOT = `https://${owner}.github.io/${repo}/` || fallback;\r\n\r\n const ALL_URL = ROOT + 'docs/ai-pack-all.min.json';\r\n const MANI_URL = ROOT + 'docs/ai-pack-everything.manifest.min.json';\r\n\r\n const UA = 'Barkday-Validator/1.0 (+'+ROOT+')';\r\n const HEADERS = { 'User-Agent': UA, 'Accept': 'application/json' };\r\n const ok = r => r.ok || (r.status >= 200 && r.status < 400);\r\n\r\n (async () => {\r\n console.log('Root:', ROOT);\r\n\r\n // 1) Combined pack\r\n const allRes = await fetch(ALL_URL, { headers: HEADERS, cache: 'no-store' });\r\n if (!ok(allRes)) throw new Error(`combined pack fetch failed: ${allRes.status} ${ALL_URL}`);\r\n const allJson = await allRes.json();\r\n if (!allJson || typeof allJson !== 'object' || !allJson.sections) {\r\n throw new Error('combined pack: missing top-level \"sections\"');\r\n }\r\n console.log('✓ combined pack OK');\r\n\r\n // 2) Manifest\r\n const maniRes = await fetch(MANI_URL, { headers: HEADERS, cache: 'no-store' });\r\n if (!ok(maniRes)) throw new Error(`manifest fetch failed: ${maniRes.status} ${MANI_URL}`);\r\n const manifest = await maniRes.json();\r\n\r\n // Allow either {shards:[...]} or an array directly\r\n const shards = Array.isArray(manifest) ? manifest : (manifest.shards || []);\r\n if (!Array.isArray(shards) || !shards.length) {\r\n throw new Error('manifest: no shards found');\r\n }\r\n\r\n // Accept your field names AND legacy variants\r\n const getJsonURL = (it) =>\r\n it.url_json || it.json || it.href_json || it.urlJson || it.url;\r\n const getTxtURL = (it) =>\r\n it.url_txt || it.txt || it.href_txt || it.urlTxt;\r\n\r\n // Probe a few shards to keep runtime small\r\n const N = Math.min(5, shards.length);\r\n for (let i = 0; i < N; i++) {\r\n const it = shards[i];\r\n const j = getJsonURL(it);\r\n const t = getTxtURL(it);\r\n if (!j || !t) {\r\n throw new Error(`manifest shard #${i} unexpected shape: ${JSON.stringify(it)}`);\r\n }\r\n const absJ = j.startsWith('http') ? j : (ROOT + j.replace(/^\\//,''));\r\n const res = await fetch(absJ, { headers: HEADERS, cache: 'no-store' });\r\n if (!ok(res)) throw new Error(`shard #${i} fetch failed: ${res.status} ${absJ}`);\r\n const shard = await res.json();\r\n if (!shard || typeof shard !== 'object' || (!('sections' in shard) && !('items' in shard))) {\r\n throw new Error(`shard #${i} unexpected JSON structure`);\r\n }\r\n }\r\n\r\n console.log(`✓ manifest OK (${shards.length} shard entries; sampled ${N})`);\r\n })().catch(e => { console.error(e.stack || e); process.exit(1); });\r\n JS\r\n\r\n - name: Pack shape lint (non-blocking)\r\n continue-on-error: true\r\n env:\r\n PAGES_OWNER: ${{ github.repository_owner }}\r\n REPO: ${{ github.repository }}\r\n run: |\r\n node - <<'JS'\r\n const fetch = global.fetch;\r\n const owner = (process.env.PAGES_OWNER || '').toLowerCase();\r\n const repo = (process.env.REPO || '').split('/')[1] || 'Barkday';\r\n const ROOT = `https://${owner}.github.io/${repo}/`;\r\n const ALL_URL = ROOT + 'docs/ai-pack-all.min.json';\r\n const MANI_URL = ROOT + 'docs/ai-pack-everything.manifest.min.json';\r\n const HEADERS = { 'User-Agent': 'Barkday-Pack-Lint/1.0', 'Accept': 'application/json' };\r\n const ok = r => r.ok || (r.status >= 200 && r.status < 400);\r\n\r\n (async () => {\r\n // Combined pack presence & v2 runtime gift-feed hint\n const allRes = await fetch(ALL_URL, { headers: HEADERS });\n if (!ok(allRes)) { console.warn('⚠️ combined pack fetch:', allRes.status); return; }\n const all = await allRes.json();\n const sections = all.sections || {};\n const hasGifts = Object.values(sections).some(s => (s.items||[]).some(it =>\n (it.path || '').includes('data/dog-gifts-merged.json')));\n console.log(hasGifts ? '✓ combined pack contains data/dog-gifts-merged.json'\n : '⚠️ combined pack: data/dog-gifts-merged.json not found; maybe only in shards');\n\r\n // Approx total shard size (HEAD)\r\n const maniRes = await fetch(MANI_URL, { headers: HEADERS });\r\n if (!ok(maniRes)) { console.warn('⚠️ manifest fetch:', maniRes.status); return; }\r\n const manifest = await maniRes.json();\r\n const shards = Array.isArray(manifest) ? manifest : (manifest.shards || []);\r\n let approxBytes = 0;\r\n for (const it of shards) {\r\n const j = it.url_json || it.json || it.href_json || it.urlJson || it.url;\r\n if (!j) continue;\r\n const absJ = j.startsWith('http') ? j : (ROOT + j.replace(/^\\//,''));\r\n const head = await fetch(absJ, { method: 'HEAD' });\r\n const len = +(head.headers.get('content-length') || 0);\r\n approxBytes += len;\r\n }\r\n console.log(`Manifest shards listed: ${shards.length}`);\r\n console.log(`Approx shard bytes: ${approxBytes.toLocaleString()} (non-blocking hint)`);\r\n })().catch(e => { console.warn('lint error (non-blocking):', e.message); });\r\n JS\r\n","inline_bytes":6657,"content_sha256":"f61947719048fdae9c6fdee1cbc5a2ad6644457db17b87f267a09e0ec7330e05"},{"path":".github/workflows/codeql.yml","size":814,"sha":"2896a7ef9c833fb4f02588808f7958a8a3a60d27","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/codeql.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/codeql.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: CodeQL\r\n\r\non:\r\n push:\r\n branches: [ main ]\r\n pull_request:\r\n schedule:\r\n - cron: \"0 6 * * 1\"\r\n\r\npermissions:\r\n contents: read\r\n security-events: write\r\n\r\njobs:\r\n analyze:\r\n runs-on: ubuntu-latest\r\n permissions:\r\n actions: read\r\n contents: read\r\n security-events: write\r\n strategy:\r\n fail-fast: false\r\n matrix:\r\n language: [ \"javascript\" ]\r\n steps:\r\n - uses: actions/checkout@v4\r\n - name: Initialize CodeQL\r\n uses: github/codeql-action/init@v3\r\n with:\r\n languages: ${{ matrix.language }}\r\n - name: Autobuild\r\n uses: github/codeql-action/autobuild@v3\r\n - name: Perform CodeQL Analysis\r\n uses: github/codeql-action/analyze@v3\r\n with:\r\n category: \"/language:${{ matrix.language }}\"\r\n","inline_bytes":814,"content_sha256":"b43f9107fe5f6ca134c917be373a0377d958fdec99912faec3ec5e9254b32903"},{"path":".github/workflows/data-health.yml","size":1614,"sha":"81e175f81d8198ab01b8ee93d9f573c9afd4472f","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/data-health.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/data-health.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: Data health checks (non-blocking)\r\n\r\non:\r\n schedule:\r\n - cron: \"23 4 * * *\" # daily ~04:23 UTC\r\n pull_request:\r\n paths:\r\n - 'data/**/*.json'\r\n workflow_dispatch: {}\r\n\r\npermissions:\r\n contents: read\r\n\r\njobs:\r\n json-lint:\r\n runs-on: ubuntu-latest\r\n steps:\r\n - uses: actions/checkout@v4\r\n\r\n - name: Lint all data/*.json with jq\r\n run: |\r\n set -e\r\n shopt -s nullglob\r\n files=(data/*.json)\r\n if [ ${#files[@]} -eq 0 ]; then\r\n echo \"No data/*.json files to check\"; exit 0\r\n fi\r\n for f in \"${files[@]}\"; do\r\n echo \"Checking $f\"\r\n jq . \"$f\" >/dev/null\r\n done\r\n\r\n - name: Sanity checks (Node)\r\n run: |\r\n node - <<'JS'\r\n const fs = require('fs');\r\n function read(p){ return JSON.parse(fs.readFileSync(p,'utf8')); }\r\n try {\r\n const curves = read('data/curves.json');\r\n if (!curves || !curves.curves || !Object.keys(curves.curves).length) {\r\n throw new Error('data/curves.json missing \"curves\" map');\r\n }\r\n } catch (e) {\r\n console.error(e.message); process.exit(1);\r\n }\r\n try {\r\n const groups = read('data/breed_groups.json');\r\n if (!Array.isArray(groups) || !groups.length) {\r\n throw new Error('data/breed_groups.json should be a non-empty array');\r\n }\r\n } catch (e) {\r\n console.error(e.message); process.exit(1);\r\n }\r\n console.log('Data sanity OK');\r\n JS\r\n","inline_bytes":1614,"content_sha256":"44a2e4f79898457e7f02a9f565bc3ddae9e797576ffed180523cbcad8a9484dd"},{"path":".github/workflows/doc-lint.yml","size":653,"sha":"4a769296ad5c11c9998e6015edabf5c07e35b345","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/doc-lint.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/doc-lint.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: Lint Docs for Policy Regressions\r\non:\r\n push:\r\n branches: [ main ]\r\n paths: [ 'docs/**/*.md', '.github/workflows/doc-lint.yml' ]\r\n pull_request:\r\n paths: [ 'docs/**/*.md' ]\r\n workflow_dispatch: {}\r\n\r\npermissions: { contents: read }\r\n\r\njobs:\r\n lint:\r\n runs-on: ubuntu-latest\r\n steps:\r\n - uses: actions/checkout@v4\r\n - name: Fail on forbidden phrases\r\n run: |\r\n set -e\r\n if rg -n -i 'gifts?[^\\\\n]{0,80}(gated|paywall)' docs/*.md; then\r\n echo \"::error::Found forbidden phrasing (gifts cannot be gated/paywalled).\"\r\n exit 1\r\n fi\r\n echo \"Docs lint passed.\"\r\n","inline_bytes":653,"content_sha256":"84f1518031dca38b7cd5c64a04d7386c1622912b34f345fc687fb01156781a61"},{"path":".github/workflows/lighthouse.yml","size":951,"sha":"600221c05ea856843caa256f46565cbe7bfa1b43","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/lighthouse.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/lighthouse.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: Lighthouse CI\r\n\r\non:\r\n push:\r\n branches: [ main ]\r\n pull_request:\r\n workflow_dispatch:\r\n\r\npermissions:\r\n contents: read\r\n\r\njobs:\r\n lhci:\r\n runs-on: ubuntu-latest\r\n steps:\r\n - uses: actions/checkout@v4\r\n with:\r\n fetch-depth: 0\r\n\r\n - name: Ensure lighthouserc.json exists\r\n run: |\r\n test -f lighthouserc.json || { echo \"::error::Missing lighthouserc.json at repo root\"; exit 1; }\r\n ls -la lighthouserc.json\r\n\r\n - uses: actions/setup-node@v4\r\n with:\r\n node-version: 20\r\n\r\n - name: Install Lighthouse CI\r\n run: npm i -g @lhci/cli\r\n\r\n - name: Run Lighthouse CI\r\n # Token is optional; enables PR status checks (gets rid of “GitHub token not set” message)\r\n env:\r\n LHCI_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\r\n GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\r\n run: lhci autorun --config=./lighthouserc.json\r\n","inline_bytes":947,"content_sha256":"b38b52b72d716e2886e1f1ba0bb6b84b135739231ceba2c7234a09f9375cdf88"},{"path":".github/workflows/link-check.yml","size":646,"sha":"2b93b719578792d67327045d39695ca4150f7999","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/link-check.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/link-check.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: Link check (site & docs)\r\non:\r\n push: { branches: [ main ] }\r\n pull_request:\r\n schedule: [ { cron: \"23 4 * * 1\" } ] # weekly\r\npermissions: { contents: read }\r\njobs:\r\n lychee:\r\n runs-on: ubuntu-latest\r\n steps:\r\n - uses: actions/checkout@v4\r\n - name: Check links with lychee\r\n uses: lycheeverse/lychee-action@v1\r\n with:\r\n args: >-\r\n --verbose --no-progress\r\n --accept 200,206,301,302,307,308\r\n --exclude-mail\r\n --timeout 20\r\n **/*.md **/*.html\r\n !node_modules/**\r\n env:\r\n GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\r\n","inline_bytes":646,"content_sha256":"7771f010690303e9ba82f4de996582e2330e09f49767eb0a8d17192f2068ba98"},{"path":".github/workflows/markdown-lint.yml","size":854,"sha":"f88996b4cac9fe7d1ca446f57868689166910706","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/markdown-lint.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/markdown-lint.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: Lint Markdown\r\n\r\non:\r\n push:\r\n branches: [main]\r\n paths:\r\n - \"**/*.md\"\r\n - \".markdownlint-cli2.yaml\"\r\n - \".github/workflows/markdown-lint.yml\"\r\n pull_request:\r\n paths:\r\n - \"**/*.md\"\r\n - \".markdownlint-cli2.yaml\"\r\n - \".github/workflows/markdown-lint.yml\"\r\n\r\npermissions:\r\n contents: read\r\n\r\njobs:\r\n markdown:\r\n runs-on: ubuntu-latest\r\n steps:\r\n - uses: actions/checkout@v4\r\n\r\n - name: Markdown lint\r\n uses: DavidAnson/markdownlint-cli2-action@v16\r\n with:\r\n globs: |\r\n **/*.md\r\n !node_modules/**\r\n !dist/**\r\n !build/**\r\n\r\n - name: Spellcheck\r\n uses: codespell-project/actions-codespell@v2\r\n with:\r\n check_filenames: true\r\n path: .\r\n ignore_words_list: Barkday,chewer\r\n ","inline_bytes":854,"content_sha256":"99216c58d511f09af9392fa6b53ec8b06c7a0cebec03de3c96692d9fdc190b3b"},{"path":".github/workflows/pages.yml","size":947,"sha":"838b2898fa913de9925ae7e3d2d16c4db136f4d3","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/pages.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/pages.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: Publish Barkday page\r\n\r\non:\r\n push:\r\n branches: [ main ]\r\n workflow_dispatch:\r\n\r\npermissions:\r\n contents: read\r\n pages: write\r\n id-token: write\r\n\r\nconcurrency:\r\n group: \"pages\"\r\n cancel-in-progress: true\r\n\r\njobs:\r\n build:\r\n runs-on: ubuntu-latest\r\n steps:\r\n - uses: actions/checkout@v4\r\n\r\n # Build the AI indices (master + docs list + data list)\r\n - uses: actions/setup-node@v4\r\n with:\r\n node-version: 20\r\n - name: Build AI indices\r\n run: node scripts/build_ai_index.mjs\r\n\r\n # Upload everything in the repo root (includes /docs/*)\r\n - name: Upload artifact\r\n uses: actions/upload-pages-artifact@v4\r\n with:\r\n path: .\r\n\r\n deploy:\r\n environment:\r\n name: github-pages\r\n url: ${{ steps.deployment.outputs.page_url }}\r\n runs-on: ubuntu-latest\r\n needs: build\r\n steps:\r\n - id: deployment\r\n uses: actions/deploy-pages@v4\r\n","inline_bytes":947,"content_sha256":"f40fd0f176b3621ca695e448abccfc9d8437bb3acc0116f89f9b04d5c098ed1a"},{"path":".github/workflows/validate-json.yml","size":2029,"sha":"686e1a7ce6b9f58fd2892fc9be1b90213fe9da8e","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/validate-json.yml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.github/workflows/validate-json.yml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"name: Validate Barkday gift catalog\n\non:\n push:\n branches: [ main ]\n paths:\n - 'app.js'\n - 'data/dog-gifts-base.json'\n - 'data/dog-gifts-catalog.json'\n - 'data/dog-gifts-merged.json'\n - 'data/dog-gifts-preferred.json'\n - 'data/gift-batches/*.json'\n - 'schema/dog-gifts-*.json'\n - 'scripts/rebuild-gift-catalog.mjs'\n - 'scripts/validate-gifts-v2.mjs'\n - 'scripts/merge-gifts-v2.mjs'\n - 'scripts/smoke-gift-logic.mjs'\n - 'scripts/barkday-doctor.mjs'\n - '.github/workflows/validate-json.yml'\n pull_request:\n paths:\n - 'app.js'\n - 'data/dog-gifts-base.json'\n - 'data/dog-gifts-catalog.json'\n - 'data/dog-gifts-merged.json'\n - 'data/dog-gifts-preferred.json'\n - 'data/gift-batches/*.json'\n - 'schema/dog-gifts-*.json'\n - 'scripts/rebuild-gift-catalog.mjs'\n - 'scripts/validate-gifts-v2.mjs'\n - 'scripts/merge-gifts-v2.mjs'\n - 'scripts/smoke-gift-logic.mjs'\n - 'scripts/barkday-doctor.mjs'\n - '.github/workflows/validate-json.yml'\n workflow_dispatch: {}\n\npermissions:\n contents: read\n\njobs:\n validate:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node\n uses: actions/setup-node@v4\n with:\n node-version: '22'\n\n - name: Check JavaScript syntax\n run: |\n node --check ./app.js\n node --check ./scripts/barkday-doctor.mjs\n\n - name: Rebuild v2 gift catalog\n run: node ./scripts/rebuild-gift-catalog.mjs\n\n - name: Validate v2 gift catalog\n run: node ./scripts/validate-gifts-v2.mjs ./data/dog-gifts-catalog.json ./data/dog-gifts-preferred.json\n\n - name: Merge v2 runtime gift feed\n run: node ./scripts/merge-gifts-v2.mjs ./data/dog-gifts-catalog.json ./data/dog-gifts-preferred.json ./data/dog-gifts-merged.json\n\n - name: Smoke gift logic\n run: node ./scripts/smoke-gift-logic.mjs\n\n - name: Doctor\n run: node ./scripts/barkday-doctor.mjs\n","inline_bytes":2029,"content_sha256":"f82d1a62b6f33a13998ab4a51bc9399a26433dcdb22c5b9bcf926995856be9f4"},{"path":".gitignore","size":54,"sha":"941f0d42d681ad512527689c0eeefdbdc8018533","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.gitignore","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.gitignore","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"IyBBaWRlciBsb2NhbCBhcnRpZmFjdHMKLmFpZGVyKgouYWlkZXIudGFncy5jYWNoZS52NC8K","inline_bytes":72,"content_sha256":"2d0b27ad0efb9f0f4e976221282c876cbb660af353a6ae2ba13e8d3b5741b4d0"},{"path":".markdownlint-cli2.yaml","size":421,"sha":"ba874de500893ad4adcc31558b1d1cc6d0c11aab","media_type":"text/yaml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.markdownlint-cli2.yaml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.markdownlint-cli2.yaml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"globs:\n - \"**/*.md\"\n - \"!node_modules/**\"\n - \"!dist/**\"\n - \"!build/**\"\n\nconfig:\n default: true\n\n # Barkday docs are operational documents, not prose manuscripts.\n MD013: false # line-length\n MD024:\n siblings_only: true # allow same heading text in different sections\n MD033: false # inline HTML allowed when needed\n MD036: false # allow emphasis-as-heading style where already used","inline_bytes":421,"content_sha256":"0aa2cf2bde041facd05af3fc93121b6a3499aae117b029228bf71dbc5f5c0493"},{"path":".nojekyll","size":1,"sha":"8b137891791fe96927ad78e64b0aad7bded08bdc","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.nojekyll","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/.nojekyll","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"Cg==","inline_bytes":4,"content_sha256":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b"},{"path":"404.html","size":540,"sha":"fcde30413f551ba2b35bbce1d78cbbc03768fac1","media_type":"text/html","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/404.html","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/404.html","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"\n\n\n \n \n 404 • Barkday™\n \n \n \n\n\n

404

\n

We couldn’t find that page.

\n

Go back to Barkday →

\n\n\n","inline_bytes":532,"content_sha256":"22a2091c642cf3cd50af8c08c881768451f464a436f621d6d41b41ef11b179b9"},{"path":"AGENTS.md","size":15362,"sha":"7e01e30fb119611ddc97dd0a1c07e1a1f07def37","media_type":"text/markdown","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/AGENTS.md","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/AGENTS.md","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"# Barkday repository instructions for local agent work\n\nLast updated: 2026-05-03\n\nThis file is the operating contract for all local agent work in this repository.\n\nRead this file before changing anything.\n\nIf a task touches files under `data/`, also read `data/AGENTS.md` before making changes.\n\n## 1) Project purpose\n\nBarkday is a public-facing dog age and Barkday planning application with:\n\n- a browser-based application shell\n- a mobile store wrapper path using Trusted Web Activity style behavior\n- runtime-fetched data\n- a public recommendation layer\n- a future premium and proprietary overlay layer\n\nThe immediate goal is launch readiness, not experimental churn.\n\nWork should reduce ambiguity, reduce dual-system drift, improve validation, and move the project toward a stable release.\n\n## 2) Non-negotiable operating principles\n\n1. Do not guess. \n If inputs are missing, contradictory, or ambiguous, stop and explain the gap instead of inventing structure or behavior.\n\n2. Do not silently choose the wrong source of truth. \n This repository currently contains both legacy and newer v2 data paths. Verify which one is canonical for the task before editing files.\n\n3. Do not widen task scope without reason. \n Make the smallest change that fully solves the requested problem.\n\n4. Do not clean up unrelated files. \n No drive-by refactors, renames, formatting churn, or dependency changes unless explicitly requested or required for the task.\n\n5. Do not break the release path. \n Any change that touches runtime data loading, gift feeds, caching, service worker behavior, or affiliate links must be validated before commit.\n\n6. Do not violate affiliate or platform rules. \n Amazon Associates compliance and mobile wrapper behavior are part of the product contract, not optional polish.\n\n7. Do not ship proprietary data inside the app shell if it is intended to remain remote-only. \n Public shell and remotely fetched data are intentional architectural boundaries.\n\n8. Re-verify against live-access links after meaningful changes. \n This repository includes generated live access indices and raw file links specifically so changes can be compared against live build state.\n\n## 3) Current repository reality\n\nThe repository currently contains both:\n\n- a legacy root-level gift feed system:\n - `dog-gifts.json`\n - `dog-gifts.schema.json`\n\n- a newer v2 catalog pipeline:\n - `data/dog-gifts-base.json`\n - `data/dog-gifts-catalog.json`\n - `data/dog-gifts-merged.json`\n - `data/dog-gifts-preferred.json`\n - `schema/dog-gifts-catalog.schema.v2.json`\n - `schema/dog-gifts-preferred.schema.v2.json`\n - `scripts/rebuild-gift-catalog.mjs`\n - `scripts/merge-gifts-v2.mjs`\n - `scripts/validate-gifts-v2.mjs`\n\nThe application shell is still centered around:\n\n- `index.html`\n- `app.js`\n- `style.css`\n- `service-worker.js`\n- `js/runtime-fetch.js`\n\nThe application codebase is still largely monolithic in `app.js`.\n\nThis repository also includes:\n\n- many GitHub workflows under `.github/workflows/`\n- local git hooks under `.githooks/`\n- a docs area with notes, decisions, maintainers, and generated AI index files\n- PowerShell tools under `tools/`\n- raw Amazon search and item fetch files under `data/raw-amazon/`\n\nTreat the current state as a migration-in-progress, not a finished architecture.\n\n## 4) Architectural direction that must guide work\n\nThe intended end-state is:\n\n- The installed or wrapped app is the shell only.\n- Changeable public product and recommendation data is fetched remotely at runtime.\n- Proprietary or premium data stays outside the shipped app and is fetched separately.\n- Weekly or frequent gift updates must not require a full app update.\n- The old flat gift feed is legacy and should not be expanded further unless a temporary compatibility export is explicitly required.\n\nThis means:\n\n- the long-term canonical gift model is the v2 structured feed\n- remote feed hosting is acceptable and preferred for public runtime gift data\n- proprietary logic and overlays must remain remote when intended\n- the app shell must normalize remote data safely\n\n## 5) Compliance rules that are binding on engineering work\n\nAmazon-related work must follow these rules:\n\n1. Relationship disclosures must remain visible where required.\n2. All affiliate links must remain proper Special Links with the correct tag and any approved subtags.\n3. No price-tracking history, price-alert features, or similar prohibited behaviors.\n4. If price or availability is shown, freshness, timestamp, and disclaimer requirements must be met.\n5. Do not store Amazon image binaries.\n6. Non-image Amazon Program Content must not be cached longer than 24 hours.\n7. Client apps must not cache Amazon Program Content offline.\n8. Mobile wrapper behavior must open Amazon externally, not inside embedded WebViews.\n9. No scraping reviews or star ratings from Amazon pages.\n10. Do not use Amazon Program Content or Special Link data to train or fine-tune machine learning systems.\n11. Do not introduce pop-up, framed, cloaked, or misleading affiliate placements.\n12. Keep regional host correctness in mind for links when regional logic is added.\n\nWhen in doubt, preserve compliance first and convenience second.\n\nReference documents already present in project context:\n\n- `AMAZON_ASSOCIATES_COMPLIANCE.md`\n- the current live access note for Barkday raw and index links\n\n## 6) Source-of-truth map\n\n### 6.1 Application shell and runtime behavior\n\nPrimary files:\n\n- `index.html`\n- `app.js`\n- `style.css`\n- `service-worker.js`\n- `js/runtime-fetch.js`\n\n### 6.2 Gift data system\n\nCanonical direction:\n\n- v2 data under `data/` and `schema/`\n\nKey files:\n\n- `data/dog-gifts-base.json`\n- `data/dog-gifts-catalog.json`\n- `data/dog-gifts-merged.json`\n- `data/dog-gifts-preferred.json`\n- `schema/dog-gifts-catalog.schema.v2.json`\n- `schema/dog-gifts-preferred.schema.v2.json`\n\nLegacy files:\n\n- `dog-gifts.json`\n- `dog-gifts.schema.json`\n\nLegacy files may still be referenced by old code. Do not assume they are canonical.\n\n### 6.3 Data import and build pipeline\n\nRelevant scripts:\n\n- `scripts/amazon-getitems-to-catalog.mjs`\n- `scripts/build-auto-batch-from-getitems.mjs`\n- `scripts/rebuild-gift-catalog.mjs`\n- `scripts/merge-gifts-v2.mjs`\n- `scripts/validate-gifts-v2.mjs`\n- `scripts/validate-gifts.mjs`\n- `scripts/smoke-gift-logic.mjs`\n- `scripts/barkday-doctor.mjs`\n\nPowerShell helpers:\n\n- `tools/amazon-get-items.ps1`\n- `tools/amazon-search-items.ps1`\n- `tools/run-barkday-checks.ps1`\n- `tools/verify.ps1`\n\n### 6.4 Live access and verification\n\nThis repository has generated live-access support through:\n\n- `docs/ai-index.min.json`\n- `docs/ai-pack-core.txt`\n- `docs/ai-pack-data-config.txt`\n- `docs/ai-pack-everything.manifest.min.json`\n\nWhen a task changes public behavior, verify using local files first, then compare to live-access references before declaring the task complete.\n\n## 7) Current known issues and cautions\n\n1. There are two gift systems in parallel. Do not add new product work to the wrong one.\n2. `data/gift-batches/2026-04-21-batch-07.json` appears suspicious and should be inspected before being trusted.\n3. The old root gift schema and the newer v2 schemas are both present. Do not mix their assumptions.\n4. `app.js` is large and contains many concerns. Avoid broad refactors unless specifically requested.\n5. Raw Amazon import artifacts are numerous. They are useful as evidence and inputs, but they are not the publishable feed.\n6. Do not hand-edit generated output files when the correct change belongs in source inputs or generator scripts.\n\n## 8) Task classification rules\n\nBefore starting work, classify the task.\n\n### Type A - application shell task\n\nExamples:\n\n- loader changes\n- rendering changes\n- filter logic\n- service worker behavior\n- external link behavior\n- wrapper-related logic\n\nRead first:\n\n- this file\n- relevant code files\n- live access references if the task affects deployed behavior\n\n### Type B - gift data model or pipeline task\n\nExamples:\n\n- catalog field changes\n- import logic\n- batch processing\n- v2 schema work\n- canonical feed rules\n- dedupe or merge logic\n\nRead first:\n\n- this file\n- `data/AGENTS.md`\n- relevant scripts and schemas\n\n### Type C - compliance-sensitive task\n\nExamples:\n\n- affiliate links\n- product cards\n- price or availability\n- data refresh behavior\n- mobile wrapper opening behavior\n- disclosures\n\nRead first:\n\n- this file\n- compliance guidance\n- any relevant UI or service-worker files\n\n### Type D - infrastructure or publishing task\n\nExamples:\n\n- GitHub workflows\n- pages publishing\n- AI index generation\n- validation workflow changes\n- deployment and verification improvements\n\nRead first:\n\n- this file\n- relevant workflow files\n- any existing docs in `docs/decisions/` or `docs/`\n\n## 9) Required work habits for Codex or any local agent\n\n1. Read before edit. \n Open the target file and any immediately related file before writing changes.\n\n2. Prefer source fixes over output edits. \n If a generated file is wrong, fix the source file or generator unless a direct output edit is explicitly intended.\n\n3. Preserve file roles. \n Do not convert a generated file into a hand-maintained file without stating that architectural change clearly.\n\n4. Keep diffs reviewable. \n Break work into focused commits where possible.\n\n5. Explain risk before risky edits. \n If a task touches:\n\n - `app.js`\n - `service-worker.js`\n - gift schema contracts\n - affiliate link logic\n - publishing behavior\n\n summarize the risk before making broad edits.\n\n6. Re-run validations after changes. \n No \"looks right\" completions.\n\n7. Re-verify live-access paths after relevant public changes. \n The project owner explicitly wants work grounded in the live file references when needed.\n\n## 10) Validation commands\n\nRun the commands that match the task.\n\n### 10.1 Core gift pipeline validation\n\nFrom repo root:\n\n`node .\\scripts\\rebuild-gift-catalog.mjs`\n\n`node .\\scripts\\validate-gifts-v2.mjs .\\data\\dog-gifts-catalog.json .\\data\\dog-gifts-preferred.json`\n\n`node .\\scripts\\merge-gifts-v2.mjs .\\data\\dog-gifts-catalog.json .\\data\\dog-gifts-preferred.json .\\data\\dog-gifts-merged.json`\n\n`node .\\scripts\\smoke-gift-logic.mjs`\n\n`node .\\scripts\\barkday-doctor.mjs`\n\n### 10.2 Local verification helper\n\nIf maintained and applicable:\n\n`.\\tools\\run-barkday-checks.ps1`\n\n### 10.3 Manual browser validation for application shell tasks\n\nWhen `app.js`, `index.html`, `style.css`, `service-worker.js`, or runtime data loading is changed:\n\n- open the app locally\n- test gift loading\n- test at least one puppy case\n- test at least one senior case\n- test at least one toy-sized case\n- test at least one giant-sized case\n- test each chewer level if gift logic is touched\n- test ignore toggles if filtering is touched\n- verify external opening behavior for Amazon links if that path is touched\n\n### 10.4 Deployment-aware validation\n\nIf public behavior changes:\n\n- compare local changed files to live-access raw references or generated indices\n- verify that deployment-oriented files still point to the intended assets and data paths\n\n## 11) Gift-system migration rules\n\nUntil migration is complete:\n\n1. Do not add new real catalog work to the legacy root `dog-gifts.json` path unless explicitly building a temporary compatibility bridge.\n2. Prefer the v2 catalog pipeline.\n3. Keep public shell behavior and data contract aligned.\n4. If changing the gift feed contract, update:\n\n - loader code\n - validation\n - schema\n - documentation\n - caching assumptions\n\n5. Do not claim migration is complete while both systems still drift independently.\n\n## 12) Remote data and proprietary data rules\n\n1. Public recommendation and gift data can live in a remote runtime-fetched file or endpoint.\n2. Proprietary overlays, premium data, or protected logic must remain remote if intended to stay out of the public app shell.\n3. Do not bundle protected data into the shipped shell as a shortcut.\n4. Any new protected data path must fail gracefully if unavailable.\n5. Public remote data should be designed so it can update without forcing a new app release.\n\n## 13) Service worker and caching rules\n\n1. Be conservative when editing `service-worker.js`.\n2. Do not let cache-first behavior make Amazon-derived or frequently updated runtime data look fresher than it is.\n3. Respect the 24-hour maximum for non-image Amazon Program Content.\n4. Do not enable offline client caching for Amazon Program Content.\n5. If a feed or public data path changes, consider whether the service worker cache name or fetch strategy must also change.\n6. Verify that app shell caching and runtime data freshness are not confused with each other.\n\n## 14) Documentation rules\n\n1. Update docs when the architecture or canonical path changes.\n2. Use `docs/decisions/` for stable architectural decisions.\n3. Do not dump raw temporary notes into permanent docs unless the information is stable and useful.\n4. Keep changelog and maintainers information accurate if ownership or release practices change.\n5. If the meaning of \"canonical gift feed\" changes, document it.\n\n## 15) Git workflow rules\n\n1. Work from the repository root: `C:\\Users\\Master\\Documents\\Barkday`\n2. Prefer a task branch or worktree for non-trivial work.\n3. Before commit:\n\n - inspect changed files\n - run relevant validations\n - check for unintended edits\n\n4. Commit messages should describe the actual change, not vague activity.\n5. Do not push broken validation state.\n6. If the branch is behind remote, fetch and rebase before push unless instructed otherwise.\n\n## 16) What done means\n\nA task is done only when all of the following are true:\n\n1. The requested change is actually implemented.\n2. The correct source-of-truth files were edited.\n3. Relevant validations were run and passed.\n4. No obvious compliance guardrail was violated.\n5. No obvious architecture regression was introduced.\n6. If public runtime behavior changed, the change was checked against live-access expectations.\n7. The resulting diff is understandable and reviewable.\n8. A clear commit can be made.\n\n## 17) What not to do\n\n- Do not invent product data.\n- Do not scrape Amazon pages.\n- Do not add pricing history features.\n- Do not keep both old and new gift systems evolving in parallel without explicit reason.\n- Do not bury critical feed-path changes inside unrelated commits.\n- Do not make temporary shortcuts that ship proprietary data in the public shell.\n- Do not use Amazon content for model training or fine-tuning.\n- Do not add new dependencies casually.\n- Do not change deployment or service-worker behavior without validation.\n\n## 18) First-read checklist for new sessions\n\nAt the beginning of a new local agent session:\n\n1. Read this file.\n2. If touching gifts or runtime data, read `data/AGENTS.md`.\n3. Confirm current branch and git status.\n4. Identify whether the task is shell, data, compliance, or publishing work.\n5. Identify the canonical files for the task.\n6. Identify the validation commands that must be run.\n7. Only then begin editing.\n\n## 19) Preferred next-step behavior for the gift migration\n\nWhen asked to continue gift-system work, default to this sequence:\n\n1. clarify canonical feed path if ambiguous\n2. inspect loader\n3. inspect schema\n4. inspect validation\n5. make minimal aligned change\n6. rebuild and validate\n7. verify runtime behavior\n8. commit cleanly\n","inline_bytes":15362,"content_sha256":"3d1d763c97bf5ed7537ea5e92d007c11ef7da4c15932d1fa05d09da61f1abb53"},{"path":"LICENSE","size":1274,"sha":"f414ccc8b3d2347b2ced0deaf9ad0f73c373e90e","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/LICENSE","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/LICENSE","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"QmFya2RheeKEoiBBcHBsaWNhdGlvbiBMaWNlbnNlCkNvcHlyaWdodCDCqSAyMDI1IENhbmRpZFF1YWxpdHkuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuCgpUaGlzIHNvZnR3YXJlLCBpbmNsdWRpbmcgYWxsIHNvdXJjZSBjb2RlLCBkZXNpZ24sIGltYWdlcywgZGF0YSBmaWxlcywgYW5kCmFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiAodGhlICJTb2Z0d2FyZSIpLCBpcyB0aGUgcHJvcHJpZXRhcnkgd29yayBvZiB0aGUKcHJvamVjdCBvd25lciBhbmQgaXMgcHJvdGVjdGVkIGJ5IGNvcHlyaWdodCwgdHJhZGVtYXJrLCBhbmQgb3RoZXIgYXBwbGljYWJsZQpsYXdzLgoKUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCB0byBpbmRpdmlkdWFscyB0byB2aWV3IGFuZCB1c2UgdGhlIFNvZnR3YXJlIGZvcgpwZXJzb25hbCwgbm9uLWNvbW1lcmNpYWwgcHVycG9zZXMgb25seSB0aHJvdWdoIHRoZSBvZmZpY2lhbCBCYXJrZGF54oSiIHdlYnNpdGUKb3IgYXV0aG9yaXplZCBkaXN0cmlidXRpb24gY2hhbm5lbHMuCgpSZXN0cmljdGlvbnMKLS0tLS0tLS0tLS0tCldpdGhvdXQgcHJpb3Igd3JpdHRlbiBjb25zZW50IGZyb20gdGhlIGNvcHlyaWdodCBob2xkZXIsIHlvdSBtYXkgTk9UOgotIENvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIG9yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZS4KLSBVc2UgdGhlIFNvZnR3YXJlLCBpbiB3aG9sZSBvciBpbiBwYXJ0LCBmb3IgYW55IGNvbW1lcmNpYWwgcHVycG9zZS4KLSBSZW1vdmUgb3IgYWx0ZXIgYW55IGNvcHlyaWdodCwgdHJhZGVtYXJrLCBvciBwcm9wcmlldGFyeSBub3RpY2VzLgoKVHJhZGVtYXJrCi0tLS0tLS0tLQpUaGUgQmFya2RheeKEoiBuYW1lIGFuZCBhc3NvY2lhdGVkIGJyYW5kaW5nIGFyZSBwcm90ZWN0ZWQgYXMgdHJhZGVtYXJrcy4gVXNlIG9mCnRoZSBCYXJrZGF54oSiIG1hcmsgd2l0aG91dCBleHByZXNzIHBlcm1pc3Npb24gaXMgc3RyaWN0bHkgcHJvaGliaXRlZC4KCkRpc2NsYWltZXIKLS0tLS0tLS0tLQpUaGUgU29mdHdhcmUgaXMgcHJvdmlkZWQg4oCcYXMgaXMs4oCdIHdpdGhvdXQgd2FycmFudHkgb2YgYW55IGtpbmQsIGV4cHJlc3Mgb3IKaW1wbGllZC4gSW4gbm8gZXZlbnQgc2hhbGwgdGhlIGNvcHlyaWdodCBob2xkZXIgYmUgbGlhYmxlIGZvciBhbnkgZGFtYWdlcwphcmlzaW5nIGZyb20gdGhlIHVzZSBvZiB0aGUgU29mdHdhcmUuCgpBbGwgcmlnaHRzIG5vdCBleHByZXNzbHkgZ3JhbnRlZCBoZXJlaW4gYXJlIHJlc2VydmVkLgo=","inline_bytes":1700,"content_sha256":"f922e4d3a5af73e337108522235c48218707e31dae2635e22bb85b11239bff59"},{"path":"README.md","size":3390,"sha":"ba89f60cbc62628087a1d312e31fc170b7cbdfe7","media_type":"text/markdown","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/README.md","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/README.md","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"# Barkday(TM)\n\n## Build & Docs Status\n\n[![Publish Barkday page](https://github.com/CandidQuality/Barkday/actions/workflows/pages.yml/badge.svg)](https://github.com/CandidQuality/Barkday/actions/workflows/pages.yml)\n\n## Live site: \n\n## AI Pack (router): \n\n\n[![Docs Policy Lint](https://github.com/CandidQuality/Barkday/actions/workflows/doc-lint.yml/badge.svg)](https://github.com/CandidQuality/Barkday/actions/workflows/doc-lint.yml)\n\n[![Validate Barkday gift catalog](https://github.com/CandidQuality/Barkday/actions/workflows/validate-json.yml/badge.svg)](https://github.com/CandidQuality/Barkday/actions/workflows/validate-json.yml)\n\nCelebrate every dog's next birthday - intelligently.\n\n## What Barkday does\n\nBarkday (TM) converts your dog's age into \"human years\" and creates a personalized plan to celebrate each milestone.\n\nIt helps guardians strengthen routines, improve wellbeing, and make every year together count - all while keeping data\nprivate and offline.\n\n---\n\n## Live App\n\nUse Barkday in your browser or install it directly to your device:\n****\n\nNo sign-up - No cloud sync - Works offline\nAll information stays safely on your device.\n\n---\n\n## Features\n\n- Converts real age to \"dog years\" and shows human-age equivalents\n- Personalized celebration and care ideas based on breed and life stage\n- Training, enrichment, bonding, and nutrition tips that evolve over time\n- Local profiles for multiple dogs\n- Works completely offline after first load\n- Optional gift ideas - hidden by default\n\n> Educational use only. Barkday does not provide veterinary advice.\n\n---\n\n## Roadmap\n\nBarkday continues to grow with:\n\n- Expanded breed coverage (international and designer breeds)\n- Optional premium add-ons (reminders, widgets, PDF exports)\n- Android app distribution via Google Play (Trusted Web Activity)\n- Continued data refinement through community feedback\n\nFor current continuity, parking-lot items, and staged next work, see\n[`docs/roadmap/barkday-continuity-roadmap.md`](docs/roadmap/barkday-continuity-roadmap.md).\n\n---\n\n## Privacy\n\nBarkday runs entirely in your browser and never uploads personal data.\nAll calculations and saved profiles remain stored locally.\n\n---\n\n## Trademark\n\n**BARKDAY(TM)** is a pending trademark of the project owner.\nAll other marks belong to their respective owners.\n\n---\n\n## License\n\n(c) 2025 Barkday(TM) and CandidQuality All rights reserved.\n\nThis software, design, and all accompanying materials are proprietary intellectual property.\nNo part of this project-including code, data files, images, text, or other assets-may be\ncopied, modified, reproduced, distributed, reverse-engineered, or used in any derivative\nwork, whether in whole or in part, without the prior written permission of the copyright owner.\n\nBarkday(TM) and the Barkday logo are pending trademarks of the project owner.\nAll other marks belong to their respective owners.\n\nThis repository is provided for internal development, testing, and verification only.\nNo license or permission is granted to use, reproduce, or distribute this software\noutside authorized channels.\n\n---\n\n## \"Better birthdays, better care, better lives - one dog at a time.\"\n","inline_bytes":3390,"content_sha256":"878692b4070aa2f1486b6968f5db1d656f774a04934bf0b4a1732dbfbc3ec94a"},{"path":"app-celebrate.js","size":5156,"sha":"cefb7a34b305fa5505f6388a80b08a1fdc9ac0e8","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/app-celebrate.js","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/app-celebrate.js","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"/* Barkday™ Celebration Patch (confetti timing fix)\r\n - Waits for drawer/modal to be visible before firing confetti\r\n - No changes to app.js required\r\n - Safe to include multiple times (no double binding)\r\n - v2025-10-22\r\n*/\r\n(function () {\r\n if (window.__bdCelebratePatched) return; // idempotent\r\n window.__bdCelebratePatched = true;\r\n\r\n // --- small helper: wait for a selector to be present/visible\r\n function waitFor(selector, timeout = 4000) {\r\n return new Promise(resolve => {\r\n const hit = document.querySelector(selector);\r\n if (hit) return resolve(hit);\r\n const mo = new MutationObserver(() => {\r\n const found = document.querySelector(selector);\r\n if (found) { mo.disconnect(); resolve(found); }\r\n });\r\n mo.observe(document.body, {\r\n childList: true,\r\n subtree: true,\r\n attributes: true,\r\n attributeFilter: ['aria-hidden','open','class']\r\n });\r\n setTimeout(() => { mo.disconnect(); resolve(null); }, timeout);\r\n });\r\n }\r\n\r\n // Heuristic: these indicate your drawer/modal is actually open\r\n const READY_SEL = '#bdSaved[aria-hidden=\"false\"], .bd-modal[open], .bd-drawer[aria-hidden=\"false\"]';\r\n\r\n // Fireworks helper that always paints on top and never blocks clicks\r\n function fireConfettiSafe() {\r\n try {\r\n // double RAF: ensure layout has finished before we create a canvas\r\n requestAnimationFrame(() => requestAnimationFrame(() => {\r\n try {\r\n const before = document.querySelector('#__bdConfettiCanvas');\r\n if (before) before.remove();\r\n\r\n // If your confetti() already creates and manages its own canvas, this call is enough:\r\n // confetti();\r\n\r\n // If you use a canvas-based confetti that needs a target, create a temp canvas:\r\n const c = document.createElement('canvas');\r\n c.id = '__bdConfettiCanvas';\r\n c.style.position = 'fixed';\r\n c.style.left = '0';\r\n c.style.top = '0';\r\n c.style.width = '100vw';\r\n c.style.height = '100vh';\r\n c.style.pointerEvents = 'none';\r\n c.style.zIndex = '2147483647';\r\n document.body.appendChild(c);\r\n\r\n // Try native confetti() first if it exists\r\n if (typeof window.confetti === 'function') {\r\n window.confetti(); // many libs hook their own full-screen canvas\r\n } else {\r\n // minimal fallback sparkle (non-blocking) so users still see *something*\r\n const ctx = c.getContext('2d');\r\n const W = c.width = innerWidth;\r\n const H = c.height = innerHeight;\r\n const n = 120;\r\n for (let i=0;ic.remove(), 1200);\r\n }\r\n } catch (e) { console.warn('[Barkday] confetti failed', e); }\r\n }));\r\n } catch (e) { console.warn('[Barkday] confetti scheduling failed', e); }\r\n }\r\n\r\n // Patch strategy:\r\n // 1) Listen for clicks on “Save/Load” that create/open the drawer,\r\n // 2) After app.js finishes rendering the plan, if “today”, wait for drawer visible, then fire.\r\n //\r\n // We don’t rely on internal functions; we infer state from the DOM the same way a user would.\r\n\r\n // Helper: find the current “run” info if app.js exposes it on the card (data attributes) or in storage.\r\n function isTodayRun() {\r\n // Prefer explicit flag if app.js sets one (not required)\r\n if (window.bdCurrentInfo && window.bdCurrentInfo.isToday) return true;\r\n\r\n // Fallback: check if the UI shows the “today” badge somewhere\r\n // (Adjust these selectors if your markup differs.)\r\n const todayBadges = document.querySelectorAll('.bd-badge-today, [data-today=\"true\"]');\r\n if (todayBadges.length) return true;\r\n\r\n // As a general fallback, let’s be conservative: return false without a clear signal\r\n return false;\r\n }\r\n\r\n // When the user loads or saves a record we’ll get a click on these buttons.\r\n // We use event delegation so dynamically inserted items are handled.\r\n document.addEventListener('click', (e) => {\r\n const el = e.target.closest('[data-act=\"load\"], [data-act=\"save\"], [data-act=\"open\"]');\r\n if (!el) return;\r\n\r\n // Schedule a post-render check: after app.js updates the DOM for the drawer/plan\r\n setTimeout(() => {\r\n if (!isTodayRun()) return;\r\n waitFor(READY_SEL, 5000).then(() => fireConfettiSafe());\r\n }, 0);\r\n });\r\n\r\n // Also cover the “first time” flow when a brand-new profile is created\r\n // (app.js often shows the drawer automatically right after submit)\r\n document.addEventListener('submit', (e) => {\r\n const form = e.target.closest('form');\r\n if (!form) return;\r\n // Post-submit render tends to be async; give it a tick\r\n setTimeout(() => {\r\n if (!isTodayRun()) return;\r\n waitFor(READY_SEL, 5000).then(() => fireConfettiSafe());\r\n }, 0);\r\n });\r\n\r\n console.log('[Barkday] celebration patch ready');\r\n})();\r\n","inline_bytes":5128,"content_sha256":"413d4c8c713b31de7bc513956cc703991b3816cc0828ee1f3b9f780ab5a6277a"},{"path":"app-curves-inline.js","size":5752,"sha":"8006f5bbdf771c2f33ebbb2ce7911a9b7862b028","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/app-curves-inline.js","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/app-curves-inline.js","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"/* Barkday™ curves inline add-on (non-module; safe to load after app.js)\r\n - Year 1 & 2: smooth monotone arithmetic gaps (LOCT 15/9), sums to 365 each year\r\n - >= 2y: smooth cumulative K(t) via monotone cubic (PCHIP) with anchors\r\n - Exposes window.bdCurves with:\r\n • loadCurves(): Promise\r\n • buildTimes(conf, opts): {k->tYears}\r\n • computeNext(dog): Promise<{k, date, tYears, curveLabel}>\r\n • dateFromYears(dob, tYears): Date\r\n*/\r\n\r\n(function(){\r\n // ---- Helpers: LOCT (Year 1 & 2) ----\r\n function yearGapsAP(n, a0Days, yearDays) {\r\n if (n <= 0) return [];\r\n const denom = n * (n - 1) / 2;\r\n const d = (yearDays - n * a0Days) / denom;\r\n const gaps = Array.from({ length: n }, (_, i) => a0Days + i * d);\r\n const sum = gaps.reduce((a, b) => a + b, 0);\r\n gaps[gaps.length - 1] += (yearDays - sum); // exact sum guard\r\n return gaps;\r\n }\r\n function kTimesYear1Year2(loctConf) {\r\n const n1 = loctConf?.y1?.n ?? 15;\r\n const a0y1 = loctConf?.y1?.a0_days ?? 10;\r\n const n2 = loctConf?.y2?.n ?? 9;\r\n const a0Hint = loctConf?.y2?.a0_hint_days ?? 38;\r\n\r\n // Year 1 → (0,1]\r\n const gapsY1 = yearGapsAP(n1, a0y1, 365);\r\n const tY1 = []; let acc = 0;\r\n for (const g of gapsY1) { acc += g; tY1.push(acc / 365); }\r\n\r\n // Year 2 → (1,2], first gap ≥ last Year1 gap\r\n const lastY1 = gapsY1[gapsY1.length - 1];\r\n const a0y2 = Math.max(a0Hint, lastY1);\r\n const gapsY2 = yearGapsAP(n2, a0y2, 365);\r\n const tY2 = []; acc = 0;\r\n for (const g of gapsY2) { acc += g; tY2.push(1 + acc / 365); }\r\n\r\n const out = {};\r\n tY1.forEach((t,i)=> out[String(i+1)] = +t.toFixed(6));\r\n tY2.forEach((t,i)=> out[String(n1+i+1)] = +t.toFixed(6));\r\n return out; // human years since DOB for k=1..24\r\n }\r\n\r\n // ---- PCHIP monotone cubic for t >= 2y ----\r\n function buildPCHIP(anchors){\r\n const n = anchors.length;\r\n if (n < 2) throw new Error('PCHIP: need >=2 anchors');\r\n const t = anchors.map(a=>+a.t_years);\r\n const y = anchors.map(a=>+a.K_total);\r\n const h = Array(n-1), d = Array(n-1);\r\n for (let i=0;i 0) || !(d[i] >= 0)) throw new Error('PCHIP: anchors must be increasing (t) and nondecreasing (K)');\r\n }\r\n const m = Array(n).fill(0);\r\n m[0]=d[0]; m[n-1]=d[n-2];\r\n for (let i=1;i= t[n-1]) return y[n-1];\r\n // locate segment\r\n let s=0,e=n-1;\r\n while (s+1>1;\r\n if (t[mid] <= x) s=mid; else e=mid;\r\n }\r\n const hS = h[s];\r\n const tau = (x - t[s]) / hS;\r\n const h00 = (1+2*tau)*(1-tau)*(1-tau);\r\n const h10 = tau*(1-tau)*(1-tau);\r\n const h01 = tau*tau*(3-2*tau);\r\n const h11 = tau*tau*(tau-1);\r\n return h00*y[s] + h10*hS*m[s] + h01*y[s+1] + h11*hS*m[s+1];\r\n }\r\n return (x)=>evalAt(x);\r\n }\r\n function invertK(evalK, k, tLo=2.0, tHi=12.0, iters=44){\r\n let lo=tLo, hi=tHi;\r\n if (k <= evalK(lo)) return lo;\r\n if (k >= evalK(hi)) return hi;\r\n for (let i=0;i nowYears && (bestT == null || t < bestT)){ bestT=t; bestK=+k; }\r\n }\r\n const dt = dateFromYears(dog.dob, bestT);\r\n return { k: bestK, date: dt, tYears: bestT, curveLabel: conf?.label || 'Default curve' };\r\n }\r\n\r\n // Expose\r\n window.bdCurves = { loadCurves, buildTimes, dateFromYears, computeNext };\r\n console.log('[Barkday] curves inline add-on ready');\r\n})();\r\n","inline_bytes":5736,"content_sha256":"e2573ec4a87a12047c712c93f530956472ee7cbc0d7f0a046f90792ec30ef250"},{"path":"app-pdf.js","size":15113,"sha":"96cdf3dd10ba13217ba5c6c6aa8e5110fac44e04","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/app-pdf.js","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/app-pdf.js","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"/* Barkday™ PDF Add-on — per-record Print PDF (v2025-10-22-FINAL)\r\n - Vector SVG logo (fallback to PNG), cache-busted, GH Pages friendly\r\n - Real QR code (local lib if present; otherwise robust PNG fallback)\r\n - \"Certificate #\" + number always shown (uses run.id/hash; else deterministic fallback)\r\n - Footer pinned to the bottom, header stays header\r\n - Buttons injected for existing & future cards\r\n*/\r\n\r\n(function () {\r\n // ---------- small utils ----------\r\n const LOG = (...a)=>console.log('[Barkday][PDF]', ...a);\r\n const WARN = (...a)=>console.warn('[Barkday][PDF]', ...a);\r\n\r\n function onceDOMReady(fn){\r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', fn, {once:true});\r\n } else { fn(); }\r\n }\r\n const sleep = (ms)=>new Promise(r=>setTimeout(r, ms));\r\n\r\n function getStoreList(){\r\n try { return (window.bdStoreList ? bdStoreList() : []); }\r\n catch { return []; }\r\n }\r\n\r\n async function fetchFirst(urls){\r\n let lastErr;\r\n for(const url of urls){\r\n try {\r\n const r = await fetch(url, { cache:'no-store' });\r\n if (!r.ok) throw new Error(String(r.status));\r\n return r;\r\n } catch (e){ lastErr = e; }\r\n }\r\n throw lastErr || new Error('All fetch paths failed');\r\n }\r\n\r\n // --- Logo helpers: prefer vector SVG, fallback to PNG ---\r\n async function drawVectorLogo(doc, x, y, w, h){\r\n if (!window.svg2pdf) {\r\n await new Promise((res, rej)=>{\r\n const s = document.createElement('script');\r\n s.src = 'https://cdn.jsdelivr.net/npm/svg2pdf.js@2.2.4/dist/svg2pdf.umd.min.js';\r\n s.onload = res; s.onerror = rej; document.head.appendChild(s);\r\n });\r\n }\r\n const resp = await fetchFirst([\r\n 'barkday-logo-vector.svg?v=3',\r\n 'assets/barkday-logo-vector.svg?v=3'\r\n ]);\r\n const svgText = await resp.text();\r\n await doc.svg(svgText, { x, y, width: w, height: h });\r\n }\r\n\r\n async function drawPngLogo(doc, x, y, w, h){\r\n const r = await fetchFirst([\r\n 'barkday-logo2.png?v=2',\r\n 'assets/barkday-logo2.png?v=2'\r\n ]);\r\n const b = await r.blob();\r\n const dataUrl = await new Promise((res, rej)=>{\r\n const fr = new FileReader();\r\n fr.onload = ()=>res(fr.result);\r\n fr.onerror = rej;\r\n fr.readAsDataURL(b);\r\n });\r\n doc.addImage(dataUrl, 'PNG', x, y, w, h);\r\n }\r\n\r\n // ensure jsPDF (index already loads it; this is a guard)\r\n async function ensurePDFLibs(){\r\n if (!window.jspdf?.jsPDF) {\r\n await new Promise((res, rej)=>{\r\n const s = document.createElement('script');\r\n s.src = 'https://cdn.jsdelivr.net/npm/jspdf@2.5.1/dist/jspdf.umd.min.js';\r\n s.onload = res; s.onerror = rej; document.head.appendChild(s);\r\n });\r\n }\r\n return window.jspdf.jsPDF;\r\n }\r\n\r\n // Try to find a local QR library; if not present, caller will use network PNG fallback\r\n async function ensureQRCode(){\r\n const pick = (w)=> (w && (w.QRCode || w.qrcode)) || null;\r\n let QR = pick(window);\r\n if (QR) return QR;\r\n if (window.opener) {\r\n QR = pick(window.opener);\r\n if (QR) return QR;\r\n }\r\n return null; // tell caller to fallback\r\n }\r\n\r\n // format helpers\r\n function fmtHumanYears(hy){\r\n if (hy == null || isNaN(+hy)) return '—';\r\n const yrs = Math.floor(hy);\r\n const mos = Math.round((hy - yrs) * 12);\r\n if (yrs === 0) return `${mos} mo`;\r\n if (mos === 0) return `${yrs} yr`;\r\n return `${yrs} yr ${mos} mo`;\r\n }\r\n const fmtDogAge = (d)=> d || '—';\r\n\r\n // Always provide a certificate number (prefer real id/hash; else deterministic fallback)\r\n function getCert(run){\r\n const s = (run?.id || run?.hash || '').toString().trim();\r\n if (s) return s;\r\n const seed = [run?.dog||'', run?.dob||'', run?.breed||'', run?.weight||''].join('|');\r\n let h = 0 >>> 0;\r\n for (let i = 0; i < seed.length; i++){\r\n h = (h * 1664525 + seed.charCodeAt(i) + 1013904223) >>> 0; // simple LCG-ish\r\n }\r\n return String(h).padStart(10, '0').slice(0, 10); // 10-digit fallback\r\n }\r\n\r\n // Build compact QR payload\r\n function buildQRPayload(run){\r\n const payload = {\r\n v: '1',\r\n id: run?.id || run?.hash || '',\r\n dog: run?.dog || '',\r\n dob: run?.dob || '',\r\n w: run?.weight ?? null,\r\n g: run?.group || '',\r\n b: run?.breed || '',\r\n };\r\n return JSON.stringify(payload);\r\n }\r\n\r\n // Robust QR render: local lib if present; otherwise network PNG fallback\r\n async function renderQRCodeToDataURL(text){\r\n const QR = await ensureQRCode();\r\n\r\n // A) local lib (preferred)\r\n if (QR && (QR.toCanvas || (QR.QRCode && QR.QRCode.toCanvas))) {\r\n const toCanvas = QR.toCanvas || QR.QRCode.toCanvas;\r\n return await new Promise((resolve, reject)=>{\r\n const c = document.createElement('canvas');\r\n try {\r\n toCanvas(c, text, { errorCorrectionLevel: 'M', margin: 1 }, (err)=>{\r\n if (err) return reject(err);\r\n try { resolve(c.toDataURL('image/png')); }\r\n catch(e){ reject(e); }\r\n });\r\n } catch(e){ reject(e); }\r\n });\r\n }\r\n\r\n // B) network PNG fallback (stable on GH Pages & blob print popups)\r\n const url = 'https://api.qrserver.com/v1/create-qr-code/?size=240x240&data=' + encodeURIComponent(text);\r\n const resp = await fetch(url, { cache: 'no-store' });\r\n if (!resp.ok) throw new Error('QR fallback fetch failed: ' + resp.status);\r\n const blob = await resp.blob();\r\n return await new Promise((res, rej)=>{\r\n const fr = new FileReader();\r\n fr.onload = ()=>res(fr.result);\r\n fr.onerror = rej;\r\n fr.readAsDataURL(blob);\r\n });\r\n }\r\n\r\n // --------- PDF LAYOUT ----------\r\n async function buildRunPDF(run){\r\n const jsPDF = await ensurePDFLibs();\r\n const doc = new jsPDF({ orientation:'landscape', unit:'pt', format:'letter' }); // 792x612\r\n\r\n const W=792, H=612, M=36;\r\n const RULE=[210,210,210];\r\n const LINE=16, BUL=14;\r\n let y = M; // header Y anchor\r\n\r\n const hr=(yy)=>{doc.setDrawColor(...RULE);doc.setLineWidth(1);doc.line(M,yy,W-M,yy);};\r\n const tx=(s,x,yy,fs=11,bold=false)=>{doc.setFontSize(fs);doc.setFont('helvetica', bold?'bold':'normal');doc.text(String(s??'—'),x,yy);};\r\n const wrap=(s,w)=>doc.splitTextToSize(String(s??'—'),w);\r\n\r\n // Header: logo (SVG-first) + title\r\n try {\r\n await drawVectorLogo(doc, M, y, 86.4, 86.4);\r\n } catch {\r\n try { await drawPngLogo(doc, M, y, 86.4, 86.4); }\r\n catch { doc.setDrawColor(255); doc.rect(M,y,86.4,86.4,'S'); }\r\n }\r\n\r\n // Right side of header: QR + Certificate #\r\n const headerLeftX = M + 86.4 + 18;\r\n const headerRightX = W - M - 150;\r\n\r\n tx('Barkday™', headerLeftX, y + 24, 22, true);\r\n if (run?.dog) tx(run.dog, headerLeftX, y + 44, 16, false);\r\n\r\n // Compact summary lines\r\n let sy = y + 64;\r\n const colGap = 14, col1W = 260, col2W = 300;\r\n function kvL(lbl, val){\r\n tx(lbl+':', headerLeftX, sy, 11, true);\r\n const lines = wrap(val, col1W-70);\r\n doc.setFontSize(11); doc.setFont('helvetica','normal'); doc.text(lines, headerLeftX+70, sy);\r\n sy += Math.max(LINE, lines.length*LINE);\r\n }\r\n let syR = y + 64;\r\n const rx = headerLeftX + col1W + colGap;\r\n function kvR(lbl, val){\r\n tx(lbl+':', rx, syR, 11, true);\r\n const lines = wrap(val, col2W-100);\r\n doc.setFontSize(11); doc.setFont('helvetica','normal'); doc.text(lines, rx+100, syR);\r\n syR += Math.max(LINE, lines.length*LINE);\r\n }\r\n\r\n const breedLine = (Array.isArray(run?.breeds) && run.breeds.length)\r\n ? run.breeds.slice(0,3).map(b=>`${b.name}${b.pct!=null?` (${b.pct}%)`:''}`).join(' · ')\r\n : (run?.breed || '-');\r\n\r\n kvL('Group', run?.group || '-');\r\n kvL('Birthdate', run?.dob || '-');\r\n kvL('Breed', breedLine);\r\n\r\n kvR('EST adult weight', (Number.isFinite(+run?.weight) ? `${run.weight} lb` : '—'));\r\n kvR('Chewer', run?.chewer || '—');\r\n kvR('Milestones', run?.smooth ? 'Smooth enabled' : 'Standard');\r\n\r\n // KPI snapshot\r\n const snapY = Math.max(sy, syR) + 8;\r\n const hyText = fmtHumanYears(run?.kpi?.hy);\r\n const dogAge = fmtDogAge(run?.kpi?.dogAge);\r\n tx(`Dog age today: ${dogAge}`, headerLeftX, snapY, 11, false);\r\n tx(`Human-years estimate: ${hyText}`, headerLeftX + 200, snapY, 11, false);\r\n\r\n const headerBottom = snapY + 12;\r\n hr(headerBottom + 10);\r\n\r\n // --- QR Code block (smaller + centered label/number) ---\r\ntry {\r\n const qrText = buildQRPayload(run);\r\n const qrDataURL = await renderQRCodeToDataURL(qrText);\r\n\r\n const QR_SCALE = 0.6; // ~60%\r\n const QR_SIZE = Math.round(96 * QR_SCALE); // 58 pt\r\n const qrX = headerRightX;\r\n const qrY = y + 6;\r\n\r\n doc.addImage(qrDataURL, 'PNG', qrX, qrY, QR_SIZE, QR_SIZE);\r\n\r\n const cert = getCert(run);\r\n const cx = qrX + QR_SIZE / 2;\r\n const labelY = qrY + QR_SIZE + 12; // tuck a little closer for the smaller code\r\n doc.setFontSize(10); doc.setFont('helvetica','bold');\r\n doc.text('Certificate #', cx, labelY, { align:'center' });\r\n doc.setFontSize(11); doc.setFont('courier','normal');\r\n doc.text(cert, cx, labelY + 14, { align:'center' });\r\n\r\n} catch (e) {\r\n WARN('QR generation failed', e);\r\n\r\n const QR_SCALE = 0.6;\r\n const QR_SIZE = Math.round(96 * QR_SCALE);\r\n const qrX = headerRightX;\r\n const qrY = y + 6;\r\n\r\n doc.setDrawColor(...RULE);\r\n doc.rect(qrX, qrY, QR_SIZE, QR_SIZE, 'S');\r\n doc.setFontSize(10); doc.setFont('helvetica','normal');\r\n doc.text('QR unavailable', qrX + 8, qrY + QR_SIZE / 2);\r\n\r\n const cert = getCert(run);\r\n const cx = qrX + QR_SIZE / 2;\r\n const labelY = qrY + QR_SIZE + 12;\r\n doc.setFontSize(10); doc.setFont('helvetica','bold');\r\n doc.text('Certificate #', cx, labelY, { align:'center' });\r\n doc.setFontSize(11); doc.setFont('courier','normal');\r\n doc.text(cert, cx, labelY + 14, { align:'center' });\r\n}\r\n\r\n // ---------- NOTES (center) ----------\r\n let notesTop = headerBottom + 26;\r\n tx('Next Barkday Plan', M, notesTop, 14, true);\r\n notesTop += LINE;\r\n\r\n const usableW = W - 2*M, innerGap = 18;\r\n const LEFT_W = (usableW - innerGap) * 0.54;\r\n const RIGHT_W = (usableW - innerGap) - LEFT_W;\r\n const X_L = M, X_R = M + LEFT_W + innerGap;\r\n let yL = notesTop, yR = notesTop;\r\n\r\n const lanes = (function(notes){\r\n const out=[]; if(!notes||typeof notes!=='string') return out;\r\n const blocks=notes.split(/\\n\\s*\\n+/);\r\n for(const b of blocks){\r\n const lines=b.split(/\\n/).map(s=>s.trim()).filter(Boolean);\r\n if(!lines.length) continue;\r\n const title=lines[0].replace(/^[-•]+\\s*/, '');\r\n const items=lines.slice(1).map(s=>s.replace(/^[-•]+\\s*/, '').trim()).filter(Boolean);\r\n if(items.length) out.push({title, items});\r\n }\r\n return out;\r\n })(run?.event?.notes);\r\n\r\n function laneBlock(title,items, colX, colW, colYRef){\r\n tx(title||'Plan', colX, colYRef.v, 12, true); colYRef.v += LINE-2;\r\n for(const b of (items||[])){\r\n const lines=wrap('• '+b, colW-14);\r\n doc.setFontSize(11); doc.setFont('helvetica','normal'); doc.text(lines, colX+10, colYRef.v);\r\n colYRef.v += lines.length*BUL;\r\n }\r\n colYRef.v += 6;\r\n }\r\n\r\n for(const lane of lanes){\r\n const leftRef = {v:yL}, rightRef = {v:yR};\r\n if (yL <= yR) laneBlock(lane.title, lane.items, X_L, LEFT_W, leftRef);\r\n else laneBlock(lane.title, lane.items, X_R, RIGHT_W, rightRef);\r\n yL = leftRef.v; yR = rightRef.v;\r\n }\r\n\r\n // --------- FOOTER pinned ----------\r\n const contentBottom = Math.max(yL, yR);\r\n const footerY = Math.max(contentBottom + 10, H - M - 50);\r\n hr(footerY);\r\n tx('Privacy: Barkday™ stores data only on this device. This PDF was generated locally in your browser.', M, footerY+18, 9, false);\r\n tx('Medical disclaimer: Barkday™ is general guidance only and not veterinary advice.', M, footerY+34, 9, false);\r\n\r\n return doc;\r\n }\r\n\r\n // -------- buttons & click handling --------\r\n function injectButtonsIn(container){\r\n const cards = container.querySelectorAll('[data-act=\"load\"]');\r\n cards.forEach(loadBtn=>{\r\n const card = loadBtn.closest('.bd-card, article, li, div') || loadBtn.parentNode;\r\n if (!card || card.querySelector('[data-act=\"pdf\"]')) return;\r\n\r\n const idx = loadBtn.dataset.idx || card.getAttribute('data-i');\r\n const actions = loadBtn.parentNode;\r\n const btn = document.createElement('button');\r\n btn.className = 'ghost';\r\n btn.type = 'button';\r\n btn.textContent = 'Print PDF';\r\n btn.setAttribute('data-act','pdf');\r\n if (idx != null) btn.setAttribute('data-idx', idx);\r\n actions.appendChild(btn);\r\n });\r\n }\r\n\r\n function computeIndexForButton(btn){\r\n let idx = btn.dataset.idx;\r\n if (idx != null) return Number(idx);\r\n\r\n const card = btn.closest('[data-i]');\r\n if (card) return Number(card.getAttribute('data-i'));\r\n\r\n const allCards = [...document.querySelectorAll('#bdSavedBody [data-act=\"load\"]')];\r\n const loadBtn = btn.parentNode?.querySelector?.('[data-act=\"load\"]');\r\n const pos = allCards.indexOf(loadBtn);\r\n return pos >= 0 ? pos : 0;\r\n }\r\n\r\n function bindGlobalClick(){\r\n document.addEventListener('click', async (e)=>{\r\n const btn = e.target.closest && e.target.closest('[data-act=\"pdf\"]');\r\n if (!btn) return;\r\n\r\n const idx = computeIndexForButton(btn);\r\n const list = getStoreList();\r\n const run = list[idx];\r\n if (!run){ (window.bdToast||alert)('Record not found'); return; }\r\n\r\n try{\r\n const doc = await buildRunPDF(run);\r\n const url = doc.output('bloburl');\r\n const w = window.open(url, '_blank');\r\n if (!w){\r\n (window.bdToast||alert)('Popup blocked — saving the PDF instead.');\r\n const safe = (run?.dog || 'Barkday').replace(/[^\\w\\- ]+/g,'').trim() || 'Barkday';\r\n doc.save(`${safe}-Barkday.pdf`);\r\n } else {\r\n setTimeout(()=>{ try { w.focus(); w.print(); } catch {} }, 300);\r\n }\r\n } catch(err){\r\n console.error(err);\r\n (window.bdToast||alert)('Sorry — could not build PDF.');\r\n }\r\n });\r\n }\r\n\r\n function startObserving(host){\r\n injectButtonsIn(host);\r\n const mo = new MutationObserver(muts=>{\r\n for(const m of muts){\r\n m.addedNodes && m.addedNodes.forEach(n=>{\r\n if (n.nodeType===1) injectButtonsIn(n);\r\n });\r\n }\r\n });\r\n mo.observe(host, {childList:true, subtree:true});\r\n }\r\n\r\n function findSavedHost(){\r\n return document.getElementById('bdSavedBody') || document.getElementById('bdSaved') || document.body;\r\n }\r\n\r\n onceDOMReady(async ()=>{\r\n let tries = 0;\r\n while(tries++ < 200){\r\n const host = findSavedHost();\r\n if (host){\r\n bindGlobalClick();\r\n startObserving(host);\r\n LOG('PDF add-on ready');\r\n return;\r\n }\r\n await sleep(100);\r\n }\r\n WARN('bdSavedBody not found; PDF buttons won’t inject yet.');\r\n });\r\n})();\r\n","inline_bytes":15078,"content_sha256":"495132fe9abae3dea6815dceb56606854c6c8f190a2301298d080e2fd3970617"},{"path":"app.js","size":94801,"sha":"0ab5b0bef2c56ab68b399fadb980657eb4a2dd2d","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/app.js","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/app.js","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"console.log('[Barkday] app.js loaded v2026-05-03-1 (v2 gift feed runtime adapter)');\n// ====================== Barkday app.js (complete, upgraded) ======================\n\n// ---------- Config ----------\nconst LOGO_SPLASH_SRC = \"barkday-logo.png?v=3\"; // full-size on splash\nconst LOGO_HEADER_SRC = \"barkday-logo2.png?v=2\"; // smaller header mark\n\n// Data sources\nconst GIFT_FEED_URL = \"data/dog-gifts-merged.json?v=2026-05-03-1\";\nconst RECO_BANDED_URL = \"data/reco-banded.json?v=2025-10-06-1\";\nconst RECO_BREED_URL = \"data/reco-breed.json?v=2026-05-04-1\";\nconst BREED_GROUPS_URL = \"data/breed_groups.json?v=2026-05-04-1\";\nconst BREED_ALIASES_URL = \"data/breed_aliases.json?v=2025-10-06-1\"; // NEW: external aliases\nconst TAXONOMY_URL = \"data/breed_taxonomy.json?v=2025-10-06-1\"; // NEW: AKC + behavioral mapping\nconst GROUP_RULES_URL = \"ddata/rules_group_defaults.json?v=2026-05-04-1\"; // NEW: group-level banded fallbacks (rich text)\nconst BARKDAY_DEBUG_MODE = [\"localhost\", \"127.0.0.1\"].includes(location.hostname) && location.search.includes(\"debug=1\");\n\n// --- Affiliate Config (Amazon live; Chewy placeholder) ---\nconst AMAZON_TAG = \"candidquality-20\"; // your live Amazon Associates tag\nconst CHEWY_IMPACT_BASE = \"\"; // leave empty until Chewy approves (e.g., \"https://chewy.pxf.io/c/XXXX/XXXX/XXXX\")\nconst CHEWY_ENABLED = !!CHEWY_IMPACT_BASE; // auto-toggle when you paste your Chewy Impact base\n\n// --- Affiliate link normalizer (Amazon live; Chewy future-proof) ---\nfunction resolveAffiliateUrl(url){\n try {\n const u = new URL(url, location.origin);\n\n // Amazon: ensure our tag is present\n if (u.hostname.includes('amazon.')) {\n if (!u.searchParams.get('tag')) {\n u.searchParams.set('tag', AMAZON_TAG);\n }\n return u.toString();\n }\n\n // Chewy: if/when enabled, wrap the destination with your Impact base\n if (CHEWY_ENABLED && CHEWY_IMPACT_BASE && u.hostname.includes('chewy.com')) {\n return CHEWY_IMPACT_BASE + encodeURIComponent(u.toString());\n }\n\n return url;\n } catch {\n return url;\n }\n}\n\nfunction rewriteAffiliateLinks(root){\n const scope = root || document;\n scope.querySelectorAll('#gifts a[href]').forEach(a => {\n const newHref = resolveAffiliateUrl(a.getAttribute('href') || '');\n if (newHref) a.setAttribute('href', newHref);\n a.setAttribute('rel', 'nofollow noopener sponsored');\n });\n}\n\n// Observe the gifts container so every render stays tagged without changing your loaders\ndocument.addEventListener('DOMContentLoaded', () => {\n const box = document.getElementById('gifts');\n if (!box) return;\n // One pass now (in case pre-rendered)\n rewriteAffiliateLinks(box);\n // Future mutations\n const mo = new MutationObserver(() => rewriteAffiliateLinks(box));\n mo.observe(box, { childList: true, subtree: true });\n\n // Safety: also rewrite after an explicit \"Load gift ideas\" click\n document.getElementById('loadGifts')?.addEventListener('click', () => {\n setTimeout(() => rewriteAffiliateLinks(box), 0);\n });\n});\n\n\n// Debug: show data file versions in console\nconsole.debug(\"[Barkday] data sources\", {\n groups: BREED_GROUPS_URL,\n banded: RECO_BANDED_URL,\n breed: RECO_BREED_URL,\n aliases: BREED_ALIASES_URL,\n gifts: GIFT_FEED_URL,\n taxonomy: TAXONOMY_URL // NEW\n});\n\n// ---------- Splash + Logos ----------\n(function(){\n const hideSplash = () => document.getElementById(\"splash\")?.classList.add(\"hide\");\n window.addEventListener(\"load\", () => setTimeout(hideSplash, 1800)); // doubled\n document.addEventListener(\"DOMContentLoaded\", () => {\n const h = document.getElementById(\"logoHeader\");\n const s = document.getElementById(\"logoSplash\");\n if (h) h.src = LOGO_HEADER_SRC;\n if (s) s.src = LOGO_SPLASH_SRC;\n setTimeout(hideSplash, 3000); // doubled fail-safe\n });\n})();\n\n// ---------- Theme ----------\nconst root=document.documentElement, themeBtn=document.getElementById('themeToggle');\nconst savedTheme = localStorage.getItem('barkday-theme') || 'dark';\nroot.setAttribute('data-theme', savedTheme==='light'?'light':'dark');\nif (themeBtn) {\n themeBtn.textContent = savedTheme==='light' ? '🌙 Dark' : '☀️ Light';\n themeBtn.addEventListener('click', () => {\n const now = root.getAttribute('data-theme')==='light'?'dark':'light';\n root.setAttribute('data-theme', now);\n localStorage.setItem('barkday-theme', now);\n themeBtn.textContent = now==='light' ? '🌙 Dark' : '☀️ Light';\n });\n}\n\n\n// ---------- DOM Shortcuts ----------\nconst $ = id => document.getElementById(id);\nconst els = {\n dogName: $('dogName'), dob: $('dob'), adultWeight: $('adultWeight'), adultWeightVal: $('adultWeightVal'),\n chewer: $('chewer'), showEpi: $('showEpigenetic'), smooth: $('smoothMilestones'),\n breed: $('breed'), breedGroup: $('breedGroup'), breedExamples: $('breedExamples'),\n ignoreAge: $('ignoreAge'), ignoreSize: $('ignoreSize'), ignoreChewer: $('ignoreChewer'),\n resetBtn: $('resetBtn'), shareBtn: $('shareBtn'), sizeWarn: $('sizeWarn'),\n nextHeadline: $('nextHeadline'), nextBday: $('nextBday'), nextBdayDelta: $('nextBdayDelta'),\n dogAge: $('dogAge'), humanYears: $('humanYears'), slopeNote: $('slopeNote'),\n loadGifts: $('loadGifts'), giftMeta: $('giftMeta'), gifts: $('gifts'),\n heroLine: $('heroLine'), profileLine: $('profileLine'), breedNotes: $('breedNotes'), epi: $('epi')\n};\n\n// --- Saved status pill (under Name) ---\nfunction getSavePill(){\n let el = document.getElementById('saveStatus');\n if (!el) {\n el = document.createElement('button');\n el.id = 'saveStatus';\n el.type = 'button';\n el.className = 'status-pill';\n el.textContent = 'No saves yet';\n }\n // Ensure it sits under the Dog name field container\n const nameField = els.dogName?.closest('div') || els.dogName?.parentElement;\n if (nameField && el.parentElement !== nameField) {\n nameField.appendChild(el);\n }\n // Open Saved drawer when tapped\n el.onclick = () => { BarkdaySaved.open(); };\n return el;\n}\nfunction markSaving(){\n const pill = getSavePill();\n pill.textContent = 'Saving…';\n pill.classList.add('saving');\n pill.classList.remove('error');\n}\nfunction markSaved(){\n const pill = getSavePill();\n const t = new Date().toLocaleTimeString([], { hour:'numeric', minute:'2-digit' });\n pill.textContent = `Saved ✓ · ${t}`;\n pill.classList.remove('saving','error');\n}\nfunction markSaveError(){\n const pill = getSavePill();\n pill.textContent = 'Save failed — retry';\n pill.classList.add('error');\n pill.classList.remove('saving');\n}\n// Mount once DOM is ready (in case HTML is loaded before JS runs)\ndocument.addEventListener('DOMContentLoaded', () => { getSavePill(); }, { once:true });\n\n// Gate Reset/Share before first calculation\ndocument.addEventListener('DOMContentLoaded', () => {\n if (els.resetBtn){ els.resetBtn.disabled = true; els.resetBtn.setAttribute('aria-disabled','true'); }\n if (els.shareBtn){ els.shareBtn.disabled = true; els.shareBtn.setAttribute('aria-disabled','true'); }\n}, { once:true });\n\n// ---------- Hero line ----------\nconst poss = n => { const t = String(n||'').trim(); if (!t) return \"your dog's\"; return /s$/i.test(t) ? `${t}’` : `${t}’s`; };\nfunction renderHero(){ els.heroLine.textContent = `Let’s find out together what ${poss(els.dogName.value)} birthdays are, so we can celebrate every single one.`; }\nels.dogName.addEventListener('input', renderHero);\nels.dogName.addEventListener('input', () => { markSaving(); });\nrenderHero();\n\n// ---------- Static group notes (UI hints under Results) ----------\nconst GROUP_META = {\n 'Working / Herding': {\n desc: 'Needs purposeful work and mental challenges; high handler focus and strong herding drive.',\n examples: ['Border Collie','Australian Shepherd','Corgi','Belgian Malinois','German Shepherd']\n },\n 'Guardian / Protection': {\n desc: 'Natural territorial guardians; confident and aloof with strangers; bond deeply with family.',\n examples: ['Rottweiler','Mastiff','Great Pyrenees','Akita','Cane Corso']\n },\n 'Sporting / Gun Dogs': {\n desc: 'High stamina and people‑oriented; enjoy water and retrieving but need variety to avoid boredom.',\n examples: ['Labrador Retriever','Golden Retriever','Vizsla','GSP','English Setter']\n },\n 'Scent Hounds': {\n desc: 'Nose‑driven trackers; independent with selective recall and vocal when on scent.',\n examples: ['Beagle','Bloodhound','Basset Hound','Coonhound','Foxhound']\n },\n 'Sight Hounds': {\n desc: 'Visual chasers and sprint athletes; restful indoors with bursts of speed; thin skin requires padding.',\n examples: ['Greyhound','Whippet','Afghan Hound','Saluki','Borzoi']\n },\n 'Terriers': {\n desc: 'Tenacious problem‑solvers; high prey drive; energetic and love to dig and tug.',\n examples: ['Jack Russell Terrier','West Highland White Terrier','Bull Terrier','Airedale Terrier','Border Terrier']\n },\n 'Toy / Companion Dogs': {\n desc: 'Small dogs bonded to people; build confidence to reduce reactivity; joints need gentle care.',\n examples: ['Chihuahua','Pomeranian','Yorkie','Maltese','Shih Tzu']\n },\n 'Nordic / Spitz Types': {\n desc: 'Endurance and independence with thick double coats; often vocal and strong pullers.',\n examples: ['Siberian Husky','Alaskan Malamute','Samoyed','Shiba Inu','Akita']\n },\n 'Bulldog / Molosser Types': {\n desc: 'Powerful bodies with brachycephalic limitations; affectionate and food‑motivated; watch joints.',\n examples: ['English Bulldog','French Bulldog','Boxer','Bullmastiff','Dogue de Bordeaux']\n },\n 'International Guardian Breeds': {\n desc: 'Large livestock guardians from around the world; independent and protective with strong instincts.',\n examples: ['Kangal','Central Asian Shepherd Dog','Caucasian Shepherd Dog','Boerboel','Spanish Mastiff']\n },\n 'Pariah & Landrace Types': {\n desc: 'Primitive or landrace dogs with strong survival instincts; high prey drive and independence.',\n examples: ['Thai Ridgeback','Canaan Dog','Carolina Dog','Africanis','Basenji']\n },\n 'Mixed / Other': {\n desc: 'Profile by observed drive and size; use weight, prey drive and independence to tailor activities.',\n examples: ['Mixed‑breed','Rescue','Unknown']\n }\n};\nconst GROUPS = {\n 'Working / Herding': [\n 'Daily jobs/puzzles like herding games and scentwork',\n 'Trick chaining and targeting games for mental challenge',\n 'Agility or obedience drills several times a week'\n ],\n 'Guardian / Protection': [\n 'Structured patrol‑style walks and neutrality practice',\n 'Mental jobs such as scent discrimination or carrying a backpack',\n 'Obstacle courses to build body awareness'\n ],\n 'Sporting / Gun Dogs': [\n 'Retrieve or swim sessions and field‑style searches',\n 'Scent or nosework games to tire the mind',\n 'Fitness drills like hill climbs and balance exercises'\n ],\n 'Scent Hounds': [\n 'Daily sniffari walks on a long line',\n 'Hide‑and‑seek or tracking games using toys or treats',\n 'Scent box or nosework courses'\n ],\n 'Sight Hounds': [\n 'Short sprint sets in a safe enclosed area',\n 'Lure coursing or flirt pole games',\n 'Long decompression walks with soft bedding for rest'\n ],\n 'Terriers': [\n 'Provide a dig box or sandbox for supervised digging',\n 'Tug games with take/drop rules',\n 'Scent and search games to challenge their minds'\n ],\n 'Toy / Companion Dogs': [\n 'Confidence games on varied surfaces and objects',\n 'Puzzle feeders to occupy the mind',\n 'Short indoor play sessions and gentle walks'\n ],\n 'Nordic / Spitz Types': [\n 'Backpacking or sledding in cool climates',\n 'Long decompression walks with sniffing time',\n 'Scent work or nose games to keep them engaged'\n ],\n 'Bulldog / Molosser Types': [\n 'Short, frequent sniff‑strolls with plenty of breaks',\n 'Low‑impact puzzle toys and chews',\n 'Regular cooperative care sessions for wrinkles, nails and ears'\n ],\n 'International Guardian Breeds': [\n 'Long patrol‑style walks and tasks that satisfy guardian instincts',\n 'Search or scent games to channel their intelligence',\n 'Early socialisation and boundaries to prevent reactivity'\n ],\n 'Pariah & Landrace Types': [\n 'Off‑leash decompression time in secure areas',\n 'Agility, lure coursing or chase games to channel prey drive',\n 'Recall and impulse‑control drills using long lines'\n ],\n 'Mixed / Other': [\n 'Tailor enrichment to the individual by observing drive and size'\n ]\n};\n\n// --- Ensure the UI never holds a blank group name ---\n// --- Group select helpers (handles name mismatches like \"Sporting / Gun Dogs\") ---\nfunction normalizeKey(s){ return String(s||'').toLowerCase().replace(/[^a-z]/g,''); }\n\n// Map an arbitrary group name to one of our GROUP_META/GROUPS keys,\n// so tips and examples always show up.\nfunction resolveGroupKey(name){\n const n = normalizeKey(name);\n for (const k of Object.keys(GROUP_META)){\n const nk = normalizeKey(k);\n if (n === nk || n.includes(nk) || nk.includes(n)) return k;\n }\n return 'Mixed / Other';\n}\n\n// ===== Round 2 helpers: toast + auto-scroll =====\nfunction bdToast(msg, ms = 2200){\n const el = document.getElementById('bdToast');\n const msgEl = document.getElementById('bdToastMsg');\n if (!el || !msgEl) return;\n msgEl.textContent = msg || 'Results updated.';\n el.classList.add('show');\n // Close handlers\n const closer = el.querySelector('.bd-x');\n const off = () => el.classList.remove('show');\n closer?.addEventListener('click', off, { once:true });\n // Auto-dismiss\n clearTimeout(bdToast._t); bdToast._t = setTimeout(off, ms);\n}\n\nfunction scrollResultsIntoView(){\n // Prefer the “Next Birthday Plan” header; fall back to first KPI\n const anchor = document.getElementById('nextPlanHeading')\n || document.querySelector('.kpi')\n || document.querySelector('h2');\n if (!anchor) return;\n // Small timeout so layout is final (after DOM writes)\n setTimeout(()=> anchor.scrollIntoView({ behavior:'smooth', block:'start' }), 50);\n}\n\n// ===== Round 3: Saved Results (mobile-safe) =====\nconst BD_STORE_KEY = 'barkday.runs.v1';\n// 1.0: ensure the Save pill flips to Saved whenever the run store updates\n(function hookSavedPill(){\n try {\n const _setItem = localStorage.setItem.bind(localStorage);\n localStorage.setItem = function(k, v){\n const r = _setItem(k, v);\n if (k === BD_STORE_KEY) { try { markSaved(); } catch(_){} }\n return r;\n };\n } catch {}\n})();\n\n// --- Monetization flags & limits (v3) ---\nconst BD_TIER = (window.BARKDAY_TIER || 'free'); // 'free' | 'pro' (placeholder for future)\nconst BD_LIMITS = {\n free: { maxDogs: 9999, maxRuns: 500 },\n pro: { maxDogs: 9999, maxRuns: 500 }\n};\n// Local-only, soft device hint (used only for gentle abuse checks and later upgrades)\nconst BD_DEVICE_KEY = 'barkday.device.v1';\n\n// Generate a semi-stable device id for soft abuse checks (no network, stays local)\n(function ensureDeviceId(){\n try{\n if (!localStorage.getItem(BD_DEVICE_KEY)) {\n const rnd = crypto.getRandomValues(new Uint32Array(4));\n const id = Array.from(rnd).map(n => n.toString(16).padStart(8,'0')).join('');\n localStorage.setItem(BD_DEVICE_KEY, id);\n }\n }catch{/* storage may be unavailable */}\n})();\n\n// Helper: how many unique dogs are saved (name trimmed, case-insensitive)\nfunction countUniqueDogs(items){\n const s = new Set();\n for (const r of (items||[])){\n const n = (r?.dog || '').trim().toLowerCase();\n if (n) s.add(n);\n }\n return s.size;\n}\n\n// Helper: current tier limits (default to 'free' if unknown)\nfunction currentLimits(){\n return BD_LIMITS[BD_TIER] || BD_LIMITS.free;\n}\n\n/* Mobile-safe storage shim\n Chooses localStorage → sessionStorage → in-memory fallback.\n Shows a small badge so you know which backend you're on. */\nconst BarkdayStore = (function(){\n let memory = {}; // last resort (per tab)\n function testArea(area){\n if (!area) return false;\n const k = '__bd_test__' + Math.random();\n try { area.setItem(k, '1'); area.removeItem(k); return true; }\n catch { return false; }\n }\n const hasLocal = testArea(window.localStorage);\n const hasSession = !hasLocal && testArea(window.sessionStorage);\n const area = hasLocal ? window.localStorage : (hasSession ? window.sessionStorage : null);\n const kind = hasLocal ? 'localStorage' : (hasSession ? 'sessionStorage' : 'memory');\n\n function get(key){\n try { return area ? area.getItem(key) : (memory[key] ?? null); }\n catch (e) { console.warn('[Barkday] storage.get failed', e); return null; }\n }\n function set(key, val){\n try {\n if (area) { area.setItem(key, val); }\n else { memory[key] = val; }\n return true;\n } catch (e) {\n console.warn('[Barkday] storage.set failed', e);\n return false;\n }\n }\n return { get, set, kind };\n})();\n\n// --- Save-status integration for the pill (runs after BarkdayStore is defined) ---\n(function wireSavePillToStore(){\n try {\n if (!window.BarkdayStore || typeof BarkdayStore.set !== 'function') return;\n\n // Wrap BarkdayStore.set so writes to the Runs list trigger \"Saved\" UI\n const _set = BarkdayStore.set;\n BarkdayStore.set = function patchedSet(key, val){\n const ok = _set(key, val);\n if (ok && key === BD_STORE_KEY) {\n try { markSaved(); } catch {}\n }\n return ok;\n };\n\n // Also catch direct localStorage/sessionStorage writes in case the backend falls back\n const hookArea = (areaName) => {\n const area = window[areaName];\n if (!area || typeof area.setItem !== 'function') return;\n const orig = area.setItem.bind(area);\n area.setItem = function(key, val){\n const out = orig(key, val);\n if (key === BD_STORE_KEY) { try { markSaved(); } catch {} }\n return out;\n };\n };\n hookArea('localStorage');\n hookArea('sessionStorage');\n } catch {}\n})();\n\n// --- Save-status visual state (classes for #saveStatus) ---\n(function enhanceSavePill(){\n function el(){ return document.getElementById('saveStatus'); }\n function setState(cls){\n const n = el(); if (!n) return;\n n.classList.remove('saving','saved','error');\n if (cls) n.classList.add(cls);\n }\n\n // Wrap markSaving so UI shows yellow state while persisting\n const __orig_markSaving = window.markSaving;\n window.markSaving = function(...args){\n try { setState('saving'); } catch {}\n if (typeof __orig_markSaving === 'function') return __orig_markSaving.apply(this, args);\n };\n\n // Wrap markSaved so UI shows green state upon success\n const __orig_markSaved = window.markSaved;\n window.markSaved = function(...args){\n try { setState('saved'); } catch {}\n if (typeof __orig_markSaved === 'function') return __orig_markSaved.apply(this, args);\n };\n\n // Optional helper you can call if a write fails\n window.markSaveError = function(){\n setState('error');\n };\n})();\n\n\n// Storage helpers (use the shim above)\nfunction bdStoreList(){\n try { const raw = BarkdayStore.get(BD_STORE_KEY); return raw ? JSON.parse(raw) : []; }\n catch { return []; }\n}\nfunction bdStoreSave(list){\n const ok = BarkdayStore.set(BD_STORE_KEY, JSON.stringify(list));\n if (!ok) bdToast('Could not save on this device (storage blocked).', 3500);\n}\n\n// Optional: show which backend we’re using (local/session/memory) — gated for dev\n(function showStorageStatus(){\n try{\n if (!(location.hostname === 'localhost' && location.search.includes('debug=1'))) return;\n const el = document.createElement('div');\n el.id = 'bdStorageStatus';\n el.textContent = `Storage: ${BarkdayStore.kind}`;\n el.style.cssText = 'position:fixed;right:10px;bottom:10px;font:12px/1.2 system-ui;padding:6px 8px;border-radius:8px;background:#0009;color:#fff;z-index:9999';\n document.addEventListener('DOMContentLoaded', ()=> document.body.appendChild(el), { once:true });\n }catch{}\n})();\n\n\n// Optional: quick self-test button (injects a dummy saved run)\n(function storageSelfTest(){\n try{\n const host = document.getElementById('selftestHost');\n if (!host) return;\n const btn = document.createElement('button');\n btn.className = 'ghost';\n btn.textContent = 'Storage Self-Test';\n btn.addEventListener('click', ()=>{\n const list = bdStoreList();\n list.unshift({\n ts: Date.now(),\n dog: 'Test Dog',\n dob: '2020-01-01',\n weight: 40,\n chewer: 'Normal',\n breed: 'Labrador Retriever',\n group: 'Sporting / Gun Dogs',\n smooth: true, epi: false,\n kpi: { nextHeadline:'Test', nextDate:new Date().toDateString(), nextDateISO:new Date().toISOString(), hy:'42.00', dogAge:'4y 0m' },\n event: { start:new Date().toISOString(), end:new Date(Date.now()+3600000).toISOString(), title:'Test', notes:'Test' }\n });\n bdStoreSave(list);\n bdToast('Dummy run saved. Open Saved ▾ to verify.');\n });\n host.appendChild(btn);\n }catch{}\n})();\n\n// Build the payload we store each time\nfunction currentRunPayload(){\n const { start, end, title, notes } = getContext(); // existing helper\n return {\n ts: Date.now(),\n dog: (els.dogName.value||'').trim(),\n dob: els.dob.value || '',\n weight: parseInt(els.adultWeight.value,10)||55,\n chewer: els.chewer.value,\n breed: (els.breed.value||'').trim(),\n group: els.breedGroup.value,\n smooth: !!els.smooth.checked,\n epi: !!els.showEpi.checked,\n kpi: {\n nextHeadline: els.nextHeadline.textContent,\n nextDate: els.nextBday.textContent,\n nextDateISO: els.nextBday.dataset.iso || null,\n hy: els.humanYears.textContent,\n dogAge: els.dogAge.textContent\n },\n event: { start, end, title, notes }\n };\n}\n\n// Save handler (session-only toast is always shown when not on localStorage)\nfunction bdSaveRun(){\n const list = bdStoreList();\n const now = Date.now();\n const cur = currentRunPayload();\n\n // --- Monetization: free-tier limits ---\n const lim = currentLimits();\n\n // Enforce unique-dog cap (free tier = 5)\n const beforeUnique = countUniqueDogs(list);\n const curDog = (cur.dog || '').trim().toLowerCase();\n const alreadyHaveDog = !!list.find(r => (r?.dog||'').trim().toLowerCase() === curDog);\n if (!alreadyHaveDog && beforeUnique >= lim.maxDogs){\n bdToast(`Free tier allows up to ${lim.maxDogs} dogs on this device. Export & delete one to add more.`, 4500);\n return;\n }\n\n\n // De-dupe: if the latest saved item matches same dog + same ISO date within 2 minutes, skip\n const last = list[0];\n const isDup = last\n && (last.dog||'').trim().toLowerCase() === (cur.dog||'').trim().toLowerCase()\n && (last.kpi?.nextDateISO || '') === (cur.kpi?.nextDateISO || '')\n && Math.abs((last.ts||0) - now) < 120000;\n\n if (!isDup) list.unshift(cur);\n // Tier-aware run cap (free=50)\n if (list.length > lim.maxRuns) list.length = lim.maxRuns;\n\n bdStoreSave(list);\n markSaved();\n bdToast(isDup ? 'Already saved recently' : 'Saved to this device');\n\n if (BarkdayStore?.kind && BarkdayStore.kind !== 'localStorage') {\n bdToast('Saved for this session only in this browser.', 3500);\n }\n\n if (document.getElementById('bdSaved')?.classList.contains('is-open')) {\n BarkdaySaved.render();\n }\n}\n\n\n\nfunction hydrateRun(run, doCompute=false){\n if (!run) return;\n els.dogName.value = run.dog || '';\n els.dob.value = run.dob || '';\n els.adultWeight.value = run.weight || 55;\n els.adultWeightVal.textContent = String(els.adultWeight.value);\n els.chewer.value = run.chewer || 'Normal';\n els.breed.value = run.breed || '';\n els.breedGroup.value = run.group || 'Working / Herding';\n els.smooth.checked = !!run.smooth;\n els.showEpi.checked = !!run.epi;\n renderHero(); updateBreedNotes();\n if (doCompute) compute();\n}\n\n// Drawer UI\nconst BarkdaySaved = (() => {\n const drawer = () => document.getElementById('bdSaved');\n const panel = () => drawer()?.querySelector('.bd-panel');\n const bodyEl = () => document.getElementById('bdSavedBody');\n\n function open(){\n const d = drawer(); if (!d) return;\n render();\n d.classList.add('is-open'); document.body.classList.add('body-lock');\n // backdrop + buttons\n d.addEventListener('click', onBackdrop);\n document.addEventListener('keydown', onEsc);\n panel()?.focus();\n }\n function close(){\n const d = drawer(); if (!d) return;\n d.classList.remove('is-open'); document.body.classList.remove('body-lock');\n d.removeEventListener('click', onBackdrop);\n document.removeEventListener('keydown', onEsc);\n }\n function onBackdrop(e){ if (e.target?.dataset?.close === 'drawer') close(); }\n function onEsc(e){ if (e.key === 'Escape') close(); }\n\n function render(){\n const host = bodyEl(); if (!host) return;\n\n // NEW: render into #bdSavedCards if present, otherwise fall back to the body\n const cardsHost = host.querySelector('#bdSavedCards') || host;\n\n const items = bdStoreList();\n if (!items.length){\n cardsHost.innerHTML = `
No saved results yet. Run Calculate — results auto-save.
`;\n return;\n }\n // Functional cap cue: always accurate, no styling\n try {\n const lim = currentLimits();\n const uniq = countUniqueDogs(items);\n\n // Remove any stale note to avoid duplication or wrong counts\n const old = document.getElementById('bdSavedCapNote');\n if (old && old.parentNode) old.parentNode.removeChild(old);\n\n // Create a fresh note each render so the count is current\n const bar = document.createElement('div');\n bar.id = 'bdSavedCapNote';\n bar.textContent = `Saved dogs: ${uniq}/${lim.maxDogs} (free tier)`;\n\n // Place the note directly above the cards container\n (cardsHost.parentElement || host).insertBefore(bar, cardsHost);\n } catch {}\n\n cardsHost.innerHTML = items.map((r, i) => {\n const date = new Date(r.ts).toLocaleString();\n const dog = r.dog || 'Your dog';\n const hy = r.kpi?.hy || '—';\n const next = r.kpi?.nextDate || '—';\n const w = r.weight ? `${r.weight} lb` : '';\n const grp = r.group || '';\n return `\n
\n

${dog}

\n
${grp}${grp&&w?' · ':''}${w} · Saved ${date}
\n
Next: ${r.kpi?.nextHeadline || '—'} (${next}) · Human-years: ${hy}
\n
\n \n \n \n \n
\n
\n `;\n }).join('');\n}\n\n function onListClick(e){\n const btn = e.target.closest('[data-act]'); if (!btn) return;\n const card = e.target.closest('.bd-card'); if (!card) return;\n const idx = parseInt(card.dataset.i,10);\n const items = bdStoreList();\n const run = items[idx];\n\n switch(btn.dataset.act){\n case 'load':\n hydrateRun(run, false);\n bdToast('Loaded inputs (not computed)');\n break;\n case 'compute':\n hydrateRun(run, true);\n bdToast('Loaded and computed');\n break;\n case 'share': {\n // Rebuild a share URL from inputs\n const p = new URLSearchParams({\n n: els.dogName.value || '',\n d: els.dob.value || '',\n w: els.adultWeight.value,\n c: els.chewer.value,\n g: els.breedGroup.value,\n r: els.breed.value || '',\n s: els.smooth.checked ? 1 : 0,\n e: els.showEpi.checked ? 1 : 0\n });\n const url = location.origin + location.pathname + '?' + p.toString();\n navigator.clipboard.writeText(url).then(()=>bdToast('Share link copied'));\n break;\n }\n case 'delete': {\n const next = items.filter((_,i)=>i!==idx);\n bdStoreSave(next);\n render();\n bdToast('Deleted');\n break;\n }\n }\n }\n\n // Footer controls\nfunction onFooterClick(e){\n const id = e.target.id;\n\n if (id === 'bdExport'){\n try {\n const runs = bdStoreList() || [];\n const payload = { version: 1, exportedAt: new Date().toISOString(), app: 'Barkday', runs };\n const blob = new Blob([JSON.stringify(payload)], { type:'application/json' });\n const a = document.createElement('a');\n a.href = URL.createObjectURL(blob);\n const dt = new Date().toISOString().slice(0,19).replace(/[:T]/g,'-');\n a.download = `barkday-export-${dt}.barkday`; // no “JSON” in filename\n document.body.appendChild(a); a.click(); a.remove();\n setTimeout(()=>URL.revokeObjectURL(a.href), 1000);\n bdToast?.('Exported your records.');\n } catch (err) {\n console.warn('[Barkday] export failed', err);\n bdToast?.('Export failed.');\n }\n\n } else if (id === 'bdImport') {\n const input = document.getElementById('bdImportFile');\n if (!input) { alert('Import not available.'); return; }\n input.value = ''; // allow same file twice\n input.onchange = async (ev) => {\n const f = ev.target.files && ev.target.files[0];\n if (!f) return;\n if (!/\\.barkday$|\\.json$/i.test(f.name)) { bdToast?.('Please choose an exported Barkday file.'); input.value=''; input.onchange=null; return; }\n\n try {\n const text = await f.text();\n const raw = JSON.parse(text);\n\n // normalize accepted shapes\n const norm = Array.isArray(raw)\n ? { version:1, exportedAt:null, runs: raw }\n : (raw && Array.isArray(raw.runs) ? { version:raw.version??1, exportedAt:raw.exportedAt??null, runs: raw.runs } : null);\n\n if (!norm) { bdToast?.('That file could not be read.'); input.value=''; input.onchange=null; return; }\n\n // soft validation\n const isRun = (x)=> x && typeof x==='object' && (('id'in x)||('_id'in x)||('ts'in x)) && (('dog'in x)||('breed'in x)||('event'in x)||('kpi'in x));\n const incoming = (norm.runs||[]).filter(isRun);\n if (!incoming.length){ bdToast?.('No records found in the file.'); input.value=''; input.onchange=null; return; }\n\n // merge with existing; dedupe by stable key, newest ts wins\n const existing = bdStoreList() || [];\n const key = (x)=> String(x?.id ?? x?._id ?? `${x?.dog||'dog'}|${x?.dob||''}|${x?.ts||''}`);\n const map = new Map();\n const add = (arr)=>arr.forEach(r=>{\n if (!isRun(r)) return;\n const k = key(r), prev = map.get(k);\n if (!prev) { map.set(k, r); return; }\n const tNew = new Date(r.ts||0).getTime(), tOld = new Date(prev.ts||0).getTime();\n if (tNew > tOld) map.set(k, r);\n });\n add(existing); add(incoming);\n const merged = Array.from(map.values());\n\n // persist with your existing helper\n bdStoreSave(merged);\n render(); // re-render drawer\n bdToast?.(`Imported ${incoming.length} record(s).`);\n } catch (err) {\n console.warn('[Barkday] import failed', err);\n bdToast?.('Import failed.');\n } finally {\n input.value=''; input.onchange=null;\n }\n };\n input.click();\n\n } else if (id === 'bdClearAll'){\n if (confirm('Delete all saved results on this device?')){\n bdStoreSave([]); render(); bdToast('Cleared');\n }\n\n } else if (e.target.dataset?.close === 'drawer'){\n close();\n }\n}\n\n\n // Public API\n return { open, close, render, onListClick, onFooterClick };\n})();\n\n\n// Find and set the closest option in \n\n\n\n \n
\n \n \n
Dog age shown under Results.
\n
\n
\n \n
\n
55 lb
\n \n
\n
\n
\n \n \n
\n \n\n
\n
\n \n \n \n
\n
\n \n \n
Notes only — math stays weight-based.
\n
\n
\n \n \n
\n
\n
\n\n
\n \n \n \n
\n\n \n
\n\n
\n\n
\n\n

Results

\n
\n
\n
\n
\n
\n
\n

Dog age today

\n

Human-years estimate

\n
\n

\n
\n\n
\n\n
\n\n

Next Birthday Plan

\n
\n\n
\n\n

Gift ideas

\n \n
\n
\n \n \n\n\n\n\n\n\n\n\n\n\n\n \n
\n

© 2025 Barkday™. All Rights Reserved.

\n

\n Privacy · \n Terms\n

\n

Sebby (our mascot) and I hope this makes you day just a little brighter.

\n
\n\n \n \n\n \n
\n
\n
\n \n
\n

Your Barkday Results

\n
\n
\n
\n \n
\n
\n
\n \n \n\n
\n Results updated.\n \n
\n\n
\n
\n
\n
\n

Saved Results

\n \n
\n
\n
\n

Privacy & portability — Barkday™ saves your results only on this device.\n To take them to another device, click Export to download a file. On the other device, open Barkday™ and click Import to load it.

\n
\n\n \n \n\n \n
\n
\n
\n \n \n \n \n
\n
\n
\n\n\n\n\n\n","inline_bytes":10851,"content_sha256":"d7f2cc3fe09b181dfd6e609cc20fce237bdb899f5d435615aea222edd15f597c"},{"path":"js/barkday-curves.js","size":4385,"sha":"e9a763cb7527076b66997da595390e5663c9d869","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/js/barkday-curves.js","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/js/barkday-curves.js","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"/* barkday-curves.js\n Smooth Bark Day scheduling helpers\n - LOCT (first 2 human years): strictly increasing AP gaps that sum to 365 per year\n - Smooth curve (>= 2y): monotone cubic (PCHIP) cumulative K(t) with anchors + inversion\n No external deps.\n*/\n\nexport function yearGapsAP(n, a0Days, yearDays = 365) {\n if (n <= 0) return [];\n const denom = n * (n - 1) / 2;\n const d = (yearDays - n * a0Days) / denom;\n const gaps = Array.from({ length: n }, (_, i) => a0Days + i * d);\n const sum = gaps.reduce((a, b) => a + b, 0);\n gaps[gaps.length - 1] += (yearDays - sum);\n return gaps;\n}\n\nexport function kTimesYear1Year2(loctConf) {\n const n1 = loctConf?.y1?.n ?? 15;\n const a0y1 = loctConf?.y1?.a0_days ?? 10;\n const n2 = loctConf?.y2?.n ?? 9;\n const a0Hint = loctConf?.y2?.a0_hint_days ?? 38;\n\n const gapsY1 = yearGapsAP(n1, a0y1, 365);\n const tY1 = [];\n let acc = 0;\n for (const g of gapsY1) { acc += g; tY1.push(acc / 365); }\n\n const lastY1Gap = gapsY1[gapsY1.length - 1];\n const a0y2 = Math.max(a0Hint, lastY1Gap);\n const gapsY2 = yearGapsAP(n2, a0y2, 365);\n const tY2 = [];\n acc = 0;\n for (const g of gapsY2) { acc += g; tY2.push(1 + acc / 365); }\n\n const out = {};\n tY1.forEach((t, i) => out[String(i + 1)] = +t.toFixed(6));\n tY2.forEach((t, i) => out[String(n1 + i + 1)] = +t.toFixed(6));\n return out;\n}\n\nexport function buildPCHIP(anchors) {\n const n = anchors.length;\n if (n < 2) throw new Error('PCHIP: Need at least two anchors');\n const t = anchors.map(a => +a.t_years);\n const y = anchors.map(a => +a.K_total);\n const h = Array(n - 1), delta = Array(n - 1);\n for (let i = 0; i < n - 1; i++) {\n h[i] = t[i + 1] - t[i];\n delta[i] = (y[i + 1] - y[i]) / h[i];\n if (!(h[i] > 0) || !(delta[i] >= 0)) {\n throw new Error('PCHIP: anchors must have increasing t and nondecreasing K');\n }\n }\n const m = Array(n).fill(0);\n m[0] = delta[0];\n m[n - 1] = delta[n - 2];\n for (let i = 1; i < n - 1; i++) {\n if (delta[i - 1] * delta[i] <= 0) {\n m[i] = 0;\n } else {\n const w1 = 2 * h[i] + h[i - 1];\n const w2 = h[i] + 2 * h[i - 1];\n m[i] = (w1 + w2) / (w1 / delta[i - 1] + w2 / delta[i]);\n }\n }\n function evalAt(x) {\n if (x <= t[0]) return y[0];\n if (x >= t[n - 1]) return y[n - 1];\n let s = 0, e = n - 1;\n while (s + 1 < e) {\n const mid = (s + e) >> 1;\n if (t[mid] <= x) s = mid; else e = mid;\n }\n const hS = h[s];\n const tau = (x - t[s]) / hS;\n const h00 = (1 + 2 * tau) * (1 - tau) * (1 - tau);\n const h10 = tau * (1 - tau) * (1 - tau);\n const h01 = tau * tau * (3 - 2 * tau);\n const h11 = tau * tau * (tau - 1);\n return h00 * y[s] + h10 * hS * m[s] + h01 * y[s + 1] + h11 * hS * m[s + 1];\n }\n return (x) => evalAt(x);\n}\n\nexport function invertK(evalK, k, tLo = 2.0, tHi = 12.0, iters = 44) {\n let lo = tLo, hi = tHi;\n let vLo = evalK(lo), vHi = evalK(hi);\n if (k <= vLo) return lo;\n if (k >= vHi) return hi;\n for (let i = 0; i < iters; i++) {\n const mid = (lo + hi) / 2;\n const v = evalK(mid);\n if (v < k) { lo = mid; } else { hi = mid; }\n }\n return (lo + hi) / 2;\n}\n\nexport function smoothTimesBeyondYear2(analyticConf, startK = 25, maxK = 80, tMaxYears = 12) {\n if (!analyticConf || !Array.isArray(analyticConf.anchors)) return {};\n const evalK = buildPCHIP(analyticConf.anchors);\n const out = {};\n for (let k = startK; k <= maxK; k++) {\n const t = invertK(evalK, k, 2.0, tMaxYears, 44);\n out[String(k)] = +t.toFixed(6);\n }\n return out;\n}\n\nexport function buildBarkdayTimes(breedCurveConf, options = {}) {\n const maxK = options.maxK ?? 80;\n const tMaxYears = options.tMaxYears ?? 12;\n\n const loctTimes = kTimesYear1Year2(breedCurveConf?.loct || {\n y1: { n: 15, a0_days: 10 },\n y2: { n: 9, a0_hint_days: 38 }\n });\n\n const beyond = smoothTimesBeyondYear2(breedCurveConf?.analytic, 25, maxK, tMaxYears);\n\n return { ...loctTimes, ...beyond };\n}\n\nexport function barkdayDate(dob, tYears) {\n const ms = dob.getTime() + tYears * 365.25 * 86400 * 1000;\n return new Date(ms);\n}\n\nexport function nextKAfterNow(dob, times) {\n const nowYears = (Date.now() - dob.getTime()) / (365.25 * 86400 * 1000);\n let bestK = null, bestT = null;\n for (const [k, t] of Object.entries(times)) {\n if (t > nowYears && (bestT == null || t < bestT)) {\n bestT = t; bestK = +k;\n }\n }\n return { k: bestK, tYears: bestT };\n}\n","inline_bytes":4385,"content_sha256":"6d0c198dee8e0a8272b88818dec72401d0f919ae4e8a2d5611d685787d38e062"},{"path":"js/runtime-fetch.js","size":1074,"sha":"9e10cb06ab77baf84441ee4da58d667c3359effd","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/js/runtime-fetch.js","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/js/runtime-fetch.js","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"// js/runtime-fetch.js\r\n(function(){\r\n async function fetchJSONWithETag(url, {cacheMinutes=60, lsKey} = {}) {\r\n const now = Date.now();\r\n const entry = JSON.parse(localStorage.getItem(lsKey) || 'null');\r\n const fresh = entry && (now - entry.savedAt) < cacheMinutes*60*1000;\r\n\r\n const headers = {};\r\n if (entry?.etag) headers['If-None-Match'] = entry.etag;\r\n\r\n const bust = fresh ? '' : `?t=${Math.floor(now/(cacheMinutes*60*1000))}`;\r\n try {\r\n const res = await fetch(url + bust, { headers, cache: 'no-cache' });\r\n if (res.status === 304 && entry?.data) return entry.data;\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n const etag = res.headers.get('ETag');\r\n const data = await res.json();\r\n localStorage.setItem(lsKey, JSON.stringify({ data, etag, savedAt: now }));\r\n return data;\r\n } catch (err) {\r\n if (entry?.data) return entry.data;\r\n console.warn('[Barkday][Gifts] fetch failed and no cache:', err);\r\n return null;\r\n }\r\n }\r\n window.BarkdayFetch = { fetchJSONWithETag };\r\n})();\r\n","inline_bytes":1074,"content_sha256":"82047dfe777473c70c43a86367d653e46ac90e0df032917e5ac1e9ed6d8fa5e6"},{"path":"lighthouserc.json","size":1660,"sha":"b5d1c57f27e7e51231c77a982aa13c7d7026132b","media_type":"application/json","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/lighthouserc.json","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/lighthouserc.json","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"{\r\n \"ci\": {\r\n \"collect\": {\r\n \"url\": [\"https://candidquality.github.io/Barkday/\"],\r\n \"numberOfRuns\": 2,\r\n \"settings\": { \"disableStorageReset\": true }\r\n },\r\n \"assert\": {\r\n \"preset\": \"lighthouse:recommended\",\r\n \"assertions\": {\r\n \"categories:performance\": [\"warn\", { \"minScore\": 0.85 }],\r\n \"categories:accessibility\": [\"warn\", { \"minScore\": 0.90 }],\r\n \"categories:seo\": [\"warn\", { \"minScore\": 0.90 }],\r\n \"categories:best-practices\":[\"warn\", { \"minScore\": 0.90 }],\r\n\r\n \"cls-culprits-insight\": \"warn\",\r\n \"image-delivery-insight\": \"warn\",\r\n \"lcp-discovery-insight\": \"warn\",\r\n \"network-dependency-tree-insight\":\"warn\",\r\n \"render-blocking-insight\": \"warn\",\r\n \"cache-insight\": \"warn\",\r\n\r\n \"unsized-images\": [\"warn\", { \"maxLength\": 0 }],\r\n \"uses-responsive-images\": [\"warn\", { \"maxLength\": 0 }],\r\n \"modern-image-formats\": [\"warn\", { \"maxLength\": 0 }],\r\n \"render-blocking-resources\":[\"warn\", { \"maxLength\": 0 }],\r\n \"uses-long-cache-ttl\": [\"warn\", { \"maxLength\": 0 }],\r\n \"unminified-javascript\": [\"warn\", { \"maxLength\": 0 }],\r\n \"unused-javascript\": [\"warn\", { \"maxLength\": 0 }],\r\n \"label-content-name-mismatch\": [\"warn\", { \"maxLength\": 0 }],\r\n\r\n \"cumulative-layout-shift\": [\"warn\", { \"minScore\": 0.85 }],\r\n \"first-contentful-paint\": [\"warn\", { \"minScore\": 0.75 }],\r\n \"largest-contentful-paint\":[\"warn\", { \"minScore\": 0.80 }]\r\n }\r\n },\r\n \"upload\": { \"target\": \"temporary-public-storage\" }\r\n }\r\n}\r\n","inline_bytes":1660,"content_sha256":"37691dee053af00e47912d6033afd7d15cbd6f4a01f2376db4f6e88f5969984e"},{"path":"manifest.json","size":940,"sha":"32bc9bf6a627b8681caeb63fcd21f8e91a904b5a","media_type":"application/json","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/manifest.json","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/manifest.json","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"{\n \"name\": \"Barkday™\",\n \"short_name\": \"Barkday\",\n \"description\": \"Dog birthday age calculator & celebration reminders with gift ideas.\",\n \"start_url\": \"/Barkday/\",\n \"scope\": \"/Barkday/\",\n \"display\": \"standalone\",\n \"background_color\": \"#ffffff\",\n \"theme_color\": \"#111827\",\n \"icons\": [\n {\n \"src\": \"icon-192.png\",\n \"sizes\": \"192x192\",\n \"type\": \"image/png\"\n },\n {\n \"src\": \"icon-256.png\",\n \"sizes\": \"256x256\",\n \"type\": \"image/png\"\n },\n {\n \"src\": \"icon-384.png\",\n \"sizes\": \"384x384\",\n \"type\": \"image/png\"\n },\n {\n \"src\": \"icon-512.png\",\n \"sizes\": \"512x512\",\n \"type\": \"image/png\"\n },\n {\n \"src\": \"icon-maskable-192.png\",\n \"sizes\": \"192x192\",\n \"type\": \"image/png\",\n \"purpose\": \"maskable\"\n },\n {\n \"src\": \"icon-maskable-512.png\",\n \"sizes\": \"512x512\",\n \"type\": \"image/png\",\n \"purpose\": \"maskable\"\n }\n ]\n}\n","inline_bytes":938,"content_sha256":"2fd71857e05468115464fc851f0b95a8d1562f0a71b5e7a21a8c58157eb4d69a"},{"path":"milestones_dog_barkdays_1_95-1.json","size":51594,"sha":"6e97d7a7896b48c2b515c5b97a13142ad8cd01e7","media_type":"application/json","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/milestones_dog_barkdays_1_95-1.json","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/milestones_dog_barkdays_1_95-1.json","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"{\n \"1\": {\n \"title\": \"1st Barkday — Puppy year — rapid learning & socialization\",\n \"expect\": \"High curiosity, short attention span; socialization is key.\",\n \"train\": [\n \"Short, upbeat sessions (3–5 min) 2–3×/day\",\n \"Name game & hand target\",\n \"Sit/down basics with luring\"\n ],\n \"care\": [\n \"Multiple short naps; controlled playdates\",\n \"Enrichment: snuffle mat once daily\",\n \"Vet consult on vaccines & parasite plan\"\n ],\n \"short\": \"Recall, stays, and social calm; add scent games.\"\n },\n \"2\": {\n \"title\": \"2nd Barkday — Late puppy — impulse control begins\",\n \"expect\": \"High curiosity, short attention span; socialization is key.\",\n \"train\": [\n \"Introduce stay (1–3s), reward calm\",\n \"Loose-leash basics in quiet areas\",\n \"Recall on long line (5–10 m)\"\n ],\n \"care\": [\n \"Rotate 2 puzzles/week\",\n \"Reinforce calm greetings\",\n \"Teething support if needed\"\n ],\n \"short\": \"Recall, stays, and social calm; add scent games.\"\n },\n \"3\": {\n \"title\": \"3rd Barkday — Young adolescent — testing limits is normal\",\n \"expect\": \"Impulse control growing; expect occasional boundary testing.\",\n \"train\": [\n \"Increase stay (5–10s) with distance\",\n \"Leave-it / drop-it games\",\n \"Mat/place training for settle\"\n ],\n \"care\": [\n \"Daily exercise 40–60 min (split)\",\n \"Grooming routine weekly\",\n \"Basic dental chew/brush intro\"\n ],\n \"short\": \"Recall, stays, and social calm; add scent games.\"\n },\n \"4\": {\n \"title\": \"4th Barkday — Adolescent peak — build consistency\",\n \"expect\": \"Impulse control growing; expect occasional boundary testing.\",\n \"train\": [\n \"Recall with higher distractions\",\n \"Directional fetch (left/right)\",\n \"Start scent games: simple hides\"\n ],\n \"care\": [\n \"Warmup before fetch/tug\",\n \"Two enrichment activities/day\",\n \"Weight check; adjust calories\"\n ],\n \"short\": \"Recall, stays, and social calm; add scent games.\"\n },\n \"5\": {\n \"title\": \"5th Barkday — Early adult — refine manners\",\n \"expect\": \"Prime learning window; habits cement quickly—good or bad.\",\n \"train\": [\n \"Longer stays (30–60s) & duration on mat\",\n \"Heel in low-to-moderate distractions\",\n \"Trick chaining (spin→sit→touch)\"\n ],\n \"care\": [\n \"Vary routes; novelty walks\",\n \"Conditioning 2×/week (hills/cavaletti)\",\n \"Annual wellness exam\"\n ],\n \"short\": \"Proof cues; nosework & conditioning keep things sharp.\"\n },\n \"6\": {\n \"title\": \"6th Barkday — Early adult — refine manners\",\n \"expect\": \"Prime learning window; habits cement quickly—good or bad.\",\n \"train\": [\n \"Longer stays (30–60s) & duration on mat\",\n \"Heel in low-to-moderate distractions\",\n \"Trick chaining (spin→sit→touch)\"\n ],\n \"care\": [\n \"Vary routes; novelty walks\",\n \"Conditioning 2×/week (hills/cavaletti)\",\n \"Annual wellness exam\"\n ],\n \"short\": \"Proof cues; nosework & conditioning keep things sharp.\"\n },\n \"7\": {\n \"title\": \"7th Barkday — Prime adult — mental work matters\",\n \"expect\": \"Prime learning window; habits cement quickly—good or bad.\",\n \"train\": [\n \"Proof cues around dogs/people\",\n \"Advanced nosework patterns\",\n \"Calm settle in busy areas (cafés/parks)\"\n ],\n \"care\": [\n \"Cross‑training (swim/hike/puzzle)\",\n \"Teeth check; consider cleaning\",\n \"Parasite prevention review\"\n ],\n \"short\": \"Proof cues; nosework & conditioning keep things sharp.\"\n },\n \"8\": {\n \"title\": \"8th Barkday — Prime adult — mental work matters\",\n \"expect\": \"Prime learning window; habits cement quickly—good or bad.\",\n \"train\": [\n \"Proof cues around dogs/people\",\n \"Advanced nosework patterns\",\n \"Calm settle in busy areas (cafés/parks)\"\n ],\n \"care\": [\n \"Cross‑training (swim/hike/puzzle)\",\n \"Teeth check; consider cleaning\",\n \"Parasite prevention review\"\n ],\n \"short\": \"Proof cues; nosework & conditioning keep things sharp.\"\n },\n \"9\": {\n \"title\": \"9th Barkday — Prime adult — mental work matters\",\n \"expect\": \"Prime learning window; habits cement quickly—good or bad.\",\n \"train\": [\n \"Proof cues around dogs/people\",\n \"Advanced nosework patterns\",\n \"Calm settle in busy areas (cafés/parks)\"\n ],\n \"care\": [\n \"Cross‑training (swim/hike/puzzle)\",\n \"Teeth check; consider cleaning\",\n \"Parasite prevention review\"\n ],\n \"short\": \"Proof cues; nosework & conditioning keep things sharp.\"\n },\n \"10\": {\n \"title\": \"10th Barkday — Mature adult — protect joints, keep brain busy\",\n \"expect\": \"Energy steady; protect joints and keep the brain engaged.\",\n \"train\": [\n \"Low‑impact agility (cavaletti/backing up)\",\n \"Longer calm settles (5–10 min)\",\n \"Discrimination games (toy A vs B)\"\n ],\n \"care\": [\n \"Joint warmups/cooldowns\",\n \"Surface awareness (non‑slip rugs)\",\n \"Body condition re‑check\"\n ],\n \"short\": \"Low‑impact work, longer calm settles, joint warmups.\"\n },\n \"11\": {\n \"title\": \"11th Barkday — Mature adult — protect joints, keep brain busy\",\n \"expect\": \"Energy steady; protect joints and keep the brain engaged.\",\n \"train\": [\n \"Low‑impact agility (cavaletti/backing up)\",\n \"Longer calm settles (5–10 min)\",\n \"Discrimination games (toy A vs B)\"\n ],\n \"care\": [\n \"Joint warmups/cooldowns\",\n \"Surface awareness (non‑slip rugs)\",\n \"Body condition re‑check\"\n ],\n \"short\": \"Low‑impact work, longer calm settles, joint warmups.\"\n },\n \"12\": {\n \"title\": \"12th Barkday — Mature adult — protect joints, keep brain busy\",\n \"expect\": \"Energy steady; protect joints and keep the brain engaged.\",\n \"train\": [\n \"Low‑impact agility (cavaletti/backing up)\",\n \"Longer calm settles (5–10 min)\",\n \"Discrimination games (toy A vs B)\"\n ],\n \"care\": [\n \"Joint warmups/cooldowns\",\n \"Surface awareness (non‑slip rugs)\",\n \"Body condition re‑check\"\n ],\n \"short\": \"Low‑impact work, longer calm settles, joint warmups.\"\n },\n \"13\": {\n \"title\": \"13th Barkday — Early senior — shorter, richer sessions\",\n \"expect\": \"Slight slowdown; shorter focused sessions work best.\",\n \"train\": [\n \"3–5 min training bursts, more frequently\",\n \"Gentle sniffaris & puzzle feeders\",\n \"Balance work: wobble cushion/slow stands\"\n ],\n \"care\": [\n \"Senior baseline labs with vet\",\n \"Softer chews & heated rest\",\n \"Monitor vision/hearing changes\"\n ],\n \"short\": \"Short, rich sessions; gentle puzzles & balance work.\"\n },\n \"14\": {\n \"title\": \"14th Barkday — Early senior — shorter, richer sessions\",\n \"expect\": \"Slight slowdown; shorter focused sessions work best.\",\n \"train\": [\n \"3–5 min training bursts, more frequently\",\n \"Gentle sniffaris & puzzle feeders\",\n \"Balance work: wobble cushion/slow stands\"\n ],\n \"care\": [\n \"Senior baseline labs with vet\",\n \"Softer chews & heated rest\",\n \"Monitor vision/hearing changes\"\n ],\n \"short\": \"Short, rich sessions; gentle puzzles & balance work.\"\n },\n \"15\": {\n \"title\": \"15th Barkday — Early senior — shorter, richer sessions\",\n \"expect\": \"Slight slowdown; shorter focused sessions work best.\",\n \"train\": [\n \"3–5 min training bursts, more frequently\",\n \"Gentle sniffaris & puzzle feeders\",\n \"Balance work: wobble cushion/slow stands\"\n ],\n \"care\": [\n \"Senior baseline labs with vet\",\n \"Softer chews & heated rest\",\n \"Monitor vision/hearing changes\"\n ],\n \"short\": \"Short, rich sessions; gentle puzzles & balance work.\"\n },\n \"16\": {\n \"title\": \"16th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"17\": {\n \"title\": \"17th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"18\": {\n \"title\": \"18th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"19\": {\n \"title\": \"19th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"20\": {\n \"title\": \"20th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"21\": {\n \"title\": \"21st Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"22\": {\n \"title\": \"22nd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"23\": {\n \"title\": \"23rd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"24\": {\n \"title\": \"24th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"25\": {\n \"title\": \"25th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"26\": {\n \"title\": \"26th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"27\": {\n \"title\": \"27th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"28\": {\n \"title\": \"28th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"29\": {\n \"title\": \"29th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"30\": {\n \"title\": \"30th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"31\": {\n \"title\": \"31st Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"32\": {\n \"title\": \"32nd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"33\": {\n \"title\": \"33rd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"34\": {\n \"title\": \"34th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"35\": {\n \"title\": \"35th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"36\": {\n \"title\": \"36th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"37\": {\n \"title\": \"37th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"38\": {\n \"title\": \"38th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"39\": {\n \"title\": \"39th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"40\": {\n \"title\": \"40th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"41\": {\n \"title\": \"41st Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"42\": {\n \"title\": \"42nd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"43\": {\n \"title\": \"43rd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"44\": {\n \"title\": \"44th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"45\": {\n \"title\": \"45th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"46\": {\n \"title\": \"46th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"47\": {\n \"title\": \"47th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"48\": {\n \"title\": \"48th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"49\": {\n \"title\": \"49th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"50\": {\n \"title\": \"50th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"51\": {\n \"title\": \"51st Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"52\": {\n \"title\": \"52nd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"53\": {\n \"title\": \"53rd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"54\": {\n \"title\": \"54th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"55\": {\n \"title\": \"55th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"56\": {\n \"title\": \"56th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"57\": {\n \"title\": \"57th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"58\": {\n \"title\": \"58th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"59\": {\n \"title\": \"59th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"60\": {\n \"title\": \"60th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"61\": {\n \"title\": \"61st Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"62\": {\n \"title\": \"62nd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"63\": {\n \"title\": \"63rd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"64\": {\n \"title\": \"64th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"65\": {\n \"title\": \"65th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"66\": {\n \"title\": \"66th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"67\": {\n \"title\": \"67th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"68\": {\n \"title\": \"68th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"69\": {\n \"title\": \"69th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"70\": {\n \"title\": \"70th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"71\": {\n \"title\": \"71st Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"72\": {\n \"title\": \"72nd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"73\": {\n \"title\": \"73rd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"74\": {\n \"title\": \"74th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"75\": {\n \"title\": \"75th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"76\": {\n \"title\": \"76th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"77\": {\n \"title\": \"77th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"78\": {\n \"title\": \"78th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"79\": {\n \"title\": \"79th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"80\": {\n \"title\": \"80th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"81\": {\n \"title\": \"81st Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"82\": {\n \"title\": \"82nd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"83\": {\n \"title\": \"83rd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"84\": {\n \"title\": \"84th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"85\": {\n \"title\": \"85th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"86\": {\n \"title\": \"86th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"87\": {\n \"title\": \"87th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"88\": {\n \"title\": \"88th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"89\": {\n \"title\": \"89th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"90\": {\n \"title\": \"90th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"91\": {\n \"title\": \"91st Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"92\": {\n \"title\": \"92nd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"93\": {\n \"title\": \"93rd Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"94\": {\n \"title\": \"94th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n },\n \"95\": {\n \"title\": \"95th Barkday — Senior 16+ — comfort, cognition, safe movement\",\n \"expect\": \"Comfort first—cognition and gentle mobility keep quality of life high.\",\n \"train\": [\n \"Cognitive games: easy scent hides\",\n \"Cooperative care (nail/ear/teeth)\",\n \"Mobility: figure‑8s, massage, slow stairs\"\n ],\n \"care\": [\n \"Twice‑yearly vet visits\",\n \"Joint support & ramps as needed\",\n \"Short, frequent enrichment\"\n ],\n \"short\": \"Easy scent games, cooperative care, gentle mobility.\"\n }\n}","inline_bytes":50652,"content_sha256":"18355331713734a7d0abfefac6c2361377719fb2590853719877b0844fcd87a8"},{"path":"play-store-icon.png","size":1050910,"sha":"9399f730782ce572f00ec839fc4c86ac3718c36b","media_type":"image/png","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/play-store-icon.png","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/play-store-icon.png","inline_state":"none","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536},{"path":"privacy.html","size":1279,"sha":"76ab97442782358f2ed7c3efacc6e27e893ae1e1","media_type":"text/html","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/privacy.html","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/privacy.html","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"\n\n\n \n \n Barkday™ • Privacy Policy\n \n \n \n\n\n

Barkday™ Privacy Policy

\n

Last updated: September 21, 2025

\n\n

Information We Collect

\n
    \n
  • Optional inputs you provide (dog’s name, breed, birthdate) are stored only in your browser.
  • \n
  • No personal data is collected or transmitted to Barkday servers.
  • \n
\n\n

How We Use Information

\n
    \n
  • To calculate and display age milestones and gift ideas directly on your device.
  • \n
  • Anonymous diagnostic data may be used by GitHub Pages hosting (standard web logs).
  • \n
\n\n

Third-Party Links

\n

Gift recommendations may include affiliate links (Amazon, Chewy). Barkday may earn commissions at no additional cost to you.

\n\n

Contact

\n

Email: hello@barkday.app

\n\n

← Back to Barkday

\n\n\n","inline_bytes":1269,"content_sha256":"554e2cee6eb463d9bf723529828f9cdcd97998f3444e7268ea2866a22f6a04d7"},{"path":"robots.txt","size":84,"sha":"4a0df3df85edd7f62673ab313f0cfc3441e4d801","media_type":"text/plain","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/robots.txt","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/robots.txt","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"User-agent: *\nAllow: /\nSitemap: https://candidquality.github.io/barkday/sitemap.xml\n","inline_bytes":84,"content_sha256":"66d559f8035482bdce909b52a5092ad27d713d503318898158ab9486e7d671bd"},{"path":"schema/dog-gifts-catalog.schema.v2.json","size":4622,"sha":"7f1001ade070006d3a9762efe1e5aba73f41bc7f","media_type":"application/json","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/schema/dog-gifts-catalog.schema.v2.json","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/schema/dog-gifts-catalog.schema.v2.json","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://barkday.app/schema/dog-gifts-catalog.v2.json\",\n \"title\": \"Barkday Gift Catalog v2\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"version\", \"generatedAt\", \"items\"],\n \"properties\": {\n \"version\": { \"const\": 2 },\n \"generatedAt\": { \"type\": \"string\", \"format\": \"date-time\" },\n \"marketplaceDefault\": { \"type\": \"string\", \"default\": \"www.amazon.com\" },\n \"notes\": { \"type\": \"string\" },\n \"items\": {\n \"type\": \"array\",\n \"items\": { \"$ref\": \"#/$defs/giftItem\" }\n }\n },\n \"$defs\": {\n \"giftItem\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\n \"id\",\n \"title\",\n \"category\",\n \"ageAxis\",\n \"sizes\",\n \"chew\",\n \"affiliate\",\n \"source\",\n \"active\"\n ],\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"pattern\": \"^[a-z0-9][a-z0-9._-]{2,80}$\"\n },\n \"title\": { \"type\": \"string\", \"minLength\": 1 },\n \"benefit\": { \"type\": \"string\" },\n \"category\": {\n \"type\": \"string\",\n \"enum\": [\n \"chew\",\n \"fetch\",\n \"training\",\n \"comfort\",\n \"feeding\",\n \"enrichment\",\n \"walks\",\n \"safety\",\n \"travel\",\n \"grooming\",\n \"health\",\n \"seasonal\",\n \"other\"\n ]\n },\n \"tags\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"default\": []\n },\n \"ageAxis\": {\n \"type\": \"string\",\n \"enum\": [\"human\", \"dog\", \"none\"]\n },\n \"minAge\": { \"type\": \"number\", \"minimum\": 0 },\n \"maxAge\": { \"type\": \"number\", \"minimum\": 0 },\n \"minDogYears\": { \"type\": \"number\", \"minimum\": 0 },\n \"maxDogYears\": { \"type\": \"number\", \"minimum\": 0 },\n \"sizes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\"toy\", \"small\", \"medium\", \"large\", \"giant\", \"any\"]\n },\n \"minItems\": 1\n },\n \"chew\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\"gentle\", \"normal\", \"strong\", \"any\"]\n },\n \"minItems\": 1\n },\n \"breedGroups\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"default\": []\n },\n \"preferred\": { \"type\": \"boolean\", \"default\": false },\n \"priority\": { \"type\": \"integer\", \"minimum\": 0, \"maximum\": 1000, \"default\": 100 },\n \"source\": {\n \"type\": \"string\",\n \"enum\": [\"curated\", \"amazon_enriched\", \"manual_partner\", \"mixed\"]\n },\n \"affiliate\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"url\"],\n \"properties\": {\n \"url\": { \"type\": \"string\", \"format\": \"uri\" },\n \"asin\": { \"type\": \"string\", \"pattern\": \"^[A-Z0-9]{10}$\" },\n \"marketplace\": { \"type\": \"string\" },\n \"partnerTag\": { \"type\": \"string\" },\n \"subtag\": { \"type\": \"string\" }\n }\n },\n \"amazon\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"properties\": {\n \"detailPageURL\": { \"type\": \"string\", \"format\": \"uri\" },\n \"imageUrl\": { \"type\": \"string\", \"format\": \"uri\" },\n \"imageRefreshedAt\": { \"type\": \"string\", \"format\": \"date-time\" },\n \"offersRefreshedAt\": { \"type\": \"string\", \"format\": \"date-time\" },\n \"titleRefreshedAt\": { \"type\": \"string\", \"format\": \"date-time\" },\n \"resources\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"default\": []\n }\n }\n },\n \"active\": { \"type\": \"boolean\" },\n \"expiresAt\": { \"type\": \"string\", \"format\": \"date-time\" },\n \"notes\": { \"type\": \"string\" }\n },\n \"allOf\": [\n {\n \"if\": { \"properties\": { \"ageAxis\": { \"const\": \"human\" } } },\n \"then\": {\n \"not\": {\n \"anyOf\": [\n { \"required\": [\"minDogYears\"] },\n { \"required\": [\"maxDogYears\"] }\n ]\n }\n }\n },\n {\n \"if\": { \"properties\": { \"ageAxis\": { \"const\": \"dog\" } } },\n \"then\": {\n \"not\": {\n \"anyOf\": [\n { \"required\": [\"minAge\"] },\n { \"required\": [\"maxAge\"] }\n ]\n }\n }\n }\n ]\n }\n }\n}\n","inline_bytes":4622,"content_sha256":"34ae1daa06fabfad38111cc27785bd276df5e023a537ff3c175a1beee5975763"},{"path":"schema/dog-gifts-preferred.schema.v2.json","size":1468,"sha":"655c3fe2159183710bd287f1dd2f8f1bfa826e84","media_type":"application/json","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/schema/dog-gifts-preferred.schema.v2.json","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/schema/dog-gifts-preferred.schema.v2.json","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"https://barkday.app/schema/dog-gifts-preferred.v2.json\",\n \"title\": \"Barkday Gift Preferred Overlay v2\",\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"version\", \"generatedAt\", \"items\"],\n \"properties\": {\n \"version\": { \"const\": 2 },\n \"generatedAt\": { \"type\": \"string\", \"format\": \"date-time\" },\n \"notes\": { \"type\": \"string\" },\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"additionalProperties\": false,\n \"required\": [\"id\", \"active\"],\n \"properties\": {\n \"id\": {\n \"type\": \"string\",\n \"pattern\": \"^[a-z0-9][a-z0-9._-]{2,80}$\"\n },\n \"title\": { \"type\": \"string\" },\n \"benefit\": { \"type\": \"string\" },\n \"category\": { \"type\": \"string\" },\n \"tags\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"default\": []\n },\n \"preferred\": { \"type\": \"boolean\", \"default\": true },\n \"priority\": { \"type\": \"integer\", \"minimum\": 0, \"maximum\": 1000, \"default\": 900 },\n \"affiliate\": {\n \"type\": \"object\",\n \"additionalProperties\": true\n },\n \"amazon\": {\n \"type\": \"object\",\n \"additionalProperties\": true\n },\n \"active\": { \"type\": \"boolean\" },\n \"notes\": { \"type\": \"string\" }\n }\n }\n }\n }\n}\n","inline_bytes":1468,"content_sha256":"3a19632daf6a429c71c6bacaf986b4aab632e7fffc308bf4662949f66a101425"},{"path":"scripts/amazon-getitems-to-catalog.mjs","size":4863,"sha":"7f47a93807061cd5bd5296a1c35b0505de91e3a9","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/amazon-getitems-to-catalog.mjs","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/amazon-getitems-to-catalog.mjs","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"#!/usr/bin/env node\nimport fs from \"node:fs\";\n\nfunction readJson(path) {\n return JSON.parse(fs.readFileSync(path, \"utf8\"));\n}\n\nfunction slugify(s) {\n return String(s || \"\")\n .toLowerCase()\n .replace(/&/g, \" and \")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 80);\n}\n\nfunction inferCategory(title, featuresText) {\n const t = `${title} ${featuresText}`.toLowerCase();\n if (t.includes(\"teething\") || t.includes(\"puppy\")) return \"teething\";\n if (t.includes(\"training\")) return \"training\";\n if (t.includes(\"fetch\") || t.includes(\"ball\") || t.includes(\"frisbee\")) return \"fetch\";\n if (t.includes(\"puzzle\") || t.includes(\"snuffle\")) return \"enrichment\";\n if (t.includes(\"slow feeder\") || t.includes(\"bowl\")) return \"feeding\";\n if (t.includes(\"leash\") || t.includes(\"harness\")) return \"walks\";\n if (t.includes(\"light\") || t.includes(\"collar\")) return \"safety\";\n return \"enrichment\";\n}\n\nfunction inferTags(title, featuresText) {\n const t = `${title} ${featuresText}`.toLowerCase();\n const tags = [];\n const checks = [\n [\"puppy\", \"puppy\"],\n [\"teething\", \"teething\"],\n [\"stuffable\", \"stuffable\"],\n [\"fetch\", \"fetch\"],\n [\"chew\", \"chew\"],\n [\"training\", \"training\"],\n [\"calm\", \"calming\"],\n [\"snuffle\", \"foraging\"],\n [\"puzzle\", \"puzzle\"],\n [\"slow feeder\", \"slow-feeding\"],\n [\"durable\", \"durable\"],\n [\"senior\", \"senior\"]\n ];\n for (const [needle, tag] of checks) {\n if (t.includes(needle) && !tags.includes(tag)) tags.push(tag);\n }\n return tags;\n}\n\nfunction inferSizes(title) {\n const t = title.toLowerCase();\n if (/\\bxs\\b|extra[- ]small|small puppies/.test(t)) return [\"toy\"];\n if (/\\bsmall\\b/.test(t)) return [\"small\"];\n if (/\\bmedium\\b|s\\/m/.test(t)) return [\"medium\"];\n if (/\\blarge\\b|l\\/xl/.test(t)) return [\"large\"];\n return [\"any\"];\n}\n\nfunction inferChew(title, featuresText) {\n const t = `${title} ${featuresText}`.toLowerCase();\n if (t.includes(\"soft puppy rubber\") || t.includes(\"gentle\")) return [\"gentle\", \"normal\"];\n if (t.includes(\"durable\") || t.includes(\"power\")) return [\"normal\", \"strong\"];\n return [\"normal\"];\n}\n\nfunction buildBenefit(title, features) {\n const first = Array.isArray(features) && features.length ? features[0] : \"\";\n const t = String(title || \"\");\n if (/puppy/i.test(t) && /teething/i.test(`${t} ${first}`)) {\n return \"Puppy-focused teething and enrichment option for supervised chewing and stuffed play.\";\n }\n if (/training/i.test(t)) {\n return \"Useful reward and handling aid for short, repeatable training sessions.\";\n }\n if (/fetch|ball|frisbee/i.test(t)) {\n return \"Good interactive play option for dogs that enjoy chase and retrieve work.\";\n }\n return \"Curated Barkday gift candidate imported from Amazon product data for manual review.\";\n}\n\nconst [,, inputPath, outputPath, optionsRaw] = process.argv;\n\nif (!inputPath || !outputPath) {\n console.error(\"Usage: node amazon-getitems-to-catalog.mjs [options-json]\");\n process.exit(1);\n}\n\nconst input = readJson(inputPath);\nconst opts = optionsRaw ? JSON.parse(optionsRaw) : {};\nconst defaultMarketplace = opts.marketplace || \"www.amazon.com\";\nconst defaultPartnerTag = opts.partnerTag || \"candidquality-20\";\nconst defaultAgeAxis = opts.ageAxis || \"human\";\nconst defaultMinAge = opts.minAge ?? 0;\nconst defaultMaxAge = opts.maxAge ?? 1;\nconst defaultPriority = opts.priority ?? 100;\nconst defaultSource = opts.source || \"curated\";\n\nconst items = (input.itemsResult?.items || []).map((item, idx) => {\n const title = item.itemInfo?.title?.displayValue || `Imported item ${idx + 1}`;\n const features = item.itemInfo?.features?.displayValues || [];\n const featureText = features.join(\" \");\n return {\n id: slugify(title),\n title,\n benefit: buildBenefit(title, features),\n category: inferCategory(title, featureText),\n tags: inferTags(title, featureText),\n ageAxis: defaultAgeAxis,\n ...(defaultAgeAxis === \"human\" ? { minAge: defaultMinAge, maxAge: defaultMaxAge } : {}),\n sizes: inferSizes(title),\n chew: inferChew(title, featureText),\n breedGroups: [],\n preferred: false,\n priority: defaultPriority,\n source: defaultSource,\n affiliate: {\n url: item.detailPageURL,\n asin: item.asin,\n marketplace: defaultMarketplace,\n partnerTag: defaultPartnerTag\n },\n active: true,\n notes: \"Draft import from Creators API GetItems. Review benefit, category, tags, age range, and sizes before publishing.\"\n };\n});\n\nconst out = {\n version: 2,\n generatedAt: new Date().toISOString(),\n marketplaceDefault: defaultMarketplace,\n notes: \"Draft Barkday catalog rows generated from Amazon Creators API GetItems response. Manual review required.\",\n items\n};\n\nfs.writeFileSync(outputPath, JSON.stringify(out, null, 2));\nconsole.log(`Wrote ${items.length} draft item(s) to ${outputPath}`);\n","inline_bytes":4863,"content_sha256":"f8aa305ca0d151540e4d5c9cde42ae79858375fe8175c779246b903cae4299c7"},{"path":"scripts/barkday-doctor.mjs","size":14944,"sha":"1e2e3a6469f80f9e08c81839e004af22b6be1aa1","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/barkday-doctor.mjs","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/barkday-doctor.mjs","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"#!/usr/bin/env node\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { execSync } from \"node:child_process\";\n\nconst repoRoot = process.cwd();\nconst errors = [];\nconst warnings = [];\nconst infos = [];\n\nfunction exists(p) {\n return fs.existsSync(path.join(repoRoot, p));\n}\n\nfunction readText(p) {\n return fs.readFileSync(path.join(repoRoot, p), \"utf8\");\n}\n\nfunction readJson(p) {\n return JSON.parse(readText(p));\n}\n\nfunction safeExec(cmd) {\n try {\n return execSync(cmd, { cwd: repoRoot, encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"pipe\"] }).trim();\n } catch (err) {\n return null;\n }\n}\n\nfunction walk(dir, out = []) {\n const abs = path.join(repoRoot, dir);\n if (!fs.existsSync(abs)) return out;\n for (const ent of fs.readdirSync(abs, { withFileTypes: true })) {\n const rel = path.posix.join(dir.replace(/\\\\/g, \"/\"), ent.name);\n if (ent.isDirectory()) walk(rel, out);\n else out.push(rel);\n }\n return out;\n}\n\nfunction addError(msg) {\n errors.push(msg);\n console.error(\"ERROR \" + msg);\n}\n\nfunction addWarn(msg) {\n warnings.push(msg);\n console.warn(\"WARN \" + msg);\n}\n\nfunction addInfo(msg) {\n infos.push(msg);\n console.log(\"INFO \" + msg);\n}\n\nfunction itemCount(value) {\n if (Array.isArray(value)) return value.length;\n if (value && typeof value === \"object\" && Array.isArray(value.items)) return value.items.length;\n return null;\n}\n\nfunction sourceItemsFrom(rel, value) {\n const items = Array.isArray(value) ? value : value?.items;\n if (!Array.isArray(items)) {\n addError(`Gift source file must contain an items array or top-level array: ${rel}`);\n return [];\n }\n return items;\n}\n\nconst canonicalGiftFeedPath = \"data/dog-gifts-merged.json\";\nconst canonicalPublishedGiftFeedUrl = \"https://candidquality.github.io/Barkday/data/dog-gifts-merged.json\";\nconst canonicalGiftWorkflowCommand = \".\\\\tools\\\\run-barkday-checks.ps1\";\nconst intendedGiftCatalogItemCount = 182;\nconst retiredGiftFeedToken = \"dog-birthday-feed\";\nconst runtimeCriticalFiles = [\n \"index.html\",\n \"app.js\",\n \"service-worker.js\",\n \"js/runtime-fetch.js\",\n \"manifest.json\",\n \"manifest.webmanifest\"\n];\nconst legacyGiftFiles = [\n \"dog-gifts.json\",\n \"dog-gifts.schema.json\"\n];\nconst v2GiftSourceFiles = [\n \"data/dog-gifts-base.json\",\n \"data/dog-gifts-preferred.json\"\n];\nconst generatedGiftFiles = [\n \"data/dog-gifts-catalog.json\",\n \"data/dog-gifts-merged.json\"\n];\nconst publishableBatchPattern = /^data\\/gift-batches\\/\\d{4}-\\d{2}-\\d{2}-batch-\\d+\\.json$/i;\nconst candidateBatchPattern = /^data\\/gift-batches\\/\\d{4}-\\d{2}-\\d{2}-batch-\\d+-[a-z0-9-]+\\.json$/i;\n\nconsole.log(\"Barkday doctor\");\nconsole.log(\"Repo \" + repoRoot);\nconsole.log(\"\");\naddInfo(`Canonical runtime gift feed path: ${canonicalGiftFeedPath}`);\naddInfo(`Canonical published gift feed URL: ${canonicalPublishedGiftFeedUrl}`);\naddInfo(`Canonical gift workflow helper: ${canonicalGiftWorkflowCommand}`);\n\nif (!exists(\".git\")) {\n addError(\"Current folder is not a git repository.\");\n} else {\n const branch = safeExec(\"git rev-parse --abbrev-ref HEAD\");\n const head = safeExec(\"git rev-parse --short HEAD\");\n addInfo(`Git branch=${branch || \"unknown\"} head=${head || \"unknown\"}`);\n\n const hasOrigin = safeExec(\"git remote get-url origin\");\n if (!hasOrigin) addWarn(\"No git remote named origin found.\");\n else addInfo(`Origin ${hasOrigin}`);\n\n const remoteMain = safeExec(\"git rev-parse --verify origin/main\");\n if (!remoteMain) {\n addWarn(\"origin/main is not available locally. Run git fetch origin for ahead/behind checks.\");\n } else {\n const counts = safeExec(\"git rev-list --left-right --count HEAD...origin/main\");\n if (counts) {\n const parts = counts.split(/\\s+/).map(Number);\n const ahead = Number.isFinite(parts[0]) ? parts[0] : 0;\n const behind = Number.isFinite(parts[1]) ? parts[1] : 0;\n if (behind > 0) addWarn(`Local branch is behind origin/main by ${behind} commit(s). Rebase before push.`);\n else addInfo(\"Local branch is not behind origin/main.\");\n if (ahead > 0) addInfo(`Local branch is ahead of origin/main by ${ahead} commit(s).`);\n }\n }\n}\n\nconst requiredAiOutputs = [\n \"docs/ai-index.min.json\",\n \"docs/ai-pack-core.txt\",\n \"docs/ai-pack-data-config.txt\",\n \"docs/ai-docs-list.min.json\",\n \"docs/ai-pack-everything.manifest.min.json\"\n];\n\nfor (const rel of requiredAiOutputs) {\n if (!exists(rel)) addError(`Missing required AI output: ${rel}`);\n}\nif (!errors.some(x => x.includes(\"Missing required AI output\"))) {\n addInfo(\"Required AI output files are present.\");\n}\n\nconst workflowDir = \".github/workflows\";\nif (exists(workflowDir)) {\n const files = walk(workflowDir).filter(f => /\\.(ya?ml)$/i.test(f));\n const byName = new Map();\n for (const rel of files) {\n const text = readText(rel);\n const m = text.match(/^\\s*name:\\s*(.+?)\\s*$/m);\n const displayName = m ? m[1].trim().replace(/^[\"']|[\"']$/g, \"\") : path.basename(rel);\n if (!byName.has(displayName)) byName.set(displayName, []);\n byName.get(displayName).push(rel);\n }\n let dupCount = 0;\n for (const [name, list] of byName.entries()) {\n if (list.length > 1) {\n dupCount += 1;\n addWarn(`Duplicate workflow display name \"${name}\" in: ${list.join(\", \")}`);\n }\n }\n if (!dupCount) addInfo(\"No duplicate workflow display names detected.\");\n} else {\n addWarn(\"No .github/workflows directory found.\");\n}\n\nconst trackedJsonFiles = [];\nconst trackedByGit = safeExec(\"git ls-files\");\nif (trackedByGit) {\n for (const rel of trackedByGit.split(/\\r?\\n/).filter(Boolean)) {\n if (/\\.json$/i.test(rel)) trackedJsonFiles.push(rel);\n }\n} else {\n trackedJsonFiles.push(...walk(\".\").filter(f => /\\.json$/i.test(f)));\n}\n\nlet badJson = 0;\nfor (const rel of trackedJsonFiles) {\n if (!exists(rel)) {\n const status = safeExec(`git status --short -- \"${rel}\"`);\n if (status && /^ ?D\\b/.test(status)) {\n addInfo(`Tracked JSON file is deleted in the working tree pending commit: ${rel}`);\n } else {\n addWarn(`Tracked JSON file is absent in the working tree: ${rel}`);\n }\n continue;\n }\n try {\n JSON.parse(readText(rel));\n } catch (err) {\n badJson += 1;\n addError(`Invalid JSON in ${rel}: ${err.message}`);\n }\n}\nif (!badJson) addInfo(`Parsed ${trackedJsonFiles.length} JSON file(s) successfully.`);\n\nconst appJs = exists(\"app.js\") ? readText(\"app.js\") : null;\nif (!appJs) {\n addWarn(\"app.js not found at repo root.\");\n} else {\n const localRefs = new Set();\n const dataRe = /[\"'`](data\\/[^\"'`]+?\\.(?:json|ya?ml|txt|md))[\"'`]/g;\n const localRootRe = /[\"'`]((?:[A-Za-z0-9._-]+\\/)?[A-Za-z0-9._-]+?\\.(?:json|ya?ml|txt|md))[\"'`]/g;\n\n for (const m of appJs.matchAll(dataRe)) localRefs.add(m[1]);\n\n for (const m of appJs.matchAll(localRootRe)) {\n const rel = m[1];\n if (/^https?:/i.test(rel)) continue;\n if (rel.startsWith(\"data/\")) continue;\n if (rel.startsWith(\"docs/\")) continue;\n if (rel.startsWith(\".github/\")) continue;\n if (/^(barkday-logo|logo|manifest|dog-gifts)\\b/i.test(path.basename(rel)) || rel === \"dog-gifts.json\" || rel === \"dog-gifts.schema.json\") {\n localRefs.add(rel);\n }\n }\n\n let missingRefs = 0;\n for (const rel of [...localRefs].sort()) {\n if (!exists(rel)) {\n missingRefs += 1;\n addError(`app.js references missing local file: ${rel}`);\n }\n }\n if (!missingRefs) addInfo(\"No missing local file references detected in app.js.\");\n}\n\nconst giftFeedUrlMatch = appJs ? appJs.match(/const\\s+GIFT_FEED_URL\\s*=\\s*[\"'`](https?:\\/\\/[^\"'`]+)[\"'`]/) : null;\nconst relativeGiftFeedUrlMatch = appJs ? appJs.match(/const\\s+GIFT_FEED_URL\\s*=\\s*[\"'`]([^\"'`]+)[\"'`]/) : null;\nif (relativeGiftFeedUrlMatch) {\n const configured = relativeGiftFeedUrlMatch[1];\n const configuredPath = configured.split(/[?#]/, 1)[0].replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n if (configuredPath !== canonicalGiftFeedPath) {\n addError(`app.js GIFT_FEED_URL points to ${configured}; expected ${canonicalGiftFeedPath}.`);\n } else {\n addInfo(`app.js uses canonical v2 gift feed: ${configured}`);\n }\n} else if (giftFeedUrlMatch) {\n addError(`app.js GIFT_FEED_URL points to remote URL ${giftFeedUrlMatch[1]}; expected ${canonicalGiftFeedPath}.`);\n} else if (appJs) {\n addError(\"app.js does not define GIFT_FEED_URL.\");\n}\n\nfor (const rel of runtimeCriticalFiles) {\n if (!exists(rel)) continue;\n const text = readText(rel);\n if (text.includes(retiredGiftFeedToken)) {\n addError(`Retired ${retiredGiftFeedToken} reference remains in runtime-critical file: ${rel}`);\n }\n}\n\nconst runtimeLegacyRefs = [];\nfor (const rel of runtimeCriticalFiles) {\n if (!exists(rel)) continue;\n const text = readText(rel);\n for (const legacy of legacyGiftFiles) {\n if (text.includes(legacy)) runtimeLegacyRefs.push(`${rel} -> ${legacy}`);\n }\n}\nif (runtimeLegacyRefs.length) {\n addWarn(`Runtime-critical files still reference legacy root gift files: ${runtimeLegacyRefs.join(\", \")}`);\n}\n\nconst presentLegacyFiles = legacyGiftFiles.filter(exists);\nconst missingLegacyFiles = legacyGiftFiles.filter(rel => !exists(rel));\nif (presentLegacyFiles.length) {\n const legacyCounts = presentLegacyFiles.map(rel => {\n try {\n const count = itemCount(readJson(rel));\n return count == null ? `${rel} (schema)` : `${rel} (${count} item(s))`;\n } catch {\n return rel;\n }\n });\n addInfo(`Deprecated legacy root gift artifacts present for compatibility only: ${legacyCounts.join(\", \")}`);\n addInfo(`Canonical runtime gift feed remains ${canonicalGiftFeedPath}; do not add new catalog work to root dog-gifts.json.`);\n}\nif (missingLegacyFiles.length) {\n addWarn(`Legacy root gift file(s) missing: ${missingLegacyFiles.join(\", \")}`);\n}\n\nconst allGiftBatchJsonFiles = walk(\"data/gift-batches\").filter(rel => /\\.json$/i.test(rel)).sort();\nconst candidateBatchFiles = allGiftBatchJsonFiles.filter(rel => candidateBatchPattern.test(rel));\nconst batchFiles = allGiftBatchJsonFiles.filter(rel => publishableBatchPattern.test(rel));\nlet suspiciousBatchCount = 0;\nlet batchItemCount = 0;\nconst sourceIds = new Set();\nconst sourceAsins = new Set();\nlet duplicateSourceKeys = 0;\nif (candidateBatchFiles.length) {\n addInfo(`Found ${candidateBatchFiles.length} curated candidate batch file(s) ignored by rebuild until promoted: ${candidateBatchFiles.join(\", \")}.`);\n}\nfor (const rel of batchFiles) {\n const abs = path.join(repoRoot, rel);\n const size = fs.statSync(abs).size;\n let value = null;\n try {\n value = readJson(rel);\n } catch (err) {\n suspiciousBatchCount += 1;\n addError(`Gift batch is invalid JSON: ${rel}: ${err.message}`);\n continue;\n }\n\n if (!Array.isArray(value)) {\n suspiciousBatchCount += 1;\n addWarn(`Gift batch is not a top-level array: ${rel}`);\n continue;\n }\n if (value.length === 0) {\n suspiciousBatchCount += 1;\n addWarn(`Gift batch is empty and should be removed or replaced intentionally: ${rel}`);\n continue;\n }\n\n const usableItems = value.filter(item => item && typeof item === \"object\" && !Array.isArray(item) && item.id);\n if (usableItems.length === 0 || size < 100) {\n suspiciousBatchCount += 1;\n addWarn(`Gift batch looks suspicious (${value.length} row(s), ${usableItems.length} with id, ${size} bytes): ${rel}`);\n }\n\n batchItemCount += value.length;\n for (const item of usableItems) {\n if (sourceIds.has(item.id)) {\n duplicateSourceKeys += 1;\n addError(`Duplicate gift source id in batch inputs: ${item.id}`);\n }\n sourceIds.add(item.id);\n\n const asin = item?.affiliate?.asin;\n if (asin) {\n if (sourceAsins.has(asin)) {\n duplicateSourceKeys += 1;\n addError(`Duplicate gift source ASIN in batch inputs: ${asin}`);\n }\n sourceAsins.add(asin);\n }\n }\n}\nif (batchFiles.length && suspiciousBatchCount === 0) {\n addInfo(`Checked ${batchFiles.length} gift batch file(s); none look empty or suspicious.`);\n} else if (!batchFiles.length) {\n addInfo(\"No gift batch files found.\");\n}\n\nconst baseSource = exists(\"data/dog-gifts-base.json\") ? readJson(\"data/dog-gifts-base.json\") : null;\nif (!baseSource) {\n addError(\"Missing v2 gift source: data/dog-gifts-base.json\");\n} else {\n const baseItems = sourceItemsFrom(\"data/dog-gifts-base.json\", baseSource);\n for (const item of baseItems.filter(item => item && typeof item === \"object\" && !Array.isArray(item) && item.id)) {\n if (sourceIds.has(item.id)) {\n duplicateSourceKeys += 1;\n addError(`Duplicate gift source id between base and batch inputs: ${item.id}`);\n }\n sourceIds.add(item.id);\n\n const asin = item?.affiliate?.asin;\n if (asin) {\n if (sourceAsins.has(asin)) {\n duplicateSourceKeys += 1;\n addError(`Duplicate gift source ASIN between base and batch inputs: ${asin}`);\n }\n sourceAsins.add(asin);\n }\n }\n\n const rebuildableSourceCount = baseItems.length + batchItemCount;\n if (rebuildableSourceCount !== intendedGiftCatalogItemCount) {\n addError(`Rebuildable v2 gift source has ${rebuildableSourceCount} item(s); expected ${intendedGiftCatalogItemCount}.`);\n } else {\n addInfo(`Rebuildable v2 gift source count is ${rebuildableSourceCount} item(s): ${baseItems.length} base + ${batchItemCount} batch.`);\n }\n}\n\nif (!duplicateSourceKeys) addInfo(\"No duplicate gift ids or ASINs detected in rebuildable source inputs.\");\n\nfor (const rel of v2GiftSourceFiles) {\n if (!exists(rel)) addError(`Missing v2 gift source file: ${rel}`);\n}\n\nconst generatedCounts = new Map();\nfor (const rel of generatedGiftFiles) {\n if (!exists(rel)) {\n addError(`Missing generated v2 gift file: ${rel}`);\n continue;\n }\n const count = itemCount(readJson(rel));\n generatedCounts.set(rel, count);\n if (count !== intendedGiftCatalogItemCount) {\n addError(`${rel} has ${count ?? \"unknown\"} item(s); expected ${intendedGiftCatalogItemCount}. Rebuild from source.`);\n }\n}\n\nif (\n generatedCounts.get(\"data/dog-gifts-catalog.json\") === intendedGiftCatalogItemCount &&\n generatedCounts.get(\"data/dog-gifts-merged.json\") === intendedGiftCatalogItemCount\n) {\n addInfo(`Generated v2 gift files match intended launch catalog size: ${intendedGiftCatalogItemCount} item(s).`);\n}\n\nconst aiScript = exists(\"scripts/build_ai_index.mjs\") ? readText(\"scripts/build_ai_index.mjs\") : null;\nif (!aiScript) {\n addWarn(\"scripts/build_ai_index.mjs not found.\");\n} else {\n const expectedOutputs = [\n \"ai-index.min.json\",\n \"ai-pack-core.txt\",\n \"ai-pack-data-config.txt\",\n \"ai-docs-list.min.json\",\n \"ai-pack-everything.manifest.min.json\"\n ];\n const missingMentions = expectedOutputs.filter(name => !aiScript.includes(name));\n if (missingMentions.length) {\n addWarn(`AI build script does not explicitly mention: ${missingMentions.join(\", \")}`);\n } else {\n addInfo(\"AI build script includes all expected pack/index output names.\");\n }\n}\n\nconsole.log(\"\");\nconsole.log(`Summary: ${errors.length} error(s), ${warnings.length} warning(s), ${infos.length} info message(s).`);\nif (errors.length) process.exit(1);\n","inline_bytes":14944,"content_sha256":"f3ad6db63c4d59079c876483b5a678a624e66b7875c42869234999d6332b0813"},{"path":"scripts/build-auto-batch-from-getitems.mjs","size":6865,"sha":"636fe892d028b15df1dfb75926819b8dfe3a6246","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/build-auto-batch-from-getitems.mjs","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/build-auto-batch-from-getitems.mjs","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"#!/usr/bin/env node\nimport fs from \"fs\";\nimport path from \"path\";\n\nconst outputPath = process.argv[2] || \"./data/gift-batches/2026-04-21-batch-07.json\";\nconst maxItems = Number(process.argv[3] || 120);\n\nfunction readJson(filePath) {\n return JSON.parse(fs.readFileSync(filePath, \"utf8\"));\n}\n\nfunction writeJson(filePath, value) {\n fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + \"\\n\", \"utf8\");\n}\n\nfunction slugify(text) {\n return String(text || \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 50);\n}\n\nfunction inferCategory(text) {\n const t = text.toLowerCase();\n\n if (/airtag|tracking/.test(t)) return \"safety\";\n if (/light up|led|visibility|reflective.*light|dog collar light|lighthound/.test(t)) return \"safety\";\n if (/harness|leash|walk/.test(t)) return \"walks\";\n if (/water bottle|travel bowl|collapsible bowl|portable.*bowl|portable.*water/.test(t)) return \"outdoors\";\n if (/cooling mat|cool pet pad|chillz/.test(t)) return \"comfort\";\n if (/lick mat|licking mat|lick pad|grooming distraction|bath lick/.test(t)) return \"calming\";\n if (/slow feeder insert|insert bowl|slow feeder bowl/.test(t)) return \"feeding\";\n if (/snuffle|foraging/.test(t)) return \"enrichment\";\n if (/tug/.test(t)) return \"tug\";\n if (/fetch stick|bumper|flyer|jive ball|ball dog toy|throwing stick|float/.test(t)) return \"fetch\";\n if (/treat dispensing|puzzle|stuff-a-ball|treat tumble|reward ball|qwizl/.test(t)) return \"enrichment\";\n if (/chew|goughnuts|hurley|stuff-a-ball/.test(t)) return \"chew\";\n\n return \"enrichment\";\n}\n\nfunction inferSizes(text, category) {\n const t = text.toLowerCase();\n const out = [];\n\n if (/x-small|xs|extra small|toy/.test(t)) out.push(\"toy\");\n if (/small/.test(t)) out.push(\"small\");\n if (/medium/.test(t)) out.push(\"medium\");\n if (/large|xl|x-large|extra large/.test(t)) out.push(\"large\");\n if (/giant|xxl/.test(t)) out.push(\"giant\");\n\n if (out.length === 0) {\n if ([\"safety\", \"walks\", \"outdoors\", \"feeding\"].includes(category)) return [\"any\"];\n return [\"medium\"];\n }\n\n return [...new Set(out)];\n}\n\nfunction inferChew(text, category) {\n const t = text.toLowerCase();\n\n if ([\"safety\", \"walks\", \"outdoors\", \"feeding\", \"comfort\"].includes(category)) return [\"any\"];\n if (/aggressive|heavy duty|tough|durable|strong chewer/.test(t)) return [\"normal\", \"strong\"];\n if (/puppy|lick mat|calming/.test(t)) return [\"gentle\", \"normal\"];\n return [\"normal\"];\n}\n\nfunction inferAge(text, category) {\n const t = text.toLowerCase();\n\n if ([\"safety\", \"walks\", \"outdoors\", \"feeding\"].includes(category)) {\n return { ageAxis: \"none\" };\n }\n\n if (/puppy/.test(t)) {\n return { ageAxis: \"human\", minAge: 0, maxAge: 0.8 };\n }\n\n if (/senior/.test(t)) {\n return { ageAxis: \"human\", minAge: 7, maxAge: 12 };\n }\n\n if (category === \"calming\") {\n return { ageAxis: \"human\", minAge: 0.3, maxAge: 12 };\n }\n\n return { ageAxis: \"human\", minAge: 0.5, maxAge: 10 };\n}\n\nfunction inferTags(text, category) {\n const t = text.toLowerCase();\n const tags = new Set();\n\n if (/lick mat|licking mat|lick pad/.test(t)) tags.add(\"lick-mat\");\n if (/suction/.test(t)) tags.add(\"suction-cups\");\n if (/bath|groom/.test(t)) {\n tags.add(\"bath\");\n tags.add(\"grooming\");\n }\n if (/anxiety|calm/.test(t)) tags.add(\"anxiety-relief\");\n\n if (/water bottle/.test(t)) {\n tags.add(\"water-bottle\");\n tags.add(\"hydration\");\n }\n if (/travel|portable/.test(t)) tags.add(\"travel\");\n if (/collapsible/.test(t)) tags.add(\"collapsible\");\n if (/bowl/.test(t)) tags.add(\"bowl\");\n if (/carabiner/.test(t)) tags.add(\"carabiner\");\n\n if (/cooling/.test(t)) tags.add(\"cooling\");\n if (/mat/.test(t)) tags.add(\"mat\");\n\n if (/led|light/.test(t)) tags.add(\"led\");\n if (/reflective/.test(t)) tags.add(\"reflective\");\n if (/visibility/.test(t)) tags.add(\"visibility\");\n if (/waterproof/.test(t)) tags.add(\"waterproof\");\n\n if (/slow feeder/.test(t)) tags.add(\"slow-feeding\");\n if (/treat dispensing|treat dispenser/.test(t)) tags.add(\"treat-dispensing\");\n if (/puzzle/.test(t)) tags.add(\"puzzle\");\n if (/snuffle|foraging/.test(t)) tags.add(\"foraging\");\n if (/stuffable/.test(t)) tags.add(\"stuffable\");\n\n if (/fetch/.test(t)) tags.add(\"fetch\");\n if (/ball/.test(t)) tags.add(\"ball\");\n if (/stick|bumper|flyer/.test(t)) tags.add(\"stick\");\n if (/float/.test(t)) tags.add(\"floatable\");\n if (/tug/.test(t)) tags.add(\"tug\");\n\n if (/chew/.test(t)) tags.add(\"chew\");\n if (/durable|tough/.test(t)) tags.add(\"durable\");\n\n if (tags.size === 0) tags.add(category);\n return [...tags];\n}\n\nfunction inferPriority(category) {\n const map = {\n chew: 170,\n enrichment: 160,\n calming: 160,\n fetch: 158,\n comfort: 156,\n feeding: 155,\n outdoors: 152,\n safety: 150,\n walks: 148,\n tug: 154\n };\n return map[category] || 140;\n}\n\nfunction mapItem(item) {\n const asin = item.asin;\n const title = item?.itemInfo?.title?.displayValue || `Amazon Item ${asin}`;\n const features = item?.itemInfo?.features?.displayValues || [];\n const featureText = features.join(\" \");\n const fullText = `${title} ${featureText}`;\n const category = inferCategory(fullText);\n const sizes = inferSizes(fullText, category);\n const chew = inferChew(fullText, category);\n const age = inferAge(fullText, category);\n const tags = inferTags(fullText, category);\n\n return {\n id: `${slugify(title)}-${asin.toLowerCase()}`,\n title,\n benefit: `Auto-generated starter entry for ${title}. Review wording later.`,\n category,\n tags,\n ...age,\n sizes,\n chew,\n breedGroups: [],\n preferred: false,\n priority: inferPriority(category),\n source: \"curated\",\n affiliate: {\n url: item.detailPageURL,\n asin,\n marketplace: \"www.amazon.com\",\n partnerTag: \"candidquality-20\"\n },\n active: true,\n notes: \"Auto-generated starter entry from bulk GetItems run. Review later.\"\n };\n}\n\nconst repoRoot = process.cwd();\nconst rawDir = path.join(repoRoot, \"data\", \"raw-amazon\");\nconst catalogPath = path.join(repoRoot, \"data\", \"dog-gifts-catalog.json\");\n\nconst catalog = readJson(catalogPath);\nconst existingAsins = new Set(\n (catalog.items || [])\n .map(it => it?.affiliate?.asin)\n .filter(Boolean)\n);\n\nconst bulkFiles = fs.readdirSync(rawDir)\n .filter(name => /^bulk-getitems-\\d+\\.json$/i.test(name))\n .sort();\n\nconst out = [];\nconst seen = new Set(existingAsins);\n\nfor (const file of bulkFiles) {\n const json = readJson(path.join(rawDir, file));\n const items = json?.itemsResult?.items || [];\n\n for (const item of items) {\n const asin = item?.asin;\n if (!asin) continue;\n if (seen.has(asin)) continue;\n\n seen.add(asin);\n out.push(mapItem(item));\n\n if (out.length >= maxItems) break;\n }\n\n if (out.length >= maxItems) break;\n}\n\nwriteJson(outputPath, out);\nconsole.log(`Wrote ${out.length} starter items to ${outputPath}`);","inline_bytes":6865,"content_sha256":"56973d22470cbe4a47e26811affa71afb4696d935da68262fd48b56b5690bfcc"},{"path":"scripts/build_ai_index.mjs","size":20741,"sha":"f34fbc20be6a5274021674e0c4e06164e149f43f","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/build_ai_index.mjs","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/build_ai_index.mjs","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"// scripts/build_ai_index.mjs\r\n// Builds repo-wide indices (ai-index.*), browsable lists, targeted inline packs,\r\n// sharded \"everything\" packs, and a combined \"all\" pack with HTML/TXT mirrors.\r\n// Safer defaults for large data, plus JSON shape hints for very large files.\r\n\r\nimport { execSync } from \"node:child_process\";\r\nimport fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport crypto from \"node:crypto\";\r\n\r\n// ---------------- git + repo meta ----------------\r\nfunction safeExec(cmd, def = \"\") {\r\n try { return execSync(cmd, { encoding: \"utf8\", stdio: [\"ignore\",\"pipe\",\"ignore\"] }).trim(); }\r\n catch { return def; }\r\n}\r\n\r\nconst repo = process.env.GITHUB_REPOSITORY\r\n || safeExec(\"git config --get remote.origin.url\")\r\n .replace(/^.*github\\.com[:/]/, \"\").replace(/\\.git$/, \"\");\r\nconst commit = process.env.GITHUB_SHA || safeExec(\"git rev-parse HEAD\");\r\nconst branch = process.env.GITHUB_REF_NAME || safeExec(\"git rev-parse --abbrev-ref HEAD\") || \"main\";\r\nconst updatedUtc = new Date().toISOString();\r\n\r\nif (!repo) {\r\n console.warn(\"[build_ai_index] Could not determine repo; continuing with minimal metadata.\");\r\n}\r\n\r\n// ---------------- helpers ----------------\r\nfunction enc(p){ return p.split(\"/\").map(encodeURIComponent).join(\"/\"); }\r\nfunction mediaTypeFor(p){\r\n const ext = p.toLowerCase().split(\".\").pop();\r\n const map = {\r\n json:\"application/json\", schema:\"application/json\",\r\n js:\"application/javascript\", mjs:\"application/javascript\",\r\n css:\"text/css\", html:\"text/html\", md:\"text/markdown\", mdx:\"text/markdown\", txt:\"text/plain\",\r\n svg:\"image/svg+xml\", png:\"image/png\", jpg:\"image/jpeg\", jpeg:\"image/jpeg\", webp:\"image/webp\", ico:\"image/x-icon\",\r\n pdf:\"application/pdf\", xml:\"application/xml\", yml:\"text/yaml\", yaml:\"text/yaml\"\r\n };\r\n return map[ext] || \"application/octet-stream\";\r\n}\r\nfunction sha256(buf){ return crypto.createHash(\"sha256\").update(buf).digest(\"hex\"); }\r\nfunction ensureDocs(){ fs.mkdirSync(\"docs\", { recursive: true }); }\r\n\r\n// ---------------- gather all tracked files at this commit ----------------\r\nfunction filesFromGitTree(gitCommit) {\r\n const raw = safeExec(`git ls-tree -r --long ${gitCommit}`);\r\n const lines = raw.split(\"\\n\").filter(Boolean);\r\n const out = [];\r\n for (const line of lines) {\r\n const m = line.match(/^\\d+\\s+\\w+\\s+([0-9a-f]{40})\\s+(\\d+)\\t(.+)$/);\r\n if (!m) continue;\r\n const [, blobSha, sizeStr, filePath] = m;\r\n if (filePath.startsWith(\".git/\")) continue;\r\n const raw_url = `https://raw.githubusercontent.com/${repo}/${commit}/${enc(filePath)}`;\r\n const html_url = `https://github.com/${repo}/blob/${commit}/${enc(filePath)}`;\r\n out.push({ path:filePath, size:Number(sizeStr), git_blob_sha:blobSha, media_type:mediaTypeFor(filePath), raw_url, html_url });\r\n }\r\n return out;\r\n}\r\n// Fallback (rare): walk working dir if git tree fails\r\nfunction walk(dir){\r\n const ents = fs.readdirSync(dir, { withFileTypes:true });\r\n const list = [];\r\n for (const e of ents){\r\n const p = path.join(dir, e.name);\r\n if (p.startsWith(\".git\")) continue;\r\n if (e.isDirectory()) list.push(...walk(p));\r\n else {\r\n const stat = fs.statSync(p);\r\n list.push({\r\n path: p.replace(/^[.][/\\\\]*/,\"\"),\r\n size: stat.size,\r\n git_blob_sha: \"\", // unknown outside git\r\n media_type: mediaTypeFor(p),\r\n raw_url: `https://raw.githubusercontent.com/${repo}/${commit}/${enc(p)}`,\r\n html_url:`https://github.com/${repo}/blob/${commit}/${enc(p)}`\r\n });\r\n }\r\n }\r\n return list;\r\n}\r\n\r\nlet files = filesFromGitTree(commit);\r\nif (!files.length) {\r\n console.warn(\"[build_ai_index] git ls-tree returned no files; falling back to FS walk.\");\r\n files = walk(\".\");\r\n}\r\n\r\n// ---------------- master index ----------------\r\nensureDocs();\r\nconst index = {\r\n schema: \"barkday.ai-index.v1\",\r\n repo, default_branch: branch, commit, updated_utc: updatedUtc,\r\n files_count: files.length,\r\n total_bytes: files.reduce((a,f)=>a+f.size, 0),\r\n files\r\n};\r\nfs.writeFileSync(\"docs/ai-index.json\", JSON.stringify(index, null, 2));\r\nfs.writeFileSync(\"docs/ai-index.min.json\", JSON.stringify(index));\r\nconsole.log(`Wrote docs/ai-index.(json|min.json) with ${files.length} entries`);\r\n\r\n// ---------------- simple list writer (json + min.json + html) ----------------\r\nfunction writeList({title, outBase, predicate}) {\r\n const subset = files.filter(predicate);\r\n const list = {\r\n schema: `barkday.${outBase}.v1`,\r\n repo, commit, updated_utc: updatedUtc,\r\n count: subset.length,\r\n files: subset.map(({path: p, size, git_blob_sha, raw_url, html_url}) => ({\r\n path: p, size, sha: git_blob_sha, raw_url, html_url\r\n }))\r\n };\r\n fs.writeFileSync(`docs/${outBase}.json`, JSON.stringify(list, null, 2));\r\n fs.writeFileSync(`docs/${outBase}.min.json`, JSON.stringify(list));\r\n\r\n const esc = s => String(s).replace(/&/g,\"&\").replace(//g,\">\");\r\n const rows = subset.map(f =>\r\n `${esc(f.path)}${f.size}rawview`\r\n ).join(\"\\n\") || `No matching files.`;\r\n\r\n const html = `Barkday • ${esc(title)}\r\n\r\n

${esc(title)} (${subset.length})

\r\n

Commit ${commit.slice(0,7)} • ${updatedUtc}

\r\n\r\n${rows}\r\n
PathSizeRawHTML
`;\r\n fs.writeFileSync(`docs/${outBase}.html`, html);\r\n\r\n console.log(`Wrote docs/${outBase}.(html|json|min.json) with ${subset.length} entries`);\r\n}\r\n\r\nwriteList({\r\n title: \"docs/*.md Markdown files\",\r\n outBase: \"ai-docs-list\",\r\n predicate: f => f.path.startsWith(\"docs/\") && /\\.mdx?$/i.test(f.path)\r\n});\r\nwriteList({\r\n title: \"data/*.md Markdown files\",\r\n outBase: \"ai-data-list\",\r\n predicate: f => f.path.startsWith(\"data/\") && /\\.mdx?$/i.test(f.path)\r\n});\r\nwriteList({\r\n title: \"data/*.json, *.yaml, *.yml files\",\r\n outBase: \"ai-data-config-list\",\r\n predicate: f => f.path.toLowerCase().startsWith(\"data/\") && /\\.(json|ya?ml)$/i.test(f.path)\r\n});\r\n\r\n// ---------------- inline limits + policy ----------------\r\nconst TEXT_EXT = new Set([\"md\",\"mdx\",\"json\",\"js\",\"mjs\",\"css\",\"html\",\"yml\",\"yaml\",\"txt\",\"svg\"]);\r\nconst INLINE_TEXT_BYTES = 600 * 1024; // inline full text <= 600 KB\r\nconst INLINE_BIN_BYTES = 200 * 1024; // inline full binary <= 200 KB (base64)\r\nconst PREVIEW_TEXT_BYTES = 64 * 1024; // if too large for full, include this much preview\r\n\r\n// Always inline full for docs/*.md, but NOT every data file by default (keeps packs lean).\r\nconst ALWAYS_TEXT_FULL_DIRS = [ /^docs\\//i ];\r\nconst ALWAYS_TEXT_FULL_PATHS = new Set([\r\n // explicitly required data/config for automation\r\n \"dog-gifts.json\",\r\n \"dog-gifts.schema.json\"\r\n]);\r\nfunction alwaysFullText(p){\r\n if (ALWAYS_TEXT_FULL_PATHS.has(p)) return true;\r\n return ALWAYS_TEXT_FULL_DIRS.some(rx => rx.test(p));\r\n}\r\n\r\n// low-level git blob read\r\nfunction execSyncBuffer(cmd){ return execSync(cmd, { encoding: \"buffer\", stdio: [\"ignore\",\"pipe\",\"inherit\"]}); }\r\nfunction gitShow(p){\r\n try { return execSyncBuffer(`git show ${commit}:${p}`); }\r\n catch { return fs.readFileSync(p); }\r\n}\r\n\r\n// ---------------- optional JSON shape hints for large files ----------------\r\nfunction jsonShapeHint(buf){\r\n try {\r\n const text = buf.toString(\"utf8\");\r\n const data = JSON.parse(text);\r\n const hint = { type: Array.isArray(data) ? \"array\" : (data && typeof data === \"object\" ? \"object\" : typeof data) };\r\n if (Array.isArray(data)) {\r\n hint.length = data.length;\r\n hint.sample = data.slice(0, Math.min(3, data.length));\r\n } else if (data && typeof data === \"object\") {\r\n hint.keys = Object.keys(data).slice(0, 12);\r\n }\r\n return hint;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n// ---------------- generic inline pack writer ----------------\r\nconst PACK_CATALOG = []; // collect emitted packs for a small catalog at the end\r\n\r\nfunction writePack({title, outBase, predicate}){\r\n const subset = files.filter(predicate);\r\n const items = [];\r\n for (const f of subset){\r\n const ext = (f.path.split(\".\").pop()||\"\").toLowerCase();\r\n const isText = TEXT_EXT.has(ext);\r\n const mustFull = isText && alwaysFullText(f.path);\r\n\r\n let inline_state = \"none\"; // \"full\" | \"preview\" | \"none\"\r\n let encoding, content, content_sha, meta;\r\n\r\n try {\r\n const buf = gitShow(f.path);\r\n if (isText) {\r\n if (mustFull || f.size <= INLINE_TEXT_BYTES) {\r\n inline_state = \"full\"; encoding = \"utf8\"; content = buf.toString(\"utf8\");\r\n content_sha = sha256(buf);\r\n } else if (PREVIEW_TEXT_BYTES > 0) {\r\n inline_state = \"preview\"; encoding = \"utf8\"; content = buf.slice(0, PREVIEW_TEXT_BYTES).toString(\"utf8\");\r\n content_sha = sha256(buf); // hash of full file (even if preview)\r\n if (ext === \"json\") meta = { json_hint: jsonShapeHint(buf) };\r\n }\r\n } else if (f.size <= INLINE_BIN_BYTES) {\r\n inline_state = \"full\"; encoding = \"base64\"; content = buf.toString(\"base64\");\r\n content_sha = sha256(buf);\r\n }\r\n } catch { /* metadata only */ }\r\n\r\n const item = {\r\n path: f.path,\r\n size: f.size,\r\n sha: f.git_blob_sha,\r\n media_type: f.media_type,\r\n raw_url: f.raw_url,\r\n html_url: f.html_url,\r\n inline_state,\r\n max_inline_text_bytes: INLINE_TEXT_BYTES,\r\n max_inline_bin_bytes: INLINE_BIN_BYTES,\r\n preview_text_bytes: PREVIEW_TEXT_BYTES\r\n };\r\n if (inline_state !== \"none\"){\r\n item.encoding = encoding;\r\n item.content = content;\r\n item.inline_bytes = typeof content === \"string\" ? content.length : 0;\r\n item.content_sha256 = content_sha;\r\n if (meta) Object.assign(item, meta);\r\n }\r\n items.push(item);\r\n }\r\n\r\n const pack = { schema: `barkday.${outBase}.v1`, repo, commit, updated_utc: updatedUtc, count: items.length, items };\r\n const pretty = JSON.stringify(pack, null, 2);\r\n const min = JSON.stringify(pack);\r\n\r\n fs.writeFileSync(`docs/${outBase}.json`, pretty);\r\n fs.writeFileSync(`docs/${outBase}.min.json`, min);\r\n fs.writeFileSync(`docs/${outBase}.txt`, min); // TXT mirror for JSON-hostile clients\r\n console.log(`Wrote docs/${outBase}.(json|min.json|txt) with ${items.length} items`);\r\n\r\n PACK_CATALOG.push({ name: outBase, count: items.length, bytes_min: min.length, files: [\r\n `docs/${outBase}.json`, `docs/${outBase}.min.json`, `docs/${outBase}.txt`\r\n ]});\r\n}\r\n\r\n// ---------------- targeted packs ----------------\r\nconst CORE_SET = new Set([\r\n \"index.html\",\r\n \"app.js\",\r\n \"app-pdf.js\",\r\n \"app-curves-inline.js\",\r\n \"app-celebrate.js\",\r\n \"service-worker.js\",\r\n \"js/runtime-fetch.js\",\r\n \"dog-gifts.json\",\r\n \"dog-gifts.schema.json\"\r\n]);\r\n\r\nwritePack({\r\n title: \"docs/*.md (inline)\",\r\n outBase: \"ai-pack-docs\",\r\n predicate: f => f.path.startsWith(\"docs/\") && /\\.mdx?$/i.test(f.path)\r\n});\r\nwritePack({\r\n title: \"data/*.json|*.yaml (inline selectively)\",\r\n outBase: \"ai-pack-data-config\",\r\n predicate: f => f.path.toLowerCase().startsWith(\"data/\") && /\\.(json|ya?ml)$/i.test(f.path)\r\n});\r\nwritePack({\r\n title: \"core app/source files (inline)\",\r\n outBase: \"ai-pack-core\",\r\n predicate: f => CORE_SET.has(f.path)\r\n});\r\nwritePack({\r\n title: \".github/workflows/*.yml (inline)\",\r\n outBase: \"ai-pack-ci\",\r\n predicate: f => f.path.startsWith(\".github/workflows/\") && /\\.ya?ml$/i.test(f.path)\r\n});\r\n\r\n// ---------------- SHARDED \"EVERYTHING\" PACK ----------------\r\nconst SHARD_TARGET_BYTES = 4 * 1024 * 1024; // ~4 MB minified JSON per shard\r\nconst SHARD_MAX_ITEMS = 500;\r\n\r\nfunction isTextPath(p){\r\n const ext = (p.split('.').pop()||'').toLowerCase();\r\n return TEXT_EXT.has(ext) || /^text\\//.test(mediaTypeFor(p));\r\n}\r\n\r\nfunction writeEverythingSharded(){\r\n // exclude generated outputs and git internals\r\n const subset = files.filter(f =>\r\n !f.path.startsWith('docs/ai-') &&\r\n !f.path.startsWith('.git/')\r\n );\r\n\r\n let items = [], bytes = 0, shardIdx = 1;\r\n const shards = [];\r\n\r\n function flush(){\r\n if (!items.length) return;\r\n const name = `ai-pack-everything-${String(shardIdx).padStart(4,'0')}`;\r\n const pack = {\r\n schema: \"barkday.ai-pack-everything.v1\",\r\n repo, commit, updated_utc: updatedUtc,\r\n count: items.length,\r\n items\r\n };\r\n const pretty = JSON.stringify(pack, null, 2);\r\n const min = JSON.stringify(pack);\r\n fs.writeFileSync(`docs/${name}.json`, pretty);\r\n fs.writeFileSync(`docs/${name}.min.json`, min);\r\n fs.writeFileSync(`docs/${name}.txt`, min);\r\n shards.push({ name, count: items.length, approx_bytes: min.length });\r\n shardIdx++; items = []; bytes = 0;\r\n console.log(`Wrote docs/${name}.(json|min.json|txt) items=${pack.count}`);\r\n }\r\n\r\n for (const f of subset){\r\n let inline_state = \"none\", encoding, content, content_sha, meta;\r\n\r\n try {\r\n const buf = gitShow(f.path);\r\n if (isTextPath(f.path)) {\r\n if (alwaysFullText(f.path) || f.size <= INLINE_TEXT_BYTES) {\r\n inline_state = \"full\"; encoding = \"utf8\"; content = buf.toString(\"utf8\");\r\n content_sha = sha256(buf); bytes += content.length;\r\n } else if (PREVIEW_TEXT_BYTES > 0) {\r\n inline_state = \"preview\"; encoding = \"utf8\"; content = buf.slice(0, PREVIEW_TEXT_BYTES).toString(\"utf8\");\r\n content_sha = sha256(buf); bytes += content.length;\r\n if (/\\.(json)$/i.test(f.path)) meta = { json_hint: jsonShapeHint(buf) };\r\n }\r\n } else if (f.size <= INLINE_BIN_BYTES) {\r\n inline_state = \"full\"; encoding = \"base64\"; content = buf.toString(\"base64\");\r\n content_sha = sha256(buf); bytes += content.length;\r\n }\r\n } catch { /* metadata only */ }\r\n\r\n const item = {\r\n path: f.path,\r\n size: f.size,\r\n sha: f.git_blob_sha,\r\n media_type: f.media_type,\r\n raw_url: f.raw_url,\r\n html_url: f.html_url,\r\n inline_state,\r\n max_inline_text_bytes: INLINE_TEXT_BYTES,\r\n max_inline_bin_bytes: INLINE_BIN_BYTES,\r\n preview_text_bytes: PREVIEW_TEXT_BYTES\r\n };\r\n if (inline_state !== \"none\"){\r\n item.encoding = encoding;\r\n item.content = content;\r\n item.inline_bytes = typeof content === \"string\" ? content.length : 0;\r\n item.content_sha256 = content_sha;\r\n if (meta) Object.assign(item, meta);\r\n }\r\n\r\n items.push(item);\r\n if (bytes >= SHARD_TARGET_BYTES || items.length >= SHARD_MAX_ITEMS) flush();\r\n }\r\n flush();\r\n\r\n // Manifest + HTML index\r\n const manifest = {\r\n schema: \"barkday.ai-pack-everything.manifest.v1\",\r\n repo, commit, updated_utc: updatedUtc,\r\n shards: shards.map(s => ({\r\n name: s.name,\r\n count: s.count,\r\n approx_bytes: s.approx_bytes,\r\n url_json: `docs/${s.name}.min.json`,\r\n url_txt: `docs/${s.name}.txt`\r\n }))\r\n };\r\n fs.writeFileSync(\"docs/ai-pack-everything.manifest.json\", JSON.stringify(manifest, null, 2));\r\n fs.writeFileSync(\"docs/ai-pack-everything.manifest.min.json\", JSON.stringify(manifest));\r\n\r\n const rows = shards.map(s =>\r\n `${s.name}${s.count}${s.approx_bytes}txt · json`\r\n ).join(\"\\n\") || `No shards emitted.`;\r\n\r\n const html = `\r\n Barkday • ai-pack-everything\r\n \r\n

ai-pack-everything

\r\n

Commit ${commit.slice(0,7)} • ${updatedUtc}

\r\n \r\n ${rows}\r\n
ShardItems~BytesLinks
`;\r\n fs.writeFileSync(\"docs/ai-pack-everything.html\", html);\r\n\r\n console.log(`Wrote docs/ai-pack-everything.(manifest.json|min.json|html) with ${shards.length} shard(s)`);\r\n\r\n PACK_CATALOG.push({ name: \"ai-pack-everything (sharded)\", count: shards.reduce((a,s)=>a+s.count,0), bytes_min: shards.reduce((a,s)=>a+s.approx_bytes,0), files: [\r\n \"docs/ai-pack-everything.manifest.min.json\", \"docs/ai-pack-everything.html\"\r\n ]});\r\n}\r\nwriteEverythingSharded();\r\n\r\n// ---------------- Combined \"ALL\" pack (docs + data-config + core + ci) ----------------\r\n(function(){\r\n const names = [\"ai-pack-docs\",\"ai-pack-data-config\",\"ai-pack-core\",\"ai-pack-ci\"];\r\n const packs = names.map(name => {\r\n const p = JSON.parse(fs.readFileSync(`docs/${name}.min.json`, \"utf8\"));\r\n return { name, items: p.items || [] };\r\n });\r\n const combined = {\r\n schema: \"barkday.ai-pack-all.v1\",\r\n repo, commit, updated_utc: updatedUtc,\r\n sections: Object.fromEntries(packs.map(p => [p.name, { count: p.items.length, items: p.items }]))\r\n };\r\n const prettyPack = JSON.stringify(combined, null, 2);\r\n const minPack = JSON.stringify(combined);\r\n\r\n fs.writeFileSync(\"docs/ai-pack-all.json\", prettyPack);\r\n fs.writeFileSync(\"docs/ai-pack-all.min.json\", minPack);\r\n fs.writeFileSync(\"docs/ai-pack-all.txt\", minPack);\r\n console.log(`Wrote docs/ai-pack-all.(json|min.json|txt)`);\r\n\r\n const escapeHtml = s => String(s).replace(/[&<>]/g, c => ({'&':'&','<':'<','>':'>'}[c]));\r\n const packHtml = `\r\nBarkday • ai-pack-all\r\n\r\n

ai-pack-all

\r\n

Commit ${commit.slice(0,7)} • ${updatedUtc}

\r\n\r\n
\r\n
\r\n

Quick links

\r\n \r\n
\r\n
\r\n

Data/Config

\r\n \r\n
\r\n
\r\n

Core & CI

\r\n \r\n
\r\n
\r\n

Everything (for deep dives)

\r\n \r\n
\r\n
\r\n\r\n

Machine-readable combined pack (below):

\r\n
${escapeHtml(prettyPack)}
`;\r\n fs.writeFileSync(\"docs/ai-pack-all.html\", packHtml);\r\n\r\n PACK_CATALOG.push({ name: \"ai-pack-all (combined)\", count: names.reduce((a,n)=>a + JSON.parse(fs.readFileSync(`docs/${n}.min.json`,\"utf8\")).items.length, 0), bytes_min: minPack.length, files: [\r\n \"docs/ai-pack-all.min.json\", \"docs/ai-pack-all.txt\", \"docs/ai-pack-all.html\"\r\n ]});\r\n})();\r\n\r\n// ---------------- tiny catalog of what we emitted ----------------\r\n(function(){\r\n const cat = {\r\n schema: \"barkday.ai-pack-catalog.v1\",\r\n repo, commit, updated_utc: updatedUtc,\r\n packs: PACK_CATALOG\r\n };\r\n fs.writeFileSync(\"docs/ai-pack-catalog.json\", JSON.stringify(cat, null, 2));\r\n fs.writeFileSync(\"docs/ai-pack-catalog.min.json\", JSON.stringify(cat));\r\n console.log(\"Wrote docs/ai-pack-catalog.(json|min.json)\");\r\n})();\r\n\r\n","inline_bytes":20726,"content_sha256":"0e3d02ae0c8a21abf932bdde3b0f9a21625527dea3db9302591a1352ee6888da"},{"path":"scripts/bulk-fetch-getitems-from-searches.ps1","size":1951,"sha":"41a867aecddcfea88a3e7a83528714856060d5f4","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/bulk-fetch-getitems-from-searches.ps1","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/bulk-fetch-getitems-from-searches.ps1","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"cGFyYW0oCiAgW2ludF0kTWF4SXRlbXMgPSAxMjAsCiAgW2ludF0kUGF1c2VTZWNvbmRzID0gNCwKICBbc3RyaW5nXSRTZWFyY2hEaXIgPSAiLlxkYXRhXHJhdy1hbWF6b24iLAogIFtzdHJpbmddJE91dFByZWZpeCA9ICIuXGRhdGFccmF3LWFtYXpvblxidWxrLWdldGl0ZW1zIgopCgokY2F0YWxvZyA9IEdldC1Db250ZW50IC5cZGF0YVxkb2ctZ2lmdHMtY2F0YWxvZy5qc29uIC1SYXcgfCBDb252ZXJ0RnJvbS1Kc29uCgokZXhpc3RpbmdBc2lucyA9IEB7fQpmb3JlYWNoICgkaXRlbSBpbiAkY2F0YWxvZy5pdGVtcykgewogIGlmICgkaXRlbS5hZmZpbGlhdGUgLWFuZCAkaXRlbS5hZmZpbGlhdGUuYXNpbikgewogICAgJGV4aXN0aW5nQXNpbnNbJGl0ZW0uYWZmaWxpYXRlLmFzaW5dID0gJHRydWUKICB9Cn0KCmZ1bmN0aW9uIFRlc3QtQXNpbiB7CiAgcGFyYW0oW3N0cmluZ10kQXNpbikKICByZXR1cm4gJEFzaW4gLW1hdGNoICdeW0EtWl1bQS1aMC05XXs5fSR8XlswLTldezl9WzAtOVhdJCcKfQoKJGFzaW5zID0gTmV3LU9iamVjdCBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0W3N0cmluZ10KJHNlYXJjaEZpbGVzID0gR2V0LUNoaWxkSXRlbSAkU2VhcmNoRGlyIC1GaWx0ZXIgInNlYXJjaC0qLmpzb24iIHwgU29ydC1PYmplY3QgTmFtZQoKZm9yZWFjaCAoJGZpbGUgaW4gJHNlYXJjaEZpbGVzKSB7CiAgdHJ5IHsKICAgICRqc29uID0gR2V0LUNvbnRlbnQgJGZpbGUuRnVsbE5hbWUgLVJhdyB8IENvbnZlcnRGcm9tLUpzb24KICB9IGNhdGNoIHsKICAgIFdyaXRlLVdhcm5pbmcgIlNraXBwaW5nIHVucmVhZGFibGUgSlNPTjogJCgkZmlsZS5OYW1lKSIKICAgIGNvbnRpbnVlCiAgfQoKICAkaXRlbXMgPSBAKCkKICBpZiAoJGpzb24uc2VhcmNoUmVzdWx0IC1hbmQgJGpzb24uc2VhcmNoUmVzdWx0Lml0ZW1zKSB7CiAgICAkaXRlbXMgPSAkanNvbi5zZWFyY2hSZXN1bHQuaXRlbXMKICB9IGVsc2VpZiAoJGpzb24uaXRlbXMpIHsKICAgICRpdGVtcyA9ICRqc29uLml0ZW1zCiAgfQoKICBmb3JlYWNoICgkaXQgaW4gJGl0ZW1zKSB7CiAgICAkYXNpbiA9IFtzdHJpbmddJGl0LmFzaW4KICAgIGlmIChbc3RyaW5nXTo6SXNOdWxsT3JXaGl0ZVNwYWNlKCRhc2luKSkgeyBjb250aW51ZSB9CiAgICAkYXNpbiA9ICRhc2luLlRyaW0oKS5Ub1VwcGVyKCkKCiAgICBpZiAoLW5vdCAoVGVzdC1Bc2luICRhc2luKSkgeyBjb250aW51ZSB9CiAgICBpZiAoJGV4aXN0aW5nQXNpbnMuQ29udGFpbnNLZXkoJGFzaW4pKSB7IGNvbnRpbnVlIH0KICAgIGlmICgkYXNpbnMgLWNvbnRhaW5zICRhc2luKSB7IGNvbnRpbnVlIH0KCiAgICAkYXNpbnMuQWRkKCRhc2luKQogICAgaWYgKCRhc2lucy5Db3VudCAtZ2UgJE1heEl0ZW1zKSB7IGJyZWFrIH0KICB9CgogIGlmICgkYXNpbnMuQ291bnQgLWdlICRNYXhJdGVtcykgeyBicmVhayB9Cn0KCldyaXRlLUhvc3QgIlF1ZXVlZCBuZXcgQVNJTnM6IiAkYXNpbnMuQ291bnQKCmlmICgkYXNpbnMuQ291bnQgLWVxIDApIHsKICB0aHJvdyAiTm8gbmV3IEFTSU5zIGZvdW5kIGluIHNlYXJjaCBmaWxlcy4iCn0KCiRpbmRleCA9IDEKZm9yICgkaSA9IDA7ICRpIC1sdCAkYXNpbnMuQ291bnQ7ICRpICs9IDEwKSB7CiAgJGVuZCA9IFtNYXRoXTo6TWluKCRpICsgOSwgJGFzaW5zLkNvdW50IC0gMSkKICAkY2h1bmsgPSBAKCRhc2luc1skaS4uJGVuZF0pCiAgJG91dEZpbGUgPSAiezB9LXsxOkQzfS5qc29uIiAtZiAkT3V0UHJlZml4LCAkaW5kZXgKCiAgV3JpdGUtSG9zdCAiRmV0Y2hpbmcgY2h1bmsgJGluZGV4IC0+ICRvdXRGaWxlIgogIFdyaXRlLUhvc3QgIkFTSU5zOiIgKCRjaHVuayAtam9pbiAiLCAiKQoKICAuXHRvb2xzXGFtYXpvbi1nZXQtaXRlbXMucHMxIC1JdGVtSWRzICRjaHVuayAtT3V0RmlsZSAkb3V0RmlsZQoKICBTdGFydC1TbGVlcCAtU2Vjb25kcyAkUGF1c2VTZWNvbmRzCiAgJGluZGV4KysKfQ==","inline_bytes":2604,"content_sha256":"2a859977d35a5f8df947e6b6d59561ff11c8ae6910a0d8ec3c667decb942b9f4"},{"path":"scripts/curate-gift-candidates.mjs","size":13855,"sha":"20614aa1c34e3fba5e94b26b129a787b35d575c3","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/curate-gift-candidates.mjs","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/curate-gift-candidates.mjs","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"#!/usr/bin/env node\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst allowedStatuses = new Set([\"approved\", \"review\", \"draft\", \"retired\"]);\nconst allowedCategories = new Set([\n \"chew\",\n \"fetch\",\n \"training\",\n \"comfort\",\n \"feeding\",\n \"enrichment\",\n \"walks\",\n \"safety\",\n \"travel\",\n \"grooming\",\n \"health\",\n \"seasonal\",\n \"other\"\n]);\nconst allowedSizes = [\"toy\", \"small\", \"medium\", \"large\", \"giant\", \"any\"];\nconst allowedChew = [\"gentle\", \"normal\", \"power\", \"any\"];\nconst placeholderPattern = /Auto-generated starter entry|Review wording later/i;\nconst catOnlyPattern = /\\b(cat|cats|kitten|kittens|feline)\\b/i;\nconst dogPattern = /\\b(dog|dogs|puppy|puppies|pet|pets|canine|collar|leash|harness)\\b/i;\nconst unsupportedPattern = /\\b(shock collar|prong|choke chain|rawhide|medicine|antibiotic|supplement|tactical|crate|muzzle|training collar)\\b/i;\n\nfunction usage() {\n console.error(\"Usage: node scripts/curate-gift-candidates.mjs --input --output --report \");\n process.exit(1);\n}\n\nfunction readArgs(argv) {\n const args = {};\n for (let i = 2; i < argv.length; i += 1) {\n const key = argv[i];\n if (!key.startsWith(\"--\")) usage();\n const value = argv[i + 1];\n if (!value || value.startsWith(\"--\")) usage();\n args[key.slice(2)] = value;\n i += 1;\n }\n if (!args.input || !args.output || !args.report) usage();\n return args;\n}\n\nfunction readJson(filePath) {\n return JSON.parse(fs.readFileSync(filePath, \"utf8\"));\n}\n\nfunction writeJson(filePath, value) {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + \"\\n\", \"utf8\");\n}\n\nfunction unique(values) {\n return [...new Set(values.filter(Boolean))];\n}\n\nfunction normalizeText(value) {\n return String(value || \"\")\n .replace(/[“”]/g, \"\\\"\")\n .replace(/[‘’]/g, \"'\")\n .replace(/[,]/g, \",\")\n .replace(/[–—]/g, \"-\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction titleLooksRaw(title) {\n const text = normalizeText(title);\n return text.length > 90 || (text.match(/[,|/-]/g) || []).length > 5 || /\\b(2PCS|2 Pack|3 Pack|4 Pack|Pack of|with|for)\\b.*\\b(with|for)\\b/i.test(text);\n}\n\nfunction removeVariantNoise(title) {\n return normalizeText(title)\n .replace(/\\[[^\\]]+\\]/g, \" \")\n .replace(/\\([^)]*(black|blue|green|pink|red|grey|gray|orange|purple|yellow|medium|large|small|xs|xl|pack|inch|oz|ct|count)[^)]*\\)/gi, \" \")\n .replace(/\\b(1st|2nd) generation\\b/gi, \" \")\n .replace(/\\bUSB[- ]?C\\b/gi, \"USB-C\")\n .replace(/\\bAir ?Tags?\\b/g, \"AirTag\")\n .replace(/\\bAirtag\\b/g, \"AirTag\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction cleanTitle(rawTitle, category) {\n const title = removeVariantNoise(rawTitle);\n const firstClause = title.split(/\\s[-|]\\s|:/)[0].split(\",\")[0].trim();\n const words = firstClause.split(/\\s+/).filter(Boolean);\n let cleaned = words.slice(0, 9).join(\" \");\n\n if (/airtag/i.test(title) && !/holder|case|mount/i.test(cleaned)) cleaned += \" Holder\";\n if (/lick/i.test(title) && /mat/i.test(title) && !/lick mat/i.test(cleaned)) cleaned = \"Dog Lick Mat\";\n if (/slow feeder|slow eating/i.test(title) && !/slow feeder/i.test(cleaned)) cleaned = \"Slow Feeder Dog Bowl Insert\";\n if (/snuffle/i.test(title) && !/snuffle/i.test(cleaned)) cleaned = \"Dog Snuffle Mat\";\n if (/water bottle/i.test(title) && !/water bottle/i.test(cleaned)) cleaned = \"Portable Dog Water Bottle\";\n if (/light up|led|illuminated/i.test(title) && /harness/i.test(title) && !/harness/i.test(cleaned)) cleaned = \"Light-Up Dog Harness\";\n if (category === \"fetch\" && /stick/i.test(title) && !/stick/i.test(cleaned)) cleaned = \"Floating Fetch Stick\";\n\n return normalizeText(cleaned)\n .replace(/\\bfor Dog(s)?\\b$/i, \"\")\n .replace(/\\bfor\\b$/i, \"\")\n .trim();\n}\n\nfunction inferCategory(text, currentCategory) {\n const t = text.toLowerCase();\n if (/airtag|tracker|reflective|light up|led|safety|collar light|illuminated/.test(t)) return \"safety\";\n if (/harness|leash|walking|walk/.test(t)) return \"walks\";\n if (/lick mat|anxiety|calming|cooling mat|blanket|bed/.test(t)) return \"comfort\";\n if (/slow feeder|bowl|water bottle|water bowl|food|feeding/.test(t)) return \"feeding\";\n if (/snuffle|puzzle|treat dispens|foraging|enrichment|iq/.test(t)) return \"enrichment\";\n if (/fetch|ball|stick|frisbee|floating/.test(t)) return \"fetch\";\n if (/chew|rubber|teeth|tug|rope/.test(t)) return \"chew\";\n if (/groom|bath|shower/.test(t)) return \"grooming\";\n if (/travel|portable|car|hiking|camping/.test(t)) return \"travel\";\n return allowedCategories.has(currentCategory) ? currentCategory : \"other\";\n}\n\nfunction inferTags(text, category) {\n const t = text.toLowerCase();\n const tags = [category];\n if (/airtag|tracker|gps/.test(t)) tags.push(\"tracking\", \"collar\");\n if (/waterproof|rainproof/.test(t)) tags.push(\"waterproof\");\n if (/reflective|light up|led|illuminated|night/.test(t)) tags.push(\"night-walks\", \"visibility\");\n if (/lick mat|licking/.test(t)) tags.push(\"lick-mat\", \"calming\");\n if (/suction/.test(t)) tags.push(\"suction-cups\");\n if (/slow feeder|slow eating|anti[- ]?bloat/.test(t)) tags.push(\"slow-feeding\");\n if (/snuffle|foraging/.test(t)) tags.push(\"foraging\");\n if (/puzzle|iq|brain|mental/.test(t)) tags.push(\"puzzle\", \"mental-stimulation\");\n if (/treat dispens|stuffable/.test(t)) tags.push(\"treat-dispensing\");\n if (/floating|pool|beach|water/.test(t)) tags.push(\"water-play\");\n if (/durable|tough|aggressive chewer|power chewer/.test(t)) tags.push(\"durable\");\n if (/bath|groom/.test(t)) tags.push(\"bath\", \"grooming\");\n if (/portable|travel|hiking|camping/.test(t)) tags.push(\"travel\");\n return unique(tags).slice(0, 6);\n}\n\nfunction inferSizes(text, currentSizes) {\n const t = text.toLowerCase();\n const sizes = [];\n if (/\\bxs\\b|extra small|toy breed|small breed|small dog|puppy/.test(t)) sizes.push(\"toy\", \"small\");\n if (/\\bmedium\\b|medium dog|medium breed/.test(t)) sizes.push(\"medium\");\n if (/\\blarge\\b|large dog|large breed|extra large|\\bxl\\b|giant/.test(t)) sizes.push(\"large\", \"giant\");\n if (!sizes.length && Array.isArray(currentSizes)) {\n for (const size of currentSizes) if (allowedSizes.includes(size)) sizes.push(size);\n }\n return unique(sizes.length ? sizes : [\"any\"]);\n}\n\nfunction inferChew(text, category, currentChew) {\n const t = text.toLowerCase();\n if (![\"chew\", \"fetch\", \"enrichment\"].includes(category)) return [\"any\"];\n if (/aggressive chewer|power chewer|tough|nearly indestructible|heavy[- ]?duty/.test(t)) return [\"normal\", \"power\"];\n if (/puppy|gentle|soft|lick mat|snuffle/.test(t)) return [\"gentle\", \"normal\"];\n if (Array.isArray(currentChew)) {\n const normalized = currentChew.map(value => value === \"strong\" ? \"power\" : value).filter(value => allowedChew.includes(value));\n if (normalized.length) return unique(normalized);\n }\n return [\"normal\"];\n}\n\nfunction inferAge(text, tags) {\n const t = text.toLowerCase();\n if (/puppy|teething/.test(t) || tags.includes(\"puppy\")) {\n return { ageAxis: \"human\", minAge: 0, maxAge: 1.5 };\n }\n if (/senior/.test(t) || tags.includes(\"senior\")) {\n return { ageAxis: \"dog\", minDogYears: 61 };\n }\n return { ageAxis: \"none\" };\n}\n\nfunction benefitFor(category, tags) {\n if (category === \"safety\") return \"Adds a practical safety upgrade for walks without changing the dog's usual routine.\";\n if (category === \"walks\") return \"Supports easier everyday walks with gear that fits into a normal outing.\";\n if (category === \"comfort\") {\n if (tags.includes(\"lick-mat\")) return \"Gives dogs a calm licking activity for grooming, bath time, or quiet breaks.\";\n return \"Adds a simple comfort boost for rest, heat, or low-key recovery days.\";\n }\n if (category === \"feeding\") return \"Helps turn meals or water breaks into a slower, more manageable routine.\";\n if (category === \"enrichment\") return \"Adds low-fuss mental stimulation through sniffing, foraging, or treat work.\";\n if (category === \"fetch\") return \"Keeps active dogs engaged with a simple toy for fetch sessions.\";\n if (category === \"chew\") return \"Gives mouthy dogs a focused outlet for chewing or tug-style play.\";\n if (category === \"grooming\") return \"Helps make grooming or bath time feel more manageable.\";\n if (category === \"travel\") return \"Makes outings easier with a portable dog-care essential.\";\n return \"Adds a practical Barkday gift option for everyday dog care.\";\n}\n\nfunction detectReasons(item, sourceText, duplicateAsins) {\n const reasons = [];\n const title = normalizeText(item.title);\n const asin = item?.affiliate?.asin;\n const url = item?.affiliate?.url;\n\n if (!url) reasons.push(\"missing_affiliate_url\");\n if (!asin) reasons.push(\"missing_asin\");\n if (asin && duplicateAsins.has(asin)) reasons.push(\"duplicate_asin\");\n if (placeholderPattern.test(JSON.stringify(item))) reasons.push(\"internal_placeholder_text\");\n if (titleLooksRaw(title)) reasons.push(\"raw_long_amazon_title\");\n if (catOnlyPattern.test(sourceText) && !dogPattern.test(sourceText)) reasons.push(\"cat_only_or_non_dog\");\n if (unsupportedPattern.test(sourceText)) reasons.push(\"unsupported_or_questionable_product_type\");\n if (!dogPattern.test(sourceText)) reasons.push(\"weak_dog_fit_signal\");\n\n return reasons;\n}\n\nfunction statusFor(reasons, inferredCategory, cleanedTitle, tags) {\n if (reasons.some(reason => [\n \"missing_affiliate_url\",\n \"missing_asin\",\n \"duplicate_asin\",\n \"cat_only_or_non_dog\",\n \"unsupported_or_questionable_product_type\"\n ].includes(reason))) return \"retired\";\n\n if (!allowedCategories.has(inferredCategory) || inferredCategory === \"other\") return \"draft\";\n if (!cleanedTitle || cleanedTitle.length > 72 || tags.length < 2) return \"draft\";\n if (/^for\\b/i.test(cleanedTitle)) return \"draft\";\n if (reasons.includes(\"weak_dog_fit_signal\")) return \"draft\";\n if (reasons.includes(\"raw_long_amazon_title\")) return \"review\";\n\n const blockingReviewReasons = reasons.filter(reason => reason !== \"internal_placeholder_text\" && reason !== \"raw_long_amazon_title\");\n if (blockingReviewReasons.length) return \"review\";\n\n return \"approved\";\n}\n\nfunction curateItem(item, duplicateAsins) {\n const sourceTitle = normalizeText(item.title);\n const sourceText = normalizeText([\n item.title,\n item.benefit,\n item.notes,\n ...(Array.isArray(item.features) ? item.features : []),\n ...(Array.isArray(item.sourceFeatures) ? item.sourceFeatures : [])\n ].filter(Boolean).join(\" \"));\n const reasons = detectReasons(item, sourceText, duplicateAsins);\n const category = inferCategory(sourceText, item.category);\n const tags = inferTags(sourceText, category);\n const title = cleanTitle(sourceTitle, category);\n const sizes = inferSizes(sourceText, item.sizes);\n const chew = inferChew(sourceText, category, item.chew);\n const age = inferAge(sourceText, tags);\n const publishStatus = statusFor(reasons, category, title, tags);\n\n const curated = {\n ...item,\n title,\n benefit: benefitFor(category, tags),\n category,\n tags,\n ...age,\n sizes,\n chew,\n breedGroups: Array.isArray(item.breedGroups) ? item.breedGroups : [],\n preferred: Boolean(item.preferred),\n priority: Number.isFinite(item.priority) ? item.priority : 100,\n source: item.source || \"amazon_enriched\",\n affiliate: {\n ...(item.affiliate || {})\n },\n active: item.active !== false,\n publishStatus,\n notes: [\n `Curated from local candidate batch. Source title: ${sourceTitle}`,\n Array.isArray(item.features) && item.features.length ? `Source features: ${item.features.slice(0, 3).join(\" | \")}` : \"\",\n reasons.length ? `Hold reasons: ${reasons.join(\", \")}` : \"No curation hold reasons.\"\n ].filter(Boolean).join(\" \")\n };\n\n if (item.amazon) curated.amazon = item.amazon;\n\n if (publishStatus !== \"approved\" && placeholderPattern.test(JSON.stringify(item))) {\n curated.notes += \" Original row contained internal starter wording.\";\n }\n\n for (const key of [\"minAge\", \"maxAge\", \"minDogYears\", \"maxDogYears\"]) {\n if (!(key in age)) delete curated[key];\n }\n\n return { item: curated, reasons };\n}\n\nconst args = readArgs(process.argv);\nconst input = readJson(args.input);\nif (!Array.isArray(input)) {\n throw new Error(\"Input candidate batch must be a top-level JSON array.\");\n}\n\nconst asinCounts = new Map();\nfor (const item of input) {\n const asin = item?.affiliate?.asin;\n if (asin) asinCounts.set(asin, (asinCounts.get(asin) || 0) + 1);\n}\nconst duplicateAsins = new Set([...asinCounts].filter(([, count]) => count > 1).map(([asin]) => asin));\n\nconst report = {\n generatedAt: new Date().toISOString(),\n input: args.input,\n output: args.output,\n counts: {\n input: input.length,\n approved: 0,\n review: 0,\n draft: 0,\n retired: 0\n },\n holdReasons: {},\n examples: []\n};\n\nconst curated = input.map((candidate) => {\n const result = curateItem(candidate, duplicateAsins);\n const status = allowedStatuses.has(result.item.publishStatus) ? result.item.publishStatus : \"draft\";\n report.counts[status] += 1;\n for (const reason of result.reasons) {\n report.holdReasons[reason] = (report.holdReasons[reason] || 0) + 1;\n }\n if (report.examples.length < 5) {\n report.examples.push({\n id: candidate.id,\n beforeTitle: candidate.title,\n afterTitle: result.item.title,\n beforeBenefit: candidate.benefit,\n afterBenefit: result.item.benefit,\n publishStatus: result.item.publishStatus,\n holdReasons: result.reasons\n });\n }\n return result.item;\n});\n\nwriteJson(args.output, curated);\nwriteJson(args.report, report);\n\nconsole.log(`Curated ${curated.length} candidate item(s).`);\nconsole.log(`approved=${report.counts.approved} review=${report.counts.review} draft=${report.counts.draft} retired=${report.counts.retired}`);\nconsole.log(`Output: ${args.output}`);\nconsole.log(`Report: ${args.report}`);\n","inline_bytes":13841,"content_sha256":"a2cad746c8dd80ae3f4579b48229f86640ea3c2fb04195fcc91e52d3650f0434"},{"path":"scripts/merge-gifts-v2.mjs","size":1964,"sha":"0fefa9e2f38cd45dcddb7e732addb0a2b75f43f2","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/merge-gifts-v2.mjs","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/merge-gifts-v2.mjs","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"#!/usr/bin/env node\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nfunction readJson(filePath) {\n return JSON.parse(fs.readFileSync(filePath, 'utf8'));\n}\n\nfunction writeJson(filePath, value) {\n fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\\n', 'utf8');\n}\n\nfunction mergeItem(base, overlay) {\n return {\n ...base,\n ...overlay,\n affiliate: { ...(base.affiliate || {}), ...(overlay.affiliate || {}) },\n amazon: { ...(base.amazon || {}), ...(overlay.amazon || {}) },\n tags: Array.from(new Set([...(base.tags || []), ...(overlay.tags || [])]))\n };\n}\n\nfunction compareItems(a, b) {\n const prefA = a.preferred ? 1 : 0;\n const prefB = b.preferred ? 1 : 0;\n if (prefA !== prefB) return prefB - prefA;\n const prioA = Number.isFinite(a.priority) ? a.priority : 0;\n const prioB = Number.isFinite(b.priority) ? b.priority : 0;\n if (prioA !== prioB) return prioB - prioA;\n return String(a.title || a.id).localeCompare(String(b.title || b.id));\n}\n\nconst [, , catalogPath, preferredPath, outPath] = process.argv;\n\nif (!catalogPath || !preferredPath || !outPath) {\n console.error('Usage: node scripts/merge-gifts-v2.mjs ');\n process.exit(1);\n}\n\nconst catalog = readJson(catalogPath);\nconst preferred = readJson(preferredPath);\n\nconst map = new Map();\nfor (const item of catalog.items || []) map.set(item.id, item);\nfor (const item of preferred.items || []) {\n const prev = map.get(item.id);\n map.set(item.id, prev ? mergeItem(prev, item) : item);\n}\n\nconst merged = {\n version: 2,\n generatedAt: new Date().toISOString(),\n marketplaceDefault: catalog.marketplaceDefault || 'www.amazon.com',\n notes: 'Merged Barkday gift catalog output',\n items: Array.from(map.values()).filter(x => x.active !== false).sort(compareItems)\n};\n\nfs.mkdirSync(path.dirname(outPath), { recursive: true });\nwriteJson(outPath, merged);\nconsole.log(`Merged ${merged.items.length} item(s) into ${outPath}`);\n","inline_bytes":1964,"content_sha256":"df4ba6088b10a9d516b45303c7d979e9b0d0a889a82ea671faaa213433f521c9"},{"path":"scripts/rebuild-gift-catalog.mjs","size":3292,"sha":"69e50026fe6fa9b00ba213bebd2dd4e6a3d96d5d","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/rebuild-gift-catalog.mjs","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/rebuild-gift-catalog.mjs","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"#!/usr/bin/env node\nimport fs from \"fs\";\nimport path from \"path\";\n\nfunction readJson(filePath) {\n return JSON.parse(fs.readFileSync(filePath, \"utf8\"));\n}\n\nfunction writeJson(filePath, value) {\n fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + \"\\n\", \"utf8\");\n}\n\nfunction ensureCatalogRoot(value) {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\"Base catalog must be a JSON object.\");\n }\n if (!Array.isArray(value.items)) {\n throw new Error(\"Base catalog must contain an items array.\");\n }\n return value;\n}\n\nfunction ensureArray(value, label) {\n if (!Array.isArray(value)) {\n throw new Error(`${label} must be a JSON array.`);\n }\n return value;\n}\n\nfunction getAsin(item) {\n return item?.affiliate?.asin || null;\n}\n\nfunction listBatchFiles(dirPath) {\n if (!fs.existsSync(dirPath)) return [];\n const batchName = /^\\d{4}-\\d{2}-\\d{2}-batch-\\d+\\.json$/i;\n\n return fs.readdirSync(dirPath)\n .filter(name => batchName.test(name))\n .sort()\n .map(name => path.join(dirPath, name));\n}\n\nfunction sanitizeItems(items, label) {\n const out = [];\n for (const item of items) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) {\n console.warn(`Skipping invalid item in ${label}`);\n continue;\n }\n if (!item.id) {\n console.warn(`Skipping item missing id in ${label}`);\n continue;\n }\n out.push(item);\n }\n return out;\n}\n\nfunction dedupeItems(items) {\n const seenIds = new Set();\n const seenAsins = new Set();\n const out = [];\n\n for (const item of items) {\n const id = item.id;\n const asin = getAsin(item);\n\n if (seenIds.has(id)) {\n console.warn(`Skipping duplicate id: ${id}`);\n continue;\n }\n if (asin && seenAsins.has(asin)) {\n console.warn(`Skipping duplicate ASIN: ${asin}`);\n continue;\n }\n\n seenIds.add(id);\n if (asin) seenAsins.add(asin);\n out.push(item);\n }\n\n return out;\n}\n\nfunction sortItems(items) {\n return [...items].sort((a, b) => {\n const pa = Number.isFinite(a?.priority) ? a.priority : 0;\n const pb = Number.isFinite(b?.priority) ? b.priority : 0;\n if (pb !== pa) return pb - pa;\n return String(a?.title || \"\").localeCompare(String(b?.title || \"\"));\n });\n}\n\nconst repoRoot = process.cwd();\nconst dataDir = path.join(repoRoot, \"data\");\nconst basePath = path.join(dataDir, \"dog-gifts-base.json\");\nconst outputPath = path.join(dataDir, \"dog-gifts-catalog.json\");\nconst batchDir = path.join(dataDir, \"gift-batches\");\n\nconst base = ensureCatalogRoot(readJson(basePath));\nconst batchFiles = listBatchFiles(batchDir);\n\nlet allItems = sanitizeItems(base.items, \"dog-gifts-base.json\");\n\nfor (const file of batchFiles) {\n const batch = ensureArray(readJson(file), path.basename(file));\n allItems.push(...sanitizeItems(batch, path.basename(file)));\n}\n\nallItems = dedupeItems(allItems);\nallItems = sortItems(allItems);\n\nconst rebuilt = {\n ...base,\n generatedAt: new Date().toISOString(),\n notes: \"Generated from dog-gifts-base.json plus data/gift-batches/*.json\",\n items: allItems\n};\n\nwriteJson(outputPath, rebuilt);\n\nconsole.log(`Rebuilt catalog with ${allItems.length} unique items.`);\nconsole.log(`Batch files used: ${batchFiles.length}`);\nconsole.log(`Output: ${path.relative(repoRoot, outputPath)}`);","inline_bytes":3292,"content_sha256":"1e15abbf552b46f43fac700c8c9ace66d77c56a1116f2250e9561ff7e163c0f6"},{"path":"scripts/smoke-gift-logic.mjs","size":2844,"sha":"73f3d6b1c71ceac15c73a328284b71a58d6b264a","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/smoke-gift-logic.mjs","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/smoke-gift-logic.mjs","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"#!/usr/bin/env node\nfunction giftTagList(it) {\n const out = [];\n if (it && it.tag != null) out.push(String(it.tag));\n if (it && it.ageTag != null) out.push(String(it.ageTag));\n if (it && Array.isArray(it.tags)) {\n for (const tag of it.tags) out.push(String(tag));\n }\n return out.map(s => s.toLowerCase());\n}\n\nfunction giftAgeMatches(it, dogYears, humanYears, ignoreAge = false) {\n if (ignoreAge) return true;\n\n const hasDogYearBounds = (it && it.minDogYears != null) || (it && it.maxDogYears != null);\n if (hasDogYearBounds) {\n if (!Number.isFinite(dogYears)) return true;\n let ok = true;\n if (it.minDogYears != null) ok = ok && dogYears >= Number(it.minDogYears);\n if (it.maxDogYears != null) ok = ok && dogYears <= Number(it.maxDogYears);\n return ok;\n }\n\n const hasHumanYearBounds = (it && it.minAge != null) || (it && it.maxAge != null);\n if (hasHumanYearBounds) {\n if (!Number.isFinite(humanYears)) return true;\n let ok = true;\n if (it.minAge != null) ok = ok && humanYears >= Number(it.minAge);\n if (it.maxAge != null) ok = ok && humanYears <= Number(it.maxAge);\n return ok;\n }\n\n const tags = giftTagList(it);\n if (tags.some(t => t.includes(\"puppy\"))) return Number.isFinite(dogYears) ? dogYears <= 15 : true;\n if (tags.some(t => t.includes(\"senior\"))) return Number.isFinite(dogYears) ? dogYears >= 61 : true;\n\n return true;\n}\n\nconst tests = [\n { name: \"explicit puppy band at 10 dog-years\", item: { minDogYears: 0, maxDogYears: 15 }, dogYears: 10, humanYears: 0.8, expect: true },\n { name: \"explicit puppy band fails at 16 dog-years\", item: { minDogYears: 0, maxDogYears: 15 }, dogYears: 16, humanYears: 1.1, expect: false },\n { name: \"senior tag fails at 10 dog-years\", item: { tag: \"senior\" }, dogYears: 10, humanYears: 2.0, expect: false },\n { name: \"senior tag passes at 61 dog-years\", item: { tag: \"senior\" }, dogYears: 61, humanYears: 10.0, expect: true },\n { name: \"human-year row passes for 8 chronological years\", item: { minAge: 7 }, dogYears: 15, humanYears: 8, expect: true },\n { name: \"human-year row fails for 6 chronological years\", item: { minAge: 7 }, dogYears: 50, humanYears: 6, expect: false },\n { name: \"mixed mid-age dog does not match senior tag\", item: { tag: \"senior\" }, dogYears: 15, humanYears: 3.0, expect: false },\n { name: \"ignoreAge bypasses filters\", item: { minDogYears: 61 }, dogYears: 10, humanYears: 2, ignoreAge: true, expect: true }\n];\n\nlet failed = 0;\nfor (const t of tests) {\n const actual = giftAgeMatches(t.item, t.dogYears, t.humanYears, !!t.ignoreAge);\n const pass = actual === t.expect;\n if (!pass) failed += 1;\n console.log(`${pass ? \"PASS\" : \"FAIL\"} ${t.name} actual=${actual} expected=${t.expect}`);\n}\n\nconsole.log(\"\");\nconsole.log(`Summary: ${tests.length - failed} passed, ${failed} failed.`);\nif (failed) process.exit(1);\n","inline_bytes":2844,"content_sha256":"b2e4529e3e4f5d6dcf639eeb19054fd3a169a43b18c0424a6388127cd89ef01a"},{"path":"scripts/validate-gifts-v2.mjs","size":3433,"sha":"648102c3a2415b3919a7eee4c4d9ea4fec267ab5","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/validate-gifts-v2.mjs","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/validate-gifts-v2.mjs","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"#!/usr/bin/env node\nimport fs from 'node:fs';\n\nfunction readJson(filePath) {\n return JSON.parse(fs.readFileSync(filePath, 'utf8'));\n}\n\nfunction fail(msg) {\n console.error(`ERROR ${msg}`);\n process.exitCode = 1;\n}\n\nfunction warn(msg) {\n console.warn(`WARN ${msg}`);\n}\n\nfunction info(msg) {\n console.log(`INFO ${msg}`);\n}\n\nconst allowedPublishStatuses = new Set(['approved', 'review', 'draft', 'retired']);\nconst placeholderPattern = /Auto-generated starter entry|Review wording later/i;\n\nfunction textContainsPlaceholder(item) {\n return placeholderPattern.test([\n item.title,\n item.benefit,\n item.notes\n ].filter(Boolean).join(' '));\n}\n\nfunction validateItem(item, seenIds) {\n if (!item.id) fail('Item missing id');\n if (seenIds.has(item.id)) fail(`Duplicate id: ${item.id}`);\n seenIds.add(item.id);\n\n if (!item.title) fail(`Item ${item.id} missing title`);\n if (!item.category) fail(`Item ${item.id} missing category`);\n if (!item.affiliate || !item.affiliate.url) fail(`Item ${item.id} missing affiliate.url`);\n if (!allowedPublishStatuses.has(item.publishStatus)) {\n fail(`Item ${item.id} has invalid or missing publishStatus`);\n }\n if (item.publishStatus === 'approved' && textContainsPlaceholder(item)) {\n fail(`Item ${item.id} is approved but still contains placeholder curation text`);\n }\n if (item.publishStatus === 'approved' && String(item.title || '').length > 90) {\n fail(`Item ${item.id} is approved but has raw-looking long title`);\n }\n\n if (item.ageAxis === 'human') {\n if (item.minDogYears != null || item.maxDogYears != null) {\n fail(`Item ${item.id} mixes human age axis with dog-year bounds`);\n }\n }\n\n if (item.ageAxis === 'dog') {\n if (item.minAge != null || item.maxAge != null) {\n fail(`Item ${item.id} mixes dog age axis with human-year bounds`);\n }\n }\n\n if (item.minAge != null && item.maxAge != null && Number(item.minAge) > Number(item.maxAge)) {\n fail(`Item ${item.id} has minAge > maxAge`);\n }\n\n if (item.minDogYears != null && item.maxDogYears != null && Number(item.minDogYears) > Number(item.maxDogYears)) {\n fail(`Item ${item.id} has minDogYears > maxDogYears`);\n }\n\n if (!Array.isArray(item.sizes) || item.sizes.length === 0) {\n fail(`Item ${item.id} missing sizes array`);\n }\n\n if (!Array.isArray(item.chew) || item.chew.length === 0) {\n fail(`Item ${item.id} missing chew array`);\n }\n\n if (item.amazon?.imageUrl && !item.amazon?.imageRefreshedAt) {\n warn(`Item ${item.id} has amazon.imageUrl without amazon.imageRefreshedAt`);\n }\n\n if (item.amazon?.offersRefreshedAt && !item.amazon?.resources?.some(r => String(r).startsWith('offersV2'))) {\n warn(`Item ${item.id} has offersRefreshedAt without an offersV2 resource note`);\n }\n}\n\nconst [, , catalogPath, preferredPath] = process.argv;\nif (!catalogPath || !preferredPath) {\n console.error('Usage: node scripts/validate-gifts-v2.mjs ');\n process.exit(1);\n}\n\nconst catalog = readJson(catalogPath);\nconst preferred = readJson(preferredPath);\nconst seen = new Set();\n\nfor (const item of catalog.items || []) validateItem(item, seen);\nfor (const item of preferred.items || []) {\n if (!item.id) fail('Preferred item missing id');\n}\n\ninfo(`Catalog items: ${(catalog.items || []).length}`);\ninfo(`Preferred items: ${(preferred.items || []).length}`);\nif (!process.exitCode) {\n info('Validation completed without errors.');\n}\n","inline_bytes":3433,"content_sha256":"8cf7e02320f11962e3a26609b9f4e5ace53dceaa2d502fb2d89223d0f1b8873c"},{"path":"scripts/validate-gifts.mjs","size":1424,"sha":"c3d256477f636eb1fcb597a491ca58b51b5f6f65","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/validate-gifts.mjs","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/scripts/validate-gifts.mjs","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"#!/usr/bin/env node\nimport { spawnSync } from \"node:child_process\";\nimport path from \"node:path\";\n\nconst [, , catalogArg, preferredArg] = process.argv;\n\nconst legacyHints = [\n \"dog-birthday-feed\",\n \"dog-gifts.json\",\n \"dog-gifts.schema.json\"\n];\n\nfor (const arg of [catalogArg, preferredArg].filter(Boolean)) {\n const normalized = String(arg).replace(/\\\\/g, \"/\");\n if (legacyHints.some(hint => normalized.includes(hint))) {\n console.error(\"ERROR scripts/validate-gifts.mjs now validates the v2 gift workflow only.\");\n console.error(\"ERROR Use data/dog-gifts-catalog.json and data/dog-gifts-preferred.json, then merge to data/dog-gifts-merged.json.\");\n console.error(\"ERROR Root dog-gifts.json and dog-birthday-feed are deprecated compatibility paths.\");\n process.exit(1);\n }\n}\n\nconst catalogPath = catalogArg || path.join(\"data\", \"dog-gifts-catalog.json\");\nconst preferredPath = preferredArg || path.join(\"data\", \"dog-gifts-preferred.json\");\n\nconsole.log(\"INFO Delegating to v2 gift validator.\");\nconsole.log(`INFO Catalog: ${catalogPath}`);\nconsole.log(`INFO Preferred: ${preferredPath}`);\n\nconst result = spawnSync(\n process.execPath,\n [path.join(\"scripts\", \"validate-gifts-v2.mjs\"), catalogPath, preferredPath],\n { stdio: \"inherit\" }\n);\n\nif (result.error) {\n console.error(`ERROR Failed to run v2 validator: ${result.error.message}`);\n process.exit(1);\n}\n\nprocess.exit(result.status ?? 1);\n","inline_bytes":1424,"content_sha256":"e45d2fca07913af3f713d83b9ff8de00e59dac74bd54e464a9a8b0ecad15eebd"},{"path":"service-worker.js","size":2325,"sha":"5c3b6f7e245ee4a9da55dab3167be428aff1615d","media_type":"application/javascript","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/service-worker.js","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/service-worker.js","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"// service-worker.js (network-first for index and app.js, cache-first for static assets)\nconst CACHE = 'bd-v7-2026-05-03-1';\n\nconst PRECACHE = [\n './',\n 'style.css?v=4',\n 'privacy.html',\n 'terms.html',\n 'favicon.ico',\n 'favicon-96x96.png',\n 'favicon.svg',\n 'icon-192.png',\n 'icon-256.png',\n 'icon-384.png',\n 'icon-512.png',\n 'icon-maskable-192.png',\n 'icon-maskable-512.png',\n 'manifest.json',\n 'js/runtime-fetch.js'\n];\n\nself.addEventListener('install', (event) => {\n self.skipWaiting();\n event.waitUntil(caches.open(CACHE).then((c) => c.addAll(PRECACHE)));\n});\n\nself.addEventListener('activate', (event) => {\n event.waitUntil(\n caches.keys().then((keys) =>\n Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))\n ).then(() => self.clients.claim())\n );\n});\n\nself.addEventListener('fetch', (event) => {\n const req = event.request;\n const url = new URL(req.url);\n const isNav = req.mode === 'navigate';\n const isAppJs = url.pathname.endsWith('/app.js') || url.pathname.endsWith('app.js');\n const isGiftFeed = /(^|\\/)dog-gifts(?:-(?:catalog|merged))?\\.json$/i.test(url.pathname);\n\n if (isGiftFeed) {\n event.respondWith(\n fetch(req, { cache: 'no-store' }).catch(() =>\n new Response(JSON.stringify({ error: 'Gift feed unavailable' }), {\n status: 503,\n headers: { 'Content-Type': 'application/json' }\n })\n )\n );\n return;\n }\n\n // Network-first for index.html and app.js (any ?v=...)\n if (isNav || isAppJs) {\n event.respondWith(\n fetch(req).then((res) => {\n const copy = res.clone();\n caches.open(CACHE).then((c) => {\n const key = isAppJs ? new Request(url.origin + url.pathname) : req;\n c.put(key, copy);\n });\n return res;\n }).catch(() => {\n if (isAppJs) return caches.match(new Request(url.origin + url.pathname), { ignoreSearch: true });\n return caches.match('./');\n })\n );\n return;\n }\n\n // Everything else: cache-first (ignore search)\n event.respondWith(\n caches.match(req, { ignoreSearch: true }).then((cached) => {\n if (cached) return cached;\n return fetch(req).then((res) => {\n const copy = res.clone();\n caches.open(CACHE).then((c) => c.put(req, copy));\n return res;\n });\n })\n );\n});\n","inline_bytes":2325,"content_sha256":"99088ea6ffcef9d67240a4d089f201822233b38b9ff5f7758bf6986ffd24aba4"},{"path":"sitemap.xml","size":327,"sha":"e6be5f4e9c32d2e774a300bb8c923bb12de21977","media_type":"application/xml","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/sitemap.xml","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/sitemap.xml","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHVybHNldCB4bWxucz0iaHR0cDovL3d3dy5zaXRlbWFwcy5vcmcvc2NoZW1hcy9zaXRlbWFwLzAuOSI+CiAgPHVybD48bG9jPmh0dHBzOi8vY2FuZGlkcXVhbGl0eS5naXRodWIuaW8vQmFya2RheS88L2xvYz48L3VybD4KICA8dXJsPjxsb2M+aHR0cHM6Ly9jYW5kaWRxdWFsaXR5LmdpdGh1Yi5pby9CYXJrZGF5L3ByaXZhY3kuaHRtbDwvbG9jPjwvdXJsPgogIDx1cmw+PGxvYz5odHRwczovL2NhbmRpZHF1YWxpdHkuZ2l0aHViLmlvL0JhcmtkYXkvdGVybXMuaHRtbDwvbG9jPjwvdXJsPgo8L3VybHNldD4K","inline_bytes":436,"content_sha256":"3392cddf0864cfd34c6c7992c379032bfd032364ae492be62ab198a272564554"},{"path":"style.css","size":18430,"sha":"323ab714966f82ed6c812591c7d93d87386853f8","media_type":"text/css","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/style.css","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/style.css","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":":root{\n /* Button Bar tokens */\n --gap: .75rem;\n --btn-min-h: 48px;\n --pad: 12px;\n --radius: 12px;\n\n --btn-primary-bg: #1f6feb;\n --btn-primary-fg: #fff;\n --btn-secondary-bg: #f3f4f6;\n --btn-secondary-fg: #111827;\n --btn-disabled-bg: #e5e7eb;\n --btn-disabled-fg: #9ca3af;\n --bg:#0b0c10; --card:#13151a; --text:#e8ecf1; --muted:#9aa4af; --brand:#4aa3ff; --accent:#6ae3b2; --danger:#ff6b6b; --border:#232734;\n --shadow:0 6px 24px rgba(0,0,0,.35);\n}\n:root[data-theme=\"light\"]{\n --bg:#f7f8fa; --card:#ffffff; --text:#0f172a; --muted:#475569; --brand:#2563eb; --accent:#059669; --danger:#b91c1c; --border:#e2e8f0;\n --shadow:0 6px 24px rgba(2,6,23,.08);\n}\n\n*{box-sizing:border-box}\nhtml,body{height:100%}\nbody{margin:0;background:var(--bg);color:var(--text);font:16px/1.45 system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,\"Helvetica Neue\",Arial}\n.wrap{max-width:1100px;margin:0 auto;padding:24px}\n\nheader{display:flex;gap:16px;align-items:center;justify-content:space-between;margin-bottom:8px}\n.title{display:flex;gap:12px;align-items:center}\n.logoImg{width:48px;height:auto;display:block;filter:drop-shadow(0 2px 4px rgba(0,0,0,.25))}\n.toggle{appearance:none;border:1px solid var(--border);background:var(--card);color:var(--text);padding:8px 12px;border-radius:12px;cursor:pointer;box-shadow:var(--shadow)}\n\n.card{background:var(--card);border:1px solid var(--border);border-radius:16px;padding:16px;box-shadow:var(--shadow)}\nh1{font-size:24px;margin:0}\nh2{font-size:18px;margin:0 0 8px}\nlabel{font-weight:600;display:block;margin:14px 0 6px}\ninput[type=\"number\"], select, input[type=\"date\"], input[type=\"text\"]{width:100%;padding:10px 12px;border-radius:12px;border:1px solid var(--border);background:var(--bg);color:var(--text)}\ninput[type=\"range\"]{width:100%}\n.row{display:flex;gap:12px;align-items:flex-start;flex-wrap:wrap}\n.row > div{flex:1 1 240px;min-width:220px}\n.muted{color:var(--muted);font-size:14px}\n.divider{height:1px;background:var(--border);margin:12px -16px}\n\n.kpi{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px;margin-top:12px}\n.pill{border:1px solid var(--border);background:linear-gradient(180deg,rgba(255,255,255,.02),rgba(0,0,0,.05));border-radius:14px;padding:10px 12px}\n.pill h3{margin:0 0 6px;font-size:15px;color:var(--muted);font-weight:600}\n.big{font-size:24px;font-weight:800}\n.headline{font-size:26px;font-weight:900;line-height:1.15;margin:0 0 4px}\n/* Limit the primary outline to KPI pills only */\n.pill.primary{ outline:2px solid var(--brand); }\n.btn{appearance:none;border:1px solid var(--border);background:var(--brand);color:white;padding:10px 14px;border-radius:12px;cursor:pointer}\n.btn.secondary{background:transparent;color:var(--text)}\n\n.cardlist{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}\n.gift{border:1px solid var(--border);border-radius:12px;padding:12px}\n.gift h4{margin:0 0 6px}\n.link{background:none;border:0;color:var(--brand);cursor:pointer;text-decoration:underline;padding:0}\n.hero{margin:4px 0 0 60px}\n\n/* Adjust hero spacing on small screens */\n@media (max-width:600px){\n .hero{ margin:8px 0 0 0 }\n}\n\n.warn{background:rgba(255,107,107,.1);border:1px solid var(--danger);color:var(--danger);padding:8px 10px;border-radius:10px;margin:8px 0}\n\n/* Plan lanes */\n.plan{margin-top:12px}\n.lane{border:1px solid var(--border);border-radius:12px;padding:12px;margin:8px 0;background:linear-gradient(180deg,rgba(255,255,255,.02),rgba(0,0,0,.04))}\n.lane h4{margin:0 0 6px;font-size:15px;color:var(--muted)}\n.lane ul{margin:0;padding-left:18px}\n.lane li{margin:4px 0}\n\n/* Splash */\n.splash{\n position:fixed; inset:0; display:grid; place-items:center;\n background:radial-gradient(1000px 500px at 20% 10%, rgba(255,255,255,.06), transparent),\n radial-gradient(1000px 500px at 80% 90%, rgba(255,255,255,.05), transparent),\n var(--bg);\n z-index:9999; transition:opacity .5s ease; opacity:1;\n}\n.splash.hide{ opacity:0; pointer-events:none }\n.splash .logoWrap{ display:grid; place-items:center; border-radius:20px; filter:drop-shadow(0 6px 16px rgba(0,0,0,.45)); }\n\n/* Support both class and id for the splash container */\n#splash,\n.splash {\n position: fixed;\n inset: 0;\n display: grid;\n place-items: center;\n /* keep your existing gradient/background via the class rule */\n padding: env(safe-area-inset-top) env(safe-area-inset-right)\n env(safe-area-inset-bottom) env(safe-area-inset-left);\n z-index: 9999;\n}\n\n#splash.hide,\n.splash.hide {\n opacity: 0;\n pointer-events: none;\n}\n\n/* Constrain the logo robustly on all devices */\n#splash .logoWrap img,\n.splash .logoWrap img {\n width: auto;\n height: auto;\n max-width: clamp(160px, 60vw, 420px);\n max-height: 60vh;\n object-fit: contain;\n image-rendering: auto;\n}\n\n/* Make the logo a bit smaller on very short screens (e.g., landscape phones) */\n@media (max-height: 540px) {\n #splash .logoWrap img,\n .splash .logoWrap img {\n max-width: clamp(140px, 50vw, 360px);\n max-height: 50vh;\n }\n}\n\n/* Respect reduced-motion preferences (optional) */\n@media (prefers-reduced-motion: reduce) {\n #splash,\n .splash {\n transition: none !important;\n }\n}\n/* === Barkday Button Bar v1 === */\n.btnbar-mount{ margin-top:12px }\n\n.btn-bar{\n display:grid;\n grid-template-columns:repeat(auto-fit, minmax(180px, 1fr));\n gap:var(--gap);\n align-items:stretch;\n}\n\n.btn-bar button{\n appearance:none; /* normalize UA styles */\n font-family:inherit; /* avoid fallback jumps */\n font-size:16px;\n line-height:1.2;\n white-space:nowrap; /* prevent wrap → height change */\n min-height:var(--btn-min-h); /* now 48px from the token */\n padding-block:12px; /* lock vertical padding */\n padding-inline:var(--pad);\n border-radius:var(--radius);\n border:1px solid var(--border);\n font-weight:600;\n cursor:pointer;\n box-shadow:var(--shadow);\n transition:transform .02s ease, opacity .15s ease;\n}\n\n.btn-bar button:active{ transform:translateY(1px) }\n\n.btn-bar button.primary{\n background:var(--btn-primary-bg);\n color:var(--btn-primary-fg);\n border-color:#1c62d4;\n}\n\n.btn-bar button.secondary{\n background:var(--btn-secondary-bg);\n color:var(--btn-secondary-fg);\n}\n\n/* Disabled state for bar buttons only */\n.btn-bar button:disabled{\n background:var(--btn-disabled-bg) !important;\n color:var(--btn-disabled-fg) !important;\n cursor:not-allowed;\n opacity:.85;\n box-shadow:none;\n}\n\n/* Stack vertically on phones */\n@media (max-width:480px){\n .btn-bar{ grid-template-columns:1fr }\n}\n\n/* Optional: self-test panel styling */\n.selftest{\n margin-top:1rem;\n padding:1rem;\n border:1px dashed #d1d5db;\n border-radius:10px;\n background:#fafafa;\n}\n.selftest h4{ margin:0 0 .5rem 0 }\n.selftest .row{ display:flex; align-items:center; gap:.5rem; margin:.25rem 0 }\n.selftest .ok{ color:#065f46; font-weight:700 }\n.selftest .fail{ color:#991b1b; font-weight:700 }\n\n/* Optional: Improve accessibility for any disabled button */\nbutton[disabled], .btn[disabled]{\n cursor:not-allowed;\n opacity:.7;\n}\n\n/* Phones: stack, breathe, and avoid crowding */\n@media (max-width: 600px){\n .wrap{ padding:16px } /* a bit less padding than 24px */\n header{ gap:12px; margin-bottom:4px }\n .logoImg{ width:40px } /* smaller header logo on phones */\n\n .row{ gap:10px } /* slightly tighter grid gaps */\n .row > div{ flex:1 1 100%; min-width:0 } /* force single-column inputs */\n .card{ padding:14px; border-radius:14px }\n .divider{ margin:10px -14px }\n\n .kpi{ gap:10px } /* KPI tiles pack nicer */\n .pill{ padding:10px }\n .headline{ font-size:24px } /* a touch smaller to avoid wraps */\n\n .cardlist{ grid-template-columns:1fr } /* gifts/cards one-per-row */\n .btnbar-mount{ margin-top:10px }\n .btn-bar{ grid-template-columns:1fr } /* button bar single column */\n .btn-bar button{ min-height:48px } /* comfy tap target */\n}\n\n@media (max-width: 360px){\n .wrap{ padding:12px }\n h1{ font-size:22px }\n h2{ font-size:17px }\n .big{ font-size:22px }\n .btn-bar button{ padding:10px } /* prevent text wrapping on buttons */\n}\n\n/* Touch polish */\nbutton, .btn, .btn-bar button, input, select {\n -webkit-tap-highlight-color: transparent;\n}\n\n/* Visible, consistent focus states (keyboard/switch users) */\n:focus-visible{\n outline:2px solid var(--brand);\n outline-offset:2px;\n border-radius:8px;\n}\n\n@supports (padding: max(0px)) {\n body{\n padding-left: max(0px, env(safe-area-inset-left));\n padding-right: max(0px, env(safe-area-inset-right));\n }\n}\n\nhtml, body{ overflow-x:hidden }\n.card, .kpi, .cardlist{ min-width:0 }\n\n/* Tablets: two-up cards look better than single column */\n@media (min-width: 601px) and (max-width: 900px){\n .cardlist{ grid-template-columns:repeat(2, minmax(0,1fr)) }\n}\n\n/* Button Bar sizing lock */\n.btnbar-mount .btn-bar button {\n font-size: 16px; /* lock font metrics */\n line-height: 1.25; /* prevent compressed text lines */\n padding: 12px 16px; /* consistent height/feel */\n min-height: 44px; /* accessible target */\n box-sizing: border-box; /* avoid growth via borders */\n}\n/* === Slider tooltip (floating value over thumb) === */\n.slider-wrap {\n position: relative;\n width: 100%;\n}\n.slider-wrap input[type=\"range\"] {\n width: 100%;\n}\n\n/* Bubble */\n.slider-tooltip{\n position: absolute;\n top: -38px; /* distance above slider track */\n left: 0; /* JS sets left in px; center via translateX(-50%) */\n transform: translateX(-50%);\n background: #222;\n color: #fff;\n padding: 4px 10px;\n border-radius: 8px;\n font-size: 0.9rem;\n line-height: 1.2;\n white-space: nowrap;\n pointer-events: none;\n box-shadow: 0 2px 6px rgba(0,0,0,.25);\n z-index: 2;\n}\n\n/* Pointer triangle */\n.slider-tooltip::after{\n content:\"\";\n position:absolute;\n bottom:-6px;\n left:50%;\n transform:translateX(-50%);\n border-width:6px 6px 0 6px;\n border-style:solid;\n border-color:#222 transparent transparent transparent;\n}\n\n/* === Slider tooltip (floating value over thumb) === */\n.slider-wrap {\n position: relative;\n width: 100%;\n}\n.slider-wrap input[type=\"range\"] {\n width: 100%;\n}\n\n/* Bubble */\n.slider-tooltip {\n position: absolute;\n top: -80px; /* distance above slider track */\n left: 0; /* JS sets left in px */\n transform: translateX(-50%);\n background: #222;\n color: #fff;\n padding: 4px 10px;\n border-radius: 8px;\n font-size: 0.9rem;\n line-height: 1.2;\n white-space: nowrap;\n pointer-events: none;\n box-shadow: 0 2px 6px rgba(0,0,0,.25);\n z-index: 2;\n\n /* Hidden by default */\n opacity: 0;\n transition: opacity .15s ease;\n}\n\n/* Pointer triangle */\n.slider-tooltip::after {\n content: \"\";\n position: absolute;\n bottom: -6px;\n left: 50%;\n transform: translateX(-50%);\n border-width: 6px 6px 0 6px;\n border-style: solid;\n border-color: #222 transparent transparent transparent;\n}\n\n/* Visibility toggles */\n.slider-tooltip.is-visible {\n opacity: 1;\n}\n.slider-tooltip.is-hidden {\n opacity: 0;\n}\n\n/* ===== Barkday Results Modal ===== */\n.bd-modal{position:fixed;inset:0;display:none;z-index:1000}\n.bd-modal.is-open{display:block}\n.bd-backdrop{position:absolute;inset:0;background:rgba(0,0,0,.45)}\n.bd-dialog{\n position:relative;max-width:680px;margin:6vh auto;background:var(--card);\n color:var(--text);border-radius:16px;box-shadow:var(--shadow);\n padding:16px;outline:none\n}\n@media (max-width:720px){.bd-dialog{margin:4vh 16px}}\n.bd-header{padding:8px 12px 4px}\n.bd-header h2{margin:0;font-size:1.25rem;line-height:1.2}\n.bd-body{padding:12px}\n.bd-footer{display:flex;justify-content:flex-end;gap:8px;padding:8px 12px}\n.bd-close{\n position:absolute;top:6px;right:8px;border:0;background:transparent;\n color:var(--muted);font-size:28px;line-height:1;cursor:pointer\n}\n.bd-close:hover{color:var(--text)}\n.bd-action{\n background:var(--btn-primary-bg);color:var(--btn-primary-fg);\n border:1px solid #1c62d4;border-radius:10px;padding:10px 16px;font-weight:600;cursor:pointer\n}\n/* Lock page scroll when modal is open */\n.body-lock{overflow:hidden}\n\n/* ===== Barkday Toast (Round 2) ===== */\n.bd-toast{\n position:fixed;\n left:50%;\n bottom:22px;\n transform:translateX(-50%);\n background:var(--card, #111827);\n color:var(--text, #e5e7eb);\n border:1px solid var(--border, #2a2f3a);\n border-radius:12px;\n padding:10px 14px;\n font-size:.95rem;\n box-shadow:var(--shadow, 0 10px 25px rgba(0,0,0,.35));\n display:none;\n z-index:1100;\n}\n.bd-toast.show{ display:block; animation:bd-toast-in .18s ease-out }\n@keyframes bd-toast-in{ from{ opacity:0; transform:translateX(-50%) translateY(6px) } to{ opacity:1; transform:translateX(-50%) translateY(0) } }\n.bd-toast .bd-x{\n margin-left:10px;\n border:0;\n background:transparent;\n color:inherit;\n font-size:1.1rem;\n cursor:pointer;\n}\n\n/* ===== Barkday Saved Results Drawer (Round 3) ===== */\n.bd-drawer{position:fixed;inset:0;display:none;z-index:1000}\n.bd-drawer.is-open{display:block}\n.bd-drawer .bd-backdrop{position:absolute;inset:0;background:rgba(0,0,0,.45)}\n.bd-panel{\n position:absolute;right:0;top:0;height:100%;width:min(520px,92vw);\n background:var(--card);color:var(--text);box-shadow:var(--shadow);\n border-left:1px solid var(--border,#2a2f3a);display:flex;flex-direction:column\n}\n.bd-panel header{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--border,#2a2f3a)}\n.bd-panel header h3{margin:0;font-size:1.1rem}\n.bd-panel .bd-body{padding:10px 14px;overflow:auto;flex:1}\n.bd-panel .bd-footer{padding:10px 14px;border-top:1px solid var(--border,#2a2f3a);display:flex;gap:8px;justify-content:flex-end}\n.bd-card{\n border:1px solid var(--border,#2a2f3a);border-radius:12px;padding:10px 12px;margin:8px 0\n}\n.bd-card h4{margin:0 0 4px 0;font-size:1rem}\n.bd-card .muted{font-size:.9rem}\n.bd-row{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}\n.bd-row .btn{border:1px solid #3a67d3;background:var(--btn-primary-bg,#1d4ed8);color:var(--btn-primary-fg,#fff);border-radius:10px;padding:8px 12px;font-weight:600;cursor:pointer}\n.bd-row .ghost{border:1px solid var(--border,#2a2f3a);background:transparent;color:var(--text);border-radius:10px;padding:8px 12px;cursor:pointer}\n.bd-close-x{border:0;background:transparent;font-size:24px;cursor:pointer;color:var(--muted)}\n.bd-close-x:hover{color:var(--text)}\n\n/* Tell browsers how to render built-in controls */\n:root[data-theme=\"light\"] { color-scheme: light; }\n:root[data-theme=\"dark\"] { color-scheme: dark; }\n\n/* Make the text box itself match your theme */\n:root[data-theme=\"dark\"] input[type=\"date\"] {\n background:#0f1115;\n color:#e8eef6;\n border-color:#2a2f3a;\n}\n:root[data-theme=\"light\"] input[type=\"date\"] {\n background:#fff;\n color:#111;\n border-color:#ddd;\n}\n\n/* Chrome/Safari (WebKit): make the calendar icon visible in dark mode */\n:root[data-theme=\"dark\"] input[type=\"date\"]::-webkit-calendar-picker-indicator {\n filter: invert(1) opacity(0.85);\n}\n\n/* Optional: tweak inner spin/clear buttons on WebKit */\n:root[data-theme=\"dark\"] input[type=\"date\"]::-webkit-clear-button,\n:root[data-theme=\"dark\"] input[type=\"date\"]::-webkit-inner-spin-button {\n filter: invert(1) opacity(0.85);\n}\n.bd-info{background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px;padding:12px 14px;margin:8px 0 14px;color:#374151;font-size:.95rem;line-height:1.35}\n.bd-info strong,.bd-info em{color:#111827;font-style:normal}\n\n/* --- Saved status pill under the Name field --- */\n.status-pill{\n display:inline-block;\n margin-top:6px;\n padding:6px 10px;\n border-radius:999px;\n font-size:.9rem;\n line-height:1.1;\n background: color-mix(in oklab, var(--accent) 18%, transparent);\n border: 1px solid color-mix(in oklab, var(--accent) 45%, var(--border));\n color: var(--text);\n cursor:pointer; /* opens Saved drawer */\n box-shadow: var(--shadow);\n}\n.status-pill.saving{\n background: color-mix(in oklab, var(--brand) 18%, transparent);\n border-color: color-mix(in oklab, var(--brand) 45%, var(--border));\n}\n.status-pill.error{\n background: color-mix(in oklab, var(--danger) 18%, transparent);\n border-color: color-mix(in oklab, var(--danger) 45%, var(--border));\n}\n\n@media (pointer:coarse){\n .status-pill{ padding:8px 12px; } /* friendlier on Android touch */\n}\n@media (max-width:600px){\n #btnBarMount #btnSaved{ display:none; }\n}\n\n/* Hide the legacy Saved button (replaced by the new pill under Name) */\n#btnSaved { display: none !important; }\n\n/* --- 1.0 visual polish: Save pill and top buttons (no logic changes) --- */\n\n/* Save pill look-and-feel */\n#saveStatus{\n display:inline-block;\n margin-top:6px;\n padding:6px 10px;\n font:13px/1.2 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;\n border-radius:999px;\n border:1px solid #d0d0d0;\n background:#f7f7f7;\n color:#222;\n vertical-align:middle;\n user-select:none;\n}\n\n/* Button bar polish without changing layout */\n#btnBarMount button{\n padding:8px 14px;\n margin:4px 6px 0 0;\n font:14px/1.2 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;\n border-radius:10px;\n border:1px solid #d3d3d3;\n background:#ffffff;\n color:#222;\n box-shadow:0 1px 2px rgba(0,0,0,0.06);\n cursor:pointer;\n transition:transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease;\n}\n\n#btnBarMount button:hover{\n transform:translateY(-1px);\n box-shadow:0 3px 8px rgba(0,0,0,0.08);\n border-color:#c0c0c0;\n}\n\n#btnBarMount button:active{\n transform:translateY(0);\n box-shadow:0 1px 3px rgba(0,0,0,0.12);\n}\n\n#btnBarMount button:focus{\n outline:2px solid transparent;\n box-shadow:0 0 0 3px rgba(0, 120, 212, 0.35);\n}\n\n#btnBarMount button[disabled],\n#btnBarMount button[aria-disabled=\"true\"]{\n opacity:0.55;\n cursor:not-allowed;\n}\n\n/* Gift loader spacing to avoid crowding controls */\n#loadGifts{ margin-top:8px; }\n#gifts{ margin-top:10px; }\n\n/* 1.0 Save pill state colors */\n#saveStatus.status-pill{\n transition: background 120ms ease, border-color 120ms ease, box-shadow 120ms ease, color 120ms ease;\n}\n\n#saveStatus.status-pill.saving{\n background:#fffbe6; /* soft yellow */\n border-color:#f0d36b;\n}\n\n#saveStatus.status-pill.saved{\n background:#e9fff0; /* soft green */\n border-color:#b8e6c5;\n}\n\n#saveStatus.status-pill.error{\n background:#ffecec; /* soft red */\n border-color:#f0a8a8;\n color:#7a0000;\n}\n","inline_bytes":18428,"content_sha256":"7db95baf64be41772d327ec5b26b15e6d4640bc2c68e97080a4fd715862be4bd"},{"path":"terms.html","size":1125,"sha":"e1e8737dee9de7c52d92e81a349ea648bdcea617","media_type":"text/html","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/terms.html","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/terms.html","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"\n\n\n \n \n Barkday™ • Terms of Use\n \n \n \n\n\n

Barkday™ Terms of Use

\n

Last updated: September 21, 2025

\n\n

No Veterinary Advice

\n

Barkday provides informational tools only. It is not a substitute for professional veterinary advice, diagnosis, or treatment.

\n\n

Affiliate Disclosure

\n

As an Amazon Associate I may earn from qualifying purchases. Chewy affiliate links will be disclosed once active.

\n\n

Trademarks

\n

BARKDAY™ is a pending trademark of the project owner. All other marks belong to their respective owners.

\n\n

Liability

\n

The app is provided “as is” without warranties of any kind. Use at your own risk.

\n\n

← Back to Barkday

\n\n\n","inline_bytes":1111,"content_sha256":"70dc96f18f429fd73eea883245772053be7e7caa65f627742ebfb61831916023"},{"path":"tests/barkday_curve_test.html","size":5549,"sha":"28263fb2299a9ea5161af4c639d05921bbbbd3d5","media_type":"text/html","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tests/barkday_curve_test.html","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tests/barkday_curve_test.html","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"utf8","content":"\r\n\r\n\r\n \r\n Barkday™ Curve Test Harness\r\n \r\n \r\n\r\n\r\n

Barkday™ Curve Test Harness

\r\n
Preview of LOCT (15/9) + smooth analytic (PCHIP) Bark Day curve output.
\r\n\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n \r\n
\r\n
\r\n\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
#Bark Day (k)t (human years)Δ days from prevDate
\r\n\r\n \r\n\r\n\r\n","inline_bytes":5534,"content_sha256":"845f95f2b178fc8c2af9fd72d94bd680c97bde54624e182f1509da361b2e6e0d"},{"path":"tools/amazon-get-items.ps1","size":3349,"sha":"cefded64ff46419ea45cc8b29f97920c6a1f0ad8","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tools/amazon-get-items.ps1","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tools/amazon-get-items.ps1","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"cGFyYW0oCiAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogIFtzdHJpbmdbXV0kSXRlbUlkcywKCiAgW3N0cmluZ10kT3V0RmlsZSA9ICIiLAoKICBbc3RyaW5nW11dJFJlc291cmNlcyA9IEAoCiAgICAiaW1hZ2VzLnByaW1hcnkuc21hbGwiLAogICAgIml0ZW1JbmZvLnRpdGxlIiwKICAgICJpdGVtSW5mby5mZWF0dXJlcyIKICApCikKCiRFcnJvckFjdGlvblByZWZlcmVuY2UgPSAiU3RvcCIKCmZ1bmN0aW9uIEdldC1Ub2tlbkVuZHBvaW50IHsKICBwYXJhbShbc3RyaW5nXSRWZXJzaW9uKQogIHN3aXRjaCAtUmVnZXggKCRWZXJzaW9uKSB7CiAgICAnXjJcLjEkJyB7IHJldHVybiAnaHR0cHM6Ly9jcmVhdG9yc2FwaS5hdXRoLnVzLWVhc3QtMS5hbWF6b25jb2duaXRvLmNvbS9vYXV0aDIvdG9rZW4nIH0KICAgICdeMlwuMiQnIHsgcmV0dXJuICdodHRwczovL2NyZWF0b3JzYXBpLmF1dGguZXUtc291dGgtMi5hbWF6b25jb2duaXRvLmNvbS9vYXV0aDIvdG9rZW4nIH0KICAgICdeMlwuMyQnIHsgcmV0dXJuICdodHRwczovL2NyZWF0b3JzYXBpLmF1dGgudXMtd2VzdC0yLmFtYXpvbmNvZ25pdG8uY29tL29hdXRoMi90b2tlbicgfQogICAgJ14zXC4xJCcgeyByZXR1cm4gJ2h0dHBzOi8vYXBpLmFtYXpvbi5jb20vYXV0aC9vMi90b2tlbicgfQogICAgJ14zXC4yJCcgeyByZXR1cm4gJ2h0dHBzOi8vYXBpLmFtYXpvbi5jby51ay9hdXRoL28yL3Rva2VuJyB9CiAgICAnXjNcLjMkJyB7IHJldHVybiAnaHR0cHM6Ly9hcGkuYW1hem9uLmNvLmpwL2F1dGgvbzIvdG9rZW4nIH0KICAgIGRlZmF1bHQgeyB0aHJvdyAiVW5zdXBwb3J0ZWQgQ1JFQVRPUlNfVkVSU0lPTjogJFZlcnNpb24iIH0KICB9Cn0KCmZ1bmN0aW9uIEdldC1DcmVhdG9yc1Rva2VuIHsKICAkY3JlZGVudGlhbElkID0gJGVudjpDUkVBVE9SU19DUkVERU5USUFMX0lECiAgJGNyZWRlbnRpYWxTZWNyZXQgPSAkZW52OkNSRUFUT1JTX0NSRURFTlRJQUxfU0VDUkVUCiAgJHZlcnNpb24gPSAkZW52OkNSRUFUT1JTX1ZFUlNJT04KCiAgaWYgKC1ub3QgJGNyZWRlbnRpYWxJZCAtb3IgLW5vdCAkY3JlZGVudGlhbFNlY3JldCAtb3IgLW5vdCAkdmVyc2lvbikgewogICAgdGhyb3cgIk1pc3Npbmcgb25lIG9yIG1vcmUgZW52IHZhcnM6IENSRUFUT1JTX0NSRURFTlRJQUxfSUQsIENSRUFUT1JTX0NSRURFTlRJQUxfU0VDUkVULCBDUkVBVE9SU19WRVJTSU9OIgogIH0KCiAgJHVyaSA9IEdldC1Ub2tlbkVuZHBvaW50IC1WZXJzaW9uICR2ZXJzaW9uCgogIGlmICgkdmVyc2lvbiAtbGlrZSAnMy4qJykgewogICAgJGJvZHkgPSBAewogICAgICBncmFudF90eXBlICAgID0gImNsaWVudF9jcmVkZW50aWFscyIKICAgICAgY2xpZW50X2lkICAgICA9ICRjcmVkZW50aWFsSWQKICAgICAgY2xpZW50X3NlY3JldCA9ICRjcmVkZW50aWFsU2VjcmV0CiAgICAgIHNjb3BlICAgICAgICAgPSAiY3JlYXRvcnNhcGk6OmRlZmF1bHQiCiAgICB9IHwgQ29udmVydFRvLUpzb24KICAgIHJldHVybiBJbnZva2UtUmVzdE1ldGhvZCAtTWV0aG9kIFBvc3QgLVVyaSAkdXJpIC1Db250ZW50VHlwZSAiYXBwbGljYXRpb24vanNvbiIgLUJvZHkgJGJvZHkKICB9IGVsc2UgewogICAgJGJvZHkgPSAiZ3JhbnRfdHlwZT1jbGllbnRfY3JlZGVudGlhbHMmY2xpZW50X2lkPSRjcmVkZW50aWFsSWQmY2xpZW50X3NlY3JldD0kY3JlZGVudGlhbFNlY3JldCZzY29wZT1jcmVhdG9yc2FwaS9kZWZhdWx0IgogICAgcmV0dXJuIEludm9rZS1SZXN0TWV0aG9kIC1NZXRob2QgUG9zdCAtVXJpICR1cmkgLUNvbnRlbnRUeXBlICJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiIC1Cb2R5ICRib2R5CiAgfQp9CgokbWFya2V0cGxhY2UgPSAkZW52OkNSRUFUT1JTX01BUktFVFBMQUNFCiRwYXJ0bmVyVGFnID0gJGVudjpDUkVBVE9SU19QQVJUTkVSX1RBRwokdmVyc2lvbiA9ICRlbnY6Q1JFQVRPUlNfVkVSU0lPTgoKaWYgKC1ub3QgJG1hcmtldHBsYWNlIC1vciAtbm90ICRwYXJ0bmVyVGFnIC1vciAtbm90ICR2ZXJzaW9uKSB7CiAgdGhyb3cgIk1pc3Npbmcgb25lIG9yIG1vcmUgZW52IHZhcnM6IENSRUFUT1JTX01BUktFVFBMQUNFLCBDUkVBVE9SU19QQVJUTkVSX1RBRywgQ1JFQVRPUlNfVkVSU0lPTiIKfQoKaWYgKCRJdGVtSWRzLkNvdW50IC1ndCAxMCkgewogIHRocm93ICJHZXRJdGVtcyBzdXBwb3J0cyB1cCB0byAxMCBBU0lOcyBwZXIgcmVxdWVzdC4iCn0KCiR0b2tlbiA9IEdldC1DcmVhdG9yc1Rva2VuCiRhdXRoSGVhZGVyID0KICBpZiAoJHZlcnNpb24gLWxpa2UgJzIuKicpIHsKICAgICJCZWFyZXIgJCgkdG9rZW4uYWNjZXNzX3Rva2VuKSwgVmVyc2lvbiAkdmVyc2lvbiIKICB9IGVsc2UgewogICAgIkJlYXJlciAkKCR0b2tlbi5hY2Nlc3NfdG9rZW4pIgogIH0KCiRoZWFkZXJzID0gQHsKICBBdXRob3JpemF0aW9uID0gJGF1dGhIZWFkZXIKICAieC1tYXJrZXRwbGFjZSIgPSAkbWFya2V0cGxhY2UKfQoKJHBheWxvYWQgPSBAewogIGl0ZW1JZHMgICAgID0gJEl0ZW1JZHMKICBpdGVtSWRUeXBlICA9ICJBU0lOIgogIG1hcmtldHBsYWNlID0gJG1hcmtldHBsYWNlCiAgcGFydG5lclRhZyAgPSAkcGFydG5lclRhZwogIHJlc291cmNlcyAgID0gJFJlc291cmNlcwp9CgokanNvbiA9ICRwYXlsb2FkIHwgQ29udmVydFRvLUpzb24gLURlcHRoIDgKJHJlc3BvbnNlID0gSW52b2tlLVJlc3RNZXRob2QgYAogIC1NZXRob2QgUG9zdCBgCiAgLVVyaSAiaHR0cHM6Ly9jcmVhdG9yc2FwaS5hbWF6b24vY2F0YWxvZy92MS9nZXRJdGVtcyIgYAogIC1IZWFkZXJzICRoZWFkZXJzIGAKICAtQ29udGVudFR5cGUgImFwcGxpY2F0aW9uL2pzb24iIGAKICAtQm9keSAkanNvbgoKaWYgKC1ub3QgJE91dEZpbGUpIHsKICAkc2FmZSA9ICgkSXRlbUlkcyAtam9pbiAnLScpLlN1YnN0cmluZygwLCBbTWF0aF06Ok1pbig1MCwgKCRJdGVtSWRzIC1qb2luICctJykuTGVuZ3RoKSkKICAkT3V0RmlsZSA9ICIuXGdldGl0ZW1zLSRzYWZlLmpzb24iCn0KCiRyZXNwb25zZSB8IENvbnZlcnRUby1Kc29uIC1EZXB0aCAyMCB8IFNldC1Db250ZW50IC1QYXRoICRPdXRGaWxlIC1FbmNvZGluZyBVVEY4CgpXcml0ZS1Ib3N0ICJTYXZlZCBHZXRJdGVtcyByZXNwb25zZSB0byAkT3V0RmlsZSIKJHJvd3MgPSBAKCkKZm9yZWFjaCAoJGl0ZW0gaW4gJHJlc3BvbnNlLml0ZW1zUmVzdWx0Lml0ZW1zKSB7CiAgJHJvd3MgKz0gW3BzY3VzdG9tb2JqZWN0XUB7CiAgICBBU0lOICA9ICRpdGVtLmFzaW4KICAgIFRpdGxlID0gJGl0ZW0uaXRlbUluZm8udGl0bGUuZGlzcGxheVZhbHVlCiAgICBVUkwgICA9ICRpdGVtLmRldGFpbFBhZ2VVUkwKICB9Cn0KJHJvd3MgfCBGb3JtYXQtVGFibGUgLUF1dG9TaXplCg==","inline_bytes":4468,"content_sha256":"bc8994dec6635f5000c477e74f17553557ba5ab5dc007c4fb2b6d04934771883"},{"path":"tools/amazon-search-items.ps1","size":3619,"sha":"f46f2b31f6b579afdbd529f919aed5df57c2bf6c","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tools/amazon-search-items.ps1","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tools/amazon-search-items.ps1","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"cGFyYW0oCiAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogIFtzdHJpbmddJEtleXdvcmRzLAoKICBbaW50XSRJdGVtQ291bnQgPSAxMCwKCiAgW3N0cmluZ10kU2VhcmNoSW5kZXggPSAiUGV0U3VwcGxpZXMiLAoKICBbc3RyaW5nXSRCcmFuZCwKCiAgW3N0cmluZ10kQnJvd3NlTm9kZUlkLAoKICBbc3RyaW5nXSRPdXRGaWxlID0gIiIsCgogIFtzdHJpbmdbXV0kUmVzb3VyY2VzID0gQCgKICAgICJpbWFnZXMucHJpbWFyeS5zbWFsbCIsCiAgICAiaXRlbUluZm8udGl0bGUiLAogICAgIml0ZW1JbmZvLmZlYXR1cmVzIgogICkKKQoKJEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICJTdG9wIgoKZnVuY3Rpb24gR2V0LVRva2VuRW5kcG9pbnQgewogIHBhcmFtKFtzdHJpbmddJFZlcnNpb24pCiAgc3dpdGNoIC1SZWdleCAoJFZlcnNpb24pIHsKICAgICdeMlwuMSQnIHsgcmV0dXJuICdodHRwczovL2NyZWF0b3JzYXBpLmF1dGgudXMtZWFzdC0xLmFtYXpvbmNvZ25pdG8uY29tL29hdXRoMi90b2tlbicgfQogICAgJ14yXC4yJCcgeyByZXR1cm4gJ2h0dHBzOi8vY3JlYXRvcnNhcGkuYXV0aC5ldS1zb3V0aC0yLmFtYXpvbmNvZ25pdG8uY29tL29hdXRoMi90b2tlbicgfQogICAgJ14yXC4zJCcgeyByZXR1cm4gJ2h0dHBzOi8vY3JlYXRvcnNhcGkuYXV0aC51cy13ZXN0LTIuYW1hem9uY29nbml0by5jb20vb2F1dGgyL3Rva2VuJyB9CiAgICAnXjNcLjEkJyB7IHJldHVybiAnaHR0cHM6Ly9hcGkuYW1hem9uLmNvbS9hdXRoL28yL3Rva2VuJyB9CiAgICAnXjNcLjIkJyB7IHJldHVybiAnaHR0cHM6Ly9hcGkuYW1hem9uLmNvLnVrL2F1dGgvbzIvdG9rZW4nIH0KICAgICdeM1wuMyQnIHsgcmV0dXJuICdodHRwczovL2FwaS5hbWF6b24uY28uanAvYXV0aC9vMi90b2tlbicgfQogICAgZGVmYXVsdCB7IHRocm93ICJVbnN1cHBvcnRlZCBDUkVBVE9SU19WRVJTSU9OOiAkVmVyc2lvbiIgfQogIH0KfQoKZnVuY3Rpb24gR2V0LUNyZWF0b3JzVG9rZW4gewogICRjcmVkZW50aWFsSWQgPSAkZW52OkNSRUFUT1JTX0NSRURFTlRJQUxfSUQKICAkY3JlZGVudGlhbFNlY3JldCA9ICRlbnY6Q1JFQVRPUlNfQ1JFREVOVElBTF9TRUNSRVQKICAkdmVyc2lvbiA9ICRlbnY6Q1JFQVRPUlNfVkVSU0lPTgoKICBpZiAoLW5vdCAkY3JlZGVudGlhbElkIC1vciAtbm90ICRjcmVkZW50aWFsU2VjcmV0IC1vciAtbm90ICR2ZXJzaW9uKSB7CiAgICB0aHJvdyAiTWlzc2luZyBvbmUgb3IgbW9yZSBlbnYgdmFyczogQ1JFQVRPUlNfQ1JFREVOVElBTF9JRCwgQ1JFQVRPUlNfQ1JFREVOVElBTF9TRUNSRVQsIENSRUFUT1JTX1ZFUlNJT04iCiAgfQoKICAkdXJpID0gR2V0LVRva2VuRW5kcG9pbnQgLVZlcnNpb24gJHZlcnNpb24KCiAgaWYgKCR2ZXJzaW9uIC1saWtlICczLionKSB7CiAgICAkYm9keSA9IEB7CiAgICAgIGdyYW50X3R5cGUgICAgPSAiY2xpZW50X2NyZWRlbnRpYWxzIgogICAgICBjbGllbnRfaWQgICAgID0gJGNyZWRlbnRpYWxJZAogICAgICBjbGllbnRfc2VjcmV0ID0gJGNyZWRlbnRpYWxTZWNyZXQKICAgICAgc2NvcGUgICAgICAgICA9ICJjcmVhdG9yc2FwaTo6ZGVmYXVsdCIKICAgIH0gfCBDb252ZXJ0VG8tSnNvbgogICAgcmV0dXJuIEludm9rZS1SZXN0TWV0aG9kIC1NZXRob2QgUG9zdCAtVXJpICR1cmkgLUNvbnRlbnRUeXBlICJhcHBsaWNhdGlvbi9qc29uIiAtQm9keSAkYm9keQogIH0gZWxzZSB7CiAgICAkYm9keSA9ICJncmFudF90eXBlPWNsaWVudF9jcmVkZW50aWFscyZjbGllbnRfaWQ9JGNyZWRlbnRpYWxJZCZjbGllbnRfc2VjcmV0PSRjcmVkZW50aWFsU2VjcmV0JnNjb3BlPWNyZWF0b3JzYXBpL2RlZmF1bHQiCiAgICByZXR1cm4gSW52b2tlLVJlc3RNZXRob2QgLU1ldGhvZCBQb3N0IC1VcmkgJHVyaSAtQ29udGVudFR5cGUgImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCIgLUJvZHkgJGJvZHkKICB9Cn0KCiRtYXJrZXRwbGFjZSA9ICRlbnY6Q1JFQVRPUlNfTUFSS0VUUExBQ0UKJHBhcnRuZXJUYWcgPSAkZW52OkNSRUFUT1JTX1BBUlRORVJfVEFHCiR2ZXJzaW9uID0gJGVudjpDUkVBVE9SU19WRVJTSU9OCgppZiAoLW5vdCAkbWFya2V0cGxhY2UgLW9yIC1ub3QgJHBhcnRuZXJUYWcgLW9yIC1ub3QgJHZlcnNpb24pIHsKICB0aHJvdyAiTWlzc2luZyBvbmUgb3IgbW9yZSBlbnYgdmFyczogQ1JFQVRPUlNfTUFSS0VUUExBQ0UsIENSRUFUT1JTX1BBUlRORVJfVEFHLCBDUkVBVE9SU19WRVJTSU9OIgp9CgokdG9rZW4gPSBHZXQtQ3JlYXRvcnNUb2tlbgoKJGF1dGhIZWFkZXIgPQogIGlmICgkdmVyc2lvbiAtbGlrZSAnMi4qJykgewogICAgIkJlYXJlciAkKCR0b2tlbi5hY2Nlc3NfdG9rZW4pLCBWZXJzaW9uICR2ZXJzaW9uIgogIH0gZWxzZSB7CiAgICAiQmVhcmVyICQoJHRva2VuLmFjY2Vzc190b2tlbikiCiAgfQoKJGhlYWRlcnMgPSBAewogIEF1dGhvcml6YXRpb24gPSAkYXV0aEhlYWRlcgogICJ4LW1hcmtldHBsYWNlIiA9ICRtYXJrZXRwbGFjZQp9CgokcGF5bG9hZCA9IEB7CiAgcGFydG5lclRhZyAgPSAkcGFydG5lclRhZwogIG1hcmtldHBsYWNlID0gJG1hcmtldHBsYWNlCiAga2V5d29yZHMgICAgPSAkS2V5d29yZHMKICBpdGVtQ291bnQgICA9ICRJdGVtQ291bnQKICBzZWFyY2hJbmRleCA9ICRTZWFyY2hJbmRleAogIHJlc291cmNlcyAgID0gJFJlc291cmNlcwp9CgppZiAoJEJyYW5kKSB7ICRwYXlsb2FkLmJyYW5kID0gJEJyYW5kIH0KaWYgKCRCcm93c2VOb2RlSWQpIHsgJHBheWxvYWQuYnJvd3NlTm9kZUlkID0gJEJyb3dzZU5vZGVJZCB9CgokanNvbiA9ICRwYXlsb2FkIHwgQ29udmVydFRvLUpzb24gLURlcHRoIDgKJHJlc3BvbnNlID0gSW52b2tlLVJlc3RNZXRob2QgYAogIC1NZXRob2QgUG9zdCBgCiAgLVVyaSAiaHR0cHM6Ly9jcmVhdG9yc2FwaS5hbWF6b24vY2F0YWxvZy92MS9zZWFyY2hJdGVtcyIgYAogIC1IZWFkZXJzICRoZWFkZXJzIGAKICAtQ29udGVudFR5cGUgImFwcGxpY2F0aW9uL2pzb24iIGAKICAtQm9keSAkanNvbgoKaWYgKC1ub3QgJE91dEZpbGUpIHsKICAkc2FmZSA9ICgkS2V5d29yZHMgLXJlcGxhY2UgJ1teQS1aYS16MC05XSsnLCctJykuVHJpbSgnLScpLlRvTG93ZXIoKQogICRPdXRGaWxlID0gIi5cc2VhcmNoLSRzYWZlLmpzb24iCn0KCiRyZXNwb25zZSB8IENvbnZlcnRUby1Kc29uIC1EZXB0aCAyMCB8IFNldC1Db250ZW50IC1QYXRoICRPdXRGaWxlIC1FbmNvZGluZyBVVEY4CgpXcml0ZS1Ib3N0ICJTYXZlZCBTZWFyY2hJdGVtcyByZXNwb25zZSB0byAkT3V0RmlsZSIKaWYgKCRyZXNwb25zZS5zZWFyY2hSZXN1bHQpIHsKICBXcml0ZS1Ib3N0ICgiVG90YWwgcmVzdWx0czogIiArICRyZXNwb25zZS5zZWFyY2hSZXN1bHQudG90YWxSZXN1bHRDb3VudCkKICAkcm93cyA9IEAoKQogIGZvcmVhY2ggKCRpdGVtIGluICRyZXNwb25zZS5zZWFyY2hSZXN1bHQuaXRlbXMpIHsKICAgICRyb3dzICs9IFtwc2N1c3RvbW9iamVjdF1AewogICAgICBBU0lOICA9ICRpdGVtLmFzaW4KICAgICAgVGl0bGUgPSAkaXRlbS5pdGVtSW5mby50aXRsZS5kaXNwbGF5VmFsdWUKICAgICAgVVJMICAgPSAkaXRlbS5kZXRhaWxQYWdlVVJMCiAgICB9CiAgfQogICRyb3dzIHwgRm9ybWF0LVRhYmxlIC1BdXRvU2l6ZQp9Cg==","inline_bytes":4828,"content_sha256":"bc8035e31988ca5c87bdf08cb025065452a56a7be69791d1ad1c1539815cc380"},{"path":"tools/append-catalog-items.ps1","size":1133,"sha":"2acb06ba527da1e68d2d8cf338d33077902d0cf1","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tools/append-catalog-items.ps1","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tools/append-catalog-items.ps1","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"cGFyYW0oCiAgW1BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgW3N0cmluZ10kQ2F0YWxvZ1BhdGgsCiAgW1BhcmFtZXRlcihNYW5kYXRvcnkgPSAkdHJ1ZSldCiAgW3N0cmluZ10kUGVuZGluZ0l0ZW1zUGF0aAopCgokY2F0YWxvZyA9IEdldC1Db250ZW50ICRDYXRhbG9nUGF0aCAtUmF3IHwgQ29udmVydEZyb20tSnNvbgokbmV3SXRlbXMgPSBHZXQtQ29udGVudCAkUGVuZGluZ0l0ZW1zUGF0aCAtUmF3IHwgQ29udmVydEZyb20tSnNvbgoKJGV4aXN0aW5nSWRzID0gQHt9CiRleGlzdGluZ0FzaW5zID0gQHt9Cgpmb3JlYWNoICgkaXRlbSBpbiAkY2F0YWxvZy5pdGVtcykgewogIGlmICgkaXRlbS5pZCkgeyAkZXhpc3RpbmdJZHNbJGl0ZW0uaWRdID0gJHRydWUgfQogIGlmICgkaXRlbS5hZmZpbGlhdGUgLWFuZCAkaXRlbS5hZmZpbGlhdGUuYXNpbikgewogICAgJGV4aXN0aW5nQXNpbnNbJGl0ZW0uYWZmaWxpYXRlLmFzaW5dID0gJHRydWUKICB9Cn0KCmZvcmVhY2ggKCRpdGVtIGluICRuZXdJdGVtcykgewogIGlmICgtbm90ICRpdGVtLmlkKSB7CiAgICB0aHJvdyAiQSBwZW5kaW5nIGl0ZW0gaXMgbWlzc2luZyBpZC4iCiAgfQogIGlmICgkZXhpc3RpbmdJZHMuQ29udGFpbnNLZXkoJGl0ZW0uaWQpKSB7CiAgICB0aHJvdyAiRHVwbGljYXRlIGlkIGZvdW5kOiAkKCRpdGVtLmlkKSIKICB9CiAgaWYgKCRpdGVtLmFmZmlsaWF0ZSAtYW5kICRpdGVtLmFmZmlsaWF0ZS5hc2luIC1hbmQgJGV4aXN0aW5nQXNpbnMuQ29udGFpbnNLZXkoJGl0ZW0uYWZmaWxpYXRlLmFzaW4pKSB7CiAgICB0aHJvdyAiRHVwbGljYXRlIEFTSU4gZm91bmQ6ICQoJGl0ZW0uYWZmaWxpYXRlLmFzaW4pIgogIH0KfQoKJGNhdGFsb2cuaXRlbXMgKz0gJG5ld0l0ZW1zCiRjYXRhbG9nLmdlbmVyYXRlZEF0ID0gKEdldC1EYXRlKS5Ub1VuaXZlcnNhbFRpbWUoKS5Ub1N0cmluZygieXl5eS1NTS1kZFRISDptbTpzc1oiKQoKJGNhdGFsb2cgfCBDb252ZXJ0VG8tSnNvbiAtRGVwdGggMjAgfCBTZXQtQ29udGVudCAtUGF0aCAkQ2F0YWxvZ1BhdGggLUVuY29kaW5nIFVURjgKCldyaXRlLUhvc3QgIkNhdGFsb2cgdXBkYXRlZC4iCldyaXRlLUhvc3QgIk5ldyBpdGVtIGNvdW50OiIgKCRjYXRhbG9nLml0ZW1zLkNvdW50KQo=","inline_bytes":1512,"content_sha256":"c8c07eca958264ba7dd4d70635229bce5f847806d625d053aea199d5e9bd20c4"},{"path":"tools/run-barkday-checks.ps1","size":1140,"sha":"b7486d4fbe43c16edfb4d2ce5aa5bd480e2cf979","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tools/run-barkday-checks.ps1","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tools/run-barkday-checks.ps1","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"JEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICJTdG9wIgoKV3JpdGUtSG9zdCAiQ2hlY2tpbmcgSmF2YVNjcmlwdCBzeW50YXguLi4iIC1Gb3JlZ3JvdW5kQ29sb3IgQ3lhbgpub2RlIC0tY2hlY2sgLlxhcHAuanMKaWYgKCRMQVNURVhJVENPREUgLW5lIDApIHsgZXhpdCAkTEFTVEVYSVRDT0RFIH0KCm5vZGUgLS1jaGVjayAuXHNjcmlwdHNcYmFya2RheS1kb2N0b3IubWpzCmlmICgkTEFTVEVYSVRDT0RFIC1uZSAwKSB7IGV4aXQgJExBU1RFWElUQ09ERSB9CgpXcml0ZS1Ib3N0ICJgblJlYnVpbGRpbmcgdjIgZ2lmdCBjYXRhbG9nLi4uIiAtRm9yZWdyb3VuZENvbG9yIEN5YW4Kbm9kZSAuXHNjcmlwdHNccmVidWlsZC1naWZ0LWNhdGFsb2cubWpzCmlmICgkTEFTVEVYSVRDT0RFIC1uZSAwKSB7IGV4aXQgJExBU1RFWElUQ09ERSB9CgpXcml0ZS1Ib3N0ICJgblZhbGlkYXRpbmcgdjIgZ2lmdCBjYXRhbG9nLi4uIiAtRm9yZWdyb3VuZENvbG9yIEN5YW4Kbm9kZSAuXHNjcmlwdHNcdmFsaWRhdGUtZ2lmdHMtdjIubWpzIC5cZGF0YVxkb2ctZ2lmdHMtY2F0YWxvZy5qc29uIC5cZGF0YVxkb2ctZ2lmdHMtcHJlZmVycmVkLmpzb24KaWYgKCRMQVNURVhJVENPREUgLW5lIDApIHsgZXhpdCAkTEFTVEVYSVRDT0RFIH0KCldyaXRlLUhvc3QgImBuTWVyZ2luZyB2MiBydW50aW1lIGdpZnQgZmVlZC4uLiIgLUZvcmVncm91bmRDb2xvciBDeWFuCm5vZGUgLlxzY3JpcHRzXG1lcmdlLWdpZnRzLXYyLm1qcyAuXGRhdGFcZG9nLWdpZnRzLWNhdGFsb2cuanNvbiAuXGRhdGFcZG9nLWdpZnRzLXByZWZlcnJlZC5qc29uIC5cZGF0YVxkb2ctZ2lmdHMtbWVyZ2VkLmpzb24KaWYgKCRMQVNURVhJVENPREUgLW5lIDApIHsgZXhpdCAkTEFTVEVYSVRDT0RFIH0KCldyaXRlLUhvc3QgImBuUnVubmluZyBnaWZ0IHNtb2tlIHRlc3RzLi4uIiAtRm9yZWdyb3VuZENvbG9yIEN5YW4Kbm9kZSAuXHNjcmlwdHNcc21va2UtZ2lmdC1sb2dpYy5tanMKaWYgKCRMQVNURVhJVENPREUgLW5lIDApIHsgZXhpdCAkTEFTVEVYSVRDT0RFIH0KCldyaXRlLUhvc3QgImBuUnVubmluZyBCYXJrZGF5IGRvY3Rvci4uLiIgLUZvcmVncm91bmRDb2xvciBDeWFuCm5vZGUgLlxzY3JpcHRzXGJhcmtkYXktZG9jdG9yLm1qcwpleGl0ICRMQVNURVhJVENPREUK","inline_bytes":1520,"content_sha256":"123a38e557511057d5c3dc348f931991edbfa8d4021494ed9ddb2e37ae4be182"},{"path":"tools/verify.ps1","size":6112,"sha":"7c492e828a7dc3dae23527d0938fd1acbbae08d8","media_type":"application/octet-stream","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tools/verify.ps1","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/tools/verify.ps1","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"JEVycm9yQWN0aW9uUHJlZmVyZW5jZSA9ICJTdG9wIgoKZnVuY3Rpb24gU3RhbXAoJG1zZykgewogICR0cyA9IEdldC1EYXRlIC1Gb3JtYXQgInl5eXktTU0tZGQgSEg6bW06c3MiCiAgV3JpdGUtSG9zdCAiWyR0c10gJG1zZyIKfQoKJHJlcG9Sb290ID0gUmVzb2x2ZS1QYXRoIChKb2luLVBhdGggJFBTU2NyaXB0Um9vdCAiLi4iKQpTZXQtTG9jYXRpb24gJHJlcG9Sb290CgpTdGFtcCAiQmFya2RheSB2ZXJpZnkgc3RhcnRpbmcuLi4iClN0YW1wICJSZXBvOiAkcmVwb1Jvb3QiCgojIDEpIFJlcXVpcmVkIGNvcmUgZmlsZXMgKGJhc2VkIG9uIHlvdXIgcmVwbyBsaXN0aW5nKQokbXVzdEV4aXN0ID0gQCgKICAiaW5kZXguaHRtbCIsCiAgInN0eWxlLmNzcyIsCiAgImFwcC5qcyIsCiAgInNlcnZpY2Utd29ya2VyLmpzIiwKICAibWFuaWZlc3QuanNvbiIsCiAgImRhdGEvZG9nLWdpZnRzLWJhc2UuanNvbiIsCiAgImRhdGEvZG9nLWdpZnRzLWNhdGFsb2cuanNvbiIsCiAgImRhdGEvZG9nLWdpZnRzLW1lcmdlZC5qc29uIiwKICAiZGF0YS9kb2ctZ2lmdHMtcHJlZmVycmVkLmpzb24iLAogICJzY2hlbWEvZG9nLWdpZnRzLWNhdGFsb2cuc2NoZW1hLnYyLmpzb24iLAogICJzY2hlbWEvZG9nLWdpZnRzLXByZWZlcnJlZC5zY2hlbWEudjIuanNvbiIsCiAgInNjcmlwdHMvcmVidWlsZC1naWZ0LWNhdGFsb2cubWpzIiwKICAic2NyaXB0cy92YWxpZGF0ZS1naWZ0cy12Mi5tanMiLAogICJzY3JpcHRzL21lcmdlLWdpZnRzLXYyLm1qcyIsCiAgImxpZ2h0aG91c2VyYy5qc29uIgopCgokbWlzc2luZyA9IEAoKQpmb3JlYWNoICgkcCBpbiAkbXVzdEV4aXN0KSB7CiAgaWYgKC1ub3QgKFRlc3QtUGF0aCAkcCkpIHsgJG1pc3NpbmcgKz0gJHAgfQp9CgppZiAoJG1pc3NpbmcuQ291bnQgLWd0IDApIHsKICBTdGFtcCAiRkFJTDogTWlzc2luZyByZXF1aXJlZCBmaWxlKHMpOiIKICAkbWlzc2luZyB8IEZvckVhY2gtT2JqZWN0IHsgV3JpdGUtSG9zdCAiIC0gJF8iIH0KICBleGl0IDEKfQpTdGFtcCAiT0s6IFJlcXVpcmVkIGZpbGVzIGV4aXN0LiIKCiRsZWdhY3lHaWZ0RmlsZXMgPSBAKCJkb2ctZ2lmdHMuanNvbiIsICJkb2ctZ2lmdHMuc2NoZW1hLmpzb24iKQokcHJlc2VudExlZ2FjeUdpZnRGaWxlcyA9IEAoJGxlZ2FjeUdpZnRGaWxlcyB8IFdoZXJlLU9iamVjdCB7IFRlc3QtUGF0aCAkXyB9KQppZiAoJHByZXNlbnRMZWdhY3lHaWZ0RmlsZXMuQ291bnQgLWd0IDApIHsKICBTdGFtcCAoIklORk86IERlcHJlY2F0ZWQgbGVnYWN5IGdpZnQgYXJ0aWZhY3QocykgcHJlc2VudCBmb3IgY29tcGF0aWJpbGl0eSBvbmx5OiB7MH0iIC1mICgkcHJlc2VudExlZ2FjeUdpZnRGaWxlcyAtam9pbiAiLCAiKSkKfQoKIyAyKSBKYXZhU2NyaXB0IHN5bnRheCBjaGVja3MgKHBhcnNlLW9ubHk7IGRvZXMgbm90IHJ1biB0aGUgYXBwKQpTdGFtcCAiQ2hlY2tpbmcgSmF2YVNjcmlwdCBzeW50YXguLi4iCiRqc0ZpbGVzID0gQCgKICAiYXBwLmpzIiwKICAiYXBwLWNlbGVicmF0ZS5qcyIsCiAgImFwcC1jdXJ2ZXMtaW5saW5lLmpzIiwKICAiYXBwLXBkZi5qcyIsCiAgInNlcnZpY2Utd29ya2VyLmpzIgopCgpmb3JlYWNoICgkZiBpbiAkanNGaWxlcykgewogIGlmIChUZXN0LVBhdGggJGYpIHsgbm9kZSAtLWNoZWNrICRmIHwgT3V0LU51bGwgfQp9CgppZiAoVGVzdC1QYXRoICJqcyIpIHsKICBHZXQtQ2hpbGRJdGVtIC1QYXRoICJqcyIgLUZpbHRlciAiKi5qcyIgLUZpbGUgfCBGb3JFYWNoLU9iamVjdCB7CiAgICBub2RlIC0tY2hlY2sgJF8uRnVsbE5hbWUgfCBPdXQtTnVsbAogIH0KfQpTdGFtcCAiT0s6IEphdmFTY3JpcHQgc3ludGF4LiIKCiMgMykgSlNPTiBwYXJzZSBjaGVja3MgKHJvb3QgKyBkYXRhICsgdGVzdHMgKyBkb2NzIHdoZXJlIGFwcGxpY2FibGUpClN0YW1wICJDaGVja2luZyBKU09OIHBhcnNlLi4uIgokanNvblRhcmdldHMgPSBAKCkKJGpzb25UYXJnZXRzICs9IEdldC1DaGlsZEl0ZW0gLVBhdGggIi4iIC1GaWx0ZXIgIiouanNvbiIgLUZpbGUgLUVycm9yQWN0aW9uIFNpbGVudGx5Q29udGludWUKaWYgKFRlc3QtUGF0aCAiZGF0YSIpICB7ICRqc29uVGFyZ2V0cyArPSBHZXQtQ2hpbGRJdGVtIC1QYXRoICJkYXRhIiAgLUZpbHRlciAiKi5qc29uIiAtRmlsZSAtRXJyb3JBY3Rpb24gU2lsZW50bHlDb250aW51ZSB9CmlmIChUZXN0LVBhdGggInRlc3RzIikgeyAkanNvblRhcmdldHMgKz0gR2V0LUNoaWxkSXRlbSAtUGF0aCAidGVzdHMiIC1GaWx0ZXIgIiouanNvbiIgLUZpbGUgLUVycm9yQWN0aW9uIFNpbGVudGx5Q29udGludWUgfQppZiAoVGVzdC1QYXRoICJkb2NzIikgIHsgJGpzb25UYXJnZXRzICs9IEdldC1DaGlsZEl0ZW0gLVBhdGggImRvY3MiICAtRmlsdGVyICIqLmpzb24iIC1GaWxlIC1FcnJvckFjdGlvbiBTaWxlbnRseUNvbnRpbnVlIH0KCmZvcmVhY2ggKCRmIGluICRqc29uVGFyZ2V0cykgewogICRjb250ZW50ID0gR2V0LUNvbnRlbnQgJGYuRnVsbE5hbWUgLVJhdyAtRW5jb2RpbmcgVVRGOAogIHRyeSB7CiAgICAkbnVsbCA9ICRjb250ZW50IHwgQ29udmVydEZyb20tSnNvbgogIH0gY2F0Y2ggewogICAgU3RhbXAgIkZBSUw6IEpTT04gcGFyc2UgZXJyb3IgaW4gJCgkZi5GdWxsTmFtZSkiCiAgICB0aHJvdwogIH0KfQpTdGFtcCAiT0s6IEpTT04gcGFyc2UuIgoKIyA0KSBEYXRhIGludGVncml0eSBjaGVja3MgKGJyZWVkX2FsaWFzZXMuanNvbiB2cyBicmVlZF90YXhvbm9teS5qc29uKQpTdGFtcCAiQ2hlY2tpbmcgZGF0YSBpbnRlZ3JpdHkuLi4iCgokYnJlZWRBbGlhc2VzUGF0aCAgPSBKb2luLVBhdGggJHJlcG9Sb290ICJkYXRhL2JyZWVkX2FsaWFzZXMuanNvbiIKJGJyZWVkVGF4b25vbXlQYXRoID0gSm9pbi1QYXRoICRyZXBvUm9vdCAiZGF0YS9icmVlZF90YXhvbm9teS5qc29uIgoKJGJyZWVkQWxpYXNlcyAgPSBHZXQtQ29udGVudCAkYnJlZWRBbGlhc2VzUGF0aCAtUmF3IC1FbmNvZGluZyBVVEY4IHwgQ29udmVydEZyb20tSnNvbgokYnJlZWRUYXhvbm9teSA9IEdldC1Db250ZW50ICRicmVlZFRheG9ub215UGF0aCAtUmF3IC1FbmNvZGluZyBVVEY4IHwgQ29udmVydEZyb20tSnNvbgoKIyBCdWlsZCBmYXN0IGxvb2t1cCBzZXQgb2YgdGF4b25vbXkgY2Fub25pY2FsIGtleXMKJHRheG9ub215S2V5cyA9IFtTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5IYXNoU2V0W3N0cmluZ11dOjpuZXcoW1N5c3RlbS5TdHJpbmdDb21wYXJlcl06Ok9yZGluYWwpCmZvcmVhY2ggKCRwIGluICRicmVlZFRheG9ub215LlBTT2JqZWN0LlByb3BlcnRpZXMpIHsKICBbdm9pZF0kdGF4b25vbXlLZXlzLkFkZCgkcC5OYW1lKQp9CgokY2Fub25DaGVja2VkICAgPSAwCiRhbGlhc2VzQ2hlY2tlZCA9IDAKJG1pc3NpbmdDYW5vbiAgID0gTmV3LU9iamVjdCBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0W3N0cmluZ10KCiMgbm9ybWFsaXplZCBhbGlhcyAtPiBIYXNoU2V0IG9mIGNhbm9uaWNhbCBrZXlzIHRoYXQgY2xhaW0gaXQKJGFsaWFzT3duZXJzID0gQHt9Cgpmb3JlYWNoICgkY2Fub25Qcm9wIGluICRicmVlZEFsaWFzZXMuUFNPYmplY3QuUHJvcGVydGllcykgewogICRjYW5vbiA9ICRjYW5vblByb3AuTmFtZQogIGlmICgkY2Fub24uU3RhcnRzV2l0aCgiXyIpKSB7IGNvbnRpbnVlIH0KCiAgJGNhbm9uQ2hlY2tlZCsrCgogIGlmICgtbm90ICR0YXhvbm9teUtleXMuQ29udGFpbnMoJGNhbm9uKSkgewogICAgJG1pc3NpbmdDYW5vbi5BZGQoJGNhbm9uKSB8IE91dC1OdWxsCiAgfQoKICAkYWxpYXNWYWx1ZSA9ICRjYW5vblByb3AuVmFsdWUKICBpZiAoJG51bGwgLWVxICRhbGlhc1ZhbHVlKSB7IGNvbnRpbnVlIH0KCiAgIyBBY2NlcHQgYXJyYXkgb3Igc2luZ2xlIHN0cmluZzsgdHJlYXQgZXZlcnl0aGluZyBhcyBhIGxpc3Qgb2Ygc3RyaW5ncwogICRhbGlhc0xpc3QgPSBAKCkKICBpZiAoJGFsaWFzVmFsdWUgLWlzIFtzdHJpbmddKSB7CiAgICAkYWxpYXNMaXN0ID0gQCgkYWxpYXNWYWx1ZSkKICB9IGVsc2VpZiAoJGFsaWFzVmFsdWUgLWlzIFtTeXN0ZW0uQ29sbGVjdGlvbnMuSUVudW1lcmFibGVdKSB7CiAgICAkYWxpYXNMaXN0ID0gQCgkYWxpYXNWYWx1ZSkKICB9IGVsc2UgewogICAgJGFsaWFzTGlzdCA9IEAoJGFsaWFzVmFsdWUuVG9TdHJpbmcoKSkKICB9CgogIGZvcmVhY2ggKCRhbGlhcyBpbiAkYWxpYXNMaXN0KSB7CiAgICBpZiAoJG51bGwgLWVxICRhbGlhcykgeyBjb250aW51ZSB9CiAgICAkbm9ybSA9ICRhbGlhcy5Ub1N0cmluZygpLlRyaW0oKS5Ub0xvd2VySW52YXJpYW50KCkKICAgIGlmICgkbm9ybS5MZW5ndGggLWVxIDApIHsgY29udGludWUgfQoKICAgICRhbGlhc2VzQ2hlY2tlZCsrCgogICAgaWYgKC1ub3QgJGFsaWFzT3duZXJzLkNvbnRhaW5zS2V5KCRub3JtKSkgewogICAgICAkYWxpYXNPd25lcnNbJG5vcm1dID0gW1N5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkhhc2hTZXRbc3RyaW5nXV06Om5ldyhbU3lzdGVtLlN0cmluZ0NvbXBhcmVyXTo6T3JkaW5hbCkKICAgIH0KICAgIFt2b2lkXSRhbGlhc093bmVyc1skbm9ybV0uQWRkKCRjYW5vbikKICB9Cn0KCiRkaXN0aW5jdENvbGxpc2lvbnMgPSAwCiRjb2xsaXNpb25FeGFtcGxlcyAgPSBOZXctT2JqZWN0IFN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkxpc3Rbc3RyaW5nXQoKZm9yZWFjaCAoJGt2IGluICRhbGlhc093bmVycy5HZXRFbnVtZXJhdG9yKCkpIHsKICAkb3duZXJzID0gJGt2LlZhbHVlCiAgaWYgKCRvd25lcnMuQ291bnQgLWd0IDEpIHsKICAgICRkaXN0aW5jdENvbGxpc2lvbnMrKwogICAgaWYgKCRjb2xsaXNpb25FeGFtcGxlcy5Db3VudCAtbHQgMjUpIHsKICAgICAgJG93bmVyTGlzdCA9ICgkb3duZXJzIHwgU29ydC1PYmplY3QpIC1qb2luICIsICIKICAgICAgJGNvbGxpc2lvbkV4YW1wbGVzLkFkZCgoImFsaWFzICd7MH0nIHVzZWQgYnk6IHsxfSIgLWYgJGt2LktleSwgJG93bmVyTGlzdCkpIHwgT3V0LU51bGwKICAgIH0KICB9Cn0KCmlmICgkbWlzc2luZ0Nhbm9uLkNvdW50IC1ndCAwIC1vciAkZGlzdGluY3RDb2xsaXNpb25zIC1ndCAwKSB7CiAgU3RhbXAgKCJGQUlMOiBEYXRhIGludGVncml0eSAoY2Fub24gY2hlY2tlZD17MH0sIGFsaWFzZXMgY2hlY2tlZD17MX0sIG1pc3NpbmcgY2Fub249ezJ9LCBkaXN0aW5jdCBjb2xsaXNpb25zPXszfSkiIC1mIGAKICAgICRjYW5vbkNoZWNrZWQsICRhbGlhc2VzQ2hlY2tlZCwgJG1pc3NpbmdDYW5vbi5Db3VudCwgJGRpc3RpbmN0Q29sbGlzaW9ucykKCiAgJGxpbmVzTGVmdCA9IDI1CgogIGlmICgkbWlzc2luZ0Nhbm9uLkNvdW50IC1ndCAwIC1hbmQgJGxpbmVzTGVmdCAtZ3QgMCkgewogICAgU3RhbXAgKCJNaXNzaW5nIGNhbm9uaWNhbCBrZXlzIChzaG93aW5nIHVwIHRvIHswfSk6IiAtZiBbTWF0aF06Ok1pbigkbGluZXNMZWZ0LCAkbWlzc2luZ0Nhbm9uLkNvdW50KSkKICAgIGZvcmVhY2ggKCRtIGluICgkbWlzc2luZ0Nhbm9uIHwgU29ydC1PYmplY3QgfCBTZWxlY3QtT2JqZWN0IC1GaXJzdCAkbGluZXNMZWZ0KSkgewogICAgICBXcml0ZS1Ib3N0ICIgLSAkbSIKICAgICAgJGxpbmVzTGVmdC0tCiAgICAgIGlmICgkbGluZXNMZWZ0IC1sZSAwKSB7IGJyZWFrIH0KICAgIH0KICB9CgogIGlmICgkY29sbGlzaW9uRXhhbXBsZXMuQ291bnQgLWd0IDAgLWFuZCAkbGluZXNMZWZ0IC1ndCAwKSB7CiAgICBTdGFtcCAoIkFsaWFzIGNvbGxpc2lvbnMgKHNob3dpbmcgdXAgdG8gezB9KToiIC1mIFtNYXRoXTo6TWluKCRsaW5lc0xlZnQsICRjb2xsaXNpb25FeGFtcGxlcy5Db3VudCkpCiAgICBmb3JlYWNoICgkYyBpbiAoJGNvbGxpc2lvbkV4YW1wbGVzIHwgU2VsZWN0LU9iamVjdCAtRmlyc3QgJGxpbmVzTGVmdCkpIHsKICAgICAgV3JpdGUtSG9zdCAiIC0gJGMiCiAgICAgICRsaW5lc0xlZnQtLQogICAgICBpZiAoJGxpbmVzTGVmdCAtbGUgMCkgeyBicmVhayB9CiAgICB9CiAgfQoKICBleGl0IDEKfQoKU3RhbXAgKCJPSzogRGF0YSBpbnRlZ3JpdHkgKGNhbm9uIGNoZWNrZWQ9ezB9LCBhbGlhc2VzIGNoZWNrZWQ9ezF9LCBkaXN0aW5jdCBjb2xsaXNpb25zPTApIiAtZiAkY2Fub25DaGVja2VkLCAkYWxpYXNlc0NoZWNrZWQpCgoKU3RhbXAgIlBBU1M6IEFsbCBjaGVja3Mgc3VjY2VlZGVkLiIKZXhpdCAwCg==","inline_bytes":8152,"content_sha256":"a646a9878bf58d66923452fb17e259ed4056905db9baffddc95b1c08b35d88f7"},{"path":"web-app-manifest-192x192.png","size":19685,"sha":"212eff2b2e866e700097dbc7c405ffb7ce9ca19e","media_type":"image/png","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/web-app-manifest-192x192.png","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/web-app-manifest-192x192.png","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"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","inline_bytes":26248,"content_sha256":"75ee21f4b08dd78948e16e0cd49d8128c10a6fa4d831144d72c42d001cdc5f2b"},{"path":"web-app-manifest-512x512.png","size":70559,"sha":"230dc0625a46c99c346bf6207da84bebc8696741","media_type":"image/png","raw_url":"https://raw.githubusercontent.com/CandidQuality/Barkday/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/web-app-manifest-512x512.png","html_url":"https://github.com/CandidQuality/Barkday/blob/9e38500d723ed1e8e1ca93eb8ae821c831f1414d/web-app-manifest-512x512.png","inline_state":"full","max_inline_text_bytes":614400,"max_inline_bin_bytes":204800,"preview_text_bytes":65536,"encoding":"base64","content":"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","inline_bytes":94080,"content_sha256":"3bc51cb6a6c13a2c80d8af5541ed71ffd6649314371b127442035df13527da37"}]}