// Guestmaker · Advanced Segmentation showcase. Sits below the Bookings section.
// Interactive segment builder with a full catalogue of typed fields and operators,
// including calculated booking metrics, folio extras, semantic memory search,
// reachability, consent, behaviour and tags. Live matching count + sample contacts.

const { useState: sUseState, useEffect: sUseEffect, useMemo: sUseMemo, useRef: sUseRef } = React;

// ────────────────────────── tokens ──────────────────────────
const S_FUCHSIA      = "#ED4D86";
const S_FUCHSIA_DEEP = "#C93A6B";
const S_FUCHSIA_DARK = "#8E2148";
const S_FUCHSIA_SOFT = "#F8B7CF";
const S_FUCHSIA_PALE = "#FCE4EE";
const S_FUCHSIA_WASH = "#FDF0F5";
const S_PLUM         = "#211A22";
const S_PLUM_DEEP    = "#160F17";
const S_INK     = "#1a1a1a";
const S_DIM     = "#6e6363";
const S_FAINT   = "#a99fa3";
const S_RULE    = "#e9e3d4";
const S_RULE_S  = "#f0ebde";
const S_PAPER   = "#fbfaf6";
const S_CREAM   = "#f6f4ef";
const S_MONO    = "'JetBrains Mono', ui-monospace, monospace";
const S_SERIF   = "var(--f-display)";

// ────────────────────────── icons ──────────────────────────
function SIcon({ name, size = 14, color, strokeWidth = 1.8, style }) {
  const stroke = color || "currentColor";
  const p = {
    width: size, height: size, viewBox: "0 0 24 24", fill: "none",
    stroke, strokeWidth, strokeLinecap: "round", strokeLinejoin: "round",
    style: { display: "block", flexShrink: 0, ...style },
  };
  switch (name) {
    case "user":       return <svg {...p}><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></svg>;
    case "users":      return <svg {...p}><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8"/></svg>;
    case "calendar":   return <svg {...p}><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M16 3v4M8 3v4M3 11h18"/></svg>;
    case "bed":        return <svg {...p}><path d="M2 20v-7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v7"/><path d="M2 17h20M6 11V7a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v4"/><circle cx="8" cy="9" r="1.2"/></svg>;
    case "wallet":     return <svg {...p}><path d="M2 7a2 2 0 0 1 2-2h15a1 1 0 0 1 1 1v3"/><path d="M2 7v11a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-8H4a2 2 0 0 1-2-2z"/><circle cx="18" cy="14" r="1.2" fill={stroke}/></svg>;
    case "brain":      return <svg {...p}><path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2z"/><path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2z"/></svg>;
    case "send":       return <svg {...p}><path d="M22 2 11 13M22 2l-7 20-4-9-9-4z"/></svg>;
    case "shield":     return <svg {...p}><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>;
    case "compass":    return <svg {...p}><circle cx="12" cy="12" r="10"/><polygon points="16.2,7.8 13.4,13.4 7.8,16.2 10.6,10.6"/></svg>;
    case "tag":        return <svg {...p}><path d="M20 12 12 20 3 11V3h8z"/><circle cx="7.5" cy="7.5" r="1.2"/></svg>;
    case "chevron":    return <svg {...p}><polyline points="6,9 12,15 18,9"/></svg>;
    case "close":      return <svg {...p}><line x1="6" y1="6" x2="18" y2="18"/><line x1="6" y1="18" x2="18" y2="6"/></svg>;
    case "plus":       return <svg {...p}><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>;
    case "trash":      return <svg {...p}><polyline points="3,6 5,6 21,6"/><path d="M19 6 18 20a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6M10 11v6M14 11v6"/></svg>;
    case "search":     return <svg {...p}><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></svg>;
    case "spark":      return <svg {...p}><path d="M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1"/><circle cx="12" cy="12" r="3"/></svg>;
    case "check":      return <svg {...p}><polyline points="4,12 10,18 20,6"/></svg>;
    case "abc":        return <svg {...p}><path d="M4 18V8m0 5h4M4 8h4v10M14 18l3-10 3 10M14.7 15h4.6"/></svg>;
    case "hash":       return <svg {...p}><line x1="4" y1="9" x2="20" y2="9"/><line x1="4" y1="15" x2="20" y2="15"/><line x1="10" y1="3" x2="8" y2="21"/><line x1="16" y1="3" x2="14" y2="21"/></svg>;
    case "euro":       return <svg {...p}><path d="M18 6a8 8 0 1 0 0 12M4 10h10M4 14h10"/></svg>;
    case "boolean":    return <svg {...p}><rect x="2" y="7" width="20" height="10" rx="5"/><circle cx="17" cy="12" r="3" fill={stroke}/></svg>;
    case "list":       return <svg {...p}><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><circle cx="4" cy="6" r="1" fill={stroke}/><circle cx="4" cy="12" r="1" fill={stroke}/><circle cx="4" cy="18" r="1" fill={stroke}/></svg>;
    case "wand":       return <svg {...p}><path d="M15 4l1 2 2 1-2 1-1 2-1-2-2-1 2-1zM21 7l.5 1 1 .5-1 .5-.5 1-.5-1-1-.5 1-.5zM3 21l10-10M14 5l5 5"/></svg>;
    case "save":       return <svg {...p}><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17,21 17,13 7,13 7,21"/><polyline points="7,3 7,8 15,8"/></svg>;
    case "play":       return <svg {...p} fill={stroke}><polygon points="6,4 20,12 6,20"/></svg>;
    case "phone":      return <svg {...p}><path d="M22 16.9v3a2 2 0 0 1-2.2 2 19.8 19.8 0 0 1-8.6-3.1 19.5 19.5 0 0 1-6-6 19.8 19.8 0 0 1-3.1-8.7A2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .3 1.9.6 2.8a2 2 0 0 1-.5 2.1L8 9.9a16 16 0 0 0 6 6l1.3-1.3a2 2 0 0 1 2.1-.4c.9.3 1.8.5 2.8.6a2 2 0 0 1 1.8 2z"/></svg>;
    case "mail":       return <svg {...p}><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>;
    case "building":   return <svg {...p}><rect x="4" y="3" width="16" height="18" rx="1.5"/><path d="M8 7h3M8 11h3M8 15h3M13 7h3M13 11h3M13 15h3M9 21v-3h6v3"/></svg>;
    case "external":   return <svg {...p}><path d="M14 3h7v7M10 14 21 3M19 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h6"/></svg>;
    case "filter":     return <svg {...p}><polygon points="3,4 21,4 14,12 14,20 10,18 10,12"/></svg>;
    case "layers":     return <svg {...p}><polygon points="12,2 2,8 12,14 22,8"/><polyline points="2,16 12,22 22,16"/><polyline points="2,12 12,18 22,12"/></svg>;
    case "trending":   return <svg {...p}><polyline points="3,17 9,11 13,15 21,7"/><polyline points="15,7 21,7 21,13"/></svg>;
    case "globe":      return <svg {...p}><circle cx="12" cy="12" r="10"/><path d="M2 12h20M12 2a15 15 0 0 1 0 20M12 2a15 15 0 0 0 0 20"/></svg>;
    default: return null;
  }
}

// ────────────────────────── field catalogue ──────────────────────────
const S_FIELDS = [
  {
    group: "Contact", icon: "user",
    items: [
      { id: "first_name",   label: "First Name",   type: "string" },
      { id: "last_name",    label: "Last Name",    type: "string" },
      { id: "email",        label: "Email",        type: "string" },
      { id: "phone",        label: "Phone",        type: "string" },
      { id: "language",     label: "Language",     type: "enum", options: ["English","Spanish","French","German","Italian","Portuguese","Dutch","Japanese","Polish","Greek","Czech","Hungarian","Catalan"] },
      { id: "country",      label: "Country",      type: "enum", options: ["ES","FR","DE","UK","NL","IT","JP","US","BR","AR","IE","SE","NO","DK","FI","PT","BE","CH"] },
      { id: "guest_stage",  label: "Guest Stage",  type: "enum", options: ["Unknown","Pre-Stay","In-Stay","Post-Stay","Returning"] },
      { id: "created_at",   label: "Contact Created", type: "date" },
      { id: "source",       label: "Acquisition Source", type: "enum", options: ["Booking Engine","Direct · Web","Roiback","Booking.com","Expedia","Captive Portal","Voice Centre","Reception"] },
    ],
  },
  {
    group: "Bookings · calculated", icon: "bed", accent: S_FUCHSIA,
    items: [
      { id: "total_bookings",      label: "Total Historical Bookings", type: "number" },
      { id: "lifetime_revenue",    label: "Lifetime Revenue",          type: "currency" },
      { id: "avg_booking_value",   label: "Avg Booking Value",         type: "currency" },
      { id: "total_nights",        label: "Total Nights Stayed",       type: "number" },
      { id: "last_booking_date",   label: "Last Booking Date",         type: "date" },
      { id: "first_booking_date",  label: "First Booking Date",        type: "date" },
      { id: "properties_stayed",   label: "Properties Stayed",         type: "multi-enum", options: ["AURELIA Cala Marina","AURELIA Costa Brava","AURELIA Playa Roja","AURELIA Bahía Verde","AURELIA Punta Azul"] },
      { id: "rooms_stayed",        label: "Room Types Booked",         type: "multi-enum", options: ["Standard","Doble Vista Mar","Vista Piscina","Junior Suite","Suite Vista Mar","Family Suite"] },
      { id: "boards_stayed",       label: "Board Types Booked",        type: "multi-enum", options: ["RO","BB","HB","FB","AI"] },
      { id: "rate_plans",          label: "Rate Plans Booked",         type: "multi-enum", options: ["NRF","FLEX","ADV","PROMO","CORP"] },
      { id: "cancellation_count",  label: "Cancellations",             type: "number" },
      { id: "no_show_count",       label: "No-Shows",                  type: "number" },
      { id: "upcoming_stays",      label: "Upcoming Stays",            type: "number" },
    ],
  },
  {
    group: "Folio extras · calculated", icon: "wallet", accent: S_FUCHSIA_DEEP,
    items: [
      { id: "total_extras",   label: "Total Folio Extras Spend", type: "currency" },
      { id: "spa_spend",      label: "Spa Spend",                type: "currency" },
      { id: "fb_spend",       label: "F&B Outlets Spend",        type: "currency" },
      { id: "minibar_spend",  label: "Minibar Spend",            type: "currency" },
      { id: "excursion_spend",label: "Excursions Spend",         type: "currency" },
      { id: "parking_spend",  label: "Parking Spend",            type: "currency" },
      { id: "extras_ratio",   label: "Extras / Room Revenue %",  type: "number" },
    ],
  },
  {
    group: "Memory · semantic", icon: "brain", accent: S_PLUM,
    items: [
      { id: "interests",   label: "Interests",     type: "semantic" },
      { id: "preferences", label: "Preferences",   type: "semantic" },
      { id: "dislikes",    label: "Dislikes",      type: "semantic" },
      { id: "context",     label: "Guest Context", type: "semantic" },
      { id: "issues",      label: "Past Issues",   type: "semantic" },
    ],
  },
  {
    group: "Channels & engagement", icon: "send",
    items: [
      { id: "reachable_on",     label: "Reachable On",          type: "multi-enum", options: ["WhatsApp","Email","SMS","Instagram","Facebook","Voice"] },
      { id: "last_channel",     label: "Last Channel Used",     type: "enum", options: ["WhatsApp","Web Chatbot","Voice","Instagram","Facebook","Email","SMS"] },
      { id: "engagement_score", label: "Engagement Score",      type: "number" },
      { id: "last_message_at",  label: "Last Message",          type: "date" },
      { id: "messages_30d",     label: "Messages (last 30 days)", type: "number" },
      { id: "ai_resolution_rate", label: "AI Resolution Rate %",  type: "number" },
    ],
  },
  {
    group: "Consent", icon: "shield", accent: S_FUCHSIA_DARK,
    items: [
      { id: "wa_marketing",     label: "WhatsApp Marketing",   type: "bool" },
      { id: "email_marketing",  label: "Email Marketing",      type: "bool" },
      { id: "ig_marketing",     label: "Instagram Marketing",  type: "bool" },
      { id: "promo_emails",     label: "Promotional Emails",   type: "bool" },
      { id: "newsletter",       label: "Newsletter",           type: "bool" },
      { id: "announcements",    label: "Announcements",        type: "bool" },
    ],
  },
  {
    group: "Behaviour", icon: "compass",
    items: [
      { id: "sessions_90d",     label: "Website Sessions (90d)", type: "number" },
      { id: "pages_per_session",label: "Pages per Session",      type: "number" },
      { id: "funnel_stage",     label: "Deepest Funnel Stage",   type: "enum", options: ["Landing","Room Details","Date Picker","Booking Started","Booking Completed"] },
      { id: "cart_abandoned",   label: "Cart Abandoned",         type: "bool" },
      { id: "last_visit_at",    label: "Last Visit",             type: "date" },
    ],
  },
  {
    group: "Tags & custom fields", icon: "tag",
    items: [
      { id: "tags",             label: "Tags",                  type: "multi-enum", options: ["VIP","Returning","Big Spender","Loyalty Silver","Loyalty Gold","Loyalty Platinum","Cyclist","Foodie","Wellness","Family","Honeymoon","Corporate"] },
      { id: "loyalty_tier",     label: "Loyalty Tier",          type: "enum",  options: ["None","Silver","Gold","Platinum"] },
      { id: "loyalty_points",   label: "Loyalty Points",        type: "number" },
      { id: "vat_id",           label: "VAT ID (Corporate)",    type: "string" },
    ],
  },
];

const S_FIELD_BY_ID = {};
for (const grp of S_FIELDS) for (const f of grp.items) S_FIELD_BY_ID[f.id] = { ...f, group: grp.group, groupIcon: grp.icon };

// Operators per type
const S_OPERATORS = {
  string:       ["equals","does not equal","contains","does not contain","starts with","ends with","is one of","is not one of","is empty","is not empty"],
  number:       ["equals","does not equal","greater than","less than","≥","≤","between","is empty","is not empty"],
  currency:     ["greater than","less than","≥","≤","between","equals"],
  date:         ["before","after","between","in the last X days","more than X days ago","equals","is empty","is not empty"],
  bool:         ["is true","is false"],
  enum:         ["equals","is one of","is not one of","is empty","is not empty"],
  "multi-enum": ["includes","includes any of","includes all of","excludes","is empty","is not empty"],
  semantic:     ["matches","similar to","does not match"],
};
const TYPE_ICON = { string: "abc", number: "hash", currency: "euro", date: "calendar", bool: "boolean", enum: "list", "multi-enum": "list", semantic: "brain" };
const TYPE_LABEL = { string: "TEXT", number: "NUMBER", currency: "CURRENCY", date: "DATE", bool: "BOOLEAN", enum: "ENUM", "multi-enum": "MULTI-ENUM", semantic: "SEMANTIC" };

// Default segment + conditions
const DEFAULT_CONDITIONS = [
  {
    id: "g1", match: "ALL",
    conditions: [
      { id: "c1", field: "lifetime_revenue",   op: "≥",          value: 2500 },
      { id: "c2", field: "total_bookings",     op: "≥",          value: 3 },
      { id: "c3", field: "reachable_on",       op: "includes any of", value: ["WhatsApp","Email"] },
      { id: "c4", field: "interests",          op: "similar to",  value: "cycling routes, wine tasting, spa retreat" },
    ],
  },
  {
    id: "g2", match: "ANY",
    conditions: [
      { id: "c5", field: "last_booking_date",  op: "in the last X days", value: 180 },
      { id: "c6", field: "properties_stayed",  op: "includes",   value: ["AURELIA Cala Marina","AURELIA Bahía Verde"] },
    ],
  },
];

// Sample matching contacts (preview)
const S_SAMPLE = [
  { fn: "Sofia",     ln: "Marchetti",      phone: "+39 348 772 1183",  email: "sofia.marchetti@aribamail.it", lang: "IT", country: "IT", hotel: "AURELIA Cala Marina",  spend: 8420, bookings: 6, last: "12 days ago", tier: "Gold" },
  { fn: "Hiroko",    ln: "Tanaka",         phone: "+81 90 4118 2207",  email: "hiroko.tanaka@kireimail.jp",   lang: "JP", country: "JP", hotel: "AURELIA Bahía Verde",  spend: 14210,bookings: 9, last: "1 month ago",tier: "Platinum" },
  { fn: "Anna",      ln: "Lindgren",       phone: "+46 70 412 8855",   email: "anna.l@duckpost.io",            lang: "SE", country: "SE", hotel: "AURELIA Cala Marina",  spend: 6510, bookings: 4, last: "4 days ago", tier: "Gold" },
  { fn: "Mathias",   ln: "Brun",           phone: "+41 78 332 4901",   email: "mathias.brun@swissnet.ch",      lang: "DE", country: "CH", hotel: "AURELIA Bahía Verde",  spend: 5290, bookings: 3, last: "2 months ago",tier: "Silver" },
  { fn: "Pieter",    ln: "de Vries",       phone: "+31 6 2235 6671",   email: "p.devries@tulipmail.nl",        lang: "NL", country: "NL", hotel: "AURELIA Playa Roja",   spend: 11030,bookings: 7, last: "3 weeks ago",tier: "Gold" },
  { fn: "Karoline",  ln: "Berg",           phone: "+47 41 332 9907",   email: "karoline.berg@nordpost.no",     lang: "NO", country: "NO", hotel: "AURELIA Cala Marina",  spend: 3420, bookings: 3, last: "5 days ago", tier: "Silver" },
  { fn: "Brian",     ln: "O'Hara",         phone: "+1 415 220 7785",   email: "brian.ohara@northport.us",      lang: "EN", country: "US", hotel: "AURELIA Bahía Verde",  spend: 9180, bookings: 5, last: "9 days ago", tier: "Gold" },
  { fn: "Lucía",     ln: "Rivero",         phone: "+54 11 6622 3340",  email: "lucia.rivero@vientomail.ar",    lang: "ES", country: "AR", hotel: "AURELIA Cala Marina",  spend: 4720, bookings: 3, last: "1 month ago",tier: "Silver" },
  { fn: "Camille",   ln: "Dubois",         phone: "+33 6 7702 1144",   email: "camille.dubois@brisemail.fr",   lang: "FR", country: "FR", hotel: "AURELIA Bahía Verde",  spend: 7240, bookings: 4, last: "2 weeks ago",tier: "Gold" },
  { fn: "Tessa",     ln: "Brandt",         phone: "+31 6 4451 2208",   email: "tessa.brandt@tulipmail.nl",     lang: "NL", country: "NL", hotel: "AURELIA Cala Marina",  spend: 5980, bookings: 4, last: "6 days ago", tier: "Gold" },
  { fn: "Sigrún",    ln: "Magnúsdóttir",   phone: "+354 690 4421",     email: "sigrun.m@northmail.is",         lang: "IS", country: "IS", hotel: "AURELIA Bahía Verde",  spend: 3160, bookings: 3, last: "3 weeks ago",tier: "Silver" },
  { fn: "Diego",     ln: "Solano",         phone: "+52 55 4422 1108",  email: "diego.solano@solpost.mx",       lang: "ES", country: "MX", hotel: "AURELIA Punta Azul",   spend: 6810, bookings: 5, last: "1 week ago", tier: "Gold" },
];

// ────────────────────────── atoms ──────────────────────────
function SMono({ children, size = 11, color = S_DIM, style }) {
  return <span style={{ fontFamily: S_MONO, fontSize: size, color, letterSpacing: "0.04em", ...style }}>{children}</span>;
}
function SEyebrow({ children, color = S_FUCHSIA, style }) {
  return <div style={{
    fontFamily: S_MONO, fontSize: 10.5, color, fontWeight: 700,
    letterSpacing: "0.22em", textTransform: "uppercase", ...style,
  }}>{children}</div>;
}
function SDot({ color, size = 6, pulse = false, style }) {
  return <span style={{
    display: "inline-block", width: size, height: size, borderRadius: "50%",
    background: color, animation: pulse ? "gm-dot-pulse 1.4s ease-in-out infinite" : "none",
    flexShrink: 0, ...style,
  }} />;
}

function STopBar() {
  return (
    <div style={{
      display: "flex", alignItems: "center", justifyContent: "space-between",
      padding: "0 16px", height: 38, background: "#0e0e0e", color: "#cfc8c8",
      borderTopLeftRadius: 12, borderTopRightRadius: 12,
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
        <span style={{ width: 10, height: 10, borderRadius: 5, background: "#ff5f56" }} />
        <span style={{ width: 10, height: 10, borderRadius: 5, background: "#ffbd2e" }} />
        <span style={{ width: 10, height: 10, borderRadius: 5, background: "#27c93f" }} />
        <span style={{ marginLeft: 16, fontFamily: S_MONO, fontSize: 10.5, letterSpacing: "0.08em", color: "#8b8181" }}>
          guestmaker.ai / segments / new
        </span>
      </div>
      <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
        <span style={{ fontFamily: S_MONO, fontSize: 10, letterSpacing: "0.18em", color: "#b8acac", fontWeight: 700 }}>ADMIN</span>
        <span style={{ fontFamily: S_MONO, fontSize: 10, letterSpacing: "0.06em", color: "#cfc8c8" }}>AURELIA Hotels ▾</span>
      </div>
    </div>
  );
}

// ────────────────────────── dropdown shell ──────────────────────────
// Single floating popover used by Field/Operator/Value pickers.
function Popover({ open, onClose, anchor, width = 280, children }) {
  if (!open) return null;
  return (
    <>
      <div onClick={onClose} style={{
        position: "fixed", inset: 0, zIndex: 50,
      }} />
      <div style={{
        position: "absolute", top: "calc(100% + 6px)", left: 0,
        zIndex: 51, minWidth: width,
        background: "#fff", border: `1px solid ${S_RULE}`,
        borderRadius: 10, padding: 0,
        boxShadow: "0 24px 40px -22px rgba(20,14,10,0.32), 0 0 0 1px rgba(255,255,255,0.4) inset",
        maxHeight: 340, overflow: "auto",
        animation: "gm-fadein 0.15s ease",
      }} className="gm-scroll">
        {children}
      </div>
    </>
  );
}

// ────────────────────────── field picker ──────────────────────────
function TypeBadge({ type, small }) {
  return (
    <span style={{
      display: "inline-flex", alignItems: "center", gap: 3,
      padding: small ? "1px 5px" : "1px 6px", borderRadius: 3,
      background: S_FUCHSIA_WASH, color: S_FUCHSIA_DEEP,
      border: `1px solid ${S_FUCHSIA}33`,
      fontFamily: S_MONO, fontSize: small ? 8 : 8.5, fontWeight: 700, letterSpacing: "0.08em",
    }}>
      <SIcon name={TYPE_ICON[type]} size={small ? 8 : 9} color={S_FUCHSIA_DEEP} strokeWidth={2} />
      {TYPE_LABEL[type]}
    </span>
  );
}

function FieldPicker({ value, onChange }) {
  const [open, setOpen] = sUseState(false);
  const [q, setQ] = sUseState("");
  const field = S_FIELD_BY_ID[value];
  const filtered = sUseMemo(() => {
    if (!q) return S_FIELDS;
    const ql = q.toLowerCase();
    return S_FIELDS.map(g => ({
      ...g,
      items: g.items.filter(f => f.label.toLowerCase().includes(ql) || f.id.toLowerCase().includes(ql)),
    })).filter(g => g.items.length > 0);
  }, [q]);

  return (
    <div style={{ position: "relative", flex: "1 1 240px", minWidth: 200 }}>
      <button onClick={() => setOpen(o => !o)} style={pickerButton(open)}>
        <SIcon name={field?.groupIcon || "filter"} size={13} color={S_DIM} strokeWidth={1.9} />
        <span style={{ fontSize: 12.5, color: S_INK, fontWeight: 600, flex: 1, textAlign: "left", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
          {field?.label || "Select field…"}
        </span>
        {field && <TypeBadge type={field.type} small />}
        <SIcon name="chevron" size={11} color={S_FAINT} strokeWidth={2}
          style={{ transform: open ? "rotate(180deg)" : "none", transition: "transform 0.15s" }} />
      </button>
      <Popover open={open} onClose={() => setOpen(false)} width={340}>
        <div style={{
          position: "sticky", top: 0, padding: "10px 12px 8px",
          background: "#fff", borderBottom: `1px solid ${S_RULE_S}`,
          display: "flex", alignItems: "center", gap: 7,
        }}>
          <SIcon name="search" size={12} color={S_DIM} strokeWidth={2} />
          <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search fields…"
            autoFocus
            style={{
              flex: 1, border: "none", outline: "none", background: "transparent",
              fontSize: 12, color: S_INK, fontFamily: "'Inter', sans-serif",
            }} />
        </div>
        {filtered.map((grp, gi) => (
          <div key={gi} style={{ padding: "8px 0 6px" }}>
            <div style={{
              padding: "4px 14px 6px",
              display: "flex", alignItems: "center", gap: 7,
            }}>
              <SIcon name={grp.icon} size={11} color={grp.accent || S_FUCHSIA} strokeWidth={2} />
              <SMono size={9.5} color={grp.accent || S_FUCHSIA_DEEP} style={{ letterSpacing: "0.16em", fontWeight: 700 }}>
                {grp.group.toUpperCase()}
              </SMono>
            </div>
            {grp.items.map(f => (
              <button key={f.id}
                onClick={() => { onChange(f.id); setOpen(false); setQ(""); }}
                style={{
                  display: "grid", gridTemplateColumns: "1fr auto",
                  gap: 8, alignItems: "center",
                  padding: "7px 14px",
                  background: f.id === value ? S_FUCHSIA + "10" : "transparent",
                  border: "none", width: "100%", cursor: "pointer",
                  fontSize: 12, color: S_INK, textAlign: "left",
                  fontFamily: "'Inter', sans-serif",
                }}
                onMouseEnter={e => { if (f.id !== value) e.currentTarget.style.background = S_FUCHSIA + "06"; }}
                onMouseLeave={e => { if (f.id !== value) e.currentTarget.style.background = "transparent"; }}
              >
                <span style={{ fontWeight: f.id === value ? 700 : 500 }}>{f.label}</span>
                <TypeBadge type={f.type} small />
              </button>
            ))}
          </div>
        ))}
      </Popover>
    </div>
  );
}

function pickerButton(open) {
  return {
    width: "100%", display: "flex", alignItems: "center", gap: 8,
    padding: "9px 12px", background: "#fff",
    border: `1px solid ${open ? S_FUCHSIA + "AA" : S_RULE}`,
    borderRadius: 8, cursor: "pointer", textAlign: "left",
    boxShadow: open ? `0 0 0 3px ${S_FUCHSIA}1F` : "none",
    fontFamily: "'Inter', sans-serif",
    transition: "all 0.15s ease",
    minHeight: 38,
  };
}

// ────────────────────────── operator picker ──────────────────────────
function OperatorPicker({ field, value, onChange }) {
  const [open, setOpen] = sUseState(false);
  const ops = field ? S_OPERATORS[field.type] || [] : [];
  return (
    <div style={{ position: "relative", flex: "0 0 200px", minWidth: 180 }}>
      <button onClick={() => setOpen(o => !o)} style={pickerButton(open)}>
        <span style={{ fontSize: 12.5, color: value ? S_INK : S_FAINT, fontWeight: 600, flex: 1 }}>
          {value || "operator…"}
        </span>
        <SIcon name="chevron" size={11} color={S_FAINT} strokeWidth={2}
          style={{ transform: open ? "rotate(180deg)" : "none", transition: "transform 0.15s" }} />
      </button>
      <Popover open={open} onClose={() => setOpen(false)} width={220}>
        <div style={{ padding: "8px 0" }}>
          {ops.map(op => (
            <button key={op}
              onClick={() => { onChange(op); setOpen(false); }}
              style={{
                display: "flex", alignItems: "center", gap: 8,
                padding: "7px 14px", border: "none",
                background: op === value ? S_FUCHSIA + "10" : "transparent",
                width: "100%", cursor: "pointer",
                fontSize: 12, color: S_INK, textAlign: "left",
                fontFamily: "'Inter', sans-serif",
              }}
              onMouseEnter={e => { if (op !== value) e.currentTarget.style.background = S_FUCHSIA + "06"; }}
              onMouseLeave={e => { if (op !== value) e.currentTarget.style.background = "transparent"; }}
            >
              <span style={{ fontWeight: op === value ? 700 : 500 }}>{op}</span>
              {op === value && <SIcon name="check" size={11} color={S_FUCHSIA} strokeWidth={2.4} style={{ marginLeft: "auto" }} />}
            </button>
          ))}
        </div>
      </Popover>
    </div>
  );
}

// ────────────────────────── value input (type-aware) ──────────────────────────
function ValueInput({ field, op, value, onChange }) {
  if (!field || !op) return <div style={{ flex: "1 1 240px", minWidth: 200 }}></div>;

  // single-empty operators don't need a value
  if (op.includes("is empty") || op.includes("is not empty")) {
    return (
      <div style={{
        flex: "1 1 240px", minWidth: 200, padding: "9px 12px",
        background: S_PAPER, border: `1px dashed ${S_RULE}`,
        borderRadius: 8, fontSize: 12, color: S_FAINT, fontStyle: "italic",
      }}>no value required</div>
    );
  }
  if (op === "is true" || op === "is false") {
    return (
      <div style={{
        flex: "1 1 240px", minWidth: 200, padding: "9px 12px",
        background: S_FUCHSIA_WASH, border: `1px solid ${S_FUCHSIA}33`,
        borderRadius: 8, fontSize: 12.5, color: S_FUCHSIA_DEEP, fontWeight: 700,
      }}>
        {op === "is true" ? "TRUE" : "FALSE"}
      </div>
    );
  }

  switch (field.type) {
    case "number":
    case "currency":
      return <NumberValueInput field={field} op={op} value={value} onChange={onChange} />;
    case "date":
      return <DateValueInput field={field} op={op} value={value} onChange={onChange} />;
    case "enum":
      return <EnumValueInput field={field} op={op} value={value} onChange={onChange} multi={false} />;
    case "multi-enum":
      return <EnumValueInput field={field} op={op} value={value} onChange={onChange} multi={true} />;
    case "semantic":
      return <SemanticValueInput field={field} op={op} value={value} onChange={onChange} />;
    case "string":
    default:
      return <StringValueInput field={field} op={op} value={value} onChange={onChange} />;
  }
}

function NumberValueInput({ field, op, value, onChange }) {
  if (op === "between") {
    const arr = Array.isArray(value) ? value : [0, 0];
    return (
      <div style={{ flex: "1 1 240px", display: "flex", gap: 6, alignItems: "center", minWidth: 200 }}>
        <NumInput value={arr[0]} onChange={v => onChange([v, arr[1]])} prefix={field.type === "currency" ? "€" : null} />
        <SMono size={10} color={S_FAINT}>and</SMono>
        <NumInput value={arr[1]} onChange={v => onChange([arr[0], v])} prefix={field.type === "currency" ? "€" : null} />
      </div>
    );
  }
  return (
    <div style={{ flex: "1 1 240px", minWidth: 200 }}>
      <NumInput value={value} onChange={onChange} prefix={field.type === "currency" ? "€" : null} />
    </div>
  );
}
function NumInput({ value, onChange, prefix }) {
  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 6,
      padding: "9px 12px", background: "#fff", border: `1px solid ${S_RULE}`,
      borderRadius: 8, flex: 1, minHeight: 38,
    }}>
      {prefix && <SMono size={12} color={S_FUCHSIA_DEEP} style={{ fontWeight: 700 }}>{prefix}</SMono>}
      <input
        type="number" value={value ?? ""}
        onChange={e => onChange(e.target.value === "" ? "" : Number(e.target.value))}
        style={{
          flex: 1, border: "none", outline: "none", background: "transparent",
          fontSize: 12.5, color: S_INK, fontWeight: 600,
          fontFamily: S_MONO,
        }}
      />
    </div>
  );
}

function DateValueInput({ field, op, value, onChange }) {
  if (op === "in the last X days" || op === "more than X days ago") {
    return (
      <div style={{ flex: "1 1 240px", display: "flex", alignItems: "center", gap: 8, minWidth: 200 }}>
        <NumInput value={value || 30} onChange={onChange} />
        <SMono size={11} color={S_DIM}>days</SMono>
      </div>
    );
  }
  if (op === "between") {
    const arr = Array.isArray(value) ? value : ["", ""];
    return (
      <div style={{ flex: "1 1 240px", display: "flex", gap: 6, alignItems: "center", minWidth: 200 }}>
        <DatePill v={arr[0] || "Pick start"} />
        <SMono size={10} color={S_FAINT}>and</SMono>
        <DatePill v={arr[1] || "Pick end"} />
      </div>
    );
  }
  return (
    <div style={{ flex: "1 1 240px", minWidth: 200 }}>
      <DatePill v={typeof value === "string" ? value : "Pick a date"} />
    </div>
  );
}
function DatePill({ v }) {
  return (
    <div style={{
      flex: 1, display: "flex", alignItems: "center", gap: 7,
      padding: "9px 12px", background: "#fff", border: `1px solid ${S_RULE}`,
      borderRadius: 8, minHeight: 38, cursor: "pointer",
    }}>
      <SIcon name="calendar" size={12} color={S_DIM} strokeWidth={1.9} />
      <span style={{ fontSize: 12.5, color: v.startsWith("Pick") ? S_FAINT : S_INK, fontWeight: 600 }}>{v}</span>
    </div>
  );
}

function StringValueInput({ field, op, value, onChange }) {
  return (
    <div style={{
      flex: "1 1 240px", minWidth: 200,
      display: "flex", alignItems: "center", gap: 7,
      padding: "9px 12px", background: "#fff", border: `1px solid ${S_RULE}`,
      borderRadius: 8, minHeight: 38,
    }}>
      <SIcon name="abc" size={13} color={S_DIM} strokeWidth={1.9} />
      <input value={value || ""} onChange={e => onChange(e.target.value)}
        placeholder="text value…"
        style={{
          flex: 1, border: "none", outline: "none", background: "transparent",
          fontSize: 12.5, color: S_INK, fontWeight: 600,
          fontFamily: "'Inter', sans-serif",
        }}
      />
    </div>
  );
}

function EnumValueInput({ field, op, value, onChange, multi }) {
  const [open, setOpen] = sUseState(false);
  const selected = multi ? (Array.isArray(value) ? value : []) : (value ? [value] : []);

  const toggle = (opt) => {
    if (multi) {
      if (selected.includes(opt)) onChange(selected.filter(s => s !== opt));
      else onChange([...selected, opt]);
    } else {
      onChange(opt);
      setOpen(false);
    }
  };

  return (
    <div style={{ position: "relative", flex: "1 1 240px", minWidth: 200 }}>
      <button onClick={() => setOpen(o => !o)} style={{
        ...pickerButton(open),
        background: "#fff",
        padding: selected.length ? "6px 10px" : "9px 12px",
      }}>
        <span style={{ display: "flex", flexWrap: "wrap", gap: 4, flex: 1, alignItems: "center" }}>
          {selected.length === 0 ? (
            <span style={{ fontSize: 12.5, color: S_FAINT, fontStyle: "italic" }}>select…</span>
          ) : selected.map(s => (
            <span key={s} style={{
              padding: "2px 8px 2px 9px", borderRadius: 4,
              background: S_FUCHSIA_WASH, color: S_FUCHSIA_DEEP,
              border: `1px solid ${S_FUCHSIA}33`,
              fontFamily: S_MONO, fontSize: 10, fontWeight: 700, letterSpacing: "0.04em",
              display: "inline-flex", alignItems: "center", gap: 5,
            }}>
              {s}
              {multi && (
                <SIcon name="close" size={9} color={S_FUCHSIA_DEEP} strokeWidth={2.4}
                  style={{ cursor: "pointer" }}
                  onClick={(e) => { e.stopPropagation(); toggle(s); }} />
              )}
            </span>
          ))}
        </span>
        <SIcon name="chevron" size={11} color={S_FAINT} strokeWidth={2}
          style={{ transform: open ? "rotate(180deg)" : "none", transition: "transform 0.15s" }} />
      </button>
      <Popover open={open} onClose={() => setOpen(false)} width={240}>
        <div style={{ padding: "6px 0" }}>
          {(field.options || []).map(opt => (
            <button key={opt} onClick={() => toggle(opt)} style={{
              display: "flex", alignItems: "center", gap: 8,
              padding: "7px 14px", border: "none",
              background: selected.includes(opt) ? S_FUCHSIA + "10" : "transparent",
              width: "100%", cursor: "pointer",
              fontSize: 12, color: S_INK, textAlign: "left",
              fontFamily: "'Inter', sans-serif",
            }}
              onMouseEnter={e => { if (!selected.includes(opt)) e.currentTarget.style.background = S_FUCHSIA + "06"; }}
              onMouseLeave={e => { if (!selected.includes(opt)) e.currentTarget.style.background = "transparent"; }}
            >
              <span style={{
                width: 14, height: 14, borderRadius: 3,
                border: `1.5px solid ${selected.includes(opt) ? S_FUCHSIA : S_RULE}`,
                background: selected.includes(opt) ? S_FUCHSIA : "#fff",
                display: "flex", alignItems: "center", justifyContent: "center",
                flexShrink: 0,
              }}>
                {selected.includes(opt) && <SIcon name="check" size={9} color="#fff" strokeWidth={2.8} />}
              </span>
              <span style={{ fontWeight: selected.includes(opt) ? 700 : 500 }}>{opt}</span>
            </button>
          ))}
        </div>
      </Popover>
    </div>
  );
}

function SemanticValueInput({ field, op, value, onChange }) {
  return (
    <div style={{
      flex: "1 1 240px", minWidth: 200,
      display: "flex", alignItems: "center", gap: 8,
      padding: "8px 12px",
      background: `linear-gradient(90deg, ${S_FUCHSIA_WASH} 0%, #fff 60%)`,
      border: `1px solid ${S_FUCHSIA}55`,
      borderRadius: 8, minHeight: 38, position: "relative",
    }}>
      <SIcon name="wand" size={13} color={S_FUCHSIA_DEEP} strokeWidth={1.9} />
      <input value={value || ""} onChange={e => onChange(e.target.value)}
        placeholder="describe semantically…"
        style={{
          flex: 1, border: "none", outline: "none", background: "transparent",
          fontSize: 12.5, color: S_INK, fontWeight: 600,
          fontFamily: "'Inter', sans-serif", fontStyle: value ? "italic" : "normal",
        }}
      />
      <SMono size={9} color={S_FUCHSIA_DEEP} style={{ letterSpacing: "0.16em", fontWeight: 700, whiteSpace: "nowrap" }}>VECTOR · 0.86</SMono>
    </div>
  );
}

// ────────────────────────── condition row + group ──────────────────────────
function ConditionRow({ cond, onChange, onDelete, showAnd }) {
  const field = S_FIELD_BY_ID[cond.field];
  // when field changes, reset op + value to sensible defaults
  const setField = (newId) => {
    const newField = S_FIELD_BY_ID[newId];
    const ops = S_OPERATORS[newField.type] || [];
    onChange({ ...cond, field: newId, op: ops[0], value: defaultValueFor(newField, ops[0]) });
  };
  const setOp = (op) => {
    onChange({ ...cond, op, value: defaultValueFor(field, op) });
  };
  const setVal = (v) => onChange({ ...cond, value: v });

  return (
    <div>
      {showAnd && (
        <div style={{ padding: "4px 0 6px 4px", fontFamily: S_MONO, fontSize: 9.5, color: S_FAINT, letterSpacing: "0.22em", fontWeight: 700 }}>
          AND
        </div>
      )}
      <div style={{
        display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap",
      }}>
        <FieldPicker value={cond.field} onChange={setField} />
        <OperatorPicker field={field} value={cond.op} onChange={setOp} />
        <ValueInput field={field} op={cond.op} value={cond.value} onChange={setVal} />
        <button onClick={onDelete} style={{
          width: 38, height: 38, borderRadius: 8,
          background: "#fff", border: `1px solid ${S_RULE}`,
          cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center",
          color: S_FAINT, flexShrink: 0,
        }}
          onMouseEnter={e => { e.currentTarget.style.color = S_FUCHSIA_DEEP; e.currentTarget.style.borderColor = S_FUCHSIA + "55"; }}
          onMouseLeave={e => { e.currentTarget.style.color = S_FAINT; e.currentTarget.style.borderColor = S_RULE; }}
        >
          <SIcon name="trash" size={13} color="currentColor" strokeWidth={1.9} />
        </button>
      </div>
    </div>
  );
}

function defaultValueFor(field, op) {
  if (!field || !op) return "";
  if (op.includes("is empty") || op.includes("is not empty")) return null;
  if (op === "is true" || op === "is false") return null;
  if (op === "between") return field.type === "date" ? ["", ""] : [0, 0];
  if (op === "in the last X days" || op === "more than X days ago") return 30;
  if (field.type === "multi-enum") return [];
  if (field.type === "enum") return field.options?.[0] || "";
  if (field.type === "number" || field.type === "currency") return 0;
  if (field.type === "bool") return null;
  return "";
}

function ConditionGroup({ group, idx, onChange, onDelete, deletable }) {
  const setMatch = (m) => onChange({ ...group, match: m });
  const setCond = (cid, nc) => onChange({ ...group, conditions: group.conditions.map(c => c.id === cid ? nc : c) });
  const delCond = (cid) => onChange({ ...group, conditions: group.conditions.filter(c => c.id !== cid) });
  const addCond = () => {
    const newC = { id: "c" + Date.now(), field: "lifetime_revenue", op: "greater than", value: 1000 };
    onChange({ ...group, conditions: [...group.conditions, newC] });
  };

  return (
    <div style={{
      background: "#fff", border: `1px solid ${S_RULE}`, borderRadius: 12,
      padding: "16px 18px", marginBottom: 12,
      position: "relative",
    }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 14 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
          <SIcon name="layers" size={14} color={S_FUCHSIA} strokeWidth={2} />
          <span style={{ fontSize: 13, color: S_INK, fontWeight: 700 }}>Group {idx + 1}</span>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <SMono size={10} color={S_FAINT} style={{ letterSpacing: "0.14em", fontWeight: 700 }}>MATCH</SMono>
          <div style={{
            display: "flex", padding: 3, background: "#efeadd",
            border: `1px solid ${S_RULE}`, borderRadius: 7,
          }}>
            {["ALL", "ANY"].map(m => (
              <button key={m} onClick={() => setMatch(m)} style={{
                padding: "4px 12px", border: "none", borderRadius: 5,
                background: group.match === m ? S_INK : "transparent",
                color: group.match === m ? "#fff" : S_DIM,
                fontFamily: S_MONO, fontSize: 10, fontWeight: 700, letterSpacing: "0.12em",
                cursor: "pointer",
              }}>{m}</button>
            ))}
          </div>
          {deletable && (
            <button onClick={onDelete} style={{
              width: 30, height: 30, borderRadius: 7,
              background: "transparent", border: `1px solid ${S_RULE}`,
              cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center",
              color: S_FAINT,
            }}>
              <SIcon name="trash" size={12} color="currentColor" strokeWidth={1.9} />
            </button>
          )}
        </div>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
        {group.conditions.map((c, ci) => (
          <ConditionRow key={c.id} cond={c}
            showAnd={ci > 0}
            onChange={(nc) => setCond(c.id, nc)}
            onDelete={() => delCond(c.id)}
          />
        ))}
      </div>

      <button onClick={addCond} style={{
        marginTop: 12, padding: "10px",
        background: "transparent", border: `1px dashed ${S_RULE}`,
        borderRadius: 8, width: "100%", cursor: "pointer",
        display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 7,
        fontSize: 12, color: S_DIM, fontWeight: 600,
        fontFamily: "'Inter', sans-serif",
      }}
        onMouseEnter={e => { e.currentTarget.style.borderColor = S_FUCHSIA + "AA"; e.currentTarget.style.color = S_FUCHSIA_DEEP; }}
        onMouseLeave={e => { e.currentTarget.style.borderColor = S_RULE; e.currentTarget.style.color = S_DIM; }}
      >
        <SIcon name="plus" size={12} color="currentColor" strokeWidth={2.2} />
        Add Condition
      </button>
    </div>
  );
}

// ────────────────────────── matching count tile (animated) ──────────────────────────
function MatchingTile({ count, total, dynamic }) {
  const pct = total ? Math.min(100, (count / total) * 100) : 0;
  return (
    <div style={{
      background: `linear-gradient(135deg, ${S_FUCHSIA} 0%, ${S_FUCHSIA_DEEP} 100%)`,
      borderRadius: 12, padding: "18px 22px 16px",
      color: "#fff", position: "relative", overflow: "hidden",
      boxShadow: `0 24px 40px -22px ${S_FUCHSIA}AA`,
    }}>
      <div style={{
        position: "absolute", right: -50, top: -50, width: 200, height: 200,
        borderRadius: "50%", background: "rgba(255,255,255,0.07)", filter: "blur(8px)",
      }} />
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 6 }}>
        <SMono size={10} color="rgba(255,255,255,0.85)" style={{ letterSpacing: "0.18em", fontWeight: 700 }}>
          MATCHING CONTACTS
        </SMono>
        {dynamic && (
          <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
            <SDot color="#fff" size={6} pulse />
            <SMono size={9} color="#fff" style={{ letterSpacing: "0.22em", fontWeight: 700 }}>LIVE</SMono>
          </span>
        )}
      </div>
      <div style={{
        display: "flex", alignItems: "baseline", gap: 10, marginBottom: 8,
      }}>
        <div key={count} style={{
          fontFamily: S_SERIF, fontSize: 44, fontWeight: 600, lineHeight: 1,
          letterSpacing: "-0.03em", fontVariantNumeric: "tabular-nums",
          animation: "gm-fadein 0.4s ease",
        }}>
          {count.toLocaleString("en-US")}
        </div>
        <SMono size={11} color="rgba(255,255,255,0.7)">/ {total.toLocaleString("en-US")} contacts</SMono>
      </div>
      <div style={{ height: 5, background: "rgba(255,255,255,0.15)", borderRadius: 3, overflow: "hidden" }}>
        <div style={{
          width: `${pct}%`, height: "100%",
          background: "linear-gradient(90deg, rgba(255,255,255,0.6), rgba(255,255,255,0.9))",
          borderRadius: 3, transition: "width 0.7s cubic-bezier(0.2,0.7,0.2,1)",
        }} />
      </div>
      <SMono size={10.5} color="rgba(255,255,255,0.85)" style={{ display: "block", marginTop: 8 }}>
        {pct.toFixed(2)}% of total · refreshing live
      </SMono>
    </div>
  );
}

// ────────────────────────── condition summary chip used as natural language ──────────────────────────
function summariseGroup(group) {
  const join = group.match === "ALL" ? " AND " : " OR ";
  return group.conditions.map(c => {
    const f = S_FIELD_BY_ID[c.field];
    if (!f) return "N/A";
    let v = c.value;
    if (Array.isArray(v)) v = v.join(", ");
    if (typeof v === "number" && f.type === "currency") v = "€" + v.toLocaleString();
    return `${f.label} ${c.op}${v != null ? " " + v : ""}`;
  }).join(join);
}

// ────────────────────────── preview table ──────────────────────────
function PreviewTable({ count }) {
  const rows = S_SAMPLE;
  return (
    <div style={{
      background: "#fff", border: `1px solid ${S_RULE}`, borderRadius: 12,
      overflow: "hidden",
    }}>
      <div style={{
        padding: "13px 18px",
        borderBottom: `1px solid ${S_RULE_S}`,
        display: "flex", alignItems: "center", gap: 10,
      }}>
        <SIcon name="users" size={14} color={S_INK} strokeWidth={1.9} />
        <span style={{ fontSize: 13, color: S_INK, fontWeight: 700 }}>Preview matching contacts</span>
        <span style={{
          padding: "2px 8px", borderRadius: 4,
          background: S_INK, color: "#fff",
          fontFamily: S_MONO, fontSize: 10, fontWeight: 700, letterSpacing: "0.06em",
        }}>{count.toLocaleString("en-US")}</span>
        <span style={{ flex: 1 }} />
        <SMono size={10.5} color={S_FAINT}>showing 12 of {count.toLocaleString("en-US")} · streaming sample</SMono>
      </div>
      <div style={{
        display: "grid",
        gridTemplateColumns: "1.4fr 1.1fr 1.6fr 0.6fr 1.3fr 0.9fr 0.7fr 0.7fr 30px",
        columnGap: 14, padding: "10px 18px",
        borderBottom: `1px solid ${S_RULE_S}`, background: S_PAPER,
        fontFamily: S_MONO, fontSize: 9, letterSpacing: "0.16em",
        fontWeight: 700, color: S_FAINT,
      }}>
        <span>NAME</span><span>PHONE</span><span>EMAIL</span><span>LANG</span>
        <span>HOTEL</span><span style={{ textAlign: "right" }}>LIFETIME €</span>
        <span style={{ textAlign: "right" }}>BK</span><span>TIER</span><span />
      </div>
      {rows.map((r, i) => (
        <div key={i} style={{
          display: "grid",
          gridTemplateColumns: "1.4fr 1.1fr 1.6fr 0.6fr 1.3fr 0.9fr 0.7fr 0.7fr 30px",
          columnGap: 14, padding: "12px 18px",
          borderBottom: i < rows.length - 1 ? `1px solid ${S_RULE_S}` : "none",
          alignItems: "center", fontSize: 12.5, color: S_INK,
        }}>
          <span style={{ fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{r.fn} {r.ln}</span>
          <SMono size={11} color={S_DIM} style={{ whiteSpace: "nowrap" }}>{r.phone}</SMono>
          <SMono size={11} color={S_DIM} style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{r.email}</SMono>
          <SMono size={11} color={S_FUCHSIA_DEEP} style={{ fontWeight: 700 }}>{r.lang}</SMono>
          <span style={{ fontSize: 12, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{r.hotel}</span>
          <SMono size={11} color={S_INK} style={{ fontWeight: 700, textAlign: "right", fontVariantNumeric: "tabular-nums" }}>
            €{r.spend.toLocaleString()}
          </SMono>
          <SMono size={11} color={S_INK} style={{ textAlign: "right" }}>{r.bookings}</SMono>
          <span style={{
            padding: "2px 8px", borderRadius: 999,
            background: r.tier === "Platinum" ? S_PLUM_DEEP : r.tier === "Gold" ? S_FUCHSIA_DEEP : S_PLUM,
            color: "#fff",
            fontFamily: S_MONO, fontSize: 9, fontWeight: 700, letterSpacing: "0.06em",
            textAlign: "center", whiteSpace: "nowrap",
          }}>{r.tier.toUpperCase()}</span>
          <button style={{
            width: 26, height: 26, borderRadius: 6,
            background: "transparent", border: "none",
            cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center",
          }}>
            <SIcon name="external" size={12} color={S_FUCHSIA} strokeWidth={2} />
          </button>
        </div>
      ))}
    </div>
  );
}

// ────────────────────────── main shell ──────────────────────────
// A rough "selectivity score" so editing conditions visibly changes the count.
function estimateCount(groups, total = 547329) {
  // Crude heuristic — each condition has an estimated selectivity 0.05..0.9.
  // Within a group, ALL = product, ANY = max. Groups combine as AND (product).
  const selFor = (c) => {
    const f = S_FIELD_BY_ID[c.field];
    if (!f) return 1;
    const op = c.op || "";
    let sel = 0.5;
    switch (f.type) {
      case "currency":
        if (op.includes("greater") || op === "≥") sel = c.value > 5000 ? 0.06 : c.value > 2000 ? 0.18 : 0.42;
        else if (op.includes("less") || op === "≤") sel = c.value > 5000 ? 0.94 : 0.6;
        else sel = 0.18;
        break;
      case "number":
        if (op.includes("greater") || op === "≥") sel = c.value > 5 ? 0.18 : c.value > 2 ? 0.35 : 0.55;
        else if (op.includes("less") || op === "≤") sel = 0.6;
        else sel = 0.3;
        break;
      case "date":
        if (op === "in the last X days") sel = c.value < 30 ? 0.18 : c.value < 90 ? 0.35 : 0.6;
        else if (op === "more than X days ago") sel = c.value > 365 ? 0.7 : 0.4;
        else sel = 0.4;
        break;
      case "bool":
        sel = op === "is true" ? 0.7 : 0.3; break;
      case "enum":
        sel = 1 / Math.max(2, (f.options || []).length); break;
      case "multi-enum": {
        const n = Array.isArray(c.value) ? c.value.length : 0;
        const total = (f.options || []).length || 5;
        sel = Math.min(0.9, (n / total) * (op.includes("all of") ? 0.5 : 1.4));
        if (n === 0) sel = 1;
        break;
      }
      case "semantic":
        sel = c.value && c.value.length > 4 ? 0.22 : 1; break;
      case "string":
        sel = c.value ? 0.3 : 1; break;
      default: sel = 0.5;
    }
    if (op.includes("does not") || op.includes("excludes") || op.includes("not")) sel = Math.min(1, 1 - sel + 0.1);
    return Math.max(0.01, Math.min(1, sel));
  };
  let groupSel = 1;
  for (const g of groups) {
    if (!g.conditions.length) continue;
    const sels = g.conditions.map(selFor);
    let s;
    if (g.match === "ALL") s = sels.reduce((a, b) => a * b, 1);
    else { // ANY = 1 - product(1 - s)
      s = 1 - sels.reduce((a, b) => a * (1 - b), 1);
    }
    groupSel *= s;
  }
  return Math.max(0, Math.round(total * groupSel));
}

function SegmentsSection() {
  const [name, setName] = sUseState("High-value cyclists & spa lovers · WhatsApp reachable");
  const [dynamic, setDynamic] = sUseState(true);
  const [groups, setGroups] = sUseState(DEFAULT_CONDITIONS);

  const TOTAL = 547329;
  const matching = sUseMemo(() => estimateCount(groups, TOTAL), [groups]);

  const updateGroup = (id, ng) => setGroups(gs => gs.map(g => g.id === id ? ng : g));
  const deleteGroup = (id) => setGroups(gs => gs.filter(g => g.id !== id));
  const addGroup = () => {
    setGroups(gs => [...gs, {
      id: "g" + Date.now(), match: "ALL",
      conditions: [{ id: "c" + Date.now(), field: "total_extras", op: "greater than", value: 250 }],
    }]);
  };

  return (
    <section data-screen-label="Advanced segmentation" style={{
      position: "relative",
      background: S_CREAM,
      color: S_INK,
      fontFamily: "'Inter', system-ui, sans-serif",
      padding: "80px clamp(20px,4vw,48px) 96px",
      overflow: "hidden",
    }}>
      <div style={{
        position: "absolute", top: -100, right: -200, width: 800, height: 600,
        background: `radial-gradient(ellipse, ${S_FUCHSIA}11 0%, transparent 60%)`,
        filter: "blur(50px)", pointerEvents: "none",
      }} />

      {/* section header */}
      <div style={{ maxWidth: "var(--rail)", margin: "0 auto 36px", textAlign: "center" }}>
        <div className="eyebrow" style={{ justifyContent: "center" }}>
          Built for campaigns, broadcasts and journeys
        </div>
        <h2 className="h-2" style={{ marginTop: 16 }}>
          Cohorts as deep as your data.{" "}
          <em className="italic-accent" style={{ display: "block" }}>
            From lifetime spend to semantic memory.
          </em>
        </h2>
        <p className="lead" style={{ maxWidth: 800, margin: "20px auto 0" }}>
          Combine identity, calculated booking metrics, folio extras, semantic memory search,
          reachability and consent in nested AND / OR groups. Operators adapt to each field's
          data type. Counts refresh live and feed your WhatsApp broadcasts, email campaigns
          and journeys in one click.
        </p>
      </div>

      {/* product frame */}
      <div style={{
        maxWidth: "var(--rail)", margin: "0 auto",
        borderRadius: 14, overflow: "hidden",
        background: S_PAPER, border: `1px solid ${S_RULE}`,
        boxShadow:
          "0 40px 80px -40px rgba(20,14,10,0.25), 0 8px 24px -16px rgba(20,14,10,0.12), 0 0 0 1px rgba(255,255,255,0.5) inset",
        position: "relative",
      }}>
        <STopBar />
        <div style={{ height: 1180, display: "flex", flexDirection: "column", background: S_CREAM, padding: "26px 32px 0", minHeight: 0 }}>
          {/* breadcrumb */}
          <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 12 }}>
            <SMono size={10.5} color={S_FAINT} style={{ letterSpacing: "0.12em", fontWeight: 600 }}>CRM</SMono>
            <SIcon name="chevron" size={11} color={S_FAINT} strokeWidth={2} style={{ transform: "rotate(-90deg)" }} />
            <SMono size={10.5} color={S_FAINT} style={{ letterSpacing: "0.12em", fontWeight: 600 }}>SEGMENTS</SMono>
            <SIcon name="chevron" size={11} color={S_FAINT} strokeWidth={2} style={{ transform: "rotate(-90deg)" }} />
            <SMono size={10.5} color={S_INK} style={{ letterSpacing: "0.12em", fontWeight: 700 }}>NEW</SMono>
          </div>

          {/* title row */}
          <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", marginBottom: 16 }}>
            <div>
              <h3 style={{
                fontFamily: S_SERIF, fontSize: 30, fontWeight: 600,
                color: S_INK, letterSpacing: "-0.022em", lineHeight: 1.05, margin: 0,
              }}>
                Create Segment
              </h3>
              <p style={{ fontSize: 13, color: S_DIM, margin: "6px 0 0" }}>
                Define rules to group contacts into targetable cohorts.
              </p>
            </div>
            <div style={{ display: "flex", gap: 8 }}>
              <button style={btnGhost()}>
                <SIcon name="play" size={11} color={S_INK} strokeWidth={2} />
                Test run
              </button>
              <button style={btnGhost()}>Cancel</button>
              <button style={btnPrimary()}>
                <SIcon name="save" size={12} color="#fff" strokeWidth={2.2} />
                Create Segment
              </button>
            </div>
          </div>

          {/* scrollable body */}
          <div className="gm-scroll" style={{
            flex: 1, minHeight: 0, overflowY: "auto",
            paddingRight: 6, marginRight: -6, paddingBottom: 30,
          }}>
            {/* Segment details */}
            <div style={{
              background: "#fff", border: `1px solid ${S_RULE}`, borderRadius: 12,
              padding: "16px 18px", marginBottom: 16,
              display: "grid", gridTemplateColumns: "1.6fr 1fr", gap: 22, alignItems: "start",
            }}>
              <div>
                <SMono size={9.5} color={S_FAINT} style={{ letterSpacing: "0.16em", fontWeight: 700, display: "block", marginBottom: 6 }}>NAME *</SMono>
                <input value={name} onChange={e => setName(e.target.value)} style={{
                  width: "100%", padding: "10px 12px",
                  background: S_PAPER, border: `1px solid ${S_RULE}`, borderRadius: 8,
                  fontSize: 13.5, color: S_INK, fontWeight: 600,
                  fontFamily: "'Inter', sans-serif", outline: "none",
                }} />
                <SMono size={10} color={S_FAINT} style={{ display: "block", marginTop: 6 }}>
                  Tip: name your segment in the same shape your campaigns will use, e.g. "WhatsApp · Returning VIPs · DE".
                </SMono>
              </div>
              <div style={{
                background: dynamic ? S_FUCHSIA_WASH : S_PAPER,
                border: `1px solid ${dynamic ? S_FUCHSIA + "55" : S_RULE}`,
                borderRadius: 10, padding: "10px 14px",
                display: "flex", alignItems: "center", gap: 12,
              }}>
                <SIcon name="spark" size={15} color={S_FUCHSIA} strokeWidth={2} />
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 13, color: S_INK, fontWeight: 700 }}>Dynamic Segment</div>
                  <SMono size={10.5} color={S_DIM}>Recomputes live as memories, stays and signals change.</SMono>
                </div>
                <button onClick={() => setDynamic(d => !d)} style={toggleBtn(dynamic)}>
                  <span style={toggleHandle(dynamic)} />
                </button>
              </div>
            </div>

            {/* conditions header */}
            <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 10 }}>
              <SIcon name="filter" size={14} color={S_INK} strokeWidth={2} />
              <span style={{ fontSize: 13.5, color: S_INK, fontWeight: 700 }}>Conditions</span>
              <SMono size={11} color={S_DIM}>Build groups for nested AND / OR logic. Operators adapt to each field's data type.</SMono>
            </div>

            {/* groups */}
            {groups.map((g, gi) => (
              <div key={g.id}>
                {gi > 0 && (
                  <div style={{
                    display: "flex", alignItems: "center", gap: 10,
                    margin: "6px 18px 8px",
                  }}>
                    <span style={{ flex: 1, height: 1, background: S_RULE_S }} />
                    <SMono size={10} color={S_FUCHSIA_DEEP} style={{ letterSpacing: "0.22em", fontWeight: 700 }}>AND</SMono>
                    <span style={{ flex: 1, height: 1, background: S_RULE_S }} />
                  </div>
                )}
                <ConditionGroup
                  group={g} idx={gi}
                  onChange={(ng) => updateGroup(g.id, ng)}
                  onDelete={() => deleteGroup(g.id)}
                  deletable={groups.length > 1}
                />
              </div>
            ))}

            <button onClick={addGroup} style={{
              padding: "12px",
              background: "#fff", border: `1px dashed ${S_FUCHSIA}66`,
              borderRadius: 10, width: "100%", cursor: "pointer",
              display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8,
              fontSize: 12.5, color: S_FUCHSIA_DEEP, fontWeight: 700,
              fontFamily: "'Inter', sans-serif", marginBottom: 18,
            }}
              onMouseEnter={e => { e.currentTarget.style.background = S_FUCHSIA_WASH; }}
              onMouseLeave={e => { e.currentTarget.style.background = "#fff"; }}
            >
              <SIcon name="plus" size={13} color={S_FUCHSIA_DEEP} strokeWidth={2.4} />
              Add Condition Group
            </button>

            {/* matching tile + summary */}
            <div style={{ display: "grid", gridTemplateColumns: "1.1fr 1fr", gap: 14, marginBottom: 18 }}>
              <MatchingTile count={matching} total={TOTAL} dynamic={dynamic} />
              <div style={{
                background: "#fff", border: `1px solid ${S_RULE}`, borderRadius: 12,
                padding: "16px 18px",
                display: "flex", flexDirection: "column", gap: 8,
              }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  <SIcon name="layers" size={13} color={S_FUCHSIA} strokeWidth={2} />
                  <SEyebrow color={S_DIM} style={{ fontSize: 10 }}>Natural-language summary</SEyebrow>
                </div>
                <div style={{
                  fontFamily: S_SERIF, fontSize: 13, color: S_INK, lineHeight: 1.5,
                  letterSpacing: "-0.005em",
                }}>
                  Contacts where {groups.map((g, i) => (
                    <span key={g.id}>
                      {i > 0 && <strong style={{ color: S_FUCHSIA_DEEP }}> AND </strong>}
                      <span style={{ color: S_DIM }}>(</span>
                      <em>{summariseGroup(g)}</em>
                      <span style={{ color: S_DIM }}>)</span>
                    </span>
                  ))}
                </div>
                <div style={{ display: "flex", gap: 6, marginTop: 4, flexWrap: "wrap" }}>
                  {[
                    { lbl: "Use in WhatsApp", icon: "send" },
                    { lbl: "Use in Email Campaign", icon: "mail" },
                    { lbl: "Use in Journey", icon: "layers" },
                  ].map((b, i) => (
                    <button key={i} style={{
                      display: "inline-flex", alignItems: "center", gap: 6,
                      padding: "6px 10px", borderRadius: 7,
                      background: S_FUCHSIA_WASH, color: S_FUCHSIA_DEEP,
                      border: `1px solid ${S_FUCHSIA}33`,
                      fontSize: 11, fontWeight: 700, cursor: "pointer",
                      fontFamily: "'Inter', sans-serif",
                    }}>
                      <SIcon name={b.icon} size={11} color={S_FUCHSIA_DEEP} strokeWidth={2} />
                      {b.lbl}
                    </button>
                  ))}
                </div>
              </div>
            </div>

            <PreviewTable count={matching} />
          </div>
        </div>
      </div>
    </section>
  );
}

// shared button styles
function btnGhost() {
  return {
    display: "inline-flex", alignItems: "center", gap: 6,
    padding: "8px 12px", borderRadius: 7,
    background: "#fff", border: `1px solid ${S_RULE}`,
    fontSize: 12, color: S_INK, fontWeight: 600, cursor: "pointer",
    fontFamily: "'Inter', sans-serif",
  };
}
function btnPrimary() {
  return {
    display: "inline-flex", alignItems: "center", gap: 6,
    padding: "8px 14px", borderRadius: 7,
    background: S_INK, color: "#fff", border: "none",
    fontSize: 12, fontWeight: 700, cursor: "pointer",
    fontFamily: "'Inter', sans-serif",
  };
}
function toggleBtn(on) {
  return {
    width: 38, height: 22, borderRadius: 999,
    background: on ? S_FUCHSIA : "#cfc4c4",
    border: "none", padding: 0, position: "relative", cursor: "pointer",
    transition: "background 0.2s",
  };
}
function toggleHandle(on) {
  return {
    position: "absolute", top: 2, left: on ? 18 : 2,
    width: 18, height: 18, borderRadius: "50%", background: "#fff",
    boxShadow: "0 1px 3px rgba(0,0,0,0.18)", transition: "left 0.2s",
  };
}

window.SegmentsSection = SegmentsSection;
