/* ──────────────────────────────────────────────────────────────────────────
   macros_v2.css — visual layer for redesigned macros in ui_patterns.html

   Purpose: keep the new macro styles ISOLATED from tailwind.css. Touching
   tailwind.css would force a rebuild and ripple to every page in the app —
   too much blast radius for one commit. This file is small, fast to load,
   and only contains styles the redesigned macros need.

   Link this from base.html (or wherever the global stylesheet chain lives)
   so the macros render correctly on every page that uses them.

   See ~/.claude/UI_DESIGN_RULES.md for the rules these styles follow.
   ────────────────────────────────────────────────────────────────────────── */

/* ─── Status dot + text (replaces colored pill) ───────────────────────────── */
.wm-status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--theme-text-secondary);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.wm-status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--theme-text-tertiary);
}

/* Semantic color tokens with sensible fallbacks. If the project defines
   --success/--danger/--warning/--brand-primary (wallmarkets does), they're
   used; otherwise fall back to the hard-coded hex literals matching
   wallmarkets' design-variables.css palette. */
.wm-status-dot.wm-stdot-ok    { background: var(--success); }
.wm-status-dot.wm-stdot-bad   { background: var(--danger); }
.wm-status-dot.wm-stdot-warn  { background: var(--warning); }
.wm-status-dot.wm-stdot-info  { background: var(--info); }
.wm-status-dot.wm-stdot-brand { background: var(--brand-primary); }
.wm-status-dot.wm-stdot-mute  { background: var(--theme-text-tertiary); }

/* ── Store origin badge ───────────────────────────────────────────────────
   Sequential store ID (#0001) on storefronts, browse cards, supermarket index
   and admin. Flat fill + hairline border + monospace code. Founding stores
   (#0001–0009) get a restrained amber tint; everyone else is neutral. No
   gradient / glow / decorative icon — hierarchy lives in the mono code, not the
   chrome (UI_DESIGN_RULES). Theme-aware via --theme-* tokens. */
.store-origin {
  display: inline-flex; align-items: center;
  padding: 1px 7px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm, 0.25rem);
  background: var(--theme-bg-secondary);
  color: var(--theme-text-secondary);
  font-family: var(--font-family-mono);
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.02em; line-height: 1.55;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.store-origin--md { padding: 3px 9px; font-size: 12px; }
.store-origin--founding {
  background: rgba(245, 158, 11, 0.08);
  border-color: rgba(245, 158, 11, 0.30);
  /* amber-800, not amber-700 (#B45309).
     The 8% wash above is TRANSLUCENT, so the fill this text sits on depends on
     whatever surface is underneath — and a storefront tints its page with the
     store's own brand colour. Measured from rendered pixels on /@demoshop:
     #B45309 gives 4.72:1 on a white card, 4.55:1 on the neutral page, and only
     4.00:1 over the amber store tint — a WCAG 1.4.3 failure on 11.5px text,
     invisible everywhere except a warm-toned store, which is why it survived.
     #92400E measures 6.66 / 6.42 / 5.65 across the same three surfaces.
     The dark variant below was checked the same way (9.7–10.7:1) and is fine. */
  color: #92400E;
}
[data-theme="dark"] .store-origin--founding,
.dark .store-origin--founding {
  background: rgba(245, 158, 11, 0.13);
  border-color: rgba(245, 158, 11, 0.34);
  color: #FCD34D;
}


/* ──────────────────────────────────────────────────────────────────────────
   Rating stars — the _sf_stars macro (market/_partials/_sf_stars.html)

   Two overlaid five-star tracks: an "off" track in the border colour, and an
   "on" track clipped to width:<pct>% by an inline style. The clipping is what
   renders a fractional rating, and it depends on .sf-rate-on being absolutely
   positioned inside a relatively positioned .sf-rate-stars.

   These rules lived in pages/storefront/v2.css scoped under `.sf`. The macro's
   own comment calls it "one atom for grid card, also-viewed card, PDP rating
   link, reviews header, and each review row" — and market/products.html uses
   it outside the storefront shell, where none of the rules applied. Measured
   on /market/products: position was `static`, so the two tracks sat SIDE BY
   SIDE ("★★★★★ ★★★★★ 4.0 (7)"), both inheriting body grey — a 4.0 product and
   a 1.0 product looked identical. The aria-label carried the rating, so a
   screen reader was fine and only sighted users lost it.

   Unscoped here, in the stylesheet whose header says it exists so "the macros
   render correctly on every page that uses them".
   ────────────────────────────────────────────────────────────────────────── */
.sf-rate { display: inline-flex; align-items: center; gap: 5px; line-height: 1; }
.sf-rate-stars { position: relative; display: inline-block; font-size: 12.5px; letter-spacing: 1.5px; }
.sf-rate--md .sf-rate-stars { font-size: 16px; }
/* The empty-star track under a rating. It is aria-hidden (the filled stars
   and the number carry the rating), but as the visible "out of five" it is
   a meaning-bearing graphic: --border-strong measured 2.28:1 on the dark
   card; the tertiary text token clears WCAG 1.4.11's 3:1 in both themes. */
.sf-rate-off { color: var(--theme-text-tertiary); opacity: 0.72; } /* dark: 2.49 at 55% → ≥3:1 */
/* Light: the tertiary token at 55% fell to 2.24:1 on white; full strength
   clears 3:1 and still sits behind the filled stars. Dark keeps 55%. */
:root:not([data-theme="dark"]) .sf-rate-off { opacity: 0.9; }
.sf-rate-on { position: absolute; left: 0; top: 0; overflow: hidden; white-space: nowrap; color: var(--rating-star); }
.sf-rate-meta { font-size: 12px; color: var(--theme-text-secondary); font-variant-numeric: tabular-nums; }
.sf-rate-meta b { color: var(--theme-text); font-weight: 600; }
.sf-rate-n { color: var(--theme-text-tertiary); }


/* ──────────────────────────────────────────────────────────────────────────
   Checkbox and radio hit area — WCAG 2.2 SC 2.5.8 Target Size (Minimum), AA

   Every checkbox and radio in this app renders at 16x16 (20x20 for -lg), with
   no padding, no margin and — measured across 118 pages at a 375px viewport —
   no wrapping <label> to click instead. A census found 14 distinct shapes and
   all 14 were under the 24px minimum, so the input's own box was the entire
   target.

   The visual size is deliberate and is left alone. What grows is a transparent
   24x24 ::before centred on the box, which takes the pointer for its
   originating element. Verified in the browser rather than assumed: before,
   a hit test 10px above centre missed the input; after, it hits. 14px still
   misses, which is a 24px box behaving correctly.

   ::before is used, not ::after — .ord-checkbox already draws its tick with
   ::after. It renders at all because these inputs set appearance:none.

   Written against the element, not a class list. A first version named
   .wm-checkbox / .wm-radio / .ord-checkbox and its own regression test found
   twenty-odd inputs in templates carrying some other class or none at all —
   dv-checkbox, the settings toggles, the storefront filters — every one of
   which would have quietly opted out.

   Visually hidden inputs need no exclusion. The .sr-only pattern is a 1px box
   with overflow:hidden, which clips the pseudo-element away to nothing, and a
   display:none input renders no pseudo-element at all.

   Checked for collisions across the same 118 pages: the widened area never
   overlaps a different control. The only intersections found were with the
   FIXED mobile bottom nav, which already paints over whatever it covers.
   ────────────────────────────────────────────────────────────────────────── */
input[type="checkbox"],
input[type="radio"] {
  position: relative;
}
input[type="checkbox"]::before,
input[type="radio"]::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 24px;
  transform: translate(-50%, -50%);
}
