/-- If there are no configurations of satellites with `N+1` points, one never uses more than `N`
distinct families in the Besicovitch inductive construction. -/
theorem color_lt {i : Ordinal.{u}} (hi : i < p.lastStep) {N : ℕ}
    (hN : IsEmpty (SatelliteConfig α N p.τ)) : p.color i < N := by
  /- By contradiction, consider the first ordinal `i` for which one would have `p.color i = N`.
    Choose for each `k < N` a ball with color `k` that intersects the ball at color `i`
    (there is such a ball, otherwise one would have used the color `k` and not `N`).
    Then this family of `N+1` balls forms a satellite configuration, which is forbidden by
    the assumption `hN`. -/
  induction' i using Ordinal.induction with i IH
  let A : Set ℕ :=
    ⋃ (j : { j // j < i })
      (_ : (closedBall (p.c (p.index j)) (p.r (p.index j)) ∩
        closedBall (p.c (p.index i)) (p.r (p.index i))).Nonempty),
      {p.color j}
  have color_i : p.color i = sInf (univ \ A) := by rw [color]
  rw [color_i]
  have N_mem : N ∈ univ \ A := by
    simp only [not_exists, true_and_iff, exists_prop, mem_iUnion, mem_singleton_iff, mem_closedBall,
      not_and, mem_univ, mem_diff, Subtype.exists, Subtype.coe_mk]
    intro j ji _
    exact (IH j ji (ji.trans hi)).ne'
  suffices sInf (univ \ A) ≠ N by
    rcases (csInf_le (OrderBot.bddBelow (univ \ A)) N_mem).lt_or_eq with (H | H)
    · exact H
    · exact (this H).elim
  intro Inf_eq_N
  have :
    ∀ k, k < N → ∃ j, j < i ∧
      (closedBall (p.c (p.index j)) (p.r (p.index j)) ∩
        closedBall (p.c (p.index i)) (p.r (p.index i))).Nonempty ∧ k = p.color j := by
    intro k hk
    rw [← Inf_eq_N] at hk
    have : k ∈ A := by
      simpa only [true_and_iff, mem_univ, Classical.not_not, mem_diff] using
        Nat.not_mem_of_lt_sInf hk
    simp only [mem_iUnion, mem_singleton_iff, exists_prop, Subtype.exists, exists_and_right,
      and_assoc] at this
    simpa only [exists_prop, mem_iUnion, mem_singleton_iff, mem_closedBall, Subtype.exists,
      Subtype.coe_mk]
  choose! g hg using this
  -- Choose for each `k < N` an ordinal `G k < i` giving a ball of color `k` intersecting
  -- the last ball.
  let G : ℕ → Ordinal := fun n => if n = N then i else g n
  have color_G : ∀ n, n ≤ N → p.color (G n) = n := by
    intro n hn
    rcases hn.eq_or_lt with (rfl | H)
    · simp only; simp only [color_i, Inf_eq_N, if_true, eq_self_iff_true]
    · simp only; simp only [H.ne, (hg n H).right.right.symm, if_false]
  have G_lt_last : ∀ n, n ≤ N → G n < p.lastStep := by
    intro n hn
    rcases hn.eq_or_lt with (rfl | H)
    · simp only; simp only [hi, if_true, eq_self_iff_true]
    · simp only; simp only [H.ne, (hg n H).left.trans hi, if_false]
  have fGn :
      ∀ n, n ≤ N →
        p.c (p.index (G n)) ∉ p.iUnionUpTo (G n) ∧ p.R (G n) ≤ p.τ * p.r (p.index (G n)) := by
    intro n hn
    have :
      p.index (G n) =
        Classical.epsilon fun t => p.c t ∉ p.iUnionUpTo (G n) ∧ p.R (G n) ≤ p.τ * p.r t :=
      by rw [index]; rfl
    

Proof state:
α : Type u_1
inst✝¹ : MetricSpace α
β : Type u
inst✝ : Nonempty β
p : TauPackage β α
N : ℕ
hN : IsEmpty (SatelliteConfig α N p.τ)
i : Ordinal.{u}
IH : ∀ k < i, k < lastStep p → color p k < N
hi : i < lastStep p
A : Set ℕ :=
  ⋃ j,
    ⋃ (_ :
      Set.Nonempty
        (closedBall (BallPackage.c p.toBallPackage (index p ↑j)) (BallPackage.r p.toBallPackage (index p ↑j)) ∩
          closedBall (BallPackage.c p.toBallPackage (index p i)) (BallPackage.r p.toBallPackage (index p i)))),
      {color p ↑j}
color_i : color p i = sInf (univ \ A)
N_mem : N ∈ univ \ A
Inf_eq_N : sInf (univ \ A) = N
g : ℕ → Ordinal.{u}
hg :
  ∀ k < N,
    g k < i ∧
      Set.Nonempty
          (closedBall (BallPackage.c p.toBallPackage (index p (g k))) (BallPackage.r p.toBallPackage (index p (g k))) ∩
            closedBall (BallPackage.c p.toBallPackage (index p i)) (BallPackage.r p.toBallPackage (index p i))) ∧
        k = color p (g k)
G : ℕ → Ordinal.{u} := fun n => if n = N then i else g n
color_G : ∀ n ≤ N, color p (G n) = n
G_lt_last : ∀ n ≤ N, G n < lastStep p
n : ℕ
hn : n ≤ N
this :
  index p (G n) =
    Classical.epsilon fun t =>
      BallPackage.c p.toBallPackage t ∉ iUnionUpTo p (G n) ∧ R p (G n) ≤ p.τ * BallPackage.r p.toBallPackage t
⊢ BallPackage.c p.toBallPackage (index p (G n)) ∉ iUnionUpTo p (G n) ∧
    R p (G n) ≤ p.τ * BallPackage.r p.toBallPackage (index p (G n))

Next tactic:
rw [this]