<?php
/**
 * /stock — Plattr Stock, the free image library.
 *
 * Started life at /blog/images as a gallery of the photos used on the Plattr
 * blog. It is now a product surface: the same library is what merchants pick
 * from inside the site editor (see includes/stock-images.php + the Free photos
 * tab in the media picker), so this page is the public face of that, not a
 * blog appendix. /blog/images 301s here.
 *
 * A free, searchable gallery of every photo used on the Plattr blog. All
 * images are public domain or CC BY, hosted by us (landing/blog/img/), and
 * described in img/library.json (the single source of truth — see the
 * _readme key there and BLOG_PLAYBOOK.md §8.1).
 *
 * Two views in one file:
 *   • Gallery (default)      — searchable grid, license chips
 *   • Detail  (?img=<file>)  — full attribution, license, download,
 *                              ImageObject JSON-LD (licensable badge)
 *
 * Why it exists: Google Images traffic for the blog, a future stock library
 * for Plattr customers, and clean attribution for everything we use.
 */
declare(strict_types=1);

$base = 'https://' . ($_SERVER['HTTP_HOST'] ?? 'dev.onplattr.com');

$lib = [];
// The manifest and the jpgs live at landing/blog/img/ and did NOT move with
// this page — the picker writes those absolute URLs into merchants' saved
// schemas, so relocating the files would blank images on live storefronts.
// __DIR__ is landing/ now, so the path has to be explicit.
$raw = @file_get_contents(__DIR__ . '/blog/img/library.json');
if ($raw !== false) {
    $j = json_decode($raw, true);
    if (is_array($j) && isset($j['images']) && is_array($j['images'])) $lib = $j['images'];
}

// Only list images whose file actually exists — the manifest can never 404 us.
$lib = array_values(array_filter($lib, fn($im) =>
    !empty($im['file'])
    && preg_match('~^[a-z0-9-]+\.(jpg|jpeg|png|webp)$~', $im['file'])
    && is_file(__DIR__ . '/blog/img/' . $im['file'])
));

// ── Detail view resolution ────────────────────────────────────────
$detail = null;
if (!empty($_GET['img'])) {
    $want = preg_replace('~[^a-z0-9.-]~', '', strtolower((string)$_GET['img']));
    foreach ($lib as $im) {
        if ($im['file'] === $want || pathinfo($im['file'], PATHINFO_FILENAME) === $want) { $detail = $im; break; }
    }
    if ($detail === null) { http_response_code(404); }
}

$e = fn($s) => htmlspecialchars((string)$s, ENT_QUOTES);

$pageTitle = $detail
    ? ($detail['title'] . ': free food photo | Plattr Stock')
    : 'Plattr Stock: free food photos for your store';
$pageDesc = $detail
    ? ('Free to use: ' . $detail['description'] . ' License: ' . $detail['license_label'] . '.')
    : 'Free food and restaurant photos, public domain and CC BY, with clear attribution. Free to download, and built into every Plattr store.';
$canonical = $detail
    ? $base . '/stock?img=' . rawurlencode(pathinfo($detail['file'], PATHINFO_FILENAME))
    : $base . '/stock';
$ogImage = $detail ? ($base . '/blog/img/' . $detail['file']) : ($lib ? $base . '/blog/img/' . $lib[0]['file'] : '');
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= $e($pageTitle) ?></title>
<meta name="description" content="<?= $e($pageDesc) ?>">
<link rel="canonical" href="<?= $e($canonical) ?>">
<meta property="og:title" content="<?= $e($pageTitle) ?>">
<meta property="og:description" content="<?= $e($pageDesc) ?>">
<meta property="og:type" content="website">
<meta property="og:url" content="<?= $e($canonical) ?>">
<?php if ($ogImage): ?><meta property="og:image" content="<?= $e($ogImage) ?>"><?php endif; ?>
<meta name="twitter:card" content="summary_large_image">
<link rel="icon" href="/assets/favicon/favicon-96x96.png?v=4" sizes="32x32">
<link href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css" rel="stylesheet">
<?php if ($detail): ?>
<script type="application/ld+json"><?= json_encode([
    '@context' => 'https://schema.org',
    '@type' => 'ImageObject',
    'contentUrl' => $base . '/blog/img/' . $detail['file'],
    'url' => $canonical,
    'name' => $detail['title'],
    'description' => $detail['description'],
    'width' => (int)$detail['width'],
    'height' => (int)$detail['height'],
    'encodingFormat' => 'image/jpeg',
    'license' => $detail['license_url'],
    'acquireLicensePage' => $canonical,
    'creditText' => $detail['attribution'],
    'creator' => ['@type' => ($detail['creator'] === 'USDA' ? 'Organization' : 'Organization'), 'name' => $detail['creator'], 'url' => $detail['creator_url']],
    'copyrightNotice' => $detail['attribution'],
    'isAccessibleForFree' => true,
], JSON_UNESCAPED_SLASHES) ?></script>
<?php else: ?>
<script type="application/ld+json"><?= json_encode([
    '@context' => 'https://schema.org',
    '@type' => 'CollectionPage',
    'name' => 'Plattr Image Library: free food photos',
    'description' => $pageDesc,
    'url' => $canonical,
    'isAccessibleForFree' => true,
], JSON_UNESCAPED_SLASHES) ?></script>
<?php endif; ?>
<style>
:root{
  --bg:#FAFAF9; --card:#fff; --ink:#0a0a0f; --soft:#52525b; --faint:#a1a1aa;
  --line:#e7e5e4; --brand:#2456DB; --brand-soft:#F3EFFE; --green:#059669;
  --radius:16px; --ease:cubic-bezier(0.22,1,0.36,1);
}
*{margin:0;padding:0;box-sizing:border-box}
body{background:var(--bg);color:var(--ink);font-family:Inter,-apple-system,'SF Pro Display',system-ui,sans-serif;-webkit-font-smoothing:antialiased;line-height:1.55}
a{color:var(--brand);text-decoration:none}
a:hover{text-decoration:underline}
.wrap{max-width:1080px;margin:0 auto;padding:0 22px}
.top{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:18px 0;border-bottom:1px solid var(--line)}
.top-brand{display:inline-flex;align-items:center;gap:9px;font-weight:800;letter-spacing:-0.02em;color:var(--ink);font-size:16px}
.top-brand img{width:26px;height:26px;object-fit:contain}
.top-links{display:flex;gap:18px;font-size:13.5px;font-weight:600}
.head{padding:44px 0 10px}
.head .eyebrow{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;font-weight:800;letter-spacing:0.1em;text-transform:uppercase;color:var(--brand);margin-bottom:12px}
.head h1{font-size:clamp(28px,4.6vw,40px);font-weight:800;letter-spacing:-0.03em;line-height:1.12;margin-bottom:10px}
.head p{font-size:16px;color:var(--soft);max-width:62ch}
.tools{display:flex;gap:10px;flex-wrap:wrap;align-items:center;padding:22px 0 6px}
.search{flex:1;min-width:220px;display:flex;align-items:center;gap:9px;background:var(--card);border:1px solid var(--line);border-radius:12px;padding:11px 14px}
.search i{color:var(--faint);font-size:18px}
.search input{border:0;outline:0;flex:1;font-size:14.5px;font-family:inherit;background:transparent;color:var(--ink)}
.chip{border:1px solid var(--line);background:var(--card);border-radius:99px;padding:9px 15px;font-size:12.5px;font-weight:700;color:var(--soft);cursor:pointer;font-family:inherit;transition:all .2s var(--ease)}
.chip.on{background:var(--brand);border-color:var(--brand);color:#fff}
.count{font-size:12.5px;color:var(--faint);padding:8px 2px 0}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:18px;padding:18px 0 70px}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;transition:transform .25s var(--ease),box-shadow .25s var(--ease);display:block;color:inherit}
.card:hover{transform:translateY(-3px);box-shadow:0 14px 34px rgba(10,10,15,0.09);text-decoration:none}
.card-media{aspect-ratio:4/3;background:#EFEDEA;overflow:hidden}
.card-media img{width:100%;height:100%;object-fit:cover;display:block}
.card-body{padding:13px 15px 15px}
.card-title{font-size:14.5px;font-weight:700;letter-spacing:-0.01em;margin-bottom:5px}
.card-meta{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--faint)}
.badge{display:inline-flex;align-items:center;gap:4px;border-radius:6px;padding:2px 7px;font-weight:800;font-size:10.5px;letter-spacing:0.04em}
.badge.pd{background:#ECFDF5;color:var(--green)}
.badge.by{background:var(--brand-soft);color:var(--brand)}
.empty{padding:60px 0;text-align:center;color:var(--faint);display:none}
/* detail */
.crumb{padding:22px 0 0;font-size:13px;color:var(--faint)}
.detail{display:grid;grid-template-columns:1.5fr 1fr;gap:28px;padding:22px 0 80px;align-items:start}
@media(max-width:820px){.detail{grid-template-columns:1fr}}
.detail-media{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
.detail-media img{width:100%;height:auto;display:block}
.panel{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:22px}
.panel h1{font-size:22px;font-weight:800;letter-spacing:-0.02em;line-height:1.2;margin-bottom:8px}
.panel .desc{font-size:14px;color:var(--soft);margin-bottom:18px}
.meta-row{display:flex;justify-content:space-between;gap:12px;padding:9px 0;border-top:1px solid var(--line);font-size:13px}
.meta-row .k{color:var(--faint);font-weight:600}
.meta-row .v{text-align:right;font-weight:600}
.actions{display:grid;gap:9px;margin:18px 0 6px}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:11px;padding:12px 16px;font-size:14px;font-weight:700;font-family:inherit;cursor:pointer;border:1px solid var(--line);background:var(--card);color:var(--ink);transition:all .2s var(--ease);text-decoration:none}
.btn:hover{border-color:var(--brand);color:var(--brand);text-decoration:none}
.btn.primary{background:var(--brand);border-color:var(--brand);color:#fff}
.btn.primary:hover{filter:brightness(1.06);color:#fff}
.attr-box{background:var(--bg);border:1px dashed var(--line);border-radius:11px;padding:12px 14px;font-size:12.5px;color:var(--soft);margin-top:10px}
.attr-box b{color:var(--ink)}
.usage{font-size:12.5px;color:var(--faint);line-height:1.6;margin-top:14px}
.tagline{display:flex;gap:7px;flex-wrap:wrap;margin-top:16px}
.tagline a{font-size:11.5px;background:var(--bg);border:1px solid var(--line);border-radius:99px;padding:5px 11px;color:var(--soft);font-weight:600}
.tagline a:hover{color:var(--brand);border-color:var(--brand);text-decoration:none}
.foot{border-top:1px solid var(--line);padding:26px 0 40px;font-size:12.5px;color:var(--faint);display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap}
</style>
</head>
<body>

<div class="wrap">
  <div class="top">
    <a class="top-brand" href="/"><img src="/plattr-mini.webp?v=4" alt="Plattr">Plattr</a>
    <div class="top-links">
      <a href="/blog/">Blog</a>
      <a href="/stock">Plattr Stock</a>
      <a href="/">Get started</a>
    </div>
  </div>

<?php if ($detail): ?>
  <?php $fileUrl = '/blog/img/' . $detail['file']; $slug = pathinfo($detail['file'], PATHINFO_FILENAME); ?>
  <div class="crumb"><a href="/stock">← All photos</a></div>
  <div class="detail">
    <div class="detail-media">
      <img src="<?= $e($fileUrl) ?>" alt="<?= $e($detail['alt']) ?>" width="<?= (int)$detail['width'] ?>" height="<?= (int)$detail['height'] ?>">
    </div>
    <div class="panel">
      <h1><?= $e($detail['title']) ?></h1>
      <p class="desc"><?= $e($detail['description']) ?></p>

      <div class="meta-row"><span class="k">License</span><span class="v"><a href="<?= $e($detail['license_url']) ?>" rel="license nofollow" target="_blank"><?= $e($detail['license_label']) ?></a></span></div>
      <div class="meta-row"><span class="k">Creator</span><span class="v"><a href="<?= $e($detail['creator_url']) ?>" rel="nofollow" target="_blank"><?= $e($detail['creator']) ?></a></span></div>
      <div class="meta-row"><span class="k">Source</span><span class="v"><a href="<?= $e($detail['source']) ?>" rel="nofollow" target="_blank"><?= $e($detail['provider']) ?></a></span></div>
      <div class="meta-row"><span class="k">Size</span><span class="v"><?= (int)$detail['width'] ?> × <?= (int)$detail['height'] ?> · <?= number_format((int)$detail['bytes'] / 1024) ?> KB</span></div>

      <div class="actions">
        <a class="btn primary" href="<?= $e($fileUrl) ?>" download><i class="bx bx-download"></i> Download free</a>
        <button class="btn" type="button" id="copyAttr"><i class="bx bx-copy"></i> Copy attribution</button>
      </div>

      <div class="attr-box" id="attrText">Photo: <b><?= $e($detail['attribution']) ?></b><?= $detail['license'] === 'by' ? ', attribution required when you use it.' : ', no attribution required, credit appreciated.' ?></div>

      <p class="usage"><?= in_array($detail['license'], ['pdm','cc0'], true)
          ? 'This image is in the public domain: free to use for any purpose, including commercial, with no permission needed.'
          : ($detail['license'] === 'pexels'
            ? 'This image is free under the Pexels License: free to use for commercial and personal projects, no attribution required.'
            : 'This image is licensed CC BY: free to use for any purpose, including commercial, as long as you credit the creator (the line above is enough).') ?>
        Plattr hosts this copy as part of our blog and takes no ownership of it.</p>

      <?php if (!empty($detail['tags'])): ?>
      <div class="tagline">
        <?php foreach (array_slice($detail['tags'], 0, 6) as $t): ?>
          <a href="/stock?q=<?= rawurlencode($t) ?>"><?= $e($t) ?></a>
        <?php endforeach; ?>
      </div>
      <?php endif; ?>
    </div>
  </div>

<?php else: ?>
  <div class="head">
    <span class="eyebrow"><i class="bx bx-images"></i> Plattr Stock</span>
    <h1>Free food photos, clearly licensed.</h1>
    <p>Public domain, CC BY and other free-license photos of food, restaurants and markets. Free to download and use commercially, with the attribution ready to copy where one is required. If you sell on Plattr, this whole library is already inside your site editor, so there is nothing to download.</p>
  </div>

  <div class="tools">
    <label class="search"><i class="bx bx-search"></i><input type="search" id="q" placeholder="Search images… (market, catering, dining)" autocomplete="off" value="<?= $e((string)($_GET['q'] ?? '')) ?>"></label>
    <button class="chip on" data-lic="">All</button>
    <button class="chip" data-lic="pdm">Public domain</button>
    <button class="chip" data-lic="by">CC BY</button>
  </div>
  <div class="count" id="count"></div>

  <div class="grid" id="grid">
    <?php foreach ($lib as $im): $slug = pathinfo($im['file'], PATHINFO_FILENAME); ?>
    <a class="card" href="/stock?img=<?= rawurlencode($slug) ?>"
       data-hay="<?= $e(strtolower($im['title'] . ' ' . implode(' ', $im['tags'] ?? []) . ' ' . $im['creator'])) ?>"
       data-lic="<?= $e($im['license'] === 'cc0' ? 'pdm' : $im['license']) ?>">
      <div class="card-media"><img src="/blog/img/<?= $e($im['file']) ?>" alt="<?= $e($im['alt']) ?>" loading="lazy" decoding="async" width="<?= (int)$im['width'] ?>" height="<?= (int)$im['height'] ?>"></div>
      <div class="card-body">
        <div class="card-title"><?= $e($im['title']) ?></div>
        <div class="card-meta">
          <span class="badge <?= $im['license'] === 'by' ? 'by' : 'pd' ?>"><?= $im['license'] === 'by' ? 'CC BY' : ($im['license'] === 'pexels' ? 'FREE' : 'PUBLIC DOMAIN') ?></span>
          <span><?= $e($im['creator']) ?></span>
        </div>
      </div>
    </a>
    <?php endforeach; ?>
  </div>
  <div class="empty" id="empty">No images match that search yet. Try a broader word.</div>

  <!-- Closing CTA. This page ranks for "free food photos", which is almost
       exactly Plattr's audience arriving under their own steam. The claim is
       literally true — the same library is in the site editor — so it costs
       nobody anything to say so. No fake urgency, no invented numbers, and the
       commission line is the honest one (from 2.5%, region-dependent). -->
  <section class="stock-cta">
    <h2>These are already in your store.</h2>
    <p>Every photo here is built into Plattr's site editor, so you can drop one
       onto your homepage, a product or an offer without downloading anything.
       Sell online with your own site, menu and checkout, from 2.5% commission.</p>
    <a class="stock-cta-btn" href="/">Start building free</a>
  </section>
<?php endif; ?>

<style>
  .stock-cta{margin:56px auto 8px;max-width:640px;text-align:center;padding:34px 26px;
             border:1px solid rgba(17,12,34,.10);border-radius:18px;background:#fbfaf8}
  .stock-cta h2{margin:0 0 10px;font-size:clamp(22px,3vw,30px);line-height:1.2;letter-spacing:-.02em}
  .stock-cta p{margin:0 auto 20px;max-width:52ch;font-size:14.5px;line-height:1.65;color:#5b5768}
  .stock-cta-btn{display:inline-flex;align-items:center;justify-content:center;
                 padding:12px 26px;border-radius:999px;background:#2352D8;color:#fff;
                 font-weight:650;font-size:14.5px;transition:background .18s,transform .18s}
  .stock-cta-btn:hover{background:#16307A;transform:translateY(-1px)}
  @media (prefers-color-scheme: dark){
    .stock-cta{background:rgba(255,255,255,.03);border-color:rgba(255,255,255,.10)}
    .stock-cta p{color:#a9a4b8}
  }
</style>
  <div class="foot">
    <span>Images remain the work of their credited creators. Plattr hosts them under their public licenses.</span>
    <span><a href="/blog/">Plattr Blog</a> · <a href="/">onplattr.com</a></span>
  </div>
</div>

<script>
// Copy-attribution (detail view)
(function(){
  var btn = document.getElementById('copyAttr');
  if (!btn) return;
  btn.addEventListener('click', function(){
    var txt = (document.getElementById('attrText') || {}).innerText || '';
    txt = txt.replace(/,\s*(attribution required|no attribution).*$/i, '').replace(/^Photo:\s*/i, 'Photo: ');
    try { navigator.clipboard.writeText(txt); } catch(e) {}
    btn.innerHTML = '<i class="bx bx-check"></i> Copied';
    setTimeout(function(){ btn.innerHTML = '<i class="bx bx-copy"></i> Copy attribution'; }, 1600);
  });
})();

// Search + license filter (gallery view)
(function(){
  var q = document.getElementById('q');
  if (!q) return;
  var chips = document.querySelectorAll('.chip');
  var cards = document.querySelectorAll('#grid .card');
  var empty = document.getElementById('empty');
  var count = document.getElementById('count');
  var lic = '';
  function apply(){
    var term = q.value.trim().toLowerCase(), shown = 0;
    cards.forEach(function(c){
      var ok = (!term || c.dataset.hay.indexOf(term) !== -1) && (!lic || c.dataset.lic === lic);
      c.style.display = ok ? '' : 'none';
      if (ok) shown++;
    });
    empty.style.display = shown ? 'none' : 'block';
    count.textContent = shown + ' image' + (shown === 1 ? '' : 's') + (term || lic ? ' matching' : ' in the library');
  }
  q.addEventListener('input', apply);
  chips.forEach(function(ch){
    ch.addEventListener('click', function(){
      chips.forEach(function(x){ x.classList.remove('on'); });
      ch.classList.add('on');
      lic = ch.dataset.lic || '';
      apply();
    });
  });
  apply();
})();
</script>
</body>
</html>
