// UI atoms for Xybos landing — Nocturne direction.
// Pill, Button, Container, Section header, Stars, Avatar stack, glow card,
// inline icons. All consume CSS custom properties defined in xybos-landing.html.

const { useState, useEffect } = React;

// ─── Layout ──────────────────────────────────────────────────
function Container({ children, style, max = 1240, className = '' }) {
  return (
    <div className={className} style={{ maxWidth: max, margin: '0 auto', padding: '0 32px', ...style }}>
      {children}
    </div>
  );
}

function Section({ children, id, style, className = '' }) {
  return (
    <section id={id} className={className} style={{ padding: '120px 0', position: 'relative', ...style }}>
      {children}
    </section>
  );
}

// Eyebrow pill — "[ 01 · SECTION TITLE ]" style
function Pill({ children, dot = true, accent = false }) {
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 8,
      padding: '6px 14px', borderRadius: 999,
      background: accent ? 'rgba(30,107,255,.10)' : 'rgba(255,255,255,.04)',
      border: accent ? '1px solid rgba(30,107,255,.4)' : '1px solid var(--line)',
      fontFamily: 'var(--mono)', fontSize: 11, color: accent ? '#9FBFFF' : 'rgba(255,255,255,.72)',
      letterSpacing: 0.6, fontWeight: 500, textTransform: 'uppercase', whiteSpace: 'nowrap',
    }}>
      {dot && <span style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--blue)', boxShadow: '0 0 12px var(--blue)' }} />}
      {children}
    </div>
  );
}

// Section header — eyebrow + h2 + (optional) tagline
function SectionHeader({ eyebrow, title, tagline, align = 'left', children, max = 720, total = 4 }) {
  // Pull the section number out of "[ 02 · …" — used for the counter chip.
  const m = typeof eyebrow === 'string' ? eyebrow.match(/\b(\d{2})\b/) : null;
  const num = m ? m[1] : null;
  const tot = String(total).padStart(2, '0');

  return (
    <div style={{ textAlign: align, maxWidth: align === 'center' ? max : 880, margin: align === 'center' ? '0 auto' : '0', position: 'relative' }}>
      {eyebrow && (
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 22 }}>
          <Pill>{eyebrow}</Pill>
          {num && align !== 'center' && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, fontFamily: 'var(--mono)', fontSize: 11, color: 'rgba(255,255,255,.4)', letterSpacing: 0.6 }}>
              <span style={{ width: 28, height: 1, background: 'var(--line)' }} />
              <span className="xy-section-counter"><span style={{ color: '#9FBFFF' }}>{num}</span> / {tot}</span>
            </div>
          )}
        </div>
      )}
      <h2 style={{
        fontSize: 'clamp(40px, 5vw, 64px)', fontWeight: 600, letterSpacing: -1.8,
        lineHeight: 1.04, margin: 0, color: '#fff',
        position: 'relative', paddingLeft: align === 'left' ? 18 : 0,
      }}>
        {align === 'left' && (
          <span aria-hidden style={{
            position: 'absolute', left: 0, top: 12, bottom: 12,
            width: 3, borderRadius: 2,
            background: 'linear-gradient(180deg, var(--blue-bright), var(--blue) 60%, transparent)',
            boxShadow: '0 0 12px rgba(30,107,255,.6)',
          }} />
        )}
        {title}
      </h2>
      {tagline && (
        <p style={{
          fontSize: 18, color: 'rgba(255,255,255,.55)', lineHeight: 1.55,
          margin: '20px 0 0', maxWidth: max, marginLeft: align === 'center' ? 'auto' : 0, marginRight: align === 'center' ? 'auto' : 0,
        }}>{tagline}</p>
      )}
      {children}
    </div>
  );
}

// ─── Buttons ─────────────────────────────────────────────────
function Btn({ children, variant = 'primary', size = 'md', as = 'button', href, onClick, icon, style: extra }) {
  const sizes = {
    sm: { padding: '8px 14px', fontSize: 13, gap: 6 },
    md: { padding: '12px 20px', fontSize: 14, gap: 8 },
    lg: { padding: '15px 26px', fontSize: 15, gap: 10 },
  };
  const variants = {
    primary: { background: 'var(--blue)', color: '#fff', border: 'none', boxShadow: '0 0 24px var(--blue-glow)' },
    secondary: { background: 'rgba(255,255,255,.05)', color: '#fff', border: '1px solid rgba(255,255,255,.12)' },
    ghost: { background: 'transparent', color: 'rgba(255,255,255,.85)', border: 'none' },
  };
  const base = {
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
    fontFamily: 'var(--sans)', fontWeight: 500, letterSpacing: -0.1,
    borderRadius: 10, cursor: 'pointer', transition: 'transform .15s, box-shadow .15s, background .15s',
    whiteSpace: 'nowrap',
  };
  const props = { onClick, style: { ...base, ...sizes[size], ...variants[variant], ...extra } };
  const C = as === 'a' ? 'a' : 'button';
  return (
    <C {...(C === 'a' ? { href } : {})} {...props}>
      {children}
      {icon && <Arrow size={size === 'lg' ? 16 : 14} />}
    </C>
  );
}

function Arrow({ size = 14 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M5 12h14M13 6l6 6-6 6" />
    </svg>
  );
}

// ─── Logo ────────────────────────────────────────────────────
// Both source PNGs are 282px tall, so display them at equal heights.
function Logo({ height = 36, glow = true }) {
  return (
    <a href="#" style={{ display: 'inline-flex', alignItems: 'center', gap: 10 }}>
      <img src="assets/xybos-mark.png" alt="" draggable={false}
        style={{ height, width: 'auto', filter: glow ? 'drop-shadow(0 0 14px rgba(30,107,255,.6))' : 'none' }} />
      <img src="assets/xybos-wordmark-white.png" alt="Xybos" draggable={false}
        style={{ height, width: 'auto' }} />
    </a>
  );
}

// ─── Stars + Avatar stack (social proof) ─────────────────────
function Stars({ count = 5, size = 14, color = '#FFB948' }) {
  return (
    <div style={{ display: 'inline-flex', gap: 2 }}>
      {Array.from({ length: count }, (_, i) => (
        <svg key={i} width={size} height={size} viewBox="0 0 16 16" fill={color}>
          <path d="M8 1l2.09 4.43L15 6.16l-3.5 3.5.83 5.06L8 12.27l-4.33 2.45.83-5.06L1 6.16l4.91-.73L8 1z" />
        </svg>
      ))}
    </div>
  );
}

const AVATAR_PALETTES = [
  ['#FFB948', '#FF7A2C'],
  ['#4DD3FF', '#1E6BFF'],
  ['#B488FF', '#7B3FE4'],
  ['#52E1A7', '#138F6B'],
  ['#FF7AB4', '#D43F90'],
  ['#9DB9FF', '#3B5BC4'],
];

function Avatar({ initials, palette = 0, size = 36, ringColor = 'var(--void)', ring = 2 }) {
  const [a, b] = AVATAR_PALETTES[palette % AVATAR_PALETTES.length];
  return (
    <div style={{
      width: size, height: size, borderRadius: 999,
      background: `linear-gradient(135deg, ${a}, ${b})`,
      border: `${ring}px solid ${ringColor}`,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      color: '#fff', fontWeight: 600, fontSize: size * 0.36, letterSpacing: -0.4,
      flexShrink: 0,
    }}>{initials}</div>
  );
}

function AvatarStack({ people, size = 32 }) {
  return (
    <div style={{ display: 'inline-flex' }}>
      {people.map((p, i) => (
        <div key={i} style={{ marginLeft: i ? -size * 0.32 : 0, zIndex: people.length - i }}>
          <Avatar initials={p.i} palette={p.p ?? i} size={size} />
        </div>
      ))}
    </div>
  );
}

// ─── Inline icons (24px, 1.6 stroke) ─────────────────────────
const ICONS = {
  bolt:     <path d="M13 2L4 14h7l-1 8 9-12h-7l1-8z" />,
  cube:     <><path d="M12 3l9 5v8l-9 5-9-5V8l9-5z" /><path d="M3 8l9 5 9-5M12 13v10" /></>,
  flow:     <><circle cx="5" cy="6" r="2.5" /><circle cx="19" cy="6" r="2.5" /><circle cx="12" cy="18" r="2.5" /><path d="M7 7l3.5 9M17 7l-3.5 9" /></>,
  chart:    <path d="M4 20V8M10 20V4M16 20v-8M22 20H2" />,
  brain:    <path d="M9 4a4 4 0 00-4 4v2a3 3 0 000 6 4 4 0 004 4M15 4a4 4 0 014 4v2a3 3 0 010 6 4 4 0 01-4 4M9 4v16M15 4v16" />,
  api:      <path d="M3 12h4l2-3 4 6 2-3h6" />,
  search:   <><circle cx="11" cy="11" r="6" /><path d="M20 20l-4.5-4.5" /></>,
  shield:   <path d="M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6l8-3z" />,
  database: <><ellipse cx="12" cy="5" rx="8" ry="3" /><path d="M4 5v14c0 1.5 3.5 3 8 3s8-1.5 8-3V5M4 12c0 1.5 3.5 3 8 3s8-1.5 8-3" /></>,
  spark:    <path d="M12 2v6M12 16v6M2 12h6M16 12h6M5 5l4 4M15 15l4 4M19 5l-4 4M9 15l-4 4" />,
  arrow:    <path d="M5 12h14M13 6l6 6-6 6" />,
  check:    <path d="M5 12l5 5 9-11" />,
  plus:     <path d="M12 5v14M5 12h14" />,
  minus:    <path d="M5 12h14" />,
  chev:     <path d="M6 9l6 6 6-6" />,
  globe:    <><circle cx="12" cy="12" r="9" /><path d="M3 12h18M12 3a14 14 0 010 18M12 3a14 14 0 000 18" /></>,
  clock:    <><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></>,
};

function Icon({ name, size = 22, stroke = 1.6, color = 'currentColor' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke={color} strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round">
      {ICONS[name]}
    </svg>
  );
}

// ─── Glow card (used for services, work) ─────────────────────
function GlowCard({ children, style, hoverable = true, className = '' }) {
  const cls = [hoverable ? 'glow-card' : '', className].filter(Boolean).join(' ');
  return (
    <div className={cls} style={{
      background: 'linear-gradient(180deg, rgba(255,255,255,.025), rgba(255,255,255,.005))',
      border: '1px solid var(--line)',
      borderRadius: 18, padding: 32, position: 'relative', overflow: 'hidden',
      transition: 'border-color .25s, transform .25s, box-shadow .25s',
      ...style,
    }}>
      {children}
    </div>
  );
}

// Hairline divider with optional eyebrow
function Hairline({ children }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 16, color: 'rgba(255,255,255,.45)' }}>
      <div style={{ flex: 1, height: 1, background: 'var(--line)' }} />
      {children && <div style={{ fontFamily: 'var(--mono)', fontSize: 11, textTransform: 'uppercase', letterSpacing: 0.6 }}>{children}</div>}
      <div style={{ flex: 1, height: 1, background: 'var(--line)' }} />
    </div>
  );
}

// Inject hover styles once
if (typeof document !== 'undefined' && !document.getElementById('xy-hover')) {
  const s = document.createElement('style');
  s.id = 'xy-hover';
  s.textContent = `
    .glow-card:hover { border-color: rgba(30,107,255,.4) !important; box-shadow: 0 0 0 1px rgba(30,107,255,.2), 0 24px 60px rgba(30,107,255,.12); transform: translateY(-3px); }
    .glow-card { transition: border-color .3s cubic-bezier(.2,.7,.3,1), box-shadow .3s cubic-bezier(.2,.7,.3,1), transform .3s cubic-bezier(.2,.7,.3,1); }

    /* Nav link underline reveal */
    .nav-link { position: relative; }
    .nav-link::after { content:''; position:absolute; left:0; right:100%; bottom:-6px; height:1px; background: linear-gradient(90deg, var(--blue-bright), transparent); transition: right .35s cubic-bezier(.2,.7,.3,1), background .25s; }
    .nav-link:hover { color: #fff !important; }
    .nav-link:hover::after { right: 0; }

    /* Primary button — lift + glow grow on hover */
    .btn-primary { transition: background .2s, box-shadow .25s, transform .25s cubic-bezier(.2,.7,.3,1); }
    .btn-primary:hover { background: var(--blue-bright) !important; box-shadow: 0 0 42px rgba(30,107,255,.65) !important; transform: translateY(-1px); }

    .faq-item summary::-webkit-details-marker { display: none; }

    /* Editorial row hovers — Work (basic slide) ── Process gets its own block below */
    .work-row {
      transition: background .3s cubic-bezier(.2,.7,.3,1), transform .35s cubic-bezier(.2,.7,.3,1);
      will-change: transform;
    }
    .work-row:hover { background: linear-gradient(90deg, rgba(30,107,255,.08), transparent 65%); transform: translateX(14px); }
    .work-row:hover .work-swatch { width: 80px !important; height: 80px !important; }
    .work-row:hover .work-arrow  { color: var(--blue-bright) !important; transform: translateX(6px); }

    /* ── Process row hover — multi-layer editorial response ─────────────── */
    .process-row {
      position: relative;
      overflow: hidden;
      transition: background .55s cubic-bezier(.2,.7,.3,1);
    }
    /* Subtle bg wash on hover */
    .process-row:hover {
      background: linear-gradient(90deg, rgba(30,107,255,.09) 0%, rgba(30,107,255,.035) 38%, transparent 78%);
    }
    /* Left edge accent bar — grows vertically from center */
    .process-row .pr-edge {
      position: absolute; left: 0; top: 50%;
      width: 2px; height: 0; transform: translateY(-50%);
      background: linear-gradient(180deg, transparent, var(--blue-bright) 18%, var(--blue) 82%, transparent);
      box-shadow: 0 0 14px rgba(30,107,255,.55);
      opacity: 0; pointer-events: none;
      transition: height .6s cubic-bezier(.2,.7,.3,1), opacity .35s cubic-bezier(.2,.7,.3,1);
    }
    .process-row:hover .pr-edge { height: 72%; opacity: 1; }

    /* Numeric counter — color + glow + tighten + slight slide */
    .process-row .pr-num {
      transition: color .55s cubic-bezier(.2,.7,.3,1),
                  text-shadow .55s cubic-bezier(.2,.7,.3,1),
                  letter-spacing .55s cubic-bezier(.2,.7,.3,1),
                  transform .5s cubic-bezier(.2,.7,.3,1);
      transform-origin: left center; will-change: transform;
    }
    .process-row:hover .pr-num {
      color: #4D8BFF;
      text-shadow: 0 0 28px rgba(77,139,255,.45), 0 0 8px rgba(77,139,255,.3);
      letter-spacing: -2px;
      transform: translateX(10px) scale(1.04);
    }

    /* Title — subtle slide + animated underline */
    .process-row .pr-title {
      position: relative;
      transition: transform .45s cubic-bezier(.2,.7,.3,1), color .35s;
    }
    .process-row .pr-title::after {
      content: ''; position: absolute;
      left: 0; bottom: -8px; height: 1.5px; width: 0;
      background: linear-gradient(90deg, var(--blue-bright), transparent);
      transition: width .65s cubic-bezier(.2,.7,.3,1);
    }
    .process-row:hover .pr-title          { transform: translateX(6px); }
    .process-row:hover .pr-title::after   { width: 64%; }

    /* Body — brighten + nudge */
    .process-row .pr-body {
      transition: color .55s cubic-bezier(.2,.7,.3,1), transform .55s cubic-bezier(.2,.7,.3,1);
    }
    .process-row:hover .pr-body {
      color: rgba(255,255,255,.82);
      transform: translateX(4px);
    }

    /* Duration — pill background + glow + nudge left */
    .process-row .pr-dur {
      display: inline-block;
      padding: 5px 12px;
      border-radius: 999px;
      border: 1px solid transparent;
      background: rgba(255,255,255,0);
      transition: color .35s, background .45s cubic-bezier(.2,.7,.3,1),
                  border-color .35s, box-shadow .5s cubic-bezier(.2,.7,.3,1),
                  transform .45s cubic-bezier(.2,.7,.3,1);
    }
    .process-row:hover .pr-dur {
      color: #fff;
      background: rgba(30,107,255,.14);
      border-color: rgba(77,139,255,.45);
      box-shadow: 0 0 22px rgba(30,107,255,.30), inset 0 0 12px rgba(30,107,255,.08);
      transform: translateX(-4px);
    }

    /* Section-level reveal disabled — content reveal is handled per-card via
       [data-stagger] / .process-row, which gives one unified cascade animation
       instead of double-animating (section + cards). */
    .xy-reveal     {}
    .xy-reveal-in  {}

    /* ── Unified stagger reveal — apply data-stagger to any container with cards/rows.
       Each direct child rises + fades in with cascading delay. Works for any block.
       Cards retain their own hover state because we only animate opacity/transform.
       Long-form transition properties (not shorthand) so the nth-child transition-delay
       rules can override cleanly. !important needed on duration/timing/property because
       .glow-card sets a transition shorthand that would otherwise reset opacity transition. */
    [data-stagger] > * {
      opacity: 0; transform: translateY(28px);
      transition-property: opacity, transform !important;
      transition-duration: .9s, .9s !important;
      transition-timing-function: cubic-bezier(.2,.7,.3,1), cubic-bezier(.2,.7,.3,1) !important;
      transition-delay: 0s, 0s !important;
      will-change: transform, opacity;
    }
    [data-stagger].xy-stagger-in > *                     { opacity: 1; transform: none; }
    [data-stagger].xy-stagger-in > *:nth-child(1)        { transition-delay: .25s, .25s !important; }
    [data-stagger].xy-stagger-in > *:nth-child(2)        { transition-delay: .37s, .37s !important; }
    [data-stagger].xy-stagger-in > *:nth-child(3)        { transition-delay: .49s, .49s !important; }
    [data-stagger].xy-stagger-in > *:nth-child(4)        { transition-delay: .61s, .61s !important; }
    [data-stagger].xy-stagger-in > *:nth-child(5)        { transition-delay: .73s, .73s !important; }
    [data-stagger].xy-stagger-in > *:nth-child(6)        { transition-delay: .85s, .85s !important; }

    /* Section counter pulses softly so the [01/04] feels alive */
    @keyframes counterPulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
    .xy-section-counter { animation: counterPulse 3.6s ease-in-out infinite; }

    /* ── Process row scroll-reveal — cascade in when row enters viewport ── */
    /* .pr-edge is excluded so it doesn't take a slot in the stagger sequence */
    .process-row > *:not(.pr-edge) { opacity: 0; transform: translateY(14px); transition: opacity .72s cubic-bezier(.2,.7,.3,1), transform .72s cubic-bezier(.2,.7,.3,1); }
    .process-row > .pr-num { transform: translateX(-30px) scale(.6); transform-origin: left center; }
    .process-row-in > *:not(.pr-edge) { opacity: 1; transform: none; }
    .process-row-in > .pr-num   { transition-delay: .25s; }
    .process-row-in > .pr-title { transition-delay: .37s; }
    .process-row-in > .pr-body  { transition-delay: .49s; }
    .process-row-in > div:last-child { transition-delay: .61s; }
    .process-row::before {
      content: ''; position: absolute; left: 0; bottom: -1px; height: 1px;
      width: 0; background: linear-gradient(90deg, var(--blue-bright), transparent);
      transition: width .9s cubic-bezier(.2,.7,.3,1) .3s;
      pointer-events: none;
    }
    .process-row-in::before { width: 100%; }

    /* ── Mobile menu (hamburger + slide-in overlay) ─────────────────────── */
    /* Desktop default: overlay hidden, hamburger hidden, desktop nav/actions visible */
    .xy-menu { display: none; }
    .xy-burger { display: none !important; }

    @media (max-width: 900px) {
      .xy-burger          { display: inline-flex !important; }
      .xy-desktop-nav     { display: none !important; }
      .xy-desktop-actions { display: none !important; }
      /* On mobile reorder so logo appears on the right of the hamburger */
      .xy-header > div { justify-content: space-between !important; }
      .xy-header .xy-burger { order: 1; }
      .xy-header > div > a:first-of-type, .xy-header > div > .xy-logo { order: 2; margin-left: auto; }

      .xy-menu {
        display: block !important;
        position: fixed; top: 0; left: 0;
        width: 100vw; height: 100vh; height: 100dvh;
        z-index: 80;
        background: rgba(6,7,10,.72);
        backdrop-filter: blur(14px);
        opacity: 0; pointer-events: none;
        overflow: hidden;
        transition: opacity .35s cubic-bezier(.2,.7,.3,1);
      }
      .xy-menu.xy-menu-open { opacity: 1; pointer-events: auto; }

      .xy-menu-panel {
        position: absolute; top: 0; left: 0;
        width: min(420px, 100vw); height: 100%;
        display: flex; flex-direction: column;
        padding: 22px 24px 28px;
        background: linear-gradient(180deg, #0A0B0E 0%, #06070A 100%);
        border-right: 1px solid rgba(30,107,255,.18);
        transform: translateX(-100%);
        transition: transform .45s cubic-bezier(.2,.7,.3,1);
        overflow-y: auto;
        overscroll-behavior: contain;
      }
      .xy-menu-open .xy-menu-panel { transform: translateX(0); }

      .xy-menu-head { display: flex; align-items: center; justify-content: space-between; padding-bottom: 28px; border-bottom: 1px solid var(--line); margin-bottom: 12px; }
      .xy-menu-close {
        width: 40px; height: 40px; padding: 0; border-radius: 10px;
        background: rgba(255,255,255,.04); border: 1px solid var(--line);
        color: rgba(255,255,255,.75); cursor: pointer;
        display: flex; align-items: center; justify-content: center;
        transition: background .2s, color .2s, border-color .2s;
        font-family: inherit;
      }
      .xy-menu-close:hover, .xy-menu-close:active { color: #fff; background: rgba(30,107,255,.18); border-color: rgba(30,107,255,.5); }

      .xy-menu-nav { display: flex; flex-direction: column; gap: 0; flex: 1; }
      .xy-menu-nav a {
        display: flex; align-items: center; gap: 16px;
        padding: 22px 4px;
        border-bottom: 1px solid var(--line-soft);
        color: #fff; text-decoration: none;
        font-size: 22px; font-weight: 500; letter-spacing: -0.4px;
        transition: color .2s, transform .25s cubic-bezier(.2,.7,.3,1), padding-left .25s cubic-bezier(.2,.7,.3,1);
        opacity: 0; transform: translateY(12px);
      }
      .xy-menu-open .xy-menu-nav a {
        opacity: 1; transform: none;
        transition: opacity .5s cubic-bezier(.2,.7,.3,1) calc(.15s + var(--i, 0) * .06s),
                    transform .5s cubic-bezier(.2,.7,.3,1) calc(.15s + var(--i, 0) * .06s),
                    color .2s, padding-left .25s cubic-bezier(.2,.7,.3,1);
      }
      .xy-menu-nav a:hover, .xy-menu-nav a:active { color: #4D8BFF; padding-left: 8px; }
      .xy-menu-nav a:hover .xy-menu-arr, .xy-menu-nav a:active .xy-menu-arr { color: #4D8BFF; transform: translateX(4px); }
      .xy-menu-num { font-family: var(--mono); font-size: 11px; color: #9FBFFF; letter-spacing: 0.8px; width: 24px; }
      .xy-menu-lbl { flex: 1; }
      .xy-menu-arr { color: rgba(255,255,255,.35); transition: color .2s, transform .2s; }

      .xy-menu-foot {
        display: flex; flex-direction: column; gap: 14px; align-items: stretch;
        padding-top: 22px; border-top: 1px solid var(--line);
      }
      .xy-menu-foot > * { width: 100%; }
      .xy-menu-foot > .btn-primary, .xy-menu-foot > a.btn-primary { justify-content: center; padding: 14px 18px; font-size: 15px; }
      .xy-menu-foot > div:first-child { align-self: flex-start; }  /* lang toggle on its own row */
    }

    /* Service card tag — keep on one line if possible; break only at spaces, never mid-word */
    .service-tag { word-break: keep-all; overflow-wrap: normal; white-space: normal; }

    /* On narrow viewports the long LV tags wrap awkwardly next to the icon.
       Drop the tag to its own line below the icon, full width, left-aligned. */
    @media (max-width: 720px) {
      .service-tophead {
        flex-direction: column !important;
        align-items: flex-start !important;
        gap: 14px !important;
      }
      .service-tag {
        max-width: 100% !important;
        text-align: left !important;
      }
    }

    /* ── Mobile (general) ───────────────────────────────────────────────── */
    @media (max-width: 640px) {
      /* "Built by..." proof strip — drop the pill, stack as 2-line card with sans font */
      .proof-wrap { padding: 0 16px; }
      .proof-strip {
        display: flex !important;
        align-items: flex-start !important;
        gap: 12px !important;
        padding: 14px 18px !important;
        border-radius: 14px !important;
        background: rgba(10,11,14,.62) !important;
        box-shadow: 0 0 0 1px rgba(30,107,255,.10), 0 14px 40px rgba(0,0,0,.35);
        max-width: 360px; margin: 0 auto;
      }
      .proof-dot { margin-top: 7px; }
      .proof-text {
        font-family: var(--sans) !important;
        font-size: 13px !important;
        line-height: 1.45 !important;
        letter-spacing: -0.1px !important;
        text-align: left;
        color: rgba(255,255,255,.72) !important;
      }
      .proof-line { display: block; }
      .proof-line-1 { color: rgba(255,255,255,.92) !important; margin-bottom: 2px; }
      .proof-sep { display: none; }
    }

    @media (max-width: 900px) {
      section { padding: 64px 0 !important; }
      section#services > div > div:nth-child(2) { grid-template-columns: 1fr !important; }
      section#why     > div > div:last-child   { grid-template-columns: 1fr !important; }
      section#services > div > div:first-child,
      section#why      > div > div:first-child,
      section#process  > div > div:first-child { grid-template-columns: 1fr !important; gap: 32px !important; }
      .process-row { grid-template-columns: 1fr !important; gap: 8px !important; padding: 24px 8px !important; }
      .process-row > div:first-child { font-size: 36px !important; }
      .process-row > div:last-child  { text-align: left !important; }
      section#contact > div > div { padding: 40px 24px !important; }
      section#contact > div > div > div:last-child { grid-template-columns: 1fr !important; gap: 32px !important; }
      footer > div > div:first-child { grid-template-columns: 1fr !important; gap: 32px !important; margin-bottom: 32px !important; }
    }
    @media (max-width: 640px) {
      main > section:first-child { min-height: 720px !important; padding: 64px 0 48px !important; }
      .glow-card { padding: 24px !important; }
    }
  `;
  document.head.appendChild(s);
}

Object.assign(window, {
  Container, Section, Pill, SectionHeader,
  Btn, Arrow, Logo, Stars, Avatar, AvatarStack,
  Icon, GlowCard, Hairline,
});

// ─── Scroll reveal — sections fade-up as they enter the viewport ─────
function initScrollReveals() {
  const sections = document.querySelectorAll('section[id]');
  if (!sections.length) { requestAnimationFrame(initScrollReveals); return; }
  sections.forEach((s) => s.classList.add('xy-reveal'));
  const io = new IntersectionObserver((entries) => {
    entries.forEach((e) => {
      if (e.isIntersecting) { e.target.classList.add('xy-reveal-in'); io.unobserve(e.target); }
    });
  }, { rootMargin: '0px 0px -120px 0px', threshold: 0.05 });
  sections.forEach((s) => io.observe(s));

  // Process row stagger reveal — fires when the row is just entering the viewport
  // so the cascade plays out as the user is looking at it.
  const rows = document.querySelectorAll('.process-row');
  if (rows.length) {
    const io2 = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) { e.target.classList.add('process-row-in'); io2.unobserve(e.target); }
      });
    }, { rootMargin: '0px 0px -80px 0px', threshold: 0.2 });
    rows.forEach((r) => io2.observe(r));
  }

  // Unified stagger reveal — fires when the grid's top edge crosses just
  // past the viewport bottom, so cards animate in as soon as the user
  // first sees them (combined with a small CSS transition-delay below).
  const stagGroups = document.querySelectorAll('[data-stagger]');
  stagGroups.forEach((grp) => {
    const io4 = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          e.target.classList.add('xy-stagger-in');
          io4.unobserve(e.target);
        }
      });
    }, { rootMargin: '0px 0px -120px 0px', threshold: 0 });
    io4.observe(grp);
  });
}
if (typeof window !== 'undefined' && !window.__xy_reveal_init) {
  window.__xy_reveal_init = true;
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => requestAnimationFrame(initScrollReveals));
  } else {
    requestAnimationFrame(initScrollReveals);
  }
}
