/* =========================================================================
   Veto · UI primitives (shadcn ports) + icon set + tooltip
   ========================================================================= */
const { useState: useStateUI, useRef: useRefUI, useEffect: useEffectUI } = React;

/* --------------------------------------------------------------- Button */
const BTN_BASE =
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0";
const BTN_VARIANT = {
  default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
  destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
  outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
  secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
  ghost: "hover:bg-accent hover:text-accent-foreground",
  link: "text-primary underline-offset-4 hover:underline",
};
const BTN_SIZE = { default: "h-9 px-4 py-2", sm: "h-8 rounded-md px-3 text-xs", lg: "h-10 rounded-md px-8", icon: "h-9 w-9" };
function buttonVariants({ variant = "default", size = "default", className } = {}) {
  return cn(BTN_BASE, BTN_VARIANT[variant], BTN_SIZE[size], className);
}
function Button({ className, variant, size, ...props }) {
  return <button className={buttonVariants({ variant, size, className })} {...props} />;
}

/* --------------------------------------------------------------- Badge */
const BADGE_BASE =
  "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none";
const BADGE_VARIANT = {
  default: "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
  secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
  destructive: "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
  outline: "text-foreground",
};
function Badge({ className, variant = "default", ...props }) {
  return <div className={cn(BADGE_BASE, BADGE_VARIANT[variant], className)} {...props} />;
}

/* --------------------------------------------------------------- Card */
function Card({ className, ...p }) { return <div className={cn("rounded-xl border border-line bg-card text-card-foreground shadow-sm", className)} {...p} />; }
function CardHeader({ className, ...p }) { return <div className={cn("flex flex-col space-y-1.5 p-6", className)} {...p} />; }
function CardTitle({ className, ...p }) { return <div className={cn("font-semibold leading-none tracking-tight", className)} {...p} />; }
function CardDescription({ className, ...p }) { return <div className={cn("text-sm text-muted-foreground", className)} {...p} />; }
function CardContent({ className, ...p }) { return <div className={cn("p-6 pt-0", className)} {...p} />; }
function CardFooter({ className, ...p }) { return <div className={cn("flex items-center p-6 pt-0", className)} {...p} />; }

/* ----------------------------------------------------------- Separator */
function Separator({ className, orientation = "horizontal", ...p }) {
  return <div className={cn("shrink-0 bg-border", orientation === "horizontal" ? "h-px w-full" : "h-full w-px", className)} {...p} />;
}

/* ------------------------------------------------------------- Tooltip */
/* Mercury-style hover tooltip: dark rounded pill with a caret pointer,
   blown-up keycaps for the shortcut, a short open-delay so it doesn't flash.
   After one tooltip shows, adjacent ones open instantly (shared grace window),
   so sweeping the nav rail feels immediate instead of re-waiting each time. */
let hintSkipUntil = 0;
function Hint({ label, shortcut, side = "right", delay = 120, children }) {
  const [open, setOpen] = useStateUI(false);
  const timer = useRefUI(null);
  const show = () => {
    clearTimeout(timer.current);
    if (Date.now() < hintSkipUntil) { setOpen(true); hintSkipUntil = Date.now() + 400; return; }
    timer.current = setTimeout(() => { setOpen(true); hintSkipUntil = Date.now() + 400; }, delay);
  };
  const hide = () => { clearTimeout(timer.current); setOpen(false); };
  useEffectUI(() => () => clearTimeout(timer.current), []);

  // Bubble position relative to the trigger.
  const pos = side === "right" ? "left-full top-1/2 -translate-y-1/2 ml-2.5"
            : side === "top" ? "bottom-full left-1/2 -translate-x-1/2 mb-2.5"
            : side === "bottom" ? "top-full left-1/2 -translate-x-1/2 mt-2.5"
            : "right-full top-1/2 -translate-y-1/2 mr-2.5";
  // Caret sits on the edge facing the trigger.
  const caret = side === "right" ? "left-[-3px] top-1/2 -translate-y-1/2"
            : side === "left" ? "right-[-3px] top-1/2 -translate-y-1/2"
            : side === "top" ? "bottom-[-3px] left-1/2 -translate-x-1/2"
            : "top-[-3px] left-1/2 -translate-x-1/2";
  const origin = side === "right" ? "left center" : side === "left" ? "right center"
            : side === "top" ? "center bottom" : "center top";
  const keys = shortcut ? String(shortcut).trim().split(/\s+/) : [];

  return (
    <span className="relative inline-flex"
      onMouseEnter={show} onMouseLeave={hide} onFocus={show} onBlur={hide}>
      {children}
      {open && label && (
        <span className={cn("pointer-events-none absolute z-50", pos)}>
          <span role="tooltip"
            className="relative flex items-center gap-2 whitespace-nowrap rounded-lg bg-ink px-2.5 py-1.5 text-[12.5px] font-medium leading-none text-background shadow-[0_6px_20px_-6px_rgba(0,0,0,0.45)]"
            style={{ animation: "hintIn .13s cubic-bezier(0.16,1,0.3,1)", transformOrigin: origin }}>
            <span aria-hidden className={cn("absolute h-[7px] w-[7px] rotate-45 rounded-[1.5px] bg-ink", caret)} />
            <span>{label}</span>
            {keys.length > 0 && (
              <span className="flex items-center gap-1">
                {keys.map((k, i) => (
                  <kbd key={i} className="inline-flex h-[19px] min-w-[19px] items-center justify-center rounded-[5px] bg-background/15 px-1.5 font-mono text-[11px] font-semibold text-background/90">{k}</kbd>
                ))}
              </span>
            )}
          </span>
        </span>
      )}
    </span>
  );
}

/* --------------------------------------------------------------- Icons */
/* Minimal lucide-react port: <Icon name="x" /> renders stroked paths.   */
const ICON_PATHS = {
  plus: '<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>',
  x: '<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>',
  check: '<polyline points="20 6 9 17 4 12"/>',
  "chevron-right": '<polyline points="9 18 15 12 9 6"/>',
  "chevron-left": '<polyline points="15 18 9 12 15 6"/>',
  "chevron-down": '<polyline points="6 9 12 15 18 9"/>',
  "arrow-right": '<line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/>',
  "arrow-up": '<line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/>',
  "arrow-left": '<line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/>',
  search: '<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>',
  settings: '<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>',
  inbox: '<polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/>',
  bookmark: '<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>',
  clock: '<circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/>',
  calendar: '<rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/>',
  "alert-triangle": '<path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>',
  "check-circle": '<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>',
  circle: '<circle cx="12" cy="12" r="10"/>',
  dot: '<circle cx="12" cy="12" r="3" fill="currentColor"/>',
  file: '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/>',
  "file-text": '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><line x1="10" y1="9" x2="8" y2="9"/>',
  "file-plus": '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="12" x2="12" y2="18"/><line x1="9" y1="15" x2="15" y2="15"/>',
  lock: '<rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
  user: '<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>',
  users: '<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.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
  "external-link": '<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/>',
  "more-horizontal": '<circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/>',
  paperclip: '<path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/>',
  download: '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>',
  printer: '<polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="8"/>',
  phone: '<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/>',
  mail: '<rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-10 5L2 7"/>',
  shield: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>',
  "rotate-ccw": '<polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/>',
  eye: '<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/>',
  link: '<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>',
  minus: '<line x1="5" y1="12" x2="19" y2="12"/>',
  "corner-down-right": '<polyline points="15 10 20 15 15 20"/><path d="M4 4v7a4 4 0 0 0 4 4h12"/>',
  command: '<path d="M18 3a3 3 0 0 0-3 3v12a3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3H6a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3V6a3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3h12a3 3 0 0 0 3-3 3 3 0 0 0-3-3z"/>',
  home: '<path d="M3 9.5 12 3l9 6.5"/><path d="M5 10v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V10"/>',
  "arrow-up-right": '<line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/>',
  "arrow-down-left": '<line x1="17" y1="7" x2="7" y2="17"/><polyline points="17 17 7 17 7 7"/>',
  scale: '<path d="M12 3v18"/><path d="M5 7h14"/><path d="m5 7-3 6a3 3 0 0 0 6 0z"/><path d="m19 7-3 6a3 3 0 0 0 6 0z"/><path d="M7 21h10"/>',
  "book-open": '<path d="M2 4h7a3 3 0 0 1 3 3v13a2.5 2.5 0 0 0-2.5-2.5H2z"/><path d="M22 4h-7a3 3 0 0 0-3 3v13a2.5 2.5 0 0 1 2.5-2.5H22z"/>',
  "life-buoy": '<circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="3.5"/><line x1="4.9" y1="4.9" x2="9.5" y2="9.5"/><line x1="14.5" y1="14.5" x2="19.1" y2="19.1"/><line x1="14.5" y1="9.5" x2="19.1" y2="4.9"/><line x1="4.9" y1="19.1" x2="9.5" y2="14.5"/>',
  beaker: '<path d="M9 3h6"/><path d="M10 3v6.5L5 18a2 2 0 0 0 1.8 3h10.4A2 2 0 0 0 19 18l-5-8.5V3"/><line x1="7" y1="14" x2="17" y2="14"/>',
  sparkles: '<path d="M12 3l1.6 4.4L18 9l-4.4 1.6L12 15l-1.6-4.4L6 9l4.4-1.6z"/><path d="M19 14l.7 1.9L21.5 16l-1.8.7L19 18.5l-.7-1.8L16.5 16l1.8-.7z"/>',
  "log-out": '<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/>',
  "message-circle": '<path d="M21 11.5a8.38 8.38 0 0 1-9 8.5 8.5 8.5 0 0 1-3.8-.9L3 21l1.9-5.2A8.5 8.5 0 0 1 12 3a8.38 8.38 0 0 1 9 8.5z"/>',
  "corner-up-left": '<polyline points="9 14 4 9 9 4"/><path d="M20 20v-7a4 4 0 0 0-4-4H4"/>',
  "shield-check": '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/>',
  building: '<rect x="4" y="3" width="16" height="18" rx="1.5"/><line x1="9" y1="7" x2="9" y2="7"/><line x1="15" y1="7" x2="15" y2="7"/><line x1="9" y1="11" x2="9" y2="11"/><line x1="15" y1="11" x2="15" y2="11"/><path d="M9 21v-4h6v4"/>',
  gauge: '<path d="M12 13l4-3.5"/><path d="M3.5 16a9 9 0 1 1 17 0"/>',
  landmark: '<line x1="3" y1="22" x2="21" y2="22"/><line x1="6" y1="18" x2="6" y2="11"/><line x1="10" y1="18" x2="10" y2="11"/><line x1="14" y1="18" x2="14" y2="11"/><line x1="18" y1="18" x2="18" y2="11"/><polygon points="12 2 20 7 4 7"/>',
  "upload-cloud": '<path d="M16 16l-4-4-4 4"/><path d="M12 12v9"/><path d="M20.4 14.9A5 5 0 0 0 18 6h-1.3A8 8 0 1 0 4 15.2"/>',
  "trending-up": '<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/>',
  table: '<rect x="3" y="3" width="18" height="18" rx="2"/><line x1="3" y1="9.5" x2="21" y2="9.5"/><line x1="3" y1="15" x2="21" y2="15"/><line x1="9" y1="3" x2="9" y2="21"/>',
  "alert-circle": '<circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/>',
  banknote: '<rect x="2" y="6" width="20" height="12" rx="2"/><circle cx="12" cy="12" r="2.5"/>',
  "map-pin": '<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/>',
  calendar2: '<rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/>',
  bell: '<path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.7 21a2 2 0 0 1-3.4 0"/>',
  "panel-left": '<rect x="3" y="4" width="18" height="16" rx="2"/><line x1="9" y1="4" x2="9" y2="20"/><polyline points="14 9 12 12 14 15"/>',
  "panel-right": '<rect x="3" y="4" width="18" height="16" rx="2"/><line x1="9" y1="4" x2="9" y2="20"/><polyline points="13 9 15 12 13 15"/>',
};
/* Custom raster icon set (line-art PNGs, normalized to clean alpha masks in
   assets/icons/tinted/). Rendered via CSS mask with background:currentColor so
   they tint to the surrounding text color and keep the same active/inactive
   (ink / ink-soft) theming as the inline SVG icons. */
const IMAGE_ICONS = {
  home: "assets/icons/tinted/home.png",
  search: "assets/icons/tinted/search-clear.png",
  settings: "assets/icons/tinted/settings.png",
  bell: "assets/icons/tinted/notifications.png",
  files: "assets/icons/tinted/files.png",
  tasks: "assets/icons/tinted/tasks.png",
  receipt: "assets/icons/tinted/receipt.png",
  manifest: "assets/icons/tinted/manifest.png",
  gauge: "assets/icons/tinted/gauge.png",
  "panel-left": "assets/icons/tinted/sidebar-collapse.png",
  "panel-right": "assets/icons/tinted/sidebar-expand.png",
  // Money lines + intake/exception
  "buyer-funding": "assets/icons/tinted/buyer-funding.png",
  "seller-proceeds": "assets/icons/tinted/seller-proceeds.png",
  "payoff-demand": "assets/icons/tinted/payoff-demand.png",
  "trust-account": "assets/icons/tinted/trust-account.png",
  "new-file": "assets/icons/tinted/new-file.png",
  hold: "assets/icons/tinted/hold.png",
};
function Icon({ name, size = 16, strokeWidth = 1.6, className, style, ...rest }) {
  const src = IMAGE_ICONS[name];
  if (src) {
    return (
      <span aria-hidden="true" className={className}
        style={{
          display: "inline-block", width: size, height: size, flexShrink: 0,
          backgroundColor: "currentColor",
          WebkitMaskImage: `url(${src})`, maskImage: `url(${src})`,
          WebkitMaskRepeat: "no-repeat", maskRepeat: "no-repeat",
          WebkitMaskPosition: "center", maskPosition: "center",
          WebkitMaskSize: "contain", maskSize: "contain",
          ...style,
        }} {...rest} />
    );
  }
  const d = ICON_PATHS[name] || ICON_PATHS.circle;
  return (
    <svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24"
      fill="none" stroke="currentColor" strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round"
      className={className} aria-hidden="true" {...rest}
      dangerouslySetInnerHTML={{ __html: d }} />
  );
}

/* ------------------------------------------------------------ VetoLogo */
function VetoLogo({ className, title = "Veto" }) {
  return (
    <span role="img" aria-label={title}
      className={cn("inline-flex items-center font-semibold tracking-[-0.03em] text-ink", className)}
      style={{ fontFeatureSettings: '"ss01"' }}>
      veto
    </span>
  );
}

/* ----------------------------------------------------------- EmptyState */
function EmptyState({ icon, artifact, title, note, action, secondaryAction }) {
  return (
    <div className="flex flex-col items-center justify-center px-6 py-16 text-center">
      {artifact ? (
        <div className="relative mb-7 w-full max-w-[280px]">
          <div className="pointer-events-none select-none overflow-hidden rounded-xl border border-line bg-background text-left shadow-[0_2px_24px_-12px_rgba(0,0,0,0.18)]">{artifact}</div>
          <div aria-hidden className="pointer-events-none absolute inset-x-0 bottom-0 h-2/3 rounded-b-xl"
            style={{ background: "linear-gradient(180deg, rgba(255,255,255,0) 0%, var(--background) 92%)" }} />
        </div>
      ) : icon ? (
        <div className="mb-6 grid h-16 w-16 place-items-center rounded-2xl border border-line bg-surface/70 text-ink-soft">{icon}</div>
      ) : null}
      <h3 className="text-[18px] font-semibold tracking-[-0.01em] text-ink">{title}</h3>
      {note && <p className="mt-2 max-w-[340px] text-[13px] leading-relaxed text-ink-soft">{note}</p>}
      {(action || secondaryAction) && <div className="mt-6 flex items-center gap-5">{action}{secondaryAction}</div>}
    </div>
  );
}

/* A faded "file row" artifact for empty states (Veto's row grammar). */
function FilesArtifact() {
  const rows = [
    { a: "1428 Donlyn Dr", n: "PD-0214" },
    { a: "82 Cresta Vista", n: "SP-0208" },
    { a: "316 Harbor Light", n: "BF-0190" },
  ];
  return (
    <div className="flex flex-col divide-y divide-line">
      {rows.map((r) => (
        <div key={r.n} className="flex items-center gap-3 px-4 py-3.5">
          <span className="grid h-7 w-7 shrink-0 place-items-center rounded-full bg-surface-2 text-[10px] font-medium text-ink-soft">ML</span>
          <span className="min-w-0 flex-1">
            <span className="block truncate text-[12px] text-ink">{r.a}</span>
            <span className="block font-mono text-[10px] text-muted-foreground">{r.n}</span>
          </span>
          <span className="h-1.5 w-1.5 rounded-full bg-[var(--ok)]/50" />
        </div>
      ))}
    </div>
  );
}

/* Faded skeleton rows — Mercury "no completed tasks" grammar. Generic. */
function RowsSkeleton({ rows = 4, lead = "circle", meta = true }) {
  return (
    <div className="flex flex-col divide-y divide-line">
      {Array.from({ length: rows }).map((_, i) => (
        <div key={i} className="flex items-center gap-3 px-4 py-3.5">
          <span className={cn("h-7 w-7 shrink-0 bg-surface-2", lead === "circle" ? "rounded-full" : "rounded-md")} />
          <span className="h-2.5 flex-1 rounded-full bg-surface-2" style={{ maxWidth: `${72 - i * 7}%` }} />
          {meta && <span className="h-2.5 w-9 shrink-0 rounded-full bg-surface-2" />}
        </div>
      ))}
    </div>
  );
}

/* Faded receipt/record card — Acctual sample-invoice grammar. */
function ReceiptArtifact() {
  const rows = [["Amount", "w-16"], ["Destination", "w-20"], ["Callback", "w-14"], ["Office action", "w-10"]];
  return (
    <div className="p-4">
      <div className="flex items-center justify-between">
        <span className="text-[9px] uppercase tracking-[0.08em] text-muted-foreground">File Review Record</span>
        <span className="font-mono text-[9px] text-muted-foreground">v1</span>
      </div>
      <div className="mt-3 space-y-2.5">
        {rows.map(([l, w], i) => (
          <div key={i} className="flex items-center justify-between">
            <span className="text-[10px] text-ink-soft">{l}</span>
            <span className={cn("h-2 rounded-full bg-surface-2", w)} />
          </div>
        ))}
      </div>
      <div className="mt-3.5 flex items-center justify-between border-t border-line pt-2.5">
        <span className="text-[9px] text-muted-foreground">Signed</span>
        <span className="h-2 w-14 rounded-full bg-surface-2" />
      </div>
    </div>
  );
}

/* Subtle "Learn more" secondary action — opens the help launcher. */
function LearnMore({ label = "Learn more" }) {
  return (
    <button type="button" onClick={() => window.dispatchEvent(new CustomEvent("veto:help"))}
      className="rounded-sm text-[12.5px] text-ink-soft underline decoration-line underline-offset-4 outline-none transition hover:text-ink">{label}</button>
  );
}

/* Address / office typeahead — custom dropdown (not native datalist).
   places=true renders Google-Maps-style rows: pin, street line + locality. */
function Autocomplete({ value, onChange, placeholder, options, icon, autoFocus, places }) {
  const [open, setOpen] = useStateUI(false);
  const [hi, setHi] = useStateUI(0);
  const t = (value || "").toLowerCase();
  const matches = (options || []).filter((o) => o.toLowerCase().includes(t)).slice(0, 6);
  const show = open && value && matches.length > 0;
  const leadIcon = icon || (places ? "map-pin" : "search");
  useEffectUI(() => { setHi(0); }, [value]);
  return (
    <div className="relative">
      <div className="relative">
        <Icon name={leadIcon} size={15} className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-ink-soft" />
        <input value={value} onChange={(e) => { onChange(e.target.value); setOpen(true); }} onFocus={() => setOpen(true)} onBlur={() => setTimeout(() => setOpen(false), 120)}
          onKeyDown={(e) => {
            if (!show) return;
            if (e.key === "ArrowDown") { e.preventDefault(); setHi((i) => Math.min(i + 1, matches.length - 1)); }
            else if (e.key === "ArrowUp") { e.preventDefault(); setHi((i) => Math.max(i - 1, 0)); }
            else if (e.key === "Enter") { e.preventDefault(); onChange(matches[hi]); setOpen(false); }
          }}
          placeholder={placeholder} autoFocus={autoFocus} autoComplete="off"
          className="h-11 w-full rounded-lg border border-line bg-background pl-9 pr-3 text-[14px] text-ink outline-none transition placeholder:text-muted-foreground focus:border-ink/40 focus:ring-1 focus:ring-ink/15" />
      </div>
      {show && (
        <div className="absolute z-50 mt-1 w-full overflow-hidden rounded-xl border border-line bg-background shadow-[0_12px_32px_-12px_rgba(0,0,0,0.25)]">
          <ul className="py-1">
            {matches.map((o, idx) => {
              const ci = o.indexOf(",");
              const primary = places && ci > 0 ? o.slice(0, ci) : o;
              const secondary = places && ci > 0 ? o.slice(ci + 1).trim() : null;
              return (
                <li key={o}>
                  <button type="button" onMouseEnter={() => setHi(idx)} onMouseDown={(e) => { e.preventDefault(); onChange(o); setOpen(false); }}
                    className={cn("flex w-full items-center gap-3 px-3 py-2 text-left transition", idx === hi ? "bg-surface" : "hover:bg-surface/60")}>
                    <Icon name={leadIcon} size={15} className="shrink-0 text-ink-soft" />
                    <span className="min-w-0 flex-1">
                      <span className="block truncate text-[13px] text-ink">{primary}</span>
                      {secondary && <span className="block truncate text-[11.5px] text-ink-soft">{secondary}</span>}
                    </span>
                  </button>
                </li>
              );
            })}
          </ul>
          {places && (
            <div className="flex items-center justify-end gap-1 border-t border-line px-3 py-1.5 text-[10px] text-muted-foreground">
              powered by <span className="font-medium tracking-tight text-ink-soft">Google</span>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

/* Custom calendar date picker (value is ISO yyyy-mm-dd). No native control. */
const DOW = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
const MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
function parseISO(v) {
  if (!v) return null;
  const [y, m, d] = v.split("-").map(Number);
  if (!y || !m || !d) return null;
  return new Date(y, m - 1, d);
}
function toISO(dt) {
  return `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, "0")}-${String(dt.getDate()).padStart(2, "0")}`;
}
function fmtNice(dt) {
  return `${MONTHS[dt.getMonth()].slice(0, 3)} ${dt.getDate()}, ${dt.getFullYear()}`;
}
function DateField({ value, onChange, autoFocus, placeholder = "Select a date" }) {
  const [open, setOpen] = useStateUI(false);
  const selected = parseISO(value);
  const today = new Date(); today.setHours(0, 0, 0, 0);
  const [view, setView] = useStateUI(() => { const b = selected || today; return { y: b.getFullYear(), m: b.getMonth() }; });
  const wrapRef = useRefUI(null);

  useEffectUI(() => {
    if (!open) return;
    const onDoc = (e) => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [open]);

  const first = new Date(view.y, view.m, 1);
  const startPad = first.getDay();
  const daysInMonth = new Date(view.y, view.m + 1, 0).getDate();
  const cells = [];
  for (let i = 0; i < startPad; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(view.y, view.m, d));
  const sameDay = (a, b) => a && b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
  const stepMonth = (n) => setView((v) => { const dt = new Date(v.y, v.m + n, 1); return { y: dt.getFullYear(), m: dt.getMonth() }; });

  return (
    <div className="relative" ref={wrapRef}>
      <button type="button" autoFocus={autoFocus} onClick={() => setOpen((o) => !o)}
        className={cn("flex h-11 w-full items-center gap-2.5 rounded-lg border bg-background px-3.5 text-left text-[14px] outline-none transition focus:ring-1 focus:ring-ink/15",
          open ? "border-ink/40" : "border-line hover:border-ink/25")}>
        <Icon name="calendar2" size={15} className="shrink-0 text-ink-soft" />
        <span className={cn("flex-1", selected ? "text-ink" : "text-muted-foreground")}>{selected ? fmtNice(selected) : placeholder}</span>
        <Icon name="chevron-down" size={15} className={cn("shrink-0 text-ink-soft transition-transform", open && "rotate-180")} />
      </button>
      {open && (
        <div className="absolute z-50 mt-1.5 w-[296px] rounded-xl border border-line bg-background p-3 shadow-[0_16px_44px_-16px_rgba(0,0,0,0.28)]">
          <div className="mb-2 flex items-center justify-between px-1">
            <button type="button" onClick={() => stepMonth(-1)} aria-label="Previous month" className="grid h-7 w-7 place-items-center rounded-md text-ink-soft transition hover:bg-surface hover:text-ink"><Icon name="chevron-left" size={16} /></button>
            <div className="text-[13px] font-medium text-ink">{MONTHS[view.m]} {view.y}</div>
            <button type="button" onClick={() => stepMonth(1)} aria-label="Next month" className="grid h-7 w-7 place-items-center rounded-md text-ink-soft transition hover:bg-surface hover:text-ink"><Icon name="chevron-right" size={16} /></button>
          </div>
          <div className="grid grid-cols-7 gap-0.5">
            {DOW.map((d) => <div key={d} className="grid h-7 place-items-center text-[10.5px] font-medium uppercase tracking-wide text-muted-foreground">{d}</div>)}
            {cells.map((dt, i) => {
              if (!dt) return <div key={i} />;
              const isSel = sameDay(dt, selected);
              const isToday = sameDay(dt, today);
              return (
                <button key={i} type="button"
                  onClick={() => { onChange(toISO(dt)); setOpen(false); }}
                  className={cn("grid h-9 place-items-center rounded-md text-[12.5px] tabular-nums transition",
                    isSel ? "bg-ink font-medium text-background" : "text-ink hover:bg-surface",
                    !isSel && isToday && "font-semibold text-ink ring-1 ring-inset ring-line")}>
                  {dt.getDate()}
                </button>
              );
            })}
          </div>
          <div className="mt-2 flex items-center justify-between border-t border-line px-1 pt-2">
            <button type="button" onClick={() => { onChange(toISO(today)); setView({ y: today.getFullYear(), m: today.getMonth() }); setOpen(false); }} className="text-[12px] text-ink-soft transition hover:text-ink">Today</button>
            {value && <button type="button" onClick={() => { onChange(""); setOpen(false); }} className="text-[12px] text-ink-soft transition hover:text-ink">Clear</button>}
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, {
  Button, buttonVariants, Badge, Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter,
  Separator, Hint, Icon, VetoLogo, EmptyState, FilesArtifact, RowsSkeleton, ReceiptArtifact, LearnMore, Autocomplete, DateField,
});
