// table-styles.jsx — SwipeTable, FlipTable, ExpandTable
// Three alternative layouts for the set log that handle column overflow on mobile.

// ─── A · Swipe table ─────────────────────────────────────────────────────
// Set + Reps stay pinned on the left. Right portion scrolls to reveal
// Weight, Equip, Tempo, RPE, Done. Header scrolls with rows.
function SwipeTable({ theme, ex, exIdx, cols, onUpdateSet }) {
  const headRef = React.useRef(null);
  const rowRefs = React.useRef([]);
  const [atEnd, setAtEnd] = React.useState(false);
  const [allOpen, setAllOpen] = React.useState(false);

  // Build the scrollable columns list dynamically
  const scrollCols = [{ k: 'weight', label: 'Wt' }];
  if (cols.equip) scrollCols.push({ k: 'equip', label: 'Equip' });
  if (cols.tempo) scrollCols.push({ k: 'tempo', label: 'Tempo' });
  if (cols.rpe)   scrollCols.push({ k: 'rpe',   label: 'RPE' });
  scrollCols.push({ k: 'done',   label: 'Done' });

  const SCROLL_COL_W = 72;
  const innerW = scrollCols.length * SCROLL_COL_W;

  const syncingRef = React.useRef(false);
  const handleScroll = (e) => {
    if (syncingRef.current) return;
    syncingRef.current = true;
    const src = e.currentTarget;
    const left = src.scrollLeft;
    const all = [headRef.current, ...rowRefs.current].filter(Boolean);
    all.forEach(el => { if (el !== src) el.scrollLeft = left; });
    setAtEnd(left + src.clientWidth >= src.scrollWidth - 4);
    syncingRef.current = false;
  };

  // SHOW-ALL MODE — each row stacks: Set+Reps on top, all extras wrapped below
  if (allOpen) {
    return (
      <div style={{ borderRadius: 8, overflow: 'hidden', border: `1px solid ${theme.border}` }}>
        <ShowAllBar theme={theme} active onToggle={() => setAllOpen(false)} hint="All columns visible"/>
        {ex.sets.map((s, i) => (
          <div key={i} style={{
            padding: '8px 10px',
            borderTop: i === 0 ? 'none' : `0.5px solid ${theme.border}`,
            background: s.done
              ? (theme.isDark ? 'rgba(52,211,153,0.10)' : 'rgba(46,125,50,0.07)')
              : exerciseSetTint(theme, exIdx, i),
            display: 'flex', flexDirection: 'column', gap: 6,
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div style={{ fontFamily: theme.monoFamily, fontSize: 12, color: theme.muted, fontWeight: 700, minWidth: 18 }}>{i + 1}</div>
              <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
                <LabelledCell theme={theme} label="Reps" value={s.reps ?? ''} onChange={v => onUpdateSet(i, { reps: v })}/>
                <LabelledCell theme={theme} label="Wt"   value={s.weight ?? ''} onChange={v => onUpdateSet(i, { weight: v })}/>
              </div>
              <DoneCheck theme={theme} done={s.done} onClick={() => onUpdateSet(i, { done: !s.done })}/>
            </div>
            {(cols.equip || cols.tempo || cols.rpe) && (
              <div style={{ display: 'grid', gridTemplateColumns: `repeat(${(cols.equip?1:0)+(cols.tempo?1:0)+(cols.rpe?1:0)}, 1fr)`, gap: 6, paddingLeft: 26 }}>
                {cols.equip && <LabelledCell theme={theme} label="Equip" value={s.equip ?? ''} onChange={v => onUpdateSet(i, { equip: v })}/>}
                {cols.tempo && <LabelledCell theme={theme} label="Tempo" value={s.tempo ?? ''} onChange={v => onUpdateSet(i, { tempo: v })}/>}
                {cols.rpe   && <LabelledCell theme={theme} label="RPE"   value={s.rpe ?? ''}   onChange={v => onUpdateSet(i, { rpe: v })}/>}
              </div>
            )}
          </div>
        ))}
      </div>
    );
  }

  return (
    <div style={{ borderRadius: 8, overflow: 'hidden', border: `1px solid ${theme.border}`, position: 'relative' }}>
      <ShowAllBar theme={theme} active={false} onToggle={() => setAllOpen(true)} hint="Swipe →"/>
      {/* Header */}
      <div style={{
        display: 'grid', gridTemplateColumns: '28px 1fr',
        background: theme.isDark ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.025)',
        borderBottom: `0.5px solid ${theme.border}`,
      }}>
        <SwipeFrozen theme={theme} isHeader>
          <span style={swipeHeadStyle(theme)}>Set</span>
          <span style={{...swipeHeadStyle(theme), textAlign: 'left'}}>Reps</span>
        </SwipeFrozen>
        <div ref={headRef} onScroll={handleScroll} style={swipeScrollStyle()}>
          <div style={{ display: 'grid', gridTemplateColumns: `repeat(${scrollCols.length}, ${SCROLL_COL_W}px)`, width: innerW }}>
            {scrollCols.map(c => (
              <div key={c.k} style={{
                ...swipeHeadStyle(theme), padding: '6px 6px',
                borderLeft: `0.5px solid ${theme.border}`, textAlign: 'left',
              }}>{c.label}</div>
            ))}
          </div>
        </div>
      </div>

      {/* Rows */}
      {ex.sets.map((s, i) => (
        <div key={i} style={{
          display: 'grid', gridTemplateColumns: '28px 1fr',
          borderTop: i === 0 ? 'none' : `0.5px solid ${theme.border}`,
          background: s.done
              ? (theme.isDark ? 'rgba(52,211,153,0.10)' : 'rgba(46,125,50,0.07)')
              : exerciseSetTint(theme, exIdx, i),
        }}>
          <SwipeFrozen theme={theme}>
            <div style={{ fontFamily: theme.monoFamily, fontSize: 12, color: theme.muted, fontWeight: 700, textAlign: 'left' }}>{i + 1}</div>
            <CellInput theme={theme} value={s.reps ?? ''} onChange={v => onUpdateSet(i, { reps: v })}/>
          </SwipeFrozen>
          <div ref={el => rowRefs.current[i] = el} onScroll={handleScroll} style={swipeScrollStyle()}>
            <div style={{ display: 'grid', gridTemplateColumns: `repeat(${scrollCols.length}, ${SCROLL_COL_W}px)`, width: innerW, alignItems: 'center', padding: '6px 0' }}>
              {scrollCols.map(c => (
                <div key={c.k} style={{ padding: '0 6px', borderLeft: `0.5px solid ${theme.border}` }}>
                  {c.k === 'done'
                    ? <DoneCheck theme={theme} done={s.done} onClick={() => onUpdateSet(i, { done: !s.done })}/>
                    : <CellInput theme={theme} value={s[c.k] ?? ''} onChange={v => onUpdateSet(i, { [c.k]: v })}/>}
                </div>
              ))}
            </div>
          </div>
        </div>
      ))}

      {/* Fade + chevron — overlay on the right edge of scroll area */}
      <div style={{
        position: 'absolute', top: 30, bottom: 0, right: 0, width: 28,
        pointerEvents: 'none',
        background: `linear-gradient(to right, transparent, ${theme.surface})`,
        opacity: atEnd ? 0 : 1, transition: 'opacity 0.2s',
      }}/>
      {!atEnd && (
        <div style={{
          position: 'absolute', top: '55%', right: 4, transform: 'translateY(-50%)',
          pointerEvents: 'none', color: theme.primary,
          animation: 'tmPulseRight 1.6s ease-in-out infinite',
        }}>
          <Icon name="chevron" size={12} color={theme.primary} strokeWidth={2.5}/>
        </div>
      )}
    </div>
  );
}

// Shared "Show all" / "Expand all" header bar
function ShowAllBar({ theme, active, onToggle, hint }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 8,
      padding: '6px 8px', borderBottom: `0.5px solid ${theme.border}`,
      background: theme.isDark ? 'rgba(255,255,255,0.02)' : 'rgba(0,0,0,0.015)',
    }}>
      <span style={{ fontFamily: theme.uiFamily, fontSize: 10, color: theme.muted, flex: 1 }}>
        {hint}
      </span>
      <button onClick={onToggle} style={{
        display: 'inline-flex', alignItems: 'center', gap: 4,
        padding: '3px 8px', borderRadius: 9999,
        background: active ? theme.primary : 'transparent',
        color: active ? theme.primaryInk : theme.primary,
        border: `1px solid ${theme.primary}`,
        fontFamily: theme.uiFamily, fontSize: 10, fontWeight: 600, cursor: 'pointer',
        whiteSpace: 'nowrap',
      }}>
        <Icon name={active ? 'check' : 'expand'} size={10} color={active ? theme.primaryInk : theme.primary} strokeWidth={2.4}/>
        {active ? 'All shown' : 'Show all'}
      </button>
    </div>
  );
}

function LabelledCell({ theme, label, value, onChange }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
      <span style={{ fontFamily: theme.uiFamily, fontSize: 9, fontWeight: 700, color: theme.muted, textTransform: 'uppercase', letterSpacing: 0.4 }}>{label}</span>
      <CellInput theme={theme} value={value} onChange={onChange}/>
    </div>
  );
}

function SwipeFrozen({ theme, isHeader, children }) {
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: '28px 1fr',
      alignItems: 'center', gap: 6,
      padding: isHeader ? '6px 8px' : '6px 8px',
      borderRight: `1px solid ${theme.border}`,
      background: theme.surface,
    }}>{children}</div>
  );
}
function swipeHeadStyle(theme) {
  return {
    fontFamily: theme.uiFamily, fontSize: 9, fontWeight: 600,
    color: theme.muted, textTransform: 'uppercase', letterSpacing: 0.4,
    padding: '4px 0',
  };
}
function swipeScrollStyle() {
  return {
    overflowX: 'auto', overflowY: 'hidden',
    WebkitOverflowScrolling: 'touch',
    scrollSnapType: 'x mandatory',
    scrollbarWidth: 'none',
  };
}

// ─── B · Flip table ──────────────────────────────────────────────────────
// 1 card per set. Front: Set/Reps/Wt/✓. Back: extras (Equip, Tempo, RPE).
// Tap flip icon → rotate. Only one flipped at a time.
function FlipTable({ theme, ex, exIdx, cols, onUpdateSet }) {
  const [flippedIdx, setFlippedIdx] = React.useState(null);
  const [allOpen, setAllOpen] = React.useState(false);

  const backFields = [];
  if (cols.equip) backFields.push({ k: 'equip', label: 'Equip' });
  if (cols.tempo) backFields.push({ k: 'tempo', label: 'Tempo' });
  if (cols.rpe)   backFields.push({ k: 'rpe',   label: 'RPE' });
  const hasBack = backFields.length > 0;

  // SHOW-ALL MODE — render each set as one row with front + back fields inline
  if (allOpen && hasBack) {
    return (
      <div style={{ borderRadius: 8, overflow: 'hidden', border: `1px solid ${theme.border}` }}>
        <ShowAllBar theme={theme} active onToggle={() => setAllOpen(false)} hint="Both faces visible"/>
        {ex.sets.map((s, i) => (
          <div key={i} style={{
            padding: '8px 10px',
            borderTop: i === 0 ? 'none' : `0.5px solid ${theme.border}`,
            background: s.done
              ? (theme.isDark ? 'rgba(52,211,153,0.10)' : 'rgba(46,125,50,0.07)')
              : exerciseSetTint(theme, exIdx, i),
            display: 'flex', flexDirection: 'column', gap: 6,
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <div style={{ fontFamily: theme.monoFamily, fontSize: 12, color: theme.muted, fontWeight: 700, minWidth: 18 }}>{i + 1}</div>
              <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
                <LabelledCell theme={theme} label="Reps" value={s.reps ?? ''} onChange={v => onUpdateSet(i, { reps: v })}/>
                <LabelledCell theme={theme} label="Wt"   value={s.weight ?? ''} onChange={v => onUpdateSet(i, { weight: v })}/>
              </div>
              <DoneCheck theme={theme} done={s.done} onClick={() => onUpdateSet(i, { done: !s.done })}/>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: `repeat(${backFields.length}, 1fr)`, gap: 6, paddingLeft: 26 }}>
              {backFields.map(f => (
                <LabelledCell key={f.k} theme={theme} label={f.label} value={s[f.k] ?? ''} onChange={v => onUpdateSet(i, { [f.k]: v })}/>
              ))}
            </div>
          </div>
        ))}
      </div>
    );
  }

  return (
    <div style={{ borderRadius: 8, overflow: 'hidden', border: `1px solid ${theme.border}` }}>
      {hasBack && <ShowAllBar theme={theme} active={false} onToggle={() => setAllOpen(true)} hint={`Tap chevron to flip · ${backFields.map(f => f.label).join(' · ')} on back`}/>}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6, padding: '6px 0' }}>
      {/* Column header */}
      <div style={{
        display: 'grid', gridTemplateColumns: '28px 1fr 1fr 28px 36px',
        gap: 6, padding: '0 8px',
        fontFamily: theme.uiFamily, fontSize: 9, fontWeight: 600, color: theme.muted,
        textTransform: 'uppercase', letterSpacing: 0.4,
      }}>
        <div style={{ textAlign: 'left' }}>Set</div>
        <div>Reps</div>
        <div>Wt</div>
        <div style={{ textAlign: 'left' }}>✓</div>
        <div></div>
      </div>

      {ex.sets.map((s, i) => {
        const flipped = flippedIdx === i;
        return (
          <div key={i} style={{
            perspective: 1000, height: 38, padding: '0 8px',
          }}>
            <div style={{
              position: 'relative', width: '100%', height: '100%',
              transformStyle: 'preserve-3d',
              transition: 'transform 0.5s cubic-bezier(0.45, 0.05, 0.2, 1.05)',
              transform: flipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
            }}>
              {/* Front */}
              <FlipFace theme={theme} done={s.done}>
                <div style={{ fontFamily: theme.monoFamily, fontSize: 12, color: theme.muted, fontWeight: 700, textAlign: 'left' }}>{i + 1}</div>
                <CellInput theme={theme} value={s.reps ?? ''} onChange={v => onUpdateSet(i, { reps: v })}/>
                <CellInput theme={theme} value={s.weight ?? ''} onChange={v => onUpdateSet(i, { weight: v })}/>
                <DoneCheck theme={theme} done={s.done} onClick={() => onUpdateSet(i, { done: !s.done })}/>
                {hasBack ? (
                  <FlipBtn theme={theme} onClick={() => setFlippedIdx(i)} direction="next" label={backFields.map(f => f.label).join(' · ')}/>
                ) : <div/>}
              </FlipFace>
              {/* Back */}
              {hasBack && (
                <FlipFace theme={theme} done={s.done} back backCols={backFields.length}>
                  <div style={{ fontFamily: theme.monoFamily, fontSize: 12, color: theme.primary, fontWeight: 700, textAlign: 'left' }}>{i + 1}</div>
                  {backFields.map(f => (
                    <div key={f.k} style={{ display: 'flex', flexDirection: 'column', gap: 0 }}>
                      <span style={{ fontFamily: theme.uiFamily, fontSize: 8, fontWeight: 700, color: theme.muted, textTransform: 'uppercase', letterSpacing: 0.4, marginBottom: 1 }}>{f.label}</span>
                      <CellInput theme={theme} value={s[f.k] ?? ''} onChange={v => onUpdateSet(i, { [f.k]: v })}/>
                    </div>
                  ))}
                  <FlipBtn theme={theme} onClick={() => setFlippedIdx(null)} direction="back" label=""/>
                </FlipFace>
              )}
            </div>
          </div>
        );
      })}
      </div>
    </div>
  );
}

function FlipFace({ theme, done, back, backCols, children }) {
  // grid columns: front 28/1fr/1fr/28/36, back 28/{n × 1fr}/36
  const grid = back
    ? `28px ${Array.from({ length: backCols }, () => '1fr').join(' ')} 36px`
    : '28px 1fr 1fr 28px 36px';
  return (
    <div style={{
      position: 'absolute', inset: 0,
      display: 'grid', gridTemplateColumns: grid, gap: 6,
      alignItems: 'center', padding: '0 8px',
      borderRadius: 8,
      WebkitBackfaceVisibility: 'hidden', backfaceVisibility: 'hidden',
      transform: back ? 'rotateY(180deg)' : 'none',
      background: back
        ? (theme.isDark ? 'rgba(232,131,11,0.10)' : 'rgba(232,131,11,0.08)')
        : (done ? (theme.isDark ? 'rgba(52,211,153,0.06)' : 'rgba(46,125,50,0.04)') : theme.surface),
      border: `1px solid ${back ? theme.primary + '55' : theme.border}`,
    }}>{children}</div>
  );
}

function FlipBtn({ theme, onClick, direction, label }) {
  return (
    <button onClick={onClick} title={label} style={{
      width: 32, height: 26, justifySelf: 'end',
      borderRadius: 6, padding: 0, cursor: 'pointer',
      background: 'transparent', border: `1px solid ${theme.border}`,
      color: theme.muted,
      display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 2,
    }}>
      <Icon name={direction === 'next' ? 'chevron' : 'chevronLeft'} size={11} color={theme.muted} strokeWidth={2.2}/>
    </button>
  );
}

// ─── C · Expand table ────────────────────────────────────────────────────
// Strong / Hevy pattern. 4-col table; tap row → expands to show extras.
function ExpandTable({ theme, ex, exIdx, cols, onUpdateSet }) {
  const [openIdx, setOpenIdx] = React.useState(null);
  const [allOpen, setAllOpen] = React.useState(false);
  const hasExtras = cols.equip || cols.tempo || cols.rpe;

  const extras = [];
  if (cols.equip) extras.push({ k: 'equip', label: 'Equip', hint: 'Equipment setting' });
  if (cols.tempo) extras.push({ k: 'tempo', label: 'Tempo', hint: 'Ecc-pause-conc' });
  if (cols.rpe)   extras.push({ k: 'rpe',   label: 'RPE',   hint: 'Effort 1–10' });

  const grid = hasExtras ? '28px 1fr 1fr 28px 64px' : '28px 1fr 1fr 28px';

  return (
    <div style={{ borderRadius: 8, overflow: 'hidden', border: `1px solid ${theme.border}` }}>
      {/* Top hint + expand-all toggle */}
      {hasExtras && (
        <div style={{
          display: 'flex', alignItems: 'center', gap: 8,
          padding: '6px 8px', borderBottom: `0.5px solid ${theme.border}`,
          background: theme.isDark ? 'rgba(255,255,255,0.02)' : 'rgba(0,0,0,0.015)',
        }}>
          <span style={{ fontFamily: theme.uiFamily, fontSize: 10, color: theme.muted, flex: 1 }}>
            Tap a row for {extras.map(e => e.label).join(' · ')}
          </span>
          <button onClick={() => { setAllOpen(v => !v); setOpenIdx(null); }} style={{
            display: 'inline-flex', alignItems: 'center', gap: 4,
            padding: '3px 8px', borderRadius: 9999,
            background: allOpen ? theme.primary : 'transparent',
            color: allOpen ? theme.primaryInk : theme.primary,
            border: `1px solid ${theme.primary}`,
            fontFamily: theme.uiFamily, fontSize: 10, fontWeight: 600, cursor: 'pointer',
            whiteSpace: 'nowrap',
          }}>
            <Icon name={allOpen ? 'check' : 'expand'} size={10}
              color={allOpen ? theme.primaryInk : theme.primary} strokeWidth={2.4}/>
            {allOpen ? 'All open' : 'Expand all'}
          </button>
        </div>
      )}

      {/* Header */}
      <div style={{
        display: 'grid', gridTemplateColumns: grid, gap: 6,
        padding: '6px 8px', background: theme.isDark ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.025)',
        fontFamily: theme.uiFamily, fontSize: 9, fontWeight: 600, color: theme.muted,
        textTransform: 'uppercase', letterSpacing: 0.4,
      }}>
        <div style={{ textAlign: 'left' }}>Set</div>
        <div>Reps</div>
        <div>Wt</div>
        <div style={{ textAlign: 'left' }}>✓</div>
        {hasExtras && <div style={{ textAlign: 'left' }}>More</div>}
      </div>

      {ex.sets.map((s, i) => {
        const open = allOpen || openIdx === i;
        return (
          <React.Fragment key={i}>
            <div
              onClick={hasExtras && !allOpen ? () => setOpenIdx(open ? null : i) : undefined}
              style={{
                display: 'grid', gridTemplateColumns: grid, gap: 6,
                padding: '8px 8px', alignItems: 'center',
                borderTop: i === 0 ? 'none' : `0.5px solid ${theme.border}`,
                background: open
                  ? exRgba(exerciseColor(theme, exIdx), theme.isDark ? 0.22 : 0.16)
                  : s.done
                    ? (theme.isDark ? 'rgba(52,211,153,0.10)' : 'rgba(46,125,50,0.07)')
                    : exerciseSetTint(theme, exIdx, i),
                cursor: hasExtras && !allOpen ? 'pointer' : 'default',
              }}
            >
              <div style={{ fontFamily: theme.monoFamily, fontSize: 12, color: theme.muted, fontWeight: 700, textAlign: 'left' }}>{i + 1}</div>
              <div onClick={e => e.stopPropagation()}>
                <CellInput theme={theme} value={s.reps ?? ''} onChange={v => onUpdateSet(i, { reps: v })}/>
              </div>
              <div onClick={e => e.stopPropagation()}>
                <CellInput theme={theme} value={s.weight ?? ''} onChange={v => onUpdateSet(i, { weight: v })}/>
              </div>
              <div onClick={e => e.stopPropagation()}>
                <DoneCheck theme={theme} done={s.done} onClick={() => onUpdateSet(i, { done: !s.done })}/>
              </div>
              {hasExtras && (
                <div style={{
                  display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4,
                  padding: '3px 6px', borderRadius: 9999,
                  background: open ? theme.primary : (theme.isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.06)'),
                  color: open ? theme.primaryInk : theme.muted,
                  fontFamily: theme.uiFamily, fontSize: 10, fontWeight: 600,
                }}>
                  <span>{open ? 'Hide' : 'More'}</span>
                  {!allOpen && (
                    <span style={{
                      display: 'inline-flex',
                      transform: open ? 'rotate(90deg)' : 'rotate(0deg)',
                      transition: 'transform 0.2s',
                    }}>
                      <Icon name="chevron" size={10} color="currentColor" strokeWidth={2.6}/>
                    </span>
                  )}
                </div>
              )}
            </div>
            {hasExtras && (
              <div style={{
                display: 'grid', gridTemplateRows: open ? '1fr' : '0fr',
                transition: 'grid-template-rows 0.22s ease',
                background: theme.isDark ? 'rgba(0,0,0,0.18)' : 'rgba(0,0,0,0.025)',
              }}>
                <div style={{ overflow: 'hidden' }}>
                  <div style={{
                    padding: '10px 12px',
                    display: 'grid', gridTemplateColumns: `repeat(${extras.length}, 1fr)`, gap: 10,
                  }}>
                    {extras.map(f => (
                      <div key={f.k} style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                        <span style={{ fontFamily: theme.uiFamily, fontSize: 9, fontWeight: 700, color: theme.muted, textTransform: 'uppercase', letterSpacing: 0.4 }}>{f.label}</span>
                        <CellInput theme={theme} value={s[f.k] ?? ''} onChange={v => onUpdateSet(i, { [f.k]: v })}/>
                        <span style={{ fontFamily: theme.uiFamily, fontSize: 9, color: theme.muted, opacity: 0.7 }}>{f.hint}</span>
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            )}
          </React.Fragment>
        );
      })}
    </div>
  );
}

Object.assign(window, { SwipeTable, FlipTable, ExpandTable });
