<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
    <title>折石咖啡豆单与报价 - ZHE'S COFFEE</title>
    <meta name="description" content="折石咖啡豆单与报价。44 款精品咖啡豆，含瑰夏、耶加雪菲、云南保山等产地，¥66-¥980/200g。">
    <link rel="canonical" href="https://zhescoffee.com/products.html" />
    <meta property="og:type" content="website" />
    <meta property="og:site_name" content="折石咖啡 ZHE'S COFFEE" />
    <meta property="og:title" content="折石咖啡豆单与报价 — ZHE'S COFFEE" />
    <meta property="og:description" content="44 款精品咖啡豆，含瑰夏、耶加雪菲、云南保山等产地，¥66-¥980/200g。" />
    <meta property="og:url" content="https://zhescoffee.com/products.html" />
    <meta property="og:image" content="https://zhescoffee.com/img/zhes-logo.png" />
    <meta property="og:locale" content="zh_CN" />
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content="折石咖啡豆单与报价 — ZHE'S COFFEE" />
    <meta name="twitter:description" content="44 款精品咖啡豆，含瑰夏、耶加雪菲、云南保山等产地，¥66-¥980/200g。" />
    <meta name="twitter:image" content="https://zhescoffee.com/img/zhes-logo.png" />
    <link rel="icon" type="image/png" href="img/zhes-logo.png">
    <link rel="stylesheet" href="css/tailwind.css">
    <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "WebSite",
      "@id": "https://zhescoffee.com/#website",
      "url": "https://zhescoffee.com/",
      "name": "折石咖啡 ZHE'S COFFEE",
      "description": "上海欧焙客贸易旗下精品咖啡品牌。创始人江承哲，世界烘焙亚军。",
      "inLanguage": "zh-CN",
      "publisher": { "@id": "https://zhescoffee.com/#organization" }
    }
    </script>
    <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "Organization",
      "@id": "https://zhescoffee.com/#organization",
      "name": "折石咖啡 ZHE'S COFFEE",
      "alternateName": ["ZHE'S COFFEE", "折石咖啡"],
      "url": "https://zhescoffee.com",
      "logo": "https://zhescoffee.com/img/zhes-logo.png",
      "legalName": "上海欧焙客贸易有限公司",
      "description": "折石咖啡 ZHE'S COFFEE — 上海欧焙客贸易有限公司旗下精品咖啡品牌。创始人江承哲为世界烘焙亚军、台湾烘焙冠军、SCA Diploma 持证人。提供精品咖啡零售、烘焙与订阅服务。",
      "slogan": "在坚硬现实中寻找精确诗意",
      "founder": { "@type": "Person", "name": "江承哲", "@id": "https://jiangchengzhe.com/#person" },
      "brand": { "@type": "Brand", "name": "ZHE'S COFFEE", "alternateName": "折石咖啡" },
      "subOrganization": {
        "@type": "Organization",
        "@id": "https://tastermatrix.com/#organization",
        "name": "解味视界 TasterMatrix",
        "alternateName": ["TasterMatrix", "解味视界"],
        "url": "https://tastermatrix.com"
      },
      "contactPoint": {
        "@type": "ContactPoint",
        "contactType": "customer support",
        "url": "https://zhescoffee.com/contact.html",
        "availableLanguage": ["zh-CN", "en"]
      },
      "areaServed": { "@type": "City", "name": "Shanghai" },
      "sameAs": ["https://zhescoffee.taobao.com"]
    }
    </script>
    <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "ItemList",
      "name": "折石咖啡精选推荐豆单",
      "description": "精选 6 款推荐咖啡豆。完整 44 款豆单见 https://zhescoffee.com/products.html 页面表格。",
      "url": "https://zhescoffee.com/products.html",
      "itemListElement": [
        {
          "@type": "ListItem",
          "position": 1,
          "item": {
            "@type": "Product",
            "name": "哥伦比亚考卡天堂92日本清酒曲厌氧水洗条纹波旁",
            "image": "https://zhescoffee.com/img/monthly-bean-1.jpg",
            "description": "清酒、粉色花香、荔枝、口感活泼余韵悠长",
            "brand": { "@id": "https://zhescoffee.com/#organization" },
            "category": "中南美洲",
            "offers": {
              "@type": "Offer",
              "price": "368",
              "priceCurrency": "CNY",
              "availability": "https://schema.org/InStock",
              "url": "https://zhescoffee.com/products.html"
            }
          }
        },
        {
          "@type": "ListItem",
          "position": 2,
          "item": {
            "@type": "Product",
            "name": "卢旺达盖瑟克处理厂酵母发酵日晒黄金百香果",
            "description": "黄金百香果、玫瑰花、猕猴桃",
            "brand": { "@id": "https://zhescoffee.com/#organization" },
            "category": "非洲",
            "offers": {
              "@type": "Offer",
              "price": "128",
              "priceCurrency": "CNY",
              "availability": "https://schema.org/InStock",
              "url": "https://zhescoffee.com/products.html"
            }
          }
        },
        {
          "@type": "ListItem",
          "position": 3,
          "item": {
            "@type": "Product",
            "name": "哥伦比亚分界线庄园双重发酵日晒希爪",
            "description": "复合莓果汁、杏桃、紫，浓郁复合果汁",
            "brand": { "@id": "https://zhescoffee.com/#organization" },
            "category": "中南美洲",
            "offers": {
              "@type": "Offer",
              "price": "358",
              "priceCurrency": "CNY",
              "availability": "https://schema.org/InStock",
              "url": "https://zhescoffee.com/products.html"
            }
          }
        },
        {
          "@type": "ListItem",
          "position": 4,
          "item": {
            "@type": "Product",
            "name": "巴拿马波奎特翡翠庄园绿标水洗瑰夏哈拉米约地块",
            "description": "香草玫瑰、柠檬、黑莓、复合水果茶、活泼多汁口感",
            "brand": { "@id": "https://zhescoffee.com/#organization" },
            "category": "中南美洲",
            "offers": {
              "@type": "Offer",
              "price": "550",
              "priceCurrency": "CNY",
              "availability": "https://schema.org/InStock",
              "url": "https://zhescoffee.com/products.html"
            }
          }
        },
        {
          "@type": "ListItem",
          "position": 5,
          "item": {
            "@type": "Product",
            "name": "巴拿马极光庄园水洗绿顶瑰夏火石系列",
            "description": "茉莉花、佛手柑、柠檬、柑橘、白桃、酸甜美味丰富多汁",
            "brand": { "@id": "https://zhescoffee.com/#organization" },
            "category": "中南美洲",
            "offers": {
              "@type": "Offer",
              "price": "600",
              "priceCurrency": "CNY",
              "availability": "https://schema.org/InStock",
              "url": "https://zhescoffee.com/products.html"
            }
          }
        },
        {
          "@type": "ListItem",
          "position": 6,
          "item": {
            "@type": "Product",
            "name": "巴拿马詹森庄园绿顶瑰夏 HolaGeishaV 水洗",
            "description": "茉莉花、佛手柑，高海拔纯净花果的极致表达",
            "brand": { "@id": "https://zhescoffee.com/#organization" },
            "category": "中南美洲",
            "offers": {
              "@type": "Offer",
              "price": "580",
              "priceCurrency": "CNY",
              "availability": "https://schema.org/InStock",
              "url": "https://zhescoffee.com/products.html"
            }
          }
        }
      ]
    }
    </script>
    <style>
        :root {
            --oatmeal: #E2DED0;
            --quartz: #F2F0E6;
            --sand: #D2C9B1;
            --blush: #E6D6C6;
            --ash: #4A4A4A;
            --slate: #7B8C96;
            --denim: #5A6B75;
            --silver: #B2B2B2;
            --moss: #667260;
            --line: rgba(74, 74, 74, 0.14);
            --quartz-vein: #FEFBF0;
        }

        * {
            box-sizing: border-box;
        }

        body {
            margin: 0;
            color: var(--ash);
            font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", sans-serif;
            background-color: var(--oatmeal);
            background-image:
                linear-gradient(170deg, rgba(255, 255, 255, 0.36) 0%, transparent 58%),
                linear-gradient(350deg, rgba(123, 140, 150, 0.14) 0%, transparent 62%),
                repeating-linear-gradient(90deg, rgba(74, 74, 74, 0.025) 0, rgba(74, 74, 74, 0.025) 1px, transparent 1px, transparent 96px);
        }

        a {
            color: inherit;
            text-decoration: none;
        }

        button,
        input,
        select {
            font: inherit;
        }

        .site-shell {
            min-height: 100vh;
        }

        .site-header {
            position: sticky;
            top: 0;
            z-index: 20;
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 24px;
            padding: 18px 24px;
            border-bottom: 1px solid rgba(74, 74, 74, 0.08);
            background: rgba(226, 222, 208, 0.82);
            backdrop-filter: blur(16px);
        }

        .brand-link {
            display: inline-flex;
            align-items: center;
            gap: 14px;
            font-size: 12px;
            font-weight: 700;
            letter-spacing: 0.18em;
            text-transform: uppercase;
        }

        .brand-link img {
            width: 56px;
            height: 56px;
            object-fit: contain;
        }

        .nav-links {
            display: flex;
            align-items: center;
            justify-content: flex-end;
            gap: 10px;
            color: rgba(74, 74, 74, 0.66);
            font-size: 13px;
        }

        .nav-links a {
            border: 1px solid transparent;
            padding: 9px 12px;
            border-radius: 999px;
            transition: border-color 180ms ease, background 180ms ease, color 180ms ease;
        }

        .nav-links a:hover,
        .nav-links a[aria-current="page"] {
            color: var(--ash);
            border-color: rgba(90, 107, 117, 0.24);
            background: rgba(255, 255, 255, 0.25);
        }
        .nav-links a[aria-current="page"] {
            position: relative;
            box-shadow: inset 0 -2px 0 var(--quartz-vein);
        }
        .nav-links a[aria-current="page"]::after {
            content: "";
            position: absolute;
            bottom: -5px;
            left: 50%;
            transform: translateX(-50%);
            width: 16px;
            height: 2px;
            background: var(--quartz-vein);
            border-radius: 1px;
        }

        .catalog-shell {
            width: min(1180px, calc(100% - 40px));
            margin: 0 auto;
            padding: 52px 0 88px;
        }

        .hero-grid {
            display: grid;
            grid-template-columns: minmax(0, 1.35fr) minmax(300px, 0.65fr);
            gap: 24px;
            align-items: stretch;
            margin-bottom: 28px;
        }

        .hero-panel,
        .purchase-panel,
        .filter-panel {
            border: 1px solid rgba(250, 246, 236, 0.6);
            border-radius: 8px;
            background: rgba(250, 246, 236, 0.82);
            box-shadow: 0 22px 56px rgba(74, 74, 74, 0.08);
            backdrop-filter: blur(12px);
        }

        .hero-panel {
            position: relative;
            overflow: hidden;
            padding: 34px;
        }

        .hero-panel::before {
            content: "";
            position: absolute;
            inset: 0;
            pointer-events: none;
            background:
                linear-gradient(90deg, rgba(123, 140, 150, 0.18), transparent 36%),
                linear-gradient(180deg, transparent, rgba(210, 201, 177, 0.22));
        }

        .hero-content {
            position: relative;
            z-index: 1;
        }

        .eyebrow {
            margin: 0 0 18px;
            color: var(--denim);
            font-size: 11px;
            font-weight: 700;
            letter-spacing: 0.24em;
            text-transform: uppercase;
        }
        .eyebrow::before {
            content: "";
            display: inline-block;
            width: 2px;
            height: 12px;
            background: var(--quartz-vein);
            margin-right: 10px;
            vertical-align: middle;
        }
        .eyebrow::after {
            content: "";
            display: block;
            width: 32px;
            height: 1px;
            background: var(--quartz-vein);
            margin-top: 8px;
        }

        h1 {
            max-width: 740px;
            margin: 0;
            color: #343434;
            font-size: 48px;
            line-height: 1.16;
            font-weight: 800;
        }

        .hero-copy {
            max-width: 720px;
            margin: 20px 0 0;
            color: rgba(74, 74, 74, 0.72);
            font-size: 16px;
            line-height: 1.85;
        }

        .stats-strip {
            display: grid;
            grid-template-columns: repeat(4, minmax(0, 1fr));
            gap: 1px;
            margin-top: 28px;
            overflow: hidden;
            border: 1px solid var(--line);
            border-radius: 8px;
            background: var(--line);
        }

        .stat-item {
            min-height: 88px;
            padding: 16px;
            background: rgba(255, 255, 255, 0.27);
        }

        .stat-value {
            display: block;
            color: var(--denim);
            font-size: 24px;
            font-weight: 800;
            line-height: 1;
        }

        .stat-label {
            display: block;
            margin-top: 10px;
            color: rgba(74, 74, 74, 0.58);
            font-size: 12px;
            line-height: 1.35;
        }

        .purchase-panel {
            display: flex;
            flex-direction: column;
            padding: 24px;
        }

        .panel-title {
            margin: 0 0 14px;
            color: #383838;
            font-size: 18px;
            font-weight: 800;
        }

        .purchase-copy {
            margin: 0 0 18px;
            color: rgba(74, 74, 74, 0.68);
            font-size: 14px;
            line-height: 1.7;
        }

        .purchase-actions {
            display: grid;
            gap: 10px;
            margin-top: auto;
        }

        .action-link,
        .copy-button {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 14px;
            min-height: 48px;
            width: 100%;
            padding: 12px 14px;
            border: 1px solid rgba(90, 107, 117, 0.22);
            border-radius: 8px;
            color: #343434;
            background: rgba(255, 255, 255, 0.32);
            cursor: pointer;
            transition: transform 180ms ease, border-color 180ms ease, background 180ms ease;
        }

        .action-link.primary {
            color: #fff;
            border-color: transparent;
            background: linear-gradient(135deg, var(--slate), var(--denim));
        }

        .action-link:hover,
        .copy-button:hover {
            transform: translateY(-2px);
            border-color: rgba(90, 107, 117, 0.44);
            background: rgba(255, 255, 255, 0.48);
        }

        .action-link.primary:hover {
            background: linear-gradient(135deg, #8397A0, var(--denim));
        }

        .action-label {
            font-size: 13px;
            font-weight: 800;
        }

        .action-value {
            color: rgba(74, 74, 74, 0.62);
            font-size: 12px;
        }

        .primary .action-value {
            color: rgba(255, 255, 255, 0.76);
        }

        .filter-panel {
            display: grid;
            grid-template-columns: minmax(240px, 1fr) auto;
            gap: 18px;
            align-items: start;
            margin-bottom: 22px;
            padding: 18px;
        }

        .search-field {
            position: relative;
        }

        .search-field input,
        .select-control {
            width: 100%;
            min-height: 46px;
            border: 1px solid rgba(90, 107, 117, 0.22);
            border-radius: 8px;
            color: var(--ash);
            background: rgba(255, 255, 255, 0.35);
            outline: none;
        }

        .search-field input {
            padding: 0 14px;
        }

        .select-control {
            padding: 0 34px 0 12px;
            appearance: none;
        }

        .search-field input:focus,
        .select-control:focus {
            border-color: rgba(90, 107, 117, 0.62);
            box-shadow: 0 0 0 3px rgba(123, 140, 150, 0.16);
        }

        .filter-groups {
            display: grid;
            gap: 12px;
        }

        .chip-row {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
        }

        .filter-chip {
            min-height: 36px;
            padding: 0 12px;
            border: 1px solid rgba(90, 107, 117, 0.22);
            border-radius: 999px;
            color: rgba(74, 74, 74, 0.72);
            background: rgba(255, 255, 255, 0.24);
            cursor: pointer;
        }

        .filter-chip.active {
            color: #fff;
            border-color: transparent;
            background: var(--ash);
        }

        .selects {
            display: grid;
            grid-template-columns: repeat(3, 150px);
            gap: 10px;
        }

        .result-line {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 16px;
            margin: 0 0 18px;
            color: rgba(74, 74, 74, 0.62);
            font-size: 13px;
        }

        .legend {
            display: flex;
            flex-wrap: wrap;
            justify-content: flex-end;
            gap: 8px;
        }

        .legend span {
            padding: 4px 8px;
            border: 1px solid rgba(90, 107, 117, 0.16);
            border-radius: 999px;
            background: rgba(255, 255, 255, 0.22);
        }

        .product-grid {
            display: grid;
            grid-template-columns: repeat(3, minmax(0, 1fr));
            gap: 14px;
        }

        .product-card {
            display: flex;
            min-height: 318px;
            flex-direction: column;
            border: 1px solid rgba(74, 74, 74, 0.12);
            border-radius: 8px;
            background: rgba(242, 240, 230, 0.78);
            box-shadow: 0 18px 42px rgba(74, 74, 74, 0.07);
            overflow: hidden;
        }

        .product-head {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 12px;
            padding: 14px 16px;
            border-bottom: 1px solid rgba(74, 74, 74, 0.1);
            background: rgba(255, 255, 255, 0.24);
        }

        .product-code {
            color: rgba(74, 74, 74, 0.5);
            font-size: 12px;
            font-weight: 800;
            letter-spacing: 0.08em;
        }

        .product-category {
            color: var(--denim);
            font-size: 12px;
            font-weight: 800;
        }

        .product-body {
            display: flex;
            flex: 1;
            flex-direction: column;
            padding: 18px 16px 16px;
        }

        .product-title-row {
            display: flex;
            align-items: flex-start;
            justify-content: space-between;
            gap: 12px;
        }

        .product-title {
            margin: 0;
            color: #343434;
            font-size: 22px;
            line-height: 1.25;
            font-weight: 850;
        }

        .stars {
            flex: none;
            color: var(--moss);
            font-size: 13px;
            letter-spacing: 0;
            white-space: nowrap;
        }

        .product-name {
            margin: 12px 0 0;
            color: rgba(74, 74, 74, 0.72);
            font-size: 13px;
            line-height: 1.65;
        }

        .meta-grid {
            display: grid;
            grid-template-columns: repeat(2, minmax(0, 1fr));
            gap: 8px;
            margin: 16px 0;
        }

        .meta-pill {
            min-height: 34px;
            padding: 8px 10px;
            border: 1px solid rgba(90, 107, 117, 0.14);
            border-radius: 8px;
            color: rgba(74, 74, 74, 0.74);
            background: rgba(255, 255, 255, 0.24);
            font-size: 12px;
            line-height: 1.35;
        }

        .flavor-tags {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: auto;
        }

        .flavor-tags span {
            padding: 5px 8px;
            border-radius: 999px;
            color: rgba(74, 74, 74, 0.68);
            background: rgba(210, 201, 177, 0.34);
            font-size: 12px;
            line-height: 1.25;
        }

        .price-row {
            display: flex;
            align-items: baseline;
            justify-content: space-between;
            gap: 12px;
            margin-top: 18px;
            padding-top: 14px;
            border-top: 1px solid rgba(74, 74, 74, 0.1);
        }

        .price-label {
            color: rgba(74, 74, 74, 0.56);
            font-size: 12px;
        }

        .price {
            color: var(--ash);
            font-size: 28px;
            font-weight: 900;
        }

        .product-actions {
            display: grid;
            grid-template-columns: 1.25fr 1fr 1fr;
            gap: 8px;
            margin-top: 12px;
        }

        .product-action {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            min-height: 38px;
            width: 100%;
            padding: 8px 10px;
            border: 1px solid rgba(90, 107, 117, 0.2);
            border-radius: 8px;
            color: var(--denim);
            background: rgba(255, 255, 255, 0.28);
            font-size: 12px;
            font-weight: 800;
            line-height: 1.25;
            text-align: center;
            cursor: pointer;
        }

        .product-action.primary {
            color: #fff;
            border-color: transparent;
            background: linear-gradient(135deg, var(--slate), var(--denim));
        }

        .catalog-notes {
            margin-top: 26px;
            border: 1px solid rgba(90, 107, 117, 0.15);
            border-radius: 8px;
            padding: 18px;
            background: rgba(255, 255, 255, 0.2);
        }

        .catalog-notes h2 {
            margin: 0 0 10px;
            font-size: 16px;
            font-weight: 800;
        }

        .catalog-notes ul {
            margin: 0;
            padding-left: 1.2em;
            color: rgba(74, 74, 74, 0.7);
            font-size: 13px;
            line-height: 1.8;
        }

        .empty-state {
            display: none;
            min-height: 180px;
            align-items: center;
            justify-content: center;
            border: 1px dashed rgba(90, 107, 117, 0.28);
            border-radius: 8px;
            color: rgba(74, 74, 74, 0.62);
            background: rgba(255, 255, 255, 0.18);
        }

        .page-footer {
            border-top: 1px solid rgba(74, 74, 74, 0.08);
            padding: 34px 24px;
            color: rgba(74, 74, 74, 0.52);
            text-align: center;
            font-size: 12px;
            letter-spacing: 0.18em;
            text-transform: uppercase;
        }

        @media (max-width: 980px) {
            .hero-grid {
                grid-template-columns: 1fr;
            }

            .filter-panel {
                grid-template-columns: 1fr;
            }

            .selects {
                grid-template-columns: repeat(3, minmax(0, 1fr));
            }

            .product-grid {
                grid-template-columns: repeat(2, minmax(0, 1fr));
            }
        }

        @media (max-width: 700px) {
            .site-header {
                align-items: flex-start;
                flex-direction: column;
                padding: 14px 18px;
            }

            .brand-link img {
                width: 48px;
                height: 48px;
            }

            .nav-links {
                width: 100%;
                justify-content: space-between;
            }

            .catalog-shell {
                width: min(100% - 28px, 1180px);
                padding: 28px 0 58px;
            }

            .hero-panel {
                padding: 24px 18px;
            }

            h1 {
                font-size: 34px;
            }

            .stats-strip {
                grid-template-columns: repeat(2, minmax(0, 1fr));
            }

            .stat-item {
                min-height: 78px;
            }

            .selects {
                grid-template-columns: 1fr;
            }

            .result-line {
                align-items: flex-start;
                flex-direction: column;
            }

            .legend {
                justify-content: flex-start;
            }

            .product-grid {
                grid-template-columns: 1fr;
            }

            .product-card {
                min-height: auto;
            }

            .product-actions {
                grid-template-columns: 1fr;
            }
        }
        .hero-panel, .purchase-panel, .filter-panel,
        .product-card {
            border-left: 2px solid var(--quartz-vein);
        }
    </style>
</head>
<body>
    <div class="site-shell">
        <header class="site-header">
            <a href="/" class="brand-link" aria-label="返回 ZHE'S COFFEE 首页">
                <img src="img/zhes-logo.png" alt="ZHE'S COFFEE Logo">
                <span>ZHE'S COFFEE</span>
            </a>
            <nav class="nav-links" aria-label="主导航">
                <a href="/">首页</a>
                <a href="products.html?src=site_nav" aria-current="page">豆单与报价</a>
                <a href="quiz.html?src=site_nav">帮我选豆</a>
<a href="monthly-beans.html?src=site_nav">月度补给</a>
<a href="articles.html?src=site_nav">专栏</a>
<a href="account.html?src=site_nav">登录/补给</a>
                <a href="contact.html?src=site_nav">联系</a>
                <a href="https://zhescoffee.taobao.com" target="_blank" rel="noopener">淘宝</a>
            </nav>
        </header>

        <main class="catalog-shell">
            <section class="hero-grid" aria-labelledby="catalog-title">
                <div class="hero-panel">
                    <div class="hero-content">
                        <p class="eyebrow">Retail Catalog</p>
                        <h1 id="catalog-title">折石咖啡豆单与报价</h1>
                        <p class="hero-copy">从单品豆到配方设计，按产区、烘焙度、规格和风味线索整理。报价由最新 Excel 豆单生成。</p>
                        <div class="stats-strip" aria-label="豆单摘要">
                            <div class="stat-item">
                                <span class="stat-value" id="stat-total">--</span>
                                <span class="stat-label">在售商品</span>
                            </div>
                            <div class="stat-item">
                                <span class="stat-value" id="stat-range">--</span>
                                <span class="stat-label">价格范围</span>
                            </div>
                            <div class="stat-item">
                                <span class="stat-value" id="stat-update">--</span>
                                <span class="stat-label">报价更新</span>
                            </div>
                            <div class="stat-item">
                                <span class="stat-value" id="stat-spec">--</span>
                                <span class="stat-label">主要规格</span>
                            </div>
                        </div>
                    </div>
                </div>

                <aside class="purchase-panel" aria-labelledby="purchase-title">
                    <h2 class="panel-title" id="purchase-title">购买入口</h2>
                    <p class="purchase-copy">请优先到淘宝下单；需要协助挑豆、批量采购或课程合作，可以联系官方客服。</p>
                    <div class="purchase-actions">
                        <a id="products-taobao-link" class="action-link primary" href="https://zhescoffee.taobao.com" target="_blank" rel="noopener" data-web-url="https://zhescoffee.taobao.com" data-app-url="tbopen://m.taobao.com/tbopen/index.html?action=ali.open.nav&module=h5&bootImage=0&h5Url=https%3A%2F%2Fzhescoffee.taobao.com">
                            <span class="action-label">到淘宝购买</span>
                            <span class="action-value">zhescoffee.taobao.com</span>
                        </a>
                        <button class="copy-button" type="button" data-copy="Lexi806">
                            <span class="action-label">官方客服微信</span>
                            <span class="action-value">Lexi806</span>
                        </button>
                        <a class="action-link" href="mailto:chengzhe@zhescoffee.com">
                            <span class="action-label">Email 联系</span>
                            <span class="action-value">chengzhe@zhescoffee.com</span>
                        </a>
                    </div>
                </aside>
            </section>

            <section class="filter-panel" aria-label="产品筛选">
                <div class="filter-groups">
                    <label class="search-field">
                        <input id="search-input" type="search" placeholder="搜索简称、产区、处理法或风味关键词" autocomplete="off">
                    </label>
                    <div class="chip-row" id="category-chips" aria-label="产区筛选"></div>
                </div>
                <div class="selects">
                    <select id="roast-select" class="select-control" aria-label="烘焙度筛选">
                        <option value="all">全部烘焙</option>
                    </select>
                    <select id="spec-select" class="select-control" aria-label="规格筛选">
                        <option value="all">全部规格</option>
                    </select>
                    <select id="sort-select" class="select-control" aria-label="排序">
                        <option value="sequence">豆单顺序</option>
                        <option value="price-asc">价格由低到高</option>
                        <option value="price-desc">价格由高到低</option>
                        <option value="stars-desc">推荐星级优先</option>
                    </select>
                </div>
            </section>

            <div class="result-line">
                <span id="result-count">正在读取豆单...</span>
                <div class="legend" id="star-legend" aria-label="推荐星级说明"></div>
            </div>

            <section class="product-grid" id="product-grid" aria-live="polite"></section>
            <div class="empty-state" id="empty-state">没有符合当前筛选条件的商品。</div>

            <section class="catalog-notes" aria-labelledby="notes-title">
                <h2 id="notes-title">订购说明</h2>
                <ul id="catalog-notes"></ul>
            </section>
        </main>

        <footer class="page-footer">© 2026 ZHE'S COFFEE · 上海欧焙客贸易有限公司</footer>
    </div>

    <script>
        (function () {
            var query = new URLSearchParams(window.location.search);
            var state = {
                category: 'all',
                roast: 'all',
                spec: 'all',
                search: '',
                sort: query.get('sort') === 'stars' ? 'stars-desc' : 'sequence'
            };
            var catalog = null;

            var elements = {
                total: document.getElementById('stat-total'),
                range: document.getElementById('stat-range'),
                update: document.getElementById('stat-update'),
                spec: document.getElementById('stat-spec'),
                search: document.getElementById('search-input'),
                categoryChips: document.getElementById('category-chips'),
                roast: document.getElementById('roast-select'),
                specSelect: document.getElementById('spec-select'),
                sort: document.getElementById('sort-select'),
                resultCount: document.getElementById('result-count'),
                legend: document.getElementById('star-legend'),
                grid: document.getElementById('product-grid'),
                empty: document.getElementById('empty-state'),
                notes: document.getElementById('catalog-notes')
            };

            function escapeHtml(value) {
                return String(value || '').replace(/[&<>"']/g, function (char) {
                    return {
                        '&': '&amp;',
                        '<': '&lt;',
                        '>': '&gt;',
                        '"': '&quot;',
                        "'": '&#39;'
                    }[char];
                });
            }

            function unique(values) {
                var seen = {};
                return values.filter(function (value) {
                    if (!value || seen[value]) {
                        return false;
                    }
                    seen[value] = true;
                    return true;
                });
            }

            function splitName(name) {
                var tags = String(name || '').match(/#[^#]+/g) || [];
                var base = String(name || '').replace(/#[^#]+/g, '').trim();
                return {
                    base: base,
                    tags: tags.map(function (tag) {
                        return tag.replace(/^#/, '').trim();
                    }).filter(Boolean).slice(0, 4)
                };
            }

            function buildOrderNote(product) {
                var nameParts = splitName(product.name);
                var displayName = nameParts.base || product.name;
                return '折石咖啡订购：#' + String(product.sequence).padStart(2, '0') + ' '
                    + (product.shortName || displayName) + '，' + product.spec + '，享味价 ¥' + product.price
                    + '。请客服确认库存、烘焙安排，以及是否需要磨粉。';
            }

            function renderSummary() {
                var summary = catalog.summary;
                var priceRange = summary.priceRange || {};
                var specs = Object.keys(summary.specCounts || {}).join(' / ');

                elements.total.textContent = summary.totalProducts || 0;
                elements.range.textContent = priceRange.min ? '¥' + priceRange.min + '-¥' + priceRange.max : '--';
                elements.update.textContent = catalog.updatedAt || '--';
                elements.spec.textContent = specs || '--';
            }

            function renderFilters() {
                var chips = [{ label: '全部', value: 'all' }].concat(
                    (catalog.categories || []).map(function (category) {
                        return { label: category, value: category };
                    })
                );
                elements.categoryChips.innerHTML = chips.map(function (chip) {
                    var active = chip.value === state.category ? ' active' : '';
                    return '<button class="filter-chip' + active + '" type="button" data-category="' + escapeHtml(chip.value) + '">' + escapeHtml(chip.label) + '</button>';
                }).join('');

                unique(catalog.products.map(function (product) { return product.roast; })).forEach(function (roast) {
                    var option = document.createElement('option');
                    option.value = roast;
                    option.textContent = roast;
                    elements.roast.appendChild(option);
                });

                unique(catalog.products.map(function (product) { return product.spec; })).forEach(function (spec) {
                    var option = document.createElement('option');
                    option.value = spec;
                    option.textContent = spec;
                    elements.specSelect.appendChild(option);
                });

                elements.legend.innerHTML = (catalog.starLegend || []).map(function (item) {
                    return '<span>' + '★'.repeat(item.stars) + ' ' + escapeHtml(item.label) + '</span>';
                }).join('');
                elements.sort.value = state.sort;
            }

            function matchesSearch(product, term) {
                if (!term) {
                    return true;
                }
                var haystack = [
                    product.category,
                    product.roast,
                    product.spec,
                    product.aroma,
                    product.process,
                    product.acidity,
                    product.shortName,
                    product.name
                ].join(' ').toLowerCase();
                return haystack.indexOf(term.toLowerCase()) >= 0;
            }

            function filteredProducts() {
                var products = catalog.products.filter(function (product) {
                    return (state.category === 'all' || product.category === state.category)
                        && (state.roast === 'all' || product.roast === state.roast)
                        && (state.spec === 'all' || product.spec === state.spec)
                        && matchesSearch(product, state.search);
                }).slice();

                products.sort(function (a, b) {
                    if (state.sort === 'price-asc') {
                        return a.price - b.price;
                    }
                    if (state.sort === 'price-desc') {
                        return b.price - a.price;
                    }
                    if (state.sort === 'stars-desc') {
                        return (b.recommendationStars - a.recommendationStars) || (a.sequence - b.sequence);
                    }
                    return a.sequence - b.sequence;
                });
                return products;
            }

            function renderProduct(product) {
                var nameParts = splitName(product.name);
                var stars = product.recommendationStars > 0 ? '★'.repeat(product.recommendationStars) : '';
                var tags = nameParts.tags.map(function (tag) {
                    return '<span>' + escapeHtml(tag) + '</span>';
                }).join('');
                var displayName = nameParts.base || product.name;
                var orderNote = buildOrderNote(product);

                return [
                    '<article class="product-card">',
                    '<div class="product-head">',
                    '<span class="product-code">#' + String(product.sequence).padStart(2, '0') + '</span>',
                    '<span class="product-category">' + escapeHtml(product.category) + '</span>',
                    '</div>',
                    '<div class="product-body">',
                    '<div class="product-title-row">',
                    '<h2 class="product-title">' + escapeHtml(product.shortName || displayName) + '</h2>',
                    stars ? '<span class="stars" aria-label="' + product.recommendationStars + ' 星推荐">' + stars + '</span>' : '',
                    '</div>',
                    '<p class="product-name">' + escapeHtml(displayName) + '</p>',
                    '<div class="meta-grid">',
                    '<span class="meta-pill">' + escapeHtml(product.roast) + '</span>',
                    '<span class="meta-pill">' + escapeHtml(product.spec) + '</span>',
                    '<span class="meta-pill">' + escapeHtml(product.process) + '</span>',
                    '<span class="meta-pill">' + escapeHtml(product.acidity || product.aroma) + '</span>',
                    '</div>',
                    tags ? '<div class="flavor-tags">' + tags + '</div>' : '',
                    '<div class="price-row">',
                    '<span class="price-label">享味价</span>',
                    '<strong class="price">¥' + escapeHtml(product.price) + '</strong>',
                    '</div>',
                    '<div class="product-actions">',
                    '<button class="product-action primary" type="button" data-copy-order-note="' + escapeHtml(orderNote) + '">复制下单备注</button>',
                    '<a class="product-action" href="contact.html?src=product_card&product=' + encodeURIComponent(product.id) + '">问客服</a>',
                    '<a class="product-action" href="https://zhescoffee.taobao.com" target="_blank" rel="noopener">淘宝购买</a>',
                    '</div>',
                    '</div>',
                    '</article>'
                ].join('');
            }

            function renderProducts() {
                var products = filteredProducts();
                elements.resultCount.textContent = '显示 ' + products.length + ' / ' + catalog.products.length + ' 款商品';
                elements.grid.innerHTML = products.map(renderProduct).join('');
                elements.empty.style.display = products.length ? 'none' : 'flex';
            }

            function renderNotes() {
                elements.notes.innerHTML = (catalog.notes || []).map(function (note) {
                    return '<li>' + escapeHtml(note) + '</li>';
                }).join('');
            }

            function bindEvents() {
                elements.categoryChips.addEventListener('click', function (event) {
                    var button = event.target.closest('[data-category]');
                    if (!button) {
                        return;
                    }
                    state.category = button.getAttribute('data-category');
                    renderFilters();
                    renderProducts();
                });

                elements.search.addEventListener('input', function () {
                    state.search = elements.search.value.trim();
                    renderProducts();
                });

                elements.roast.addEventListener('change', function () {
                    state.roast = elements.roast.value;
                    renderProducts();
                });

                elements.specSelect.addEventListener('change', function () {
                    state.spec = elements.specSelect.value;
                    renderProducts();
                });

                elements.sort.addEventListener('change', function () {
                    state.sort = elements.sort.value;
                    renderProducts();
                });

                document.addEventListener('click', function (event) {
                    var copyButton = event.target.closest('[data-copy], [data-copy-order-note]');
                    if (!copyButton || !navigator.clipboard) {
                        return;
                    }
                    var value = copyButton.getAttribute('data-copy-order-note') || copyButton.getAttribute('data-copy');
                    var valueNode = copyButton.querySelector('.action-value') || copyButton;
                    var oldText = valueNode.textContent;
                    navigator.clipboard.writeText(value).then(function () {
                        valueNode.textContent = '已复制';
                        window.setTimeout(function () {
                            valueNode.textContent = oldText;
                        }, 1400);
                    });
                });
            }

            function bindTaobaoAppLink() {
                var link = document.getElementById('products-taobao-link');
                var mobilePattern = /Android|iPhone|iPad|iPod|Mobile/i;
                if (!link) {
                    return;
                }
                link.addEventListener('click', function (event) {
                    var webUrl = link.getAttribute('data-web-url');
                    var appUrl = link.getAttribute('data-app-url');
                    if (!webUrl || !appUrl) {
                        return;
                    }
                    event.preventDefault();
                    if (!mobilePattern.test(navigator.userAgent)) {
                        window.open(webUrl, '_blank', 'noopener');
                        return;
                    }
                    var fallbackTimer = window.setTimeout(function () {
                        if (document.visibilityState === 'visible') {
                            window.location.href = webUrl;
                        }
                    }, 900);
                    var cancelFallback = function () {
                        window.clearTimeout(fallbackTimer);
                        document.removeEventListener('visibilitychange', cancelFallback);
                        window.removeEventListener('pagehide', cancelFallback);
                    };
                    document.addEventListener('visibilitychange', cancelFallback);
                    window.addEventListener('pagehide', cancelFallback);
                    window.location.href = appUrl;
                });
            }

            fetch('data/products.json')
                .then(function (response) {
                    if (!response.ok) {
                        throw new Error('Catalog request failed: ' + response.status);
                    }
                    return response.json();
                })
                .then(function (data) {
                    catalog = data;
                    renderSummary();
                    renderFilters();
                    renderProducts();
                    renderNotes();
                    bindEvents();
                })
                .catch(function () {
                    elements.resultCount.textContent = '豆单读取失败，请稍后再试。';
                    elements.empty.textContent = '无法读取 data/products.json。';
                    elements.empty.style.display = 'flex';
                });

            bindTaobaoAppLink();
        })();
    </script>
</body>
</html>
