/* Loops — Homepage v2 sections A: Seasons, Mechanics, Brain, Built kind, Who sees what */ const V2_SEASONS = [ { title: "Career and work", body: "The promotion you're working towards, the difficult conversation you've been avoiding, the work that builds your future." }, { title: "Money", body: "The goal you set, the habits that get you there, the honest conversations with yourself about spending." }, { title: "Exercise and physical health", body: "The fitness goal, the daily movement, the recovery you need to honour." }, { title: "Mood and mental health", body: "The patterns you can see across days, the support on the hard ones, the tools that work for your brain." }, { title: "Relationships", body: "The conversations worth having, the patterns worth changing, the work of being present." }, { title: "Exams and learning", body: "The qualification you're working towards, the daily revision, the long arc of getting good at something." }, { title: "Parenting", body: "Especially when you and your child are both wired differently. The work of showing up as the parent you want to be." }, { title: "The big questions", body: "Meaning, purpose, the things that come up at 2am." }, ]; const V2SeasonCard = ({ s, i }) =>

{s.title}

{s.body}

; const V2SeasonTicker = () => { const trackRef = React.useRef(null); const secondSetRef = React.useRef(null); const offset = React.useRef(0); const speed = React.useRef(1); const target = React.useRef(1); const dragging = React.useRef(false); const dragStartX = React.useRef(0); const dragStartOffset = React.useRef(0); const moved = React.useRef(false); const [reduced, setReduced] = React.useState(false); const [grabbing, setGrabbing] = React.useState(false); React.useEffect(() => { const mq = window.matchMedia("(prefers-reduced-motion: reduce)"); const update = () => setReduced(mq.matches); update(); mq.addEventListener("change", update); return () => mq.removeEventListener("change", update); }, []); const wrapValue = (v) => { const w = secondSetRef.current ? secondSetRef.current.offsetLeft : 0; if (w <= 0) return v; return (v % w + w) % w; }; React.useEffect(() => { if (reduced) return; let raf, last = null; const PX_PER_SEC = 34; const loop = (t) => { if (last == null) last = t; const dt = Math.min(0.05, (t - last) / 1000); last = t; if (!dragging.current) { speed.current += (target.current - speed.current) * Math.min(1, dt * 2.4); offset.current = wrapValue(offset.current + PX_PER_SEC * speed.current * dt); } if (trackRef.current) trackRef.current.style.transform = `translate3d(${-offset.current}px,0,0)`; raf = requestAnimationFrame(loop); }; raf = requestAnimationFrame(loop); return () => cancelAnimationFrame(raf); }, [reduced]); const slow = () => { if (!dragging.current) target.current = 0; }; const resume = () => { if (!dragging.current) target.current = 1; }; const onPointerDown = (e) => { dragging.current = true; moved.current = false; dragStartX.current = e.clientX; dragStartOffset.current = offset.current; speed.current = 0; target.current = 0; setGrabbing(true); e.currentTarget.setPointerCapture?.(e.pointerId); }; const onPointerMove = (e) => { if (!dragging.current) return; const dx = e.clientX - dragStartX.current; if (Math.abs(dx) > 3) moved.current = true; offset.current = wrapValue(dragStartOffset.current - dx); }; const endDrag = (e) => { if (!dragging.current) return; dragging.current = false; setGrabbing(false); const stillHovering = e.currentTarget.matches(":hover"); target.current = stillHovering ? 0 : 1; }; if (reduced) { return (
{V2_SEASONS.map((s, i) => )}
); } return (
{ if (moved.current) { e.preventDefault(); e.stopPropagation(); } }}>
{V2_SEASONS.map((s, i) => )} {V2_SEASONS.map((s, i) =>
)}
); }; const TravelSectionV2 = () =>

When your goals change, your Loops change too. The app stays the same. The actions, the rewards and the coaching adapt around you.

Most apps help with one part. Loops is built around all five.

    {V2_MECHANICS.map((m) => )}
; /* ---------------- Mechanics ---------------- */ const V2_MECHANICS = [ { n: "01", title: "Set a goal that matters", body: "Write it in your own words. Give it a season. Name exactly what done looks like. A goal with a finish line is something your brain can actually see." }, { n: "02", title: "Do small, doable Loops", body: "A Loop is an action small enough to start, so procrastination never gets a foothold. 30 press-ups a day. 3 runs a week. 2 hours of study. Reading to your daughter every night. Daily, weekly, hours per week, or one-offs. The commitment is the count. When you do it is your business." }, { n: "03", title: "Be seen by your Buddy", body: "Pick someone who matters. Your partner, your best mate, your mum. They see your progress as you complete Loops, and they can react with a tap. It's body doubling, built in: they don't nag, they don't manage you, they just get to watch you do the thing. That changes everything." }, { n: "04", title: "Feel the win", body: "Completing week streaks triggers rewards you choose for yourself. The gig tickets. The tattoo. The guilt-free Saturday. Your brain gets to feel the progress, not just the gap." }, { n: "05", title: "Talk to Dora", gloss: true, cta: { label: "Learn More About Dora", href: "/ai-coach/" }, body: "Dora is an AI coach who gets ADHD. Ask her anything about how your brain works, or let her suggest Loop ideas to move your goal along. She already knows your goal, your Loops and your history, so there's no explaining yourself from the start. And she's there at 11pm, which is when you actually need her." }, ]; const V2MechanicCard = ({ m }) =>
  • {m.n}

    {m.gloss ? {m.title} : m.title}

    {m.body}

    {m.cta ?
    : null}
  • ; const MechanicsSectionV2 = () =>
    {["Set a goal", "Do small Loops", "Be seen", "Feel the win", "Talk to Dora"].map((c) => {c} )}

    Most apps help with one part. Loops is built around all five.

      {V2_MECHANICS.map((m) => )}
    ; /* ---------------- Brain ---------------- */ const BrainSectionV2 = () =>

    That same care makes Loops work. For everyone.

    Loops is used by
      {[ "Parents helping their child revise for exams", "Career changers building towards the next thing", "Runners training for their first marathon", "Founders fundraising a Series A", "Recently bereaved people finding structure again", "Students preparing for finals"]. map((p) =>
    • {p}
    • )}

    For anyone trying to get good at something hard. The same app. The same coach. Different seasons, different goals, different Loops.

    If it works on the bad days, it works on the good ones. That's the design.

    ; /* ---------------- Built kind ---------------- */ const V2_KIND = [ { t: "Quiet by default", b: "At most three notifications a day. A morning round-up, an afternoon check-in only if nothing's happening, and a kind word in the evening. When you're on track, we stay silent." }, { t: "Rest days", b: "Four a month, no questions asked. Your streaks survive." }, { t: "Away mode", b: "Holidays, illness, life. Everything pauses. Nothing is lost. No guilt when you come back." }, { t: "No \u201Cstreak broken\u201D", b: "No \u201Cwe miss you\u201D. A missed day is information, not failure." }, ]; const BuiltKindV2 = () =>
    {V2_KIND.map((k) =>

    {k.t}

    {k.b}

    )}
    ; /* ---------------- Who sees what ---------------- */ const WhoSeesWhatV2 = () =>
    Who sees what

    Your work, not your diary.

    Your Buddy sees the work, never the diary. The Loops you've closed and the streaks you've built. That's it.

    Your conversations with Dora are always private. Nothing is sold. There are no advertisers.

    ; Object.assign(window, { TravelSectionV2, MechanicsSectionV2, BrainSectionV2, BuiltKindV2, WhoSeesWhatV2 });