// Self-contained primitives for the Calmaeta website UI kit.
// Assigns Button, Badge, Tag, MenuItem, Input to window so all
// subsequent Babel scripts can use them without the compiled bundle.

// Idle float + "lean away from cursor" motion shared by every photo frame below.
// The wrapper drifts up/down forever (phase-shifted per instance so photos don't
// bob in sync); the inner image also nudges in the OPPOSITE direction of the
// cursor and scales up slightly, so the photo feels alive and slightly magnetic.
const prefersReducedMotion = () => window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

if (!document.getElementById('calmaeta-motion-styles')) {
  const styleEl = document.createElement('style');
  styleEl.id = 'calmaeta-motion-styles';
  styleEl.textContent = `
    @keyframes calmaetaFloat {
      0%, 100% { transform: translateY(0); }
      50% { transform: translateY(-10px); }
    }

    /* Entrance animation for Reveal-wrapped content. Visible by default (opacity:1
       base rule, no JS dependency) — the animation is a pure-CSS enhancement that
       plays once on mount; if it never runs for any reason the base rule already
       shows the content, so nothing can get stuck invisible. */
    .calmaeta-reveal { opacity: 1; transform: translateY(0); }
    @media (prefers-reduced-motion: no-preference) {
      .calmaeta-reveal {
        animation: calmaetaReveal 700ms cubic-bezier(0.16,1,0.3,1) both;
        animation-delay: var(--reveal-delay, 0ms);
      }
    }
    @keyframes calmaetaReveal {
      from { transform: translateY(var(--reveal-y, 24px)); }
      to   { transform: translateY(0); }
    }

    /* Coffee-bean cursor */
    @media (hover: hover) and (pointer: fine) {
      body.calmaeta-cursor-active, body.calmaeta-cursor-active * { cursor: none !important; }
    }

    /* CTA steam wisps — hidden by default; only animate under no-preference motion */
    .calmaeta-steam-wrap { position: relative; }
    .calmaeta-steam { position: absolute; left: 0; right: 0; bottom: 100%; height: 0; pointer-events: none; overflow: visible; }
    .calmaeta-steam-line {
      position: absolute; bottom: 2px; opacity: 0;
      transform: translateX(-50%) translateY(2px) scaleY(0.75);
      transform-origin: bottom center;
    }
    .calmaeta-steam-line svg { display: block; filter: drop-shadow(0 0 1px rgba(35,31,32,0.22)); }
    @media (prefers-reduced-motion: no-preference) {
      .calmaeta-steam-wrap:hover .calmaeta-steam-line-1 { animation: calmaetaSteam 1.6s ease-in-out infinite; }
      .calmaeta-steam-wrap:hover .calmaeta-steam-line-2 { animation: calmaetaSteam 1.9s ease-in-out infinite 0.35s; }
      .calmaeta-steam-wrap:hover .calmaeta-steam-line-3 { animation: calmaetaSteam 1.7s ease-in-out infinite 0.7s; }
    }
    @keyframes calmaetaSteam {
      0%   { opacity: 0;    transform: translateX(-50%) translateY(2px)   scaleY(0.75); }
      25%  { opacity: 0.5;  transform: translateX(-50%) translateY(-8px)  scaleY(1); }
      100% { opacity: 0;    transform: translateX(-50%) translateY(-24px) scaleY(1.3); }
    }
  `;
  document.head.appendChild(styleEl);
}

// Minimal coffee-bean custom cursor — desktop pointer devices only, and only
// when the user hasn't asked for reduced motion. A small dark espresso-brown
// bean with a terracota crease, smooth-follows the pointer (high lerp factor
// so it stays responsive), and gently scales/tilts over clickable elements.
(function setupCoffeeCursor() {
  if (document.getElementById('calmaeta-cursor')) return;
  const isFinePointer = window.matchMedia && window.matchMedia('(hover: hover) and (pointer: fine)').matches;
  const reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  if (!isFinePointer || reduceMotion) return;

  function init() {
    const cursor = document.createElement('div');
    cursor.id = 'calmaeta-cursor';
    cursor.setAttribute('aria-hidden', 'true');
    cursor.innerHTML = `<img src="assets/images/coffee-bean-cursor.png" srcset="assets/images/coffee-bean-cursor.png 1x, assets/images/coffee-bean-cursor@2x.png 2x" width="22" height="22" style="display:block;width:100%;height:100%;object-fit:contain;" alt="" />`;
    cursor.style.cssText = `
      position: fixed; top: 0; left: 0; width: 22px; height: 22px;
      pointer-events: none; z-index: 99999; will-change: transform, opacity;
      transform: translate3d(-100px, -100px, 0) rotate(0deg) scale(1);
      transform-origin: 15% 15%;
      opacity: 0; transition: opacity 200ms ease, transform 140ms ease-out;
    `;
    document.body.appendChild(cursor);
    document.body.classList.add('calmaeta-cursor-active');

    // The new pointer-style bean artwork has its tip — the actual point of contact,
    // like a normal arrow cursor's hotspot — near the top-left of the frame rather
    // than dead-center, so the offset below aligns THAT tip with the real pointer
    // position instead of centering the whole 22px box on it.
    const TIP_OFFSET = 3;
    let mouseX = -100, mouseY = -100, curX = -100, curY = -100, shown = false, hoveringClickable = false;

    window.addEventListener('mousemove', (e) => {
      mouseX = e.clientX; mouseY = e.clientY;
      if (!shown) { curX = mouseX; curY = mouseY; shown = true; cursor.style.opacity = '1'; }
    }, { passive: true });

    document.addEventListener('mouseover', (e) => {
      const t = e.target;
      hoveringClickable = !!(t && t.closest && t.closest('a, button, input, textarea, select, [role="button"], .calmaeta-cursor-hover'));
    }, { passive: true });

    document.addEventListener('mouseleave', () => { cursor.style.opacity = '0'; shown = false; });

    function raf() {
      const lerp = 0.35; // smooth-follow but responsive, not laggy
      curX += (mouseX - curX) * lerp;
      curY += (mouseY - curY) * lerp;
      const scale = hoveringClickable ? 1.35 : 1;
      const rotate = hoveringClickable ? -14 : 0;
      cursor.style.transform = `translate3d(${(curX - TIP_OFFSET).toFixed(1)}px, ${(curY - TIP_OFFSET).toFixed(1)}px, 0) rotate(${rotate}deg) scale(${scale})`;
      requestAnimationFrame(raf);
    }
    requestAnimationFrame(raf);
  }

  if (document.body) init();
  else document.addEventListener('DOMContentLoaded', init);
})();

function usePhotoMotion(strength = 10) {
  const [hov, setHov] = React.useState(false);
  const [tilt, setTilt] = React.useState({ x: 0, y: 0 });
  const floatDur = React.useRef(5200 + Math.round(Math.random() * 2600)).current;
  const floatDelay = React.useRef(-Math.round(Math.random() * 4000)).current;

  const onMouseMove = (e) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const px = (e.clientX - rect.left) / rect.width - 0.5;
    const py = (e.clientY - rect.top) / rect.height - 0.5;
    setTilt({ x: px, y: py });
  };
  const onMouseEnter = () => setHov(true);
  const onMouseLeave = () => { setHov(false); setTilt({ x: 0, y: 0 }); };

  // Layer 1 (float): a plain CSS keyframe animation on `transform` and NOTHING
  // else ever touches this element's transform — so the bob is always smooth,
  // continuous, and never collides with a transition.
  const floatStyle = prefersReducedMotion() ? {} : {
    animation: `calmaetaFloat ${floatDur}ms ease-in-out infinite`,
    animationDelay: `${floatDelay}ms`,
  };
  // Layer 2 (cursor-lean + hover "enlarge"): a plain inline transform driven by
  // React state, smoothed by a CSS transition — kept on a SEPARATE element from
  // the float animation above so the two motions never fight over `transform`
  // (that fight is what previously froze the float and caused hover to snap).
  const frameTransform = (hoverScale) => {
    const scale = hov ? hoverScale : 1;
    return `scale(${scale}) translate(${(-tilt.x * strength).toFixed(2)}px, ${(-tilt.y * strength).toFixed(2)}px)`;
  };

  return { floatStyle, frameTransform, handlers: { onMouseMove, onMouseEnter, onMouseLeave } };
}

function Button({ children, variant='primary', size='md', disabled=false, fullWidth=false, onClick, href, style: extra, steam=false }) {
  const [hov, setHov] = React.useState(false);
  const sz = { sm:{ fontSize:'11px', padding:'8px 16px' }, md:{ fontSize:'11px', padding:'12px 24px' }, lg:{ fontSize:'13px', padding:'16px 32px' } }[size] || {};
  const v = {
    primary:   { background: hov?'#002d7a':'#003da5', color:'#fff' },
    warm:      { background: hov?'#9a3821':'#bd472a', color:'#fff' },
    secondary: { background: hov?'#e8edf7':'transparent', color:'#003da5', border:'1.5px solid #003da5' },
    ghost:     { background: hov?'#eeeade':'transparent', color:'#231f20', border:'1.5px solid #e3ded4' },
    text:      { background:'transparent', color: hov?'#bd472a':'#003da5', padding:'0', letterSpacing:'0.06em', fontSize:'13px' },
  }[variant] || {};
  const base = {
    display:'inline-flex', alignItems:'center', justifyContent:'center',
    fontFamily:'var(--font-primary)', fontWeight:600, letterSpacing:'0.14em',
    textTransform:'uppercase', textDecoration:'none', border:'none',
    cursor: disabled?'not-allowed':'pointer', borderRadius:'4px',
    lineHeight:1, whiteSpace:'nowrap',
    transition:'background 150ms ease, color 150ms ease, transform 150ms ease',
    opacity: disabled?0.45:1,
    transform: hov&&!disabled?'translateY(-1px)':'none',
    width: fullWidth?'100%':undefined,
    boxSizing:'border-box',
    ...sz, ...v, ...extra,
  };
  const ev = { onMouseEnter:()=>setHov(true), onMouseLeave:()=>setHov(false) };
  const el = href
    ? <a href={href} target={href.startsWith('http')?'_blank':undefined} rel={href.startsWith('http')?'noreferrer':undefined} style={base} {...ev}>{children}</a>
    : <button onClick={onClick} disabled={disabled} style={base} {...ev}>{children}</button>;

  if (!steam) return el;

  // Subtle rising steam wisps above the button on hover — a small coffee-inspired
  // detail for primary CTAs. Purely decorative (aria-hidden), CSS-driven, and
  // gated on prefers-reduced-motion via the injected stylesheet.
  return (
    <span className="calmaeta-steam-wrap" style={{ position:'relative', display: fullWidth?'block':'inline-block' }}>
      {el}
      <span className="calmaeta-steam" aria-hidden="true">
        <span className="calmaeta-steam-line calmaeta-steam-line-1" style={{ left:'34%' }}>
          <svg width="8" height="22" viewBox="0 0 8 22"><path d="M4 22C6 17 2 14 4 10C6 6 2 3 4 0" stroke="var(--color-terracota)" strokeWidth="1.3" strokeLinecap="round" fill="none" /></svg>
        </span>
        <span className="calmaeta-steam-line calmaeta-steam-line-2" style={{ left:'50%' }}>
          <svg width="7" height="26" viewBox="0 0 7 26"><path d="M3.5 26C5.5 20 1.5 17 3.5 12C5.5 7 1.5 4 3.5 0" stroke="var(--color-terracota)" strokeWidth="1.2" strokeLinecap="round" fill="none" /></svg>
        </span>
        <span className="calmaeta-steam-line calmaeta-steam-line-3" style={{ left:'66%' }}>
          <svg width="8" height="20" viewBox="0 0 8 20"><path d="M4 20C6 15 2 12 4 8C6 4 2 2 4 0" stroke="var(--color-terracota)" strokeWidth="1.3" strokeLinecap="round" fill="none" /></svg>
        </span>
      </span>
    </span>
  );
}

function Badge({ children, color='muted', style: extra }) {
  const c = ({
    azul:      { bg:'#e8edf7', fg:'#002d7a' },
    terracota: { bg:'#f7ebe7', fg:'#9a3821' },
    negro:     { bg:'#231f20', fg:'#f8f7f2' },
    muted:     { bg:'#ede9e1', fg:'#6b6468' },
  })[color] || { bg:'#ede9e1', fg:'#6b6468' };
  return (
    <span style={{ display:'inline-flex', alignItems:'center', fontFamily:'var(--font-primary)', fontSize:'10px', fontWeight:600, letterSpacing:'0.12em', textTransform:'uppercase', lineHeight:1, padding:'4px 10px', borderRadius:'9999px', background:c.bg, color:c.fg, whiteSpace:'nowrap', ...extra }}>
      {children}
    </span>
  );
}

function Tag({ children, active=false, onClick }) {
  const [hov, setHov] = React.useState(false);
  const on = active || (hov && !!onClick);
  return (
    <span
      onClick={onClick}
      onMouseEnter={()=>setHov(true)}
      onMouseLeave={()=>setHov(false)}
      style={{ display:'inline-flex', alignItems:'center', fontFamily:'var(--font-primary)', fontSize:'10px', fontWeight: on?600:500, letterSpacing:'0.2em', textTransform:'uppercase', lineHeight:1, padding:'6px 14px', borderRadius:'9999px', border:'1px solid', borderColor: on?'#bd472a':'#e3ded4', background: on?'#f7ebe7':'transparent', color: on?'#9a3821':'#6b6468', cursor: onClick?'pointer':'default', transition:'all 150ms ease', userSelect:'none' }}
    >{children}</span>
  );
}

function MenuItem({ name, description, price, badge, divider=true }) {
  return (
    <div>
      <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between', gap:'16px', padding:'16px 0' }}>
        <div style={{ flex:1, display:'flex', flexDirection:'column', gap:'4px' }}>
          <div style={{ display:'flex', alignItems:'center', gap:'10px', flexWrap:'wrap' }}>
            <span style={{ fontFamily:'var(--font-primary)', fontSize:'16px', fontWeight:600, color:'#231f20', lineHeight:1.15 }}>{name}</span>
            {badge && <span style={{ fontFamily:'var(--font-primary)', fontSize:'10px', fontWeight:600, letterSpacing:'0.12em', textTransform:'uppercase', padding:'2px 8px', borderRadius:'9999px', background:'#f7ebe7', color:'#9a3821' }}>{badge}</span>}
          </div>
          {description && <span style={{ fontFamily:'var(--font-primary)', fontSize:'13px', fontWeight:300, color:'#6b6468', lineHeight:1.55 }}>{description}</span>}
        </div>
        {price && <span style={{ fontFamily:'var(--font-primary)', fontSize:'18px', fontWeight:300, color:'#231f20', whiteSpace:'nowrap' }}>{price}</span>}
      </div>
      {divider && <div style={{ height:'1px', background:'#e3ded4' }} />}
    </div>
  );
}

function Input({ label, placeholder, type='text', hint, error, disabled=false, defaultValue, id, style: extra }) {
  const [focused, setFocused] = React.useState(false);
  const inputId = id || (label ? label.toLowerCase().replace(/\s+/g,'-') : undefined);
  const borderColor = error?'#bd472a': focused?'#003da5':'#e3ded4';
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:'6px', ...extra }}>
      {label && <label htmlFor={inputId} style={{ fontFamily:'var(--font-primary)', fontSize:'10px', fontWeight:600, letterSpacing:'0.12em', textTransform:'uppercase', color: error?'#bd472a':'#6b6468' }}>{label}</label>}
      <input
        id={inputId} type={type} placeholder={placeholder} defaultValue={defaultValue}
        disabled={disabled} onFocus={()=>setFocused(true)} onBlur={()=>setFocused(false)}
        style={{ fontFamily:'var(--font-primary)', fontSize:'16px', fontWeight:400, color:'#231f20', background: disabled?'#e7dcc3':'var(--color-bg-card)', border:`1.5px solid ${borderColor}`, borderRadius:'6px', padding:'12px 16px', outline:'none', width:'100%', boxSizing:'border-box', opacity: disabled?0.6:1, transition:'border-color 150ms ease' }}
      />
      {(hint||error) && <span style={{ fontFamily:'var(--font-primary)', fontSize:'13px', color: error?'#bd472a':'#6b6468' }}>{error||hint}</span>}
    </div>
  );
}

// Decorative open-ring arc — an abstraction of the swirl in the Calmaeta mark.
// Used sparingly as a graphic accent behind photos and section headings.
function SwirlArc({ size = 280, color = 'var(--color-terracota)', strokeWidth = 28, rotate = 0, arc = 0.72, style: extra, className }) {
  const r = (size - strokeWidth) / 2;
  const circumference = 2 * Math.PI * r;
  const dash = circumference * arc;
  const gap = circumference - dash;
  // display:'block' is only a default — skip it when a className is given so a
  // responsive class (e.g. hiding this decorative arc on mobile) can own `display`
  // itself without an inline value fighting it.
  const base = className ? {} : { display: 'block' };
  return (
    <svg className={className} width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ ...base, overflow: 'visible', transform: `rotate(${rotate}deg)`, ...extra }}>
      <circle
        cx={size / 2} cy={size / 2} r={r}
        fill="none" stroke={color} strokeWidth={strokeWidth}
        strokeDasharray={`${dash} ${gap}`} strokeLinecap="round"
      />
    </svg>
  );
}

// Photo masked into an arch (doorway) shape — the site's signature "bold geometric" photo frame.
// The outer box floats idly; the whole masked frame (shape + shadow + photo together)
// leans away from the cursor on hover — the element moves, not just the image inside it.
function ArchFrame({ src, alt = '', archDepth = 0.22, style: extra, imgStyle }) {
  const v = Math.round(archDepth * 100);
  const { floatStyle, frameTransform, handlers } = usePhotoMotion(14);
  const { boxShadow, ...outerExtra } = extra || {};
  return (
    <div style={{ ...outerExtra, position: (extra && extra.position) || 'relative' }}>
      <div style={{ width: '100%', height: '100%', willChange: 'transform', ...floatStyle }}>
        <div
          {...handlers}
          style={{
            position: 'relative', width: '100%', height: '100%', overflow: 'hidden',
            borderRadius: `50% 50% 0 0 / ${v}% ${v}% 0 0`,
            boxShadow: boxShadow || undefined,
            transform: frameTransform(1.035),
            transition: 'transform 450ms cubic-bezier(0.16,1,0.3,1)',
            willChange: 'transform',
          }}>
          {/* Slightly oversized so subpixel rounding during float/hover animation
              can never expose a hairline of background at the clip edge. */}
          <img src={src} alt={alt} style={{ position: 'absolute', top: '-1px', left: '-1px', width: 'calc(100% + 2px)', height: 'calc(100% + 2px)', objectFit: 'cover', display: 'block', ...imgStyle }} />
        </div>
      </div>
    </div>
  );
}

// Photo masked into a circle — used for founder portraits and small detail shots.
function CircleFrame({ src, alt = '', size = 280, style: extra, className, fluid = false }) {
  const strength = Math.min(14, size * 0.05);
  const { floatStyle, frameTransform, handlers } = usePhotoMotion(strength);
  const { boxShadow, ...outerExtra } = extra || {};
  // fluid: let a responsive CSS class own width/height instead of the fixed
  // `size` value, while `size` still drives the motion-physics math above.
  const dims = fluid ? {} : { width: size, height: size };
  return (
    <div className={className} style={{ ...dims, flexShrink: 0, ...outerExtra, position: (extra && extra.position) || 'relative' }}>
      <div style={{ width: '100%', height: '100%', willChange: 'transform', ...floatStyle }}>
        <div
          {...handlers}
          style={{
            position: 'relative', width: '100%', height: '100%',
            borderRadius: '50%', overflow: 'hidden',
            boxShadow: boxShadow || undefined,
            transform: frameTransform(1.045),
            transition: 'transform 400ms cubic-bezier(0.16,1,0.3,1)',
            willChange: 'transform',
          }}
        >
          <img src={src} alt={alt} style={{ position: 'absolute', top: '-1px', left: '-1px', width: 'calc(100% + 2px)', height: 'calc(100% + 2px)', objectFit: 'cover', display: 'block' }} />
        </div>
      </div>
    </div>
  );
}

// Wraps children and fades/slides them into place on mount — a lightweight entrance
// flourish. Visibility is guaranteed by a plain CSS rule (`.calmaeta-reveal { opacity:1 }`);
// the animation itself is a pure-CSS `@keyframes` enhancement layered on top via
// `animation-fill-mode: both`, so it never depends on React state or JS timing —
// content can't get stuck invisible even if the animation never fires.
function Reveal({ children, delay = 0, y = 28, style: extra, as = 'div', className }) {
  const Tag = as;
  return (
    <Tag
      className={className ? `calmaeta-reveal ${className}` : 'calmaeta-reveal'}
      style={{
        '--reveal-delay': `${delay}ms`,
        '--reveal-y': `${y}px`,
        ...extra,
      }}
    >
      {children}
    </Tag>
  );
}

// Plain rectangular photo with the same hover-lean treatment as ArchFrame/CircleFrame,
// for spots that don't need arch/circle masking (gallery tiles, detail shots).
function HoverImage({ src, alt = '', style: extra, imgStyle }) {
  const { floatStyle, frameTransform, handlers } = usePhotoMotion(14);
  const { borderRadius, boxShadow, ...outerExtra } = extra || {};
  return (
    <div style={{ ...outerExtra, position: (extra && extra.position) || 'relative' }}>
      <div style={{ width: '100%', height: '100%', willChange: 'transform', ...floatStyle }}>
        <div
          {...handlers}
          style={{
            position: 'relative', width: '100%', height: '100%',
            overflow: 'hidden', borderRadius: borderRadius || 0,
            boxShadow: boxShadow || undefined,
            transform: frameTransform(1.045),
            transition: 'transform 400ms cubic-bezier(0.16,1,0.3,1)',
            willChange: 'transform',
          }}
        >
          <img src={src} alt={alt} style={{ position: 'absolute', top: '-1px', left: '-1px', width: 'calc(100% + 2px)', height: 'calc(100% + 2px)', objectFit: 'cover', display: 'block', ...imgStyle }} />
        </div>
      </div>
    </div>
  );
}

// Minimal auto-advancing photo carousel — one photo visible at a time (crossfade)
// plus small dot navigation, so a whole set of photos can live in a compact
// space without feeling busy. Pauses on hover and respects reduced-motion.
function Carousel({ images, alt = '', interval = 4200, style: extra }) {
  const [idx, setIdx] = React.useState(0);
  const [hover, setHover] = React.useState(false);

  React.useEffect(() => {
    if (prefersReducedMotion() || hover || images.length < 2) return;
    const t = setInterval(() => setIdx(i => (i + 1) % images.length), interval);
    return () => clearInterval(t);
  }, [hover, images.length, interval]);

  return (
    <div
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{ position: 'relative', width: '100%', height: '100%', overflow: 'hidden', background: 'var(--color-perla-dark)', ...extra }}
    >
      {images.map((src, i) => (
        <div key={src} style={{ position: 'absolute', inset: 0, opacity: i === idx ? 1 : 0, transition: 'opacity 700ms ease' }}>
          <img src={src} alt="" aria-hidden="true" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', filter: 'blur(24px) saturate(1.1) brightness(0.9)', transform: 'scale(1.15)' }} />
          <img src={src} alt={i === idx ? alt : ''} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'contain' }} />
        </div>
      ))}
      {images.length > 1 && (
        <React.Fragment>
          <button
            onClick={(e) => { e.stopPropagation(); setIdx(i => (i - 1 + images.length) % images.length); }}
            aria-label="Foto anterior"
            style={{ position: 'absolute', top: '50%', left: '14px', transform: 'translateY(-50%)', width: '36px', height: '36px', borderRadius: '9999px', border: 'none', background: 'rgba(35,31,32,0.35)', color: '#fff', fontSize: '16px', lineHeight: 1, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
          >‹</button>
          <button
            onClick={(e) => { e.stopPropagation(); setIdx(i => (i + 1) % images.length); }}
            aria-label="Foto siguiente"
            style={{ position: 'absolute', top: '50%', right: '14px', transform: 'translateY(-50%)', width: '36px', height: '36px', borderRadius: '9999px', border: 'none', background: 'rgba(35,31,32,0.35)', color: '#fff', fontSize: '16px', lineHeight: 1, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
          >›</button>
          <div style={{ position: 'absolute', bottom: '10px', left: 0, right: 0, display: 'flex', justifyContent: 'center', gap: '5px' }}>
            {images.map((_, i) => (
              <button
                key={i} onClick={(e) => { e.stopPropagation(); setIdx(i); }} aria-label={`Foto ${i + 1}`}
                style={{ width: i === idx ? '14px' : '5px', height: '5px', borderRadius: '9999px', border: 'none', padding: 0, background: i === idx ? '#fff' : 'rgba(255,255,255,0.55)', cursor: 'pointer', transition: 'width 250ms ease' }}
              />
            ))}
          </div>
        </React.Fragment>
      )}
    </div>
  );
}

Object.assign(window, { Button, Badge, Tag, MenuItem, Input, SwirlArc, ArchFrame, CircleFrame, Reveal, HoverImage, Carousel });
