// screens/recipe.jsx — the strategic battlefield template
const RecipeScreen = ({ locale, onNavigate, onCookMode }) => {
  const r = RECIPE;
  const [servings, setServings] = useState(r.servings);
  const [unit, setUnit] = useState('metric'); // 'metric' | 'imperial'
  const [checked, setChecked] = useState({});
  const [saved, setSaved] = useState(false);
  const [activeStep, setActiveStep] = useState(null);
  const recipeRef = useRef(null);

  const scale = servings / r.servings;
  const title = r.titleI18n[locale] || r.title;
  const summary = r.summaryI18n[locale] || r.summary;

  const scrollToRecipe = () => {
    const y = recipeRef.current?.getBoundingClientRect().top + window.scrollY - 80;
    window.scrollTo({ top: y, behavior: 'smooth' });
  };

  return (
    <article>
      <Breadcrumb locale={locale} onNavigate={onNavigate} title={title} />
      <RecipeHero locale={locale} recipe={r} title={title} summary={summary}
                  saved={saved} setSaved={setSaved}
                  onJump={scrollToRecipe} onCookMode={onCookMode} />
      <TrustBlock locale={locale} recipe={r} />
      <QuickAnswer locale={locale} recipe={r} onJump={scrollToRecipe} />
      <div ref={recipeRef} />
      <div className="page" style={{
        display: 'grid', gridTemplateColumns: '1fr 360px', gap: 'var(--s-10)',
        marginTop: 'var(--s-10)',
      }} >
        <RecipeMain locale={locale} recipe={r}
                    servings={servings} setServings={setServings}
                    unit={unit} setUnit={setUnit}
                    checked={checked} setChecked={setChecked}
                    scale={scale}
                    activeStep={activeStep} setActiveStep={setActiveStep}
                    onCookMode={onCookMode} />
        <RecipeSidebar locale={locale} recipe={r} onCookMode={onCookMode} />
      </div>

      <WhyItWorks locale={locale} recipe={r} />
      <Faq locale={locale} recipe={r} />
      <RelatedRecipes locale={locale} recipe={r} onNavigate={onNavigate} />

      <StickyCta locale={locale} recipe={r} onJump={scrollToRecipe}
                 saved={saved} setSaved={setSaved} onCookMode={onCookMode} />

      <style>{`
        @media (max-width: 980px){
          .recipe-grid-mobile { grid-template-columns: 1fr !important; }
          .recipe-sidebar { order: 2; }
        }
      `}</style>
    </article>
  );
};

/* ---------- Breadcrumb ---------- */
const Breadcrumb = ({ locale, onNavigate, title }) => (
  <div className="page" style={{ paddingTop: 'var(--s-5)' }}>
    <nav style={{ fontSize: 12, color: 'var(--ink-mute)', fontFamily: 'var(--font-mono)', letterSpacing: '.04em' }}>
      <a href={`#/${locale}/`} onClick={e=>{e.preventDefault(); onNavigate(`/${locale}/`);}} style={{ color: 'inherit' }}>/{locale}</a>
      <span style={{ margin: '0 6px', opacity: .5 }}>/</span>
      <a href="#" onClick={e=>e.preventDefault()} style={{ color: 'inherit' }}>recipes</a>
      <span style={{ margin: '0 6px', opacity: .5 }}>/</span>
      <a href="#" onClick={e=>e.preventDefault()} style={{ color: 'inherit' }}>baking</a>
      <span style={{ margin: '0 6px', opacity: .5 }}>/</span>
      <a href="#" onClick={e=>e.preventDefault()} style={{ color: 'inherit' }}>cookies</a>
      <span style={{ margin: '0 6px', opacity: .5 }}>/</span>
      <span style={{ color: 'var(--ink-soft)' }}>{title.toLowerCase().replace(/\s+/g, '-')}</span>
    </nav>
  </div>
);

/* ---------- Recipe hero ---------- */
const RecipeHero = ({ locale, recipe: r, title, summary, saved, setSaved, onJump, onCookMode }) => (
  <section style={{ padding: 'var(--s-8) 0 0' }}>
    <div className="page" style={{
      display: 'grid', gridTemplateColumns: '1.05fr 1fr', gap: 'var(--s-12)', alignItems: 'center',
    }} className="hero-grid">
      <div className="fade-in">
        <div className="row" style={{ gap: 8, marginBottom: 'var(--s-3)' }}>
          <span className="chip" style={{ background: 'var(--accent-tint)', color: 'var(--accent)' }}>
            <Icon name="flame" size={11} /> {r.tags[0]}
          </span>
          <span className="chip chip-outline">{r.course}</span>
          <span className="chip chip-outline">{r.cuisine}</span>
        </div>
        <h1 className="display" style={{
          fontSize: 'clamp(36px, 5vw, 64px)',
          margin: '0 0 var(--s-4)',
        }}>{title}</h1>
        <p style={{
          fontSize: 'clamp(16px, 1.3vw, 19px)', lineHeight: 1.55,
          color: 'var(--ink-soft)', maxWidth: 540, margin: '0 0 var(--s-6)',
        }}>{summary}</p>

        {/* rating row */}
        <div className="row" style={{ gap: 14, marginBottom: 'var(--s-6)' }}>
          <Stars value={r.rating} size={16} />
          <span style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink-strong)' }}>{r.rating}</span>
          <span style={{ fontSize: 13, color: 'var(--ink-mute)' }}>· {t(locale, 'rating_count', r.ratingCount)}</span>
        </div>

        {/* CTA + actions */}
        <div className="row wrap" style={{ gap: 8, marginBottom: 'var(--s-8)' }}>
          <button className="btn btn-primary btn-lg" onClick={onJump} style={{ fontSize: 16, paddingInline: 32 }}>
            <Icon name="arrowR" size={16} /> {t(locale, 'jump_to_recipe')}
          </button>
          <button className="btn btn-ghost" onClick={()=>setSaved(s => !s)}
                  style={saved ? { background: 'var(--ink-strong)', color: 'var(--bg)', borderColor: 'var(--ink-strong)' } : {}}>
            <Icon name={saved ? 'bookmarkFilled' : 'bookmark'} size={15} /> {saved ? 'Saved' : t(locale, 'save')}
          </button>
          <button className="btn btn-ghost"><Icon name="share" size={15} /> {t(locale, 'share')}</button>
          <button className="btn btn-ghost"><Icon name="print" size={15} /> {t(locale, 'print')}</button>
        </div>

        {/* At-a-glance bar */}
        <AtAGlance locale={locale} recipe={r} />
      </div>

      <Photo tone="butter" label="brown butter chocolate chip cookies"
             ratio="4/5" radius="var(--r-5)"
             style={{ boxShadow: 'var(--shadow-lg)' }} />
    </div>

    <style>{`
      @media (max-width: 920px) {
        section .hero-grid { grid-template-columns: 1fr !important; }
        section .hero-grid > div:last-child { aspect-ratio: 4/3 !important; }
      }
    `}</style>
  </section>
);

const AtAGlance = ({ locale, recipe: r }) => {
  const items = [
    { k: t(locale, 'prep'),       v: `${r.prep} ${t(locale, 'minutes')}` },
    { k: t(locale, 'cook'),       v: `${r.cook} ${t(locale, 'minutes')}` },
    { k: t(locale, 'rest'),       v: `24 h` },
    { k: t(locale, 'servings'),   v: r.servings },
    { k: t(locale, 'calories'),   v: r.calories },
    { k: t(locale, 'difficulty'), v: r.difficulty },
  ];
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)',
      gap: 0, borderRadius: 'var(--r-4)',
      border: '1px solid var(--line)', overflow: 'hidden',
      background: 'var(--bg-elevated)',
    }} className="glance-grid">
      {items.map((x, i) => (
        <div key={i} style={{
          padding: '14px 16px',
          borderRight: i < items.length - 1 ? '1px solid var(--line)' : 'none',
        }}>
          <div className="eyebrow" style={{ fontSize: 10, marginBottom: 4 }}>{x.k}</div>
          <div className="display num" style={{ fontSize: 18, color: 'var(--ink-strong)' }}>{x.v}</div>
        </div>
      ))}
      <style>{`
        @media (max-width: 720px){
          .glance-grid { grid-template-columns: repeat(3, 1fr) !important; }
          .glance-grid > div:nth-child(3n) { border-right: none !important; }
          .glance-grid > div:nth-child(-n+3) { border-bottom: 1px solid var(--line); }
        }
      `}</style>
    </div>
  );
};

/* ---------- Trust block ---------- */
const TrustBlock = ({ locale, recipe: r }) => (
  <section style={{ padding: 'var(--s-10) 0 0' }}>
    <div className="page">
      <div className="card" style={{ padding: 'var(--s-5)' }}>
        <div className="row wrap" style={{ gap: 'var(--s-8)', justifyContent: 'space-between' }}>
          <div className="row" style={{ gap: 14 }}>
            <div style={{
              width: 56, height: 56, borderRadius: 999,
              background: 'var(--accent)', color: 'var(--accent-ink)',
              display: 'grid', placeItems: 'center',
              fontFamily: 'var(--font-display)', fontSize: 22, fontWeight: 600,
            }}>{r.author.initials}</div>
            <div>
              <div style={{ fontSize: 12, color: 'var(--ink-mute)' }}>{t(locale, 'tested_by')}</div>
              <div style={{ fontSize: 16, fontWeight: 600, color: 'var(--ink-strong)' }}>{r.author.name}</div>
              <div style={{ fontSize: 12, color: 'var(--ink-soft)' }}>{r.author.role} · {r.author.credential}</div>
            </div>
          </div>
          <div style={{ flex: 1, minWidth: 240, color: 'var(--ink-soft)', fontSize: 14, lineHeight: 1.5 }}>
            <div className="row" style={{ gap: 6, color: 'var(--accent)', marginBottom: 4, fontSize: 12, fontWeight: 600 }}>
              <Icon name="check" size={12} /> TESTED &amp; PHOTOGRAPHED UNEDITED
            </div>
            {r.author.testNote}
          </div>
          <div style={{ textAlign: 'right' }}>
            <div className="meta" style={{ fontSize: 12 }}>{t(locale, 'updated')}</div>
            <div className="num" style={{ fontWeight: 600, color: 'var(--ink-strong)' }}>{r.updated}</div>
          </div>
        </div>
      </div>
    </div>
  </section>
);

/* ---------- Quick Answer ---------- */
const QuickAnswer = ({ locale, recipe: r, onJump }) => (
  <section style={{ padding: 'var(--s-10) 0 0' }}>
    <div className="page">
      <div style={{
        position: 'relative',
        background: 'var(--accent-tint)',
        borderRadius: 'var(--r-5)',
        padding: 'var(--s-8)',
        border: '1px solid var(--accent-soft)',
      }}>
        <div className="row" style={{ marginBottom: 12, gap: 8 }}>
          <span style={{
            width: 28, height: 28, borderRadius: 999, background: 'var(--accent)',
            color: 'var(--accent-ink)', display: 'grid', placeItems: 'center',
          }}><Icon name="sparkle" size={14} /></span>
          <div>
            <div className="eyebrow" style={{ color: 'var(--accent)' }}>{t(locale, 'quick_answer')}</div>
          </div>
        </div>
        <p className="display" style={{
          fontSize: 'clamp(18px, 1.8vw, 24px)', lineHeight: 1.4,
          margin: '0 0 var(--s-5)', color: 'var(--ink-strong)', fontWeight: 'inherit',
        }}>
          {r.quickAnswer.headline}
        </p>
        <ul style={{
          listStyle: 'none', padding: 0, margin: 0,
          display: 'flex', flexDirection: 'column', gap: 10,
        }}>
          {r.quickAnswer.bullets.map((b, i) => (
            <li key={i} className="row" style={{ alignItems: 'flex-start', gap: 12, fontSize: 15, color: 'var(--ink)' }}>
              <span style={{
                flex: '0 0 auto', width: 22, height: 22, borderRadius: 999,
                background: 'var(--accent)', color: 'var(--accent-ink)',
                display: 'grid', placeItems: 'center',
                fontFamily: 'var(--font-mono)', fontSize: 11, fontWeight: 700,
              }}>{i + 1}</span>
              <span style={{ lineHeight: 1.55, paddingTop: 1 }}>{b}</span>
            </li>
          ))}
        </ul>
      </div>
    </div>
  </section>
);

/* ---------- Main recipe (ingredients + steps) ---------- */
const RecipeMain = ({ locale, recipe: r, servings, setServings, unit, setUnit, checked, setChecked, scale, activeStep, setActiveStep, onCookMode }) => {
  return (
    <div className="recipe-grid-mobile" style={{ display: 'contents' }}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--s-10)' }}>
        {/* Ingredients */}
        <div>
          <div className="row between" style={{ marginBottom: 'var(--s-5)', alignItems: 'flex-end', flexWrap: 'wrap', gap: 12 }}>
            <h2 className="display" style={{ fontSize: 'clamp(26px, 2.6vw, 34px)', margin: 0 }}>
              {t(locale, 'ingredients')}
            </h2>
            <div className="row" style={{ gap: 10 }}>
              <Stepper value={servings} setValue={setServings} label={t(locale, 'servings')} min={1} max={48} />
              <UnitToggle unit={unit} setUnit={setUnit} locale={locale} />
            </div>
          </div>

          {r.ingredientGroups.map((g, gi) => (
            <div key={gi} style={{ marginBottom: 'var(--s-6)' }}>
              <div className="eyebrow" style={{ marginBottom: 10 }}>{g.label}</div>
              <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>
                {g.items.map((it, ii) => {
                  const key = `${gi}-${ii}`;
                  const isChecked = !!checked[key];
                  const amount = unit === 'metric'
                    ? formatAmount(it.metric * scale, it.mUnit)
                    : formatAmount(it.imp * scale, it.iUnit);
                  return (
                    <li key={ii}>
                      <label className="ingredient-row" style={{
                        display: 'grid', gridTemplateColumns: '24px 110px 1fr',
                        gap: 14, padding: '10px 0',
                        borderBottom: '1px solid var(--line)',
                        cursor: 'pointer', alignItems: 'baseline',
                        opacity: isChecked ? 0.45 : 1,
                        textDecoration: isChecked ? 'line-through' : 'none',
                        transition: 'opacity .2s, text-decoration-color .2s',
                      }}>
                        <span style={{
                          width: 20, height: 20, borderRadius: 6,
                          border: '1.5px solid var(--line-strong)',
                          background: isChecked ? 'var(--accent)' : 'transparent',
                          borderColor: isChecked ? 'var(--accent)' : 'var(--line-strong)',
                          display: 'grid', placeItems: 'center',
                          color: 'var(--accent-ink)',
                          transition: 'all .15s var(--ease)',
                        }}>
                          {isChecked && <Icon name="check" size={12} stroke={2.5} />}
                        </span>
                        <input type="checkbox" checked={isChecked}
                               onChange={e=>setChecked({...checked, [key]: e.target.checked})}
                               style={{ position: 'absolute', opacity: 0, width: 0, height: 0 }} />
                        <span className="num display" style={{
                          fontSize: 16, fontVariantNumeric: 'tabular-nums',
                          color: 'var(--ink-strong)', fontWeight: 500,
                        }}>{amount}</span>
                        <span style={{ fontSize: 15, color: 'var(--ink)' }}>
                          {it.name}
                          {it.note && <span style={{ color: 'var(--ink-mute)', fontSize: 13, fontStyle: 'italic' }}>, {it.note}</span>}
                        </span>
                      </label>
                    </li>
                  );
                })}
              </ul>
            </div>
          ))}

          <button className="btn btn-ghost btn-sm" onClick={()=>setChecked({})}>
            Reset checklist
          </button>
        </div>

        {/* Instructions */}
        <div>
          <div className="row between" style={{ marginBottom: 'var(--s-5)', alignItems: 'flex-end', flexWrap: 'wrap', gap: 12 }}>
            <h2 className="display" style={{ fontSize: 'clamp(26px, 2.6vw, 34px)', margin: 0 }}>
              {t(locale, 'instructions')}
            </h2>
            <button className="btn btn-secondary" onClick={onCookMode}>
              <Icon name="play" size={12} /> {t(locale, 'cook_mode')}
            </button>
          </div>

          <ol style={{ listStyle: 'none', padding: 0, margin: 0 }}>
            {r.steps.map((s, i) => (
              <StepRow key={i} step={s} index={i} locale={locale}
                       active={activeStep === i} onToggle={()=>setActiveStep(activeStep === i ? null : i)} />
            ))}
          </ol>
        </div>
      </div>
    </div>
  );
};

const StepRow = ({ step, index, locale, active, onToggle }) => {
  return (
    <li onClick={onToggle}
        style={{
          display: 'grid', gridTemplateColumns: '64px 1fr 120px', gap: 'var(--s-4)',
          padding: 'var(--s-5) 0',
          borderTop: index === 0 ? '1px solid var(--line)' : 'none',
          borderBottom: '1px solid var(--line)',
          cursor: 'pointer',
          background: active ? 'var(--accent-tint)' : 'transparent',
          marginLeft: active ? '-12px' : 0,
          marginRight: active ? '-12px' : 0,
          paddingLeft: active ? 12 : 0,
          paddingRight: active ? 12 : 0,
          borderRadius: active ? 'var(--r-3)' : 0,
          transition: 'all .2s var(--ease)',
        }} className="step-row">
      <div className="display" style={{
        fontSize: 36, fontWeight: 600,
        color: active ? 'var(--accent)' : 'var(--ink-mute)',
        lineHeight: 1, fontVariantNumeric: 'tabular-nums',
      }}>{String(index + 1).padStart(2, '0')}</div>
      <div>
        <h4 className="display" style={{ fontSize: 19, fontWeight: 500, margin: '0 0 6px', color: 'var(--ink-strong)' }}>{step.title}</h4>
        <p style={{ margin: 0, fontSize: 15, lineHeight: 1.6, color: 'var(--ink-soft)' }}>{step.body}</p>
        {step.timer && (
          <div className="row" style={{ gap: 8, marginTop: 12 }}>
            <button className="btn btn-ghost btn-sm" onClick={e=>e.stopPropagation()}>
              <Icon name="timer" size={13} /> {t(locale, 'start_timer')} · {step.timer} min
            </button>
          </div>
        )}
      </div>
      <Photo tone={step.tone || 'butter'} label={`step ${index + 1}`} ratio="1/1" radius="var(--r-3)" />

      <style>{`
        @media (max-width: 720px) {
          .step-row { grid-template-columns: 48px 1fr !important; }
          .step-row > :last-child { grid-column: 1 / -1; aspect-ratio: 16/9 !important; }
        }
      `}</style>
    </li>
  );
};

/* ---------- Sidebar ---------- */
const RecipeSidebar = ({ locale, recipe: r, onCookMode }) => (
  <aside className="recipe-sidebar" style={{ position: 'sticky', top: 92, alignSelf: 'start',
                  display: 'flex', flexDirection: 'column', gap: 'var(--s-4)' }}>
    {/* Nutrition */}
    <div className="card" style={{ padding: 'var(--s-5)' }}>
      <div className="eyebrow" style={{ marginBottom: 12 }}>{t(locale, 'nutrition')}</div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px 20px' }}>
        {[
          { k: 'Calories', v: r.nutrition.cal, u: 'kcal' },
          { k: 'Fat',      v: r.nutrition.fat, u: 'g' },
          { k: 'Carbs',    v: r.nutrition.carb, u: 'g' },
          { k: 'Sugar',    v: r.nutrition.sugar, u: 'g' },
          { k: 'Protein',  v: r.nutrition.protein, u: 'g' },
          { k: 'Sodium',   v: r.nutrition.sodium, u: 'mg' },
        ].map((n, i) => (
          <div key={i} className="row between" style={{
            paddingBottom: 6, borderBottom: '1px solid var(--line)',
          }}>
            <span style={{ fontSize: 13, color: 'var(--ink-soft)' }}>{n.k}</span>
            <span className="num" style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink-strong)' }}>
              {n.v}<span style={{ color: 'var(--ink-mute)', fontWeight: 400, marginLeft: 2 }}>{n.u}</span>
            </span>
          </div>
        ))}
      </div>
    </div>

    {/* Allergens */}
    <div className="card" style={{ padding: 'var(--s-5)' }}>
      <div className="eyebrow" style={{ marginBottom: 10 }}>{t(locale, 'allergens')}</div>
      <div className="row wrap" style={{ gap: 6 }}>
        {r.allergens.map(a => (
          <span key={a} className="chip" style={{ background: 'var(--bg-sunken)' }}>
            <span style={{ width: 6, height: 6, borderRadius: 999, background: 'var(--warn)' }} />{a}
          </span>
        ))}
      </div>
    </div>

    {/* Substitutions */}
    <div className="card" style={{ padding: 'var(--s-5)' }}>
      <div className="eyebrow" style={{ marginBottom: 10 }}>{t(locale, 'subs')}</div>
      <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 10 }}>
        {[
          { from: 'Bread flour', to: 'More AP flour + 1 tsp vital wheat gluten' },
          { from: 'Vanilla bean paste', to: '2 tsp pure vanilla extract' },
          { from: 'Dark brown sugar', to: 'Light brown + 1 tsp molasses' },
        ].map((s, i) => (
          <li key={i} style={{ fontSize: 13, lineHeight: 1.5 }}>
            <span style={{ color: 'var(--ink-mute)' }}>{s.from} → </span>
            <span style={{ color: 'var(--ink)' }}>{s.to}</span>
          </li>
        ))}
      </ul>
    </div>
  </aside>
);

/* ---------- Stepper ---------- */
const Stepper = ({ value, setValue, label, min = 1, max = 99 }) => (
  <div className="row" style={{
    background: 'var(--bg-elevated)', borderRadius: 'var(--r-pill)',
    border: '1px solid var(--line-strong)', padding: 3,
  }}>
    <button onClick={()=>setValue(Math.max(min, value - 1))} aria-label="Decrease"
            style={{
              width: 30, height: 30, borderRadius: 999, border: 0,
              background: 'transparent', color: 'var(--ink-soft)', cursor: 'pointer',
              display: 'grid', placeItems: 'center',
            }}><Icon name="minus" size={13} /></button>
    <div style={{ minWidth: 60, textAlign: 'center', padding: '0 6px' }}>
      <div className="num display" style={{ fontSize: 16, fontWeight: 600 }}>{value}</div>
      <div style={{ fontSize: 10, color: 'var(--ink-mute)', marginTop: -2, letterSpacing: '.04em', textTransform: 'uppercase' }}>{label}</div>
    </div>
    <button onClick={()=>setValue(Math.min(max, value + 1))} aria-label="Increase"
            style={{
              width: 30, height: 30, borderRadius: 999, border: 0,
              background: 'transparent', color: 'var(--ink-soft)', cursor: 'pointer',
              display: 'grid', placeItems: 'center',
            }}><Icon name="plus" size={13} /></button>
  </div>
);

const UnitToggle = ({ unit, setUnit, locale }) => (
  <div className="row" style={{
    background: 'var(--bg-elevated)', borderRadius: 'var(--r-pill)',
    border: '1px solid var(--line-strong)', padding: 3,
  }}>
    {['metric', 'imperial'].map(u => (
      <button key={u} onClick={()=>setUnit(u)}
              style={{
                padding: '6px 14px', borderRadius: 999, border: 0,
                background: unit === u ? 'var(--ink-strong)' : 'transparent',
                color: unit === u ? 'var(--bg)' : 'var(--ink-soft)',
                fontSize: 12, fontWeight: 600, cursor: 'pointer',
                transition: 'all .18s var(--ease)', letterSpacing: '.02em',
              }}>{t(locale, u === 'metric' ? 'metric' : 'imperial')}</button>
    ))}
  </div>
);

/* ---------- formatter ---------- */
function formatAmount(n, unit) {
  if (unit === 'lg' || unit === 'tsp' || unit === 'tbsp') {
    const rounded = Math.round(n * 4) / 4;
    return `${prettyFraction(rounded)} ${unit}`;
  }
  if (unit === 'cup') {
    const rounded = Math.round(n * 8) / 8;
    return `${prettyFraction(rounded)} ${unit}`;
  }
  if (n < 10) return `${(Math.round(n * 10) / 10)} ${unit}`;
  return `${Math.round(n)} ${unit}`;
}
function prettyFraction(n) {
  const whole = Math.floor(n);
  const frac = n - whole;
  const fmap = { 0.125: '⅛', 0.25: '¼', 0.333: '⅓', 0.375: '⅜', 0.5: '½', 0.625: '⅝', 0.66: '⅔', 0.667: '⅔', 0.75: '¾', 0.875: '⅞' };
  let bestKey = null, bestDelta = Infinity;
  for (const k of Object.keys(fmap)) {
    const d = Math.abs(parseFloat(k) - frac);
    if (d < bestDelta) { bestDelta = d; bestKey = k; }
  }
  if (frac < 0.05) return `${whole}`;
  if (bestDelta < 0.04) return whole === 0 ? fmap[bestKey] : `${whole} ${fmap[bestKey]}`;
  return n.toFixed(2).replace(/\.?0+$/, '');
}

/* ---------- Why this works ---------- */
const WhyItWorks = ({ locale, recipe }) => (
  <section className="section">
    <div className="page" style={{ display: 'grid', gridTemplateColumns: '1fr 1.4fr', gap: 'var(--s-12)', alignItems: 'start' }} className="why-grid">
      <div style={{ position: 'sticky', top: 92 }}>
        <span className="eyebrow"><Icon name="flame" size={11} /> Editorial</span>
        <h2 className="display" style={{ fontSize: 'clamp(28px, 3vw, 40px)', margin: '8px 0 var(--s-4)' }}>
          {t(locale, 'why_works')}
        </h2>
        <p style={{ color: 'var(--ink-soft)', fontSize: 15, lineHeight: 1.6 }}>
          The technique notes behind the recipe — written by the editor who tested it, not a content farm.
        </p>
      </div>
      <div>
        {[
          { h: 'The brown butter is the entire flavor system.',
            p: 'Browning butter denatures the milk proteins and triggers Maillard browning, producing 2-furfurylthiol and related toasted compounds that read on the palate as hazelnut and caramel. In a chocolate chip cookie those compounds amplify the chocolate without adding sweetness — which is why this cookie tastes more chocolatey than recipes using twice the chocolate.' },
          { h: 'Two flours are not a gimmick.',
            p: 'A blend of all-purpose and bread flour adds enough gluten development for a chewy interior while preserving the tender crumb you get from AP. Bread flour alone tightens the crumb; AP alone makes the cookie too tender and prone to crumbling at the edges.' },
          { h: 'The 24-hour rest changes everything.',
            p: 'Resting the dough allows the flour to fully hydrate, the enzymes to break down starches into simpler sugars, and the brown butter aromatics to redistribute. The result is a deeper-colored cookie with a more complex flavor and the characteristic ripple-edge.' },
          { h: 'Tap the tray.',
            p: 'Tapping the pan firmly when the cookies leave the oven deflates the centers and creates the rippled, fault-line edge. It also breaks the surface tension that would otherwise trap moisture, giving you crisp edges and a soft middle.' },
        ].map((b, i) => (
          <div key={i} style={{ marginBottom: 'var(--s-6)' }}>
            <h3 className="display" style={{ fontSize: 22, margin: '0 0 8px', color: 'var(--ink-strong)' }}>{b.h}</h3>
            <p style={{ margin: 0, fontSize: 16, lineHeight: 1.65, color: 'var(--ink-soft)' }}>{b.p}</p>
          </div>
        ))}
      </div>
      <style>{`
        @media (max-width: 880px){ .why-grid { grid-template-columns: 1fr !important; } .why-grid > div:first-child { position: static !important; } }
      `}</style>
    </div>
  </section>
);

/* ---------- FAQ ---------- */
const Faq = ({ locale, recipe: r }) => {
  const [open, setOpen] = useState(0);
  return (
    <section className="section" style={{ background: 'var(--bg-sunken)' }}>
      <div className="page">
        <div style={{ textAlign: 'center', marginBottom: 'var(--s-8)' }}>
          <span className="eyebrow"><Icon name="sparkle" size={11} /> Answer-ready</span>
          <h2 className="display" style={{ fontSize: 'clamp(28px, 3vw, 40px)', margin: '8px 0 0' }}>
            {t(locale, 'faq')}
          </h2>
        </div>
        <div style={{ maxWidth: 820, margin: '0 auto', display: 'flex', flexDirection: 'column', gap: 10 }}>
          {r.faqs.map((f, i) => (
            <div key={i} className="card" style={{
              padding: 'var(--s-5)',
              borderColor: open === i ? 'var(--accent)' : 'var(--line)',
              boxShadow: open === i ? 'var(--shadow-md)' : 'var(--shadow-xs)',
            }}>
              <button onClick={()=>setOpen(open === i ? null : i)}
                      style={{
                        display: 'flex', width: '100%', alignItems: 'flex-start',
                        justifyContent: 'space-between', gap: 14,
                        background: 'transparent', border: 0, padding: 0,
                        font: 'inherit', textAlign: 'left', cursor: 'pointer', color: 'inherit',
                      }}>
                <span className="display" style={{ fontSize: 18, fontWeight: 500, color: 'var(--ink-strong)' }}>{f.q}</span>
                <span style={{
                  flex: '0 0 auto', width: 28, height: 28, borderRadius: 999,
                  background: open === i ? 'var(--accent)' : 'var(--bg-sunken)',
                  color: open === i ? 'var(--accent-ink)' : 'var(--ink-soft)',
                  display: 'grid', placeItems: 'center',
                  transition: 'all .2s var(--ease)',
                  transform: open === i ? 'rotate(45deg)' : 'rotate(0)',
                }}><Icon name="plus" size={12} stroke={2} /></span>
              </button>
              {open === i && (
                <p style={{
                  margin: '14px 0 0', fontSize: 15, lineHeight: 1.65, color: 'var(--ink-soft)',
                  animation: 'fadeUp .25s var(--ease)',
                }}>{f.a}</p>
              )}
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

/* ---------- Related ---------- */
const RelatedRecipes = ({ locale, recipe: r, onNavigate }) => (
  <section className="section">
    <div className="page">
      <div className="row between" style={{ marginBottom: 'var(--s-6)', alignItems: 'flex-end' }}>
        <div>
          <span className="eyebrow">{t(locale, 'similar')}</span>
          <h2 className="display" style={{ fontSize: 'clamp(26px, 2.6vw, 36px)', margin: '8px 0 0' }}>More from our baking editors</h2>
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 14 }} className="rel-grid">
        {TRENDING.slice(1, 5).map((rec, i) => (
          <RecipeCard key={i} recipe={rec} locale={locale} onClick={()=>onNavigate(`/${locale}/r/${RECIPE.slug}`)} />
        ))}
      </div>
      <style>{`@media (max-width: 880px){ .rel-grid { grid-template-columns: 1fr 1fr !important; } }`}</style>
    </div>
  </section>
);

/* ---------- Sticky bottom CTA ---------- */
const StickyCta = ({ locale, recipe: r, onJump, saved, setSaved, onCookMode }) => {
  const [hidden, setHidden] = useState(true);
  useEffect(() => {
    const onScroll = () => setHidden(window.scrollY < 600);
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return (
    <div style={{
      position: 'fixed', left: 0, right: 0, bottom: hidden ? -100 : 0,
      zIndex: 30,
      padding: 'var(--s-4) var(--s-6)',
      background: 'color-mix(in oklab, var(--bg-elevated) 92%, transparent)',
      backdropFilter: 'blur(14px) saturate(140%)',
      WebkitBackdropFilter: 'blur(14px) saturate(140%)',
      borderTop: '1px solid var(--line)',
      transition: 'bottom .35s var(--ease)',
      pointerEvents: hidden ? 'none' : 'auto',
    }}>
      <div className="page row between" style={{ gap: 'var(--s-4)' }}>
        <div className="row" style={{ gap: 12, minWidth: 0 }}>
          <div style={{
            width: 40, height: 40, borderRadius: 'var(--r-2)', flexShrink: 0,
            background: 'linear-gradient(135deg, var(--photo-1), var(--photo-3))',
          }} />
          <div style={{ minWidth: 0 }}>
            <div style={{
              fontSize: 13, fontWeight: 600, color: 'var(--ink-strong)',
              overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
              maxWidth: 280,
            }}>{r.titleI18n[locale] || r.title}</div>
            <div className="row" style={{ gap: 8, fontSize: 11, color: 'var(--ink-mute)' }}>
              <Stars value={r.rating} size={11} />
              <span>{r.rating} · {r.total} min</span>
            </div>
          </div>
        </div>
        <div className="row" style={{ gap: 8 }}>
          <button className="btn btn-ghost btn-sm" onClick={()=>setSaved(s => !s)}>
            <Icon name={saved ? 'bookmarkFilled' : 'bookmark'} size={14} />
          </button>
          <button className="btn btn-ghost btn-sm" onClick={onCookMode}>
            <Icon name="play" size={12} /> {t(locale, 'cook_mode')}
          </button>
          <button className="btn btn-primary btn-sm" onClick={onJump}>
            <Icon name="arrowR" size={12} /> {t(locale, 'jump_to_recipe')}
          </button>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { RecipeScreen });
