/* ──────────────────────────────────────────────────────────────────────────
 * Broken Bags — admin / customer / landing
 *
 * This file CLONES the live theme's design tokens, button styles, hero,
 * tile pattern, and panel system from `vaultlight-themev17` (Broken Bags
 * Noir) so go.brokenbags.shop and admin.brokenbags.shop look identical to
 * the WordPress site at brokenbags.shop. New dashboard-specific styles
 * (KPI cards, tier badge, mail feed) are appended at the bottom and use
 * the same visual vocabulary.
 * ────────────────────────────────────────────────────────────────────── */

/* ── Type faces (self-hosted woff2) ───────────────────────────────────────
 * Display: Clash Display (Fontshare, OFL) — headlines/hero only.
 * Body:    Hanken Grotesk (Google Fonts, OFL) — variable 400–800, latin subset.
 * font-display:swap + the two critical weights are <link rel=preload>ed in base.html.
 * ────────────────────────────────────────────────────────────────────── */
@font-face {
  font-family: "Clash Display";
  src: url("/static/fonts/clash-display-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Clash Display";
  src: url("/static/fonts/clash-display-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Clash Display";
  src: url("/static/fonts/clash-display-600.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Clash Display";
  src: url("/static/fonts/clash-display-700.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Hanken Grotesk";
  src: url("/static/fonts/hanken-grotesk.woff2") format("woff2");
  font-weight: 400 800; font-style: normal; font-display: swap;
}

:root {
  --bg: #050505;
  --bg-elevated: rgba(10, 10, 10, 0.94);
  --panel: #0d0d0f;
  --panel-soft: #1a1a1d;
  --text: #f6f6f4;
  --muted: #d4d4d8;          /* was #c0c0c6 — bumped for AA contrast on dark bg */
  --muted-soft: #a8a8ae;     /* for tertiary copy where bright muted is too loud */
  --line: rgba(255, 255, 255, 0.12);  /* was 0.08 — clearer card boundaries */
  --line-strong: rgba(255, 255, 255, 0.22);
  --accent: #ff2ec4;          /* was #d80f16 — brighter for body-on-dark legibility */
  --accent-strong: #ff66d9;
  --accent-soft: rgba(255, 46, 196, 0.14);
  --shadow: 0 24px 80px rgba(0, 0, 0, 0.62);
  --content-width: min(1200px, calc(100vw - 32px));
  --radius-lg: 28px;
  --radius-md: 18px;
  --radius-sm: 12px;
  --radius-btn: 12px;        /* was a hard 4px on buttons — unified with the soft-rect system */
  --radius-pill: 999px;

  /* Type system — Refined Luxury (Clash Display + Hanken Grotesk) */
  --font-display: "Clash Display", "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-body: "Hanken Grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --lh-tight: 1.04;
  --lh-snug: 1.2;
  --lh-body: 1.6;
  /* Fluid modular scale (~1.22 ratio), clamped for mobile→desktop */
  --step--1: clamp(0.78rem, 0.74rem + 0.18vw, 0.86rem);
  --step-0:  clamp(0.94rem, 0.90rem + 0.20vw, 1.02rem);
  --step-1:  clamp(1.10rem, 1.02rem + 0.40vw, 1.35rem);
  --step-2:  clamp(1.38rem, 1.24rem + 0.66vw, 1.85rem);
  --step-3:  clamp(1.80rem, 1.55rem + 1.10vw, 2.65rem);
  --step-4:  clamp(2.35rem, 1.90rem + 2.10vw, 3.90rem);
  --step-5:  clamp(3.00rem, 2.20rem + 3.60vw, 5.60rem);

  /* Elevation set (existing --shadow kept as the large default / --shadow-lg alias) */
  /* Two-part physics: a tight near-black contact shadow + a soft grounded cast
     (negative spread so it hugs, not haloes) + a faint magenta tint. Honest
     black elevation is the tell of premium dark UI — surfaces float, not buzz. */
  --shadow-sm: 0 1px 1px rgba(0, 0, 0, 0.5), 0 8px 20px -10px rgba(0, 0, 0, 0.55);
  --shadow-md: 0 1px 1px rgba(0, 0, 0, 0.55), 0 18px 44px -14px rgba(0, 0, 0, 0.62), 0 0 38px -22px rgba(255, 46, 196, 0.12);
  --shadow-lg: var(--shadow);
  --ring-accent: 0 0 0 1px rgba(255, 46, 196, 0.35);
  --focus-ring: 0 0 0 3px rgba(255, 46, 196, 0.30);

  /* ── Brand monogram watermark tile (single source of truth) ──────────────
   * Red transparent "BROKEN BAGS" wordmark with the broken-heart line-mark
   * woven through it. Consumed by body.brand-bg::before (rotated, rest of
   * site) and by the /local menu's axis-aligned override (iOS-safe). Colours
   * are %23-encoded; the heart is a stroked 100x100 glyph scaled in place,
   * geometry matches static/brand/mark.svg — keep them in sync. */
  --bb-monogram: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='760' height='220' viewBox='0 0 760 220'%3E%3Cg fill='%23ff2ec4' fill-opacity='0.028' font-family='Arial, Helvetica, sans-serif' font-size='26' font-weight='700' letter-spacing='5'%3E%3Ctext x='-20' y='48'%3EBROKEN BAGS BROKEN BAGS BROKEN BAGS%3C/text%3E%3Ctext x='-170' y='112'%3EBROKEN BAGS BROKEN BAGS BROKEN BAGS%3C/text%3E%3Ctext x='-20' y='176'%3EBROKEN BAGS BROKEN BAGS BROKEN BAGS%3C/text%3E%3C/g%3E%3Cg fill='none' stroke='%23ff2ec4' stroke-opacity='0.11' stroke-width='5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg transform='translate(340,60) scale(0.30)'%3E%3Cpath d='M50 88 C 22 68 8 50 14 32 C 19 17 38 14 50 28 C 62 14 81 17 86 32 C 92 50 78 68 50 88 Z'/%3E%3Cpath d='M50 28 L 41 42 L 57 52 L 44 64 L 53 74 L 50 88'/%3E%3C/g%3E%3Cg transform='translate(120,128) scale(0.30)'%3E%3Cpath d='M50 88 C 22 68 8 50 14 32 C 19 17 38 14 50 28 C 62 14 81 17 86 32 C 92 50 78 68 50 88 Z'/%3E%3Cpath d='M50 28 L 41 42 L 57 52 L 44 64 L 53 74 L 50 88'/%3E%3C/g%3E%3Cg transform='translate(610,12) scale(0.30)'%3E%3Cpath d='M50 88 C 22 68 8 50 14 32 C 19 17 38 14 50 28 C 62 14 81 17 86 32 C 92 50 78 68 50 88 Z'/%3E%3Cpath d='M50 28 L 41 42 L 57 52 L 44 64 L 53 74 L 50 88'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}

*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  min-height: 100%;
  background: #040404;
}

body {
  margin: 0;
  min-height: 100%;
  overflow-x: hidden;
  background:
    radial-gradient(circle at top, rgba(255, 46, 196, 0.16), transparent 24%),
    linear-gradient(180deg, #000 0%, #070708 50%, #000 100%);
  color: var(--text);
  font-family: var(--font-body);
  font-weight: 500;
  line-height: var(--lh-body);
  letter-spacing: 0.005em;
  position: relative;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* The diagonal "BROKEN BAGS" + broken-heart tile — at ~5% so it reads as
   ambience, not noise. Tile lives in --bb-monogram (single source of truth);
   the /local menu re-uses it axis-aligned for its iOS-locked scroll. */
body.brand-bg::before {
  content: "";
  position: fixed;
  inset: -60vmax;
  background-image: var(--bb-monogram);
  background-repeat: repeat;
  background-position: center;
  background-size: 760px 220px;
  transform: rotate(-18deg) scale(1.08);
  transform-origin: center;
  pointer-events: none;
  z-index: 0;
  /* Premium wall, not flat wallpaper: a hair of dark offset embosses the marks
     (carved into a dark surface), and a soft radial vignette lets the texture
     fade toward the corners — ambience under one light. Radii in vmax so the
     fade lands at viewport scale despite the oversized rotated layer. */
  filter: drop-shadow(0 0.5px 0 rgba(0, 0, 0, 0.55));
  -webkit-mask: radial-gradient(circle at 50% 50%, #000 22vmax, rgba(0, 0, 0, 0.5) 52vmax, transparent 82vmax);
          mask: radial-gradient(circle at 50% 50%, #000 22vmax, rgba(0, 0, 0, 0.5) 52vmax, transparent 82vmax);
}
/* Ambient neon glow — a fixed, soft magenta haze so the pink reads as a sign
   actually LIGHTING the dark vault, not just pink graphics: strongest up top
   (where the sign hangs), faint plum spill at the lower corners. Sits behind
   content, above the monogram. pointer-events:none + an opacity-ONLY breathe =
   GPU-safe (no transform repaint) even on the iOS-locked /local menu; the
   global reduced-motion block holds it static for those users. */
body.brand-bg::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(78% 50% at 50% -8%, rgba(255, 46, 196, 0.15), transparent 70%),
    radial-gradient(48% 38% at 6% 24%, rgba(255, 46, 196, 0.055), transparent 68%),
    radial-gradient(52% 42% at 94% 32%, rgba(180, 60, 220, 0.06), transparent 68%),
    radial-gradient(95% 45% at 50% 112%, rgba(255, 46, 196, 0.05), transparent 72%);
  animation: bb-ambient-glow 11s ease-in-out infinite alternate;
}
@keyframes bb-ambient-glow {
  from { opacity: 0.72; }
  to   { opacity: 1; }
}
body.brand-bg > *:not(.bb-loader):not(.bb-atmos):not(.bb-tabbar):not(.bb-sheet):not(.bb-progress):not(.bb-intro):not(.bb-skip) { position: relative; z-index: 1; }

a { color: inherit; text-decoration: none; }
a:hover { color: var(--text); text-decoration: underline; text-decoration-color: rgba(255, 46, 196, 0.5); }

img { display: block; max-width: 100%; height: auto; }
hr  { border: 0; border-top: 1px solid var(--line); margin: 28px 0; }

code, .copybox code {
  background: var(--panel-soft);
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 13px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: var(--text);
  border: 1px solid var(--line);
}

.muted { color: var(--muted); }
.small { font-size: 13px; font-weight: 500; line-height: 1.5; }
p { color: var(--text); }
p.muted, .muted p, .muted { line-height: 1.55; }

/* Display face — large/headline type only. Small uppercase labels (h2, .kicker,
   nav, pills, table heads) intentionally stay in the grotesque for legibility.
   Clash Display tops out at 700, so existing 800/900 requests render its Bold. */
h1, h3,
.hero__title,
.me-hero .greeting,
.kpi .value,
.trust b,
.display { font-family: var(--font-display); }

/* ── Site shell ───────────────────────────────────────────────────────── */
.site-shell { width: var(--content-width); margin: 0 auto; }

.site-header {
  padding: 12px 0 9px;
  background: linear-gradient(180deg, rgba(5, 5, 6, 0.97), rgba(5, 5, 6, 0.92));
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.site-header__inner {
  display: flex; align-items: center; gap: 14px;
  flex-wrap: wrap;                      /* admin nav has many items — allow row 2 */
  width: min(1200px, calc(100vw - 32px));
  margin: 0 auto;
}
.site-branding { display: flex; align-items: center; gap: 12px; }
.site-logo {
  width: 36px; height: 36px;
  filter: drop-shadow(0 10px 24px rgba(255, 46, 196, 0.18));
  transition: filter 240ms ease;
}
.site-title {
  margin: 0;
  font-size: 0.7rem; letter-spacing: 0.34em;
  text-transform: uppercase; font-weight: 700;
  white-space: nowrap;                  /* keep "Broken Bags" on one line */
}
.site-nav {
  margin-left: auto;
  display: flex; align-items: center;
  gap: 10px 16px;                       /* row-gap when wrapping, column-gap between items */
  flex-wrap: wrap;                      /* let overflow drop to a new row instead of squeezing */
  justify-content: flex-end;
}
.site-nav a {
  color: var(--muted);                  /* was rgba(244,244,242,0.58) — too dim */
  font-size: 0.72rem;
  letter-spacing: 0.20em;               /* was 0.28em — tighter for legibility */
  text-transform: uppercase;
  font-weight: 700;
  transition: color 160ms ease;
  white-space: nowrap;                  /* never break multi-word labels mid-link */
}
.site-nav a:hover { color: var(--text); text-decoration: none; }
.site-nav .who { color: var(--muted-soft); font-size: 11px; letter-spacing: 0.14em; white-space: nowrap; }

.content { width: var(--content-width); margin: 28px auto 0; padding: 0; }
.site-footer__inner {
  width: var(--content-width); margin: 60px auto 32px;
  padding-top: 18px; border-top: 1px solid var(--line);
  color: var(--muted); font-size: 0.74rem;
  text-transform: uppercase; letter-spacing: 0.22em;
  text-align: center;
}

/* ── Hero (used on landing + login) ────────────────────────────────────── */
.hero { padding: 42px 0 22px; }
.hero__wrap {
  width: min(920px, calc(100vw - 32px));
  margin: 0 auto;
  display: grid; justify-items: center; text-align: center;
  padding: 24px 0 18px;
}
.bb-brand-lockup { margin-bottom: 22px; }
.bb-brand-image--hero {
  width: min(220px, 42vw);
  filter: drop-shadow(0 18px 36px rgba(255, 46, 196, 0.10));
}
.bb-brand-image--small { width: min(96px, 28vw); }
.hero__eyebrow {
  margin: 0 0 10px;
  font-size: 0.68rem; letter-spacing: 0.34em;
  text-transform: uppercase; color: var(--accent);
}
.hero__title {
  margin: 0;
  font-size: clamp(2.8rem, 6vw, 5rem);
  line-height: 0.98;
  font-weight: 700;
  letter-spacing: -0.015em;
  text-transform: uppercase;
}
.hero__title .accent { color: var(--accent); }
.hero__text {
  max-width: 640px; margin: 14px auto 0;
  color: rgba(244, 244, 242, 0.68); font-size: 0.98rem;
}

/* ── Buttons (verbatim from theme) ────────────────────────────────────── */
.button, .button-link, button.btn,
input[type="submit"] {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 12px 22px;
  border: 0; border-radius: var(--radius-btn);
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  color: #fff;
  font-weight: 700;
  font-family: inherit; font-size: 0.86rem;
  cursor: pointer;
  transition: transform 180ms ease, filter 180ms ease;
  letter-spacing: 0.18em; text-transform: uppercase;
  box-shadow: 0 14px 30px rgba(255, 46, 196, 0.22);
}
.button:hover, .button-link:hover, button.btn:hover,
input[type="submit"]:hover {
  transform: translateY(-1px); filter: brightness(1.04);
  text-decoration: none; color: #fff;
}
.button.ghost {
  background: rgba(255, 255, 255, 0.02);
  color: var(--text);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: none;
}
.button.ghost:hover { border-color: rgba(255, 255, 255, 0.32); filter: none; }

/* ── Panels (entry-card style) ────────────────────────────────────────── */
.entry-card, .panel {
  padding: 24px;
  background: rgba(13, 13, 15, 0.97);   /* was 0.92 — watermark was bleeding through */
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

h1, h2, h3 { font-weight: 800; }
h1 {
  margin: 0 0 18px;
  font-size: clamp(1.6rem, 2.4vw, 2.2rem);
  line-height: 1; text-transform: uppercase;
  letter-spacing: -0.02em;
  color: var(--text);
}
h2 {
  margin: 32px 0 14px;
  font-size: 0.86rem;        /* was 0.78 — too small to read at 0.24em tracking */
  letter-spacing: 0.16em;    /* was 0.24em — too sparse hurt scanning */
  text-transform: uppercase;
  color: var(--text);        /* was 78% alpha — full strength now */
  font-weight: 800;
}
h3 { color: var(--text); font-size: 1rem; }
.kicker {
  font-size: 0.72rem; color: var(--muted);
  font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.18em;
  margin: 0 0 8px;
}

/* ── Tables ───────────────────────────────────────────────────────────── */
.table {
  width: 100%; border-collapse: collapse;
  background: rgba(13, 13, 15, 0.97);   /* was 0.92 */
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.table th, .table td {
  text-align: left;
  padding: 13px 16px;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
  color: var(--text);
}
.table th {
  font-weight: 800; color: var(--text); font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.14em;   /* was 0.22 */
  background: rgba(0, 0, 0, 0.45);
}
.table tr:last-child td { border-bottom: 0; }
.table tr:hover td { background: rgba(255, 255, 255, 0.04); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }
.table .muted, .table td.muted { color: var(--muted); }

/* ── Pills (status / tag) ─────────────────────────────────────────────── */
.pill {
  display: inline-block;
  padding: 4px 11px; border-radius: 999px;
  font-size: 10px; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.12em;   /* was 0.18 — tighter reads cleaner */
  border: 1px solid var(--line-strong);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text);
}
.pill.good { color: #7eea9a; border-color: rgba(110,224,141,0.5); background: rgba(110,224,141,0.08); }
.pill.warn { color: #fbcd76; border-color: rgba(247,196,102,0.5); background: rgba(247,196,102,0.08); }
.pill.bad  { color: #ff8a8a; border-color: rgba(255,118,118,0.5); background: rgba(255,118,118,0.08); }
.pill.red  { color: var(--accent-strong); border-color: rgba(255,46,196,0.55); background: rgba(255,46,196,0.10); }

/* ── KPI cards ────────────────────────────────────────────────────────── */
.kpi-row {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  margin: 0 0 28px;
}
.kpi {
  padding: 20px 22px;
  background: rgba(13, 13, 15, 0.97);   /* was 0.92 — solid against watermark */
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
}
.kpi .label {
  color: var(--muted); font-size: 11px;
  font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.14em;   /* was 0.22 */
}
.kpi .value {
  font-size: 1.95rem; font-weight: 800; margin-top: 8px;
  letter-spacing: -0.02em;
  color: var(--text);
}
.kpi .delta { font-size: 13px; font-weight: 600; margin-top: 6px; color: var(--muted-soft); }
.kpi .delta.pos { color: #6ee07b; }
.kpi.accent { border-color: rgba(255, 46, 196, 0.55); box-shadow: 0 14px 30px rgba(255, 46, 196, 0.18); }
.kpi.accent .value { color: var(--accent); }

/* ── Tier badge ───────────────────────────────────────────────────────── */
.tier-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px; border-radius: 999px;
  font-size: 0.66rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.22em;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid var(--line);
  color: var(--text);
}
.tier-badge.t-Member   { color: #b8b8c0; }
.tier-badge.t-Bronze   { color: #c47a4a; border-color: rgba(196,122,74,0.35); }
.tier-badge.t-Silver   { color: #c4c4cc; border-color: rgba(196,196,204,0.35); }
.tier-badge.t-Gold     { color: #f0c060; border-color: rgba(240,192,96,0.45); }
.tier-badge.t-Platinum { color: #d6e6f0; border-color: rgba(214,230,240,0.45); }
.tier-badge.t-Diamond  { color: #fff; border-color: var(--accent);
                         background: linear-gradient(180deg, rgba(255,46,196,0.18), rgba(11,11,12,0.92)); }

/* ── Welcome / countdown bar ──────────────────────────────────────────── */
.welcome-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  padding: 16px 20px;
  background: linear-gradient(90deg, rgba(255,46,196,0.20), rgba(255,46,196,0.04));
  border: 1px solid rgba(255,46,196,0.45);
  border-radius: var(--radius-md);
  margin-bottom: 22px;
}
.welcome-bar .gift { font-size: 22px; }
.welcome-bar b { color: var(--accent); }
.welcome-bar .countdown {
  margin-left: auto; font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-size: 0.7rem; letter-spacing: 0.20em; text-transform: uppercase;
}

/* ── Progress bar ─────────────────────────────────────────────────────── */
.progress {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line);
  border-radius: 999px;
  height: 12px; overflow: hidden;
}
.progress > .fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-strong));
  transition: width 0.4s ease;
}
.progress-row {
  display: flex; justify-content: space-between;
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--muted); margin: 12px 0 8px;
}

/* ── /me hero (greeting + tier badge) ─────────────────────────────────── */
.me-hero {
  padding: 22px 24px;
  background: rgba(11, 11, 12, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  margin-bottom: 22px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 18px;
}
.me-hero .greeting {
  font-size: 1.7rem; font-weight: 800; line-height: 1;
  letter-spacing: -0.02em; text-transform: uppercase;
}

/* ── Copy box (referral link, magic links, etc.) ──────────────────────── */
.copybox {
  display: flex; gap: 10px; align-items: center;
  padding: 10px 14px;
  background: var(--panel-soft);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--radius-sm);
  margin: 12px 0;
}
.copybox code {
  background: transparent; padding: 0; flex: 1; font-size: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.copybox button {
  min-height: 44px; padding: 9px 16px;
  font-size: 0.66rem; letter-spacing: 0.16em; font-weight: 800;
  text-transform: uppercase; font-family: var(--font-body);
  border: 0; border-radius: var(--radius-sm); cursor: pointer;
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  color: #fff;
  transition: filter 160ms ease, transform 160ms ease;
}
.copybox button:hover { filter: brightness(1.08); transform: translateY(-1px); }
.copybox button.ghost {
  background: rgba(255, 255, 255, 0.04); color: var(--text);
  border: 1px solid var(--line-strong);
}
.copybox button.ghost:hover { border-color: var(--accent); filter: none; }

/* ── Mail feed (status + credit events) ───────────────────────────────── */
.mail {
  background: rgba(11, 11, 12, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.mail .row {
  display: flex; gap: 14px; padding: 14px 18px;
  border-bottom: 1px solid var(--line); font-size: 14px; font-weight: 500;
}
.mail .row:last-child { border-bottom: 0; }
.mail .icon { font-size: 18px; line-height: 1.2; }
.mail .body { flex: 1; }
.mail .body .when {
  color: var(--muted); font-size: 11px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase; margin-top: 4px;
}

/* ── Trust counters strip (used on /go landing) ───────────────────────── */
.trust {
  display: flex; gap: 14px; justify-content: center; flex-wrap: wrap;
  max-width: 720px; margin: 36px auto 0;
}
.trust > div {
  flex: 1 1 140px; min-width: 130px;
  padding: 16px 18px; text-align: center;
  background: rgba(11, 11, 12, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-md);
}
.trust b { display: block; font-size: 1.4rem; font-weight: 800; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.trust span {
  display: block; margin-top: 4px;
  color: var(--muted); font-size: 10px;
  text-transform: uppercase; letter-spacing: 0.22em;
}

/* ── Recent-orders ticker ─────────────────────────────────────────────── */
.ticker {
  max-width: 720px; margin: 26px auto 0;
  padding: 18px 22px;
  background: rgba(11, 11, 12, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-md);
}
.ticker .kicker { color: var(--accent); }
.ticker .row {
  display: flex; align-items: baseline;
  gap: 28px;
  padding: 11px 0; font-size: 14px;
  border-top: 1px solid var(--line);
}
.ticker .row:first-of-type { border-top: 0; }
.ticker .row .who {
  color: var(--text);
  flex: 1 1 auto; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ticker .row .when {
  color: var(--muted); font-size: 11px; letter-spacing: 0.18em;
  text-transform: uppercase;
  flex: 0 0 auto; white-space: nowrap;
  margin-left: auto;
}

/* ── Auth card (login / login-denied) ─────────────────────────────────── */
.auth-card {
  width: min(560px, 100%);
  margin: 60px auto 0;
  padding: 36px 40px;
  background: linear-gradient(180deg, #17171b 0%, #0d0d0f 100%);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--radius-lg);
  box-shadow: 0 30px 70px -22px rgba(0,0,0,0.7), inset 0 1px 0 rgba(255,255,255,0.06);
  text-align: center;
}
.auth-card h1 {
  margin: 0 0 8px;
  font-size: 1.2rem; line-height: 1.1;
  text-transform: none; letter-spacing: 0;
}
.auth-card p { max-width: 42ch; margin: 0 auto 18px; color: var(--muted); }
.auth-card .button { margin-top: 6px; }

/* ── Nav micro-styles (lifted out of base.html inline <style>) ────────── */
.nav-sep { color: rgba(255, 255, 255, .20); margin: 0 .15rem; user-select: none; }
.site-nav a[href]:hover { color: var(--accent); }

/* ══════════════════════════════════════════════════════════════════════
 * SHARED COMPONENTS (added in the level-up — pages migrate onto these and
 * delete their per-page <style> duplicates). Names are new so legacy
 * classes keep working until each page is converted.
 * ════════════════════════════════════════════════════════════════════ */

/* ── Earn-pulse: the one focal "earning now" red card ─────────────────── */
.earn-pulse {
  position: relative; overflow: hidden;
  padding: 26px 28px;
  border-radius: var(--radius-lg);
  border: 1px solid rgba(255, 46, 196, 0.40);
  background:
    radial-gradient(120% 140% at 0% 0%, rgba(255, 46, 196, 0.16), transparent 55%),
    linear-gradient(180deg, rgba(22, 9, 10, 0.96), rgba(11, 11, 12, 0.96));
  box-shadow: var(--shadow-md);
}
.earn-pulse::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(60% 120% at 100% 0%, rgba(255, 46, 196, 0.22), transparent 60%);
  animation: bb-earn-glow 3.6s ease-in-out infinite;
}
.earn-pulse > * { position: relative; z-index: 1; }
.earn-pulse__live {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 0.64rem; font-weight: 800; letter-spacing: 0.20em; text-transform: uppercase;
  color: #7eea9a;   /* green = "live / earning now", matching the site-wide convention */
  background: rgba(110, 224, 141, 0.10);
  border: 1px solid rgba(110, 224, 141, 0.38);
  padding: 4px 11px; border-radius: var(--radius-pill);
}
.earn-pulse__live::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: #7eea9a; box-shadow: 0 0 8px rgba(126, 234, 154, 0.9);
  animation: bb-shimmer-dot 1.6s ease-in-out infinite;
}
.earn-pulse__headline {
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--step-3); line-height: var(--lh-tight);
  letter-spacing: -0.01em; margin: 12px 0 6px;
}
.earn-pulse__body { color: var(--muted); font-size: var(--step-0); margin: 0 0 18px; max-width: 54ch; }
@keyframes bb-earn-glow { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }

/* ── Feature card / grid: the one elevated surface tile ───────────────── */
.feature-grid {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.feature-card {
  display: block; padding: 20px;
  background: var(--panel-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  transition: transform 220ms cubic-bezier(.2, .7, .2, 1),
              border-color 220ms ease, box-shadow 220ms ease;
}
a.feature-card, .feature-card[href] { color: inherit; }
.feature-card:hover {
  transform: translateY(-3px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-md), var(--ring-accent);
  text-decoration: none;
}
.feature-card__title { font-family: var(--font-display); font-weight: 600; font-size: var(--step-1); margin: 0 0 5px; letter-spacing: -0.01em; }
.feature-card__desc  { color: var(--muted); font-size: var(--step--1); margin: 0; line-height: 1.5; }

/* ── Form controls: the missing input system ──────────────────────────── */
.field { display: block; margin: 0 0 16px; }
.field__label {
  display: block; margin: 0 0 7px;
  font-size: 0.7rem; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--muted);
}
.input, .select, .textarea,
.field input, .field select, .field textarea {
  width: 100%; padding: 13px 15px;
  background: var(--panel-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: var(--font-body); font-size: var(--step-0); font-weight: 500;
  line-height: 1.4;
  transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease;
  -webkit-appearance: none; appearance: none;
}
.input::placeholder, .textarea::placeholder,
.field input::placeholder, .field textarea::placeholder { color: var(--muted-soft); }
.input:focus, .select:focus, .textarea:focus,
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: rgba(255, 46, 196, 0.55);
  box-shadow: var(--focus-ring);
  background: #161618;
}
.textarea, .field textarea { min-height: 110px; resize: vertical; }
.select, .field select {
  padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23a8a8ae' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center; background-size: 12px;
}
.field__hint { margin: 7px 0 0; font-size: var(--step--1); color: var(--muted-soft); }

/* ── Chip: the one filter/tag chip (promotes the inline admin pattern) ── */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: var(--radius-pill);
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.10em; text-transform: uppercase;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--line);
  white-space: nowrap;
  transition: color 160ms ease, border-color 160ms ease, background 160ms ease;
}
.chip:hover { color: var(--text); border-color: var(--line-strong); text-decoration: none; }
.chip.is-active, .chip--active {
  color: #fff; border-color: transparent;
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  box-shadow: 0 8px 20px rgba(255, 46, 196, 0.25);
}

/* Cashout currency selector: a visually-hidden native radio + .cur-card label.
   The card lights up when its radio is checked / keyboard-focused. */
.cur-card { transition: background 160ms ease, box-shadow 160ms ease; }
input:checked + .cur-card { background: var(--accent); color: #050505; box-shadow: 0 0 20px var(--accent-soft); }
input:focus-visible + .cur-card { box-shadow: var(--focus-ring); }

/* ── Mobile ──────────────────────────────────────────────────────────── */
@media (max-width: 800px) {
  .site-header__inner { flex-wrap: wrap; }
  .site-nav a:not(.who):not(.logout) { display: none; }
}
@media (max-width: 560px) {
  :root { --content-width: min(100vw - 24px, 100%); }
  .hero { padding-top: 24px; }
  .hero__wrap { padding: 16px 0 6px; }
  .auth-card { padding: 28px 22px; }
}

/* ── Animations & micro-interactions ─────────────────────────────────── */

@keyframes bb-fade-up {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes bb-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes bb-pulse-warn {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245, 165, 36, 0.45); }
  50%      { box-shadow: 0 0 0 6px rgba(245, 165, 36, 0); }
}

@keyframes bb-pulse-red {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 46, 196, 0.55); }
  60%      { box-shadow: 0 0 0 8px rgba(255, 46, 196, 0); }
}

@keyframes bb-shimmer-dot {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.55; transform: scale(0.85); }
}

@keyframes bb-progress-fill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* Hero / auth cards: subtle fade-up on load */
.hero__wrap > *,
.auth-card > *,
.go-hero > *,
.me-hero { animation: bb-fade-up 540ms cubic-bezier(.2,.7,.2,1) both; }
.hero__wrap > *:nth-child(1) { animation-delay: 0ms; }
.hero__wrap > *:nth-child(2) { animation-delay: 80ms; }
.hero__wrap > *:nth-child(3) { animation-delay: 160ms; }
.hero__wrap > *:nth-child(4) { animation-delay: 240ms; }
.hero__wrap > *:nth-child(5) { animation-delay: 320ms; }
.hero__wrap > *:nth-child(n+6) { animation-delay: 400ms; }

/* KPI cards: stagger on entrance */
.kpi-row .kpi { animation: bb-fade-up 480ms cubic-bezier(.2,.7,.2,1) both; }
.kpi-row .kpi:nth-child(1) { animation-delay:  20ms; }
.kpi-row .kpi:nth-child(2) { animation-delay:  90ms; }
.kpi-row .kpi:nth-child(3) { animation-delay: 160ms; }
.kpi-row .kpi:nth-child(4) { animation-delay: 230ms; }
.kpi-row .kpi:nth-child(5) { animation-delay: 300ms; }
.kpi-row .kpi:nth-child(6) { animation-delay: 370ms; }

/* Trust counters strip */
.trust > div { animation: bb-fade-up 520ms cubic-bezier(.2,.7,.2,1) both; }
.trust > div:nth-child(1) { animation-delay: 320ms; }
.trust > div:nth-child(2) { animation-delay: 380ms; }
.trust > div:nth-child(3) { animation-delay: 440ms; }
.trust > div:nth-child(4) { animation-delay: 500ms; }

/* Live-orders ticker rows */
.ticker .row { animation: bb-fade-up 360ms cubic-bezier(.2,.7,.2,1) both; }
.ticker .row:nth-child(1) { animation-delay: 540ms; }
.ticker .row:nth-child(2) { animation-delay: 600ms; }
.ticker .row:nth-child(3) { animation-delay: 660ms; }
.ticker .row:nth-child(4) { animation-delay: 720ms; }
.ticker .kicker::before {
  content: "";
  display: inline-block; width: 7px; height: 7px;
  border-radius: 50%; background: var(--accent);
  margin-right: 6px; vertical-align: 2px;
  animation: bb-shimmer-dot 1.4s ease-in-out infinite;
}

/* Mail rows: stagger fade-in */
.mail .row { animation: bb-fade-up 360ms cubic-bezier(.2,.7,.2,1) both; }
.mail .row:nth-child(1) { animation-delay:  0ms; }
.mail .row:nth-child(2) { animation-delay: 60ms; }
.mail .row:nth-child(3) { animation-delay: 120ms; }
.mail .row:nth-child(4) { animation-delay: 180ms; }
.mail .row:nth-child(5) { animation-delay: 240ms; }

/* Status pills: pulsing accent for in-flight statuses */
.pill.warn { animation: bb-pulse-warn 2.4s ease-in-out infinite; }

/* Welcome credit bar: gentle attention pulse */
.welcome-bar { animation: bb-fade-up 480ms cubic-bezier(.2,.7,.2,1) both,
                          bb-pulse-red 3.2s ease-in-out 1.2s infinite; }

/* Progress bar fill — animate from left edge */
.progress > .fill {
  transform-origin: left center;
  animation: bb-progress-fill 900ms cubic-bezier(.2,.7,.2,1) 200ms both;
}

/* Buttons: smoother lift + red glow on hover */
.button, .button-link, button.btn, input[type="submit"] {
  transition: transform 180ms cubic-bezier(.2,.7,.2,1),
              filter 180ms ease,
              box-shadow 240ms ease;
}
.button:hover, .button-link:hover, button.btn:hover, input[type="submit"]:hover {
  transform: translateY(-2px);
  filter: brightness(1.08);
  box-shadow: 0 18px 38px rgba(255, 46, 196, 0.30),
              0 0 0 1px rgba(255, 255, 255, 0.04) inset;
}
.button:active { transform: translateY(0); }

/* Topbar logo: subtle glow on hover */
.site-branding:hover .site-logo {
  filter: drop-shadow(0 12px 28px rgba(255, 46, 196, 0.32));
}

/* Media tiles: smoother hover lift (already had basic) */
.media-tile img {
  transition: transform 260ms cubic-bezier(.2,.7,.2,1),
              box-shadow 260ms ease,
              border-color 260ms ease !important;
}

/* Page-level fade-in to soften route transitions */
main.content { animation: bb-fade-in 280ms ease-out both; }

/* Reduced-motion users get no movement, just opacity-snap */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
  .pill.warn, .welcome-bar { animation: none !important; }
}

/* ──────────────────────────────────────────────────────────────────────────
 * Mobile polish — small screens (≤640px). Keep desktop unchanged.
 * Goal: nothing horizontal-scrolls, tap targets are thumb-friendly,
 * dense tables fall back to a stacked card layout when they'd overflow.
 * ────────────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  :root { --content-width: calc(100vw - 24px); }
  .content   { padding: 0; margin-top: 16px; }
  h1         { font-size: clamp(1.4rem, 6vw, 1.8rem); }
  h2         { font-size: 0.8rem; letter-spacing: 0.12em; margin: 22px 0 10px; }

  /* Site header — thinner; branding + sign-out share row 1, nav wraps to row 2 */
  .site-header { padding: 4px 0; }
  .site-header__inner {
    position: relative;                /* anchor for the absolute sign-out */
    flex-wrap: wrap;
    width: calc(100vw - 24px);
    gap: 4px 14px;
    padding: 0;
    padding-right: 78px;               /* keep branding text clear of sign-out */
  }
  .site-nav {
    margin-left: 0;
    gap: 12px;
    flex-wrap: wrap;
    width: 100%;
    justify-content: flex-start;
  }
  .site-nav a {
    display: inline-block;             /* override the 800px rule that hides nav links */
    font-size: 0.66rem;
    letter-spacing: 0.16em;
    padding: 4px 0;
  }
  .site-nav .who { display: none; }    /* save space; user knows who they are */
  .site-nav .logout {                  /* hangs at the right, level with the logo */
    position: absolute;
    top: 0;
    right: 0;
    height: 36px;                      /* matches .site-logo height for vertical alignment */
    display: flex;
    align-items: center;
    padding: 0;
  }
  .site-title    { font-size: 0.62rem; letter-spacing: 0.24em; }

  /* KPI grid: 2 columns minimum, but allow phones to drop to single column */
  .kpi-row { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
  .kpi     { padding: 16px 16px; }
  .kpi .value { font-size: 1.55rem; }
  .kpi .label { font-size: 10px; letter-spacing: 0.12em; }

  /* Card padding tightens up — was eating 1/4 of the viewport */
  .entry-card, .panel { padding: 18px 16px; border-radius: 16px; }

  /* Tables that would overflow get a horizontal scroll wrapper instead of
     breaking out of the page. Wrap any .table in a div.table-wrap on
     templates that need it, or rely on the fallback below. */
  .table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
  }
  .table th, .table td {
    padding: 10px 12px;
    font-size: 13px;
  }
  .table th {
    font-size: 10px;
    letter-spacing: 0.10em;
  }

  /* Make every clickable button at least 44px tall for finger taps */
  .button { padding: 12px 20px; min-height: 44px; font-size: 13px; }

  /* The /me hero — name + tier pill stack on small screens */
  .me-hero { flex-direction: column; align-items: flex-start; gap: 10px; }
  .me-hero .tier-badge { margin-left: 0; }

  /* Welcome credit bar wraps */
  .welcome-bar { flex-wrap: wrap; gap: 8px 14px; padding: 14px 16px; }
  .welcome-bar .countdown { margin-left: 0; font-size: 12px; }

  /* Copy box: input stretches, buttons drop below */
  .copybox { flex-wrap: wrap; gap: 8px; }
  .copybox code  { flex-basis: 100%; min-width: 0; word-break: break-all; }
  .copybox button { flex: 1; }

  /* /me KPI row: tighter 2-col grid + smaller card padding */
  .kpi-row { grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 18px; }
  .kpi { padding: 12px 12px; }
  .kpi .label { font-size: 9px; letter-spacing: 0.10em; }
  .kpi .value { font-size: 1.3rem; }
  .kpi .delta { font-size: 11px; }

  /* /me Refer & Earn focal card — less padding, smaller halo */
  .me-earn-card { padding: 18px 16px; margin: 16px 0 22px; }
  .me-earn-card__headline { font-size: 1.25rem; }
  .me-earn-card__body { font-size: 13px; margin-bottom: 12px; }

  /* /me mail feed — tighter rows */
  .mail .row { gap: 10px; padding: 10px 14px; }
  .mail .icon { font-size: 18px; }
  .mail .body { font-size: 13px; }
  .mail .when { font-size: 10px; margin-top: 3px; }

  /* /me order history table — already wraps via .table block, but
     tighten cells a notch further for small screens */
  .table th { padding: 8px 10px; font-size: 10px; }
  .table td { padding: 8px 10px; font-size: 12px; }
  .pill { font-size: 9px; padding: 3px 8px; }

  /* Quick links button row — wrap cleanly */
  main .content p a.cta { display: block; margin-bottom: 8px; text-align: center; }

  /* Site footer */
  .site-footer__inner { font-size: 10px; padding: 16px 0; }
}

/* Even smaller — narrow phones. Tightens further. */
@media (max-width: 380px) {
  .kpi-row     { grid-template-columns: 1fr; }
  .button      { padding: 11px 16px; font-size: 12px; }
  .site-nav a  { font-size: 0.60rem; letter-spacing: 0.12em; }
  h1           { font-size: 1.3rem; }
}

/* ══════════════════════════════════════════════════════════════════════
 * OBSIDIAN LEDGER — site-wide elevation + ledger polish (2026-06)
 * Appended last so it refines the shared components above without a rewrite.
 * Surfaces feel milled (a 1px top bevel), numbers read like a ledger
 * (tabular), interactions feel tactile (tap-scale), and the one motion
 * gesture is the accent "hairline wipe". Everything is transform/opacity +
 * box-shadow, so it holds 60fps on a phone and the global
 * prefers-reduced-motion block above already disables the motion.
 * ════════════════════════════════════════════════════════════════════ */
:root {
  --e1: #0d0d0f;
  --e2: #131316;
  --e3: #17171b;
  --bevel: inset 0 1px 0 rgba(255, 255, 255, 0.055);
  --bevel-2: inset 0 1px 0 rgba(255, 255, 255, 0.05), inset 0 -1px 0 rgba(0, 0, 0, 0.5);
  --glow-edge: inset 0 1px 0 rgba(255, 227, 246, 0.18);
  --accent-line: linear-gradient(90deg, transparent, var(--accent) 55%, transparent);
  --gold: #f0c060;
}

/* Pressed-metal: a milled top-bevel + lit-from-above gradient on the key
   customer-facing surfaces (these read from style.css, not page-inline CSS,
   so the upgrade lands without touching each template). */
.kpi,
.feature-card,
.trust > div,
.ticker,
.mail,
.me-hero {
  background: linear-gradient(180deg, var(--e3), var(--e1));
  box-shadow: var(--shadow-md), var(--bevel-2), var(--glow-edge);
}
.kpi.accent {
  background: linear-gradient(180deg, rgba(255, 46, 196, 0.06), var(--e1));
  box-shadow: 0 14px 30px rgba(255, 46, 196, 0.18), var(--bevel);
}

/* Ledger numerals — align prices/stats in tabular columns site-wide.
   These selectors don't set font-variant-numeric inline, so this applies
   cleanly through the cascade. */
.kpi .value,
.trust b,
.ticker .row b,
.lb-row__stat b,
.me-hero .greeting,
.lb-hero__accent,
.welcome-bar .countdown {
  font-variant-numeric: tabular-nums;
}

/* Tactile tap-scale — the phone visibly responds under a thumb. Pure
   transition (no keyframes), so reduced-motion users get the static state. */
.kpi,
.feature-card,
.chip,
a.cta,
.copybox button {
  transition: transform 120ms cubic-bezier(.2, .7, .2, 1),
              filter 180ms ease, box-shadow 240ms ease, border-color 200ms ease;
}
.kpi:active,
.feature-card:active,
.chip:active,
a.cta:active { transform: scale(.985); }

/* Headlines never orphan a trailing word */
h1,
.hero__title,
.feature-card__title,
.lb-hero__headline,
.me-earn-card__headline,
.earn-hero__headline { text-wrap: balance; }

/* Progress fill gains the accent sheen + a faint glow */
.progress > .fill {
  box-shadow: 0 0 14px rgba(255, 46, 196, 0.45);
}

/* Accent-hairline reveal — the signature "wipe" gesture. Opt-in via .bb-wipe;
   a 1px accent rule grows from 0 when the element gets .is-in (set by an
   IntersectionObserver). Available to any page; used on the /local menu. */
.bb-wipe { position: relative; }
.bb-wipe::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--accent-line); transform: scaleX(0); transform-origin: left;
}
.bb-wipe.is-in::after { animation: bb-wipe-x .6s cubic-bezier(.2, .7, .2, 1) forwards; }
@keyframes bb-wipe-x { to { transform: scaleX(1); } }
/* Reduced-motion: the global reduce block disables the wipe animation, so
   show the hairline at full width rather than leaving it at scale 0. */
@media (prefers-reduced-motion: reduce) {
  .bb-wipe::after { transform: scaleX(1); }
}

/* ══════════════════════════════════════════════════════════════════════
 * MOTION + RICHNESS LAYER (2026-06) — adds the "wow": a site-wide
 * scroll-reveal system, a premium button light-sweep, card hover-glow,
 * and a reusable drifting-aurora atmosphere. All compositor-only
 * (transform/opacity), gated behind prefers-reduced-motion. The aurora
 * is OPT-IN (.bb-atmos element) so it never lands on /local, whose iOS
 * lockdown forbids fixed full-page overlays.
 * ════════════════════════════════════════════════════════════════════ */

/* ── Scroll reveal: elements fade+rise once as they enter the viewport.
   Add data-reveal to any element; data-reveal-delay="1..6" staggers it.
   base.html adds .revealed via IntersectionObserver (one-shot). ────── */
[data-reveal] {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .7s cubic-bezier(.2, .7, .2, 1),
              transform .7s cubic-bezier(.2, .7, .2, 1);
  will-change: opacity, transform;
}
[data-reveal].revealed { opacity: 1; transform: none; will-change: auto; }
[data-reveal][data-reveal-delay="1"] { transition-delay: .07s; }
[data-reveal][data-reveal-delay="2"] { transition-delay: .14s; }
[data-reveal][data-reveal-delay="3"] { transition-delay: .21s; }
[data-reveal][data-reveal-delay="4"] { transition-delay: .28s; }
[data-reveal][data-reveal-delay="5"] { transition-delay: .35s; }
[data-reveal][data-reveal-delay="6"] { transition-delay: .42s; }

/* ── Premium light-sweep on buttons (a diagonal sheen crosses on hover) ── */
.button, .button-link, button.btn, input[type="submit"] {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.button::after, .button-link::after, button.btn::after, input[type="submit"]::after {
  content: "";
  position: absolute; top: 0; left: -160%;
  width: 55%; height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.30), transparent);
  transform: skewX(-18deg);
  transition: left .65s cubic-bezier(.2, .7, .2, 1);
  pointer-events: none; z-index: 1;
}
.button:hover::after, .button-link:hover::after,
button.btn:hover::after, input[type="submit"]:hover::after { left: 160%; }
/* Idle auto-sweep for hero/primary CTAs (opt-in via .cta-glow) */
.cta-glow::after { animation: bb-sheen 4.5s ease-in-out 1.5s infinite; }
@keyframes bb-sheen {
  0%, 18% { left: -160%; }
  38%, 100% { left: 160%; }
}

/* ── Card hover-glow: a soft red bloom + lift on the elevated tiles ───── */
.feature-card:hover, .kpi:hover {
  box-shadow: var(--shadow-md), var(--bevel-2), var(--glow-edge),
              0 0 0 1px rgba(255, 46, 196, 0.18),
              0 22px 48px -28px rgba(255, 46, 196, 0.5);
}

/* ── Drifting aurora atmosphere (OPT-IN element: <div class="bb-atmos">).
   Three slow red radial blooms behind content — living depth without
   touching legibility. Safe on the /local GATE (short lock screen); never
   add it to the /local MENU (long scroll + iOS lockdown). ─────────────── */
.bb-atmos {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  animation: bb-aurora-drift 19s ease-in-out infinite alternate;
}
.bb-atmos::after {
  content: ""; position: absolute; inset: 0; opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}
@keyframes bb-aurora-drift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  100% { transform: translate3d(0, -3%, 0) scale(1.08); }
}

/* Reduced-motion: keep the reveal content visible, freeze the atmosphere. */
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .bb-atmos { animation: none !important; }
  .cta-glow::after { animation: none !important; }
}

/* ══════════════════════════════════════════════════════════════════════
 * NATIVE APP SHELL (2026-06) — the layer that turns the polished website
 * into a polished mobile *app*: a persistent bottom tab bar, native screen
 * transitions, an app-style top progress bar, a bottom sheet, and the small
 * platform tells (no tap-flash, no input zoom, safe-area aware, no
 * rubber-band). Everything is compositor-only + gated behind reduced-motion.
 * ════════════════════════════════════════════════════════════════════ */

:root { --tabbar-h: 66px; }   /* bar height excluding the bottom safe-area inset */

/* ── Platform tells: kill the "this is a web page" giveaways ───────────── */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
* { -webkit-tap-highlight-color: transparent; }                /* no blue tap flash */
body { overscroll-behavior-y: none; }                          /* no pull-to-refresh / bounce flash */

/* Chrome is not selectable (feels like UI, not a document); content stays
   selectable so prices, codes and referral links can still be copied. */
.site-header, .site-nav, .bb-tabbar, .bb-tab, .bb-sheet,
.button, .button-link, button.btn, .chip, .pill, .tier-badge, .kicker, .site-title {
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}

/* iOS auto-zooms any focused control with text < 16px. Force 16px on phones
   (covers the shared inputs + the /local request box) — no maximum-scale hack. */
@media (max-width: 640px) {
  input, select, textarea,
  .input, .select, .textarea,
  .field input, .field select, .field textarea,
  .request-box__field { font-size: 16px; }
}

/* ── Safe areas (notch + home indicator). Status bar is black-translucent,
   so it overlays content — the header and the headerless-page spacer both
   reserve the top inset. ──────────────────────────────────────────────── */
.site-header { padding-top: calc(12px + env(safe-area-inset-top, 0px)); }
.bb-statusbar-pad { height: env(safe-area-inset-top, 0px); }

/* ── Inline icon system (referenced from the #i-* sprite) ─────────────── */
.ti {
  width: 22px; height: 22px; display: inline-block; vertical-align: middle;
  flex: 0 0 auto; fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.ti--solid { fill: currentColor; stroke: none; }

/* ── Bottom tab bar — the headline native pattern. Mobile only; desktop
   keeps the top nav. ──────────────────────────────────────────────────── */
.bb-tabbar {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  align-items: stretch; justify-content: space-around; gap: 2px;
  padding: 6px 6px max(env(safe-area-inset-bottom, 0px), 8px);
  background: linear-gradient(180deg, rgba(12,12,14,0.82), rgba(6,6,7,0.96));
  -webkit-backdrop-filter: blur(20px) saturate(1.3);
  backdrop-filter: blur(20px) saturate(1.3);
  border-top: 1px solid var(--line);
  box-shadow: 0 -10px 34px rgba(0,0,0,0.5);
}
.bb-tab {
  position: relative; flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: 8px 4px 4px;
  background: none; border: 0; cursor: pointer; font-family: inherit;
  color: var(--muted-soft); text-decoration: none;
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.03em;
  transition: color 180ms ease, transform 130ms cubic-bezier(.2,.7,.2,1);
}
.bb-tab .ti { width: 24px; height: 24px; transition: transform 220ms cubic-bezier(.2,.7,.2,1); }
.bb-tab__lbl { line-height: 1; white-space: nowrap; }
.bb-tab:active { transform: scale(.9); }
.bb-tab:hover { color: var(--muted); text-decoration: none; }
.bb-tab.is-active { color: var(--text); }
.bb-tab.is-active .ti { color: var(--accent); transform: translateY(-1px); }

/* The lit indicator that hangs from the top edge of the active tab. Carries a
   view-transition-name so it slides between tabs across navigation. */
.bb-tab__ind {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 26px; height: 3px; border-radius: 0 0 4px 4px;
  background: linear-gradient(90deg, var(--accent), var(--accent-strong));
  box-shadow: 0 0 12px rgba(255,46,196,0.75);
  opacity: 0; transition: opacity 180ms ease;
}
.bb-tab.is-active .bb-tab__ind { opacity: 1; }

/* Customer "Shop" tab — the primary action, rendered as an accent FAB pill. */
.bb-tab--accent .ti {
  color: #fff; width: 34px; height: 34px; padding: 7px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  box-shadow: 0 6px 16px rgba(255,46,196,0.42);
}
.bb-tab--accent { color: var(--accent-strong); }
.bb-tab--accent:active .ti { transform: scale(.9); }
/* When the accent tab is also the current page, keep its glyph white — the
   generic .is-active rule would otherwise tint it red-on-red inside the FAB. */
.bb-tab--accent.is-active .ti { color: #fff; }

/* Unread badge on the admin "More" tab. */
.bb-tab__dot {
  position: absolute; top: 7px; left: calc(50% + 7px);
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 7px rgba(255,46,196,0.85);
}

@media (max-width: 900px) {
  .bb-tabbar { display: flex; }
  body.has-tabbar { padding-bottom: calc(var(--tabbar-h) + max(env(safe-area-inset-bottom, 0px), 8px)); }
  /* The bottom bar owns navigation now — retire the wrapped top-nav links
     (keep sign-out reachable in the header; admin overflow lives in the sheet). */
  body.has-tabbar .site-nav a:not(.logout) { display: none; }
  body.has-tabbar .site-nav .who { display: none; }
  /* The bottom bar already surfaces Shop + Catalog, so the /me dashboard's
     duplicate quick-action pills are redundant on mobile — hide them (desktop
     keeps them; it has no tab bar). Inline display:flex needs !important. */
  body.has-tabbar .me-quickactions { display: none !important; }
}

/* ── Bottom sheet (admin "More") ──────────────────────────────────────── */
.bb-sheet { position: fixed; inset: 0; z-index: 80; }
.bb-sheet[hidden] { display: none; }
.bb-sheet__scrim {
  position: absolute; inset: 0; background: rgba(0,0,0,0.55);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  opacity: 0; transition: opacity 0.26s ease;
}
.bb-sheet.is-open .bb-sheet__scrim { opacity: 1; }
.bb-sheet__panel {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: linear-gradient(180deg, var(--e3), var(--e1));
  border-top: 1px solid var(--line-strong);
  border-radius: 22px 22px 0 0;
  box-shadow: 0 -22px 60px rgba(0,0,0,0.6), var(--bevel);
  padding: 10px 12px calc(16px + env(safe-area-inset-bottom, 0px));
  max-height: 82vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
  transform: translateY(100%);
  transition: transform 0.32s cubic-bezier(.2,.7,.2,1);
}
.bb-sheet.is-open .bb-sheet__panel { transform: translateY(0); }
.bb-sheet__grip { width: 38px; height: 4px; border-radius: 999px; background: var(--line-strong); margin: 4px auto 12px; }
.bb-sheet__title { margin: 0 0 6px; padding: 0 8px; font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); font-weight: 800; }
.bb-sheet__row {
  display: flex; align-items: center; gap: 14px;
  padding: 13px 12px; border-radius: 14px;
  color: var(--text); text-decoration: none; font-weight: 600; font-size: 0.95rem;
  transition: background 140ms ease;
}
.bb-sheet__row .ti { width: 22px; height: 22px; color: var(--muted); }
.bb-sheet__row span { flex: 1 1 auto; }
.bb-sheet__row:hover, .bb-sheet__row:active { background: rgba(255,255,255,0.05); text-decoration: none; }
.bb-sheet__chev { width: 18px; height: 18px; color: var(--muted-soft); }
.bb-sheet__row--danger, .bb-sheet__row--danger .ti { color: var(--accent-strong); }
.bb-sheet__badge { background: var(--accent); color: #fff; font-size: 0.62rem; font-weight: 800; padding: 2px 9px; border-radius: 999px; }
body.bb-sheet-open { overflow: hidden; }

/* ── Top progress bar — app-style loading affordance on navigation ─────── */
.bb-progress {
  position: fixed; top: env(safe-area-inset-top, 0px); left: 0;
  height: 3px; width: 0; z-index: 200;
  background: linear-gradient(90deg, var(--accent), var(--accent-strong));
  box-shadow: 0 0 12px rgba(255,46,196,0.8);
  opacity: 0; pointer-events: none; border-radius: 0 3px 3px 0;
}
.bb-progress.is-active { opacity: 1; width: 90%; transition: width 8s cubic-bezier(.05,.7,.1,1), opacity 0.12s ease; }
.bb-progress.is-done   { opacity: 0; width: 100%; transition: width 0.2s ease, opacity 0.34s ease 0.12s; }

/* ── Native screen transitions (cross-document View Transitions). Degrades
   silently to a normal load where unsupported. The persistent chrome is
   named so it stays put while content crossfades; the active tab indicator
   slides between tabs. ────────────────────────────────────────────────── */
@view-transition { navigation: auto; }
.site-header { view-transition-name: bb-header; }
.bb-tabbar   { view-transition-name: bb-tabbar; }
.bb-tab.is-active .bb-tab__ind { view-transition-name: bb-ind; }

::view-transition-old(root) { animation: bb-vt-out 170ms ease both; }
::view-transition-new(root) { animation: bb-vt-in 280ms cubic-bezier(.2,.7,.2,1) both; }
@keyframes bb-vt-out { to   { opacity: 0; transform: translateY(-6px); } }
@keyframes bb-vt-in  { from { opacity: 0; transform: translateY(10px); } }

/* ── Skeleton shimmer (utility for any future loading state) ───────────── */
.skeleton {
  position: relative; overflow: hidden;
  background: var(--panel-soft); border-radius: var(--radius-sm);
}
.skeleton::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 20%, rgba(255,255,255,0.07) 50%, transparent 80%);
  transform: translateX(-100%); animation: bb-skel 1.3s ease-in-out infinite;
}
.skeleton-text { height: 0.8em; border-radius: 6px; }
@keyframes bb-skel { to { transform: translateX(100%); } }

/* ── Reduced-motion: freeze the new motion; keep everything readable ───── */
@media (prefers-reduced-motion: reduce) {
  .bb-progress { display: none; }
  .bb-tab, .bb-tab .ti, .bb-tab__ind, .bb-sheet__panel, .bb-sheet__scrim,
  .skeleton::after { transition: none !important; animation: none !important; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none !important; }
}

/* ══════════════════════════════════════════════════════════════════════
 * GSAP MOTION GATE (2026-06) — html.bb-motion means motion.js owns the
 * entrance animations; the CSS keyframe entrances above become the
 * fallback path and are suppressed here. Ambient loops (pulse dots,
 * sheen, aurora, skeleton) are NOT gated — GSAP never touches them.
 * html.bb-motion-failed force-restores anything GSAP may have hidden
 * (set by the head failsafe when GSAP doesn't load). !important beats
 * the inline styles gsap.set leaves behind.
 * ════════════════════════════════════════════════════════════════════ */

html.bb-motion .hero__wrap > *,
html.bb-motion .auth-card > *,
html.bb-motion .go-hero > *,
html.bb-motion .me-hero,
html.bb-motion .kpi-row .kpi,
html.bb-motion .trust > div,
html.bb-motion .ticker .row,
html.bb-motion .mail .row,
html.bb-motion main.content { animation: none; }
/* Keep the welcome-bar attention pulse, drop only its CSS entrance */
html.bb-motion .welcome-bar { animation: bb-pulse-red 3.2s ease-in-out 1.2s infinite; }
/* Cashout status banners reuse .welcome-bar but must not pulse — opt out via .is-static */
html.bb-motion .welcome-bar.is-static { animation: none; }
/* [data-reveal]: keep the hidden initial state (GSAP animates from it),
   kill the CSS transition so it never fights GSAP's per-tick styles */
html.bb-motion [data-reveal] { transition: none; }

html.bb-motion-failed .hero__wrap > *,
html.bb-motion-failed .auth-card > *,
html.bb-motion-failed .go-hero > *,
html.bb-motion-failed .me-hero,
html.bb-motion-failed .kpi-row .kpi,
html.bb-motion-failed .trust > div,
html.bb-motion-failed .ticker .row,
html.bb-motion-failed .mail .row,
html.bb-motion-failed [data-reveal],
html.bb-motion-failed .earn-hero > *,
html.bb-motion-failed .earn-hero__logo,
html.bb-motion-failed .lb-row,
html.bb-motion-failed .wall-card,
html.bb-motion-failed .menu-card,
html.bb-motion-failed .lock > * {
  opacity: 1 !important;
  visibility: visible !important;
  transform: none !important;
}

/* Brand mark plumbing: shards animate around their own box; the onyx halves
   carry a soft magenta bloom so the neon edge reads as a lit tube. */
.bb-mark__shard { transform-box: fill-box; transform-origin: center; filter: drop-shadow(0 0 2px rgba(255, 46, 196, 0.55)); }
svg.site-logo { display: block; }

/* Native smooth anchor scrolling (chip nav, jump links) */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* ── Wave 2 (2026-06) ──────────────────────────────────────────────── */

/* One-shot specular sweep across tier badges. motion.js adds .is-shined
   to the row/card after its reveal; works on /leaderboard and /me. */
.tier-badge { position: relative; overflow: hidden; }
.is-shined .tier-badge::after {
  content: ""; position: absolute; top: 0; left: -80%;
  width: 50%; height: 100%; pointer-events: none;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.35), transparent);
  transform: skewX(-18deg);
  animation: bb-sweep-once 0.7s ease-out 1.2s forwards;
}
@keyframes bb-sweep-once { to { left: 130%; } }

/* Static film grain over hero panels — kills gradient banding on OLED
   phones. Reuses the atmosphere's turbulence tile; intentionally NOT
   animated. Opt-in via .bb-grain on a position:relative panel. */
.bb-grain { position: relative; }
.bb-grain::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: inherit; z-index: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  opacity: 0.05;
  mix-blend-mode: overlay;
}
.bb-grain > * { position: relative; z-index: 1; }

/* Wall stars split into glyphs for the pop-in */
.bb-star { display: inline-block; }

/* The one green live pill morphs between pages on same-origin navigation
   (cross-document View Transitions; non-supporting browsers keep the
   plain crossfade). Exactly one bb-live element exists per page. */
.earn-hero__live,
.media-earn-banner__live,
.lb-hero__live,
.wall-hero__live,
.me-earn-card__live { view-transition-name: bb-live; }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

/* ════════════════════════════════════════════════════════════════════
   Guest chrome (desktop nav, trust footer)
   ════════════════════════════════════════════════════════════════════ */

/* Guest top nav — desktop only. Mobile guests use the bottom tab bar, so
   showing this there would double the navigation and eat the hero. */
.site-header--guest { display: none; }
@media (min-width: 901px) { .site-header--guest { display: block; } }

/* Trust footer (public/guest pages) */
.bb-footer__inner {
  width: var(--content-width); margin: 56px auto 26px;
  padding-top: 22px; border-top: 1px solid var(--line);
  text-align: center;
}
.bb-footer__nav {
  display: flex; gap: 12px 20px; flex-wrap: wrap; justify-content: center;
  margin-bottom: 14px;
}
.bb-footer__nav a {
  color: var(--muted); font-size: 12px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; text-decoration: none;
}
.bb-footer__nav a:hover { color: var(--accent); }
/* Center these max-width-capped lines within the footer. The selector must out-
   rank .caption/.fineprint (which set margin:0 later in the cascade), so scope
   under .bb-footer__inner for the extra specificity. */
.bb-footer__inner .bb-footer__note { margin: 0 auto 8px; color: var(--muted-soft); font-size: 12px; line-height: 1.5; }
.bb-footer__inner .bb-footer__scam { margin: 0 auto; color: var(--muted-soft); font-size: 12px; line-height: 1.5; }
.bb-footer__scam a { color: var(--muted); font-weight: 700; }
@media (max-width: 900px) { .bb-footer__inner { margin-top: 32px; } }

/* ══════════════════════════════════════════════════════════════════════
 * NEON PINK REFRESH (2026-06) — black + hot-magenta neon identity.
 * The accent family above was retuned red→magenta (#ff2ec4). This block
 * adds the missing "neon sign" half: a glow scale + the hand-tagged script
 * wordmark. "Tasteful" = hero / logo / primary-CTA blast, while nav, cards
 * and badges stay calm. Glow is pure box/text-shadow (compositor-cheap)
 * and survives prefers-reduced-motion; only the sheen MOTION is gated.
 * ════════════════════════════════════════════════════════════════════ */
:root {
  --neon-core: #ffe3f6;                              /* white-pink tube core */
  --glow-sm: 0 0 8px rgba(255, 46, 196, 0.45);
  /* Argon tube ramp: white-hot filament core -> saturated brand magenta ->
     cool violet outer spill (the plum reused from .bb-atmos / --signage-bloom).
     Color temperature, not flat pink, is what reads as real lit neon. */
  --glow-md: 0 0 3px var(--neon-core),
             0 0 6px rgba(255, 255, 255, 0.35),
             0 0 16px rgba(255, 46, 196, 0.70),
             0 0 36px rgba(180, 60, 220, 0.30);
  --glow-hero: 0 0 4px var(--neon-core),
               0 0 10px rgba(255, 255, 255, 0.45),
               0 0 22px rgba(255, 46, 196, 0.75),
               0 0 46px rgba(255, 46, 196, 0.50),
               0 0 84px rgba(180, 60, 220, 0.34);
}

/* ── Hand-tagged neon script wordmark (Permanent Marker, self-hosted) ──── */
@font-face {
  font-family: "BB Script";
  src: url("/static/fonts/permanent-marker.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
.bb-wordmark {
  font-family: "BB Script", "Clash Display", cursive;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0.01em;
  line-height: 1;
  color: var(--accent);
  text-shadow: var(--glow-sm);
  white-space: nowrap;
}
/* Header lockup: small, calm glow, sits beside the heart icon. */
.site-branding .bb-wordmark { font-size: 1.35rem; transform: translateY(1px); }

/* Graffiti logo IMAGE wordmark (generated 5★ tag) — replaces the text wordmark
   in the header. Pink-on-transparent PNG; keep a touch of glow for cohesion. */
.bb-logo { height: 34px; width: auto; display: block; filter: drop-shadow(0 0 7px rgba(255, 46, 196, 0.4)); }
/* Hero centerpiece logo (chooser/landing) — large, centered, full glow. */
.bb-logo--hero { height: clamp(82px, 21vw, 112px); margin: 0 auto; filter: drop-shadow(0 0 16px rgba(255, 46, 196, 0.55)) drop-shadow(0 0 40px rgba(255, 46, 196, 0.32)); }
.site-branding .bb-logo { transform: translateY(1px); }
@media (max-width: 640px) { .site-branding .bb-logo { height: 28px; } }
/* Hero lockup: full neon-sign blast. */
.bb-wordmark--hero {
  display: block;
  font-size: clamp(2.6rem, 9vw, 5.2rem);
  text-shadow: var(--glow-hero);
}

/* ── Neon-glow signature — hero / logo / CTA blast; UI stays calm ─────── */
/* The heart-mark crack reads as a lit tube wherever the mark renders. */
.bb-mark__crack { filter: drop-shadow(var(--glow-sm)); }
.site-logo { filter: drop-shadow(0 0 10px rgba(255, 46, 196, 0.45)); }
/* Primary hero CTAs bloom (opt-in via .cta-glow — already on the hero CTA). */
.cta-glow { box-shadow: 0 14px 30px rgba(255, 46, 196, 0.30), var(--glow-md); }
.cta-glow:hover { box-shadow: 0 16px 34px rgba(255, 46, 196, 0.40), var(--glow-md); }
/* Hero headline accent + eyebrow get a soft tube glow (not body copy). */
.earn-hero__headline,
.hero__title .accent,
.hero__eyebrow { text-shadow: var(--glow-sm); }

/* ── Atmosphere: nudge the opt-in aurora toward the reference's plum wall.
   Base --bg stays pure black; only the drifting bloom gains a violet lobe. */
.bb-atmos {
  background:
    radial-gradient(42% 32% at 18% 12%, rgba(255, 46, 196, 0.16), transparent 60%),
    radial-gradient(38% 30% at 84% 22%, rgba(180, 60, 220, 0.12), transparent 62%),
    radial-gradient(48% 38% at 50% 88%, rgba(255, 46, 196, 0.09), transparent 66%);
}

/* ════════════════════════════════════════════════════════════════════════
 * ★ 5★ DESIGN SYSTEM v2 (2026-06) — "5-star NOIR Quiet Loud"
 * ────────────────────────────────────────────────────────────────────────
 * The reusable foundation that turns the shipped magenta refresh into the
 * full hype-drop graffiti language. APPEND-ONLY: every rule here builds on
 * the tokens above (--accent, --neon-core, --glow-*, --bevel, --line) and
 * never reverts or forks them.
 *
 * SIGNAGE-ONLY law: spray/marker faces + magenta fills are for display
 * moments ≥ ~28px (one sprayed word or numeral, one hero, one divider, one
 * loud card per page). Body / UI / nav / labels / prices stay off-white
 * Hanken for AA. Textures stay masked, low-opacity, aria-hidden, decorative.
 * All motion is compositor-only (transform/opacity/filter), one-shot, and
 * fully neutralised under prefers-reduced-motion (the static poster is the
 * acceptance test).
 *
 * Template agents: consume these by CLASS NAME — markup only, no new CSS.
 * ════════════════════════════════════════════════════════════════════════ */

/* ── Helper tokens (the small layer the locked language calls for) ──────── */
:root {
  /* Sprayed display face — SIGNAGE ONLY, never body/UI/buttons. */
  --font-spray: "BB Spray", "Clash Display", system-ui, sans-serif;

  /* Doubled neon-tube hairline: transparent → magenta → transparent. */
  --neon-hairline: linear-gradient(90deg, transparent, var(--accent) 50%, transparent);
  /* Small magenta blur halo for hairlines / lit edges. */
  --neon-halo: 0 0 6px rgba(255, 46, 196, 0.85), 0 0 3px rgba(255, 46, 196, 0.5);
  /* Center-out mask so grille/halftone dissolve to black at their edges. */
  --grille-mask: radial-gradient(ellipse 75% 70% at 50% 42%, #000 0%, rgba(0,0,0,0.55) 55%, transparent 100%);
  /* Soft magenta radial — the "lit wall behind the sign" bloom. */
  --signage-bloom: radial-gradient(ellipse 62% 55% at 50% 22%, rgba(255, 46, 196, 0.18) 0%, rgba(180, 60, 220, 0.07) 42%, transparent 72%);
  /* Shared caps the language fixes: textures ≤6%, global grain ~3.5%. */
  --tex-opacity: 0.06;
  --grain-opacity: 0.035;
}

/* ── Sprayed display face (Rubik Spray Paint, self-hosted) ─────────────────
 * Registered as "BB Spray". Display-only: the ONE sprayed word/numeral per
 * page. Never set on body, nav, labels, prices, or anything < ~28px. */
@font-face {
  font-family: "BB Spray";
  src: url("/static/fonts/rubik-spray-paint.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}

/* ── Display-type utilities ────────────────────────────────────────────────
 * .bb-spray  = the sprayed accent word/numeral inside a headline (magenta + glow).
 * .bb-marker = the marker-script signature moment (reuses "BB Script").
 * Both are signage; min-size guarded by their intended use in big type. */
.bb-spray {
  font-family: var(--font-spray);
  font-weight: 400;
  color: var(--accent);
  text-shadow: var(--glow-md);
  letter-spacing: 0.005em;
  /* slight optical lift so the spray word sits with Clash caps */
  line-height: 0.9;
}
.bb-spray--hero {
  display: inline-block;
  font-size: clamp(2.6rem, 9vw, 5.4rem);
  text-shadow: var(--glow-hero);
}
.bb-marker {
  font-family: "BB Script", "Clash Display", cursive;
  font-weight: 400;
  color: var(--accent);
  text-shadow: var(--glow-sm);
  letter-spacing: 0.01em;
}

/* ── Star-tag stamp (.bb-startag) ──────────────────────────────────────────
 * The graffiti 5-point tag as a tintable mask. NOTE: .bb-star is already
 * taken (motion.js glyph-splits wall stars), so the stamp is .bb-startag.
 *  - inline glyph beside ONE label / as a rating mark, OR
 *  - a single big hero centerpiece (.bb-startag--hero).
 * Magenta via mask + currentColor; one per page (anti-clip-art). */
.bb-startag {
  display: inline-block;
  width: 1.15em; height: 1.15em;
  vertical-align: -0.22em;
  color: var(--accent);
  background-color: currentColor;
  -webkit-mask: url("/static/brand/fx/star-tag.svg") no-repeat center / contain;
          mask: url("/static/brand/fx/star-tag.svg") no-repeat center / contain;
  filter: drop-shadow(var(--glow-sm));
  pointer-events: none;
}
.bb-startag--hero {
  width: clamp(120px, 26vw, 220px);
  height: clamp(120px, 26vw, 220px);
  vertical-align: middle;
  filter: drop-shadow(var(--glow-md));
}

/* ── Spray splatter accent (.bb-splatter) ──────────────────────────────────
 * A single magenta spray cloud behind/under one hero accent. Decorative
 * pseudo-fill; keep to ONE per page, low opacity. */
.bb-splatter {
  position: absolute;
  inset: auto auto -8% -6%;
  width: clamp(120px, 22vw, 200px);
  aspect-ratio: 1;
  color: var(--accent);
  background-color: currentColor;
  -webkit-mask: url("/static/brand/fx/splatter.svg") no-repeat center / contain;
          mask: url("/static/brand/fx/splatter.svg") no-repeat center / contain;
  opacity: 0.16;
  pointer-events: none;
  z-index: 0;
}

/* ── Dripping section edge (.bb-drip) ──────────────────────────────────────
 * Paint drips off the BOTTOM of exactly ONE block (the hero). Add to a
 * position:relative element; never a row, never a top edge. */
.bb-drip { position: relative; }
.bb-drip::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -22px;
  height: 26px;
  color: var(--accent);
  background-color: currentColor;
  -webkit-mask: url("/static/brand/fx/drip.svg") repeat-x left top / auto 100%;
          mask: url("/static/brand/fx/drip.svg") repeat-x left top / auto 100%;
  opacity: 0.5;
  filter: drop-shadow(0 0 6px rgba(255, 46, 196, 0.5));
  pointer-events: none;
  z-index: 1;
}
/* Subtle variant — single short drip at one corner, even quieter. */
.bb-drip--corner::after {
  left: auto; right: 8%; width: clamp(90px, 18vw, 150px);
  opacity: 0.4;
}

/* ── Faint texture backgrounds (masked, capped ≤6%) ────────────────────────
 * .bb-tex-grille  = speaker-grille dot field, the hi-fi connective backdrop.
 * .bb-tex-halftone= one corner halftone wedge on ONE card per page.
 * Both tint magenta via mask + currentColor and fade out via --grille-mask. */
.bb-tex-grille { position: relative; isolation: isolate; }
.bb-tex-grille::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  color: var(--accent);
  background-color: currentColor;
  -webkit-mask:
    url("/static/brand/fx/grille.svg") repeat left top / 26px 26px,
    var(--grille-mask);
  -webkit-mask-composite: source-in;
          mask:
    url("/static/brand/fx/grille.svg") repeat left top / 26px 26px,
    var(--grille-mask);
          mask-composite: intersect;
  opacity: var(--tex-opacity);
  pointer-events: none;
  z-index: -1;
}
.bb-tex-grille > * { position: relative; z-index: 0; }

.bb-tex-halftone { position: relative; isolation: isolate; }
.bb-tex-halftone::after {
  content: "";
  position: absolute; top: 0; right: 0;
  width: clamp(70px, 22%, 120px); height: clamp(70px, 22%, 120px);
  color: var(--accent);
  background-color: currentColor;
  -webkit-mask:
    url("/static/brand/fx/halftone.svg") repeat left top / 18px 18px,
    linear-gradient(225deg, #000 0%, transparent 78%);
  -webkit-mask-composite: source-in;
          mask:
    url("/static/brand/fx/halftone.svg") repeat left top / 18px 18px,
    linear-gradient(225deg, #000 0%, transparent 78%);
          mask-composite: intersect;
  opacity: 0.07;
  pointer-events: none;
  z-index: -1;
}

/* ── Black + magenta DUOTONE (.bb-duotone) ─────────────────────────────────
 * For BRAND / PEOPLE / HERO imagery ONLY — NEVER product photos (.bb-duotone
 * must not touch .pd-gallery__img). Shadows → near-black, highlights → hot
 * magenta. CSS-only fallback (no SVG filter dependency): grayscale + contrast
 * floors it to two-tone, the screen-blend overlay paints in the magenta. */
.bb-duotone {
  position: relative;
  display: inline-block;
  isolation: isolate;
}
.bb-duotone > img,
.bb-duotone.bb-duotone--img {
  display: block;
  filter: grayscale(1) contrast(1.18) brightness(0.92);
}
.bb-duotone::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(150deg, #050505 0%, var(--accent) 100%);
  mix-blend-mode: screen;
  opacity: 0.85;
  pointer-events: none;
  border-radius: inherit;
}
/* When an SVG <filter id="bb-duotone"> ships in base.html, opt into the
   crisper feColorMatrix path and drop the blend overlay. */
.bb-duotone--svg > img { filter: url(#bb-duotone); }
.bb-duotone--svg::after { display: none; }
/* Hard guard: product galleries stay TRUE colour, subtle vignette at most. */
.pd-gallery__img.bb-duotone,
.bb-duotone .pd-gallery__img { filter: none !important; }

/* ── Neon-tube section divider (.bb-divider) ───────────────────────────────
 * The ONE doubled magenta hairline per major break; every other rule stays
 * neutral (var(--line)). Use on an <hr> or a bare <div>. */
.bb-divider {
  height: 1px; border: 0;
  width: 100%;
  margin: 30px 0;
  background: var(--neon-hairline);
  box-shadow: var(--neon-halo);
  opacity: 0.9;
}

/* ── Advisory badge helper (UNUSED — markup removed) ───────────────────────
 * BLACK/WHITE for instant cred (NOT magenta). Two ways to use it:
 *  - .badge-21       → the full SVG stamp.
 *  - .badge-21--text → a compact text pill when the SVG is overkill. */
.badge-21 {
  display: inline-block;
  width: clamp(88px, 18vw, 132px);
  aspect-ratio: 220 / 130;
  background: url("/static/brand/fx/badge-21.svg") no-repeat center / contain;
  pointer-events: none;
}
.badge-21--text {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 10px;
  background: #000; color: #fff;
  border: 1.5px solid #fff; border-radius: 3px;
  font-family: var(--font-body);
  font-size: 0.62rem; font-weight: 800;
  letter-spacing: 0.12em; text-transform: uppercase;
  white-space: nowrap;
}

/* ── Elevated hero shell (.bb-hero) ────────────────────────────────────────
 * The per-page detonation wrapper. Stacks the lit wall (signage bloom) +
 * grille backdrop behind content; pair with .bb-drip for the bottom drip and
 * .bb-grain for film grain. Layers content above via z-index. Reuses the
 * existing .earn-hero / .go-hero geometry — this only adds the backdrop. */
.bb-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.bb-hero::before {   /* lit magenta wall behind the sign */
  content: "";
  position: absolute; inset: 0;
  background: var(--signage-bloom);
  pointer-events: none;
  z-index: -2;
}
.bb-hero::after {    /* speaker-grille dot field, radial-masked to black */
  content: "";
  position: absolute; inset: 0;
  color: var(--accent);
  background-color: currentColor;
  -webkit-mask:
    url("/static/brand/fx/grille.svg") repeat left top / 30px 30px,
    var(--grille-mask);
  -webkit-mask-composite: source-in;
          mask:
    url("/static/brand/fx/grille.svg") repeat left top / 30px 30px,
    var(--grille-mask);
          mask-composite: intersect;
  opacity: 0.08;
  pointer-events: none;
  z-index: -1;
}
.bb-hero > * { position: relative; z-index: 1; }

/* ── Neon-edge / "taped" featured card (.bb-card-neon) ──────────────────────
 * The single lit card per page: a magenta neon-tube border + bloom over the
 * existing pressed-metal surface. Calm cards keep their neutral hairline. */
.bb-card-neon {
  border: 1px solid var(--accent);
  box-shadow:
    var(--shadow-md),
    var(--bevel),
    inset 0 0 0 1px rgba(255, 46, 196, 0.45),
    var(--glow-edge);
}
/* "Taped" — a strip of tape across one corner for the hype-room collage feel. */
.bb-taped { position: relative; }
.bb-taped::before {
  content: "";
  position: absolute; top: 10px; left: -14px;
  width: 64px; height: 18px;
  background: rgba(255, 227, 246, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.18);
  transform: rotate(-24deg);
  pointer-events: none;
}

/* ── Marquee / ticker readout (.bb-ticker) ─────────────────────────────────
 * A calm low-light readout, NOT a perpetual crawl: a magenta LIVE dot + a
 * fade-stack. Reuses the existing .ticker visuals; this adds the LIVE dot and
 * the one-shot reveal. The dot's glow is static; only the entrance animates. */
.bb-ticker__live {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-body);
  font-size: 0.62rem; font-weight: 800;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--accent);
}
.bb-ticker__live::before {
  content: "";
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
  box-shadow: var(--neon-halo);
  flex: 0 0 auto;
}

/* ── Nav / footer / tab-bar polish ─────────────────────────────────────────
 * Active link = magenta neon-tube underline (calm, no flicker). */
.bb-navlink.is-active,
.site-nav a[aria-current="page"] {
  position: relative;
  color: var(--text);
}
.bb-navlink.is-active::after,
.site-nav a[aria-current="page"]::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -4px;
  height: 2px; border-radius: 2px;
  background: var(--accent);
  box-shadow: var(--neon-halo);
}
/* Mobile tab bar: a single lit indicator for the active item. */
/* Footer: one quiet sprayed star sitting beside the heart/links. */
.bb-footer__inner .bb-startag { opacity: 0.9; }

/* ── Loader / empty state (.bb-startag-loader) ─────────────────────────────
 * The star-tag glyph spray-reveals once instead of a spinner; reduced-motion
 * shows it fully painted. */
.bb-startag-loader {
  display: inline-block;
  width: 56px; height: 56px;
  color: var(--accent);
  background-color: currentColor;
  -webkit-mask: url("/static/brand/fx/star-tag.svg") no-repeat center / contain;
          mask: url("/static/brand/fx/star-tag.svg") no-repeat center / contain;
  filter: drop-shadow(var(--glow-sm));
}

/* ── Tracked numbered kicker (.bb-kicker-num) — "01 / EARN" eyebrow ─────── */
.bb-kicker-num {
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
  text-wrap: balance;
}
.bb-kicker-num b { color: var(--accent); font-weight: 700; }

/* ════════════════════════════════════════════════════════════════════════
 * MOTION — neon FLICKER + spray-on REVEAL.
 * Compositor-only (opacity/filter/transform), ONE-SHOT (no infinite loops),
 * and gated behind .bb-motion so motion.js owns activation. Fully neutral
 * under prefers-reduced-motion: the painted/lit static state is the result.
 * ════════════════════════════════════════════════════════════════════════ */

/* Irregular one-shot neon buzz that settles lit (hero signage only). */
@keyframes bb-flicker {
  0%   { opacity: 0.2; }
  6%   { opacity: 0.9; }
  10%  { opacity: 0.25; }
  14%  { opacity: 1; }
  20%  { opacity: 0.5; }
  24%  { opacity: 1; }
  100% { opacity: 1; }
}
/* Spray-on reveal: a soft-edged wipe + bloom that resolves to fully painted. */
@keyframes bb-spray-on {
  0%   { opacity: 0; filter: blur(6px) saturate(0.4); transform: scale(0.98); }
  60%  { opacity: 1; filter: blur(1px) saturate(1.1); }
  100% { opacity: 1; filter: blur(0) saturate(1); transform: scale(1); }
}

/* Default (no JS / no .bb-motion): everything is already lit & painted — the
   classes below are inert until motion.js adds .bb-motion to <html>. */
html.bb-motion .bb-flicker {
  animation: bb-flicker 900ms steps(1, end) 120ms 1 both;
}
html.bb-motion .bb-spray-reveal {
  animation: bb-spray-on 620ms cubic-bezier(.2, .7, .2, 1) both;
}
/* One slow hero glow PULSE is allowed (single, gentle), distinct from flicker. */
html.bb-motion .bb-glow-pulse {
  animation: bb-earn-glow 3.6s ease-in-out 0.4s 1 both;  /* reuses existing keyframes */
}

@media (prefers-reduced-motion: reduce) {
  html.bb-motion .bb-flicker,
  html.bb-motion .bb-spray-reveal,
  html.bb-motion .bb-glow-pulse,
  .bb-drip::after { animation: none !important; }
  .bb-flicker, .bb-spray-reveal { opacity: 1 !important; filter: none !important; transform: none !important; }
}

/* ════════════════════════════════════════════════════════════════════════
 * ✶ FIRST-VISIT INTRO — "neon sign ignition" (#bb-intro)
 * Opaque cover shown ONLY when the <head> gate sets html.bb-intro-on (fresh
 * external visit + motion on). motion.js#introPlay runs the GSAP ignition then
 * adds html.bb-intro-done to reveal the page; the <head> failsafe + the
 * CSS-only fallback below cover a failed/slow GSAP load. Compositor-only
 * (opacity / transform / filter). The mark/word/star START hidden here so the
 * deferred motion.js never flashes the finished frame before it animates.
 * ──────────────────────────────────────────────────────────────────────── */
.bb-intro {
  position: fixed;
  inset: 0;
  z-index: 10001;                 /* above #bb-loader (9999) + all chrome */
  display: none;                  /* OFF until the gate turns it on */
  align-items: center;
  justify-content: center;
  background:
    var(--signage-bloom),
    radial-gradient(circle at center, #0a0a0c 0%, #020202 72%);
  overflow: hidden;
  will-change: opacity, transform;
}
html.bb-intro-on .bb-intro { display: flex; }
.bb-intro::before {               /* breathing signage bloom — keeps the cover alive */
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background: radial-gradient(40% 32% at 50% 47%,
              rgba(255, 46, 196, 0.22), rgba(255, 46, 196, 0.06) 42%, transparent 72%);
  animation: bb-intro-breathe 3.8s ease-in-out infinite;
}
.bb-intro__stage { z-index: 1; }  /* sign sits above its bloom */
.bb-intro::after {                /* OLED film grain (matches .bb-grain) */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: 0.05; mix-blend-mode: overlay;
}
.bb-intro__stage {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  gap: clamp(14px, 3vw, 26px);
  padding: 24px;
}
.bb-intro__mark {                 /* svg container — visible, but its parts ignite in sequence:
                                     crack traces in first, then the shards light up around it */
  width: clamp(96px, 30vw, 188px);
  height: auto;
  color: var(--text);
  opacity: 1;
  filter: drop-shadow(0 0 0 rgba(255, 46, 196, 0));
  transition: filter 0.4s ease;
}
.bb-intro__mark.is-lit {          /* magenta neon glow — engaged BEFORE the heart appears,
                                     so it ignites already glowing (never a bare white flash) */
  filter: drop-shadow(0 0 4px var(--neon-core))
          drop-shadow(0 0 16px rgba(255, 46, 196, 0.78))
          drop-shadow(0 0 38px rgba(255, 46, 196, 0.55));
}
.bb-intro__mark.is-humming {      /* breathe/hum — added only after the strike settles, so its
                                     opacity loop can't override the GSAP ignition flicker */
  animation: bb-intro-hum 2.8s ease-in-out 0.15s infinite;
}
.bb-intro__mark .bb-mark__shard { opacity: 0; }  /* white halves hidden until they ignite */
.bb-intro__mark .bb-mark__crack {                /* magenta neon line — traces in first, glows on its own */
  stroke-dasharray: 1; stroke-dashoffset: 1;     /* undrawn */
  stroke-width: 3.2;
  filter: drop-shadow(0 0 4px var(--neon-core))
          drop-shadow(0 0 11px rgba(255, 46, 196, 0.9))
          drop-shadow(0 0 20px rgba(255, 46, 196, 0.55));
}
.bb-intro__word {                 /* graffiti wordmark — sprays in */
  height: clamp(40px, 9vw, 74px);
  width: auto;
  opacity: 0;
  filter: drop-shadow(0 0 16px rgba(255, 46, 196, 0.55)) drop-shadow(0 0 40px rgba(255, 46, 196, 0.32));
}
.bb-intro__star {                 /* 5★ stamp — pops over the wordmark */
  position: absolute; top: -4%; right: -2%;
  width: clamp(34px, 9vw, 60px); height: clamp(34px, 9vw, 60px);
  color: var(--accent); background-color: currentColor;
  -webkit-mask: url("/static/brand/fx/star-tag.svg") no-repeat center / contain;
          mask: url("/static/brand/fx/star-tag.svg") no-repeat center / contain;
  filter: drop-shadow(var(--glow-md));
  opacity: 0; transform: scale(0.2) rotate(-12deg);
  pointer-events: none;
}
.bb-intro__wipe {                 /* magenta tube sweep on exit (GSAP scaleX) */
  position: absolute; left: 0; right: 0; top: 50%;
  height: 2px; margin-top: -1px;
  background: var(--neon-hairline); box-shadow: var(--glow-md);
  transform: scaleX(0); transform-origin: left center;
  opacity: 0; pointer-events: none;
}
/* Reveal — driven by the GSAP exit AND the <head> failsafe. Cover fades +
   scales up so the page underneath reads as "arriving". */
html.bb-intro-done .bb-intro {
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: scale(1.04);
  transition: opacity 0.45s ease, transform 0.5s ease, visibility 0s linear 0.5s;
}

/* Ambient life. bb-intro-breathe: the bloom swells/dims slowly. bb-intro-hum:
   a real neon tube never sits perfectly still — tiny opacity dips + a breath of
   scale on the lit mark. Both are killed by the global reduced-motion block. */
@keyframes bb-intro-breathe {
  0%, 100% { opacity: 0.55; transform: scale(0.96); }
  50%      { opacity: 1;    transform: scale(1.06); }
}
@keyframes bb-intro-hum {
  0%, 100% { opacity: 1;    transform: scale(1);     }
  28%      { opacity: 0.94; transform: scale(1.012); }
  50%      { opacity: 1;    transform: scale(1.024); }
  63%      { opacity: 0.9;  transform: scale(1.018); }
  78%      { opacity: 0.98; transform: scale(1.01);  }
}

/* CSS-only fallback: motion is on but GSAP failed. Run a self-contained
   ignition via keyframes, then self-dismiss (bb-intro-failsafe-out) so this
   path never waits on the 5.2s <head> failsafe. Reuses bb-flicker / bb-spray-on. */
html.bb-motion-failed.bb-intro-on .bb-intro {
  animation: bb-intro-failsafe-out 700ms ease 2500ms forwards;
}
html.bb-motion-failed.bb-intro-on .bb-intro__mark {
  animation: bb-intro-light 900ms ease-out 760ms 1 forwards;   /* svg glow ramps as the shards arrive */
}
html.bb-motion-failed.bb-intro-on .bb-intro__mark .bb-mark__crack {
  animation: bb-intro-crack 620ms ease-out 200ms forwards;     /* crack traces in FIRST (leads) */
}
html.bb-motion-failed.bb-intro-on .bb-intro__mark .bb-mark__shard {
  animation: bb-flicker 760ms steps(1, end) 820ms 1 both;      /* shards flicker on after the crack */
}
html.bb-motion-failed.bb-intro-on .bb-intro__word {
  animation: bb-spray-on 680ms cubic-bezier(.2,.7,.2,1) 1320ms both;
}
html.bb-motion-failed.bb-intro-on .bb-intro__star {
  animation: bb-intro-pop 460ms cubic-bezier(.2,1.4,.3,1) 1700ms both;
}
@keyframes bb-intro-failsafe-out { to { opacity: 0; visibility: hidden; } }
@keyframes bb-intro-light { to {
  filter: drop-shadow(0 0 4px var(--neon-core)) drop-shadow(0 0 16px rgba(255,46,196,.75)) drop-shadow(0 0 38px rgba(255,46,196,.55));
} }
@keyframes bb-intro-crack { to { stroke-dashoffset: 0; } }
@keyframes bb-intro-pop {
  from { opacity: 0; transform: scale(0.2) rotate(-12deg); }
  to   { opacity: 1; transform: scale(1) rotate(-4deg); }
}

@media (max-width: 640px) {       /* mobile: smaller + snappier, no scale on exit */
  .bb-intro__mark { width: clamp(88px, 42vw, 150px); }
  .bb-intro__word { height: clamp(34px, 12vw, 56px); }
  html.bb-intro-done .bb-intro { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .bb-intro { display: none !important; }  /* belt-and-suspenders; gate also bails */
}

/* ════════════════════════════════════════════════════════════════════════
 * ✶ GRAFFITI TAG SYSTEM (.bb-tag) — Broken Bags' own "things"
 * ────────────────────────────────────────────────────────────────────────
 * Hand-tag link/action labels in the marker hand (BB Script = Permanent
 * Marker — the same hand as the wordmark) with neon-pink glow and a slight
 * spray tilt, à la a streamer's tag wall. SIGNAGE-ONLY (per the v2 law):
 * use on link/action labels & section moments ≥ ~20px — never body/UI/prices.
 * On-brand pink only: magenta / hot-pink / white-hot core.
 * ════════════════════════════════════════════════════════════════════════ */
.bb-tag {
  font-family: "BB Script", "Clash Display", cursive;
  font-weight: 400;
  line-height: 1;
  text-transform: none;
  letter-spacing: 0.01em;
  color: var(--accent);
  text-shadow: var(--glow-sm);
  text-decoration: none;
  display: inline-block;
  transition: transform 170ms cubic-bezier(.2,.7,.2,1), color 170ms ease, text-shadow 170ms ease;
}
.bb-tag:hover,
.bb-tag:focus-visible {
  color: var(--neon-core);
  text-shadow: var(--glow-md);
  transform: translateY(-2px) scale(1.04);
  text-decoration: none;
}

/* Tag wall: a sprayed cluster with per-tag hand-tilt + on-brand tonal variety. */
.bb-tagwall { display: flex; flex-wrap: wrap; gap: 16px 30px; align-items: baseline; justify-content: center; }
.bb-tagwall .bb-tag { font-size: clamp(1.5rem, 6vw, 2.1rem); }
.bb-tagwall .bb-tag:nth-child(4n+1) { color: var(--accent);    transform: rotate(-3deg); }
.bb-tagwall .bb-tag:nth-child(4n+2) { color: var(--neon-core); transform: rotate(2deg);  }
.bb-tagwall .bb-tag:nth-child(4n+3) { color: #ff66d9;          transform: rotate(-1deg); }
.bb-tagwall .bb-tag:nth-child(4n+4) { color: var(--accent);    transform: rotate(3deg);  }
.bb-tagwall .bb-tag:hover,
.bb-tagwall .bb-tag:focus-visible { color: var(--neon-core); transform: translateY(-3px) rotate(0deg) scale(1.06); }

/* Footer tag wall — replaces the plain uppercase link row site-wide. */
.bb-footer__nav.bb-tagwall { gap: 14px 26px; margin-bottom: 18px; }
.bb-footer__nav.bb-tagwall .bb-tag { font-size: clamp(1.35rem, 5.5vw, 1.85rem); }

@media (prefers-reduced-motion: reduce) {
  .bb-tag { transition: none; }
}
/* ── end graffiti tag system ─────────────────────────────────────────── */

/* ════════════════════════════════════════════════════════════════════════
 * ✶ TYPE & MICRO-UI COHESION v3 — the QUIET layer
 * ────────────────────────────────────────────────────────────────────────
 * The loud signage (hero / graffiti / neon) is shipped. This block makes the
 * QUIET text — body, labels, captions, prices, inputs, table cells, lists,
 * microcopy, empty states, links — feel like ONE intentional system instead
 * of default Hanken. Builds ON the shipped tokens/classes; never reverts them.
 *
 * Two settled global moves carry the pass:
 *   1. Prose drops to weight 430 + letter-spacing 0 — SCOPED to .prose/.lead/
 *      .caption/etc, NEVER the global body element (UI chrome keeps 500).
 *   2. One canonical caps-tracking constant --track:0.14em replaces the
 *      scattered 0.10–0.22em values (label/chip/pill/th/nav/kicker).
 *
 * RULES: no new fonts, no new colors. Magenta = accents/labels/links only,
 * never long body. 3-tier muted ladder (--text / --muted / --muted-soft).
 * Tabular + slashed-zero gives the "datasheet" feel without a mono face.
 * Motion compositor-only + reduced-motion safe. AA preserved.
 * ════════════════════════════════════════════════════════════════════════ */

/* ── Scoped tokens (no colors, no fonts) ─────────────────────────────────── */
:root {
  --track: 0.14em;          /* the ONE caps-tracking constant */
  --measure: 64ch;          /* running prose max-width */
  --measure-lead: 54ch;     /* lead / intro paragraph */
  --measure-cap: 46ch;      /* captions / fineprint */
  --measure-tight: 42ch;    /* empty states / auth — extends shipped 42ch convention */
  --lh-prose: 1.62;         /* generous paragraph leading (UI keeps --lh-body:1.6) */
}

/* ── BODY / PROSE ─────────────────────────────────────────────────────────
 * Hanken, tuned. Scoped weight 430 + tracking 0 so spacing itself becomes the
 * prose-vs-label signal. Measure-capped so text never runs full content width. */
.prose,
.content p,
.lead,
.caption,
.fineprint,
.field__hint {
  font-weight: 430;
  letter-spacing: 0;
}
.prose,
.content p {
  line-height: var(--lh-prose);
  max-width: var(--measure);
  color: var(--muted);
  text-wrap: pretty;
}
.prose { color: var(--text); }       /* a dedicated prose block reads at full strength */

/* Lead / intro paragraph — one notch up, --text, narrower measure. */
.lead {
  font-size: var(--step-1);
  line-height: 1.45;
  max-width: var(--measure-lead);
  color: var(--text);
  text-wrap: pretty;
}

/* Paragraph rhythm: margin-only separation, never indents. Black space = luxe. */
.prose p + p,
.content p + p { margin-top: 0.9em; }
.prose h1, .prose h2, .prose h3,
.prose h4 { margin: 1.6em 0 0.5em; text-wrap: balance; }
.prose > :first-child,
.content p:first-child { margin-top: 0; }
.prose h1 + p, .prose h2 + p, .prose h3 + p,
.content h1 + p, .content h2 + p, .content h3 + p { margin-top: 0; }

/* Emphasis inside body: weight, never magenta, never 700 (AA + restraint). */
.prose strong, .content strong, .lead strong { font-weight: 650; color: inherit; }
.prose em, .content em { font-style: italic; }

/* ── HEADINGS ─────────────────────────────────────────────────────────────
 * Clash stays (shipped family at line 162). Just add widow control + ease the
 * h2 micro-cap onto --track so the label-tier heading joins the family. */
h1, h2, h3, .hero__title { text-wrap: balance; }
h2 { letter-spacing: var(--track); }

/* ── KICKERS / EYEBROWS — the universal "01 / LABEL ★" opener ─────────────── */
.bb-kicker-num { letter-spacing: var(--track); }   /* migrate shipped 0.22em */
/* .kicker--rule: a short magenta neon-hairline stub to the LEFT, tying the
   eyebrow to .bb-divider language. Section kickers + form-group headers ONLY. */
.kicker--rule { display: flex; align-items: center; gap: 10px; }
.kicker--rule::before {
  content: "";
  flex: 0 0 auto;
  width: 20px; height: 1px;
  background: var(--neon-hairline);
  box-shadow: var(--neon-halo);
  opacity: 0.9;
}
.kicker { letter-spacing: var(--track); }   /* shipped .kicker onto the constant */

/* ── LABELS / CAPTIONS / FINEPRINT — the muted ladder ──────────────────────
 * .label = the reusable uppercase tracked label (Hanken, tier --muted). */
.label {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--muted);
}
/* Magenta hairline-underline label — a label that doubles as a quiet divider. */
.label--rule {
  position: relative;
  padding-bottom: 8px;
}
.label--rule::after {
  content: "";
  position: absolute; left: 0; bottom: 0;
  width: 28px; height: 1px;
  background: var(--neon-hairline);
  box-shadow: var(--neon-halo);
  opacity: 0.85;
}
/* Caption (photo credits, supporting copy) — tertiary tier. */
.caption {
  font-family: var(--font-body);
  font-size: var(--step--1);
  color: var(--muted-soft);
  line-height: 1.5;
  max-width: var(--measure-cap);
  margin: 0;
}
/* Fineprint (terms, legal, metadata) — a notch quieter than caption. */
.fineprint {
  font-family: var(--font-body);
  font-size: 0.70rem;
  color: var(--muted-soft);
  line-height: 1.5;
  max-width: var(--measure-cap);
  margin: 0;
  opacity: 0.92;
}
/* Form hint joins the tertiary tier (color already shipped; just leading/measure). */
.field__hint { line-height: 1.5; max-width: var(--measure-cap); }
.field__hint--ok  { color: #7eea9a; }   /* green tier (reuses .pill.good hue) */
.field__hint--err { color: #ff8a8a; }   /* red tier  (reuses .pill.bad hue)  */

/* ── PRICES ────────────────────────────────────────────────────────────────
 * Dedicated, weighted, tabular. Currency/cents recede so the figure dominates.
 * Magenta NEVER on the number — a small .pill "SALE" carries the color. */
.price {
  font-family: var(--font-body);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;     /* slashed zero — the datasheet tell */
  letter-spacing: -0.01em;
  color: var(--text);
}
.price__unit {           /* $, ¢, currency code */
  font-size: 0.7em;
  font-weight: 600;
  color: var(--muted-soft);
}
.price--was {            /* compare-at / strikethrough */
  font-weight: 500;
  color: var(--muted-soft);
  text-decoration: line-through;
  text-decoration-color: var(--muted-soft);
}

/* ── DIGITS — tabular + slashed-zero everywhere they appear ─────────────────
 * Extends the shipped ledger block (lines 1005-1012) to the new surfaces. */
.num, [data-number], .count, .badge--count, .chip--code, .price {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
}
.table .num { font-feature-settings: "zero" 1; }

/* ── FORMS — placeholder lighter than value; focus echoes the hairline ─────── */
.field__label { letter-spacing: var(--track); }   /* migrate shipped 0.16em */
.input::placeholder, .textarea::placeholder,
.field input::placeholder, .field textarea::placeholder {
  color: var(--muted-soft);
  font-weight: 430;           /* visibly lighter than the 500 input value */
  font-style: normal;         /* upright, never italic */
  opacity: 1;                 /* normalise Firefox's dimming */
}
/* Numeric inputs (qty / code / card) align as a column. */
.field input[type="number"],
.field input[inputmode="numeric"],
.input--num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
}
/* Optional: focus nudges the bottom edge magenta to echo the neon hairline. */
.input:focus, .textarea:focus,
.field input:focus, .field textarea:focus { border-bottom-color: var(--accent); }
/* Validation: error label + hint in the red tier, 1px error border. */
.field--error .field__label { color: #ff8a8a; }
.field--error input, .field--error textarea, .field--error select {
  border-color: rgba(255, 118, 118, 0.55);
}
.field--error .field__hint { color: #ff8a8a; }

/* ── TABLES — calmer cells, one neon hairline under the thead ───────────────
 * th tracking already shipped at 0.14em — leave it. td drops to weight 430 for
 * editorial calm; first column may carry the row label. */
.table td { font-weight: 430; }
.table td:first-child { font-weight: 650; color: var(--text); }
.table .muted, .table td.muted { font-weight: 500; }   /* keep secondary cells legible */
/* The ONE table accent: a magenta hairline under the whole header row — NOT
   under every th (avoids glow-noise on dense admin tables). */
.table thead { position: relative; }
.table thead::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--neon-hairline);
  box-shadow: var(--neon-halo);
  opacity: 0.8;
  pointer-events: none;
}

/* ── LISTS — one site-wide magenta triangle bullet (▸) ─────────────────────
 * The single list/marker glyph across the site. Star (.bb-startag) stays for
 * one rating/empty-state mark per view — never mixed into the same list. */
.list-clean { list-style: none; padding-left: 0; margin: 0; }
.list-clean li {
  position: relative;
  padding-left: 1.4em;
  line-height: 1.55;
  margin-bottom: 0.5em;
  max-width: 60ch;
  color: var(--muted);
}
.list-clean li::before {
  content: "\25B8";          /* ▸ */
  position: absolute; left: 0; top: 0;
  color: var(--accent);
  font-size: 0.8em;
  line-height: 1.7;
}
/* Numbered list: a tabular magenta index counter. */
.list-num { list-style: none; padding-left: 0; margin: 0; counter-reset: ln; }
.list-num li {
  position: relative;
  padding-left: 2.1em;
  line-height: 1.55;
  margin-bottom: 0.5em;
  max-width: 60ch;
  color: var(--muted);
  counter-increment: ln;
}
.list-num li::before {
  content: counter(ln, decimal-leading-zero);
  position: absolute; left: 0; top: 0;
  color: var(--accent);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
  font-size: 0.85em;
}
/* Refined definition list — quiet spec-sheet rows. */
.dl-spec { display: grid; grid-template-columns: minmax(0, 0.5fr) minmax(0, 1fr); gap: 6px 18px; margin: 0; }
.dl-spec dt {
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--muted-soft);
}
.dl-spec dd { margin: 0; color: var(--text); font-weight: 430; }

/* ── LINKS — inline prose links carry a 1px magenta underline AT REST ───────
 * Extends shipped a:hover (line 139) without layout shift. Standalone/utility
 * links use the shipped tracked-caps + neon-underline nav pattern. */
.prose a, .content a:not([class]), a.link {
  color: var(--text);
  border-bottom: 1px solid rgba(255, 46, 196, 0.5);
  text-underline-offset: 3px;
  text-decoration: none;
  transition: color 160ms ease, border-color 160ms ease;
}
.prose a:hover, .content a:not([class]):hover, a.link:hover {
  color: var(--accent-strong);
  border-bottom-color: var(--accent-strong);
  text-decoration: none;
}
/* Utility / standalone link — tracked micro-cap. */
.link-caps {
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--muted);
}
.link-caps:hover { color: var(--text); text-decoration: none; }
/* Arrow link — trailing ▸ that nudges 2px on hover (compositor transform only). */
.link-arrow { display: inline-flex; align-items: center; gap: 0.45em; color: var(--text); }
.link-arrow::after {
  content: "\25B8";          /* ▸ */
  color: var(--accent);
  font-size: 0.85em;
  transition: transform 160ms ease;
}
.link-arrow:hover { text-decoration: none; }
.link-arrow:hover::after { transform: translateX(2px); }

/* ── CHIPS / PILLS / BADGES — one micro-cap family on --track ───────────────
 * Migrate the scattered tracking onto the constant. Tier colors/states stay. */
.chip { letter-spacing: var(--track); }     /* shipped 0.10em → --track */
.pill { letter-spacing: var(--track); }     /* shipped 0.12em → --track */
.tier-badge { letter-spacing: var(--track); }   /* shipped 0.22em → --track */
.pill { font-variant-numeric: tabular-nums; }    /* any count reads as a figure */

/* Count badge — tiny magenta pill for cart / notification counts. */
.badge--count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--radius-pill);
  font-size: 0.62rem; font-weight: 800;
  font-variant-numeric: tabular-nums; font-feature-settings: "zero" 1;
  background: var(--accent-soft);
  color: var(--accent-strong);
  border: 1px solid rgba(255, 46, 196, 0.45);
}
/* Code chip — SKU / order-ID. NOT uppercase; digits earn looser tracking here. */
.chip--code {
  text-transform: none;
  letter-spacing: 0.04em;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
  color: var(--muted);
}

/* ── EMPTY STATES — branded, not blank ─────────────────────────────────────
 * Centered stack with ONE brand star (reuse the loader glyph), Clash title,
 * one muted caption, optional ghost CTA, and a single neon hairline above it. */
.empty {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 14px;
  max-width: var(--measure-tight);
  margin: 0 auto;
  padding: 40px 20px;
}
.empty .bb-startag,
.empty .bb-startag-loader { width: 40px; height: 40px; }
.empty h2 {
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 600;
  letter-spacing: -0.01em;       /* override the label-tier h2 tracking here */
  text-transform: none;
  color: var(--text);
  margin: 0;
}
.empty p {
  color: var(--muted);
  font-weight: 430;
  max-width: var(--measure-tight);
  margin: 0;
}
/* Optional spec-line subtext — a status-code micro-cap ("NO DROPS — STANDBY"). */
.empty .status {
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--muted-soft);
}
.empty .button { margin-top: 6px; }
.empty::after {
  content: "";
  width: 24px; height: 1px;
  background: var(--neon-hairline);
  box-shadow: var(--neon-halo);
  opacity: 0.5;
  margin-top: 6px;
}

/* ── BLOCKQUOTE / REVIEW ATTRIBUTION — quiet editorial pull ─────────────────
 * A thin magenta rule on the left + a tracked attribution cap underneath. */
.quote, blockquote.quote {
  margin: 0;
  padding: 2px 0 2px 18px;
  border-left: 2px solid var(--accent);
  box-shadow: -1px 0 6px rgba(255, 46, 196, 0.25);   /* faint neon bleed off the rule */
  color: var(--text);
  font-size: var(--step-1);
  font-weight: 430;
  line-height: 1.45;
  max-width: var(--measure-lead);
  text-wrap: pretty;
}
.quote__cite, .quote cite {
  display: block;
  margin-top: 10px;
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: var(--track);
  text-transform: uppercase;
  font-style: normal;
  color: var(--muted-soft);
}
.quote__cite b, .quote cite b { color: var(--text); }
/* Review stars: one branded magenta star mark per review, tabular score beside. */
.review__score {
  font-variant-numeric: tabular-nums; font-feature-settings: "zero" 1;
  font-weight: 650; color: var(--text);
}
.review__stars { color: var(--accent); letter-spacing: 0.08em; }

/* ── AA + COHESION FIXES on shipped components ─────────────────────────────
 * Primary button: near-black text on the magenta gradient (was #fff, borderline
 * AA on #ff2ec4) + ease tracking onto --track. Ghost button keeps light text. */
.button, .button-link, button.btn, input[type="submit"] {
  color: #050505;
  letter-spacing: var(--track);
}
.button:hover, .button-link:hover, button.btn:hover, input[type="submit"]:hover { color: #050505; }
.button.ghost { color: var(--text); }
.button.ghost:hover { color: var(--text); }

/* Site-wide keyboard focus ring (WCAG 2.4.7) — reuses the shipped --focus-ring
   token so every primary control/nav/tab/chip shows a visible accent ring. */
.button:focus-visible, .button-link:focus-visible, button.btn:focus-visible,
input[type="submit"]:focus-visible, .bb-navlink:focus-visible, .chip:focus-visible,
.copybox button:focus-visible, .bb-sheet__row:focus-visible {
  outline: none; box-shadow: var(--focus-ring);
}
.bb-tab:focus-visible {
  outline: none; box-shadow: inset 0 0 0 2px var(--accent); border-radius: var(--radius-sm);
}

/* Site nav + title + footer micro-caps onto the constant for one tracked family. */
.site-title, .site-nav a, .site-footer__inner { letter-spacing: var(--track); }

/* Texture restraint reminder: .bb-tex-grille / .bb-tex-halftone stay on ONE
   elevated panel or card-corner per page at the shipped ≤6–8% cap — never
   behind running body. (No rule needed; the shipped --tex-opacity guards it.) */

/* ── end TYPE & MICRO-UI COHESION v3 ─────────────────────────────────────── */

/* ── end 5★ DESIGN SYSTEM v2 ─────────────────────────────────────────── */

/* ════════════════════════════════════════════════════════════════════════
 * ✶ FULL-SITE COVERAGE v4 (2026-06) — the "every page on-system" safety net
 * ────────────────────────────────────────────────────────────────────────
 * PURPOSE: bring the SECONDARY/INTERNAL pages (the 25 blog/reviews articles
 * that share blog/post.html, the blog index, and every admin tool) up to the
 * shipped 5★ bar WITHOUT per-page edits. This block is APPEND-ONLY and builds
 * exclusively on the tokens/classes defined above (--accent, --line, --muted,
 * --glow-*, --bevel, --neon-hairline, --track, --step-*, .prose, .table,
 * .field, .pill, .empty …). It NEVER redefines or reverts a shipped rule.
 *
 * CASCADE NOTE (load order): style.css is <link>ed in base.html BEFORE the
 * per-page inline <style> (which lands in {% block head %} further down the
 * <head>). So for EQUAL specificity the page inline rules win. To respect the
 * shipped per-page CSS instead of fighting it, the article-body defaults here
 * use :where() (specificity 0,0,0): they paint bare/uncovered elements but
 * silently yield to any inline class or element rule a template already sets.
 * Admin + generic safety nets use normal specificity because those pages have
 * no competing inline element rules — only utility classes that should win.
 *
 * RULES honoured: no new fonts, no new colors, AA preserved (body off-white,
 * magenta for accents/labels/links only — never long body copy), motion
 * compositor-only + already covered by the global reduced-motion blocks above.
 * ════════════════════════════════════════════════════════════════════════ */

/* ──────────────────────────────────────────────────────────────────────────
 * 1) BLOG / REVIEWS ARTICLE BODY — render as .prose by default
 * ──────────────────────────────────────────────────────────────────────────
 * The article container is .review-wrap (blog/post.html); the editorial body
 * lives in {% block body %} of each child post. The parent template already
 * sets .review-wrap p/h2/h3/li/a/blockquote/table inline, so we DON'T restate
 * those (they'd lose the specificity tie anyway). Instead we (a) give the
 * container the prose measure + rhythm, and (b) paint the elements the inline
 * sheet leaves bare so untouched markup still reads as one system.
 * All selectors are :where()-wrapped → zero specificity, yields to templates. */

/* Container: prose measure + comfortable reading rhythm. */
:where(.review-wrap) {
  color: var(--muted);
  line-height: var(--lh-prose);
}
:where(.review-wrap) > * { max-width: var(--measure); }
:where(.review-wrap) > .verdict,
:where(.review-wrap) > .funnel,
:where(.review-wrap) > .trust-chip,
:where(.review-wrap) > .cust-reviews,
:where(.review-wrap) > .related-block,
:where(.review-wrap) > table { max-width: none; }   /* full-width UI blocks */

/* Paragraph rhythm — margin-only separation (matches .prose). */
:where(.review-wrap p) { text-wrap: pretty; }
:where(.review-wrap p + p) { margin-top: 0.9em; }

/* Lead intro — narrower measure, full-strength text (template sets size/color). */
:where(.review-wrap .lead) { max-width: var(--measure-lead); text-wrap: pretty; }

/* Emphasis inside body: weight only, never magenta, never heavy (AA + calm). */
:where(.review-wrap strong) { font-weight: 650; color: var(--text); }
:where(.review-wrap em) { font-style: italic; }

/* Headings widow-control + balanced wrap (size/rule already set inline). */
:where(.review-wrap h1, .review-wrap h2, .review-wrap h3, .review-wrap h4) {
  text-wrap: balance;
}

/* Bare elements the inline sheet never reaches → on-system defaults. */
:where(.review-wrap hr) {
  border: 0;
  height: 1px;
  margin: 30px 0;
  background: var(--neon-hairline);
  box-shadow: var(--neon-halo);
  opacity: 0.7;
}
:where(.review-wrap img) {
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
}
:where(.review-wrap figure) { margin: 1.4em 0; }
:where(.review-wrap figcaption) {
  margin-top: 8px;
  font-size: var(--step--1);
  color: var(--muted-soft);
  line-height: 1.5;
}
:where(.review-wrap code) {
  background: var(--panel-soft);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 2px 7px;
  font-size: 0.88em;
  color: var(--text);
}
:where(.review-wrap small) { font-size: var(--step--1); color: var(--muted-soft); }
:where(.review-wrap dl) { margin: 1.2em 0; }
:where(.review-wrap dt) {
  font-weight: 700;
  letter-spacing: var(--track);
  text-transform: uppercase;
  font-size: var(--step--1);
  color: var(--muted-soft);
}
:where(.review-wrap dd) { margin: 0 0 0.7em; color: var(--text); }

/* List markers: a quiet magenta tick where the template only sets padding.
   Zero-specificity so a template that adds its own marker still wins. */
:where(.review-wrap ul) { list-style: none; padding-left: 1.4em; }
:where(.review-wrap ul > li) { position: relative; }
:where(.review-wrap ul > li)::before {
  content: "\25B8";                 /* ▸ — the site-wide list glyph */
  position: absolute;
  left: -1.2em;
  color: var(--accent);
  font-size: 0.8em;
  line-height: 1.9;
}
:where(.review-wrap ol) {
  list-style: none;
  padding-left: 0;
  counter-reset: bbli;
}
:where(.review-wrap ol > li) {
  position: relative;
  padding-left: 2.1em;
  counter-increment: bbli;
}
:where(.review-wrap ol > li)::before {
  content: counter(bbli, decimal-leading-zero);
  position: absolute; left: 0; top: 0;
  color: var(--accent);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "zero" 1;
  font-size: 0.85em;
}

/* Article numerals read as figures (prices, potency %, order counts). */
:where(.review-wrap) { font-variant-numeric: tabular-nums; font-feature-settings: "zero" 1; }
:where(.review-wrap h1, .review-wrap h2, .review-wrap h3) { font-feature-settings: normal; }

/* ──────────────────────────────────────────────────────────────────────────
 * 2) BLOG INDEX (/blog) — give the bespoke .blog-wrap container prose calm.
 * The inline sheet sizes .blog-wrap h1/.lead and the cards; we only add the
 * reading measure + widow control it omits (zero-specificity, yields to it). */
:where(.blog-wrap) { color: var(--muted); }
:where(.blog-wrap h1, .blog-wrap h2) { text-wrap: balance; }
:where(.blog-wrap .lead) { max-width: var(--measure-lead); text-wrap: pretty; }
:where(.blog-wrap p) { text-wrap: pretty; }

/* ──────────────────────────────────────────────────────────────────────────
 * 3) ADMIN + INTERNAL TOOLS — branded defaults on the shared .content shell.
 * Admin templates extend base.html (no .review-wrap / .blog-wrap), so .content
 * is the reliable hook. These run at normal specificity: admin pages carry no
 * competing inline ELEMENT rules, only utility classes (.table/.pill/.button/
 * .input/.entry-card) which are equal-or-higher specificity and still win.
 * Functional polish — NOT bespoke hero treatments (per the brief).
 * ──────────────────────────────────────────────────────────────────────── */

/* Page titles: bare admin <h1> already inherits the shipped h1 (Clash, caps).
   Tighten the top margin so admin pages start clean under the chrome. */
.content > h1:first-child,
.content > div:first-child > h1 { margin-top: 0; }

/* Bare admin <h2> section heads → the shipped tracked micro-cap, with a quiet
   magenta hairline underneath so sections read as deliberate breaks.
   .review-wrap/.blog-wrap excluded (they set their own h2). */
.content h2:not(.review-wrap h2):not(.blog-wrap h2):not(.empty h2) {
  position: relative;
  padding-bottom: 8px;
}
.content h2:not(.review-wrap h2):not(.blog-wrap h2):not(.empty h2)::after {
  content: "";
  position: absolute; left: 0; bottom: 0;
  width: 32px; height: 1px;
  background: var(--neon-hairline);
  box-shadow: var(--neon-halo);
  opacity: 0.8;
  pointer-events: none;
}

/* Bare TABLES (no .table class) inside .content get the full ledger treatment
   so an untouched admin table still looks like the shipped one. The .table
   class (higher specificity / richer) keeps overriding where it's applied. */
.content table:not(.table):not(.review-wrap table) {
  width: 100%;
  border-collapse: collapse;
  background: rgba(13, 13, 15, 0.97);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  overflow: hidden;
  font-size: 14px;
}
.content table:not(.table):not(.review-wrap table) th,
.content table:not(.table):not(.review-wrap table) td {
  text-align: left;
  padding: 13px 16px;
  border-bottom: 1px solid var(--line);
  color: var(--text);
}
.content table:not(.table):not(.review-wrap table) th {
  font-weight: 800;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: var(--track);
  background: rgba(0, 0, 0, 0.45);
}
.content table:not(.table):not(.review-wrap table) tbody tr:last-child td,
.content table:not(.table):not(.review-wrap table) tr:last-child td { border-bottom: 0; }
.content table:not(.table):not(.review-wrap table) tr:hover td { background: rgba(255, 255, 255, 0.04); }

/* Bare FORM CONTROLS (no .input/.select/.textarea/.field class) inside .content
   → the shipped field chrome. Keyed off :not(...) so classed inputs win. */
.content input:not(.input):not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="file"]),
.content select:not(.select),
.content textarea:not(.textarea) {
  width: 100%;
  padding: 13px 15px;
  background: var(--panel-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 500;
  line-height: 1.4;
  transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease;
  -webkit-appearance: none; appearance: none;
}
.content input:not(.input):not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="file"]):focus,
.content select:not(.select):focus,
.content textarea:not(.textarea):focus {
  outline: none;
  border-color: rgba(255, 46, 196, 0.55);
  box-shadow: var(--focus-ring);
  background: #161618;
}
.content input:not(.input)::placeholder,
.content textarea:not(.textarea)::placeholder {
  color: var(--muted-soft);
  font-weight: 430;
  opacity: 1;
}
.content textarea:not(.textarea) { min-height: 110px; resize: vertical; }

/* Bare LABELS for those inputs → tracked uppercase micro-cap. */
.content form label:not(.field__label):not(.label) {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--muted);
}

/* Bare <dl> definition lists in admin (order/user detail spec rows). */
.content dl:not(.dl-spec):not(.review-wrap dl) {
  display: grid;
  grid-template-columns: minmax(0, 0.5fr) minmax(0, 1fr);
  gap: 6px 18px;
  margin: 0;
}
.content dl:not(.dl-spec):not(.review-wrap dl) dt {
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--muted-soft);
}
.content dl:not(.dl-spec):not(.review-wrap dl) dd { margin: 0; color: var(--text); }

/* Bare <blockquote> inside admin/generic .content → the quiet pull-quote rule
   (.quote class stays the richer canonical; .review-wrap sets its own inline). */
.content blockquote:not(.quote):not(.review-wrap blockquote) {
  margin: 1.2em 0;
  padding: 2px 0 2px 18px;
  border-left: 2px solid var(--accent);
  box-shadow: -1px 0 6px rgba(255, 46, 196, 0.25);
  color: var(--text);
  font-weight: 430;
  line-height: 1.45;
}

/* Bare <pre> blocks (rare admin JSON/log dumps) read as a calm code panel. */
.content pre:not(.review-wrap pre) {
  background: var(--panel-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  font-size: 13px;
  color: var(--text);
  line-height: 1.5;
}

/* ──────────────────────────────────────────────────────────────────────────
 * 4) GENERIC LINK SAFETY NET — any bare inline link inside an admin/text
 * block on .content (not chrome, not a button/chip/card/pill) gets the
 * shipped magenta-underline-at-rest treatment, matching .prose a / .content a.
 * Utility/structural links (nav, tabs, cards, footer, buttons) are excluded so
 * their own styling stands. The shipped ".content a" rule (line ~2286) already
 * covers most of this; this scopes the hover color consistently and is a no-op
 * where a more specific class already paints the link. */
.content a:not(.button):not(.button-link):not(.btn):not(.chip):not(.pill):not(.link-caps):not(.link-arrow):not(.feature-card):not(.bb-tag):not(.bb-tab):not(.bb-navlink):not(.copybox button):not([class*="__"]):hover {
  color: var(--accent-strong);
}

/* ──────────────────────────────────────────────────────────────────────────
 * 5) EMPTY / FALLBACK STATES — admin "nothing here yet" cards (which use a
 * bare <p class="muted"> inside an .entry-card) get centered, measured copy so
 * they read as the shipped .empty language even without the full markup. */
.content .entry-card[style*="text-align:center"] p,
.content .entry-card[style*="text-align: center"] p {
  max-width: var(--measure-tight);
  margin-left: auto;
  margin-right: auto;
  font-weight: 430;
}

/* ── end FULL-SITE COVERAGE v4 ─────────────────────────────────────────── */
