/* SOLUTIONS — overview page + per-tier detail pages.
   Route:
     /solutions  → problem-based overview (Cost, Speed, Consistency,
                  Scale, Representation, Quality)
*/

/* ---------- Problems content ----------
   Six photography problems the studio solves. Sequence matches the sticky index. */

const SOLUTION_PROBLEMS = [
{
  id: 'cost',
  label: 'Cost',
  headline: <>Production costs<br /><em style={{ fontStyle: 'italic' }}>that don&rsquo;t scale with your range.</em></>, pain: 'The bill lands before the imagery does. Once committed, the budget is gone whether or not the brief still fits.',
  pains: [
  'Day rates and crew costs eat the season\u2019s image budget',
  'Reshoots and retouching push timelines and bills out',
  'Cost per image stays high no matter how many SKUs you ship'],

  answers: [
  'Per-image rates from £0.30, billed only on export',
  'No crew, no studio hire, no day rates \u2014 ever',
  'Forecast image spend as a line item, not an unknown'],

  plate: { src: 'assets/hero-model-chair.jpg', label: 'Studio \u00B7 4K', subject: 'no day rate', position: 'center 18%' }
},
{
  id: 'speed',
  label: 'Speed',
  headline: <>Sample to shelf,<br /><em style={{ fontStyle: 'italic' }}>in days, not months.</em></>,
  pain: 'Sampling lands. The shoot books eight weeks out. Edits land a fortnight after that. By the time the imagery is live, the trend has already moved.',
  pains: [
  'Studio bookings sit six to eight weeks out',
  'Retouching adds another fortnight at the back end',
  'Trends turn over faster than your shoot calendar'],

  answers: [
  'Generate finished frames in minutes, not months',
  'Approve direction, queue the batch, wake up to exports',
  'Ship new imagery the same week sampling lands'],

  plate: { src: 'assets/solutions-speed-car.jpg', label: 'Drop 02 \u00B7 4K', subject: 'live same week', position: 'center 30%' }
},
{
  id: 'consistency',
  label: 'Consistency',
  headline: <>One brand,<br /><em style={{ fontStyle: 'italic' }}>every channel.</em></>,
  pain: 'Different photographers, different days, different briefs — every shoot lands a little off the last. Across a full season the look drifts, until the catalogue no longer feels like one brand.',
  pains: [
  'Every shoot starts from a fresh brief and a fresh interpretation',
  'Lighting, casting, and styling shift from one shoot to the next',
  'Across campaign, website, and social, the brand stops looking like one brand'],

  answers: [
  'Define the look once, reuse it on every shoot',
  'Reuse the same digital twin on every shoot, every season',
  'Deliver every format \u2014 4:5, 16:9, 1:1, 9:16 \u2014 from a single frame'],

  plate: { src: 'assets/beauty-blue-shadow.jpg', label: 'Brand kit \u00B7 4K', subject: 'digital twin', position: 'center 30%' }
},
{
  id: 'scale',
  label: 'Scale',
  headline: <>Thousands of SKUs<br /><em style={{ fontStyle: 'italic' }}>in one day.</em></>,
  pain: 'A 1000 SKU range needs a thousand frames. Per garment. Per colourway. Per angle. Batch upload is how ViZO handles that volume without the storage solution, the marathon shoot block, or the six weeks the calendar doesn\u2019t have.',
  pains: [
  'Catalogue scale eats every minute of every shoot day',
  'Bulk volume forces compromise on direction and finish',
  'SKU-level photography rarely keeps up with stock'],

  answers: [
  'Batch upload queues up to 1000 tagged SKUs in a single overnight run',
  'Apply one-brief across the whole batch, no per-SKU setup',
  'Exports return organised by SKU, colourway, and view'],

  plate: { src: 'assets/solutions-scale-night.jpg', label: 'Batch \u00B7 20K', subject: 'overnight queue', position: 'center 30%' }
},
{
  id: 'representation',
  label: 'Representation',
  headline: <>Every body,<br /><em style={{ fontStyle: 'italic' }}>every customer.</em></>,
  pain: 'Modelling agencies have a roster. Their roster has a look. Casting wider means more day rates, more travel, more time \u2014 so the catalogue stays narrow whether you meant it to or not.',
  pains: [
  'Casting a wider array of models doubles or triples the day rate',
  'One roster rarely represents a global customer base',
  'True size and age diversity means more castings, days, and cost'],

  answers: [
  'Generate every age, gender, size, skin tone, and background',
  'Match real customers without booking ten castings',
  'Build an inclusive catalogue on a low budget'],

  plate: { src: 'assets/solutions-representation-knit.jpg', label: 'Cast \u00B7 open', subject: 'every body', position: 'center 30%' }
},
{
  id: 'quality',
  label: 'Quality',
  headline: <>Hold your own<br /><em style={{ fontStyle: 'italic' }}>next to the houses.</em></>,
  pain: 'A small brand looks small the moment its imagery doesn\u2019t measure up. Smartphone shots and home-studio backdrops sit next to brand-house campaigns.',
  pains: [
  'Great products lose ground when imagery can\u2019t match the majors',
  'Polished imagery costs more than your margin allows',
  'Investors and customers judge the brand on the imagery'],

  answers: [
  '2K or 4K finish on every export, no smartphone tells',
  'Editorial sets, real models, directed lighting',
  'Look like a fashion house, ship like a boutique'],

  plate: { src: 'assets/editorial-pink-curtains.jpg', label: 'Finish \u00B7 4K', subject: 'editorial', position: 'center 25%' }
}];


window.SOLUTION_PROBLEMS = SOLUTION_PROBLEMS;

/* ---------- Solutions overview page ---------- */
function SolutionsPage() {
  const [active, setActive] = React.useState(SOLUTION_PROBLEMS[0].id);

  // Scroll spy — anchor the active label to the section whose top has passed the strip.
  React.useEffect(() => {
    const onScroll = () => {
      const offset = 200; // approx: 72 nav + strip + breathing room
      let current = SOLUTION_PROBLEMS[0].id;
      for (const p of SOLUTION_PROBLEMS) {
        const el = document.getElementById(`problem-${p.id}`);
        if (!el) continue;
        const top = el.getBoundingClientRect().top;
        if (top - offset <= 0) current = p.id;
      }
      setActive(current);
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  return (
    <div data-screen-label="03 Solutions">
      <SolutionsHeader />
      <ProblemIndexStrip active={active} />
      {SOLUTION_PROBLEMS.map((p, i) =>
      <ProblemSection key={p.id} problem={p} index={i} />
      )}
      <CTABand />
    </div>);

}

window.SolutionsPage = SolutionsPage;

/* ---------- Page header (60vh, no CTA) ---------- */
function SolutionsHeader() {
  const { isMobile } = useBreakpoint();
  return (
    <section style={{
      background: 'var(--paper)',
      padding: `clamp(28px, 4vw, 40px) var(--pad-x) clamp(56px, 7vw, 88px)`,
      minHeight: '60vh',
      display: 'flex', alignItems: 'center'
    }}>
      <div style={{ maxWidth: 'var(--container)', margin: '0 auto', width: '100%' }}>
        <Breadcrumbs trail={[{ l: 'Solutions' }]} />
        <div style={{ marginTop: 24 }}>
          <Eyebrow>Solutions</Eyebrow>
        <h1 style={{ ...{
              fontFamily: 'var(--font-display)', fontWeight: 300,
              fontSize: isMobile ? 'clamp(40px, 9vw, 60px)' : 'clamp(56px, 7.5vw, 96px)',
              lineHeight: 0.98, letterSpacing: '-0.045em',
              color: 'var(--ink)',
              margin: '24px 0 0',
              maxWidth: '16ch',
              textWrap: 'pretty'
            } }}>
          Fashion content<br /><em style={{ fontStyle: 'italic' }}>at pace.</em>
        </h1>

        <p style={{
            marginTop: 'clamp(24px, 3vw, 32px)',
            fontSize: 'clamp(16px, 1.55vw, 19px)',
            lineHeight: 1.55,
            color: 'var(--graphite)',
            maxWidth: '56ch'
          }}>
          Six everyday challenges in fashion content production &mdash; Cost, Speed, Consistency, Scale, Representation, Quality. ViZO is built to solve every one of them, in one place.
        </p>
        <div style={{
            marginTop: 'clamp(28px, 4vw, 40px)',
            fontFamily: 'var(--font-mono)', fontSize: 12, letterSpacing: '0.08em',
            color: 'var(--slate)', textTransform: 'uppercase',
            display: 'flex', alignItems: 'center', gap: 10
          }}>
          <span style={{ display: 'inline-block', width: 28, height: 1, background: 'var(--slate)' }} />
          <span>Six challenges &middot; One platform</span>
        </div>
      </div>
      </div>
    </section>);

}

/* ---------- Sticky problem index ---------- */
function ProblemIndexStrip({ active }) {
  const { isMobile } = useBreakpoint();
  const jump = (id) => (e) => {
    e.preventDefault();
    const el = document.getElementById(`problem-${id}`);
    if (!el) return;
    const stripH = isMobile ? 56 : 64;
    const navH = isMobile ? 64 : 72;
    const y = el.getBoundingClientRect().top + window.scrollY - (navH + stripH) + 1;
    window.scrollTo({ top: y, behavior: 'smooth' });
  };

  return (
    <nav aria-label="Problem index" style={{
      position: 'sticky',
      top: isMobile ? 64 : 72,
      zIndex: 30,
      background: 'var(--canvas)',
      borderTop: '1px solid var(--bone)',
      borderBottom: '1px solid var(--bone)'
    }}>
      <div style={{
        maxWidth: 'var(--container)', margin: '0 auto',
        padding: `0 var(--pad-x)`
      }}>
        <ul style={{
          display: 'flex',
          alignItems: 'stretch',
          gap: 'clamp(16px, 3vw, 40px)',
          listStyle: 'none', margin: 0, padding: 0,
          overflowX: 'auto',
          scrollbarWidth: 'none',
          msOverflowStyle: 'none'
        }} className="vizo-no-scrollbar">
          {SOLUTION_PROBLEMS.map((p, i) => {
            const isActive = p.id === active;
            return (
              <li key={p.id} style={{ flex: '0 0 auto' }}>
                <a
                  href={`#problem-${p.id}`}
                  onClick={jump(p.id)}
                  style={{
                    position: 'relative',
                    display: 'inline-flex',
                    alignItems: 'center',
                    gap: 8,
                    padding: `${isMobile ? 16 : 20}px 0`,
                    fontFamily: 'var(--font-mono)',
                    fontSize: isMobile ? 11 : 12,
                    letterSpacing: '0.1em',
                    textTransform: 'uppercase',
                    color: isActive ? 'var(--ink)' : 'var(--slate)',
                    textDecoration: 'none',
                    whiteSpace: 'nowrap',
                    transition: 'color 200ms var(--ease-standard)'
                  }}>
                  
                  <span style={{ opacity: isActive ? 1 : 0.7 }}>{String(i + 1).padStart(2, '0')}</span>
                  <span aria-hidden="true" style={{ opacity: 0.5 }}>·</span>
                  <span style={{ fontWeight: isActive ? 600 : 500 }}>{p.label}</span>
                  <span style={{
                    position: 'absolute', left: 0, right: 0, bottom: -1, height: 2,
                    background: 'var(--ink)',
                    transform: isActive ? 'scaleX(1)' : 'scaleX(0)',
                    transformOrigin: 'left center',
                    transition: 'transform 250ms var(--ease-standard)'
                  }} />
                </a>
              </li>);

          })}
        </ul>
      </div>
      <style>{`.vizo-no-scrollbar::-webkit-scrollbar { display: none; }`}</style>
    </nav>);

}

/* ---------- One problem section (~80vh, alternating image side) ---------- */
function ProblemSection({ problem, index }) {
  const { isMobile, isTablet } = useBreakpoint();
  const imageRight = index % 2 === 0; // 01 image right, 02 image left, ...
  const bg = index % 2 === 0 ? 'var(--paper)' : 'var(--canvas)';
  const num = String(index + 1).padStart(2, '0');

  // Build the two columns; we swap order via CSS grid order on desktop.
  const text =
  <div>
      <Eyebrow>Problem {num} · {problem.label}</Eyebrow>
      <h2 style={{
      fontFamily: 'var(--font-display)', fontWeight: 300,
      fontSize: 'clamp(34px, 5.4vw, 64px)',
      lineHeight: 1.0, letterSpacing: '-0.035em',
      color: 'var(--ink)',
      margin: '20px 0 0',
      maxWidth: '14ch',
      textWrap: 'pretty', width: "100%"
    }}>
        {problem.headline}
      </h2>
      <p style={{
      marginTop: 'clamp(20px, 2.5vw, 28px)',
      fontSize: 'clamp(15.5px, 1.45vw, 17.5px)',
      lineHeight: 1.6, color: 'var(--graphite)',
      maxWidth: '52ch'
    }}>
        {problem.pain}
      </p>

      <PainAnswerGrid problem={problem} isMobile={isMobile} />
    </div>;


  const figure =
  <div style={{ position: 'relative' }}>
      <FashionPlate
      ratio="4 / 5"
      src={problem.plate.src}
      position={problem.plate.position}
      fit={problem.plate.fit}
      bg={problem.plate.bg}
      label={problem.plate.label}
      subject={problem.plate.subject}
      idx={index} />
    
      <div style={{
      position: 'absolute', top: 16, left: 16,
      background: 'var(--canvas)', color: 'var(--ink)',
      fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.1em',
      padding: '6px 10px', textTransform: 'uppercase', fontWeight: 600
    }}>
        Problem {num}
      </div>
    </div>;


  return (
    <section
      id={`problem-${problem.id}`}
      data-screen-label={`03 Solutions \u203A ${num} ${problem.label}`}
      style={{
        background: bg,
        padding: `clamp(56px, 7vw, 96px) var(--pad-x)`,
        minHeight: isMobile ? 'auto' : '80vh',
        display: 'flex', alignItems: 'center',
        position: 'relative',
        scrollMarginTop: isMobile ? 120 : 136
      }}>
      {/* Short alias anchor so external links like /solutions#scale resolve directly. */}
      <span id={problem.id} aria-hidden="true" style={{
        position: 'absolute', top: isMobile ? -120 : -136, left: 0, width: 1, height: 1, overflow: 'hidden'
      }} />
      <div style={{
        maxWidth: 'var(--container)', margin: '0 auto', width: '100%',
        display: 'grid',
        gridTemplateColumns: isMobile ? '1fr' : isTablet ? '1fr 1fr' : '1.05fr 1fr',
        gap: 'clamp(28px, 5vw, 72px)',
        alignItems: 'center'
      }}>
        {isMobile ?
        <>
            {figure}
            {text}
          </> :
        imageRight ?
        <>
            {text}
            {figure}
          </> :

        <>
            {figure}
            {text}
          </>
        }
      </div>
    </section>);

}

window.SolutionsHeader = SolutionsHeader;
window.ProblemIndexStrip = ProblemIndexStrip;
window.ProblemSection = ProblemSection;

/* ---------- Pain / Answer block ----------
   Desktop: side-by-side, paired-row grid.
   Mobile:  pain points shown first; the ViZO answers sit behind a "Show what ViZO does" toggle. */
function PainAnswerGrid({ problem, isMobile }) {
  const [open, setOpen] = React.useState('pain');

  const painHeader =
  <div style={{
    display: 'flex', alignItems: 'center', gap: 10,
    paddingBottom: 12, borderBottom: '1px solid var(--mist)'
  }}>
      <span style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--graphite)', display: 'inline-block' }} />
      <span style={{
      fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.1em',
      color: 'var(--graphite)', textTransform: 'uppercase', fontWeight: 600
    }}>The pain</span>
    </div>;

  const answerHeader =
  <div style={{
    display: 'flex', alignItems: 'center', gap: 10,
    paddingBottom: 12, borderBottom: '1px solid var(--ink)'
  }}>
      <span style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--ink)', display: 'inline-block' }} />
      <span style={{
      fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.1em',
      color: 'var(--ink)', textTransform: 'uppercase', fontWeight: 600
    }}>What <span style={{ textTransform: 'none' }}>ViZO</span> does</span>
    </div>;


  const painItem = (p, i) =>
  <div key={i} style={{
    display: 'flex', gap: 12, alignItems: 'flex-start',
    fontSize: 14.5, lineHeight: 1.55, color: 'var(--graphite)'
  }}>
      <span aria-hidden="true" style={{ fontFamily: 'var(--font-mono)', color: 'var(--slate)', flex: '0 0 auto', marginTop: 1 }}>&mdash;</span>
      <span>{p}</span>
    </div>;

  const answerItem = (a, i) =>
  <div key={i} style={{
    display: 'flex', gap: 12, alignItems: 'flex-start',
    fontSize: 14.5, lineHeight: 1.55, color: 'var(--ink)'
  }}>
      <span aria-hidden="true" style={{ flex: '0 0 auto', marginTop: 2, color: 'var(--ink)' }}>
        <Icon.check width="16" height="16" />
      </span>
      <span>{a}</span>
    </div>;


  if (isMobile) {
    /* Mobile: tabs. Both headers always visible; tap to swap which list is shown. */
    const tab = (key, label, dotColor) => {
      const active = open === key;
      return (
        <button
          type="button"
          onClick={() => setOpen(key)}
          aria-pressed={active}
          style={{
            appearance: 'none', cursor: 'pointer',
            display: 'inline-flex', alignItems: 'center', gap: 10,
            background: 'transparent', border: 'none', padding: '12px 0',
            position: 'relative',
            color: active ? 'var(--ink)' : 'var(--slate)',
            fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.1em',
            textTransform: 'uppercase', fontWeight: 600,
            transition: 'color 200ms var(--ease-standard)',
            textAlign: 'left'
          }}>
          <span style={{
            width: 6, height: 6, borderRadius: 999,
            background: active ? dotColor : 'var(--mist)',
            display: 'inline-block',
            transition: 'background 200ms var(--ease-standard)'
          }} />
          {label}
          <span aria-hidden="true" style={{
            position: 'absolute', left: 0, right: 0, bottom: -1, height: 2,
            background: 'var(--ink)',
            transform: active ? 'scaleX(1)' : 'scaleX(0)',
            transformOrigin: 'left center',
            transition: 'transform 240ms var(--ease-standard)'
          }} />
        </button>);

    };

    return (
      <div style={{ marginTop: 'clamp(24px, 3vw, 32px)' }}>
        <div role="tablist" style={{
          display: 'flex', gap: 24,
          borderBottom: '1px solid var(--mist)'
        }}>
          {tab('pain', 'The pain', 'var(--graphite)')}
          {tab('answer', <>What <span style={{ textTransform: 'none' }}>ViZO</span> does</>, 'var(--ink)')}
        </div>

        <div style={{ marginTop: 20, display: 'flex', flexDirection: 'column', gap: 14 }}>
          {open === 'pain' ?
          problem.pains.map(painItem) :
          problem.answers.map(answerItem)}
        </div>

        <style>{`@keyframes painAnswerIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }`}</style>
      </div>);

  }

  /* Desktop: paired grid — pain row N aligned with answer row N. */
  return (
    <div style={{
      marginTop: 'clamp(28px, 3.5vw, 40px)',
      display: 'grid',
      gridTemplateColumns: '1fr 1fr',
      gap: 'clamp(20px, 2.4vw, 28px) clamp(20px, 2.4vw, 28px)',
      rowGap: 16
    }}>
      {painHeader}
      {answerHeader}
      {problem.pains.map((p, i) =>
      <React.Fragment key={i}>
          {painItem(p, i)}
          {answerItem(problem.answers[i], i)}
        </React.Fragment>
      )}
    </div>);

}

window.PainAnswerGrid = PainAnswerGrid;

/* ---------- Breadcrumbs ---------- */
function Breadcrumbs({ trail }) {
  return (
    <nav aria-label="Breadcrumb" style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.06em', color: 'var(--slate)', textTransform: 'uppercase' }}>
      <Link to="/" style={{ color: 'var(--slate)', textDecoration: 'none' }}>Home</Link>
      {trail.map((t, i) =>
      <React.Fragment key={i}>
          <span>/</span>
          {t.to ? <Link to={t.to} style={{ color: 'var(--slate)', textDecoration: 'none' }}>{t.l}</Link> : <span style={{ color: 'var(--ink)' }}>{t.l}</span>}
        </React.Fragment>
      )}
    </nav>);

}

function NotFound() {
  return (
    <section style={{ padding: 'var(--pad-y) var(--pad-x)', textAlign: 'center', background: 'var(--paper)', minHeight: '60vh' }}>
      <Eyebrow>404</Eyebrow>
      <h1 style={{ fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 'clamp(36px, 6vw, 64px)', color: 'var(--ink)', margin: '20px 0' }}>Couldn't find that page.</h1>
      <Link to="/"><Button variant="primary" size="large" arrow>Back to home</Button></Link>
    </section>);

}

Object.assign(window, { Breadcrumbs, NotFound });