// helpers.jsx — Staychain explainer: visual system + reusable flat components (part 1).

const C = {
  cream:'#F5F7F9', cream2:'#EAEDF1', ink:'#15183A', ink2:'#5B6472',
  coral:'#6C5CE7', coralDk:'#5646C9', coralSoft:'#F2F0FF',
  teal:'#0FB888', tealSoft:'#D6F4EC', gold:'#E7B23E', goldDk:'#C7902A',
  white:'#FFFFFF', line:'#E6E8EC', green:'#0FB888', greenSoft:'#E7FBF3',
  grey:'#B7BEC6', red:'#E5484D',
};
const F = { sans:"'Manrope', system-ui, sans-serif", mono:"'Space Mono', ui-monospace, monospace" };
const ease = window.Easing, interp = window.interpolate, clamp = window.clamp;

function seg(t, a, b, e) { const p = clamp((t - a) / (b - a), 0, 1); return e ? e(p) : p; }

function Scene({ start, end, bg, children, fadeIn = 0.5, fadeOut = 0.5, zoom = 0 }) {
  return (
    <Sprite start={start} end={end}>
      {({ localTime, duration }) => {
        const fi = clamp(localTime / fadeIn, 0, 1);
        const fo = clamp((duration - localTime) / fadeOut, 0, 1);
        const opacity = Math.min(ease.easeOutQuad(fi), ease.easeOutQuad(fo));
        const sc = 1 + zoom * clamp(localTime / duration, 0, 1);
        return (
          <div style={{ position:'absolute', inset:0, opacity, background: bg||'transparent',
            transform:`scale(${sc})`, transformOrigin:'center', willChange:'transform, opacity', overflow:'hidden' }}>
            {typeof children === 'function' ? children({ localTime, duration }) : children}
          </div>
        );
      }}
    </Sprite>
  );
}

function Caption({ children, y = 906, sub = false, color, x = 960, max = 1360, align = 'center', size, weight }) {
  return (
    <div style={{ position:'absolute', left:x, top:y, transform:'translateX(-50%)',
      width:max, maxWidth:max, textAlign:align, fontFamily:F.sans,
      fontWeight: weight || (sub ? 500 : 700), fontSize: size || (sub ? 33 : 50),
      lineHeight:1.18, letterSpacing:'-0.02em', color: color||C.ink, textWrap:'pretty' }}>{children}</div>
  );
}

function Reveal({ t, a = 0, b = 0.6, y = 24, x = 0, scale, children, style }) {
  const p = seg(t, a, b, ease.easeOutCubic);
  const s = scale != null ? (scale + (1 - scale) * p) : 1;
  return (
    <div style={{ opacity:p, transform:`translate(${(1-p)*x}px, ${(1-p)*y}px) scale(${s})`, ...style }}>{children}</div>
  );
}

function Coin({ size = 120, label = '$', color = C.gold, dark = C.goldDk, text = '#5A4410', sub, style }) {
  return (
    <div style={{ width:size, height:size, borderRadius:'50%',
      background:`radial-gradient(circle at 35% 30%, ${color}, ${dark})`,
      boxShadow:`inset 0 -${size*0.06}px ${size*0.1}px rgba(0,0,0,0.18), 0 ${size*0.05}px ${size*0.12}px rgba(60,40,0,0.18)`,
      border:`${size*0.05}px solid ${dark}`, display:'flex', flexDirection:'column',
      alignItems:'center', justifyContent:'center', fontFamily:F.sans, fontWeight:800,
      color:text, lineHeight:1, flexShrink:0, ...style }}>
      <div style={{ fontSize:size*(label.length>2?0.3:0.46) }}>{label}</div>
      {sub && <div style={{ fontSize:size*0.15, fontWeight:700, marginTop:size*0.04, opacity:0.75 }}>{sub}</div>}
    </div>
  );
}

function Avatar({ size = 140, color = C.coral, ring = C.white, label, style }) {
  return (
    <div style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:size*0.1, ...style }}>
      <div style={{ width:size, height:size, borderRadius:'50%', background:color,
        position:'relative', overflow:'hidden',
        boxShadow:`0 ${size*0.06}px ${size*0.14}px rgba(0,0,0,0.14), inset 0 0 0 ${size*0.045}px ${ring}` }}>
        <svg viewBox="0 0 100 100" width={size} height={size} style={{ position:'absolute', inset:0 }}>
          <circle cx="50" cy="38" r="17" fill={ring} />
          <path d="M22 84 C22 62 78 62 78 84 Z" fill={ring} />
        </svg>
      </div>
      {label && <div style={{ fontFamily:F.sans, fontWeight:700, fontSize:size*0.19, color:C.ink }}>{label}</div>}
    </div>
  );
}

function Shield({ size = 120, color = C.teal, glow = 0, check = true }) {
  return (
    <div style={{ width:size, height:size*1.1, position:'relative',
      filter: glow ? `drop-shadow(0 0 ${glow}px ${C.teal}99)` : 'none' }}>
      <svg viewBox="0 0 100 110" width={size} height={size*1.1}>
        <path d="M50 4 L90 20 V52 C90 80 72 98 50 106 C28 98 10 80 10 52 V20 Z"
          fill={color} stroke={C.white} strokeWidth="5" strokeLinejoin="round" />
        {check && <path d="M33 56 L45 68 L69 40" fill="none" stroke={C.white}
          strokeWidth="8" strokeLinecap="round" strokeLinejoin="round" />}
      </svg>
    </div>
  );
}

function Lockbox({ size = 320, lit = false, color = C.teal, children }) {
  return (
    <div style={{ width:size, height:size*0.94, borderRadius:size*0.08, background:C.white,
      border:`${size*0.02}px solid ${color}`,
      boxShadow: lit ? `0 30px 70px rgba(44,140,132,0.30), 0 0 0 ${size*0.028}px ${C.tealSoft}`
        : `0 24px 50px rgba(0,0,0,0.12)`, position:'relative', transition:'box-shadow 300ms' }}>
      <div style={{ position:'absolute', top:size*0.06, left:'50%', transform:'translateX(-50%)',
        width:size*0.34, height:size*0.035, borderRadius:99, background:C.line }} />
      <div style={{ position:'absolute', top:size*0.14, right:size*0.09, width:size*0.12, height:size*0.12,
        borderRadius:'50%', border:`${size*0.018}px solid ${color}`, background:C.cream }}>
        <div style={{ position:'absolute', top:'50%', left:'50%', width:size*0.012, height:size*0.045,
          background:color, transform:'translate(-50%,-100%)', borderRadius:4 }} />
      </div>
      {children}
    </div>
  );
}

function Phone({ width = 420, children, style }) {
  return (
    <div style={{ width, height:width*2.04, borderRadius:width*0.13, background:C.ink, padding:width*0.028,
      boxShadow:'0 40px 90px rgba(0,0,0,0.28)', position:'relative', flexShrink:0, ...style }}>
      <div style={{ width:'100%', height:'100%', borderRadius:width*0.1, background:C.cream,
        overflow:'hidden', position:'relative' }}>
        <div style={{ position:'absolute', top:0, left:'50%', transform:'translateX(-50%)',
          width:width*0.32, height:width*0.05, background:C.ink,
          borderRadius:`0 0 ${width*0.05}px ${width*0.05}px`, zIndex:5 }} />
        {children}
      </div>
    </div>
  );
}

const PROP_GRADS = [
  'linear-gradient(160deg,#7FD4E8 0%,#A8E6CF 55%,#F4E2A0 100%)',
  'linear-gradient(160deg,#F6C68B 0%,#F19E7A 60%,#E27D9A 100%)',
  'linear-gradient(160deg,#8FD3C7 0%,#5FB8C4 100%)',
  'linear-gradient(160deg,#FFD89B 0%,#F0A35E 100%)',
];
function PropertyCard({ w = 300, title = 'Tropical Villa', price = '$210', grad = 0, dates = 'Jul 4–9', tag, style }) {
  return (
    <div style={{ width:w, background:C.white, borderRadius:w*0.06,
      boxShadow:'0 18px 40px rgba(0,0,0,0.10)', overflow:'hidden', fontFamily:F.sans, flexShrink:0, ...style }}>
      <div style={{ width:'100%', height:w*0.62, background:PROP_GRADS[grad%4], position:'relative' }}>
        <div style={{ position:'absolute', top:w*0.08, right:w*0.1, width:w*0.13, height:w*0.13,
          borderRadius:'50%', background:'rgba(255,255,255,0.85)', filter:'blur(1px)' }} />
        {tag && <div style={{ position:'absolute', top:w*0.06, left:w*0.06, background:C.white, color:C.ink,
          fontSize:w*0.05, fontWeight:700, padding:`${w*0.016}px ${w*0.05}px`, borderRadius:99 }}>{tag}</div>}
      </div>
      <div style={{ padding:w*0.06 }}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'baseline' }}>
          <div style={{ fontWeight:800, fontSize:w*0.072, color:C.ink }}>{title}</div>
          <div style={{ fontWeight:800, fontSize:w*0.068, color:C.coral }}>{price}</div>
        </div>
        <div style={{ color:C.ink2, fontSize:w*0.05, marginTop:w*0.02, fontWeight:500 }}>{dates} · night</div>
      </div>
    </div>
  );
}

function Pill({ label, active }) {
  return (
    <div style={{ padding:'12px 26px', borderRadius:99, whiteSpace:'nowrap', fontFamily:F.sans,
      fontWeight:700, fontSize:26, background: active?C.ink:C.white, color: active?C.cream:C.ink2,
      border:`2px solid ${active?C.ink:C.line}` }}>{label}</div>
  );
}

function CheckRow({ label, done, w = 470 }) {
  return (
    <div style={{ display:'flex', alignItems:'center', gap:18, fontFamily:F.sans, width:w }}>
      <div style={{ width:38, height:38, borderRadius:10, flexShrink:0,
        background: done?C.teal:'transparent', border:`3px solid ${done?C.teal:C.line}`,
        display:'flex', alignItems:'center', justifyContent:'center', transition:'background 220ms' }}>
        {done && <svg viewBox="0 0 24 24" width={24} height={24}>
          <path d="M5 13l4 4L19 7" fill="none" stroke={C.white} strokeWidth="3.5"
            strokeLinecap="round" strokeLinejoin="round" />
        </svg>}
      </div>
      <div style={{ fontSize:33, fontWeight:700, color: done?C.ink:C.ink2, opacity: done?1:0.65 }}>{label}</div>
    </div>
  );
}

function CheckBurst({ size = 200, p = 1, color = C.green }) {
  const draw = clamp(p, 0, 1), len = 120;
  return (
    <div style={{ width:size, height:size, borderRadius:'50%', background:color,
      display:'flex', alignItems:'center', justifyContent:'center',
      boxShadow:`0 20px 50px ${color}55`, transform:`scale(${0.6+0.4*ease.easeOutBack(draw)})` }}>
      <svg viewBox="0 0 100 100" width={size*0.6} height={size*0.6}>
        <path d="M24 52 L44 72 L78 32" fill="none" stroke={C.white} strokeWidth="10"
          strokeLinecap="round" strokeLinejoin="round"
          strokeDasharray={len} strokeDashoffset={len*(1-clamp((draw-0.2)/0.8,0,1))} />
      </svg>
    </div>
  );
}

function Wordmark({ size = 84, color = C.ink, accent = C.teal }) {
  return (
    <div style={{ fontFamily:F.sans, fontWeight:800, fontSize:size, letterSpacing:'-0.04em',
      color, display:'flex', alignItems:'center' }}>
      <span>stay</span><span style={{ color:accent }}>chain</span>
    </div>
  );
}

Object.assign(window, {
  C, F, ease, interp, clamp, seg,
  Scene, Caption, Reveal, Coin, Avatar, Shield, Lockbox, Phone,
  PropertyCard, Pill, CheckRow, CheckBurst, Wordmark,
});
