// The work on the left, what it costs on the right, and an arrow in the gutter
// saying the first causes the second. Hovering a group of work lights the
// consequences it drives; when nobody is interacting the section walks itself
// through the groups.
function TheWork() {
  const groups = [
    {
      key: 'close',
      label: 'Books & close',
      items: [
        'A chart of accounts built for your model',
        'Expenses categorized correctly, every month',
        'The monthly close run and landed on a date',
        'Your accountants managed',
      ],
      slips: [0, 3],
    },
    {
      key: 'cash',
      label: 'Cash & payables',
      items: [
        'Bills paid on time',
        'Enough cash in the operating account to cover them',
        'Idle balances earning interest',
      ],
      slips: [1, 3],
    },
    {
      key: 'billing',
      label: 'Billing & collections',
      items: [
        'Accurate invoices out on the first',
        'Customers paying on terms',
      ],
      slips: [1, 3],
    },
    {
      key: 'planning',
      label: 'Planning & modeling',
      items: [
        'An operating model tied to your hiring plan',
        'The annual plan and budget',
        'Expense rules and budgets so costs don’t drift',
        'Salary and equity numbers that hold up',
      ],
      slips: [1, 2],
    },
    {
      key: 'board',
      label: 'Investors & board',
      items: [
        'The metrics your next raise turns on, tracked',
        'Board decks that show progress and name the problems',
        'Investor updates written and sent',
      ],
      slips: [2, 4],
    },
    {
      key: 'capital',
      label: 'Capital & transactions',
      items: [
        'Cloud commitments negotiated',
        'Debt facilities sourced and negotiated',
        'Buy-side or sell-side diligence',
        '409A valuations on schedule',
        'Audit readiness',
      ],
      slips: [2, 3],
    },
  ];

  const slips = [
    'Books close late.',
    'Cash flow is poorly modeled and runway is uncertain.',
    'The metrics that matter go untracked and unimproved.',
    'Your time goes to clerical work instead of the decisions that determine whether this works.',
    'Board decks become a scramble.',
  ];

  const CYCLE_MS = 3600;
  const [active, setActive] = React.useState(0);
  const [pinned, setPinned] = React.useState(false);
  const [seen, setSeen] = React.useState(false);
  const [stacked, setStacked] = React.useState(false);
  const ref = React.useRef(null);

  // Below 900px the two columns stack and the spotlight has nothing left to
  // point at, so the whole thing goes static rather than tinting labels for a
  // connection the reader can no longer see.
  React.useEffect(() => {
    if (!window.matchMedia) return;
    const mq = window.matchMedia('(max-width: 900px)');
    const sync = () => setStacked(mq.matches);
    sync();
    mq.addEventListener('change', sync);
    return () => mq.removeEventListener('change', sync);
  }, []);

  // Don't animate a section nobody is looking at
  React.useEffect(() => {
    const el = ref.current;
    if (!el || typeof IntersectionObserver === 'undefined') { setSeen(true); return; }
    const io = new IntersectionObserver(([e]) => setSeen(e.isIntersecting), { threshold: 0.25 });
    io.observe(el);
    return () => io.disconnect();
  }, []);

  React.useEffect(() => {
    if (pinned || !seen || stacked) return;
    const id = setTimeout(() => setActive((i) => (i + 1) % groups.length), CYCLE_MS);
    return () => clearTimeout(id);
  }, [active, pinned, seen, stacked]);

  const lit = stacked ? [] : groups[active].slips;

  return (
    <section ref={ref} id="the-work" style={{
      padding: '48px 32px',
      borderBottom: '1px solid var(--line-2)',
    }}>
      <style>{`
        @keyframes workProg { from { transform: scaleX(0) } to { transform: scaleX(1) } }

        /* Three columns: the work, the arrow that says it causes the rest,
           and what slips. The middle column is the gutter. */
        .work-grid {
          margin-top: 48px;
          display: grid;
          grid-template-columns: 1.52fr 96px 1fr;
          align-items: stretch;
        }
        .work-groups {
          column-count: 2;
          column-gap: 36px;
        }
        .work-group {
          break-inside: avoid;
          -webkit-column-break-inside: avoid;
          display: inline-block;
          width: 100%;
          margin-bottom: 28px;
        }

        .work-arrow { display: flex; flex-direction: column; align-items: center; }
        .work-arrow-line { flex: 1 1 auto; width: 1px; background: var(--line); }
        .work-arrow-node {
          flex: 0 0 auto;
          width: 44px; height: 44px; border-radius: 999px;
          display: grid; place-items: center;
          background: var(--paper);
          border: 1px solid var(--line);
          margin: 14px 0;
        }

        @media (max-width: 900px) {
          .work-grid { grid-template-columns: 1fr !important; }
          /* stacked, the arrow turns to point down the page instead of across */
          .work-arrow { flex-direction: row !important; padding: 10px 0 !important; }
          .work-arrow-line { width: auto !important; height: 1px !important; }
          .work-arrow-node { margin: 0 14px !important; }
          .work-arrow svg { transform: rotate(90deg); }
          .work-group, .work-slip { opacity: 1 !important; }
          .work-prog { display: none !important; }
        }
        @media (max-width: 640px) {
          .work-groups { column-count: 1 !important; }
          .work-group { margin-bottom: 24px !important; }
        }
      `}</style>

      <div style={{ maxWidth: 1100, margin: '0 auto' }}>
        {/* Line one ends on "time". The cap is in ems, not pixels, so the break
            holds as the clamp scales the type down: line one is 9.86em and
            pulling "that" up would take 11.31em, so 10.5em splits them at every
            size. Instrument Serif ships regular and italic only - no bold - so
            "time" is emphasised with the italic and the moss accent rather than
            a weight the browser would have to fake. */}
        <h2 style={{
          ...window.sectionHeadingStyle,
          maxWidth: '10.5em',
          fontSize: 'clamp(32px, 4.4vw, 56px)',
        }}>
          Running finance requires{' '}
          <span style={{ fontStyle: 'italic', color: 'var(--accent)' }}>time</span>
          {' '}that founders don’t have.
        </h2>

        <div className="work-grid">

          {/* LEFT: the work */}
          <div onMouseLeave={() => setPinned(false)}>
            <ColumnLabel>Core finance tasks</ColumnLabel>
            <div className="work-groups" style={{ marginTop: 26 }}>
              {groups.map((g, i) => {
                const on = !stacked && i === active;
                return (
                  <div
                    key={g.key}
                    className="work-group"
                    onMouseEnter={() => {setPinned(true);setActive(i);}}
                    style={{
                      position: 'relative',
                      opacity: on ? 1 : 0.78,
                      transition: 'opacity 320ms ease',
                      cursor: 'default',
                    }}>

                    <div className="mono" style={{
                      fontSize: 12.5,
                      letterSpacing: '0.08em',
                      textTransform: 'uppercase',
                      color: on ? 'var(--accent)' : 'var(--ink-3)',
                      paddingBottom: 9,
                      borderBottom: '1px solid var(--line-2)',
                      transition: 'color 320ms ease',
                    }}>
                      {g.label}
                    </div>

                    {on && !pinned &&
                    <span
                      key={`p-${active}`}
                      className="work-prog"
                      style={{
                        position: 'absolute', left: 0, right: 0, top: 29, height: 1,
                        background: 'var(--accent)',
                        transformOrigin: 'left',
                        animation: `workProg ${CYCLE_MS}ms linear forwards`,
                      }} />
                    }

                    <ul style={{
                      margin: '12px 0 0', padding: 0, listStyle: 'none',
                      display: 'flex', flexDirection: 'column', gap: 7,
                    }}>
                      {g.items.map((t, j) =>
                      <li key={j} style={{
                        display: 'grid', gridTemplateColumns: '5px 1fr', gap: 11,
                        fontSize: 14, lineHeight: 1.5, color: 'var(--ink-2)',
                      }}>
                          <span style={{
                          marginTop: 8, width: 5, height: 5, borderRadius: '50%',
                          background: on ? 'var(--accent)' : 'var(--line)',
                          transition: 'background 320ms ease',
                        }} />
                          <span>{t}</span>
                        </li>
                      )}
                    </ul>
                  </div>);

              })}
            </div>
          </div>

          {/* MIDDLE: the causation arrow */}
          <div className="work-arrow" aria-hidden="true">
            <span className="work-arrow-line" />
            <span className="work-arrow-node">
              <svg width="17" height="12" viewBox="0 0 17 12" fill="none">
                <path d="M1 6h14M10.5 1.2 15.6 6l-5.1 4.8"
                  stroke="var(--accent)" strokeWidth="1.4"
                  strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </span>
            <span className="work-arrow-line" />
          </div>

          {/* RIGHT: what it costs */}
          <div>
            <ColumnLabel>What often slips</ColumnLabel>
            <div style={{ marginTop: 26 }}>
              {slips.map((t, i) => {
                const on = lit.indexOf(i) !== -1;
                return (
                  <div
                    key={i}
                    className="work-slip"
                    style={{
                      display: 'grid', gridTemplateColumns: '20px 1fr', gap: 14,
                      alignItems: 'start',
                      padding: '15px 0',
                      borderTop: i === 0 ? 'none' : '1px solid var(--line-2)',
                      opacity: on ? 1 : 0.45,
                      transition: 'opacity 380ms ease',
                    }}>

                    <span style={{
                      marginTop: 12, height: 1,
                      background: on ? 'var(--accent)' : 'var(--line)',
                      transition: 'background 380ms ease',
                    }} />
                    <span className="serif" style={{
                      fontSize: 21, lineHeight: 1.3, color: 'var(--ink)',
                    }}>
                      {t}
                    </span>
                  </div>);

              })}
            </div>
          </div>

        </div>
      </div>
    </section>);

}

// One label treatment for both columns, centred over the content it heads and
// set to a common width so the two read as a matched pair.
function ColumnLabel({ children }) {
  return (
    <div style={{ textAlign: 'center' }}>
      <span className="mono" style={{
        display: 'inline-block',
        width: 'min(360px, 100%)',
        fontSize: 15,
        fontWeight: 600,
        letterSpacing: '0.14em',
        textTransform: 'uppercase',
        color: 'var(--ink)',
        padding: '15px 30px',
        border: '1px solid var(--line)',
        borderRadius: 999,
        background: 'var(--paper)',
      }}>
        {children}
      </span>
    </div>);

}

window.TheWork = TheWork;
