/* JUTTO product page — Liquid Glass marketplace.

   This page runs a different visual system from the rest of the site, chosen
   deliberately: Liquid Glass, the blue/orange retail palette and Rubik with
   Nunito Sans, per the design-system recommendation for a high-end e-commerce
   listing.

   The shared bar must NOT follow it. Every page carries the same nav, and
   assets/nav.css builds that bar out of --bg, --ink, --accent and friends, so
   redefining those at :root would repaint the nav on this page alone and break
   the consistency the rest of the site depends on. The site tokens therefore
   stay at :root for the bar to read, and the marketplace palette is scoped to
   .market, which wraps everything below the nav.

   Two accessibility notes the recommendation itself flags. Glass surfaces are
   kept at high enough opacity that body text clears 4.5:1 rather than floating
   over whatever is behind them, and every blur has an opaque fallback, because
   text over a failed backdrop-filter is the usual way this style becomes
   unreadable. */

* { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }

/* ---------- site tokens: the shared bar reads these ---------- */
:root {
  --bg: oklch(97.2% 0.005 255);
  --ink: oklch(24% 0.028 262);
  --accent: oklch(50% 0.22 262);
  --well: oklch(92.5% 0.012 255);
  --mid: oklch(52% 0.03 258);
  --line: color-mix(in oklab, var(--ink) 12%, transparent);

  --sh-3: 0 4px 10px color-mix(in oklab, var(--ink) 8%, transparent),
          0 34px 80px color-mix(in oklab, var(--ink) 15%, transparent);
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ---------- marketplace tokens ----------
   At :root, not on .market. The colour field behind the page sits outside that
   wrapper and still has to read them, and a token that resolves nowhere makes
   the whole background shorthand invalid rather than merely wrong. Nothing
   here collides with the site tokens above: the bar reads --bg and --ink, the
   page reads --m-bg and --m-text, and neither can repaint the other. */
:root {
  --m-primary: #2563EB;
  --m-secondary: #3B82F6;
  --m-cta: #F97316;
  --m-bg: #F8FAFC;
  --m-text: #1E293B;
  --m-muted: #64748B;      /* 4.8:1 on --m-bg */
  --m-line: #E2E8F0;
  --m-surface: #FFFFFF;

  /* Glass: opaque enough to carry body text on its own, so the blur is a
     refinement rather than the thing legibility depends on. */
  --m-glass: rgba(255, 255, 255, 0.82);
  --m-glass-line: rgba(255, 255, 255, 0.9);
  --m-blur: saturate(1.6) blur(18px);

  --m-sh-1: 0 1px 2px rgba(15, 23, 42, 0.06), 0 2px 8px rgba(15, 23, 42, 0.05);
  --m-sh-2: 0 2px 6px rgba(15, 23, 42, 0.07), 0 14px 34px rgba(15, 23, 42, 0.09);
  --m-sh-3: 0 6px 16px rgba(37, 99, 235, 0.16), 0 22px 60px rgba(37, 99, 235, 0.18);

  --m-r: 16px;
  --m-r-lg: 22px;
  --m-ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* transparent on purpose: the colour field is painted on a fixed layer behind
   the page, and an opaque wrapper here would cover it completely */
.market {
  color: var(--m-text);
  font-family: 'Nunito Sans', sans-serif;
  font-size: 16px;
  line-height: 1.6;
  display: block;
}

html { background: var(--m-bg); }
body { background: transparent; color: var(--m-text); font-family: 'Nunito Sans', sans-serif; }
img { display: block; max-width: 100%; }
*:focus-visible { outline: 3px solid var(--m-primary); outline-offset: 2px; border-radius: 4px; }

.market h1, .market h2, .market h3, .market .rubik {
  font-family: 'Rubik', sans-serif; letter-spacing: -0.02em; line-height: 1.15;
}
.market .wrap { max-width: 1280px; margin: 0 auto; padding-inline: clamp(20px, 4vw, 40px); }
.mono { font-family: 'Spline Sans Mono', monospace; font-variant-numeric: tabular-nums; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------- the flowing ground ----------
   Two soft colour fields behind the page give the glass something to refract.
   They are painted on a fixed layer at low alpha, so they never sit close
   enough to text to eat its contrast. */
.market-ground {
  position: fixed; inset: 0; z-index: -1; pointer-events: none; overflow: hidden;
  background:
    radial-gradient(58vw 46vw at 12% -6%, rgba(59, 130, 246, 0.20), transparent 62%),
    radial-gradient(46vw 40vw at 92% 6%, rgba(249, 115, 22, 0.14), transparent 60%),
    radial-gradient(52vw 50vw at 72% 96%, rgba(37, 99, 235, 0.14), transparent 62%),
    var(--m-bg);
}

/* ---------- hero: search is the call to action ---------- */
.m-hero { padding: clamp(40px, 6vw, 76px) 0 clamp(26px, 3vw, 38px); }
.m-hero .eyebrow {
  font: 500 12.5px 'Spline Sans Mono', monospace; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--m-primary); margin-bottom: 14px;
}
.m-hero h1 { font-size: clamp(34px, 5.4vw, 60px); font-weight: 600; max-width: 16ch; }
.m-hero .lede {
  font-size: clamp(16.5px, 1.5vw, 19px); color: var(--m-muted);
  max-width: 56ch; margin-top: 16px;
}

/* search field */
.m-search { margin-top: clamp(24px, 3vw, 34px); max-width: 620px; position: relative; }
.m-search input {
  width: 100%; height: 60px; padding: 0 52px 0 52px;
  font: 400 16.5px 'Nunito Sans', sans-serif; color: var(--m-text);
  background: var(--m-glass); border: 1px solid var(--m-glass-line);
  border-radius: 999px; box-shadow: var(--m-sh-2);
  transition: box-shadow 0.3s var(--m-ease), border-color 0.3s var(--m-ease);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .m-search input { backdrop-filter: var(--m-blur); -webkit-backdrop-filter: var(--m-blur); }
}
.m-search input::placeholder { color: var(--m-muted); }
.m-search input:focus { border-color: var(--m-primary); box-shadow: var(--m-sh-3); }
/* z-index because the field's own translucent background paints over an
   absolutely positioned sibling and washes the glyph out to near-invisible */
.m-search .ico {
  position: absolute; left: 20px; top: 50%; transform: translateY(-50%); z-index: 1;
  width: 20px; height: 20px; color: var(--m-muted); pointer-events: none;
}
/* clearing a search is a 44px target, not a 16px glyph */
.m-search .clear {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%); z-index: 1;
  width: 44px; height: 44px; display: grid; place-items: center;
  background: none; border: 0; border-radius: 999px; cursor: pointer; color: var(--m-muted);
}
.m-search .clear:hover { background: rgba(15, 23, 42, 0.06); color: var(--m-text); }

.m-stats { display: flex; gap: 26px; flex-wrap: wrap; margin-top: 26px; }
.m-stat .n { font: 500 22px 'Rubik', sans-serif; display: block; }
.m-stat .k { font-size: 13.5px; color: var(--m-muted); }

/* ---------- shop by line ---------- */
.m-sec { padding-block: clamp(30px, 4vw, 52px); }
/* the bar is sticky, so an anchored jump has to stop short of hiding the heading */
.m-sec[id] { scroll-margin-top: 96px; }
.m-sec-head { display: flex; align-items: end; justify-content: space-between; gap: 20px; margin-bottom: 22px; flex-wrap: wrap; }
.m-sec-head h2 { font-size: clamp(22px, 2.6vw, 30px); font-weight: 600; }
.m-sec-head p { color: var(--m-muted); font-size: 15px; margin-top: 6px; }

/* 200px, so the five lines sit as one row of five on a desktop rather than
   four and a lonely fifth; they reflow to 3, 2 and 1 as the screen narrows */
.m-lines { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.m-line {
  position: relative; display: flex; flex-direction: column;
  background: var(--m-glass); border: 1px solid var(--m-glass-line);
  border-radius: var(--m-r-lg); box-shadow: var(--m-sh-1);
  overflow: hidden; text-align: left; cursor: pointer;
  font: inherit; color: inherit;
  transition: box-shadow 0.35s var(--m-ease), transform 0.35s var(--m-ease), border-color 0.35s var(--m-ease);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .m-line { backdrop-filter: var(--m-blur); -webkit-backdrop-filter: var(--m-blur); }
}
.m-line:hover { transform: translateY(-4px); box-shadow: var(--m-sh-2); }
.m-line .shot { position: relative; aspect-ratio: 4 / 3; overflow: hidden; }
.m-line .shot img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--m-ease); }
.m-line:hover .shot img { transform: scale(1.05); }
/* img.can, not .can: it has to out-specify `.m-line .shot img` above, which
   sets width and height to 100% and would otherwise blow the little can up to
   fill the whole photograph */
.m-line .shot img.can {
  position: absolute; right: 10px; bottom: 10px; width: 58px; height: auto;
  aspect-ratio: 4 / 5; object-fit: contain;
  filter: drop-shadow(0 8px 16px rgba(15, 23, 42, 0.32));
  transition: transform 0.45s var(--m-ease);
}
.m-line:hover .shot img.can { transform: translateY(-4px) scale(1.04); }
.m-line .body { padding: 18px 18px 20px; display: grid; gap: 6px; }
.m-line h3 { font-size: 16.5px; font-weight: 600; }
.m-line .use {
  font: 400 12px 'Spline Sans Mono', monospace; color: var(--m-muted);
  text-transform: lowercase;
}
.m-line .desc { font-size: 14px; color: var(--m-muted); }
.m-line .price { font: 500 15px 'Rubik', sans-serif; color: var(--m-primary); margin-top: 4px; }
/* selected line acts as a filter, so it has to look chosen, not just hovered */
.m-line[aria-pressed="true"] {
  border-color: var(--m-primary);
  box-shadow: var(--m-sh-3), inset 0 0 0 1px var(--m-primary);
}
.m-line[aria-pressed="true"]::after {
  content: ''; position: absolute; inset: 0; border-radius: var(--m-r-lg);
  background: linear-gradient(180deg, rgba(37, 99, 235, 0.10), rgba(37, 99, 235, 0.02));
  pointer-events: none;
}

/* ---------- sticky filter + sort bar ---------- */
.m-toolbar {
  position: sticky; top: 68px; z-index: 30;
  margin-bottom: 22px; padding: 12px;
  background: var(--m-glass); border: 1px solid var(--m-glass-line);
  border-radius: var(--m-r); box-shadow: var(--m-sh-1);
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .m-toolbar { backdrop-filter: var(--m-blur); -webkit-backdrop-filter: var(--m-blur); }
}
@media (prefers-reduced-transparency: reduce) {
  .m-toolbar, .m-line, .m-card, .m-search input { background: var(--m-surface); backdrop-filter: none; -webkit-backdrop-filter: none; }
}

.m-chips { display: flex; gap: 8px; flex-wrap: wrap; }
.m-chip {
  min-height: 44px; padding: 0 16px; border-radius: 999px;
  background: transparent; border: 1px solid var(--m-line);
  font: 500 14px 'Nunito Sans', sans-serif; color: var(--m-text); cursor: pointer;
  display: inline-flex; align-items: center; gap: 8px;
  transition: background-color 0.25s var(--m-ease), border-color 0.25s var(--m-ease), color 0.25s var(--m-ease);
}
.m-chip:hover { background: rgba(37, 99, 235, 0.08); border-color: var(--m-secondary); }
.m-chip .dot { width: 11px; height: 11px; border-radius: 999px; border: 1px solid rgba(15, 23, 42, 0.18); }
.m-chip[aria-pressed="true"] {
  background: var(--m-primary); border-color: var(--m-primary); color: #fff;
  box-shadow: 0 2px 8px rgba(37, 99, 235, 0.35);
}
.m-chip[aria-pressed="true"] .dot { border-color: rgba(255, 255, 255, 0.6); }

.m-toolbar .spacer { margin-left: auto; }
.m-count { font-size: 14px; color: var(--m-muted); white-space: nowrap; }
.m-count strong { color: var(--m-text); font-weight: 600; }
.m-sort {
  min-height: 44px; padding: 0 14px; border-radius: 999px;
  background: var(--m-surface); border: 1px solid var(--m-line);
  font: 500 14px 'Nunito Sans', sans-serif; color: var(--m-text); cursor: pointer;
}
.m-sort:hover { border-color: var(--m-secondary); }

/* ---------- product grid ---------- */
.m-grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }

.m-card {
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  background: var(--m-glass); border: 1px solid var(--m-glass-line);
  border-radius: var(--m-r-lg); box-shadow: var(--m-sh-1);
  transition: box-shadow 0.35s var(--m-ease), transform 0.35s var(--m-ease);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .m-card { backdrop-filter: var(--m-blur); -webkit-backdrop-filter: var(--m-blur); }
}
.m-card:hover { transform: translateY(-4px); box-shadow: var(--m-sh-2); }

.m-card .shot { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--m-line); }
.m-card .shot img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--m-ease); }
.m-card:hover .shot img { transform: scale(1.06); }
/* the colour itself, floated over the room photograph it was shot in */
.m-card .swatch {
  position: absolute; left: 12px; bottom: 12px; width: 52px; height: 52px;
  border-radius: 14px; border: 2px solid rgba(255, 255, 255, 0.85);
  box-shadow: 0 6px 18px rgba(15, 23, 42, 0.3);
}
.m-card .fam-tag {
  position: absolute; right: 10px; top: 10px;
  padding: 5px 11px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.9); color: var(--m-text);
  font: 500 11.5px 'Nunito Sans', sans-serif; white-space: nowrap;
}

.m-card .body { padding: 14px 16px 16px; display: grid; gap: 3px; flex: 1; }
.m-card .code { font: 400 12px 'Spline Sans Mono', monospace; color: var(--m-muted); }
.m-card h3 { font-size: 16px; font-weight: 600; }
.m-card .en { font-size: 13px; color: var(--m-muted); }
.m-card .note {
  font-size: 13.5px; color: var(--m-muted); margin-top: 6px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.m-card .buy {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--m-line);
}
.m-card .price { font: 500 17px 'Rubik', sans-serif; }
.m-card .price .unit { font: 400 12px 'Nunito Sans', sans-serif; color: var(--m-muted); margin-left: 3px; }

/* The one loud control on the page: orange, per the retail palette.

   Dark ink on the orange rather than white. White on #F97316 measures 2.8:1,
   which fails AA for 14px text — the contrast risk this style is flagged for.
   Pairing the palette's own CTA and text colours clears 4.5:1 while keeping
   the specified orange exactly as it is, rather than muddying it to a brown
   dark enough to carry white. */
.m-add {
  min-height: 44px; padding: 0 18px; border-radius: 999px; border: 0; cursor: pointer;
  background: var(--m-cta); color: var(--m-text);
  font: 700 14px 'Nunito Sans', sans-serif; white-space: nowrap;
  box-shadow: 0 2px 6px rgba(249, 115, 22, 0.32), 0 10px 24px rgba(249, 115, 22, 0.24);
  transition: transform 0.2s var(--m-ease), box-shadow 0.3s var(--m-ease), background-color 0.3s var(--m-ease);
}
.m-add:hover { background: #FB8B3C; box-shadow: 0 3px 10px rgba(249, 115, 22, 0.4), 0 14px 30px rgba(249, 115, 22, 0.3); }
.m-add:active { transform: scale(0.96); }
/* confirmation is a state on the button itself, where the user is looking.
   green-800: measured, because green-600 (3.2:1) and green-700 (4.2:1) both
   fall short of AA behind white text at this size. */
.m-add.added { background: #166534; color: #fff; box-shadow: 0 2px 8px rgba(22, 101, 52, 0.4); }

/* ---------- empty state ---------- */
.m-empty {
  grid-column: 1 / -1; padding: clamp(40px, 7vw, 76px) 24px; text-align: center;
  background: var(--m-glass); border: 1px dashed var(--m-line); border-radius: var(--m-r-lg);
}
.m-empty h3 { font-size: 20px; font-weight: 600; margin-bottom: 8px; }
.m-empty p { color: var(--m-muted); max-width: 42ch; margin: 0 auto 18px; }
.m-reset {
  min-height: 44px; padding: 0 20px; border-radius: 999px; cursor: pointer;
  background: var(--m-primary); color: #fff; border: 0;
  font: 600 14px 'Nunito Sans', sans-serif;
}
.m-reset:hover { background: #1D4ED8; }

/* ---------- trust band ---------- */
.m-trust { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.m-trust .t {
  padding: 22px; border-radius: var(--m-r-lg);
  background: var(--m-glass); border: 1px solid var(--m-glass-line); box-shadow: var(--m-sh-1);
  display: grid; gap: 8px;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .m-trust .t { backdrop-filter: var(--m-blur); -webkit-backdrop-filter: var(--m-blur); }
}
.m-trust svg { width: 26px; height: 26px; color: var(--m-primary); }
.m-trust h3 { font-size: 16px; font-weight: 600; }
.m-trust p { font-size: 14px; color: var(--m-muted); }

/* ---------- closing call to action ---------- */
.m-cta-band {
  margin-block: clamp(30px, 4vw, 52px);
  padding: clamp(30px, 4vw, 52px);
  border-radius: var(--m-r-lg); color: #fff;
  background:
    radial-gradient(70% 140% at 100% 0%, rgba(249, 115, 22, 0.55), transparent 60%),
    linear-gradient(120deg, var(--m-primary), var(--m-secondary));
  box-shadow: var(--m-sh-3);
  display: flex; align-items: center; justify-content: space-between; gap: 26px; flex-wrap: wrap;
}
.m-cta-band h2 { font-size: clamp(22px, 3vw, 32px); font-weight: 600; }
.m-cta-band p { color: rgba(255, 255, 255, 0.92); margin-top: 8px; max-width: 46ch; }
.m-cta-band .acts { display: flex; gap: 12px; flex-wrap: wrap; }
.m-btn {
  min-height: 48px; padding: 0 22px; border-radius: 999px; border: 0; cursor: pointer;
  display: inline-flex; align-items: center;
  font: 600 15px 'Nunito Sans', sans-serif; text-decoration: none;
}
.m-btn-solid { background: #fff; color: var(--m-primary); }
.m-btn-solid:hover { background: #EFF6FF; }
.m-btn-ghost { background: rgba(255, 255, 255, 0.16); color: #fff; border: 1px solid rgba(255, 255, 255, 0.5); }
.m-btn-ghost:hover { background: rgba(255, 255, 255, 0.26); }

/* ---------- toast ---------- */
.m-toast {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 16px);
  z-index: 200; padding: 13px 20px; border-radius: 999px;
  background: var(--m-text); color: #fff; font-size: 14.5px; font-weight: 500;
  box-shadow: var(--m-sh-2);
  opacity: 0; pointer-events: none; transition: opacity 0.25s var(--m-ease), transform 0.25s var(--m-ease);
}
.m-toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- footer ---------- */
.m-foot {
  border-top: 1px solid var(--m-line); margin-top: clamp(30px, 4vw, 56px);
  padding-block: 30px 46px;
  display: grid; gap: 6px; font-size: 14px; color: var(--m-muted);
}
.m-foot a { color: var(--m-muted); }
.m-foot a:hover { color: var(--m-primary); }

/* ================= JUTTO products =================
   The product catalogue is built from the same surfaces, shadows and easing as
   the colour marketplace above, so the page reads as the page it was. What is
   deliberately different is the shot: a colour is a room photograph cropped to
   fill, a product is a can on white that must never be cropped. */

/* ---------- sticky category jump ----------
   Anchors, not buttons. The four sections are real sections with real ids, so
   these work with JavaScript blocked. */
.p-jump {
  position: sticky; top: 68px; z-index: 30;
  background: var(--m-glass); border-block: 1px solid var(--m-glass-line);
  box-shadow: var(--m-sh-1);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .p-jump { backdrop-filter: var(--m-blur); -webkit-backdrop-filter: var(--m-blur); }
}
@media (prefers-reduced-transparency: reduce) {
  .p-jump, .p-card { background: var(--m-surface); backdrop-filter: none; -webkit-backdrop-filter: none; }
}
.p-jump-in { display: flex; gap: 8px; flex-wrap: wrap; padding-block: 10px; }
.p-chip {
  min-height: 44px; padding: 0 16px; border-radius: 999px;
  background: transparent; border: 1px solid var(--m-line);
  font: 500 14px 'Nunito Sans', sans-serif; color: var(--m-text); text-decoration: none;
  display: inline-flex; align-items: center; gap: 8px; white-space: nowrap;
  transition: background-color 0.25s var(--m-ease), border-color 0.25s var(--m-ease);
}
.p-chip:hover { background: rgba(37, 99, 235, 0.08); border-color: var(--m-secondary); }
.p-chip .mono { color: var(--m-muted); font-size: 12.5px; }

/* ---------- category section ---------- */
.p-cat { padding-block: clamp(30px, 4vw, 52px); }
/* clear of the sticky jump bar, so a jump does not land under it */
.p-cat[id] { scroll-margin-top: 128px; }
.p-cat-head { margin-bottom: 20px; }
.p-cat-head h2 { font-size: clamp(22px, 2.6vw, 30px); font-weight: 600; }
.p-cat-head p { color: var(--m-muted); font-size: 15px; margin-top: 6px; max-width: 62ch; }
.p-cat-head .p-n {
  display: inline-block; margin-top: 10px; font-size: 12.5px; color: var(--m-muted);
}

/* ---------- product card ---------- */
.p-grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }

.p-card {
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  background: var(--m-glass); border: 1px solid var(--m-glass-line);
  border-radius: var(--m-r-lg); box-shadow: var(--m-sh-1);
  transition: box-shadow 0.35s var(--m-ease), transform 0.35s var(--m-ease);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .p-card { backdrop-filter: var(--m-blur); -webkit-backdrop-filter: var(--m-blur); }
}
.p-card:hover { transform: translateY(-4px); box-shadow: var(--m-sh-2); }

/* `contain`, never `cover`: the cans were shot to the edge of the label, and
   cropping takes the lid and the brand mark with it. The white ground matches
   the ground they were photographed on, so the padding is invisible. */
.p-card .shot {
  position: relative; aspect-ratio: 1; background: #fff;
  display: grid; place-items: center; padding: 14px;
}
.p-card .shot img { width: 100%; height: 100%; object-fit: contain; }
.p-card .badge {
  position: absolute; right: 10px; top: 10px;
  padding: 5px 11px; border-radius: 999px;
  /* ink on the orange, not white. Same measurement as .m-add above: white on
     #F97316 is 2.8:1 and fails AA at this size. */
  background: var(--m-cta); color: var(--m-text);
  font: 700 11.5px 'Nunito Sans', sans-serif; white-space: nowrap;
  box-shadow: 0 2px 8px rgba(249, 115, 22, 0.35);
}

.p-card .body { padding: 14px 16px 16px; display: flex; flex-direction: column; flex: 1; }
.p-card .tier {
  font: 500 11px 'Spline Sans Mono', monospace; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--m-primary);
}
.p-card h3 { font-size: 16px; font-weight: 600; margin-top: 5px; }

/* drawn ticks, matching the folder's own ticked bullets */
.p-card .feat { list-style: none; margin-top: 10px; display: grid; gap: 5px; }
.p-card .feat li {
  position: relative; padding-left: 19px;
  font-size: 13.5px; line-height: 1.5; color: var(--m-muted);
}
.p-card .feat li::before {
  content: '✓'; position: absolute; left: 0; top: 0;
  color: var(--m-primary); font-weight: 700; font-size: 12px;
}

.p-card .vols { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 12px; }
.p-card .vol {
  padding: 3px 10px; border-radius: 999px; border: 1px solid var(--m-line);
  font-size: 12px; color: var(--m-text); background: var(--m-surface);
}

.p-card .buy {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: auto; padding-top: 12px; border-top: 1px solid var(--m-line);
}
/* a label, not a figure. Set in the body face rather than Rubik, which the
   page uses for numbers and which would make "liên hệ" read as a price. */
.p-card .price { font: 600 14px 'Nunito Sans', sans-serif; color: var(--m-muted); }
.p-ask {
  min-height: 44px; padding: 0 18px; border-radius: 999px; border: 0;
  display: inline-flex; align-items: center; text-decoration: none;
  background: var(--m-cta); color: var(--m-text);
  font: 700 14px 'Nunito Sans', sans-serif; white-space: nowrap;
  box-shadow: 0 2px 6px rgba(249, 115, 22, 0.32), 0 10px 24px rgba(249, 115, 22, 0.24);
  transition: transform 0.2s var(--m-ease), box-shadow 0.3s var(--m-ease), background-color 0.3s var(--m-ease);
}
.p-ask:hover { background: #FB8B3C; }
.p-ask:active { transform: scale(0.96); }

/* ---------- product search feedback ---------- */
.p-count { font-size: 14px; color: var(--m-muted); margin-top: 12px; }
.p-count strong { color: var(--m-text); font-weight: 600; }
.p-empty {
  padding: clamp(40px, 7vw, 76px) 24px; text-align: center;
  background: var(--m-glass); border: 1px dashed var(--m-line); border-radius: var(--m-r-lg);
}
.p-empty h3 { font-size: 20px; font-weight: 600; margin-bottom: 8px; }
.p-empty p { color: var(--m-muted); max-width: 46ch; margin: 0 auto 18px; }

/* ---------- entrance ----------
   Staggered by index in market.js, capped so a long grid never crawls. */
.m-card, .m-line, .m-trust .t, .p-card { opacity: 1; }
.reveal-up { opacity: 0; transform: translateY(14px); }
.reveal-up.in { opacity: 1; transform: none; transition: opacity 0.5s var(--m-ease), transform 0.5s var(--m-ease); }

@media (max-width: 900px) {
  .m-toolbar, .p-jump { top: 60px; }
  .m-sec-head { align-items: start; }
  .p-cat[id] { scroll-margin-top: 120px; }
}
@media (max-width: 560px) {
  .m-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; }
  .m-card .note { display: none; }
  .m-card .buy { flex-direction: column; align-items: stretch; }
  .m-add { width: 100%; justify-content: center; }
  .m-toolbar { padding: 10px; gap: 10px; }
  /* the chip row scrolls rather than wrapping into a wall on a small screen */
  .m-chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
  .m-chips::-webkit-scrollbar { display: none; }
  .m-chip { flex: none; }

  .p-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
  /* a seven-item feature list is a wall on a phone; the first three carry the
     product, and the whole list is still there for anyone who searches it */
  .p-card .feat li:nth-child(n+4) { display: none; }
  .p-card .buy { flex-direction: column; align-items: stretch; }
  .p-ask { width: 100%; justify-content: center; }
  .p-jump-in { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .p-jump-in::-webkit-scrollbar { display: none; }
  .p-chip { flex: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  .reveal-up { opacity: 1; transform: none; }
}
