// components.jsx — UI primitives

const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ─────────────────────────────────────────────────────────────
// Logo A1
// ─────────────────────────────────────────────────────────────
function A1Logo({ size = 28 }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
      <div style={{
        width: size, height: size, borderRadius: size * 0.22,
        background: 'linear-gradient(135deg, #EE2D8F, #7230F0)',
        color: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontWeight: 800, fontSize: size * 0.5, letterSpacing: -0.5,
      }}>A1</div>
      <div style={{ fontWeight: 700, fontSize: size * 0.58, letterSpacing: -0.3, color: 'var(--ink-900)' }}>
        Broker
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Top App Bar — back, brand, progress
// ─────────────────────────────────────────────────────────────
function AppBar({ onBack, step, total, onRestart, showProgress = true }) {
  const pct = total > 0 ? Math.round((step / total) * 100) : 0;
  return (
    <div style={{
      position: 'sticky', top: 0, background: '#fff',
      zIndex: 20, borderBottom: '1px solid var(--ink-100)',
      paddingTop: 'env(safe-area-inset-top)',
    }}>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 12,
        padding: '12px 16px',
      }}>
        <button
          onClick={onBack}
          disabled={!onBack}
          aria-label="Atrás"
          style={{
            width: 36, height: 36, borderRadius: 10,
            background: onBack ? 'var(--ink-100)' : 'transparent',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            opacity: onBack ? 1 : 0.3,
          }}
        >
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
            <path d="M15 6l-6 6 6 6" stroke="var(--ink-900)" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        </button>
        <div style={{ flex: 1, display: 'flex', justifyContent: 'center' }}>
          <span style={{ fontWeight: 700, fontSize: 13, letterSpacing: 0.8, color: 'var(--ink-900)', textTransform: 'uppercase' }}>
            A1 Broker Seguros
          </span>
        </div>
        <button
          onClick={onRestart}
          aria-label="Reiniciar"
          style={{
            width: 36, height: 36, borderRadius: 10,
            background: 'var(--ink-100)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}
        >
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
            <path d="M3 12a9 9 0 1 0 3-6.7L3 8M3 3v5h5" stroke="var(--ink-700)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        </button>
      </div>
      {showProgress && total > 0 && (
        <div style={{ padding: '0 16px 12px' }}>
          <div style={{
            display: 'flex', justifyContent: 'space-between',
            fontSize: 12, color: 'var(--ink-500)',
            fontWeight: 500, marginBottom: 6,
          }}>
            <span>Paso {Math.min(step + 1, total)} de {total}</span>
            <span style={{ fontFeatureSettings: '"tnum"' }}>{pct}%</span>
          </div>
          <div style={{
            height: 6, borderRadius: 99, background: 'var(--ink-100)', overflow: 'hidden',
          }}>
            <div style={{
              height: '100%', width: `${pct}%`,
              background: 'linear-gradient(90deg, var(--brand-600), var(--brand-500))',
              borderRadius: 99, transition: 'width 280ms cubic-bezier(.4,0,.2,1)',
            }} />
          </div>
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Screen wrapper — scrollable body + sticky footer
// ─────────────────────────────────────────────────────────────
function Screen({ children, footer }) {
  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', minHeight: 0 }}>
      <div style={{
        flex: 1, overflowY: 'auto', padding: '20px 20px 24px',
        WebkitOverflowScrolling: 'touch',
      }}>
        {children}
      </div>
      {footer && (
        <div style={{
          background: '#fff',
          borderTop: '1px solid var(--ink-100)',
          padding: '12px 16px calc(20px + env(safe-area-inset-bottom))',
          boxShadow: '0 -4px 20px rgba(10,37,64,0.05)',
          overflow: 'visible',
        }}>
          {footer}
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Question header — eyebrow + title + subtitle
// ─────────────────────────────────────────────────────────────
function QHeader({ eyebrow, title, subtitle }) {
  return (
    <div style={{ marginBottom: 24 }}>
      {eyebrow && (
        <div style={{
          fontSize: 12, fontWeight: 600, letterSpacing: 0.8,
          color: 'var(--brand-600)', textTransform: 'uppercase',
          marginBottom: 10,
        }}>
          {eyebrow}
        </div>
      )}
      <h1 style={{
        fontSize: 26, fontWeight: 700, lineHeight: 1.2,
        color: 'var(--ink-900)', textWrap: 'pretty',
      }}>{title}</h1>
      {subtitle && (
        <p style={{
          marginTop: 8, fontSize: 15, lineHeight: 1.5,
          color: 'var(--ink-500)', textWrap: 'pretty',
        }}>{subtitle}</p>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Input
// ─────────────────────────────────────────────────────────────
function Input({
  label, value, onChange, placeholder, type = 'text',
  inputMode, maxLength, prefix, suffix, error, hint, autoFocus,
  pattern,
}) {
  const ref = useRef(null);
  useEffect(() => {
    if (autoFocus && ref.current) {
      // Avoid double scroll on iOS on mount
      setTimeout(() => ref.current && ref.current.focus(), 100);
    }
  }, [autoFocus]);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {label && (
        <label style={{
          fontSize: 13, fontWeight: 500, color: 'var(--ink-700)',
        }}>{label}</label>
      )}
      <div style={{
        display: 'flex', alignItems: 'center',
        background: '#fff',
        border: `1.5px solid ${error ? 'var(--err)' : 'var(--ink-200)'}`,
        borderRadius: 12,
        transition: 'border-color 120ms, box-shadow 120ms',
      }}
        onFocusCapture={(e) => {
          if (!error) e.currentTarget.style.borderColor = 'var(--brand-500)';
          e.currentTarget.style.boxShadow = error
            ? '0 0 0 3px rgba(220,38,38,0.12)'
            : '0 0 0 3px rgba(42,125,225,0.12)';
        }}
        onBlurCapture={(e) => {
          e.currentTarget.style.borderColor = error ? 'var(--err)' : 'var(--ink-200)';
          e.currentTarget.style.boxShadow = 'none';
        }}
      >
        {prefix && (
          <div style={{
            padding: '0 4px 0 14px', color: 'var(--ink-400)', fontSize: 16,
            fontWeight: 500,
          }}>{prefix}</div>
        )}
        <input
          ref={ref}
          type={type}
          inputMode={inputMode}
          maxLength={maxLength}
          value={value || ''}
          onChange={(e) => onChange(e.target.value)}
          placeholder={placeholder}
          pattern={pattern}
          style={{
            flex: 1, border: 'none', background: 'transparent',
            padding: '14px 14px', fontSize: 16,
            width: '100%',
          }}
        />
        {suffix && (
          <div style={{ padding: '0 14px 0 4px', color: 'var(--ink-400)', fontSize: 14 }}>{suffix}</div>
        )}
      </div>
      {(error || hint) && (
        <div style={{
          fontSize: 12.5, color: error ? 'var(--err)' : 'var(--ink-500)',
          display: 'flex', alignItems: 'center', gap: 5,
        }}>
          {error && (
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none">
              <circle cx="12" cy="12" r="10" stroke="var(--err)" strokeWidth="2"/>
              <path d="M12 7v6M12 16v.5" stroke="var(--err)" strokeWidth="2" strokeLinecap="round"/>
            </svg>
          )}
          {error || hint}
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Textarea
// ─────────────────────────────────────────────────────────────
function Textarea({ label, value, onChange, placeholder, rows = 3, error, hint }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {label && <label style={{ fontSize: 13, fontWeight: 500, color: 'var(--ink-700)' }}>{label}</label>}
      <textarea
        value={value || ''}
        onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder}
        rows={rows}
        style={{
          padding: '14px',
          border: `1.5px solid ${error ? 'var(--err)' : 'var(--ink-200)'}`,
          borderRadius: 12, background: '#fff', resize: 'vertical',
          fontSize: 16, lineHeight: 1.5, minHeight: 80,
        }}
      />
      {(error || hint) && (
        <div style={{ fontSize: 12.5, color: error ? 'var(--err)' : 'var(--ink-500)' }}>
          {error || hint}
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Radio / Option cards (for single-choice)
// ─────────────────────────────────────────────────────────────
function OptionList({ value, onChange, options, columns = 1 }) {
  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: `repeat(${columns}, 1fr)`,
      gap: 10,
    }}>
      {options.map((opt) => {
        const v = typeof opt === 'string' ? opt : opt.value;
        const label = typeof opt === 'string' ? opt : opt.label;
        const desc = typeof opt === 'string' ? null : opt.desc;
        const icon = typeof opt === 'string' ? null : opt.icon;
        const active = value === v;
        return (
          <button
            key={v}
            onClick={() => onChange(v)}
            style={{
              textAlign: 'left', padding: '14px 16px',
              border: `1.5px solid ${active ? 'var(--brand-500)' : 'var(--ink-200)'}`,
              background: active ? 'var(--brand-50)' : '#fff',
              borderRadius: 14,
              display: 'flex', alignItems: 'center', gap: 12,
              transition: 'all 120ms',
              boxShadow: active ? '0 0 0 3px rgba(42,125,225,0.15)' : 'none',
            }}
          >
            {icon && <div style={{ fontSize: 20, flexShrink: 0 }}>{icon}</div>}
            <div style={{ flex: 1 }}>
              <div style={{
                fontSize: 15, fontWeight: 600, color: 'var(--ink-900)',
              }}>{label}</div>
              {desc && (
                <div style={{ fontSize: 13, color: 'var(--ink-500)', marginTop: 2 }}>{desc}</div>
              )}
            </div>
            <div style={{
              width: 22, height: 22, borderRadius: 99,
              border: `2px solid ${active ? 'var(--brand-500)' : 'var(--ink-300)'}`,
              background: active ? 'var(--brand-500)' : 'transparent',
              flexShrink: 0, position: 'relative',
            }}>
              {active && (
                <svg width="12" height="12" viewBox="0 0 24 24" fill="none"
                  style={{ position: 'absolute', top: 3, left: 3 }}>
                  <path d="M4 12l5 5L20 6" stroke="#fff" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"/>
                </svg>
              )}
            </div>
          </button>
        );
      })}
    </div>
  );
}

// Multi-select variant (checkbox cards)
function CheckList({ value, onChange, options }) {
  const arr = Array.isArray(value) ? value : [];
  const toggle = (v) => {
    if (arr.includes(v)) onChange(arr.filter(x => x !== v));
    else onChange([...arr, v]);
  };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      {options.map(opt => {
        const v = typeof opt === 'string' ? opt : opt.value;
        const label = typeof opt === 'string' ? opt : opt.label;
        const active = arr.includes(v);
        return (
          <button
            key={v}
            onClick={() => toggle(v)}
            style={{
              textAlign: 'left', padding: '14px 16px',
              border: `1.5px solid ${active ? 'var(--brand-500)' : 'var(--ink-200)'}`,
              background: active ? 'var(--brand-50)' : '#fff',
              borderRadius: 14,
              display: 'flex', alignItems: 'center', gap: 12,
              transition: 'all 120ms',
            }}
          >
            <div style={{
              width: 22, height: 22, borderRadius: 6,
              border: `2px solid ${active ? 'var(--brand-500)' : 'var(--ink-300)'}`,
              background: active ? 'var(--brand-500)' : 'transparent',
              flexShrink: 0, position: 'relative',
            }}>
              {active && (
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none"
                  style={{ position: 'absolute', top: 2, left: 2 }}>
                  <path d="M4 12l5 5L20 6" stroke="#fff" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"/>
                </svg>
              )}
            </div>
            <div style={{ fontSize: 15, fontWeight: 500, color: 'var(--ink-900)' }}>{label}</div>
          </button>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Yes/No toggle
// ─────────────────────────────────────────────────────────────
function YesNo({ value, onChange }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
      {[['si', 'Sí'], ['no', 'No']].map(([v, l]) => {
        const active = value === v;
        return (
          <button key={v} onClick={() => onChange(v)}
            style={{
              padding: '18px 12px', fontSize: 16, fontWeight: 600,
              border: `1.5px solid ${active ? 'var(--brand-500)' : 'var(--ink-200)'}`,
              background: active ? 'var(--brand-50)' : '#fff',
              color: active ? 'var(--brand-700)' : 'var(--ink-700)',
              borderRadius: 14, transition: 'all 120ms',
            }}>
            {l}
          </button>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// File upload
// ─────────────────────────────────────────────────────────────
function FileUpload({ value, onChange, accept = 'image/*,.pdf', label, icon = '📎', multiple = false, uploadFn }) {
  const ref = useRef(null);
  const [uploading, setUploading] = React.useState(false);
  const [uploadError, setUploadError] = React.useState(null);
  const files = Array.isArray(value) ? value : (value ? [value] : []);
  const handle = async (e) => {
    const list = Array.from(e.target.files || []);
    if (!list.length) return;
    e.target.value = ''; // permite re-seleccionar el mismo archivo
    setUploadError(null);
    if (uploadFn) {
      setUploading(true);
      try {
        const uploaded = await Promise.all(list.map(f => uploadFn(f)));
        if (multiple) {
          onChange([...files, ...uploaded]);
        } else {
          onChange(uploaded[0]);
        }
      } catch (err) {
        setUploadError('Error al subir. Intentá de nuevo.');
      } finally {
        setUploading(false);
      }
    } else {
      const mapped = list.map(f => ({ name: f.name, size: f.size, type: f.type }));
      if (multiple) onChange([...files, ...mapped]);
      else onChange(mapped[0]);
    }
  };
  const removeAt = (idx) => {
    if (multiple) onChange(files.filter((_, i) => i !== idx));
    else onChange(null);
  };
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      <button
        onClick={() => !uploading && ref.current && ref.current.click()}
        disabled={uploading}
        style={{
          padding: '18px 16px',
          border: '1.5px dashed var(--ink-300)',
          borderRadius: 14, background: uploading ? 'var(--ink-100)' : 'var(--ink-50)',
          display: 'flex', alignItems: 'center', gap: 12,
          textAlign: 'left', opacity: uploading ? 0.75 : 1,
        }}
      >
        <div style={{ fontSize: 22 }}>{uploading ? '⏳' : icon}</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink-900)' }}>
            {uploading ? 'Subiendo...' : (label || 'Subir archivo')}
          </div>
          <div style={{ fontSize: 12, color: 'var(--ink-500)', marginTop: 2 }}>
            Foto o PDF · toca para elegir
          </div>
        </div>
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
          <path d="M12 5v14M5 12h14" stroke="var(--brand-600)" strokeWidth="2.5" strokeLinecap="round"/>
        </svg>
      </button>
      <input ref={ref} type="file" accept={accept} multiple={multiple} onChange={handle} style={{ display: 'none' }} />
      {files.length > 0 && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
          {files.map((f, i) => (
            <div key={i} style={{
              display: 'flex', alignItems: 'center', gap: 10,
              padding: '10px 12px', background: 'var(--accent-100)',
              borderRadius: 10, border: '1px solid rgba(34,197,94,0.3)',
            }}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" style={{ flexShrink: 0 }}>
                <path d="M4 12l5 5L20 6" stroke="var(--accent-600)" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"/>
              </svg>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 500, color: 'var(--ink-900)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                  {f.name}
                </div>
                <div style={{ fontSize: 11, color: 'var(--ink-500)' }}>
                  {(f.size / 1024).toFixed(0)} KB
                </div>
              </div>
              <button onClick={() => removeAt(i)} style={{
                width: 24, height: 24, borderRadius: 99,
                background: 'rgba(0,0,0,0.06)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>
                <svg width="10" height="10" viewBox="0 0 24 24" fill="none">
                  <path d="M5 5l14 14M19 5L5 19" stroke="var(--ink-700)" strokeWidth="2.5" strokeLinecap="round"/>
                </svg>
              </button>
            </div>
          ))}
        </div>
      )}
      {uploadError && (
        <div style={{ fontSize: 12, color: '#DC2626', padding: '6px 10px', background: '#FEF2F2', borderRadius: 8 }}>
          {uploadError}
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Date picker (native input, styled wrapper)
// ─────────────────────────────────────────────────────────────
function DateInput({ value, onChange, error, hint, label }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {label && <label style={{ fontSize: 13, fontWeight: 500, color: 'var(--ink-700)' }}>{label}</label>}
      <input
        type="date"
        value={value || ''}
        onChange={(e) => onChange(e.target.value)}
        style={{
          padding: '14px', border: `1.5px solid ${error ? 'var(--err)' : 'var(--ink-200)'}`,
          borderRadius: 12, background: '#fff', fontSize: 16,
        }}
      />
      {(error || hint) && (
        <div style={{ fontSize: 12.5, color: error ? 'var(--err)' : 'var(--ink-500)' }}>
          {error || hint}
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Buttons
// ─────────────────────────────────────────────────────────────
function PrimaryButton({ children, onClick, disabled, icon, loading }) {
  return (
    <button
      onClick={onClick}
      disabled={disabled || loading}
      style={{
        width: '100%', padding: '16px 20px',
        background: disabled ? 'var(--ink-200)' : 'linear-gradient(135deg, #EE2D8F 0%, #7230F0 100%)',
        color: disabled ? 'var(--ink-400)' : '#fff',
        borderRadius: 14,
        fontWeight: 600, fontSize: 16,
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        transition: 'transform 80ms, opacity 120ms',
        boxShadow: disabled ? 'none' : '0 4px 18px rgba(114,48,240,0.35)',
      }}
      onMouseDown={(e) => !disabled && (e.currentTarget.style.transform = 'scale(0.98)')}
      onMouseUp={(e) => (e.currentTarget.style.transform = 'scale(1)')}
      onMouseLeave={(e) => (e.currentTarget.style.transform = 'scale(1)')}
      onTouchStart={(e) => !disabled && (e.currentTarget.style.transform = 'scale(0.98)')}
      onTouchEnd={(e) => (e.currentTarget.style.transform = 'scale(1)')}
    >
      {loading ? <Spinner /> : (<>{children}{icon}</>)}
    </button>
  );
}

function GhostButton({ children, onClick }) {
  return (
    <button
      onClick={onClick}
      style={{
        width: '100%', padding: '14px 20px',
        background: 'transparent', color: 'var(--ink-700)',
        borderRadius: 14, fontWeight: 600, fontSize: 15,
        border: '1.5px solid var(--ink-200)',
      }}
    >{children}</button>
  );
}

function Spinner() {
  return (
    <div style={{
      width: 18, height: 18, borderRadius: 99,
      border: '2.5px solid rgba(255,255,255,0.3)',
      borderTopColor: '#fff',
      animation: 'spin 0.7s linear infinite',
    }}>
      <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Info card / banner
// ─────────────────────────────────────────────────────────────
function Banner({ children, icon, tone = 'info' }) {
  const tones = {
    info: { bg: 'var(--brand-50)', border: 'var(--brand-100)', color: 'var(--brand-700)' },
    success: { bg: 'var(--accent-100)', border: 'rgba(34,197,94,0.3)', color: 'var(--accent-600)' },
    warn: { bg: 'var(--warn-100)', border: 'rgba(245,158,11,0.3)', color: '#92400E' },
  };
  const t = tones[tone];
  return (
    <div style={{
      padding: '12px 14px', background: t.bg,
      border: `1px solid ${t.border}`, borderRadius: 12,
      display: 'flex', gap: 10, alignItems: 'flex-start',
      fontSize: 13, lineHeight: 1.5, color: 'var(--ink-700)',
    }}>
      {icon && <div style={{ fontSize: 18, flexShrink: 0, lineHeight: 1 }}>{icon}</div>}
      <div style={{ flex: 1 }}>{children}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Risk category picker grid
// ─────────────────────────────────────────────────────────────
function RiskCategoryGrid({ value, onChange, options }) {
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10,
    }}>
      {options.map(opt => {
        const active = value === opt.value;
        return (
          <button
            key={opt.value}
            onClick={() => onChange(opt.value)}
            style={{
              textAlign: 'left', padding: '16px 14px',
              border: `1.5px solid ${active ? 'var(--brand-500)' : 'var(--ink-200)'}`,
              background: active ? 'var(--brand-50)' : '#fff',
              borderRadius: 16,
              display: 'flex', flexDirection: 'column', gap: 10,
              minHeight: 130, position: 'relative',
              transition: 'all 120ms',
              boxShadow: active ? '0 0 0 3px rgba(42,125,225,0.15)' : 'none',
            }}
          >
            <div style={{
              width: 44, height: 44, borderRadius: 12,
              background: active ? 'var(--brand-600)' : 'var(--ink-100)',
              color: active ? '#fff' : 'var(--brand-700)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontSize: 22, transition: 'all 120ms',
            }}>
              {opt.icon}
            </div>
            <div>
              <div style={{ fontSize: 14.5, fontWeight: 600, color: 'var(--ink-900)', lineHeight: 1.2 }}>
                {opt.label}
              </div>
              {opt.hint && (
                <div style={{ fontSize: 12, color: 'var(--ink-500)', marginTop: 2 }}>{opt.hint}</div>
              )}
            </div>
          </button>
        );
      })}
    </div>
  );
}

Object.assign(window, {
  A1Logo, AppBar, Screen, QHeader,
  Input, Textarea, DateInput,
  OptionList, CheckList, YesNo, FileUpload,
  PrimaryButton, GhostButton, Spinner,
  Banner, RiskCategoryGrid,
});
