// Shared components per the BoxMind design system.
// Every component takes `dark` + optional `moving`; colors resolve from theme().

// ─── Buttons ─────────────────────────────────────────────────
function PrimaryButton({ children, dark, moving, full = true, disabled, onClick, style, icon }) {
  const t = theme(dark, moving);
  return (
    <button onClick={onClick} disabled={disabled} style={{
      height: 52, borderRadius: 12, border: 'none',
      background: disabled ? t.surfaceTertiary : t.accent,
      color: disabled ? t.textTertiary : t.onAccent,
      ...TYPE.btn, width: full ? '100%' : undefined,
      padding: '0 20px', cursor: disabled ? 'default' : 'pointer',
      display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
      boxShadow: disabled ? 'none' : t.shadowSm,
      fontFamily: FONT_STACK,
      ...style,
    }}>
      {icon}{children}
    </button>
  );
}

function SecondaryButton({ children, dark, moving, destructive, full = true, onClick, style }) {
  const t = theme(dark, moving);
  const c = destructive ? t.destructive : t.textPrimary;
  const b = destructive ? t.destructive : t.sep;
  return (
    <button onClick={onClick} style={{
      height: 44, borderRadius: 12,
      border: `1.5px solid ${b}`, background: 'transparent',
      color: c, ...TYPE.btn, width: full ? '100%' : undefined,
      padding: '0 16px', cursor: 'pointer', fontFamily: FONT_STACK,
      display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
      ...style,
    }}>{children}</button>
  );
}

// ─── FormField ───────────────────────────────────────────────
function FormField({ label, value, placeholder, dark, moving, error, focus, multiline, rightIcon, leftIcon, disabled, type = 'text', style }) {
  const t = theme(dark, moving);
  const borderColor = error ? t.destructive : focus ? t.accent : 'transparent';
  return (
    <div style={style}>
      {label && <div style={{ ...TYPE.label, color: t.textSecondary, marginBottom: 6 }}>{label}</div>}
      <div style={{
        height: multiline ? 88 : 48, borderRadius: 12,
        background: t.surfaceTertiary, border: `2px solid ${borderColor}`,
        padding: multiline ? '12px 14px' : '0 14px',
        display: 'flex', alignItems: multiline ? 'flex-start' : 'center', gap: 10,
        opacity: disabled ? 0.6 : 1,
      }}>
        {leftIcon}
        <div style={{ flex: 1, color: value ? t.textPrimary : t.textTertiary, ...TYPE.body, fontFamily: FONT_STACK, whiteSpace: multiline ? 'pre-wrap' : 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
          {value || placeholder}
          {focus && !value && <span style={{ display: 'inline-block', width: 1.5, height: 18, background: t.accent, verticalAlign: 'middle', marginLeft: 1, animation: 'bm-caret 1s infinite' }} />}
        </div>
        {rightIcon}
      </div>
      {error && <div style={{ ...TYPE.label, color: t.destructive, marginTop: 6 }}>{error}</div>}
    </div>
  );
}

function SearchBar({ value, placeholder = 'Search items, boxes, tags…', dark, moving, style, onClear }) {
  const t = theme(dark, moving);
  return (
    <div style={{
      height: 44, borderRadius: 12, background: t.surfaceTertiary,
      padding: '0 12px', display: 'flex', alignItems: 'center', gap: 10,
      ...style,
    }}>
      <Icons.Search size={18} color={t.textTertiary} />
      <div style={{ flex: 1, ...TYPE.body, color: value ? t.textPrimary : t.textTertiary, fontFamily: FONT_STACK }}>
        {value || placeholder}
      </div>
      {value && <Icons.XCircle size={18} color={t.textTertiary} />}
    </div>
  );
}

// ─── Chips ──────────────────────────────────────────────────
function TagChip({ children, variant = 'default', dark, moving, dismissible, style }) {
  const t = theme(dark, moving);
  const map = {
    default: { bg: t.surfaceTertiary, fg: t.textPrimary },
    brand:   { bg: t.accentLight,     fg: t.accent },
    ai:      { bg: t.aiPurpleLight,   fg: t.aiPurple },
    warn:    { bg: t.warningLight,    fg: t.warning },
    danger:  { bg: t.destructiveLight,fg: t.destructive },
    info:    { bg: t.infoLight,       fg: t.info },
  };
  const c = map[variant];
  return (
    <div style={{
      height: 24, borderRadius: 8, padding: '0 10px',
      background: c.bg, color: c.fg, ...TYPE.caption,
      display: 'inline-flex', alignItems: 'center', gap: 6, fontFamily: FONT_STACK,
      ...style,
    }}>
      {children}
      {dismissible && <Icons.X size={10} color={c.fg} strokeWidth={2.5} />}
    </div>
  );
}

function FilterChip({ children, selected, count, dark, moving, onClick, style }) {
  const t = theme(dark, moving);
  return (
    <button onClick={onClick} style={{
      height: 36, borderRadius: 9999, border: 'none',
      padding: '0 14px', background: selected ? t.accent : t.surfaceTertiary,
      color: selected ? t.onAccent : t.textPrimary,
      fontSize: 14, fontWeight: 600, fontFamily: FONT_STACK,
      cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 4,
      ...style,
    }}>
      {children}
      {typeof count === 'number' && <span style={{ opacity: 0.7 }}>({count})</span>}
    </button>
  );
}

// ─── BoxCard ────────────────────────────────────────────────
function BoxCard({ name, meta, color = '#0D7377', thumb, thumbIcon, dark, moving, onClick, style, statusPill }) {
  const t = theme(dark, moving);
  return (
    <div onClick={onClick} style={{
      borderRadius: 24, padding: 16, background: t.surface,
      display: 'flex', alignItems: 'center', gap: 14,
      boxShadow: t.shadowSm, position: 'relative', overflow: 'hidden',
      cursor: onClick ? 'pointer' : 'default', ...style,
    }}>
      <div style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: 4, background: color }} />
      <div style={{
        width: 44, height: 44, borderRadius: 10,
        background: thumb || `${color}20`, flexShrink: 0,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        {thumbIcon || <Icons.Package size={22} color={color} />}
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ ...TYPE.h3, color: t.textPrimary, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{name}</div>
        <div style={{ ...TYPE.label, color: t.textSecondary, marginTop: 2 }}>{meta}</div>
      </div>
      {statusPill}
      <Icons.ChevronR size={18} color={t.textTertiary} />
    </div>
  );
}

// ─── StatCard / QuickAction ─────────────────────────────────
function StatCard({ icon, value, label, tint, dark, moving, style }) {
  const t = theme(dark, moving);
  const c = tint || t.accent;
  const bg = tint ? `${tint}20` : t.accentLight;
  return (
    <div style={{
      borderRadius: 12, padding: 16, background: t.surface,
      boxShadow: t.shadowSm, ...style,
    }}>
      <div style={{
        width: 40, height: 40, borderRadius: 20, background: bg,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        marginBottom: 10,
      }}>{icon ? React.cloneElement(icon, { color: c }) : null}</div>
      <div style={{ ...TYPE.h2, color: t.textPrimary, letterSpacing: -0.3 }}>{value}</div>
      <div style={{ ...TYPE.caption, color: t.textSecondary, marginTop: 2 }}>{label}</div>
    </div>
  );
}

function QuickActionCard({ icon, label, tint, dark, moving, style, small = false }) {
  const t = theme(dark, moving);
  const c = tint || t.accent;
  const bg = tint ? `${tint}20` : t.accentLight;
  const iconSize = small ? 40 : 48;
  const iconGlyph = small ? 20 : 22;
  return (
    <div style={{
      borderRadius: 12, padding: small ? 10 : 16, background: t.surface, minHeight: small ? 86 : 88,
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: small ? 8 : 10,
      boxShadow: t.shadowSm, ...style,
    }}>
      <div style={{ width: iconSize, height: iconSize, borderRadius: iconSize / 2, background: bg, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        {icon ? React.cloneElement(icon, { color: c, size: iconGlyph }) : null}
      </div>
      <div style={{ fontSize: small ? 11 : 12, color: t.textPrimary, textAlign: 'center', fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '100%' }}>{label}</div>
    </div>
  );
}

// ─── TipCard (AI) ────────────────────────────────────────────
function TipCard({ children, cachedAt = '2h ago', dark, moving, style, footer = true }) {
  const t = theme(dark, moving);
  return (
    <div style={{
      borderRadius: 12, padding: '14px 14px 12px 16px',
      background: t.aiPurpleLight,
      borderLeft: `3px solid ${t.aiPurple}`,
      position: 'relative',
      ...style,
    }}>
      <div style={{ position: 'absolute', top: 10, right: 10, cursor: 'pointer' }}>
        <Icons.X size={14} color={t.aiPurple} strokeWidth={2.2} />
      </div>
      <div style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
        <div style={{ paddingTop: 1 }}><Icons.Sparkles size={18} color={t.aiPurple} /></div>
        <div style={{ flex: 1 }}>
          <div style={{ ...TYPE.body, color: dark ? t.textPrimary : '#4C2889', paddingRight: 14 }}>{children}</div>
          {footer && (
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 8 }}>
              <div style={{ ...TYPE.caption, color: dark ? t.textTertiary : '#7C59B8' }}>Cached · {cachedAt}</div>
              <div style={{ ...TYPE.caption, color: t.aiPurple, textDecoration: 'underline', fontWeight: 600 }}>Don't show again</div>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// ─── ItemRow ────────────────────────────────────────────────
function ItemRow({ name, meta, thumb, thumbIcon, thumbColor, loan, dark, moving, style, last }) {
  const t = theme(dark, moving);
  return (
    <div style={{
      minHeight: 56, display: 'flex', alignItems: 'center', gap: 12,
      padding: '8px 16px', borderBottom: last ? 'none' : `0.5px solid ${t.sep}`,
      ...style,
    }}>
      <div style={{
        width: 40, height: 40, borderRadius: 10, flexShrink: 0,
        background: thumb || `${thumbColor || t.accent}20`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        {thumbIcon || <Icons.Package size={20} color={thumbColor || t.accent} />}
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ ...TYPE.h3, color: t.textPrimary, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{name}</div>
        {meta && <div style={{ ...TYPE.label, color: t.textSecondary, marginTop: 1 }}>{meta}</div>}
      </div>
      {loan && <LoanBadge status={loan.status} label={loan.label} dark={dark} moving={moving} />}
      <Icons.ChevronR size={16} color={t.textTertiary} />
    </div>
  );
}

function LoanBadge({ status = 'active', label, dark, moving }) {
  const t = theme(dark, moving);
  const map = {
    overdue:  { bg: t.destructiveLight, fg: t.destructive },
    due_soon: { bg: t.warningLight,     fg: t.warning },
    active:   { bg: t.accentLight,      fg: t.accent },
  };
  const c = map[status];
  return (
    <div style={{
      height: 22, padding: '0 8px', borderRadius: 6,
      background: c.bg, color: c.fg, ...TYPE.caption,
      display: 'inline-flex', alignItems: 'center',
      fontFamily: FONT_STACK,
    }}>{label}</div>
  );
}

function LoanRow({ item, borrower, due, status, dark, moving, last, style }) {
  const t = theme(dark, moving);
  return (
    <div style={{
      minHeight: 64, display: 'flex', alignItems: 'center', gap: 12,
      padding: '10px 16px', borderBottom: last ? 'none' : `0.5px solid ${t.sep}`,
      ...style,
    }}>
      <div style={{
        width: 40, height: 40, borderRadius: 20, flexShrink: 0,
        background: t.accentLight, display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <Icons.User size={20} color={t.accent} />
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ ...TYPE.h3, color: t.textPrimary }}>{borrower}</div>
        <div style={{ ...TYPE.label, color: t.textSecondary, marginTop: 1 }}>{item}</div>
      </div>
      <LoanBadge status={status} label={due} dark={dark} moving={moving} />
    </div>
  );
}

// ─── Empty state ────────────────────────────────────────────
function EmptyState({ illustration, title, body, cta, link, dark, moving, style }) {
  const t = theme(dark, moving);
  return (
    <div style={{ padding: 32, display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', ...style }}>
      <div style={{
        width: 160, height: 160, borderRadius: 80,
        background: t.surfaceTertiary, marginBottom: 20,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        position: 'relative', overflow: 'hidden',
      }}>
        {illustration}
      </div>
      <div style={{ ...TYPE.h1, color: t.textPrimary, marginBottom: 6 }}>{title}</div>
      <div style={{ ...TYPE.body, color: t.textSecondary, maxWidth: 280, lineHeight: '22px' }}>{body}</div>
      {cta && <div style={{ marginTop: 20, width: '100%', maxWidth: 280 }}>{cta}</div>}
      {link && <div style={{ marginTop: 12, ...TYPE.bodySm, color: t.accent, textDecoration: 'underline', fontWeight: 500 }}>{link}</div>}
    </div>
  );
}

// ─── Toast ──────────────────────────────────────────────────
function Toast({ kind = 'success', message, action, dark, moving, style }) {
  const t = theme(dark, moving);
  const map = {
    success:     { c: t.success },
    destructive: { c: t.destructive },
    warning:     { c: t.warning },
    info:        { c: t.info },
  };
  const c = map[kind].c;
  return (
    <div style={{
      borderRadius: 8, background: t.surface, boxShadow: t.shadowMd,
      borderLeft: `4px solid ${c}`,
      padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 12,
      ...style,
    }}>
      <div style={{ flex: 1, ...TYPE.body, color: t.textPrimary }}>{message}</div>
      {action && <div style={{ ...TYPE.btn, color: t.accent, fontSize: 14 }}>{action}</div>}
    </div>
  );
}

// ─── Tab bar + FAB ──────────────────────────────────────────
// Platform-aware: iOS = floating pill with integrated FAB; Android = Material 3 navigation bar
// with pill-shape indicator behind the active icon.
function TabBar({ active = 'dashboard', dark, moving, style, onTab, withoutFab = false, platform = 'ios' }) {
  if (platform === 'android') return <AndroidNavBar active={active} dark={dark} moving={moving} style={style} onTab={onTab} />;
  const t = theme(dark, moving);
  const tabs = [
    { id: 'boxes',     label: 'Boxes',     icon: Icons.Archive },
    { id: 'dashboard', label: 'Home',      icon: Icons.Home },
    { id: 'scan',      label: 'Scan',      icon: null, fab: true },
    { id: 'search',    label: 'Search',    icon: Icons.Search },
    { id: 'loans',     label: 'Loans',     icon: Icons.HandReach },
  ];
  return (
    <div style={{
      position: 'absolute', left: 12, right: 12, bottom: 12,
      height: 64, borderTopLeftRadius: 24, borderTopRightRadius: 24,
      borderBottomLeftRadius: 24, borderBottomRightRadius: 24,
      background: t.surface, boxShadow: t.shadowMd,
      display: 'flex', alignItems: 'flex-start', justifyContent: 'space-around',
      paddingTop: 10, zIndex: 20, ...style,
    }}>
      {tabs.map((tab) => {
        if (tab.fab && !withoutFab) {
          return (
            <div key={tab.id} onClick={() => onTab && onTab(tab.id)} style={{
              position: 'relative', flex: 1, display: 'flex', flexDirection: 'column',
              alignItems: 'center', cursor: 'pointer',
            }}>
              <div style={{
                width: 56, height: 56, borderRadius: 28, background: t.accent,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                boxShadow: t.fabShadow, marginTop: -34,
              }}>
                <Icons.Radio size={26} color={t.amber} strokeWidth={2.2} />
              </div>
              <div style={{ ...TYPE.caption, color: active === 'scan' ? t.accent : t.textSecondary, marginTop: 4, fontWeight: 500 }}>Scan</div>
            </div>
          );
        }
        const Icon = tab.icon;
        const isActive = active === tab.id;
        return (
          <div key={tab.id} onClick={() => onTab && onTab(tab.id)} style={{
            flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3, cursor: 'pointer',
          }}>
            <Icon size={22} color={isActive ? t.accent : t.textSecondary} strokeWidth={isActive ? 2.2 : 2} />
            <div style={{ ...TYPE.caption, color: isActive ? t.accent : t.textSecondary, fontWeight: 500 }}>{tab.label}</div>
          </div>
        );
      })}
    </div>
  );
}

// Material 3 bottom navigation bar.
//  · Sits flush on the bottom (not floating).
//  · Active item has a pill-shaped indicator (56×32) behind the icon, tinted with accent.
//  · Scan is an ordinary nav item here — FAB is docked separately above the bar per M3 guidelines.
function AndroidNavBar({ active = 'dashboard', dark, moving, style, onTab }) {
  const t = theme(dark, moving);
  const navBg = dark ? '#1C1F26' : '#FFFFFF';
  const tabs = [
    { id: 'boxes',     label: 'Boxes',  icon: Icons.Archive },
    { id: 'dashboard', label: 'Home',   icon: Icons.Home },
    { id: 'scan',      label: 'Scan',   icon: Icons.Radio },
    { id: 'search',    label: 'Search', icon: Icons.Search },
    { id: 'loans',     label: 'Loans',  icon: Icons.HandReach },
  ];
  return (
    <div style={{
      position: 'absolute', left: 0, right: 0, bottom: 0,
      height: 80, paddingBottom: 18, background: navBg,
      display: 'flex', alignItems: 'flex-start', justifyContent: 'space-around',
      zIndex: 20, paddingTop: 12,
      boxShadow: dark ? 'none' : '0 -1px 0 rgba(0,0,0,0.06)',
      fontFamily: ANDROID_FONT_STACK, ...style,
    }}>
      {tabs.map((tab) => {
        const Icon = tab.icon;
        const isActive = active === tab.id;
        return (
          <div key={tab.id} onClick={() => onTab && onTab(tab.id)} style={{
            flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4, cursor: 'pointer',
          }}>
            <div style={{
              width: 56, height: 32, borderRadius: 16,
              background: isActive ? t.accentTint : 'transparent',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              transition: 'background 160ms',
            }}>
              <Icon size={22} color={isActive ? t.accent : t.textSecondary} strokeWidth={isActive ? 2.4 : 2} />
            </div>
            <div style={{
              fontSize: 12, lineHeight: '16px', fontWeight: isActive ? 600 : 500,
              color: isActive ? t.textPrimary : t.textSecondary,
              fontFamily: ANDROID_FONT_STACK, letterSpacing: 0.2,
            }}>{tab.label}</div>
          </div>
        );
      })}
    </div>
  );
}

function Fab({ icon, dark, moving, style, onClick, color, platform = 'ios' }) {
  const t = theme(dark, moving);
  // Material 3 FAB: larger (56), 16px squircle corners, "primary container" tone.
  // iOS FAB: perfect circle, accent tone.
  const isAndroid = platform === 'android';
  return (
    <div onClick={onClick} style={{
      position: 'absolute', right: isAndroid ? 16 : 20, bottom: isAndroid ? 96 : 100,
      width: 56, height: 56, borderRadius: isAndroid ? 16 : 28,
      background: color || t.accent,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      boxShadow: isAndroid
        ? '0 6px 10px rgba(0,0,0,0.22), 0 1px 3px rgba(0,0,0,0.12)'
        : t.fabShadow,
      cursor: 'pointer', zIndex: 15, ...style,
    }}>
      {icon || <Icons.Plus size={26} color={t.onAccent} strokeWidth={2.5} />}
    </div>
  );
}

// ─── Screen scaffold with standard header + content area ─────
function Screen({ dark, moving, children, bg, style }) {
  const t = theme(dark, moving);
  return (
    <div style={{
      position: 'absolute', inset: 0, background: bg || t.bg,
      display: 'flex', flexDirection: 'column', overflow: 'hidden', ...style,
    }}>{children}</div>
  );
}

function ParallaxHeader({ title, dark, moving, showAvatar = true, collapsed = false, subtitle, style, showBack, rightAction, platform = 'ios', moving_toggle = false, onMoving, movingActive = false }) {
  const t = theme(dark, moving);
  if (platform === 'android') {
    return <AndroidAppBar title={title} subtitle={subtitle} dark={dark} moving={moving} collapsed={collapsed}
      showBack={showBack} showAvatar={showAvatar} rightAction={rightAction} style={style}
      moving_toggle={moving_toggle} onMoving={onMoving} movingActive={movingActive} />;
  }
  // iOS: when Moving Mode is active, the orange stripe wraps the status bar and
  // adds a row below — push the header down by ~34px to clear it.
  const topPad = (collapsed ? 54 : 54) + (moving ? 34 : 0);
  return (
    <div style={{
      padding: `${topPad}px 16px ${collapsed ? 12 : 16}px`,
      background: t.bg, position: 'relative', zIndex: 2,
      ...style,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', minHeight: collapsed ? 40 : 56 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          {showBack && <Icons.ChevronL size={24} color={t.textPrimary} />}
          <div>
            <div style={{ ...(collapsed ? TYPE.h1 : TYPE.display), color: t.textPrimary, letterSpacing: '-0.3px' }}>{title}</div>
            {subtitle && !collapsed && <div style={{ ...TYPE.body, color: t.textSecondary, marginTop: 4 }}>{subtitle}</div>}
          </div>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          {/* iOS Moving Mode toggle lives top-right in the nav bar */}
          {moving_toggle && (
            <div onClick={onMoving} style={{
              height: 30, borderRadius: 15, padding: '0 10px',
              display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer',
              background: movingActive ? '#EA580C' : t.surfaceTertiary,
              color: movingActive ? '#fff' : t.textSecondary,
              fontSize: 12, fontWeight: 600, letterSpacing: 0.2,
            }}>
              <span style={{ fontSize: 13 }}>🚚</span>
              <span>{movingActive ? 'Moving' : 'Moving Mode'}</span>
            </div>
          )}
          {rightAction}
          {showAvatar && <Avatar dark={dark} moving={moving} />}
        </div>
      </div>
    </div>
  );
}

// Material 3 top app bar.
//  · 64dp height, title left-aligned (NOT a large display title like iOS).
//  · Left: back arrow (←, not chevron) when showBack; else page title
//  · Right: action icons + OVERFLOW menu (kebab ⋮). Moving Mode is tucked inside the overflow.
//  · Subtitle, if present, sits below the title at 14sp / onSurfaceVariant.
//  · Avatar, when present, replaces overflow as the last action (profile entry).
function AndroidAppBar({ title, subtitle, dark, moving, collapsed, showBack, showAvatar, rightAction, style, moving_toggle, onMoving, movingActive }) {
  const t = theme(dark, moving);
  const navBg = dark ? '#1C1F26' : '#FFFFFF';
  return (
    <div style={{
      paddingTop: 32 + (moving ? 38 : 0), // status bar + (moving stripe row) consumed
      background: navBg, position: 'relative', zIndex: 2,
      boxShadow: dark ? 'none' : '0 1px 0 rgba(0,0,0,0.05)',
      fontFamily: ANDROID_FONT_STACK, ...style,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 4, padding: '8px 4px 12px 16px', minHeight: 64 }}>
        {showBack && (
          <div style={{ width: 40, height: 40, borderRadius: 20, display: 'flex', alignItems: 'center', justifyContent: 'center', marginRight: 4, marginLeft: -8 }}>
            <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={t.textPrimary} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>
          </div>
        )}
        <div style={{ flex: 1 }}>
          <div style={{
            fontSize: 22, lineHeight: '28px', fontWeight: 500,
            color: t.textPrimary, fontFamily: ANDROID_FONT_STACK,
          }}>{title}</div>
          {subtitle && !collapsed && (
            <div style={{
              fontSize: 14, lineHeight: '20px', color: t.textSecondary,
              marginTop: 2, fontFamily: ANDROID_FONT_STACK,
            }}>{subtitle}</div>
          )}
        </div>
        <div style={{ display: 'flex', alignItems: 'center' }}>
          {rightAction}
          {/* Overflow menu (⋮) — Moving Mode entry lives in here on Android */}
          <AndroidOverflow dark={dark} moving={moving}
            movingToggle={moving_toggle} onMoving={onMoving} movingActive={movingActive} />
          {showAvatar && <div style={{ marginLeft: 4, marginRight: 12 }}><Avatar dark={dark} moving={moving} /></div>}
        </div>
      </div>
      {/* Contextual Moving banner when active on Android (overflow-selected state) */}
      {moving_toggle && movingActive && (
        <div style={{
          margin: '0 16px 12px', height: 36, borderRadius: 8,
          padding: '0 12px', display: 'flex', alignItems: 'center', gap: 8,
          background: 'rgba(234,88,12,0.12)', color: '#EA580C',
          fontSize: 13, fontWeight: 500, fontFamily: ANDROID_FONT_STACK,
        }}>
          <span>🚚</span>
          <span style={{ flex: 1 }}>Moving Mode active</span>
          <span onClick={onMoving} style={{ textTransform: 'uppercase', letterSpacing: 0.4, fontSize: 12, fontWeight: 600, cursor: 'pointer' }}>Turn off</span>
        </div>
      )}
    </div>
  );
}

// Open-state-illustrated overflow menu: renders the kebab, and if `movingToggle`
// is on, shows a floating menu card next to it so the affordance is visible
// in the static design.
function AndroidOverflow({ dark, moving, movingToggle, onMoving, movingActive, showOpen = false }) {
  const t = theme(dark, moving);
  return (
    <div style={{ position: 'relative', width: 40, height: 40, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
      {/* kebab icon */}
      <svg width="22" height="22" viewBox="0 0 24 24" fill={t.textPrimary}>
        <circle cx="12" cy="5" r="1.8"/><circle cx="12" cy="12" r="1.8"/><circle cx="12" cy="19" r="1.8"/>
      </svg>
    </div>
  );
}

function Avatar({ dark, moving, size = 36, initials = 'CM' }) {
  const t = theme(dark, moving);
  return (
    <div style={{
      width: size, height: size, borderRadius: size / 2, background: t.accentLight,
      color: t.accent, display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontSize: size * 0.38, fontWeight: 600, fontFamily: FONT_STACK,
    }}>{initials}</div>
  );
}

// ─── Photo placeholder (striped) ────────────────────────────
function PhotoPlaceholder({ size = 44, radius = 10, label, dark, moving, style }) {
  const t = theme(dark, moving);
  return (
    <div style={{
      width: size, height: size, borderRadius: radius,
      background: `repeating-linear-gradient(45deg, ${t.surfaceTertiary} 0, ${t.surfaceTertiary} 4px, ${dark ? '#2A2D35' : '#E8EAEE'} 4px, ${dark ? '#2A2D35' : '#E8EAEE'} 8px)`,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      ...style,
    }}>{label && <span style={{ fontSize: 9, color: t.textTertiary, fontFamily: 'ui-monospace, monospace' }}>{label}</span>}</div>
  );
}

// ─── Bottom Sheet container ─────────────────────────────────
function BottomSheet({ children, dark, moving, height = 'auto', style, backdrop = true }) {
  const t = theme(dark, moving);
  return (
    <div style={{
      position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end',
      background: backdrop ? 'rgba(0,0,0,0.5)' : 'transparent', ...style,
    }}>
      <div style={{
        background: t.surface, borderTopLeftRadius: 24, borderTopRightRadius: 24,
        boxShadow: t.shadowLg, minHeight: height, padding: '8px 0 28px',
      }}>
        <div style={{ width: 36, height: 4, borderRadius: 2, background: t.sepLight, margin: '4px auto 12px' }} />
        {children}
      </div>
    </div>
  );
}

Object.assign(window, {
  PrimaryButton, SecondaryButton, FormField, SearchBar,
  TagChip, FilterChip, BoxCard, StatCard, QuickActionCard,
  TipCard, ItemRow, LoanRow, LoanBadge, EmptyState, Toast,
  TabBar, AndroidNavBar, Fab, Screen, ParallaxHeader, AndroidAppBar, AndroidOverflow,
  Avatar, PhotoPlaceholder, BottomSheet,
});
