{-# OPTIONS --without-K --rewriting #-}

open import HoTT
open import homotopy.EilenbergMacLane
open import homotopy.EilenbergMacLane1
open import homotopy.EilenbergMacLaneFunctor

module cohomology.CupProduct.OnEM.CommutativityInLowDegrees where

module _ {i} {j} (G : AbGroup i) (H : AbGroup j) where

  private
    module G = AbGroup G
    module H = AbGroup H
    module G⊗H = TensorProduct G H
    module H⊗G = TensorProduct H G

  import cohomology.CupProduct.OnEM.InLowDegrees G H as GH
  import cohomology.CupProduct.OnEM.InLowDegrees H G as HG
  open EMExplicit

  ×-cp₀₀-comm : EM-fmap G⊗H.abgroup H⊗G.abgroup G⊗H.swap 0 ∘ GH.×-cp₀₀
              ∼ HG.×-cp₀₀ ∘ ×-swap
  ×-cp₀₀-comm (g' , h') =
    (EM-fmap G⊗H.abgroup H⊗G.abgroup G⊗H.swap 0 $
     emloop $
     (<– (emloop-equiv G.grp) g') G⊗H.⊗ (<– (emloop-equiv H.grp) h'))
      =⟨ EM₁-fmap-emloop-β G⊗H.swap $
         (<– (emloop-equiv G.grp) g') G⊗H.⊗ (<– (emloop-equiv H.grp) h') ⟩
    (emloop $
     GroupHom.f G⊗H.swap $
     (<– (emloop-equiv G.grp) g') G⊗H.⊗ (<– (emloop-equiv H.grp) h'))
      =⟨ ap emloop $ G⊗H.swap-β (<– (emloop-equiv G.grp) g') (<– (emloop-equiv H.grp) h') ⟩
    (emloop $
     (<– (emloop-equiv H.grp) h') H⊗G.⊗ (<– (emloop-equiv G.grp) g')) =∎

  ⊙×-cp₀₀-comm :
    ⊙EM-fmap G⊗H.abgroup H⊗G.abgroup G⊗H.swap 0 ◃⊙∘
    GH.⊙×-cp₀₀ ◃⊙idf
    =⊙∘
    HG.⊙×-cp₀₀ ◃⊙∘
    ⊙×-swap ◃⊙idf
  ⊙×-cp₀₀-comm =
    ⊙seq-λ= ×-cp₀₀-comm $
    contr-center $ =ₛ-level {n = -2} $ EM-level H⊗G.abgroup 0

module CP₀₁-comm {i} {j} (G : AbGroup i) (H : AbGroup j) where

  private
    module G = AbGroup G
    module H = AbGroup H
    module G⊗H = TensorProduct G H
    module H⊗G = TensorProduct H G

  import cohomology.CupProduct.OnEM.InLowDegrees G H as GH
  import cohomology.CupProduct.OnEM.InLowDegrees H G as HG

  private
    swap : H⊗G.grp →ᴳ G⊗H.grp
    swap = H⊗G.swap
    module swap = GroupHom swap

  cp₀₁-comm : ∀ g h →
    ap (GH.cp₀₁ g) (emloop h) ==
    ap (EM₁-fmap swap ∘ HG.cp₀₁ h) (emloop g)
  cp₀₁-comm g h =
    ap (GH.cp₀₁ g) (emloop h)
      =⟨ GH.cp₀₁-emloop-β g h ⟩
    emloop (g G⊗H.⊗ h)
      =⟨ ap emloop (! (H⊗G.swap-β h g)) ⟩
    emloop (swap.f (h H⊗G.⊗ g))
      =⟨ ! (EM₁-fmap-emloop-β swap (h H⊗G.⊗ g)) ⟩
    ap (EM₁-fmap swap) (emloop (h H⊗G.⊗ g))
      =⟨ ap (ap (EM₁-fmap swap)) (! (HG.cp₀₁-emloop-β h g)) ⟩
    ap (EM₁-fmap swap) (ap (HG.cp₀₁ h) (emloop g))
      =⟨ ∘-ap (EM₁-fmap swap) (HG.cp₀₁ h) (emloop g) ⟩
    ap (EM₁-fmap swap ∘ HG.cp₀₁ h) (emloop g) =∎

module CP₁₁-comm {i} {j} (G : AbGroup i) (H : AbGroup j) where

  private
    module G = AbGroup G
    module H = AbGroup H
    module G⊗H = TensorProduct G H
    module H⊗G = TensorProduct H G
    module swap = GroupHom H⊗G.swap

    import cohomology.CupProduct.OnEM.InLowDegrees G H as GH
    import cohomology.CupProduct.OnEM.InLowDegrees H G as HG

    infix 80 _G∪H_
    _G∪H_ : EM₁ G.grp → EM₁ H.grp → EMExplicit.EM G⊗H.abgroup 2
    _G∪H_ = GH.cp₁₁

    infix 80 _H∪G_
    _H∪G_ : EM₁ H.grp → EM₁ G.grp → EMExplicit.EM H⊗G.abgroup 2
    _H∪G_ = HG.cp₁₁

  ⊙−₁ : ⊙EM₁ H⊗G.grp ⊙→ ⊙EM₁ G⊗H.grp
  ⊙−₁ = ⊙EM₁-fmap (inv-hom G⊗H.abgroup) ⊙∘ ⊙EM₁-fmap H⊗G.swap

  −₁ : EM₁ H⊗G.grp → EM₁ G⊗H.grp
  −₁ = fst ⊙−₁

  − : EMExplicit.EM H⊗G.abgroup 2 → EMExplicit.EM G⊗H.abgroup 2
  − = Trunc-fmap (Susp-fmap −₁)

  ⊙− : EMExplicit.⊙EM H⊗G.abgroup 2 ⊙→ EMExplicit.⊙EM G⊗H.abgroup 2
  ⊙− = ⊙Trunc-fmap (⊙Susp-fmap −₁)

  comm-embase-emloop-seq : ∀ h →
    ap (λ y → embase G∪H y) (emloop h) =-=
    ap (λ y → − (y H∪G embase)) (emloop h)
  comm-embase-emloop-seq h =
    ap (λ y → embase G∪H y) (emloop h)
      =⟪idp⟫
    ap (cst [ north ]₂) (emloop h)
      =⟪ ap-cst [ north ]₂ (emloop h) ⟫
    idp
      =⟪idp⟫
    ap − (idp {a = [ north ]})
      =⟪ ! (ap (ap −) (HG.ap-cp₁₁-embase h)) ⟫
    ap − (ap (_H∪G embase) (emloop h))
      =⟪ ∘-ap − (_H∪G embase) (emloop h) ⟫
    ap (λ y → − (y H∪G embase)) (emloop h) ∎∎

  comm-emloop-embase-seq : ∀ g →
    ap (_G∪H embase) (emloop g) =-=
    ap (λ x → − (embase H∪G x)) (emloop g)
  comm-emloop-embase-seq g =
    ap (_G∪H embase) (emloop g)
      =⟪ GH.ap-cp₁₁-embase g ⟫
    idp
      =⟪ ! (ap-cst [ north ]₂ (emloop g)) ⟫
    ap (cst [ north ]₂) (emloop g)
      =⟪idp⟫
    ap (λ x → − (embase H∪G x)) (emloop g) ∎∎

  comm-embase-emloop' : ∀ h →
    ap (embase G∪H_) (emloop h) ==
    ap (λ y → − (y H∪G embase)) (emloop h)
  comm-embase-emloop' h = ↯ (comm-embase-emloop-seq h)

  comm-emloop-embase' : ∀ g →
    ap (λ x → GH.cp₁₁ x embase) (emloop g) ==
    ap (λ x → − (embase H∪G x)) (emloop g)
  comm-emloop-embase' g = ↯ (comm-emloop-embase-seq g)

  abstract

    comm-embase-emloop-comp' : ∀ h₁ h₂ →
      comm-embase-emloop' (H.comp h₁ h₂) ◃∙
      ap (ap (λ y → − (y H∪G embase))) (emloop-comp h₁ h₂) ◃∎
      =ₛ
      ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ◃∙
      ap-∙ (embase G∪H_) (emloop h₁) (emloop h₂) ◃∙
      ap2 _∙_ (comm-embase-emloop' h₁) (comm-embase-emloop' h₂) ◃∙
      ∙-ap (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂) ◃∎
    comm-embase-emloop-comp' h₁ h₂ =
      comm-embase-emloop' (H.comp h₁ h₂) ◃∙
      ap (ap (λ y → − (y H∪G embase))) (emloop-comp h₁ h₂) ◃∎
        =ₛ⟨ 0 & 1 & expand (comm-embase-emloop-seq (H.comp h₁ h₂)) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ! (ap (ap −) (HG.ap-cp₁₁-embase (H.comp h₁ h₂))) ◃∙
      ∘-ap − (_H∪G embase) (emloop (H.comp h₁ h₂)) ◃∙
      ap (ap (λ y → − (y H∪G embase))) (emloop-comp h₁ h₂) ◃∎
        =ₛ⟨ 2 & 2 & !ₛ $
            homotopy-naturality (ap − ∘ ap (_H∪G embase))
                                (ap (λ y → − (y H∪G embase)))
                                (∘-ap − (_H∪G embase))
                                (emloop-comp h₁ h₂) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ! (ap (ap −) (HG.ap-cp₁₁-embase (H.comp h₁ h₂))) ◃∙
      ap (ap − ∘ ap (_H∪G embase)) (emloop-comp h₁ h₂) ◃∙
      ∘-ap − (_H∪G embase) (emloop h₁ ∙ emloop h₂) ◃∎
        =ₛ₁⟨ 1 & 1 & !-ap (ap −) (HG.ap-cp₁₁-embase (H.comp h₁ h₂)) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap (ap −) (! (HG.ap-cp₁₁-embase (H.comp h₁ h₂))) ◃∙
      ap (ap − ∘ ap (_H∪G embase)) (emloop-comp h₁ h₂) ◃∙
      ∘-ap − (_H∪G embase) (emloop h₁ ∙ emloop h₂) ◃∎
        =ₛ₁⟨ 2 & 1 & ap-∘ (ap −) (ap (_H∪G embase)) (emloop-comp h₁ h₂) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap (ap −) (! (HG.ap-cp₁₁-embase (H.comp h₁ h₂))) ◃∙
      ap (ap −) (ap (ap (_H∪G embase)) (emloop-comp h₁ h₂)) ◃∙
      ∘-ap − (_H∪G embase) (emloop h₁ ∙ emloop h₂) ◃∎
        =ₛ⟨ 1 & 2 &
            ap-seq-=ₛ (ap −) $
            post-rotate-seq-in {p = _ ◃∙ _ ◃∎} $
            pre-rotate'-in $
            !ₛ $ HG.ap-cp₁₁-embase-coh h₁ h₂ ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap (ap −) (! (ap2 _∙_ (HG.ap-cp₁₁-embase h₁) (HG.ap-cp₁₁-embase h₂))) ◃∙
      ap (ap −) (! (ap-∙ (_H∪G embase) (emloop h₁) (emloop h₂))) ◃∙
      ∘-ap − (_H∪G embase) (emloop h₁ ∙ emloop h₂) ◃∎
        =ₛ₁⟨ 2 & 1 & ap-! (ap −) (ap-∙ (_H∪G embase) (emloop h₁) (emloop h₂))⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap (ap −) (! (ap2 _∙_ (HG.ap-cp₁₁-embase h₁) (HG.ap-cp₁₁-embase h₂))) ◃∙
      ! (ap (ap −) (ap-∙ (_H∪G embase) (emloop h₁) (emloop h₂))) ◃∙
      ∘-ap − (_H∪G embase) (emloop h₁ ∙ emloop h₂) ◃∎
        =ₛ₁⟨ 3 & 1 & ! (!ap-∘=∘-ap − (_H∪G embase) (emloop h₁ ∙ emloop h₂)) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap (ap −) (! (ap2 _∙_ (HG.ap-cp₁₁-embase h₁) (HG.ap-cp₁₁-embase h₂))) ◃∙
      ! (ap (ap −) (ap-∙ (_H∪G embase) (emloop h₁) (emloop h₂))) ◃∙
      ! (ap-∘ − (_H∪G embase) (emloop h₁ ∙ emloop h₂)) ◃∎
        =ₛ⟨ 2 & 2 &
            post-rotate-seq-in {p = _ ◃∙ _ ◃∎} $
            pre-rotate'-seq-in {p = _ ◃∙ _ ◃∎} $
            ap-∘-∙-coh − (_H∪G embase) (emloop h₁) (emloop h₂) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap (ap −) (! (ap2 _∙_ (HG.ap-cp₁₁-embase h₁) (HG.ap-cp₁₁-embase h₂))) ◃∙
      ap-∙ − (ap (_H∪G embase) (emloop h₁)) (ap (_H∪G embase) (emloop h₂)) ◃∙
      ! (ap2 _∙_ (ap-∘ − (_H∪G embase) (emloop h₁))
                 (ap-∘ − (_H∪G embase) (emloop h₂))) ◃∙
      ! (ap-∙ (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂)) ◃∎
        =ₛ₁⟨ 1 & 1 &
              ap (ap (ap −)) (!-ap2 _∙_ (HG.ap-cp₁₁-embase h₁) (HG.ap-cp₁₁-embase h₂)) ∙
              ap-ap2 (ap −) _∙_ (! (HG.ap-cp₁₁-embase h₁)) (! (HG.ap-cp₁₁-embase h₂)) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap2 (λ p q → ap − (p ∙ q)) (! (HG.ap-cp₁₁-embase h₁)) (! (HG.ap-cp₁₁-embase h₂)) ◃∙
      ap-∙ − (ap (_H∪G embase) (emloop h₁)) (ap (_H∪G embase) (emloop h₂)) ◃∙
      ! (ap2 _∙_ (ap-∘ − (_H∪G embase) (emloop h₁))
                 (ap-∘ − (_H∪G embase) (emloop h₂))) ◃∙
      ! (ap-∙ (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂)) ◃∎
        =ₛ⟨ 1 & 2 &
            homotopy-naturality2 (λ p q → ap − (p ∙ q))
                                  (λ p q → ap − p ∙ ap − q)
                                  (λ p q → ap-∙ − p q)
                                  (! (HG.ap-cp₁₁-embase h₁))
                                  (! (HG.ap-cp₁₁-embase h₂)) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      idp ◃∙
      ap2 (λ p q → ap − p ∙ ap − q) (! (HG.ap-cp₁₁-embase h₁)) (! (HG.ap-cp₁₁-embase h₂)) ◃∙
      ! (ap2 _∙_ (ap-∘ − (_H∪G embase) (emloop h₁))
                 (ap-∘ − (_H∪G embase) (emloop h₂))) ◃∙
      ! (ap-∙ (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂)) ◃∎
        =ₛ⟨ 1 & 1 & expand [] ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap2 (λ p q → ap − p ∙ ap − q) (! (HG.ap-cp₁₁-embase h₁)) (! (HG.ap-cp₁₁-embase h₂)) ◃∙
      ! (ap2 _∙_ (ap-∘ − (_H∪G embase) (emloop h₁))
                 (ap-∘ − (_H∪G embase) (emloop h₂))) ◃∙
      ! (ap-∙ (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂)) ◃∎
        =ₛ₁⟨ 1 & 1 &
              ! (ap2-ap-lr _∙_ (ap −) (ap −) (! (HG.ap-cp₁₁-embase h₁)) (! (HG.ap-cp₁₁-embase h₂))) ∙
              ap2 (ap2 _∙_) (ap-! (ap −) (HG.ap-cp₁₁-embase h₁)) (ap-! (ap −) (HG.ap-cp₁₁-embase h₂)) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap2 _∙_ (! (ap (ap −) (HG.ap-cp₁₁-embase h₁))) (! (ap (ap −) (HG.ap-cp₁₁-embase h₂))) ◃∙
      ! (ap2 _∙_ (ap-∘ − (_H∪G embase) (emloop h₁))
                 (ap-∘ − (_H∪G embase) (emloop h₂))) ◃∙
      ! (ap-∙ (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂)) ◃∎
        =ₛ₁⟨ 2 & 1 &
            !-ap2 _∙_ (ap-∘ − (_H∪G embase) (emloop h₁))
                      (ap-∘ − (_H∪G embase) (emloop h₂)) ∙
            ap2 (ap2 _∙_) (!ap-∘=∘-ap − (_H∪G embase) (emloop h₁))
                          (!ap-∘=∘-ap − (_H∪G embase) (emloop h₂)) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap2 _∙_ (! (ap (ap −) (HG.ap-cp₁₁-embase h₁))) (! (ap (ap −) (HG.ap-cp₁₁-embase h₂))) ◃∙
      ap2 _∙_ (∘-ap − (_H∪G embase) (emloop h₁))
              (∘-ap − (_H∪G embase) (emloop h₂)) ◃∙
      ! (ap-∙ (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂)) ◃∎
        =ₛ₁⟨ 3 & 1 & !ap-∙=∙-ap (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂) ⟩
      ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
      ap2 _∙_ (! (ap (ap −) (HG.ap-cp₁₁-embase h₁))) (! (ap (ap −) (HG.ap-cp₁₁-embase h₂))) ◃∙
      ap2 _∙_ (∘-ap − (_H∪G embase) (emloop h₁))
              (∘-ap − (_H∪G embase) (emloop h₂)) ◃∙
      ∙-ap (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂) ◃∎
        =ₛ⟨ 0 & 1 &
            ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∎
              =ₛ⟨ 1 & 0 & contract ⟩
            ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
            idp ◃∎
              =ₛ₁⟨ 1 & 1 & ! (ap-cst idp (emloop-comp h₁ h₂)) ⟩
            ap-cst [ north ] (emloop (H.comp h₁ h₂)) ◃∙
            ap (λ _ → idp) (emloop-comp h₁ h₂) ◃∎
              =ₛ⟨ !ₛ $ homotopy-naturality (ap (embase G∪H_))
                                           (λ _ → idp)
                                           (ap-cst [ north ])
                                           (emloop-comp h₁ h₂) ⟩
            ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ◃∙
            ap-cst [ north ] (emloop h₁ ∙ emloop h₂) ◃∎
              =ₛ⟨ 1 & 1 & ap-cst-coh [ north ] (emloop h₁) (emloop h₂) ⟩
            ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ◃∙
            ap-∙ (cst [ north ]) (emloop h₁) (emloop h₂) ◃∙
            ap2 _∙_ (ap-cst [ north ] (emloop h₁)) (ap-cst [ north ] (emloop h₂)) ◃∎ ∎ₛ
          ⟩
      ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ◃∙
      ap-∙ (cst [ north ]) (emloop h₁) (emloop h₂) ◃∙
      ap2 _∙_ (ap-cst [ north ] (emloop h₁)) (ap-cst [ north ] (emloop h₂)) ◃∙
      ap2 _∙_ (! (ap (ap −) (HG.ap-cp₁₁-embase h₁))) (! (ap (ap −) (HG.ap-cp₁₁-embase h₂))) ◃∙
      ap2 _∙_ (∘-ap − (_H∪G embase) (emloop h₁))
              (∘-ap − (_H∪G embase) (emloop h₂)) ◃∙
      ∙-ap (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂) ◃∎
        =ₛ⟨ 2 & 3 & ∙-ap2-seq _∙_ (comm-embase-emloop-seq h₁) (comm-embase-emloop-seq h₂) ⟩
      ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ◃∙
      ap-∙ (embase G∪H_) (emloop h₁) (emloop h₂) ◃∙
      ap2 _∙_ (comm-embase-emloop' h₁) (comm-embase-emloop' h₂) ◃∙
      ∙-ap (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂) ◃∎ ∎ₛ

    comm-emloop-comp-embase' : ∀ g₁ g₂ →
      comm-emloop-embase' (G.comp g₁ g₂) ◃∙
      ap (ap (λ x → − (embase H∪G x))) (emloop-comp g₁ g₂) ◃∎
      =ₛ
      ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ◃∙
      ap-∙ (_G∪H embase) (emloop g₁) (emloop g₂) ◃∙
      ap2 _∙_ (comm-emloop-embase' g₁) (comm-emloop-embase' g₂) ◃∙
      ∙-ap (λ x → − (embase H∪G x)) (emloop g₁) (emloop g₂) ◃∎
    comm-emloop-comp-embase' g₁ g₂ =
      comm-emloop-embase' (G.comp g₁ g₂) ◃∙
      ap (ap (λ x → − (embase H∪G x))) (emloop-comp g₁ g₂) ◃∎
        =ₛ⟨ 0 & 1 & expand (comm-emloop-embase-seq (G.comp g₁ g₂)) ⟩
      GH.ap-cp₁₁-embase (G.comp g₁ g₂) ◃∙
      ! (ap-cst [ north ] (emloop (G.comp g₁ g₂))) ◃∙
      ap (ap (λ x → − (embase H∪G x))) (emloop-comp g₁ g₂) ◃∎
        =ₛ⟨ 1 & 2 & !ₛ $
            homotopy-naturality
              (λ _ → idp)
              (ap (cst [ north ]))
              (λ p → ! (ap-cst [ north ] p))
              (emloop-comp g₁ g₂) ⟩
      GH.ap-cp₁₁-embase (G.comp g₁ g₂) ◃∙
      ap (λ _ → idp) (emloop-comp g₁ g₂) ◃∙
      ! (ap-cst [ north ] (emloop g₁ ∙ emloop g₂)) ◃∎
        =ₛ⟨ 1 & 1 & =ₛ-in {t = []} (ap-cst idp (emloop-comp g₁ g₂)) ⟩
      GH.ap-cp₁₁-embase (G.comp g₁ g₂) ◃∙
      ! (ap-cst [ north ] (emloop g₁ ∙ emloop g₂)) ◃∎
        =ₛ⟨ 0 & 1 & GH.ap-cp₁₁-embase-coh g₁ g₂ ⟩
      ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ◃∙
      ap-∙ (_G∪H embase) (emloop g₁) (emloop g₂) ◃∙
      ap2 _∙_ (GH.ap-cp₁₁-embase g₁) (GH.ap-cp₁₁-embase g₂) ◃∙
      ! (ap-cst [ north ] (emloop g₁ ∙ emloop g₂)) ◃∎
        =ₛ⟨ 3 & 1 & !-=ₛ $ ap-cst-coh [ north ] (emloop g₁) (emloop g₂) ⟩
      ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ◃∙
      ap-∙ (_G∪H embase) (emloop g₁) (emloop g₂) ◃∙
      ap2 _∙_ (GH.ap-cp₁₁-embase g₁) (GH.ap-cp₁₁-embase g₂) ◃∙
      ! (ap2 _∙_ (ap-cst [ north ] (emloop g₁)) (ap-cst [ north ] (emloop g₂))) ◃∙
      ! (ap-∙ (cst [ north ]) (emloop g₁) (emloop g₂)) ◃∎
        =ₛ₁⟨ 3 & 1 & ! (ap2-! _∙_ (ap-cst [ north ] (emloop g₁)) (ap-cst [ north ] (emloop g₂))) ⟩
      ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ◃∙
      ap-∙ (_G∪H embase) (emloop g₁) (emloop g₂) ◃∙
      ap2 _∙_ (GH.ap-cp₁₁-embase g₁) (GH.ap-cp₁₁-embase g₂) ◃∙
      ap2 _∙_ (! (ap-cst [ north ] (emloop g₁))) (! (ap-cst [ north ] (emloop g₂))) ◃∙
      ! (ap-∙ (cst [ north ]) (emloop g₁) (emloop g₂)) ◃∎
        =ₛ⟨ 2 & 2 & ∙-ap2-seq _∙_ (comm-emloop-embase-seq g₁) (comm-emloop-embase-seq g₂) ⟩
      ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ◃∙
      ap-∙ (_G∪H embase) (emloop g₁) (emloop g₂) ◃∙
      ap2 _∙_ (comm-emloop-embase' g₁) (comm-emloop-embase' g₂) ◃∙
      ! (ap-∙ (cst [ north ]) (emloop g₁) (emloop g₂)) ◃∎
        =ₛ₁⟨ 3 & 1 & !ap-∙=∙-ap (cst [ north ]) (emloop g₁) (emloop g₂) ⟩
      ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ◃∙
      ap-∙ (_G∪H embase) (emloop g₁) (emloop g₂) ◃∙
      ap2 _∙_ (comm-emloop-embase' g₁) (comm-emloop-embase' g₂) ◃∙
      ∙-ap (cst [ north ]) (emloop g₁) (emloop g₂) ◃∎ ∎ₛ

    comm-emloop-emloop' : ∀ g h →
      ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
      ap2 _∙_ (comm-embase-emloop' h) (comm-emloop-embase' g) ◃∎
      =ₛ
      ap2 _∙_ (comm-emloop-embase' g) (comm-embase-emloop' h) ◃∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎
    comm-emloop-emloop' g h =
      ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
      ap2 _∙_ (comm-embase-emloop' h) (comm-emloop-embase' g) ◃∎
        =ₛ⟨ 1 & 1 & ap2-out _∙_ (comm-embase-emloop' h) (comm-emloop-embase' g) ⟩
      ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
      ap (_∙ ap (_G∪H embase) (emloop g)) (comm-embase-emloop' h) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (comm-emloop-embase' g) ◃∎
        =ₛ⟨ 1 & 1 & ap-seq-=ₛ (_∙ ap (_G∪H embase) (emloop g))
                              (take-drop-split 1 (comm-embase-emloop-seq h)) ⟩
      ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
      ap (_∙ ap (_G∪H embase) (emloop g)) (ap-cst [ north ] (emloop h)) ◃∙
      ap (_∙ ap (_G∪H embase) (emloop g)) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (comm-emloop-embase' g) ◃∎
        =ₛ⟨ 3 & 1 & ap-seq-∙ (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (comm-emloop-embase-seq g) ⟩
      ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
      ap (_∙ ap (_G∪H embase) (emloop g)) (ap-cst [ north ] (emloop h)) ◃∙
      ap (_∙ ap (_G∪H embase) (emloop g)) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (GH.ap-cp₁₁-embase g) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (ap-cst [ north ] (emloop g))) ◃∎
        =ₛ⟨ 4 & 1 & ap-seq-=ₛ (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) step₄' ⟩
      ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
      ap (_∙ ap (_G∪H embase) (emloop g)) (ap-cst [ north ] (emloop h)) ◃∙
      ap (_∙ ap (_G∪H embase) (emloop g)) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (GH.ap-cp₁₁-embase g) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (↯ h₁'-seq) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (!-inv-r (h₁' embase))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
          (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
        =ₛ⟨ 2 & 2 & ap-comm-=ₛ _∙_ (↯ (tail (comm-embase-emloop-seq h))) (GH.ap-cp₁₁-embase g) ⟩
      ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
      ap (_∙ ap (_G∪H embase) (emloop g)) (ap-cst [ north ] (emloop h)) ◃∙
      ap (idp ∙_) (GH.ap-cp₁₁-embase g) ◃∙
      ap (_∙ idp) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (↯ h₁'-seq) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (!-inv-r (h₁' embase))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
          (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
        =ₛ⟨ 3 & 2 & ap-comm-=ₛ _∙_ (↯ (tail (comm-embase-emloop-seq h))) (↯ h₁'-seq) ⟩
      ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
      ap (_∙ ap (_G∪H embase) (emloop g)) (ap-cst [ north ] (emloop h)) ◃∙
      ap (idp ∙_) (GH.ap-cp₁₁-embase g) ◃∙
      ap (idp ∙_) (↯ h₁'-seq) ◃∙
      ap (λ a → a ∙ idp) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (!-inv-r (h₁' embase))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
          (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
        =ₛ₁⟨ 3 & 1 & ap (ap (idp ∙_)) (! (=ₛ-out heart))⟩
      ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
      ap (_∙ ap (_G∪H embase) (emloop g)) (ap-cst [ north ] (emloop h)) ◃∙
      ap (idp ∙_) (GH.ap-cp₁₁-embase g) ◃∙
      ap (idp ∙_) (↯ h₁-seq) ◃∙
      ap (λ a → a ∙ idp) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (!-inv-r (h₁' embase))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
          (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
        =ₛ⟨ 0 & 3 & top-part ⟩
      ap (ap (_G∪H embase) (emloop g) ∙_)
         (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
      ap (_∙ idp) (GH.ap-cp₁₁-embase g) ◃∙
      ap (idp ∙_) (↯ h₁-seq) ◃∙
      ap (λ a → a ∙ idp) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (!-inv-r (h₁' embase))) ◃∙
      ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
         (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
        =ₛ⟨ 4 & 3 & bottom-part ⟩
      ap (ap (_G∪H embase) (emloop g) ∙_)
         (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
      ap (_∙ idp) (GH.ap-cp₁₁-embase g) ◃∙
      ap (idp ∙_) (↯ h₁-seq) ◃∙
      ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h)) (! (ap-cst [ north ]₂ (emloop g))) ◃∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎
        =ₛ⟨ 2 & 2 & ap-comm-=ₛ _∙_ (GH.ap-cp₁₁-embase g) (↯ h₁-seq) ⟩
      ap (ap (_G∪H embase) (emloop g) ∙_)
         (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (↯ h₁-seq) ◃∙
      ap (_∙ idp) (GH.ap-cp₁₁-embase g) ◃∙
      ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h)) (! (ap-cst [ north ]₂ (emloop g))) ◃∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎
        =ₛ⟨ 3 & 2 & ap-comm-=ₛ _∙_ (GH.ap-cp₁₁-embase g) (↯ (tail (comm-embase-emloop-seq h))) ⟩
      ap (ap (_G∪H embase) (emloop g) ∙_)
         (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (↯ h₁-seq) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h)) (GH.ap-cp₁₁-embase g) ◃∙
      ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h)) (! (ap-cst [ north ]₂ (emloop g))) ◃∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎
        =ₛ⟨ 4 & 2 & ∙-ap-seq (_∙ ap (λ y → − (y H∪G embase)) (emloop h)) (comm-emloop-embase-seq g) ⟩
      ap (ap (_G∪H embase) (emloop g) ∙_)
         (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (↯ h₁-seq) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h)) (comm-emloop-embase' g) ◃∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎
        =ₛ⟨ 0 & 3 & ap-seq-=ₛ (ap (_G∪H embase) (emloop g) ∙_) step₁₃' ⟩
      ap (ap (_G∪H embase) (emloop g) ∙_) (ap-cst [ north ]₂ (emloop h)) ◃∙
      ap (ap (_G∪H embase) (emloop g) ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
      ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h)) (comm-emloop-embase' g) ◃∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎
        =ₛ⟨ 0 & 2 & !ₛ $ ap-seq-=ₛ (ap (_G∪H embase) (emloop g) ∙_) $
                    take-drop-split 1 (comm-embase-emloop-seq h) ⟩
      ap (ap (_G∪H embase) (emloop g) ∙_) (comm-embase-emloop' h) ◃∙
      ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h)) (comm-emloop-embase' g) ◃∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎
        =ₛ⟨ 0 & 2 & !ₛ (ap2-out' _∙_ (comm-emloop-embase' g) (comm-embase-emloop' h)) ⟩
      ap2 _∙_ (comm-emloop-embase' g) (comm-embase-emloop' h) ◃∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎ ∎ₛ
      where
      h₀ : ∀ y → embase G∪H y == [ north ]₂
      h₀ y = idp
      h₁ : ∀ y → embase G∪H y == [ north ]₂
      h₁ = transport (λ x → ∀ y → x G∪H y == [ north ]₂) (emloop g) h₀
      h₀' : ∀ x → − (embase H∪G x) == [ north ]₂
      h₀' x = idp
      h₁' : ∀ x → − (embase H∪G x) == [ north ]₂
      h₁' = transport (λ y → ∀ x → − (y H∪G x) == [ north ]₂) (emloop h) h₀'
      h₁-path : ∀ y → h₁ y == ! (ap [_]₂ (GH.η (GH.cp₀₁ g y)))
      h₁-path y =
        transport (λ x → ∀ y → x G∪H y == [ north ]₂) (emloop g) h₀ y
          =⟨ app= (transp-naturality {B = λ x → ∀ y → x G∪H y == [ north ]₂}
                                     {C = λ x → x G∪H y == [ north ]₂}
                                     (λ k → k y)
                                     (emloop g)) h₀ ⟩
        transport (λ x → x G∪H y == [ north ]₂) (emloop g) (h₀ y)
          =⟨ to-transp {B = λ x → x G∪H y == [ north ]₂} {p = emloop g} $
             ↓-app=cst-in {f = _G∪H y}
                          {p = emloop g} {u = idp}
                          {v = ! (ap (_G∪H y) (emloop g))} $
             ! (!-inv-r (ap (_G∪H y) (emloop g))) ⟩
        ! (ap (_G∪H y) (emloop g))
          =⟨ ap ! (GH.ap-cp₁₁ g y) ⟩
        ! (ap [_] (GH.η (GH.cp₀₁ g y))) =∎
      h₁'-path : ∀ x → h₁' x == ! (ap [_]₂ (GH.η (−₁ (HG.cp₀₁ h x))))
      h₁'-path x =
        transport (λ y → ∀ x → − (y H∪G x) == [ north ]₂) (emloop h) h₀' x
          =⟨ app= (transp-naturality {B = λ y → ∀ x → − (y H∪G x) == [ north ]₂}
                                     {C = λ y → − (y H∪G x) == [ north ]₂}
                                     (λ k → k x)
                                     (emloop h)) h₀' ⟩
        transport (λ y → − (y H∪G x) == [ north ]₂) (emloop h) (h₀' x)
          =⟨ to-transp {B = λ y → − (y H∪G x) == [ north ]₂} {p = emloop h} $
             ↓-app=cst-in {f = λ y → − (y H∪G x)}
                          {p = emloop h} {u = idp}
                          {v = ! (ap (λ y → − (y H∪G x)) (emloop h))} $
             ! (!-inv-r (ap (λ y → − (y H∪G x)) (emloop h))) ⟩
        ! (ap (λ y → − (y H∪G x)) (emloop h))
          =⟨ ap ! (ap-∘ − (_H∪G x) (emloop h)) ⟩
        ! (ap − (ap (_H∪G x) (emloop h)))
          =⟨ ap (! ∘ ap −) (HG.ap-cp₁₁ h x) ⟩
        ! (ap − (ap [_]₂ (HG.η (HG.cp₀₁ h x))))
          =⟨ ap ! (∘-ap − [_]₂ (HG.η (HG.cp₀₁ h x))) ⟩
        ! (ap (λ p → [ Susp-fmap −₁ p ]₂) (HG.η (HG.cp₀₁ h x)))
          =⟨ ap ! (ap-∘ [_]₂ (Susp-fmap −₁) (HG.η (HG.cp₀₁ h x))) ⟩
        ! (ap [_]₂ (ap (Susp-fmap −₁) (HG.η (HG.cp₀₁ h x))))
          =⟨ ! (ap (! ∘ ap [_]₂) (app= (ap fst (η-natural ⊙−₁)) (HG.cp₀₁ h x))) ⟩
        ! (ap [_]₂ (GH.η (−₁ (HG.cp₀₁ h x)))) =∎
        where open import homotopy.SuspAdjointLoop using (η-natural)
      h₁-seq : idp {a = [ north ]₂} =-= idp
      h₁-seq = ! (!-inv-r (h₁ embase)) ◃∙
                ap (λ v → h₁ v ∙ ! (h₁ embase)) (emloop h) ◃∙
                !-inv-r (h₁ embase) ◃∎
      h₁'-seq : idp {a = [ north ]₂} =-= idp
      h₁'-seq = ! (!-inv-r (h₁' embase)) ◃∙
                ! (ap (λ v → h₁' v ∙ ! (h₁' embase)) (emloop g)) ◃∙
                !-inv-r (h₁' embase) ◃∎
      {- the crucial step in the commutative diagram -}
      heart : h₁-seq =ₛ h₁'-seq
      heart =
        ! (!-inv-r (h₁ embase)) ◃∙
        ap (λ v → h₁ v ∙ ! (h₁ embase)) (emloop h) ◃∙
        !-inv-r (h₁ embase) ◃∎
          =ₛ⟨ =ₛ-in {t = ! (!-inv-r (! (ap [_]₂ (GH.η embase)))) ◃∙
                         ap (λ v → ! (ap [_]₂ (GH.η (GH.cp₀₁ g v))) ∙ ! (! (ap [_] (GH.η embase)))) (emloop h) ◃∙
                         !-inv-r (! (ap [_]₂ (GH.η embase))) ◃∎} $
              ap (λ f → ! (!-inv-r (f embase)) ∙
                        ap (λ v → f v ∙ ! (f embase)) (emloop h) ∙
                        !-inv-r (f embase))
                  (λ= h₁-path) ⟩
        ! (!-inv-r (! (ap [_]₂ (GH.η embase)))) ◃∙
        ap (λ v → ! (ap [_]₂ (GH.η (GH.cp₀₁ g v))) ∙ ! (! (ap [_]₂ (GH.η embase)))) (emloop h) ◃∙
        !-inv-r (! (ap [_]₂ (GH.η embase))) ◃∎
          =ₛ₁⟨ 1 & 1 &
                ap (λ v → ! (ap [_]₂ (GH.η (GH.cp₀₁ g v))) ∙ ! (! (ap [_]₂ (GH.η embase)))) (emloop h)
                  =⟨ ap-∘ (λ w → ! (ap [_]₂ (GH.η w)) ∙ ! (! (ap [_]₂ (GH.η embase)))) (GH.cp₀₁ g) (emloop h) ⟩
                ap (λ w → ! (ap [_]₂ (GH.η w)) ∙ ! (! (ap [_]₂ (GH.η embase)))) (ap (GH.cp₀₁ g) (emloop h))
                  =⟨ ap (ap (λ w → ! (ap [_]₂ (GH.η w)) ∙ ! (! (ap [_]₂ (GH.η embase))))) $
                    ap (GH.cp₀₁ g) (emloop h)
                      =⟨ CP₀₁-comm.cp₀₁-comm G H g h ⟩
                    ap (EM₁-fmap H⊗G.swap ∘ HG.cp₀₁ h) (emloop g)
                      =⟨ ! (!-! _) ⟩
                    ! (! (ap (EM₁-fmap H⊗G.swap ∘ HG.cp₀₁ h) (emloop g)))
                      =⟨ ap ! (! (EM₁-neg-! G⊗H.abgroup _)) ⟩
                    ! (ap (EM₁-neg G⊗H.abgroup) (ap (EM₁-fmap H⊗G.swap ∘ HG.cp₀₁ h) (emloop g)))
                      =⟨ ap ! (∘-ap (EM₁-neg G⊗H.abgroup) (EM₁-fmap H⊗G.swap ∘ HG.cp₀₁ h) (emloop g)) ⟩
                    ! (ap (−₁ ∘ HG.cp₀₁ h) (emloop g)) =∎
                    -- Yo dawg, I herd you like continued equalities,
                    -- so we put continued equalities into your continued equalities,
                    -- so u can reason equationally while u reason equationally.
                  ⟩
                ap (λ w → ! (ap [_]₂ (GH.η w)) ∙ ! (! (ap [_]₂ (GH.η embase)))) (! (ap (−₁ ∘ HG.cp₀₁ h) (emloop g)))
                  =⟨ ap-! (λ w → ! (ap [_]₂ (GH.η w)) ∙ ! (! (ap [_]₂ (GH.η embase)))) (ap (−₁ ∘ HG.cp₀₁ h) (emloop g)) ⟩
                ! (ap (λ w → ! (ap [_]₂ (GH.η w)) ∙ ! (! (ap [_]₂ (GH.η embase)))) (ap (−₁ ∘ HG.cp₀₁ h) (emloop g)))
                  =⟨ ap ! (∘-ap (λ w → ! (ap [_]₂ (GH.η w)) ∙ ! (! (ap [_]₂ (GH.η embase)))) (−₁ ∘ HG.cp₀₁ h) (emloop g)) ⟩
                ! (ap (λ v → ! (ap [_]₂ (GH.η (−₁ (HG.cp₀₁ h v)))) ∙ ! (! (ap [_]₂ (GH.η embase)))) (emloop g)) =∎
              ⟩
        ! (!-inv-r (! (ap [_]₂ (GH.η embase)))) ◃∙
        ! (ap (λ v → ! (ap [_]₂ (GH.η (−₁ (HG.cp₀₁ h v)))) ∙ ! (! (ap [_]₂ (GH.η embase)))) (emloop g)) ◃∙
        !-inv-r (! (ap [_]₂ (GH.η embase))) ◃∎
          =ₛ⟨ =ₛ-in {t = ! (!-inv-r (h₁' embase)) ◃∙
                         ! (ap (λ v → h₁' v ∙ ! (h₁' embase)) (emloop g)) ◃∙
                         !-inv-r (h₁' embase) ◃∎} $
              ap (λ f → ! (!-inv-r (f embase)) ∙
                        ! (ap (λ v → f v ∙ ! (f embase)) (emloop g)) ∙
                        !-inv-r (f embase))
                  (! (λ= h₁'-path)) ⟩
        ! (!-inv-r (h₁' embase)) ◃∙
        ! (ap (λ v → h₁' v ∙ ! (h₁' embase)) (emloop g)) ◃∙
        !-inv-r (h₁' embase) ◃∎ ∎ₛ
      transp-nat-idp : ∀ {i j k} {A : Type i} {B : Type j} {C : Type k} (f : A → B → C)
        {a₀ a₁ : A} (p : a₀ == a₁) (b : B)
        (c : C) (h₀ : ∀ b' → f a₀ b' == c)
        → app= (transp-naturality {B = λ a → ∀ b → f a b == c} (λ h → h b ∙ ! (h b)) p) h₀ ◃∎
          =ₛ
          !-inv-r (transport (λ a → ∀ b → f a b == c) p h₀ b) ◃∙
          ! (transp-idp (λ a → f a b) p) ◃∙
          ap (transport (λ a → f a b == f a b) p) (! (!-inv-r (h₀ b))) ◃∎
      transp-nat-idp f p@idp b c h₀ = !ₛ $
        !-inv-r (h₀ b) ◃∙
        idp ◃∙
        ap (λ r → r) (! (!-inv-r (h₀ b))) ◃∎
          =ₛ⟨ 1 & 1 & expand [] ⟩
        !-inv-r (h₀ b) ◃∙
        ap (λ r → r) (! (!-inv-r (h₀ b))) ◃∎
          =ₛ₁⟨ 1 & 1 & ap-idf (! (!-inv-r (h₀ b))) ⟩
        !-inv-r (h₀ b) ◃∙
        ! (!-inv-r (h₀ b)) ◃∎
          =ₛ₁⟨ !-inv-r (!-inv-r (h₀ b)) ⟩
        idp ◃∎ ∎ₛ
      top-part :
        ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
        ap (_∙ ap (_G∪H embase) (emloop g)) (ap-cst [ north ] (emloop h)) ◃∙
        ap (idp ∙_) (GH.ap-cp₁₁-embase g) ◃∎
          =ₛ
        ap (ap (_G∪H embase) (emloop g) ∙_)
           (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
        ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
        ap (_∙ idp) (GH.ap-cp₁₁-embase g) ◃∎
      top-part =
        ap-comm _G∪H_ (emloop g) (emloop h) ◃∙
        ap (_∙ ap (_G∪H embase) (emloop g))
           (ap-null-homotopic (λ y → [ north ]₂) (λ y → idp) (emloop' H.grp h)) ◃∙
        ap (idp ∙_) (GH.ap-cp₁₁-embase g) ◃∎
          =ₛ⟨ 0 & 2 & post-rotate-out {r = _ ◃∙ _ ◃∙ _ ◃∎} $
                      ap-comm-cst-coh _G∪H_ (emloop g) (emloop h) [ north ]₂ (λ y → idp) ⟩
        ap (ap (_G∪H embase) (emloop g) ∙_)
           (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
        ap (ap (_G∪H embase) (emloop g) ∙_)
           (app= (transp-naturality {B = λ x → ∀ y → x G∪H y == [ north ]₂} {C = λ x → x G∪H embase == x G∪H embase}
                                    (λ h → h embase ∙ ! (h embase)) (emloop g))
                 (λ y → idp)) ◃∙
        ! (ap-transp (_G∪H embase) (_G∪H embase) (emloop g) idp) ◃∙
        ap (idp ∙_) (GH.ap-cp₁₁-embase g) ◃∎
          =ₛ⟨ 1 & 1 & ap-seq-=ₛ (ap (_G∪H embase) (emloop g) ∙_)
                                (transp-nat-idp _G∪H_ (emloop g) embase [ north ]₂ (λ y → idp)) ⟩
        ap (ap (_G∪H embase) (emloop g) ∙_)
           (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
        ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
        ap (ap (_G∪H embase) (emloop g) ∙_)
            (! (transp-idp (_G∪H embase) (emloop g))) ◃∙
        idp ◃∙
        ! (ap-transp (_G∪H embase) (_G∪H embase) (emloop g) idp) ◃∙
        ap (idp ∙_) (GH.ap-cp₁₁-embase g) ◃∎
          =ₛ⟨ 3 & 1 & expand [] ⟩
        ap (ap (_G∪H embase) (emloop g) ∙_)
           (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
        ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
        ap (ap (_G∪H embase) (emloop g) ∙_)
           (! (transp-idp (_G∪H embase) (emloop g))) ◃∙
        ! (ap-transp (_G∪H embase) (_G∪H embase) (emloop g) idp) ◃∙
        ap (idp ∙_) (GH.ap-cp₁₁-embase g) ◃∎
          =ₛ₁⟨ 2 & 1 & ap-! (ap (_G∪H embase) (emloop g) ∙_) (transp-idp (_G∪H embase) (emloop g)) ⟩
        ap (ap (_G∪H embase) (emloop g) ∙_)
           (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
        ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
        ! (ap (ap (_G∪H embase) (emloop g) ∙_)
              (transp-idp (_G∪H embase) (emloop g))) ◃∙
        ! (ap-transp (_G∪H embase) (_G∪H embase) (emloop g) idp) ◃∙
        ap (idp ∙_) (GH.ap-cp₁₁-embase g) ◃∎
          =ₛ⟨ 2 & 2 & pre-rotate'-seq-in {p = _ ◃∙ _ ◃∎} {r = []} $
                      !ₛ $ ap-transp-idp (_G∪H embase) (emloop g) ⟩
        ap (ap (_G∪H embase) (emloop g) ∙_)
           (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
        ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
        ∙-unit-r (ap (_G∪H embase) (emloop g)) ◃∙
        ap (idp ∙_) (GH.ap-cp₁₁-embase g) ◃∎
          =ₛ⟨ 2 & 2 & !ₛ $ homotopy-naturality (_∙ idp) (idp ∙_) ∙-unit-r (GH.ap-cp₁₁-embase g) ⟩
        ap (ap (_G∪H embase) (emloop g) ∙_)
           (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
        ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
        ap (_∙ idp) (GH.ap-cp₁₁-embase g) ◃∙
        idp ◃∎
          =ₛ⟨ 3 & 1 & expand [] ⟩
        ap (ap (_G∪H embase) (emloop g) ∙_)
           (ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h)) ◃∙
        ap (ap (_G∪H embase) (emloop g) ∙_) (!-inv-r (h₁ embase)) ◃∙
        ap (_∙ idp) (GH.ap-cp₁₁-embase g) ◃∎ ∎ₛ
      bottom-part :
        ap (_∙ idp) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (!-inv-r (h₁' embase))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
           (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
        =ₛ
        ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h)) (! (ap-cst [ north ]₂ (emloop g))) ◃∙
        ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎
      bottom-part =
        ap (_∙ idp) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (!-inv-r (h₁' embase))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
           (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
          =ₛ⟨ 0 & 0 & contract ⟩
        idp ◃∙
        ap (_∙ idp) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (!-inv-r (h₁' embase))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
           (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
          =ₛ⟨ 0 & 2 & !ₛ (homotopy-naturality (idp ∙_) (_∙ idp) (! ∘ ∙-unit-r) (↯ (tail (comm-embase-emloop-seq h)))) ⟩
        ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ! (∙-unit-r (ap (λ y → − (y H∪G embase)) (emloop h))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (!-inv-r (h₁' embase))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
           (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
          =ₛ⟨ 1 & 1 & !ₛ $ post-rotate-in {p = _ ◃∙ _ ◃∎} $
                      ap-transp-idp (λ y → − (y H∪G embase)) (emloop h) ⟩
        ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ap-transp (λ y → − (y H∪G embase)) (λ y → − (y H∪G embase)) (emloop h) idp ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (transp-idp (λ y → − (y H∪G embase)) (emloop h)) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) (! (!-inv-r (h₁' embase))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
           (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
          =ₛ⟨ 2 & 2 & ap-seq-=ₛ (ap (λ y → − (y H∪G embase)) (emloop h) ∙_) $
              transp-idp (λ y → − (y H∪G embase)) (emloop h) ◃∙
              ! (!-inv-r (h₁' embase)) ◃∎
                =ₛ⟨ pre-rotate-out $ pre-rotate'-in $ post-rotate-in {p = []} $
                    transp-nat-idp (λ y x → − (y H∪G x)) (emloop h) embase [ north ]₂ (λ x → idp) ⟩
              idp ◃∙
              ! (app= (transp-naturality {B = λ y → ∀ x → − (y H∪G x) == [ north ]₂}
                                          (λ h → h embase ∙ ! (h embase)) (emloop h))
                      (λ x → idp)) ◃∎
                =ₛ⟨ 0 & 1 & expand [] ⟩
              ! (app= (transp-naturality {B = λ y → ∀ x → − (y H∪G x) == [ north ]₂}
                                          (λ h → h embase ∙ ! (h embase)) (emloop h))
                      (λ x → idp)) ◃∎ ∎ₛ
            ⟩
        ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ap-transp (λ y → − (y H∪G embase)) (λ y → − (y H∪G embase)) (emloop h) idp ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
           (! (app= (transp-naturality {B = λ y → ∀ x → − (y H∪G x) == [ north ]₂}
                                        (λ h → h embase ∙ ! (h embase)) (emloop h))
                    (λ x → idp))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
           (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
          =ₛ₁⟨ 2 & 1 & ap-! (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
                            (app= (transp-naturality {B = λ y → ∀ x → − (y H∪G x) == [ north ]₂}
                                                      (λ h → h embase ∙ ! (h embase)) (emloop h))
                                  (λ x → idp)) ⟩
        ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ap-transp (λ y → − (y H∪G embase)) (λ y → − (y H∪G embase)) (emloop h) idp ◃∙
        ! (ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
              (app= (transp-naturality {B = λ y → ∀ x → − (y H∪G x) == [ north ]₂}
                                        (λ h → h embase ∙ ! (h embase)) (emloop h))
                    (λ x → idp))) ◃∙
        ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
           (! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
          =ₛ₁⟨ 3 & 1 & ap-! (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
                            (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g)) ⟩
        ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ap-transp (λ y → − (y H∪G embase)) (λ y → − (y H∪G embase)) (emloop h) idp ◃∙
        ! (ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
              (app= (transp-naturality {B = λ y → ∀ x → − (y H∪G x) == [ north ]₂}
                                        (λ h → h embase ∙ ! (h embase)) (emloop h))
                    (λ x → idp))) ◃∙
        ! (ap (ap (λ y → − (y H∪G embase)) (emloop h) ∙_)
              (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g))) ◃∎
          =ₛ⟨ 1 & 3 & pre-rotate-out $
                      pre-rotate'-seq-in {p = _ ◃∙ _ ◃∎} $
                      post-rotate-in {p = []} $
                      ap-comm-cst-coh (λ y x → − (y H∪G x))
                                      (emloop h) (emloop g) [ north ]₂ (λ x → idp) ⟩
        ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ! (ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h))
              (ap-null-homotopic (λ x → − (embase H∪G x)) (λ x → idp) (emloop g))) ◃∙
        ! (ap-comm (λ y x → − (y H∪G x)) (emloop h) (emloop g)) ◃∎
          =ₛ₁⟨ 2 & 1 & ! (ap-comm-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h)) ⟩
        ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ! (ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h))
              (ap-null-homotopic (λ x → − (embase H∪G x)) (λ x → idp) (emloop g))) ◃∙
        ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎
          =ₛ₁⟨ 1 & 1 &
               !-ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h))
                    (ap-null-homotopic (λ x → − (embase H∪G x)) (λ x → idp) (emloop g)) ⟩
        ap (idp ∙_) (↯ (tail (comm-embase-emloop-seq h))) ◃∙
        ap (_∙ ap (λ y → − (y H∪G embase)) (emloop h)) (! (ap-cst [ north ]₂ (emloop g))) ◃∙
        ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) ◃∎ ∎ₛ
      step₄' : ! (ap-cst [ north ] (emloop g)) ◃∎
                =ₛ
                ↯ h₁'-seq ◃∙
                ! (!-inv-r (h₁' embase)) ◃∙
                ! (ap-null-homotopic (λ x → [ north ]₂) h₁' (emloop g)) ◃∎
      step₄' = pre-rotate'-in $ post-rotate-seq-in {p = []} $ !ₛ $
        ap-cst [ north ]₂ (emloop g) ◃∙
        ↯ h₁'-seq ◃∎
          =ₛ⟨ 1 & 1 & expand h₁'-seq ⟩
        ap-cst [ north ] (emloop g) ◃∙
        ! (!-inv-r (h₁' embase)) ◃∙
        ! (ap (λ v → h₁' v ∙ ! (h₁' embase)) (emloop g)) ◃∙
        !-inv-r (h₁' embase) ◃∎
          =ₛ⟨ 0 & 2 & !ₛ $ post-rotate-in {p = _ ◃∙ _ ◃∎} $
                      ap-null-homotopic-cst [ north ]₂ [ north ]₂ h₁' (emloop g) ⟩
        ap-null-homotopic (cst [ north ]₂) h₁' (emloop g) ◃∙
        ap (λ v → h₁' v ∙ ! (h₁' embase)) (emloop g) ◃∙
        ! (ap (λ v → h₁' v ∙ ! (h₁' embase)) (emloop g)) ◃∙
        !-inv-r (h₁' embase) ◃∎
          =ₛ⟨ 1 & 2 & seq-!-inv-r (ap (λ v → h₁' v ∙ ! (h₁' embase)) (emloop g) ◃∎) ⟩
        ap-null-homotopic (cst [ north ]₂) h₁' (emloop g) ◃∙
        !-inv-r (h₁' embase) ◃∎ ∎ₛ
      step₁₃' :
        ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h) ◃∙
        !-inv-r (h₁ embase) ◃∙
        ↯ h₁-seq ◃∎
        =ₛ
        ap-cst [ north ]₂ (emloop h) ◃∎
      step₁₃' =
        ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h) ◃∙
        !-inv-r (h₁ embase) ◃∙
        ↯ h₁-seq ◃∎
          =ₛ⟨ 2 & 1 & expand h₁-seq ⟩
        ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h) ◃∙
        !-inv-r (h₁ embase) ◃∙
        ! (!-inv-r (h₁ embase)) ◃∙
        ap (λ v → h₁ v ∙ ! (h₁ embase)) (emloop h) ◃∙
        !-inv-r (h₁ embase) ◃∎
          =ₛ⟨ 1 & 2 & seq-!-inv-r (!-inv-r (h₁ embase) ◃∎) ⟩
        ap-null-homotopic (λ y → [ north ]₂) h₁ (emloop h) ◃∙
        ap (λ v → h₁ v ∙ ! (h₁ embase)) (emloop h) ◃∙
        !-inv-r (h₁ embase) ◃∎
          =ₛ⟨ ap-null-homotopic-cst [ north ]₂ [ north ]₂ h₁ (emloop h) ⟩
        ap-cst [ north ]₂ (emloop h) ◃∎ ∎ₛ

  comm-embase-emloop : ∀ h →
    Square idp
            (ap (embase G∪H_) (emloop h))
            (ap (λ y → − (y H∪G embase)) (emloop h))
            idp
  comm-embase-emloop h = vert-degen-square (comm-embase-emloop' h)

  comm-emloop-embase : ∀ g →
    Square idp
            (ap (_G∪H embase) (emloop g))
            (ap (λ x → − (embase H∪G x)) (emloop g))
            idp
  comm-emloop-embase g = vert-degen-square (comm-emloop-embase' g)

  abstract

    square-helper : ∀ {i} {A : Type i}
      {a a' a'' : A}
      {p₀ : a == a'} {q₀ : a' == a''} {r₀ : a == a''}
      {p₁ : a == a'} {q₁ : a' == a''} {r₁ : a == a''}
      (s : r₀ == p₀ ∙ q₀)
      (p : p₀ == p₁)
      (q : q₀ == q₁)
      (t : p₁ ∙ q₁ == r₁)
      → s ∙v⊡ (vert-degen-square p ⊡h vert-degen-square q) ⊡v∙ t ==
        vert-degen-square (s ∙ ap2 _∙_ p q ∙ t)
    square-helper s p q t =
      s ∙v⊡ (vert-degen-square p ⊡h vert-degen-square q) ⊡v∙ t
        =⟨ ap (λ u → s ∙v⊡ u ⊡v∙ t) (vert-degen-square-⊡h p q) ⟩
      s ∙v⊡ vert-degen-square (ap2 _∙_ p q) ⊡v∙ t
        =⟨ ap (s ∙v⊡_) (vert-degen-square-⊡v∙ (ap2 _∙_ p q) t) ⟩
      s ∙v⊡ vert-degen-square (ap2 _∙_ p q ∙ t)
        =⟨ vert-degen-square-∙v⊡ s (ap2 _∙_ p q ∙ t) ⟩
      vert-degen-square (s ∙ ap2 _∙_ p q ∙ t) =∎

    comm-embase-emloop-comp : ∀ h₁ h₂ →
      comm-embase-emloop (H.comp h₁ h₂) ⊡v∙
      ap (ap (λ y → − (y H∪G embase))) (emloop-comp h₁ h₂)
      ==
      ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ∙v⊡
      ↓-='-square-comp (comm-embase-emloop h₁) (comm-embase-emloop h₂)
    comm-embase-emloop-comp h₁ h₂ =
      comm-embase-emloop (H.comp h₁ h₂) ⊡v∙
      ap (ap (λ y → − (y H∪G embase))) (emloop-comp h₁ h₂)
        =⟨ vert-degen-square-⊡v∙
              (comm-embase-emloop' (H.comp h₁ h₂))
              (ap (ap (λ y → − (y H∪G embase))) (emloop-comp h₁ h₂)) ⟩
      vert-degen-square
        (comm-embase-emloop' (H.comp h₁ h₂) ∙
          ap (ap (λ y → − (y H∪G embase))) (emloop-comp h₁ h₂))
        =⟨ ap vert-degen-square (=ₛ-out (comm-embase-emloop-comp' h₁ h₂)) ⟩
      vert-degen-square
        (ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ∙
          ap-∙ (embase G∪H_) (emloop h₁) (emloop h₂) ∙
          ap2 _∙_ (comm-embase-emloop' h₁) (comm-embase-emloop' h₂) ∙
          ∙-ap (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂))
        =⟨ ! $ vert-degen-square-∙v⊡ (ap (ap (embase G∪H_)) (emloop-comp h₁ h₂)) _ ⟩
      ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ∙v⊡
      vert-degen-square
        (ap-∙ (embase G∪H_) (emloop h₁) (emloop h₂) ∙
          ap2 _∙_ (comm-embase-emloop' h₁) (comm-embase-emloop' h₂) ∙
          ∙-ap (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂))
        =⟨ ap (ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ∙v⊡_) $ ! $
           square-helper (ap-∙ (embase G∪H_) (emloop h₁) (emloop h₂))
                         (comm-embase-emloop' h₁) (comm-embase-emloop' h₂)
                         (∙-ap (λ y → − (y H∪G embase)) (emloop h₁) (emloop h₂)) ⟩
      ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ∙v⊡
      ↓-='-square-comp' (comm-embase-emloop h₁) (comm-embase-emloop h₂)
        =⟨ ap (ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ∙v⊡_) $
           ↓-='-square-comp'=↓-='-square-comp (comm-embase-emloop h₁)
                                              (comm-embase-emloop h₂) ⟩
      ap (ap (embase G∪H_)) (emloop-comp h₁ h₂) ∙v⊡
      ↓-='-square-comp (comm-embase-emloop h₁) (comm-embase-emloop h₂) =∎

    comm-emloop-comp-embase : ∀ g₁ g₂ →
      comm-emloop-embase (G.comp g₁ g₂) ⊡v∙
      ap (ap (λ x → − (embase H∪G x))) (emloop-comp g₁ g₂)
      ==
      ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ∙v⊡
      ↓-='-square-comp (comm-emloop-embase g₁) (comm-emloop-embase g₂)
    comm-emloop-comp-embase g₁ g₂ =
      comm-emloop-embase (G.comp g₁ g₂) ⊡v∙
      ap (ap (λ x → − (embase H∪G x))) (emloop-comp g₁ g₂)
        =⟨ vert-degen-square-⊡v∙
             (comm-emloop-embase' (G.comp g₁ g₂))
             (ap (ap (λ x → − (embase H∪G x))) (emloop-comp g₁ g₂)) ⟩
      vert-degen-square
        (comm-emloop-embase' (G.comp g₁ g₂) ∙
          ap (ap (λ x → − (embase H∪G x))) (emloop-comp g₁ g₂))
          =⟨ ap vert-degen-square (=ₛ-out (comm-emloop-comp-embase' g₁ g₂)) ⟩
      vert-degen-square
        (ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ∙
         ap-∙ (_G∪H embase) (emloop g₁) (emloop g₂) ∙
         ap2 _∙_ (comm-emloop-embase' g₁) (comm-emloop-embase' g₂) ∙
         ∙-ap (λ x → − (embase H∪G x)) (emloop g₁) (emloop g₂))
        =⟨ ! $ vert-degen-square-∙v⊡ (ap (ap (_G∪H embase)) (emloop-comp g₁ g₂)) _ ⟩
      ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ∙v⊡
      vert-degen-square
        (ap-∙ (_G∪H embase) (emloop g₁) (emloop g₂) ∙
         ap2 _∙_ (comm-emloop-embase' g₁) (comm-emloop-embase' g₂) ∙
         ∙-ap (λ x → − (embase H∪G x)) (emloop g₁) (emloop g₂))
        =⟨ ap (ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ∙v⊡_) $ ! $
           square-helper
             (ap-∙ (_G∪H embase) (emloop g₁) (emloop g₂))
             (comm-emloop-embase' g₁) (comm-emloop-embase' g₂)
             (∙-ap (λ x → − (embase H∪G x)) (emloop g₁) (emloop g₂)) ⟩
      ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ∙v⊡
      ↓-='-square-comp' (comm-emloop-embase g₁) (comm-emloop-embase g₂)
        =⟨ ap (ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ∙v⊡_) $
           ↓-='-square-comp'=↓-='-square-comp
             (comm-emloop-embase g₁) (comm-emloop-embase g₂) ⟩
      ap (ap (_G∪H embase)) (emloop-comp g₁ g₂) ∙v⊡
      ↓-='-square-comp (comm-emloop-embase g₁) (comm-emloop-embase g₂) =∎

    comm-emloop-emloop : ∀ g h →
      ap-comm _G∪H_ (emloop g) (emloop h) ∙v⊡
      comm-embase-emloop h ⊡h comm-emloop-embase g
      ==
      (comm-emloop-embase g ⊡h comm-embase-emloop h) ⊡v∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h)
    comm-emloop-emloop g h =
      ap-comm _G∪H_ (emloop g) (emloop h) ∙v⊡
      comm-embase-emloop h ⊡h comm-emloop-embase g
        =⟨ ap (ap-comm _G∪H_ (emloop g) (emloop h) ∙v⊡_) $
           vert-degen-square-⊡h (comm-embase-emloop' h) (comm-emloop-embase' g) ⟩
      ap-comm _G∪H_ (emloop g) (emloop h) ∙v⊡
      vert-degen-square (ap2 _∙_ (comm-embase-emloop' h) (comm-emloop-embase' g))
        =⟨ vert-degen-square-∙v⊡ (ap-comm _G∪H_ (emloop g) (emloop h)) _ ⟩
      vert-degen-square
        (ap-comm _G∪H_ (emloop g) (emloop h) ∙
         ap2 _∙_ (comm-embase-emloop' h) (comm-emloop-embase' g))
        =⟨ ap vert-degen-square (=ₛ-out (comm-emloop-emloop' g h)) ⟩
      vert-degen-square
        (ap2 _∙_ (comm-emloop-embase' g) (comm-embase-emloop' h) ∙
         ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h))
        =⟨ ! $ vert-degen-square-⊡v∙ _ (ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h)) ⟩
      vert-degen-square (ap2 _∙_ (comm-emloop-embase' g) (comm-embase-emloop' h)) ⊡v∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h)
        =⟨ ap (_⊡v∙ ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h)) $ ! $
           vert-degen-square-⊡h (comm-emloop-embase' g) (comm-embase-emloop' h) ⟩
      (comm-emloop-embase g ⊡h comm-embase-emloop h) ⊡v∙
      ap-comm (λ x y → − (y H∪G x)) (emloop g) (emloop h) =∎

  module CP₁₁Comm =
    EM₁Level₂DoublePathElim G.grp H.grp {C = EMExplicit.EM G⊗H.abgroup 2} {{Trunc-level}}
      _G∪H_
      (λ x y → − (y H∪G x))
      idp
      comm-embase-emloop
      comm-emloop-embase
      comm-embase-emloop-comp
      comm-emloop-comp-embase
      comm-emloop-emloop

  abstract
    cp₁₁-comm : ∀ x y → x G∪H y == − (y H∪G x)
    cp₁₁-comm = CP₁₁Comm.f


open import Prelude hiding (subst; module Fin)

module Implicits.Substitutions.Lemmas.MetaType where

open import Implicits.Syntax.Type
open import Implicits.Syntax.Term hiding (var)
open import Implicits.Syntax.Context
open import Implicits.WellTyped
open import Implicits.Substitutions

open import Data.Vec hiding ([_])
open import Data.Fin as Fin using ()
open import Data.Fin.Substitution
open import Data.Fin.Substitution.Lemmas
open import Data.Vec.Properties
open import Data.Nat.Properties.Simple
open import Extensions.Substitution
open import Relation.Binary.HeterogeneousEquality as H using ()

private
  module HR = H.≅-Reasoning

module MetaTypeTypeLemmas where
  open MetaTypeTypeSubst hiding (_/✶_)
  open import Implicits.Syntax.MetaType
  open import Data.Star

  private module V = VarLemmas

  module _ {m : ℕ} where

    MT : ℕ → Set
    MT = MetaType m

    open MetaTypeApp hiding (_/_)

    module _ {T₁ T₂} {lift₁ : MetaLift T₁} {lift₂ : MetaLift T₂} where

        open Lifted {m} lift₁ using () renaming (_↑✶_ to _↑✶₁_; _/✶_ to _/✶₁_)
        open Lifted {m} lift₂ using () renaming (_↑✶_ to _↑✶₂_; _/✶_ to _/✶₂_)

        /✶-↑✶ : ∀ {n n'} (ρs₁ : Subs (T₁ m) n n') (ρs₂ : Subs (T₂ m) n n') →
                (∀ k x → (simpl (tvar x)) /✶₁ ρs₁ ↑✶₁ k ≡ (simpl (tvar x)) /✶₂ ρs₂ ↑✶₂ k) →
                ∀ k t → t /✶₁ ρs₁ ↑✶₁ k ≡ t /✶₂ ρs₂ ↑✶₂ k
        /✶-↑✶ ρs₁ ρs₂ hyp k (a ⇒ b) = begin
                (a ⇒ b) /✶₁ ρs₁ ↑✶₁ k
            ≡⟨ ⇒-/✶-↑✶ lift₁ k ρs₁ ⟩
                ((a /✶₁ ρs₁ ↑✶₁ k) ⇒ (b /✶₁ ρs₁ ↑✶₁ k))
            ≡⟨ cong₂ _⇒_ (/✶-↑✶ ρs₁ ρs₂ hyp k a) (/✶-↑✶ ρs₁ ρs₂ hyp k b) ⟩
                (a /✶₂ ρs₂ ↑✶₂ k) ⇒ (b /✶₂ ρs₂ ↑✶₂ k)
            ≡⟨ sym (⇒-/✶-↑✶ lift₂ k ρs₂) ⟩
                (a ⇒ b) /✶₂ ρs₂ ↑✶₂ k ∎
        /✶-↑✶ ρs₁ ρs₂ hyp k (∀' t) = begin
                (∀' t) /✶₁ ρs₁ ↑✶₁ k
            ≡⟨ ∀'-/✶-↑✶ lift₁ k ρs₁ ⟩
                ∀' (t /✶₁ ρs₁ ↑✶₁ (suc k))
            ≡⟨ cong ∀' (/✶-↑✶ ρs₁ ρs₂ hyp (suc k) t) ⟩
                ∀' (t /✶₂ ρs₂ ↑✶₂ (suc k))
            ≡⟨ sym $ ∀'-/✶-↑✶ lift₂ k ρs₂ ⟩
                (∀' t) /✶₂ ρs₂ ↑✶₂ k ∎
        /✶-↑✶ ρs₁ ρs₂ hyp k (simpl (tvar c)) = hyp k c
        /✶-↑✶ ρs₁ ρs₂ hyp k (simpl (mvar x)) = begin
                (simpl (mvar x)) /✶₁ ρs₁ ↑✶₁ k
            ≡⟨ mvar-/✶-↑✶ lift₁ k ρs₁ ⟩
                (simpl (mvar x))
            ≡⟨ sym $ mvar-/✶-↑✶ lift₂ k ρs₂ ⟩
                (simpl (mvar x)) /✶₂ ρs₂ ↑✶₂ k ∎
        /✶-↑✶ ρs₁ ρs₂ hyp k (simpl (a →' b)) = begin
                (simpl (a →' b)) /✶₁ ρs₁ ↑✶₁ k
            ≡⟨ →'-/✶-↑✶ lift₁ k ρs₁ ⟩
                simpl ((a /✶₁ ρs₁ ↑✶₁ k) →' (b /✶₁ ρs₁ ↑✶₁ k))
            ≡⟨ cong₂ (λ a b → simpl (a →' b)) (/✶-↑✶ ρs₁ ρs₂ hyp k a) (/✶-↑✶ ρs₁ ρs₂ hyp k b) ⟩
                simpl ((a /✶₂ ρs₂ ↑✶₂ k) →' (b /✶₂ ρs₂ ↑✶₂ k))
            ≡⟨ sym (→'-/✶-↑✶ lift₂ k ρs₂) ⟩
                (simpl (a →' b)) /✶₂ ρs₂ ↑✶₂ k ∎
        /✶-↑✶ ρs₁ ρs₂ hyp k (simpl (tc c)) = begin
                (simpl (tc c)) /✶₁ ρs₁ ↑✶₁ k
            ≡⟨ tc-/✶-↑✶ lift₁ k ρs₁ ⟩
                (simpl (tc c))
            ≡⟨ sym $ tc-/✶-↑✶ lift₂ k ρs₂ ⟩
                (simpl (tc c)) /✶₂ ρs₂ ↑✶₂ k ∎

    lemmas₃ : Lemmas₃ (MetaType m)
    lemmas₃ = record
        { lemmas₂ = record
        { lemmas₁ = record
            { lemmas₀ = record
            { simple = simple
            }
            ; weaken-var = λ {_ x} → begin
                (simpl (tvar x)) /Var V.wk      ≡⟨ refl ⟩
                (simpl (tvar (lookup x V.wk)))  ≡⟨ cong (λ x → simpl (tvar x)) (V.lookup-wk x) ⟩
                (simpl (tvar (suc x)))          ∎
            }
        ; application = Subst.application subst
        ; var-/       = refl
        }
        ; /✶-↑✶ = /✶-↑✶
        }

    private module L₃ = Lemmas₃ lemmas₃

    lemmas₅ : Lemmas₅ (MetaType m)
    lemmas₅ = record
        { lemmas₄ = record
        { lemmas₃ = lemmas₃
        ; /-wk    = λ {_ t} → begin
            t / wk       ≡⟨ /✶-↑✶ (ε ▻ wk) (ε ▻ V.wk)
                                (λ k x → begin
                                (simpl (tvar x)) / wk ↑⋆ k
                                  ≡⟨ L₃.var-/-wk-↑⋆ k x ⟩
                                (simpl (tvar (Fin.lift k suc x)))
                                  ≡⟨ cong (λ x → (simpl (tvar x))) (sym (V.var-/-wk-↑⋆ k x)) ⟩
                                (simpl (tvar (lookup x (V._↑⋆_ V.wk k))))
                                  ≡⟨ refl ⟩
                                (simpl (tvar x)) /Var V._↑⋆_ V.wk k        ∎)
                                zero t ⟩
            t /Var V.wk  ≡⟨ refl ⟩
            weaken t     ∎
        }
        }

    open Lemmas₅ lemmas₅ public hiding (lemmas₃)

module MetaTypeMetaLemmas where
  open MetaTypeMetaSubst using (module Lifted; MetaLift)
  open import Implicits.Syntax.MetaType
  open import Data.Star as Star hiding (map)
  open import Data.Star.Properties

  private module V = VarLemmas

  module MetaTypeAppLemmas {T} (l : MetaLift T) where
    open Lifted l

    →'-/✶-↑✶ : ∀ k {ν n n' a b} (ρs : Subs (flip T ν) n n') →
            (simpl (a →' b)) /✶ ρs ↑✶ k ≡ simpl ((a /✶ ρs ↑✶ k) →' (b /✶ ρs ↑✶ k))
    →'-/✶-↑✶ k ε        = refl
    →'-/✶-↑✶ k (r ◅ ρs) = cong₂ _/_ (→'-/✶-↑✶ k ρs) refl

    ⇒-/✶-↑✶ : ∀ k {ν n n' a b} (ρs : Subs (flip T ν) n n') →
            (a ⇒ b) /✶ ρs ↑✶ k ≡ (a /✶ ρs ↑✶ k) ⇒ (b /✶ ρs ↑✶ k)
    ⇒-/✶-↑✶ k ε        = refl
    ⇒-/✶-↑✶ k (r ◅ ρs) = cong₂ _/_ (⇒-/✶-↑✶ k ρs) refl

    tc-/✶-↑✶ : ∀ k {ν c n n'} (ρs : Subs (flip T ν) n n') →
            (simpl (tc c)) /✶ ρs ↑✶ k ≡ simpl (tc c)
    tc-/✶-↑✶ k ε        = refl
    tc-/✶-↑✶ k (r ◅ ρs) = cong₂ _/_ (tc-/✶-↑✶ k ρs) refl

    tvar-/✶-↑✶ : ∀ k {ν n n' c} (ρs : Subs (flip T ν) n n') →
            (simpl (tvar c)) /✶ ρs ↑✶ k ≡ simpl (tvar c)
    tvar-/✶-↑✶ k ε        = refl
    tvar-/✶-↑✶ k (r ◅ ρs) = cong₂ _/_ (tvar-/✶-↑✶ k ρs) refl

    tpweaken-subs : ∀ {ν n n'} (ρs : Subs (flip T ν) n n') → Subs (flip T (suc ν)) n n'
    tpweaken-subs ρs = Star.map (λ x → x ↑tp) ρs

    comm-↑-↑tp : ∀ {ν n n'} (s : Sub (flip T ν) n n') → (s ↑) ↑tp ≡ (s ↑tp) ↑
    comm-↑-↑tp s = begin
      (s ↑) ↑tp
        ≡⟨ refl ⟩
      map tpweaken (var zero ∷ map weaken s)
        ≡⟨ refl ⟩
      (tpweaken (var zero)) ∷ (map tpweaken (map weaken s))
        ≡⟨ cong₂ (λ x xs → x ∷ xs) (tpweaken-var zero) (sym $ map-∘ tpweaken weaken s) ⟩
      (var zero) ∷ (map (tpweaken ∘ weaken) s)
        ≡⟨ cong (λ u → var zero ∷ u) (sym $ map-cong comm-weaken-tpweaken s) ⟩
      (var zero) ∷ (map (weaken ∘ tpweaken) s)
        ≡⟨ cong (λ u → (var zero) ∷ u) (map-∘ weaken tpweaken s) ⟩
      (s ↑tp) ↑ ∎

    comm-↑⋆-↑tp : ∀ k {ν n n'} (s : Sub (flip T ν) n n') → (s ↑⋆ k) ↑tp ≡ (s ↑tp) ↑⋆ k
    comm-↑⋆-↑tp zero s = refl
    comm-↑⋆-↑tp (suc k) s = begin
      ((s ↑⋆ k) ↑) ↑tp
        ≡⟨ comm-↑-↑tp (s ↑⋆ k) ⟩
      ((s ↑⋆ k) ↑tp) ↑
        ≡⟨ cong _↑ (comm-↑⋆-↑tp k s) ⟩
      (s ↑tp) ↑⋆ (suc k) ∎

    comm-tpweaken-↑✶ : ∀ k {ν n n'} (ρs : Subs (flip T ν) n n') →
                     (tpweaken-subs ρs) ↑✶ k ≡ tpweaken-subs (ρs ↑✶ k)
    comm-tpweaken-↑✶ k ρs = begin
       (tpweaken-subs ρs) ↑✶ k
         ≡⟨ refl ⟩
       Star.gmap (_+_ k) (λ ρ → ρ ↑⋆ k) (Star.map _↑tp ρs)
         ≡⟨ gmap-∘ (_+_ k) (λ ρ₁ → ρ₁ ↑⋆ k) Prelude.id _↑tp ρs ⟩
       Star.gmap (_+_ k) (λ ρ → (ρ ↑tp) ↑⋆ k) ρs
       ≡⟨ gmap-cong (_+_ k) (λ ρ₁ → _↑tp ρ₁ ↑⋆ k) (λ ρ₁ → _↑tp (ρ₁ ↑⋆ k))
           (λ s → sym $ comm-↑⋆-↑tp k s) ρs ⟩
       Star.gmap (_+_ k) (λ ρ → (ρ ↑⋆ k) ↑tp) ρs
         ≡⟨ sym $ gmap-∘ Prelude.id _↑tp (_+_ k) (λ ρ₁ → ρ₁ ↑⋆ k) ρs ⟩
       Star.map _↑tp (Star.gmap (_+_ k) (λ ρ → ρ ↑⋆ k) ρs)
         ≡⟨ refl ⟩
       tpweaken-subs (ρs ↑✶ k) ∎

    ∀'-/✶-↑✶ : ∀ k {ν n n' a} (ρs : Subs (flip T ν) n n') →
               (∀' a) /✶ ρs ↑✶ k ≡ ∀' (a /✶ (tpweaken-subs ρs) ↑✶ k)
    ∀'-/✶-↑✶ k {a = a} ε = refl
    ∀'-/✶-↑✶ k {a = a} (x ◅ ρs) = begin
        (∀' a) /✶ (x  ◅ ρs) ↑✶ k
          ≡⟨ cong (flip _/_ (x ↑⋆ k)) (∀'-/✶-↑✶ k ρs) ⟩
        (∀' (a /✶ (tpweaken-subs ρs) ↑✶ k)) / (x ↑⋆ k)
          ≡⟨ cong (λ u → ∀' (a /✶ u / _↑tp (x ↑⋆ k))) (comm-tpweaken-↑✶ k ρs) ⟩
        ∀' (a /✶ (tpweaken-subs ((x ◅ ρs) ↑✶ k)))
          ≡⟨ sym $ cong (λ u → ∀' (a /✶ u)) (comm-tpweaken-↑✶ k (x ◅ ρs)) ⟩
        ∀' (a /✶ (tpweaken-subs (x ◅ ρs)) ↑✶ k) ∎

    module _ where
      open MetaTypeTypeSubst using () renaming (weaken to mtt-weaken)
      private
        module MTT = MetaTypeTypeSubst

      {-}↑tp-mtt-weaken : ∀ {ν m n} x (s : Sub (flip T ν) m n) →
                                 (mtt-weaken x) / (s ↑tp) ≡ mtt-weaken (x / s)-}
      postulate ↑tp-mtt-weaken : ∀ {ν m n } k x (s : Sub (flip T ν) m n) →
                       (x MTT./Var VarSubst.wk VarSubst.↑⋆ k) /
                         (Prelude.subst (λ ν → Sub (flip T ν) m n) (sym $ +-suc k ν) (s ↑tp⋆ (suc k))) ≡
                       (x / (s ↑tp⋆ k)) MTT./Var VarSubst.wk VarSubst.↑⋆ k
      {-
      ↑tp-mtt-weaken k (a ⇒ b) s = cong₂ _⇒_ (↑tp-mtt-weaken k a s) (↑tp-mtt-weaken k b s)
      ↑tp-mtt-weaken {ν} {m} {n} k (∀' x) s = begin
        (∀' (x MTT./Var VarSubst.wk VarSubst.↑⋆ (suc k))) /
          (Prelude.subst (λ ν → Sub (flip T ν) m n) (sym $ +-suc k ν) (s ↑tp⋆ (suc k)))
          ≡⟨ refl ⟩
        ∀' ((x MTT./Var VarSubst.wk VarSubst.↑⋆ (suc k)) /
          (Prelude.subst (λ ν → Sub (flip T ν) m n) (cong suc (sym $ +-suc k ν)) (s ↑tp⋆ (suc (suc k)))))
          ≡⟨ cong ∀' (↑tp-mtt-weaken (suc k) {!!} {!!}) ⟩
        (∀' ((x / (s ↑tp⋆ (suc k))) MTT./Var VarSubst.wk VarSubst.↑⋆ (suc k)))
          ≡⟨ refl ⟩
        (∀' (x / (s ↑tp⋆ (suc k)))) MTT./Var VarSubst.wk VarSubst.↑⋆ k
          ≡⟨ refl ⟩
        (∀' x / s ↑tp⋆ k) MTT./Var VarSubst.wk VarSubst.↑⋆ k ∎

      ↑tp-mtt-weaken k (simpl (tvar x)) s = refl
      ↑tp-mtt-weaken k (simpl (mvar x)) s = {!!}
      ↑tp-mtt-weaken k (simpl (a →' b)) s = cong₂ (λ u v → simpl (u →' v)) (↑tp-mtt-weaken k a s)
                                            (↑tp-mtt-weaken k b s)
      ↑tp-mtt-weaken k (simpl (tc x)) s = refl
      -}

      tpweaken-subs-var : ∀ {ν n n'} x (ρs : Subs (flip T ν) n n') →
                          (simpl (mvar x)) /✶ (tpweaken-subs ρs)
                            ≡ mtt-weaken ((simpl (mvar x)) /✶ ρs)
      tpweaken-subs-var x ε = refl
      tpweaken-subs-var x (s ◅ ρs) = begin
        (simpl (mvar x)) /✶ (Star.map _↑tp (s ◅ ρs))
          ≡⟨ refl ⟩
        (simpl (mvar x)) /✶ (tpweaken-subs ρs) / (s ↑tp)
          ≡⟨ cong (flip _/_ (_↑tp s)) (tpweaken-subs-var x ρs) ⟩
        (mtt-weaken ((simpl (mvar x)) /✶ ρs)) / (s ↑tp)
          ≡⟨ ↑tp-mtt-weaken zero (simpl (mvar x) /✶ ρs) s ⟩
        mtt-weaken ((simpl (mvar x)) /✶ (s ◅ ρs)) ∎

  module _ {T₁ T₂} {lift₁ : MetaLift T₁} {lift₂ : MetaLift T₂} where
    open MetaTypeTypeSubst using () renaming (weaken to mtt-weaken)

    open Lifted lift₁ using () renaming (_↑✶_ to _↑✶₁_; _/✶_ to _/✶₁_; _↑tp to _↑tp₁)
    open Lifted lift₂ using () renaming (_↑✶_ to _↑✶₂_; _/✶_ to _/✶₂_; _↑tp to _↑tp₂)

    open MetaTypeAppLemmas

    weaken-hyp : ∀ {ν n n'} (ρs₁ : Subs (flip T₁ ν) n n') (ρs₂ : Subs (flip T₂ ν) n n') →
                        (∀ k x → (simpl (mvar x)) /✶₁ ρs₁ ↑✶₁ k ≡ (simpl (mvar x)) /✶₂ ρs₂ ↑✶₂ k) →
                        (∀ k x → (simpl (mvar x)) /✶₁ (tpweaken-subs lift₁ ρs₁) ↑✶₁ k ≡ (simpl (mvar x)) /✶₂ (tpweaken-subs lift₂ ρs₂) ↑✶₂ k)
    weaken-hyp ρs₁ ρs₂ hyp k x = begin
      simpl (mvar x) /✶₁ (tpweaken-subs lift₁ ρs₁) ↑✶₁ k
        ≡⟨ cong (λ u → simpl (mvar x) /✶₁ u) (comm-tpweaken-↑✶ lift₁ k ρs₁) ⟩
      simpl (mvar x) /✶₁ tpweaken-subs lift₁ (ρs₁ ↑✶₁ k)
        ≡⟨ tpweaken-subs-var lift₁ x (ρs₁ ↑✶₁ k) ⟩
      mtt-weaken (simpl (mvar x) /✶₁ (ρs₁ ↑✶₁ k))
        ≡⟨ cong mtt-weaken (hyp k x) ⟩
      mtt-weaken (simpl (mvar x) /✶₂ (ρs₂ ↑✶₂ k))
        ≡⟨ sym $ tpweaken-subs-var lift₂ x (ρs₂ ↑✶₂ k) ⟩
      simpl (mvar x) /✶₂ tpweaken-subs lift₂ (ρs₂ ↑✶₂ k)
        ≡⟨ cong (λ u → simpl (mvar x) /✶₂ u) (sym $ comm-tpweaken-↑✶ lift₂ k ρs₂) ⟩
      simpl (mvar x) /✶₂ (tpweaken-subs lift₂ ρs₂) ↑✶₂ k ∎

    /✶-↑✶ : ∀ {ν n n'} (ρs₁ : Subs (flip T₁ ν) n n') (ρs₂ : Subs (flip T₂ ν) n n') →
            (∀ k x → (simpl (mvar x)) /✶₁ ρs₁ ↑✶₁ k ≡ (simpl (mvar x)) /✶₂ ρs₂ ↑✶₂ k) →
            ∀ k t → t /✶₁ ρs₁ ↑✶₁ k ≡ t /✶₂ ρs₂ ↑✶₂ k
    /✶-↑✶ ρs₁ ρs₂ hyp k (a ⇒ b) = begin
            (a ⇒ b) /✶₁ ρs₁ ↑✶₁ k
        ≡⟨ ⇒-/✶-↑✶ lift₁ k ρs₁ ⟩
            ((a /✶₁ ρs₁ ↑✶₁ k) ⇒ (b /✶₁ ρs₁ ↑✶₁ k))
        ≡⟨ cong₂ _⇒_ (/✶-↑✶ ρs₁ ρs₂ hyp k a) (/✶-↑✶ ρs₁ ρs₂ hyp k b) ⟩
            (a /✶₂ ρs₂ ↑✶₂ k) ⇒ (b /✶₂ ρs₂ ↑✶₂ k)
        ≡⟨ sym (⇒-/✶-↑✶ lift₂ k ρs₂) ⟩
            (a ⇒ b) /✶₂ ρs₂ ↑✶₂ k ∎
    /✶-↑✶ ρs₁ ρs₂ hyp k (∀' t) = begin
            (∀' t) /✶₁ ρs₁ ↑✶₁ k
        ≡⟨ ∀'-/✶-↑✶ lift₁ k ρs₁ ⟩
            (∀' (t /✶₁ (tpweaken-subs lift₁ ρs₁) ↑✶₁ k))
        ≡⟨ cong ∀' (/✶-↑✶ (tpweaken-subs lift₁ ρs₁) (tpweaken-subs lift₂ ρs₂) (weaken-hyp ρs₁ ρs₂ hyp) k t ) ⟩
            (∀' (t /✶₂ (tpweaken-subs lift₂ ρs₂) ↑✶₂ k))
        ≡⟨ sym $ ∀'-/✶-↑✶ lift₂ k ρs₂ ⟩
            (∀' t) /✶₂ ρs₂ ↑✶₂ k ∎
    /✶-↑✶ ρs₁ ρs₂ hyp k (simpl (mvar c)) = hyp k c
    /✶-↑✶ ρs₁ ρs₂ hyp k (simpl (tvar x)) = begin
            (simpl (tvar x)) /✶₁ ρs₁ ↑✶₁ k
        ≡⟨ tvar-/✶-↑✶ lift₁ k ρs₁ ⟩
            (simpl (tvar x))
        ≡⟨ sym $ tvar-/✶-↑✶ lift₂ k ρs₂ ⟩
            (simpl (tvar x)) /✶₂ ρs₂ ↑✶₂ k ∎
    /✶-↑✶ ρs₁ ρs₂ hyp k (simpl (a →' b)) = begin
            (simpl (a →' b)) /✶₁ ρs₁ ↑✶₁ k
        ≡⟨ →'-/✶-↑✶ lift₁ k ρs₁ ⟩
            simpl ((a /✶₁ ρs₁ ↑✶₁ k) →' (b /✶₁ ρs₁ ↑✶₁ k))
        ≡⟨ cong₂ (λ a b → simpl (a →' b)) (/✶-↑✶ ρs₁ ρs₂ hyp k a) (/✶-↑✶ ρs₁ ρs₂ hyp k b) ⟩
            simpl ((a /✶₂ ρs₂ ↑✶₂ k) →' (b /✶₂ ρs₂ ↑✶₂ k))
        ≡⟨ sym (→'-/✶-↑✶ lift₂ k ρs₂) ⟩
            (simpl (a →' b)) /✶₂ ρs₂ ↑✶₂ k ∎
    /✶-↑✶ ρs₁ ρs₂ hyp k (simpl (tc c)) = begin
            (simpl (tc c)) /✶₁ ρs₁ ↑✶₁ k
        ≡⟨ tc-/✶-↑✶ lift₁ k ρs₁ ⟩
            (simpl (tc c))
        ≡⟨ sym $ tc-/✶-↑✶ lift₂ k ρs₂ ⟩
            (simpl (tc c)) /✶₂ ρs₂ ↑✶₂ k ∎

  module _ {ν : ℕ} where
    open MetaTypeMetaSubst

    MT : ℕ → Set
    MT = flip MetaType ν

    lemmas₃ : Lemmas₃ (flip MetaType ν)
    lemmas₃ = record
        { lemmas₂ = record
        { lemmas₁ = record
            { lemmas₀ = record
            { simple = simple
            }
            ; weaken-var = λ {_ x} → begin
                (simpl (mvar x)) /Var V.wk      ≡⟨ refl ⟩
                (simpl (mvar (lookup x V.wk)))  ≡⟨ cong (λ x → simpl (mvar x)) (V.lookup-wk x) ⟩
                (simpl (mvar (suc x)))          ∎
            }
        ; application = Subst.application subst
        ; var-/       = refl
        }
        ; /✶-↑✶ = /✶-↑✶
        }

    private module L₃ = Lemmas₃ lemmas₃

    lemmas₅ : Lemmas₅ (flip MetaType ν)
    lemmas₅ = record
        { lemmas₄ = record
        { lemmas₃ = lemmas₃
        ; /-wk    = λ {_ t} → begin
            t / wk       ≡⟨ /✶-↑✶ (ε ▻ wk) (ε ▻ V.wk)
                                (λ k x → begin
                                (simpl (mvar x)) / wk ↑⋆ k
                                  ≡⟨ L₃.var-/-wk-↑⋆ k x ⟩
                                (simpl (mvar (Fin.lift k suc x)))
                                  ≡⟨ cong (λ x → (simpl (mvar x))) (sym (V.var-/-wk-↑⋆ k x)) ⟩
                                (simpl (mvar (lookup x (V._↑⋆_ V.wk k))))
                                  ≡⟨ refl ⟩
                                (simpl (mvar x)) /Var V._↑⋆_ V.wk k        ∎)
                                zero t ⟩
            t /Var V.wk  ≡⟨ refl ⟩
            weaken t     ∎
        }
        }

    open Lemmas₅ lemmas₅ public hiding (lemmas₃)

  open MetaTypeMetaSubst using (open-meta-k; open-meta; _↑⋆tp_; _↑tp; _◁m; _◁m₁)

  us↑-⊙-sub-u≡u∷us : ∀ {ν m} (u : MetaType zero ν) (us : Sub (flip MetaType ν) m zero) →
                     us ↑ ⊙ sub u ≡ u ∷ us
  us↑-⊙-sub-u≡u∷us {ν} {m} u us = cong (λ v → u ∷ v) map-weaken-⊙-sub

  open-mvar : ∀ {ν m} (x : Fin m) → open-meta {ν = ν} (simpl (mvar x)) ≡ simpl (mvar (suc x))
  open-mvar x = weaken-var

  open-tvar-suc : ∀ {ν m} (x : Fin m) → open-meta {ν} (simpl (tvar (suc x))) ≡ simpl (tvar x)
  open-tvar-suc x = MetaTypeTypeLemmas.suc-/-sub {t = (simpl (tvar x))}

  open import Implicits.Substitutions.Type as TS using ()
  open import Implicits.Substitutions.Lemmas.Type as TSLemmas using ()

  private
    module MTT = MetaTypeTypeSubst