// src/ui/steps/step3-timesheet.jsx — Timesheet-invoer per categorie
// Volgens Handleiding stap 4: hoofdwerk, voorbereiding, afronding (+ pr/promotie voor sommige departementen).

const StepTimesheet = ({ state, setState, next, back }) => {
  const huidigeRol = state.rollen?.[0];
  const isFestival = state.type === "festival";
  const timesheetKey = !isFestival && huidigeRol ? window.depToTimesheetKey(huidigeRol.dep) : null;
  const sjabloon = (timesheetKey && window.TIMESHEETS[timesheetKey]) || {};

  const tariefRij = huidigeRol
    ? (isFestival
      ? window.calc.tariefFestival(huidigeRol.niveau)
      : window.calc.tariefFilmAV(huidigeRol.niveau))
    : null;
  const uurtarief = tariefRij?.tarief_min || 0;

  // Hydrate lokale state uit bestaande urenDetails als user terugkomt
  const [rijen, setRijen] = React.useState(() => {
    const bestaand = huidigeRol?.urenDetails;
    if (bestaand && typeof bestaand === "object") {
      return {
        hoofdwerk:     bestaand.hoofdwerk     || [],
        voorbereiding: bestaand.voorbereiding || [],
        afronding:     bestaand.afronding     || [],
        pr_promotie:   bestaand.pr_promotie   || [],
      };
    }
    return { hoofdwerk: [], voorbereiding: [], afronding: [], pr_promotie: [] };
  });

  const [apart, setApart] = React.useState(() => ({
    reiskm:       state.apartOfferen?.reiskm       ?? 0,
    materiaal:    state.apartOfferen?.materiaal    ?? 0,
    inhuurDerden: state.apartOfferen?.inhuurDerden ?? 0,
  }));

  // AI suggesties (alleen als we timesheet-sjabloon hebben en omschrijving)
  const [aiSuggesties, setAiSuggesties] = React.useState(null);
  const [loadingAi, setLoadingAi] = React.useState(false);
  const [aiAfgewezen, setAiAfgewezen] = React.useState(false);
  const [aiError, setAiError] = React.useState(false);

  React.useEffect(() => {
    if (!huidigeRol) { back(); return; }
    if (!state.omschrijving || state.omschrijving.length < 10) return;
    if (!aiAfgewezen && !aiSuggesties && timesheetKey && Object.keys(sjabloon).length > 0) {
      const ctrl = new AbortController();
      setLoadingAi(true);
      window.aiHelp.suggestTimesheetUren(
        state.omschrijving, huidigeRol.rol, huidigeRol.niveau, sjabloon, { signal: ctrl.signal }
      ).then(r => {
        if (ctrl.signal.aborted) return;
        setLoadingAi(false);
        if (r) setAiSuggesties(r);
        else setAiError(true);
      });
      return () => ctrl.abort();
    }
  }, []);

  // Sync timesheet-state direct naar parent — bewaart invoer bij stap-wisselen
  React.useEffect(() => {
    if (!huidigeRol) return;
    const sumCat = (cat) => (rijen[cat] || []).reduce((s, r) => s + (Number(r.uren) || 0), 0);
    setState(s => ({
      ...s,
      btw21: true,
      apartOfferen: { ...apart },
      rollen: (s.rollen || []).map((r, i) => i === 0 ? {
        ...r,
        uren: {
          hoofdwerk:     sumCat("hoofdwerk"),
          voorbereiding: sumCat("voorbereiding"),
          afronding:     sumCat("afronding"),
          pr_promotie:   sumCat("pr_promotie"),
        },
        urenDetails: rijen,
      } : r),
    }));
  }, [rijen, apart]);

  const categorieen = [
    { key: "voorbereiding", label: "Voorbereiding",           hint: "Wat je doet vóór je kunt beginnen met het hoofdwerk." },
    { key: "hoofdwerk",     label: "Hoofdwerkzaamheden",      hint: "De kern van je opdracht — waar je de meeste tijd aan besteedt." },
    { key: "afronding",     label: "Afronding",               hint: "Wat je nog doet ná het hoofdwerk, tot je de opdracht echt afrondt." },
  ];
  if (sjabloon.pr_promotie?.length) {
    categorieen.push({ key: "pr_promotie", label: "PR & promotie", hint: "Optioneel — alleen als dit onderdeel is van de opdracht." });
  }

  const urenPerCat = (cat) => rijen[cat].reduce((s, r) => s + (Number(r.uren) || 0), 0);
  const urenTotaal = categorieen.reduce((s, c) => s + urenPerCat(c.key), 0);
  const subtotaalArbeid = urenTotaal * uurtarief;

  if (!huidigeRol) return null;

  // Match een AI-activiteit-naam tegen de officiële sjabloon-namen.
  // AI kort soms namen met haakjes-uitleg af ("Research" i.p.v. "Research (gesprekken voeren, ...)").
  const matchSjabloonNaam = (aiNaam, cat) => {
    const opties = sjabloon[cat] || [];
    if (!opties.length) return aiNaam;
    const norm = (s) => s.toLowerCase().trim();
    const ai = norm(aiNaam);
    // 1. exact
    let hit = opties.find(o => norm(o) === ai);
    if (hit) return hit;
    // 2. sjabloon begint met de AI-naam (typisch: "Research" → "Research (...)")
    hit = opties.find(o => norm(o).startsWith(ai + " (") || norm(o).startsWith(ai + ":"));
    if (hit) return hit;
    // 3. AI-naam komt voor in sjabloon (los van haakjes)
    const aiKern = ai.replace(/\s*\(.*?\)\s*/g, "").trim();
    hit = opties.find(o => {
      const oKern = norm(o).replace(/\s*\(.*?\)\s*/g, "").trim();
      return oKern === aiKern;
    });
    if (hit) return hit;
    // 4. geen match — laat AI-naam staan (verschijnt als losse rij)
    return aiNaam;
  };

  const neemAiOver = () => {
    if (!aiSuggesties?.suggesties) return;
    const nieuw = { hoofdwerk: [], voorbereiding: [], afronding: [], pr_promotie: [] };
    for (const cat of Object.keys(nieuw)) {
      const items = aiSuggesties.suggesties[cat];
      if (!Array.isArray(items)) continue;
      nieuw[cat] = items.map(s => ({
        id: window.crypto?.randomUUID?.() || `ai-${cat}-${Math.random()}`,
        activiteit: matchSjabloonNaam(s.activiteit, cat),
        uren: Number(s.uren) || 0,
        bron: "ai",
        reden: s.reden || "",
      }));
    }
    setRijen(nieuw);
    setAiSuggesties(null);
  };

  const commit = () => {
    const nieuweUren = {
      hoofdwerk:     urenPerCat("hoofdwerk"),
      voorbereiding: urenPerCat("voorbereiding"),
      afronding:     urenPerCat("afronding"),
      pr_promotie:   urenPerCat("pr_promotie"),
    };
    setState(s => ({
      ...s,
      btw21: true,
      apartOfferen: { ...apart },
      rollen: (s.rollen || []).map((r, i) => i === 0 ? {
        ...r,
        uren: nieuweUren,
        urenDetails: rijen,
      } : r),
    }));
    next();
  };

  return (
    <div>
      <StepHeader
        tag="Stap 3 — Timesheet"
        title="Hoeveel tijd gaat deze opdracht je kosten?"
        sub="Vul per rij in hoeveel uur de werkzaamheden je kosten. Je hoeft niet álles in te vullen — alleen wat je echt gaat doen. Reken ruim: de opslagfactor in het tarief houdt al rekening met offerte-tijd en administratie."
      />

      {huidigeRol && (
        <div className="role-summary" style={{
          display: "flex", gap: 14, alignItems: "center", flexWrap: "wrap",
          padding: "14px 18px", marginBottom: 20,
          background: FW.cream, border: `1.5px solid ${FW.gray100}`, borderRadius: 14,
        }}>
          <div style={{ fontSize: 14, color: FW.gray500, fontWeight: 700, textTransform: "uppercase", letterSpacing: 0.5 }}>Je rol</div>
          <div style={{ fontSize: 16, fontWeight: 700, color: FW.navy }}>{huidigeRol.rol}</div>
          <div style={{ fontSize: 14, color: FW.navy2 }}>· {huidigeRol.dep}</div>
          <NiveauBadge niveau={huidigeRol.niveau} />
          <div className="role-summary-spacer" style={{ marginLeft: "auto", fontSize: 14, color: FW.navy2 }}>
            Uurtarief: <b>{window.calc.fmt(uurtarief)}</b>
          </div>
        </div>
      )}

      <div className="row-2col" style={{ display: "grid", gridTemplateColumns: "1.3fr 1fr", gap: 24, alignItems: "start" }}>
        <div>
          {/* AI suggestie banner */}
          {loadingAi && (
            <div style={{ marginBottom: 20, padding: 14, background: FW.beige2, borderRadius: 14, fontSize: 14, color: FW.navy, display: "inline-flex", alignItems: "center", gap: 10 }}>
              <i className="ri-sparkling-2-line" />
              AI scant je omschrijving voor een schatting per categorie…
            </div>
          )}
          {!loadingAi && aiError && (
            <FwInlineBanner type="warning" onDismiss={() => setAiError(false)} style={{ marginBottom: 20 }}>
              <div style={{ fontWeight: 700, marginBottom: 4 }}>AI-suggestie mislukt — vul de uren zelf in.</div>
              {window.__lastAiError && (
                <div style={{ fontSize: 13, color: FW.navy2, fontFamily: "ui-monospace, monospace" }}>
                  {window.__lastAiError}
                </div>
              )}
            </FwInlineBanner>
          )}

          {aiSuggesties && (
            <AiTimesheetVoorstel
              voorstel={aiSuggesties}
              onOvernemen={neemAiOver}
              onSluiten={() => { setAiSuggesties(null); setAiAfgewezen(true); }}
            />
          )}

          {categorieen.map(c => (
            <TimesheetSectie
              key={c.key}
              label={c.label}
              hint={c.hint}
              sjabloonActiviteiten={sjabloon[c.key] || []}
              rijen={rijen[c.key]}
              setRijen={(nieuw) => setRijen(r => ({ ...r, [c.key]: nieuw }))}
              catKey={c.key}
              uurtarief={uurtarief}
            />
          ))}

          {/* Apart offreren */}
          <div style={{ marginTop: 28 }}>
            <div style={{ fontSize: 18, fontWeight: 700, color: FW.navy, marginBottom: 6 }}>Apart te offreren</div>
            <div style={{ fontSize: 14, color: FW.navy2, marginBottom: 14 }}>
              Deze posten horen niet in het uurtarief. Je mag ze bovenop je bod offreren.
            </div>
            <FwCard padded={true} style={{ padding: 22 }}>
              <div className="apart-grid" style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 16 }}>
                <NumField label="Reiskilometers (totaal)" value={apart.reiskm} onChange={(v) => setApart(a => ({ ...a, reiskm: v }))} min={0} max={50000} suffix="km" hint="€ 0,23/km (onbelast 2026)" />
                <NumField label="Materiaal / onkosten" value={apart.materiaal} onChange={(v) => setApart(a => ({ ...a, materiaal: v }))} min={0} max={1000000} suffix="€" hint="Bijv. aankopen voor kostuum, props" />
                <NumField label="Inhuur derden" value={apart.inhuurDerden} onChange={(v) => setApart(a => ({ ...a, inhuurDerden: v }))} min={0} max={1000000} suffix="€" hint="Assistenten, apparatuur" />
              </div>
            </FwCard>
          </div>

        </div>

        <AsideCard>
          <div style={{ fontSize: 14, fontWeight: 700, color: FW.navy, marginBottom: 10, display: "inline-flex", alignItems: "center", gap: 6 }}>
            <i className="ri-calculator-line" /> Lopend totaal
          </div>
          <div style={{ display: "grid", gap: 6, fontSize: 14, color: FW.navy2 }}>
            {categorieen.map(c => (
              <div key={c.key} style={{ display: "flex", justifyContent: "space-between" }}>
                <span>{c.label}</span>
                <span style={{ fontWeight: 700, color: FW.navy }}>{urenPerCat(c.key)} uur</span>
              </div>
            ))}
          </div>
          <div style={{ height: 1, background: FW.gray100, margin: "12px 0" }} />
          <div style={{ display: "flex", justifyContent: "space-between", fontSize: 15 }}>
            <span style={{ color: FW.navy2 }}>Totaal uren</span>
            <span style={{ fontWeight: 700, color: FW.navy }}>{urenTotaal} uur</span>
          </div>
          <div style={{ display: "flex", justifyContent: "space-between", fontSize: 14, marginTop: 4 }}>
            <span style={{ color: FW.navy2 }}>Uurtarief</span>
            <span style={{ color: FW.navy }}>{window.calc.fmt(uurtarief)}</span>
          </div>
          <div style={{
            marginTop: 14, padding: "14px 16px", background: FW.navy, borderRadius: 14,
            display: "flex", justifyContent: "space-between", alignItems: "baseline",
          }}>
            <span style={{ fontSize: 13, color: FW.yellow, fontWeight: 700, textTransform: "uppercase", letterSpacing: 0.5 }}>Openingsbod</span>
            <span style={{ fontSize: 22, fontWeight: 700, color: "#fff" }}>{window.calc.fmtInt(subtotaalArbeid)}</span>
          </div>
          <div style={{ fontSize: 12, color: FW.gray500, marginTop: 8, lineHeight: 1.4 }}>
            Excl. apart te offreren posten en btw. De onderhandeling gebeurt ná het openingsbod.
          </div>
        </AsideCard>
      </div>

      <div className="step-nav" style={{ marginTop: 32, display: "flex", justifyContent: "space-between" }}>
        <FwButton variant="ghost" arrow={false} onClick={back}>← Terug</FwButton>
        <FwButton variant="primary" onClick={commit} disabled={urenTotaal === 0}>
          Bekijk je openingsbod
        </FwButton>
      </div>
    </div>
  );
};

const AiTimesheetVoorstel = ({ voorstel, onOvernemen, onSluiten }) => {
  const cats = [
    { key: "voorbereiding", label: "Voorbereiding" },
    { key: "hoofdwerk", label: "Hoofdwerkzaamheden" },
    { key: "afronding", label: "Afronding" },
    { key: "pr_promotie", label: "PR & promotie" },
  ];
  const totPerCat = (k) => (voorstel.suggesties?.[k] || []).reduce((s, r) => s + (Number(r.uren) || 0), 0);
  const niets = cats.every(c => !(voorstel.suggesties?.[c.key]?.length));
  if (niets) return null;

  return (
    <div style={{ marginBottom: 20, padding: 18, background: "#FEF9B3", borderRadius: 16, border: `1.5px solid ${FW.yellow}` }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 8, fontSize: 13, fontWeight: 700, textTransform: "uppercase", letterSpacing: 0.5, color: FW.navy }}>
        <i className="ri-sparkling-2-line" /> Voorstel op basis van je omschrijving
      </div>
      {voorstel.toelichting && (
        <div style={{ fontSize: 14, color: FW.navy2, marginBottom: 12, lineHeight: 1.5 }}>{voorstel.toelichting}</div>
      )}
      <div style={{ display: "grid", gap: 10, marginBottom: 14 }}>
        {cats.map(c => {
          const items = voorstel.suggesties?.[c.key] || [];
          if (!items.length) return null;
          return (
            <div key={c.key}>
              <div style={{ fontSize: 14, fontWeight: 700, color: FW.navy, marginBottom: 4 }}>
                {c.label} <span style={{ color: FW.gray500, fontWeight: 500 }}>({totPerCat(c.key)} uur totaal)</span>
              </div>
              <ul style={{ margin: 0, paddingLeft: 18, fontSize: 14, color: FW.navy2, lineHeight: 1.5 }}>
                {items.map((it, i) => (
                  <li key={i}>{it.activiteit} — {it.uren} uur</li>
                ))}
              </ul>
            </div>
          );
        })}
      </div>
      <div style={{ display: "flex", gap: 10 }}>
        <FwButton variant="primary" small arrow={false} onClick={onOvernemen}>Alles overnemen</FwButton>
        <FwButton variant="ghost" arrow={false} onClick={onSluiten}>Zelf beginnen</FwButton>
      </div>
    </div>
  );
};

const TimesheetSectie = ({ label, hint, sjabloonActiviteiten, rijen, setRijen, catKey, uurtarief }) => {
  const [toonAlles, setToonAlles] = React.useState(false);
  const DEFAULT_TONEN = 5;

  const zichtbareActiviteiten = toonAlles
    ? sjabloonActiviteiten
    : sjabloonActiviteiten.slice(0, DEFAULT_TONEN);

  const setUrenVoorAct = (act, raw) => {
    const val = Math.min(500, Math.max(0, Number(raw) || 0));
    const bestaande = rijen.find(r => r.activiteit === act && !r.custom);
    if (val === 0 && bestaande) {
      setRijen(rijen.filter(r => r.id !== bestaande.id));
    } else if (val > 0 && !bestaande) {
      setRijen([...rijen, {
        id: window.crypto?.randomUUID?.() || `${catKey}-${Date.now()}-${Math.random()}`,
        activiteit: act,
        uren: val,
      }]);
    } else if (bestaande) {
      setRijen(rijen.map(r => r.id === bestaande.id ? { ...r, uren: val } : r));
    }
  };

  const updateUren = (id, uren) => {
    const val = Math.min(500, Math.max(0, Number(uren) || 0));
    setRijen(rijen.map(r => r.id === id ? { ...r, uren: val } : r));
  };

  const updateCustomLabel = (id, label) => {
    setRijen(rijen.map(r => r.id === id ? { ...r, activiteit: label } : r));
  };

  const verwijder = (id) => {
    setRijen(rijen.filter(r => r.id !== id));
  };

  const voegEigenToe = () => {
    setRijen([...rijen, {
      id: window.crypto?.randomUUID?.() || `${catKey}-custom-${Date.now()}`,
      activiteit: "",
      uren: 0,
      custom: true,
    }]);
  };

  const totaalUren = rijen.reduce((s, r) => s + (Number(r.uren) || 0), 0);
  const customRijen = rijen.filter(r => r.custom);

  return (
    <div style={{
      marginTop: 20, padding: 20, background: FW.white,
      border: `1.5px solid ${FW.gray100}`, borderRadius: 18,
    }}>
      <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", marginBottom: 4 }}>
        <div style={{ fontSize: 18, fontWeight: 700, color: FW.navy }}>{label}</div>
        <div style={{ fontSize: 14, color: FW.navy2 }}>
          Totaal: <b style={{ color: FW.navy }}>{totaalUren} uur</b>
          {uurtarief > 0 && totaalUren > 0 && (
            <span style={{ color: FW.gray500 }}> · {window.calc.fmt(totaalUren * uurtarief)}</span>
          )}
        </div>
      </div>
      {hint && <div style={{ fontSize: 13, color: FW.gray500, marginBottom: 14 }}>{hint}</div>}

      {sjabloonActiviteiten.length === 0 && (
        <div style={{ fontSize: 13, color: FW.gray500, fontStyle: "italic", padding: "10px 0" }}>
          Geen voorgevulde activiteiten voor dit departement — voeg ze hieronder zelf toe.
        </div>
      )}

      <div style={{ display: "grid", gap: 6 }}>
        {zichtbareActiviteiten.map((act, i) => {
          const rij = rijen.find(r => r.activiteit === act && !r.custom);
          const actief = !!rij && rij.uren > 0;
          return (
            <div key={i} style={{
              display: "flex", alignItems: "center", gap: 10,
              padding: "8px 10px",
              background: actief ? FW.cream : "transparent",
              borderRadius: 10,
              border: actief ? `1px solid ${FW.gray100}` : "1px solid transparent",
            }}>
              <div style={{ flex: 1, fontSize: 14, color: FW.navy, lineHeight: 1.4 }}>{act}</div>
              <div style={{ display: "flex", alignItems: "center", gap: 6, flexShrink: 0 }}>
                <input type="number" min="0"
                  value={rij?.uren ? rij.uren : ""}
                  placeholder="0"
                  onChange={e => setUrenVoorAct(act, e.target.value)}
                  style={{
                    width: 64, border: `1.5px solid ${FW.gray100}`, borderRadius: 8,
                    padding: "6px 8px", fontSize: 14, fontWeight: 700, color: FW.navy,
                    fontFamily: "var(--font-sans)", textAlign: "center", outline: "none", background: FW.white,
                  }} />
                <span style={{ fontSize: 13, color: FW.gray500 }}>uur</span>
              </div>
            </div>
          );
        })}
      </div>

      {sjabloonActiviteiten.length > DEFAULT_TONEN && (
        <button onClick={() => setToonAlles(!toonAlles)} style={{
          marginTop: 8, background: "transparent", border: 0, color: FW.navy,
          fontSize: 13, fontWeight: 700, cursor: "pointer", fontFamily: "var(--font-sans)",
          textDecoration: "underline", textUnderlineOffset: 3,
        }}>
          {toonAlles ? "Toon minder" : `Toon nog ${sjabloonActiviteiten.length - DEFAULT_TONEN} activiteit${sjabloonActiviteiten.length - DEFAULT_TONEN === 1 ? "" : "en"}`}
        </button>
      )}

      {/* Eigen rijen */}
      {customRijen.length > 0 && (
        <div style={{ marginTop: 14, display: "grid", gap: 6 }}>
          {customRijen.map(rij => (
            <div key={rij.id} style={{
              display: "flex", alignItems: "center", gap: 10,
              padding: "8px 10px", background: FW.cream, borderRadius: 10, border: `1px solid ${FW.gray100}`,
            }}>
              <i className="ri-edit-line" style={{ fontSize: 14, color: FW.gray500 }} />
              <input type="text" placeholder="Eigen activiteit…" value={rij.activiteit}
                onChange={e => updateCustomLabel(rij.id, e.target.value)}
                style={{
                  flex: 1, border: 0, background: "transparent", fontSize: 14, color: FW.navy,
                  fontFamily: "var(--font-sans)", outline: "none", padding: "4px 0",
                }} />
              <input type="number" min="0" value={rij.uren}
                onChange={e => updateUren(rij.id, e.target.value)}
                style={{
                  width: 64, border: `1.5px solid ${FW.gray100}`, borderRadius: 8,
                  padding: "6px 8px", fontSize: 14, fontWeight: 700, color: FW.navy,
                  fontFamily: "var(--font-sans)", textAlign: "center", outline: "none", background: FW.white,
                }} />
              <span style={{ fontSize: 13, color: FW.gray500 }}>uur</span>
              <button onClick={() => verwijder(rij.id)} title="Verwijder" style={{
                background: "transparent", border: 0, cursor: "pointer",
                color: FW.gray500, fontSize: 16, padding: 4,
              }}>×</button>
            </div>
          ))}
        </div>
      )}

      <button onClick={voegEigenToe} style={{
        marginTop: 12, background: "transparent", border: `1.5px dashed ${FW.gray100}`, color: FW.navy,
        borderRadius: 10, padding: "8px 14px", fontSize: 13, fontWeight: 700,
        cursor: "pointer", fontFamily: "var(--font-sans)",
      }}>
        + Voeg eigen activiteit toe
      </button>
    </div>
  );
};

const NumField = ({ label, value, onChange, min, max, suffix, hint }) => (
  <div>
    <div style={{ fontSize: 13, fontWeight: 700, color: FW.navy, marginBottom: 6 }}>{label}</div>
    <div style={{ display: "flex", alignItems: "center", border: `1.5px solid ${FW.gray100}`, borderRadius: 12, overflow: "hidden" }}>
      <button onClick={() => onChange(Math.max(min, (Number(value) || 0) - 1))} style={numBtn()}>−</button>
      <input type="number" value={value} min={min} max={max}
        onChange={e => onChange(e.target.value === "" ? 0 : Math.max(min, Math.min(max, Number(e.target.value))))}
        style={{
          flex: 1, border: 0, textAlign: "center", padding: "10px 0",
          fontFamily: "var(--font-sans)", fontSize: 17, fontWeight: 700, color: FW.navy, outline: "none",
          background: "transparent", fontVariantNumeric: "tabular-nums",
        }} />
      <button onClick={() => onChange(Math.min(max, (Number(value) || 0) + 1))} style={numBtn()}>+</button>
    </div>
    {suffix && <div style={{ fontSize: 12, color: FW.gray500, marginTop: 4, textAlign: "center" }}>{suffix}</div>}
    {hint && <div style={{ fontSize: 11, color: FW.gray500, marginTop: 4, lineHeight: 1.3 }}>{hint}</div>}
  </div>
);
const numBtn = () => ({
  width: 40, height: 40, border: 0, background: FW.cream, color: FW.navy,
  fontSize: 18, fontWeight: 700, cursor: "pointer", fontFamily: "var(--font-sans)",
});

window.StepTimesheet = StepTimesheet;
