// Rule Breaker Reset — session app
// Single React app. State persists to localStorage AND Supabase.
// Step-by-step navigation.
//
// All editable copy lives in COPY below. Tweaks panel exposes it inline,
// and a "Copy all language" button copies the whole block as JSON-like text
// the user can edit and paste back.

const { useState, useEffect, useMemo, useRef } = React;

// ── Supabase client ───────────────────────────────────────────────
const SUPABASE_URL  = 'https://uofbtwpfzkyjknlervph.supabase.co';
const SUPABASE_KEY  = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InVvZmJ0d3Bmemt5amtubGVydnBoIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzc5MjE1MDYsImV4cCI6MjA5MzQ5NzUwNn0.x4LqTN7ABYaW5AHLAwyDvH-8BOvoyvCvHHYmT2z3toQ';
const db = window.supabase.createClient(SUPABASE_URL, SUPABASE_KEY);

async function saveToSupabase(email, state) {
  const today = new Date().toISOString().split('T')[0];
  await db.from('sessions').upsert({
    email:        email.toLowerCase().trim(),
    session_date: today,
    step_index:   state.stepIndex || 0,
    state_json:   state,
    updated_at:   new Date().toISOString(),
  }, { onConflict: 'email,session_date' });
}

// Retrieve all previous sessions for an email — used by the future
// "show prior session alongside current" feature.
async function getPreviousSessions(email) {
  const { data } = await db
    .from('sessions')
    .select('*')
    .eq('email', email.toLowerCase().trim())
    .order('session_date', { ascending: false });
  return data || [];
}

const LS_KEY = 'rbr-session-v1';

// ── EDITABLE COPY ─────────────────────────────────────────────────
const COPY_DEFAULTS = {
  // Welcome
  welcome_h: `Welcome to the Rule Breaker Reset.`,
  welcome_body: `Enter your email`,
  welcome_cta: `Let's go`,

  // Check in
  checkin_eyebrow: `get out of your head and into the room`,
  checkin_h: `Check in`,
  checkin_body: ``,
  checkin_q1: `What's your word for today?`,
  checkin_q1_ph: `Scattered. Caffeinated. Tired but here.`,
  checkin_q2: `What's filling your cup?`,
  checkin_q2_ph: `What's giving you energy — even a little.`,
  checkin_q3: `What's draining your cup?`,
  checkin_q3_ph: `What's taking energy away.`,

  // Norms
  norms_eyebrow: `set the container before we start`,
  norms_h: `Group Norms`,
  norms_1_t: `Confidentiality.`,
  norms_1_d: `What's said here, stays here.`,
  norms_2_t: `Conscientious.`,
  norms_2_d: `Mind your air time. Share experiences, not advice.`,
  norms_3_t: `Supportive.`,
  norms_3_d: `Be kind to yourself and everyone else.`,
  norms_4_t: `Cameras on, if you can.`,
  norms_4_d: `Showing up for each other is part of the benefit.`,
  norms_in: `Drop a 👍 in chat if you're game.`,

  // Why you're here
  why_eyebrow: `the muscle we'll build`,
  why_h: `Why We're Here`,
  why_p1: `We're here to figure out why we end the day feeling like we're failing - even though we never stopped trying.`,
  why_p2: `Us high-achieving working parents face a heaping pile of unrealistic expectations: work like you don't have kids, parent like you don't have a job, and be a self-care guru at the same time.`,
  why_p3: `You're capable of all of it. You just don't have the capacity to do it all at once.`,
  why_p4: `Instead of trying to be more, better, different we're going to practice the Rule Breaker Way.`,
  why_p5: `We'll move through three steps: Awareness > Choice > Enoughness to build the muscle to decide which expectations deserve your energy and let the rest go.`,

  // Pile
  pile_career_h: `Career`,
  pile_career_intro: `Which of these expectations are you're holding?`,
  pile_career_intro2: `Include ones you're doing it, or you think you should be. These are the things your inner critic is keeping track of.`,
  pile_caregiving_h: `Caregiving`,
  pile_self_h: `Self`,

  // Count
  count_eyebrow: `what you're holding`,
  count_h: `Your Pile`,
  count_lbl: `rules.`,
  count_body: `That's the heaping pile. Not bad. Not good. Just what you're carrying.`,

  // Pride
  pride_eyebrow: `who you are in this pile`,
  pride_h: `Your Identity`,
  pride_body: `Finish the sentence: I pride myself in being...`,
  pride_prompt: `List as many as come to mind. These are the things that make you feel valuable and worthy across your work, your parenting, your relationships, the way you treat yourself, and your community.`,
  pride_ph: `Always being reliable for my team. Knowing what's in the fridge. Showing up.`,
  pride_aside: `This helps us know which rules will feel the stickiest. Like why baking 36 muffins to freeze for school snacks fills my organized, health-conscious self with immense sense of enoughness.`,

  // Pick
  pick_eyebrow: `which one matters most this month?`,
  pick_h: `Pick Your One`,
  pick_body: `Pick your one f@ck to give.`,
  pick_aside: `You're not tattooing this on your forehead. You're picking the one that wins the tug of war when overwhelm hits - and trusting the rest will get done.`,

  // Tailor
  tailor_eyebrow: `make this rule accentuate your assets`,
  tailor_h: `Tailor Your Rule`,
  tailor_body: `This is the rule you chose. Now shape it to a version that that'll actually work for you.`,
  tailor_values_label: `Values`,
  tailor_values_hint: `Why does this rule matter to you?`,
  tailor_values_ph: `Pride. Calm. Modeling something for my kids. Feeling like myself again.`,
  tailor_strengths_label: `Strengths`,
  tailor_strengths_hint: `What are you actually good at - and what are you not? This rule has to live with your unique wiring.`,
  tailor_strengths_ph: `I'm consistent in small batches. I burn out on big systems. I'm better in the morning.`,
  tailor_situation_label: `Situation`,
  tailor_situation_hint: `What's actually true about your life right now? Not two years ago or next month - right now.`,
  tailor_situation_ph: `Three kids under five. Partner travels. New role at work. No bandwidth for new systems.`,
  tailor_aside: `"Work out five times a week" looks different for a single dad with ADHD who values fitness because it keeps them emotionally stable than it does for a stay at home mom with a nanny who does classes for social relationships.`,

  // Rule
  rule_eyebrow: `choose what will matter most this month`,
  rule_h: `Rule Maker`,
  rule_body: `Make your rule specific to you by using what you said about your values, your strengths, and your situation.`,
  rule_label: `Your tailored rule for this month`,
  rule_hint: `Specific enough that you'll know if you honored it.`,
  rule_ph: `Work out Mon/Wed/Fri at 6am for 30 minutes — even if it's short.`,
  rule_example_lbl: `Generic → Tailored`,
  rule_example: `"Pursue a stretch project." → "Take two nights each week to work late, and ask my partner to sub in on bedtime so I can dial in."`,

  // Corner
  corner_eyebrow: `choose one rule that sits in the corner`,
  corner_h: `Rule Breaker`,
  corner_body: `Choose one rule you will intentionally break this month. This isn't forever or because it doesn't matter. But asking one rule to sit in the corner is how you shush the annoying critic in your head.`,
  corner_rule_label: `The rule I'm putting in the corner`,
  corner_rule_hint: `Name it specifically — not "self-care," but what exactly you're not doing this month.`,
  corner_rule_ph: `Skipping the gym this month.`,
  corner_story_label: `What I'm telling myself instead`,
  corner_story_ph: `Skipping the gym this month isn't laziness. It's a choice I'm making so I can show up for the thing that actually matters right now.`,
  corner_aside: `Most rules we drop and feel bad about it. Naming it on purpose - and what it does or doesn't say about who we are - is the difference between failing and enough.`,

  // Why matters
  whymatters_eyebrow: `make your rule larger than you`,
  whymatters_h: `Your Why`,
  whymatters_body: `You shaped the rule. Now make it matter for a reason larger than yourself.`,
  whymatters_ph: ``,
  whymatters_aside: `When your goal is bigger than just you, the pressure drops and a setback is just a data point, not a verdict on your worth.`,

  // Enough look
  enough_eyebrow: `how will you know you honoured this rule?`,
  enough_h: `Enough`,
  enough_body: `What does enough look like? Make it specific so you'll know if it happened instead of feeling like there could have been more.`,
  enough_ph: ``,
  enough_aside: `Enoughness isn't a feeling that arrives on its own. It's a decision. You have to know what you're measuring against otherwise you'll always find a reason you needed to be more.`,

  // Room
  room_eyebrow: `you're not doing this alone`,
  room_h: `The Room`,
  room_body: `Each person's tailored rule and what they're putting in the corner.`,

  // Pillow
  pillow_eyebrow: `note what you learned about yourself`,
  pillow_h: `Your pillow note.`,
  pillow_lead: `What is something true thing about yourself that you want to remember?`,
  pillow_ph: ``,
  pillow_cta: `Save`,

  // Close
  close_eyebrow: `Yay`,
  close_h: `You did the thing.`,
  close_rule_lbl: `Your tailored rule for this month`,
  close_corner_lbl: `The rule sitting in the corner`,
  close_signoff: `Sending enoughness`,
};

// ── data: every step ──────────────────────────────────────────────
const PILE = {
  Career: [
    `Do the best work I can`,
    `Stay visible in the room, on Slack, in the right conversations`,
    `Develop new skills`,
    `Network`,
    `Take stretch projects`,
    `Get strong reviews`,
    `Mentor others`,
    `Protect my reputation`,
    `Hit the numbers`,
    `Spend time on the strategic stuff`,
  ],
  Caregiving: [
    `Be home at night consistently`,
    `Provide nutritious meals`,
    `Have a tight bond with each kid`,
    `Limit screen time`,
    `Support enrichment through activities and extracurriculars`,
    `Be patient and regulated`,
    `Make core memories with holidays, parties, and trips`,
    `Know their teacher and their friends' names`,
    `Keep a clean and organized home`,
  ],
  Self: [
    `Work out consistently`,
    `Get enough sleep`,
    `Maintain friendships`,
    `Skincare and anti-aging`,
    `Read real books`,
    `Spend quality time with partner`,
    `Hobbies`,
    `Therapy`,
  ],
};

const STEPS = [
  { id: 'welcome',         phase: -1 },
  { id: 'checkin',         phase: -1 },
  { id: 'norms',           phase: -1 },
  { id: 'why',             phase: -1 },
  { id: 'pride',           phase: 0 },
  { id: 'pile-career',     phase: 0 },
  { id: 'pile-caregiving', phase: 0 },
  { id: 'pile-self',       phase: 0 },
  { id: 'count',           phase: 0 },
  { id: 'corner',          phase: 1 },
  { id: 'pick',            phase: 1 },
  { id: 'tailor',          phase: 1 },
  { id: 'rule',            phase: 1 },
  { id: 'why-matters',     phase: 2 },
  { id: 'enough-look',     phase: 2 },
  { id: 'room',            phase: 3 },
  { id: 'pillow',          phase: 3 },
  { id: 'close',           phase: 3 },
];

// ── persistence ───────────────────────────────────────────────────
function loadState() {
  try { return JSON.parse(localStorage.getItem(LS_KEY)) || {}; } catch (e) { return {}; }
}
function saveState(s) {
  try { localStorage.setItem(LS_KEY, JSON.stringify(s)); } catch (e) {}
}

// ── primitives ────────────────────────────────────────────────────
function PhaseIndicator({ phase }) {
  if (phase < 0) return null;
  const phases = ['Awareness', 'Choice', 'Enoughness'];
  return (
    <div className="rbr-phase">
      {phases.map((p, i) =>
        <React.Fragment key={p}>
          <span className={`rbr-phase-step${i === phase ? ' active' : i < phase ? ' done' : ''}`} style={{ color: "rgb(14, 25, 45)" }}>
            <span className="rbr-phase-dot"></span>
            {p}
          </span>
          {i < phases.length - 1 && <span className="rbr-phase-arrow">→</span>}
        </React.Fragment>
      )}
    </div>
  );
}

function Topbar({ phase }) {
  return (
    <div className="rbr-topbar" style={{ backgroundColor: "rgb(243, 234, 252)" }}>
      <a href="#" className="rbr-logo" aria-label="Rule Breaker Reset">
        <img src="brand/logo-wordmark-dark.svg" alt="Rule Breaker" />
        <span className="rbr-logo-suffix">Reset</span>
      </a>
      <PhaseIndicator phase={phase} />
      <span className="rbr-saved">saved</span>
    </div>
  );
}

function FooterNav({ canBack, canNext, onBack, onNext, nextLabel = 'Next →', backLabel = '← Back' }) {
  return (
    <div className="rbr-footer-nav">
      {canBack ? <button className="rbr-btn ghost" onClick={onBack}>{backLabel}</button> : <span />}
      <button className="rbr-btn" disabled={!canNext} onClick={onNext}>{nextLabel}</button>
    </div>
  );
}

// ── individual screen renderers ───────────────────────────────────

function ScrWelcome({ s, set, next, c }) {
  const ok = (s.email || '').includes('@');
  return (
    <div className="rbr-screen" style={{ gap: 40 }}>
      <div className="rbr-stack" style={{ gap: 28 }}>
        <div className="rbr-h rbr-h-1">
          Welcome to the<br />
          <span className="script">Rule Breaker Reset.</span>
        </div>
      </div>
      <div className="rbr-stack" style={{ gap: 14, marginTop: 16 }}>
        <div className="rbr-body" style={{ maxWidth: 460 }}>{c.welcome_body}</div>
        <div className="rbr-field" style={{ maxWidth: 460 }}>
          <input className="rbr-input" type="email" placeholder="you@email.com"
            value={s.email || ''} onChange={(e) => set({ email: e.target.value })} />
        </div>
      </div>
      <FooterNav canBack={false} canNext={ok} onNext={next} nextLabel={`${c.welcome_cta} →`} />
    </div>
  );
}

function ScrCheckIn({ s, set, next, back, c }) {
  const ok = (s.word || '').trim() && (s.filling || '').trim() && (s.draining || '').trim();
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.checkin_h}</div>
      <div className="rbr-eyebrow">{c.checkin_eyebrow}</div>
      <div className="rbr-body">{c.checkin_body}</div>
      <div className="rbr-stack rbr-gap-5">
        <div className="rbr-field">
          <label>{c.checkin_q1}</label>
          <input className="rbr-input" placeholder={c.checkin_q1_ph}
            value={s.word || ''} onChange={(e) => set({ word: e.target.value })} />
        </div>
        <div className="rbr-field">
          <label>{c.checkin_q2}</label>
          <textarea className="rbr-textarea" placeholder={c.checkin_q2_ph}
            value={s.filling || ''} onChange={(e) => set({ filling: e.target.value })} />
        </div>
        <div className="rbr-field">
          <label>{c.checkin_q3}</label>
          <textarea className="rbr-textarea" placeholder={c.checkin_q3_ph}
            value={s.draining || ''} onChange={(e) => set({ draining: e.target.value })} />
        </div>
      </div>
      <FooterNav canBack canNext={ok} onBack={back} onNext={next} />
    </div>
  );
}

function ScrNorms({ next, back, c }) {
  const norms = [
    ['01', c.norms_1_t, c.norms_1_d],
    ['02', c.norms_2_t, c.norms_2_d],
    ['03', c.norms_3_t, c.norms_3_d],
    ['04', c.norms_4_t, c.norms_4_d],
  ];
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.norms_h}</div>
      <div className="rbr-eyebrow">{c.norms_eyebrow}</div>
      <div className="rbr-norms">
        {norms.map(([n, t, d]) =>
          <div key={n} className="rbr-norm">
            <div className="n">{n}</div>
            <div>
              <div className="t">{t}</div>
              <div className="d">{d}</div>
            </div>
          </div>
        )}
      </div>
      <div className="rbr-norms-in">{c.norms_in}</div>
      <FooterNav canBack canNext onBack={back} onNext={next} />
    </div>
  );
}

function ScrWhy({ next, back, c }) {
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.why_h}</div>
      <div className="rbr-eyebrow">{c.why_eyebrow}</div>
      <div className="rbr-body" style={{ maxWidth: 560 }}>{c.why_p1}</div>
      <div className="rbr-body" style={{ maxWidth: 560 }}>{c.why_p2}</div>
      <div className="rbr-body" style={{ maxWidth: 560 }}>{c.why_p3}</div>
      <div className="rbr-body" style={{ maxWidth: 560 }}>{c.why_p4}</div>
      <div className="rbr-body" style={{ maxWidth: 560 }}>{c.why_p5}</div>
      <FooterNav canBack canNext onBack={back} onNext={next} />
    </div>
  );
}

function ScrPile({ s, set, next, back, category, listIndex, c }) {
  const items = PILE[category];
  const checked = s.pile?.[category] || {};
  const own = s.pileOwn?.[category] || [''];

  function toggle(label) {
    const nx = { ...checked, [label]: !checked[label] };
    set({ pile: { ...(s.pile || {}), [category]: nx } });
  }
  function setOwnAt(i, v) {
    const arr = [...own]; arr[i] = v;
    if (i === arr.length - 1 && v.trim() !== '') arr.push('');
    set({ pileOwn: { ...(s.pileOwn || {}), [category]: arr } });
  }
  function removeOwn(i) {
    const arr = [...own]; arr.splice(i, 1);
    if (arr.length === 0) arr.push('');
    set({ pileOwn: { ...(s.pileOwn || {}), [category]: arr } });
  }

  return (
    <div className="rbr-screen">
      <div className="rbr-stack rbr-gap-3">
        <div className="rbr-h rbr-h-2">The Pile</div>
        <div className="rbr-pile-chips" role="tablist" aria-label="Pile categories">
          {[
            { key: 'Career',     label: 'Career' },
            { key: 'Caregiving', label: 'Caregiving' },
            { key: 'Self',       label: 'Self-Care' },
          ].map((cat, i) =>
            <span
              key={cat.key}
              className={`rbr-pile-chip${i === listIndex ? ' active' : ''}${i < listIndex ? ' done' : ''}`}
              role="tab"
              aria-selected={i === listIndex}>
              {cat.label}
            </span>
          )}
        </div>
      </div>

      <div className="rbr-body">{c.pile_career_intro}</div>
      <div className="rbr-body">{c.pile_career_intro2}</div>

      <div className="rbr-checklist">
        {items.map((label) =>
          <div key={label} className={`rbr-check-row${checked[label] ? ' checked' : ''}`} onClick={() => toggle(label)}>
            <span className="rbr-checkbox" />
            <span>{label}</span>
          </div>
        )}
        {own.map((val, i) => {
          const filled = val.trim() !== '';
          return (
            <div key={`own-${i}`} className={`rbr-add-row${filled ? ' filled' : ''}`}>
              <span className="rbr-checkbox" style={filled ? null : { borderStyle: 'dashed', opacity: 0.5 }} />
              <input
                placeholder={i === 0 ? 'add your own' : 'add another'}
                value={val}
                onChange={(e) => setOwnAt(i, e.target.value)} />
              {filled &&
                <button className="rbr-add-x" onClick={() => removeOwn(i)} aria-label="remove">×</button>}
            </div>
          );
        })}
      </div>

      <FooterNav canBack canNext onBack={back} onNext={next} />
    </div>
  );
}

function getAllChecked(s) {
  const out = [];
  for (const cat of Object.keys(PILE)) {
    const checked = s.pile?.[cat] || {};
    for (const item of PILE[cat]) if (checked[item]) out.push({ cat, item });
    const own = s.pileOwn?.[cat] || [];
    for (const v of own) {
      if (typeof v === 'string' && v.trim()) out.push({ cat, item: v.trim(), custom: true });
    }
  }
  return out;
}

function ScrCount({ s, next, back, c }) {
  const total = getAllChecked(s).length;
  return (
    <div className="rbr-screen" style={{ alignItems: 'flex-start' }}>
      <div className="rbr-h rbr-h-2">{c.count_h}</div>
      <div className="rbr-eyebrow">{c.count_eyebrow}</div>
      <div className="rbr-count">
        <span className="num">{total || '—'}</span>
        <span className="lbl">{c.count_lbl}</span>
      </div>
      <div className="rbr-body" style={{ maxWidth: 460 }}>{c.count_body}</div>
      <FooterNav canBack canNext onBack={back} onNext={next} />
    </div>
  );
}

function ScrPride({ s, set, next, back, c }) {
  const ok = (s.pride || '').trim().length >= 4;
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.pride_h}</div>
      <div className="rbr-eyebrow">{c.pride_eyebrow}</div>
      <div className="rbr-body">{c.pride_body}</div>
      <div className="rbr-body" style={{ color: 'rgba(14,25,45,0.6)', fontStyle: 'italic' }}>{c.pride_prompt}</div>
      <textarea className="rbr-textarea" style={{ minHeight: 160 }}
        placeholder={c.pride_ph}
        value={s.pride || ''} onChange={(e) => set({ pride: e.target.value })} />
      <div className="rbr-aside">{c.pride_aside}</div>
      <FooterNav canBack canNext={ok} onBack={back} onNext={next} />
    </div>
  );
}

function ScrPick({ s, set, next, back, c }) {
  const all = getAllChecked(s).filter(({ cat, item }) => `${cat}::${item}` !== s.cornerPicked);
  const picked = s.pickedOne;
  function pick(key) { set({ pickedOne: key }); }
  const ok = !!picked;
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.pick_h}</div>
      <div className="rbr-eyebrow">{c.pick_eyebrow}</div>
      <div className="rbr-body">{c.pick_body}</div>
      <div className="rbr-aside">{c.pick_aside}</div>

      <div className="rbr-stack rbr-gap-3">
        {all.length === 0 && <div className="rbr-body" style={{ fontStyle: 'italic' }}>Go back and check at least one rule on the pile.</div>}
        {all.map(({ cat, item }) => {
          const key = `${cat}::${item}`;
          return (
            <div key={key} className={`rbr-pick-row${picked === key ? ' selected' : ''}`} onClick={() => pick(key)}>
              <span className="cat">{cat}</span>
              <span className="text">{item}</span>
              <span className="check" />
            </div>
          );
        })}
      </div>

      <FooterNav canBack canNext={ok} onBack={back} onNext={next} />
    </div>
  );
}

function pickedLabel(s) {
  if (!s.pickedOne) return '—';
  return s.pickedOne.split('::')[1];
}

function ScrTailor({ s, set, next, back, c }) {
  const ok = (s.tValues || '').trim() && (s.tStrengths || '').trim() && (s.tSituation || '').trim();
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.tailor_h}</div>
      <div className="rbr-eyebrow">{c.tailor_eyebrow}</div>
      <div className="rbr-chosen-rule">
        <div className="rbr-chosen-rule__val">{pickedLabel(s)}</div>
        <div className="rbr-chosen-rule__lbl">{c.tailor_body}</div>
      </div>

      <div className="rbr-stack rbr-gap-5">
        <div className="rbr-field">
          <label>{c.tailor_values_label}</label>
          <div className="hint">{c.tailor_values_hint}</div>
          <textarea className="rbr-textarea" placeholder={c.tailor_values_ph}
            value={s.tValues || ''} onChange={(e) => set({ tValues: e.target.value })} />
        </div>
        <div className="rbr-field">
          <label>{c.tailor_strengths_label}</label>
          <div className="hint">{c.tailor_strengths_hint}</div>
          <textarea className="rbr-textarea" placeholder={c.tailor_strengths_ph}
            value={s.tStrengths || ''} onChange={(e) => set({ tStrengths: e.target.value })} />
        </div>
        <div className="rbr-field">
          <label>{c.tailor_situation_label}</label>
          <div className="hint">{c.tailor_situation_hint}</div>
          <textarea className="rbr-textarea" placeholder={c.tailor_situation_ph}
            value={s.tSituation || ''} onChange={(e) => set({ tSituation: e.target.value })} />
        </div>
      </div>

      <div className="rbr-aside">{c.tailor_aside}</div>
      <FooterNav canBack canNext={ok} onBack={back} onNext={next} />
    </div>
  );
}

function ScrRule({ s, set, next, back, c }) {
  const ok = (s.tailoredRule || '').trim().length >= 8;
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.rule_h}</div>
      <div className="rbr-eyebrow">{c.rule_eyebrow}</div>
      <div className="rbr-body">{c.rule_body}</div>

      <div className="rbr-stack rbr-gap-3">
        <div className="rbr-pull-card"><div className="lbl">The rule you chose</div><div className="val">{pickedLabel(s)}</div></div>
        <div className="rbr-pull-card"><div className="lbl">Values</div><div className="val">{s.tValues || '—'}</div></div>
        <div className="rbr-pull-card"><div className="lbl">Strengths</div><div className="val">{s.tStrengths || '—'}</div></div>
        <div className="rbr-pull-card"><div className="lbl">Situation</div><div className="val">{s.tSituation || '—'}</div></div>
      </div>

      <div className="rbr-field">
        <label>{c.rule_label}</label>
        <div className="hint">{c.rule_hint}</div>
        <textarea className="rbr-textarea" style={{ minHeight: 100, fontSize: 18, fontFamily: 'Archivo', fontWeight: 500 }}
          placeholder={c.rule_ph}
          value={s.tailoredRule || ''} onChange={(e) => set({ tailoredRule: e.target.value })} />
      </div>

      <div className="rbr-stack rbr-gap-3 rbr-mt-2">
        <div className="rbr-tiny">Example</div>
        <div className="rbr-pull-card" style={{ background: '#fff', borderColor: 'rgba(14,25,45,0.1)' }}>
          <div className="lbl" style={{ color: 'rgba(14,25,45,0.5)' }}>{c.rule_example_lbl}</div>
          <div className="val">{c.rule_example}</div>
        </div>
      </div>

      <FooterNav canBack canNext={ok} onBack={back} onNext={next} />
    </div>
  );
}

function ScrCorner({ s, set, next, back, c }) {
  const candidates = getAllChecked(s);
  const cornerKey = s.cornerPicked || '';
  const isCustom = cornerKey === '__custom__';

  function pickCorner(key, label) {
    set({ cornerPicked: key, cornerRule: key === '__custom__' ? s.cornerRule || '' : label });
  }

  const ok = (s.cornerRule || '').trim() && (s.cornerStory || '').trim();

  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.corner_h}</div>
      <div className="rbr-eyebrow">{c.corner_eyebrow}</div>
      <div className="rbr-body">{c.corner_body}</div>

      <div className="rbr-stack rbr-gap-3">
        <div className="rbr-tiny">From your pile · pick one to put down</div>
        {candidates.length === 0 &&
          <div className="rbr-body" style={{ fontStyle: 'italic' }}>No rules left on the pile. Add a custom one below.</div>
        }
        {candidates.map(({ cat, item }) => {
          const key = `${cat}::${item}`;
          return (
            <div key={key}
              className={`rbr-pick-row${cornerKey === key ? ' selected' : ''}`}
              onClick={() => pickCorner(key, item)}>
              <span className="cat">{cat}</span>
              <span className="text">{item}</span>
              <span className="check" />
            </div>
          );
        })}
        <div
          className={`rbr-pick-row${isCustom ? ' selected' : ''}`}
          onClick={() => pickCorner('__custom__', s.cornerRule || '')}>
          <span className="cat">Other</span>
          {isCustom
            ? <input
                className="rbr-input"
                style={{ flex: 1, border: 'none', background: 'transparent', padding: 0, fontFamily: 'inherit', fontSize: 'inherit' }}
                placeholder="Name it specifically…"
                value={s.cornerRule || ''}
                onChange={(e) => { e.stopPropagation(); set({ cornerRule: e.target.value }); }}
                onClick={(e) => e.stopPropagation()}
                autoFocus />
            : <span className="text" style={{ fontStyle: 'italic', opacity: 0.75 }}>Something else I'm carrying…</span>
          }
          <span className="check" />
        </div>
      </div>

      <div className="rbr-field">
        <label>{c.corner_story_label}</label>
        <textarea className="rbr-textarea" placeholder={c.corner_story_ph}
          value={s.cornerStory || ''} onChange={(e) => set({ cornerStory: e.target.value })} />
      </div>

      <div className="rbr-aside">{c.corner_aside}</div>
      <FooterNav canBack canNext={ok} onBack={back} onNext={next} />
    </div>
  );
}

function ScrWhyMatters({ s, set, next, back, c }) {
  const ok = (s.whyMatters || '').trim().length >= 8;
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.whymatters_h}</div>
      <div className="rbr-eyebrow">{c.whymatters_eyebrow}</div>
      <div className="rbr-body">{c.whymatters_body}</div>
      <textarea className="rbr-textarea" style={{ minHeight: 140 }}
        placeholder={c.whymatters_ph}
        value={s.whyMatters || ''} onChange={(e) => set({ whyMatters: e.target.value })} />
      <div className="rbr-aside">{c.whymatters_aside}</div>
      <FooterNav canBack canNext={ok} onBack={back} onNext={next} />
    </div>
  );
}

function ScrEnoughLook({ s, set, next, back, c }) {
  const ok = (s.enoughLook || '').trim().length >= 8;
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.enough_h}</div>
      <div className="rbr-eyebrow">{c.enough_eyebrow}</div>
      <div className="rbr-body">{c.enough_body}</div>
      <textarea className="rbr-textarea" style={{ minHeight: 140 }}
        placeholder={c.enough_ph}
        value={s.enoughLook || ''} onChange={(e) => set({ enoughLook: e.target.value })} />
      <div className="rbr-aside">{c.enough_aside}</div>
      <FooterNav canBack canNext={ok} onBack={back} onNext={next} />
    </div>
  );
}


function ScrRoom({ s, next, back, c }) {
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2">{c.room_h}</div>
      <div className="rbr-eyebrow">{c.room_eyebrow}</div>
      <div className="rbr-body">{c.room_body}</div>

      <table className="rbr-room">
        <thead>
          <tr><th style={{ width: 110 }}>Name</th><th>My one this month</th><th>Sitting in the corner</th></tr>
        </thead>
        <tbody>
          <tr className="you">
            <td className="name">You</td>
            <td className="one">{s.tailoredRule || '—'}</td>
            <td className="corner">{s.cornerRule || '—'}</td>
          </tr>
        </tbody>
      </table>

      <div className="rbr-row" style={{ justifyContent: 'space-between' }}>
        <span className="rbr-tiny">Updated just now</span>
        <button className="rbr-btn ghost">↻ Refresh</button>
      </div>

      <FooterNav canBack canNext onBack={back} onNext={next} />
    </div>
  );
}

function ScrPillow({ s, set, next, back, c }) {
  const ok = (s.pillow || '').trim().length >= 6;
  return (
    <div className="rbr-screen">
      <div className="rbr-h rbr-h-2"><span className="script">{c.pillow_h}</span></div>
      <div className="rbr-eyebrow">{c.pillow_eyebrow}</div>
      <div className="rbr-lead" style={{ maxWidth: 540, marginTop: 4 }}>{c.pillow_lead}</div>
      <textarea className="rbr-textarea pillow-note-input" placeholder={c.pillow_ph}
        value={s.pillow || ''} onChange={(e) => set({ pillow: e.target.value })} />
      <FooterNav canBack canNext={ok} onBack={back} onNext={next} nextLabel={`${c.pillow_cta} →`} />
    </div>
  );
}

function ScrClose({ s, back, restart, c }) {
  return (
    <div className="rbr-screen">
      <div className="rbr-close">
        <div className="rbr-close-eyebrow">{c.close_eyebrow}</div>

        <div className="rbr-h rbr-h-1 rbr-close-headline">
          <span className="stamp">You</span> did<br/>
          <span className="script">the thing.</span>
        </div>

        <div className="rbr-close-cards">
          <div className="rbr-close-card kept">
            <span className="seal">Kept</span>
            <div className="lbl">{c.close_rule_lbl}</div>
            <div className="val">{s.tailoredRule || '—'}</div>
          </div>
          <div className="rbr-close-card let-go">
            <span className="seal">Let go</span>
            <div className="lbl">{c.close_corner_lbl}</div>
            <div className="val">{s.cornerRule || '—'}</div>
          </div>
        </div>

        <div className="rbr-close-signoff">
          <div className="text">{c.close_signoff}</div>
        </div>
      </div>

      <div className="rbr-row rbr-gap-3" style={{ marginTop: 12, justifyContent: 'center' }}>
        <button className="rbr-btn ghost" onClick={back}>← Back</button>
        <button className="rbr-btn lilac" onClick={restart}>Start a new session</button>
      </div>
    </div>
  );
}

// ── Language tweaks panel ─────────────────────────────────────────
const COPY_GROUPS = [
  { name: 'Welcome',     keys: ['welcome_h', 'welcome_body', 'welcome_cta'] },
  { name: 'Check in',   keys: ['checkin_eyebrow', 'checkin_h', 'checkin_body', 'checkin_q1', 'checkin_q1_ph', 'checkin_q2', 'checkin_q2_ph', 'checkin_q3', 'checkin_q3_ph'] },
  { name: 'Norms',      keys: ['norms_eyebrow', 'norms_h', 'norms_1_t', 'norms_1_d', 'norms_2_t', 'norms_2_d', 'norms_3_t', 'norms_3_d', 'norms_4_t', 'norms_4_d', 'norms_in'] },
  { name: 'Why',        keys: ['why_eyebrow', 'why_h', 'why_p1', 'why_p2', 'why_p3', 'why_p4', 'why_p5'] },
  { name: 'Pile',       keys: ['pile_career_h', 'pile_career_intro', 'pile_career_intro2', 'pile_caregiving_h', 'pile_self_h'] },
  { name: 'Count',      keys: ['count_eyebrow', 'count_h', 'count_lbl', 'count_body'] },
  { name: 'Pride',      keys: ['pride_eyebrow', 'pride_h', 'pride_body', 'pride_prompt', 'pride_ph', 'pride_aside'] },
  { name: 'Pick',       keys: ['pick_eyebrow', 'pick_h', 'pick_body', 'pick_aside'] },
  { name: 'Tailor',     keys: ['tailor_eyebrow', 'tailor_h', 'tailor_body', 'tailor_values_label', 'tailor_values_hint', 'tailor_values_ph', 'tailor_strengths_label', 'tailor_strengths_hint', 'tailor_strengths_ph', 'tailor_situation_label', 'tailor_situation_hint', 'tailor_situation_ph', 'tailor_aside'] },
  { name: 'Rule',       keys: ['rule_eyebrow', 'rule_h', 'rule_body', 'rule_label', 'rule_hint', 'rule_ph', 'rule_example_lbl', 'rule_example'] },
  { name: 'Corner',     keys: ['corner_eyebrow', 'corner_h', 'corner_body', 'corner_rule_label', 'corner_rule_hint', 'corner_rule_ph', 'corner_story_label', 'corner_story_ph', 'corner_aside'] },
  { name: 'Why matters',keys: ['whymatters_eyebrow', 'whymatters_h', 'whymatters_body', 'whymatters_ph', 'whymatters_aside'] },
  { name: 'Enough',     keys: ['enough_eyebrow', 'enough_h', 'enough_body', 'enough_ph', 'enough_aside'] },
  { name: 'Room',       keys: ['room_eyebrow', 'room_h', 'room_body'] },
  { name: 'Pillow',     keys: ['pillow_eyebrow', 'pillow_h', 'pillow_lead', 'pillow_ph', 'pillow_cta'] },
  { name: 'Close',      keys: ['close_eyebrow', 'close_h', 'close_rule_lbl', 'close_corner_lbl', 'close_signoff'] },
];

function LanguagePanel({ copy, setCopy, resetCopy }) {
  const [open, setOpen] = useState(null);
  const [copyState, setCopyState] = useState('idle');

  function exportText() {
    const lines = ['# Rule Breaker Reset — language', ''];
    for (const g of COPY_GROUPS) {
      lines.push(`## ${g.name}`);
      for (const k of g.keys) lines.push(`${k}: ${JSON.stringify(copy[k] ?? '')}`);
      lines.push('');
    }
    return lines.join('\n');
  }

  function downloadAll() {
    const blob = new Blob([exportText()], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = 'rule-breaker-reset-language.txt';
    document.body.appendChild(a); a.click(); a.remove();
    URL.revokeObjectURL(url);
  }

  function copyAll() {
    navigator.clipboard.writeText(exportText()).then(() => {
      setCopyState('done');
      setTimeout(() => setCopyState('idle'), 1500);
    });
  }

  return (
    <TweaksPanel title="Language">
      <div className="rbr-tw-help">Edit a line and the screen updates live. Values save to your browser.</div>
      {COPY_GROUPS.map((g) =>
        <TweakSection key={g.name} label={g.name}>
          <details open={open === g.name} onToggle={(e) => setOpen(e.target.open ? g.name : null)}>
            <summary className="rbr-tw-summary">{g.keys.length} lines</summary>
            <div className="rbr-tw-fields">
              {g.keys.map((k) => {
                const val = copy[k] ?? '';
                const long = val.length > 60 || val.includes('\n');
                return (
                  <label key={k} className="rbr-tw-field">
                    <span className="rbr-tw-key">{k}</span>
                    {long
                      ? <textarea value={val} onChange={(e) => setCopy(k, e.target.value)} rows={Math.max(2, Math.ceil(val.length / 50))} />
                      : <input value={val} onChange={(e) => setCopy(k, e.target.value)} />}
                  </label>
                );
              })}
            </div>
          </details>
        </TweakSection>
      )}
      <TweakSection label="Export">
        <div className="rbr-tw-help">Get all current copy as a text file. Edit and paste it back so it can be reapplied.</div>
        <div className="rbr-tw-row">
          <button className="rbr-tw-btn primary" onClick={copyAll}>{copyState === 'done' ? '✓ copied' : 'Copy all'}</button>
          <button className="rbr-tw-btn" onClick={downloadAll}>Download .txt</button>
          <button className="rbr-tw-btn ghost" onClick={resetCopy}>Reset</button>
        </div>
      </TweakSection>
    </TweaksPanel>
  );
}

// ── App shell ─────────────────────────────────────────────────────
const COPY_LS_KEY = 'rbr-copy-overrides-v1';

function loadCopyOverrides() {
  try { return JSON.parse(localStorage.getItem(COPY_LS_KEY)) || {}; } catch (e) { return {}; }
}

function App() {
  const [state, setState] = useState(() => ({ stepIndex: 0, ...loadState() }));
  const [overrides, setOverrides] = useState(loadCopyOverrides);

  // Persist to localStorage on every state change
  useEffect(() => { saveState(state); }, [state]);

  // Persist copy overrides
  useEffect(() => {
    try { localStorage.setItem(COPY_LS_KEY, JSON.stringify(overrides)); } catch (e) {}
  }, [overrides]);

  // Auto-save to Supabase (debounced, only once email is present)
  const saveTimer = useRef(null);
  useEffect(() => {
    if (!state.email?.includes('@')) return;
    clearTimeout(saveTimer.current);
    saveTimer.current = setTimeout(() => {
      saveToSupabase(state.email, state).catch(() => {}); // silent — localStorage is the fallback
    }, 1500);
    return () => clearTimeout(saveTimer.current);
  }, [state]);

  const copy = useMemo(() => ({ ...COPY_DEFAULTS, ...overrides }), [overrides]);
  function setCopy(key, val) { setOverrides((o) => ({ ...o, [key]: val })); }
  function resetCopy() { setOverrides({}); }

  function set(patch) { setState((s) => ({ ...s, ...patch })); }
  function go(delta) { setState((s) => ({ ...s, stepIndex: Math.max(0, Math.min(STEPS.length - 1, s.stepIndex + delta)) })); }
  function next() { go(1); window.scrollTo({ top: 0, behavior: 'instant' }); }
  function back() { go(-1); window.scrollTo({ top: 0, behavior: 'instant' }); }
  function restart() { localStorage.removeItem(LS_KEY); setState({ stepIndex: 0 }); }

  const step = STEPS[state.stepIndex];
  const phase = step.phase;
  const c = copy;

  let content = null;
  switch (step.id) {
    case 'welcome':         content = <ScrWelcome s={state} set={set} next={next} c={c} />; break;
    case 'checkin':         content = <ScrCheckIn s={state} set={set} next={next} back={back} c={c} />; break;
    case 'norms':           content = <ScrNorms next={next} back={back} c={c} />; break;
    case 'why':             content = <ScrWhy next={next} back={back} c={c} />; break;
    case 'pile-career':     content = <ScrPile s={state} set={set} next={next} back={back} category="Career"     listIndex={0} c={c} />; break;
    case 'pile-caregiving': content = <ScrPile s={state} set={set} next={next} back={back} category="Caregiving" listIndex={1} c={c} />; break;
    case 'pile-self':       content = <ScrPile s={state} set={set} next={next} back={back} category="Self"       listIndex={2} c={c} />; break;
    case 'count':           content = <ScrCount s={state} next={next} back={back} c={c} />; break;
    case 'pride':           content = <ScrPride s={state} set={set} next={next} back={back} c={c} />; break;
    case 'pick':            content = <ScrPick s={state} set={set} next={next} back={back} c={c} />; break;
    case 'tailor':          content = <ScrTailor s={state} set={set} next={next} back={back} c={c} />; break;
    case 'rule':            content = <ScrRule s={state} set={set} next={next} back={back} c={c} />; break;
    case 'corner':          content = <ScrCorner s={state} set={set} next={next} back={back} c={c} />; break;
    case 'why-matters':     content = <ScrWhyMatters s={state} set={set} next={next} back={back} c={c} />; break;
    case 'enough-look':     content = <ScrEnoughLook s={state} set={set} next={next} back={back} c={c} />; break;
    case 'room':            content = <ScrRoom s={state} next={next} back={back} c={c} />; break;
    case 'pillow':          content = <ScrPillow s={state} set={set} next={next} back={back} c={c} />; break;
    case 'close':           content = <ScrClose s={state} back={back} restart={restart} c={c} />; break;
    default:                content = <div>—</div>;
  }

  const tinted = ['welcome', 'norms', 'why', 'count', 'close'].includes(step.id);
  const isPillow = step.id === 'pillow';

  return (
    <div className={`rbr-app${isPillow ? ' pillow' : ''}`} data-screen-label={`${String(state.stepIndex + 1).padStart(2, '0')} ${step.id}`}>
      <Topbar phase={phase} />
      <div className={`rbr-stage${tinted && !isPillow ? ' tinted' : ''}`}>
        {content}
      </div>
      <LanguagePanel copy={copy} setCopy={setCopy} resetCopy={resetCopy} />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
