// nyashelf-atoms.jsx
// Atomic UI components: GlassCard, GradientButton, StatusPill, NyaInput, BottomNav, etc.

// ─── GlassCard ──────────────────────────────────────────────────────────────
function GlassCard({ children, style = {}, glow = false, padding = 14, onClick, active = false }) {
  return (
    <div
      onClick={onClick}
      style={{
        position: 'relative',
        background: 'var(--card-bg)',
        backdropFilter: 'blur(14px) saturate(140%)',
        WebkitBackdropFilter: 'blur(14px) saturate(140%)',
        border: '1px solid var(--card-border)',
        borderRadius: 'var(--radius)',
        padding,
        boxShadow: active ?
        `0 0 0 1.5px var(--glow-strong), 0 8px 28px var(--glow-soft), inset 0 1px 0 rgba(255,255,255,.08)` :
        glow ?
        `0 4px 20px var(--glow-soft), inset 0 1px 0 rgba(255,255,255,.06)` :
        `0 4px 18px rgba(0,0,0,.18), inset 0 1px 0 rgba(255,255,255,.05)`,
        cursor: onClick ? 'pointer' : 'default',
        transition: 'transform .18s ease, box-shadow .2s ease',
        ...style
      }}>
      
      {children}
    </div>);

}

// ─── GradientButton ─────────────────────────────────────────────────────────
// Pill-shaped pink/lilac gradient button with soft glow.
function GradientButton({ children, onClick, style = {}, size = 'md', icon, full = false, disabled = false }) {
  const h = size === 'sm' ? 36 : size === 'lg' ? 52 : 44;
  const fs = size === 'sm' ? 13 : size === 'lg' ? 16 : 14.5;
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      style={{
        position: 'relative',
        height: h, width: full ? '100%' : 'auto',
        padding: size === 'sm' ? '0 16px' : '0 22px',
        borderRadius: 9999, border: 0,
        background: 'linear-gradient(135deg, var(--accent-a) 0%, var(--accent-b) 100%)',
        color: '#3a1e4d',
        fontFamily: 'Quicksand, sans-serif',
        fontWeight: 600, fontSize: fs,
        boxShadow: `0 4px 18px var(--glow-soft), 0 0 28px var(--glow-soft), inset 0 1px 0 rgba(255,255,255,.5), inset 0 -1px 0 rgba(0,0,0,.08)`,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 7,
        cursor: disabled ? 'not-allowed' : 'pointer',
        opacity: disabled ? 0.45 : 1,
        transition: 'transform .15s ease, box-shadow .15s ease',
        letterSpacing: '.01em',
        ...style
      }}
      onMouseDown={(e) => e.currentTarget.style.transform = 'scale(.97)'}
      onMouseUp={(e) => e.currentTarget.style.transform = 'scale(1)'}
      onMouseLeave={(e) => e.currentTarget.style.transform = 'scale(1)'}>
      
      {icon}
      <span>{children}</span>
    </button>);

}

// ─── GhostButton ────────────────────────────────────────────────────────────
function GhostButton({ children, onClick, style = {}, size = 'md', icon, full = false }) {
  const h = size === 'sm' ? 36 : size === 'lg' ? 52 : 44;
  const fs = size === 'sm' ? 13 : size === 'lg' ? 16 : 14.5;
  return (
    <button
      onClick={onClick}
      style={{
        height: h, width: full ? '100%' : 'auto',
        padding: size === 'sm' ? '0 16px' : '0 22px',
        borderRadius: 9999,
        background: 'rgba(255,255,255,.06)',
        backdropFilter: 'blur(10px)',
        WebkitBackdropFilter: 'blur(10px)',
        border: '1px solid rgba(200,155,240,.25)',
        color: 'var(--text)',
        fontFamily: 'Quicksand, sans-serif',
        fontWeight: 500, fontSize: fs,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 7,
        cursor: 'pointer',
        transition: 'background .15s, border-color .15s',
        ...style
      }}>
      
      {icon}
      <span>{children}</span>
    </button>);

}

// ─── StatusPill ─────────────────────────────────────────────────────────────
const STATUS_DEFS = {
  available: { label: 'в наличии', dot: '#6fdb9c', bg: 'rgba(111,219,156,.14)' },
  preorder: { label: 'предзаказ', dot: '#f5d56e', bg: 'rgba(245,213,110,.14)' },
  soon: { label: 'скоро', dot: '#6fb8ff', bg: 'rgba(111,184,255,.14)' },
  paid: { label: 'оплачено', dot: '#c89bf0', bg: 'rgba(200,155,240,.14)' },
  shipped: { label: 'в пути', dot: '#9ecdff', bg: 'rgba(158,205,255,.14)' },
  delivered: { label: 'получено', dot: '#6fdb9c', bg: 'rgba(111,219,156,.14)' },
  overdue: { label: 'просрочка', dot: '#ff8aa8', bg: 'rgba(255,138,168,.16)' }
};

function StatusPill({ status, size = 'md' }) {
  const d = STATUS_DEFS[status] || STATUS_DEFS.preorder;
  const small = size === 'sm';
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      height: small ? 22 : 26,
      padding: small ? '0 9px' : '0 11px',
      background: d.bg,
      border: `0.5px solid ${d.dot}33`,
      borderRadius: 9999,
      fontSize: small ? 11 : 12,
      fontWeight: 500,
      color: 'var(--text)',
      letterSpacing: '.01em',
      whiteSpace: 'nowrap'
    }}>
      <span style={{
        width: small ? 6 : 7, height: small ? 6 : 7, borderRadius: '50%',
        background: d.dot,
        boxShadow: `0 0 6px ${d.dot}aa`
      }} />
      {d.label}
    </span>);

}

// ─── NyaInput ────────────────────────────────────────────────────────────────
function NyaInput({ value, onChange, placeholder, icon, type = 'text', style = {}, autoFocus = false }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 8,
      height: 44, padding: '0 14px',
      background: 'rgba(255,255,255,.06)',
      border: '1px solid rgba(200,155,240,.22)',
      borderRadius: 9999,
      backdropFilter: 'blur(10px)',
      WebkitBackdropFilter: 'blur(10px)',
      ...style
    }}>
      {icon && <span style={{ color: 'var(--text-dim)', display: 'flex' }}>{icon}</span>}
      <input
        type={type}
        value={value}
        autoFocus={autoFocus}
        onChange={(e) => onChange?.(e.target.value)}
        placeholder={placeholder}
        style={{
          flex: 1, background: 'transparent', border: 0, outline: 0,
          color: 'var(--text)', fontFamily: 'Quicksand, sans-serif',
          fontSize: 14.5, fontWeight: 500,
          minWidth: 0
        }} />
      
    </div>);

}

// ─── IconChip ───────────────────────────────────────────────────────────────
function IconChip({ children, onClick, active = false, style = {} }) {
  return (
    <button onClick={onClick} style={{
      width: 38, height: 38, borderRadius: '50%',
      background: active ? 'linear-gradient(135deg, var(--accent-a), var(--accent-b))' : 'rgba(255,255,255,.06)',
      border: '1px solid rgba(200,155,240,.22)',
      color: active ? '#3a1e4d' : 'var(--text)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      cursor: 'pointer', padding: 0,
      backdropFilter: 'blur(10px)',
      WebkitBackdropFilter: 'blur(10px)',
      boxShadow: active ? `0 0 18px var(--glow-soft)` : 'none',
      transition: 'all .15s',
      ...style
    }}>{children}</button>);

}

// ─── Icons (line-style kawaii) ──────────────────────────────────────────────
const I = {
  home: (s = 22) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 11 L 12 4 L 21 11 V 19 a 2 2 0 0 1 -2 2 H 5 a 2 2 0 0 1 -2 -2 Z" />
      <path d="M9 21 V 14 h 6 V 21" />
    </svg>,

  calendar: (s = 22) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <rect x="3" y="5" width="18" height="16" rx="3" />
      <path d="M3 10 H 21" />
      <path d="M8 3 V 7" /><path d="M16 3 V 7" />
    </svg>,

  search: (s = 22) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="11" cy="11" r="7" />
      <path d="M20 20 L 16 16" />
    </svg>,

  heart: (s = 22, fill = 'none') =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill={fill} stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12 21 C 12 21, 3 15, 3 8.5 C 3 5.5, 5.5 3, 8.5 3 C 10.4 3, 11.5 4.2, 12 5.5 C 12.5 4.2, 13.6 3, 15.5 3 C 18.5 3, 21 5.5, 21 8.5 C 21 15, 12 21, 12 21 Z" />
    </svg>,

  settings: (s = 22) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="12" cy="12" r="3" />
      <path d="M19.4 15 a1.65 1.65 0 0 0 .33 1.82 l .06 .06 a 2 2 0 0 1 -2.83 2.83 l -.06 -.06 a 1.65 1.65 0 0 0 -1.82 -.33 a 1.65 1.65 0 0 0 -1 1.51 V 21 a 2 2 0 0 1 -4 0 v -.09 a 1.65 1.65 0 0 0 -1 -1.51 a 1.65 1.65 0 0 0 -1.82 .33 l -.06 .06 a 2 2 0 0 1 -2.83 -2.83 l .06 -.06 a 1.65 1.65 0 0 0 .33 -1.82 a 1.65 1.65 0 0 0 -1.51 -1 H 3 a 2 2 0 0 1 0 -4 h .09 a 1.65 1.65 0 0 0 1.51 -1 a 1.65 1.65 0 0 0 -.33 -1.82 l -.06 -.06 a 2 2 0 0 1 2.83 -2.83 l .06 .06 a 1.65 1.65 0 0 0 1.82 .33 H 9 a 1.65 1.65 0 0 0 1 -1.51 V 3 a 2 2 0 0 1 4 0 v .09 a 1.65 1.65 0 0 0 1 1.51 a 1.65 1.65 0 0 0 1.82 -.33 l .06 -.06 a 2 2 0 0 1 2.83 2.83 l -.06 .06 a 1.65 1.65 0 0 0 -.33 1.82 V 9 a 1.65 1.65 0 0 0 1.51 1 H 21 a 2 2 0 0 1 0 4 h -.09 a 1.65 1.65 0 0 0 -1.51 1 Z" />
    </svg>,

  back: (s = 22) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M15 6 L 9 12 L 15 18" />
    </svg>,

  filter: (s = 18) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 6 H 21" /><path d="M6 12 H 18" /><path d="M10 18 H 14" />
    </svg>,

  plus: (s = 18) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12 5 V 19" /><path d="M5 12 H 19" />
    </svg>,

  chevDown: (s = 16) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M6 9 L 12 15 L 18 9" />
    </svg>,

  chevRight: (s = 16) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M9 6 L 15 12 L 9 18" />
    </svg>,

  bell: (s = 18) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M6 8 a 6 6 0 0 1 12 0 c 0 7 3 9 3 9 H 3 s 3 -2 3 -9" />
      <path d="M10 21 a 2 2 0 0 0 4 0" />
    </svg>,

  share: (s = 18) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="18" cy="5" r="3" /><circle cx="6" cy="12" r="3" /><circle cx="18" cy="19" r="3" />
      <path d="M8.6 10.5 L 15.4 6.5" /><path d="M8.6 13.5 L 15.4 17.5" />
    </svg>,

  check: (s = 16) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
      <path d="M5 12 L 10 17 L 19 7" />
    </svg>,

  close: (s = 16) =>
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M6 6 L 18 18" /><path d="M18 6 L 6 18" />
    </svg>

};

// ─── BottomNav ──────────────────────────────────────────────────────────────
function BottomNav({ active, onChange }) {
  const items = [
  { id: 'home', label: 'главная', icon: I.home },
  { id: 'calendar', label: 'оплаты', icon: I.calendar },
  { id: 'search', label: 'каталог', icon: I.search },
  { id: 'wishlist', label: 'вишлист', icon: I.heart },
  { id: 'settings', label: 'настройки', icon: I.settings }];

  return (
    <div style={{
      position: 'absolute', left: 12, right: 12, bottom: 10,
      height: 64,
      background: 'rgba(30,18,55,.55)',
      backdropFilter: 'blur(20px) saturate(160%)',
      WebkitBackdropFilter: 'blur(20px) saturate(160%)',
      border: '1px solid rgba(200,155,240,.18)',
      boxShadow: '0 8px 30px rgba(0,0,0,.4), inset 0 1px 0 rgba(255,255,255,.06)',
      display: 'flex', alignItems: 'stretch', justifyContent: 'space-around',
      padding: '0 6px',
      zIndex: 40, borderRadius: 24,
    }}>
      {items.map((it) => {
        const on = active === it.id;
        return (
          <button key={it.id} onClick={() => onChange(it.id)} style={{
            background: 'transparent', border: 0,
            display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
            gap: 3,
            color: on ? 'var(--accent-a)' : 'var(--text-dim)',
            cursor: 'pointer',
            position: 'relative',
            flex: 1,
            transition: 'color .18s', padding: 0,
          }}>
            <div style={{ position: 'relative', zIndex: 1, filter: on ? 'drop-shadow(0 0 6px var(--glow-strong))' : 'none' }}>
              {it.icon(22)}
            </div>
            <span style={{ position: 'relative', zIndex: 1, fontSize: 9.5, fontWeight: 500, letterSpacing: '.01em' }}>{it.label}</span>
          </button>);

      })}
    </div>);

}

// ─── Section helpers ───────────────────────────────────────────────────────
function ScreenTitle({ children, subtitle, action }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between',
      padding: '8px 4px 14px', gap: 12
    }}>
      <div style={{ minWidth: 0 }}>
        <h1 style={{
          margin: 0, fontFamily: 'Comfortaa, sans-serif', fontWeight: 600,
          fontSize: 28, lineHeight: 1.1, letterSpacing: '-.01em',
          background: 'linear-gradient(135deg, #fff 0%, var(--accent-a) 60%, var(--accent-b) 100%)',
          WebkitBackgroundClip: 'text', backgroundClip: 'text',
          color: 'transparent'
        }}>{children}</h1>
        {subtitle &&
        <div style={{ marginTop: 4, fontSize: 13, color: 'var(--text-dim)', fontWeight: 500 }}>
            {subtitle}
          </div>
        }
      </div>
      {action}
    </div>);

}

function SectionLabel({ children, action }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      padding: '4px 4px 8px', marginTop: 6
    }}>
      <h3 style={{
        margin: 0, fontFamily: 'Quicksand, sans-serif', fontWeight: 600,
        fontSize: 13, letterSpacing: '.08em', textTransform: 'uppercase',
        color: 'var(--text-dim)'
      }}>{children}</h3>
      {action}
    </div>);

}

// ─── TgAvatar / TgUser ──────────────────────────────────────────────────────
// Read the current Telegram user from window.Telegram.WebApp.initDataUnsafe.
// Falls back to a designer-friendly mock when running outside Telegram so the
// prototype always shows something sensible.
function getTgUser() {
  const tg = window.Telegram?.WebApp?.initDataUnsafe?.user;
  if (tg && tg.first_name) {
    return {
      name:     tg.first_name + (tg.last_name ? ' ' + tg.last_name : ''),
      username: tg.username || null,
      photo:    tg.photo_url || null,
    };
  }
  return { name: 'настя', username: 'nastya', photo: null };
}

// Circular avatar with optional Telegram photo. Falls back to initial + gradient
// in the figure tone hash style if no photo is available.
function TgAvatar({ user, size = 56, glow = true, style = {} }) {
  const u = user || getTgUser();
  const initial = (u.name || '?').trim()[0].toUpperCase();
  // hue derived from name → consistent personalized gradient
  let h = 0;
  for (const c of (u.name || '')) h = (h + c.charCodeAt(0) * 7) % 360;
  return (
    <div style={{
      width: size, height: size, position: 'relative', flexShrink: 0,
      borderRadius: '50%',
      boxShadow: glow ? '0 0 14px var(--glow-soft), 0 4px 14px rgba(0,0,0,.3)' : 'none',
      ...style,
    }}>
      {glow && (
        <div style={{
          position: 'absolute', inset: '-20%', borderRadius: '50%',
          background: 'radial-gradient(circle, var(--glow-soft) 0%, transparent 65%)',
          filter: 'blur(8px)', pointerEvents: 'none', zIndex: 0,
        }}/>
      )}
      <div style={{
        position: 'relative', width: '100%', height: '100%',
        borderRadius: '50%', overflow: 'hidden',
        background: `linear-gradient(135deg, hsl(${h},70%,72%), hsl(${(h+50)%360},65%,55%))`,
        border: '1.5px solid var(--card-border)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        {u.photo ? (
          <img
            src={u.photo}
            alt={u.name}
            onError={(e) => { e.currentTarget.style.display = 'none'; }}
            style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
          />
        ) : (
          <span style={{
            fontFamily: 'Comfortaa, sans-serif', fontWeight: 700,
            fontSize: size * 0.42, color: '#fff',
            lineHeight: 1,
            // Comfortaa's cap-height sits below the optical line — nudge up slightly
            paddingBottom: size * 0.04,
            textShadow: '0 1px 3px rgba(0,0,0,.25)',
            userSelect: 'none',
          }}>{initial}</span>
        )}
      </div>
    </div>
  );
}

// ─── PullToRefresh ──────────────────────────────────────────────────────────
// Wraps a scroll container's first child. When the user drags down at scrollTop
// 0, shows a refresh indicator with the mascot. Releases past threshold trigger
// onRefresh(). Works with touch + mouse-drag (the desktop preview case).
function PullToRefresh({ onRefresh, children, threshold = 70 }) {
  const [pull, setPull] = React.useState(0);
  const [refreshing, setRefreshing] = React.useState(false);
  const startY = React.useRef(null);
  const ref = React.useRef(null);

  const getScroller = () => {
    let el = ref.current;
    while (el) {
      const cs = getComputedStyle(el);
      if (cs.overflowY === 'auto' || cs.overflowY === 'scroll') return el;
      el = el.parentElement;
    }
    return null;
  };

  const beginDrag = (y) => {
    if (refreshing) return false;
    const sc = getScroller();
    if (!sc || sc.scrollTop > 0) return false;
    startY.current = y;
    return true;
  };
  const moveDrag = (y) => {
    if (refreshing || startY.current == null) return;
    const dy = y - startY.current;
    if (dy <= 0) return;
    // resistance curve — easier to start pulling, harder past threshold
    const resisted = Math.pow(dy, 0.85);
    setPull(Math.min(resisted / threshold, 1.4));
  };
  const endDrag = async () => {
    if (refreshing || startY.current == null) return;
    startY.current = null;
    if (pull >= 1) {
      setRefreshing(true); setPull(1);
      try { await Promise.resolve(onRefresh?.()); }
      finally { setRefreshing(false); setPull(0); }
    } else {
      setPull(0);
    }
  };

  const onTouchStart = (e) => beginDrag(e.touches[0].clientY);
  const onTouchMove  = (e) => moveDrag(e.touches[0].clientY);
  const onTouchEnd   = ()  => endDrag();

  // Mouse-drag fallback for desktop
  const onMouseDown = (e) => {
    if (!beginDrag(e.clientY)) return;
    const onMove = (ev) => moveDrag(ev.clientY);
    const onUp = () => { window.removeEventListener('mousemove', onMove); window.removeEventListener('mouseup', onUp); endDrag(); };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
  };

  const indicatorH = refreshing ? 70 : pull * 60;
  const rot = (pull * 360) % 360;

  return (
    <div ref={ref}
         onTouchStart={onTouchStart} onTouchMove={onTouchMove} onTouchEnd={onTouchEnd}
         onMouseDown={onMouseDown}>
      <div style={{
        height: indicatorH, overflow: 'hidden',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        transition: refreshing || pull > 0 ? 'none' : 'height .2s ease',
      }}>
        <div style={{
          opacity: Math.min(1, pull * 1.2),
          transform: `translateY(${(indicatorH - 50) / 2}px) rotate(${refreshing ? 0 : rot}deg)`,
          animation: refreshing ? 'nya-spin 1s linear infinite' : 'none',
        }}>
          <div style={{
            width: 44, height: 44, borderRadius: '50%',
            background: 'rgba(255,255,255,.06)',
            border: '1.5px solid var(--card-border)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            boxShadow: pull >= 1 || refreshing ? '0 0 14px var(--glow-strong)' : 'none',
            transition: 'box-shadow .15s',
          }}>
            <Sparkle size={18} color={pull >= 1 || refreshing ? 'var(--accent-a)' : 'var(--text-dim)'} opacity={1} />
          </div>
        </div>
      </div>
      {children}
    </div>
  );
}

// ─── Skeletons ──────────────────────────────────────────────────────────────
function SkeletonCard({ height = 268, padding = 10 }) {
  return (
    <div style={{
      height, padding,
      borderRadius: 'var(--radius)',
      background: 'rgba(255,255,255,.04)',
      border: '1px solid var(--card-border)',
      display: 'flex', flexDirection: 'column', gap: 10,
      overflow: 'hidden',
    }}>
      <div style={{
        height: 150, borderRadius: 'var(--radius-sm)',
        background: 'linear-gradient(110deg, rgba(255,255,255,.04) 25%, rgba(255,255,255,.10) 50%, rgba(255,255,255,.04) 75%)',
        backgroundSize: '200% 100%',
        animation: 'nya-shimmer 1.4s ease-in-out infinite',
      }}/>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 6 }}>
        <SkeletonLine width="55%" height={10}/>
        <SkeletonLine width="85%" height={14}/>
        <SkeletonLine width="60%" height={10}/>
        <div style={{ flex: 1 }}/>
        <SkeletonLine width="40%" height={12}/>
      </div>
    </div>
  );
}
function SkeletonLine({ width = '100%', height = 12 }) {
  return (
    <div style={{
      width, height, borderRadius: 4,
      background: 'linear-gradient(110deg, rgba(255,255,255,.04) 25%, rgba(255,255,255,.10) 50%, rgba(255,255,255,.04) 75%)',
      backgroundSize: '200% 100%',
      animation: 'nya-shimmer 1.4s ease-in-out infinite',
    }}/>
  );
}
function SkeletonRow() {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 10,
      padding: 10, borderRadius: 'var(--radius)',
      background: 'rgba(255,255,255,.04)',
      border: '1px solid var(--card-border)',
    }}>
      <div style={{
        width: 52, height: 52, borderRadius: 14,
        background: 'linear-gradient(110deg, rgba(255,255,255,.04) 25%, rgba(255,255,255,.10) 50%, rgba(255,255,255,.04) 75%)',
        backgroundSize: '200% 100%',
        animation: 'nya-shimmer 1.4s ease-in-out infinite',
      }}/>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 6 }}>
        <SkeletonLine width="60%" height={12}/>
        <SkeletonLine width="40%" height={10}/>
      </div>
      <SkeletonLine width={48} height={20}/>
    </div>
  );
}

Object.assign(window, {
  GlassCard, GradientButton, GhostButton, StatusPill, NyaInput, IconChip,
  BottomNav, ScreenTitle, SectionLabel, I, STATUS_DEFS,
  TgAvatar, getTgUser,
  PullToRefresh, SkeletonCard, SkeletonLine, SkeletonRow,
});