diff --git a/corsika/detail/framework/core/Cascade.inl b/corsika/detail/framework/core/Cascade.inl
index 5f218b8780c063abfbbcbcd8339641ff5846f3f9..28306c590bb7da30d19d70f7ddfa19917ce525a0 100644
--- a/corsika/detail/framework/core/Cascade.inl
+++ b/corsika/detail/framework/core/Cascade.inl
@@ -121,11 +121,22 @@ namespace corsika {
     ContinuousProcessStepLength const continuousMaxStep =
         sequence_.getMaxStepLength(vParticle, step);
     LengthType const continuous_max_dist = continuousMaxStep;
-    ContinuousProcessIndex const limitingId = continuousMaxStep;
 
     // take minimum of geometry, interaction, decay for next step
-    auto const min_distance =
-        std::min({distance_interact, distance_decay, continuous_max_dist, geomMaxLength});
+    LengthType const min_discrete = std::min(distance_interact, distance_decay);
+    LengthType const min_non_continuous = std::min(min_discrete, geomMaxLength);
+    LengthType const min_distance = std::min(min_non_continuous, continuous_max_dist);
+
+    // inform ContinuousProcesses (if applicable) that it is responsible for step-limit
+    // this would become simpler if we follow the idea of Max to enumerate ALL types of
+    // processes. Then non-contunuous are included and no further logic is needed to
+    // distinguish between continuous and non-continuous limit.
+    ContinuousProcessIndex limitingId;
+    bool const isContinuous = continuous_max_dist < min_non_continuous;
+    if (isContinuous) {
+      limitingId =
+          continuousMaxStep; // the current step IS limited by a known continuous process
+    }
 
     CORSIKA_LOG_DEBUG(
         "transport particle by : {} m "
@@ -136,10 +147,12 @@ namespace corsika {
         min_distance / 1_m, geomMaxLength / 1_m, distance_decay / 1_m,
         distance_interact / 1_m, continuous_max_dist / 1_m);
 
-    // here the particle is actually moved along the trajectory to new position:
+    // move particle along the trajectory to new position
+    // also update momentum/direction/time
     step.setLength(min_distance);
     vParticle.setPosition(step.getPosition(1));
-    // assumption: tracking does not change absolute momentum:
+    // assumption: tracking does not change absolute momentum (continuous physics can and
+    // will):
     vParticle.setMomentum(step.getDirection(1) * vParticle.getMomentum().getNorm());
     vParticle.setTime(vParticle.getTime() + step.getDuration());
 
@@ -148,54 +161,52 @@ namespace corsika {
         ProcessReturn::ParticleAbsorbed) {
       CORSIKA_LOG_DEBUG("Cascade: delete absorbed particle PID={} E={} GeV",
                         vParticle.getPID(), vParticle.getEnergy() / 1_GeV);
-      if (!vParticle.isErased()) vParticle.erase();
+      if (vParticle.isErased()) {
+        CORSIKA_LOG_WARN(
+            "Particle marked as Absorbed in doContinuous, but prematurely erased. This "
+            "may be bug. Check.");
+      } else {
+        vParticle.erase();
+      }
       return;
     }
+    if (isContinuous) {
+      return; // there is nothing further, step is finished
+    }
 
-    CORSIKA_LOG_DEBUG("sth. happening before geometric limit ? {}",
+    CORSIKA_LOG_DEBUG("discrete process before geometric limit ? {}",
                       ((min_distance < geomMaxLength) ? "yes" : "no"));
 
-    if (min_distance < geomMaxLength) { // interaction to happen within geometric limit
+    if (geomMaxLength < min_discrete) {
+      // geometric / tracking limit
 
-      // check whether decay or interaction limits this step the
-      // outcome of decay or interaction MAY be a) new particles in
-      // secondaries, b) the projectile particle deleted (or
-      // changed)
+      if (nextVol != currentLogicalNode) {
+        // boundary crossing, step is limited by volume boundary
 
-      TStackView secondaries(vParticle);
+        CORSIKA_LOG_DEBUG("volume boundary crossing to {}", fmt::ptr(nextVol));
 
-      if (min_distance < continuous_max_dist) {
+        if (nextVol == environment_.getUniverse().get()) {
+          CORSIKA_LOG_DEBUG(
+              "particle left physics world, is now in unknown space -> delete");
+          vParticle.erase();
+        }
+        vParticle.setNode(nextVol);
         /*
-          Create SecondaryView object on Stack. The data container
-          remains untouched and identical, and 'projectil' is identical
-          to 'vParticle' above this line. However,
-          projectil.AddSecondaries populate the SecondaryView, which can
-          then be used afterwards for further processing. Thus: it is
-          important to use projectle/view (and not vParticle) for Interaction,
-          and Decay!
-        */
+          doBoundary may delete the particle (or not)
 
-        [[maybe_unused]] auto projectile = secondaries.getProjectile();
-
-        if (distance_interact < distance_decay) {
-          interaction(secondaries);
-        } else {
-          decay(secondaries);
-          // make sure particle actually did decay if it should have done so
-          if (secondaries.getSize() == 1 &&
-              projectile.getPID() == secondaries.getNextParticle().getPID())
-            throw std::runtime_error(fmt::format("Particle {} decays into itself!",
-                                                 get_name(projectile.getPID())));
-        }
+          caveat: any changes to vParticle, or even the production
+          of new secondaries is currently not passed to ParticleCut,
+          thus, particles outside the desired phase space may be produced.
 
-        sequence_.doSecondaries(secondaries);
-        vParticle.erase();
-      } else { // step-length limitation within volume
+          \todo: this must be fixed.
+        */
 
-        CORSIKA_LOG_DEBUG("step-length limitation");
-        // no further physics happens here. just proceed to next step.
+        sequence_.doBoundaryCrossing(vParticle, *currentLogicalNode, *nextVol);
+        return; // step finished
       }
 
+      CORSIKA_LOG_DEBUG("step limit reached (e.g. deflection). nothing further happens.");
+
       [[maybe_unused]] auto const assertion = [&] {
         auto const* numericalNodeAfterStep =
             environment_.getUniverse()->getContainingNode(vParticle.getPosition());
@@ -208,31 +219,43 @@ namespace corsika {
       assert(assertion()); // numerical and logical nodes should match, since
                            // we did not cross any volume boundary
 
-    } else { // boundary crossing, step is limited by volume boundary
-
-      if (nextVol != currentLogicalNode) {
-
-        CORSIKA_LOG_DEBUG("volume boundary crossing to {}", fmt::ptr(nextVol));
-
-        if (nextVol == environment_.getUniverse().get()) {
-          CORSIKA_LOG_DEBUG(
-              "particle left physics world, is now in unknown space -> delete");
-          vParticle.erase();
-        }
-        vParticle.setNode(nextVol);
-        /*
-          doBoundary may delete the particle (or not)
+      // step length limit
+      return;
+    }
 
-          caveat: any changes to vParticle, or even the production
-          of new secondaries is currently not passed to ParticleCut,
-          thus, particles outside the desired phase space may be produced.
+    // interaction or decay to happen in this step
+    // the outcome of decay or interaction MAY be a) new particles in
+    // secondaries, b) the projectile particle deleted (or
+    // changed)
 
-          \todo: this must be fixed.
-        */
+    TStackView secondaries(vParticle);
 
-        sequence_.doBoundaryCrossing(vParticle, *currentLogicalNode, *nextVol);
-      }
+    /*
+      Create SecondaryView object on Stack. The data container
+      remains untouched and identical, and 'projectil' is identical
+      to 'vParticle' above this line. However,
+      projectil.AddSecondaries populate the SecondaryView, which can
+      then be used afterwards for further processing. Thus: it is
+      important to use projectle/view (and not vParticle) for Interaction,
+      and Decay!
+    */
+
+    [[maybe_unused]] auto projectile = secondaries.getProjectile();
+
+    if (distance_interact < distance_decay) {
+      interaction(secondaries);
+    } else {
+      decay(secondaries);
+      // make sure particle actually did decay if it should have done so
+      // \todo this should go to a validation code and not be included here
+      if (secondaries.getSize() == 1 &&
+          projectile.getPID() == secondaries.getNextParticle().getPID())
+        throw std::runtime_error(fmt::format("Particle {} decays into itself!",
+                                             get_name(projectile.getPID())));
     }
+
+    sequence_.doSecondaries(secondaries);
+    vParticle.erase();
   }
 
   template <typename TTracking, typename TProcessList, typename TStack,
diff --git a/corsika/detail/framework/core/ParticleProperties.inl b/corsika/detail/framework/core/ParticleProperties.inl
index 7d0aa253b838adf8a06d5f0cdfbb71022d896695..47504f4ea5f0dd02672418e260eb61dd6971c5c3 100644
--- a/corsika/detail/framework/core/ParticleProperties.inl
+++ b/corsika/detail/framework/core/ParticleProperties.inl
@@ -53,15 +53,15 @@ namespace corsika {
     return particle::detail::isHadron[static_cast<CodeIntType>(p)];
   }
 
-  inline bool constexpr is_em(Code c) {
+  inline bool constexpr is_em(Code const c) {
     return c == Code::Electron || c == Code::Positron || c == Code::Gamma;
   }
 
-  inline bool constexpr is_muon(Code c) {
+  inline bool constexpr is_muon(Code const c) {
     return c == Code::MuPlus || c == Code::MuMinus;
   }
 
-  inline bool constexpr is_neutrino(Code c) {
+  inline bool constexpr is_neutrino(Code const c) {
     return c == Code::NuE || c == Code::NuMu || c == Code::NuTau || c == Code::NuEBar ||
            c == Code::NuMuBar || c == Code::NuTauBar;
   }
@@ -88,7 +88,7 @@ namespace corsika {
     return stream << get_name(code);
   }
 
-  inline Code convert_from_PDG(PDGCode p) {
+  inline Code convert_from_PDG(PDGCode const p) {
     static_assert(particle::detail::conversionArray.size() % 2 == 1);
     // this will fail, for the strange case where the maxPDG is negative...
     int constexpr maxPDG{(particle::detail::conversionArray.size() - 1) >> 1};
diff --git a/corsika/detail/framework/process/ProcessSequence.inl b/corsika/detail/framework/process/ProcessSequence.inl
index 7a0d6409feadf182a1e8402c581d118009a75b2f..b93331d05079962f5e710ac8de952935eb289517 100644
--- a/corsika/detail/framework/process/ProcessSequence.inl
+++ b/corsika/detail/framework/process/ProcessSequence.inl
@@ -67,12 +67,10 @@ namespace corsika {
     }
 
     if constexpr (t2ProcSeq) {
-      if (!isAbsorbed(ret)) { ret |= B_.doContinuous(particle, vT, limitId); }
+      ret |= B_.doContinuous(particle, vT, limitId);
     } else if constexpr (is_continuous_process_v<process2_type>) {
-      if (!isAbsorbed(ret)) {
-        ret |= B_.doContinuous(particle, vT,
-                               limitId == ContinuousProcessIndex(IndexProcess2));
-      }
+      ret |=
+          B_.doContinuous(particle, vT, limitId == ContinuousProcessIndex(IndexProcess2));
     }
 
     return ret;
diff --git a/corsika/detail/modules/LongitudinalProfile.inl b/corsika/detail/modules/LongitudinalProfile.inl
index d332913b5d995c83135fdbcb2adf4d383cf13456..48deafe6e79a474f06ecf664d9b70640b8e7756b 100644
--- a/corsika/detail/modules/LongitudinalProfile.inl
+++ b/corsika/detail/modules/LongitudinalProfile.inl
@@ -35,9 +35,11 @@ namespace corsika {
     GrammageType const grammageStart = shower_axis_.getProjectedX(vTrack.getPosition(0));
     GrammageType const grammageEnd = shower_axis_.getProjectedX(vTrack.getPosition(1));
 
-    CORSIKA_LOG_INFO(
-        "pos1={} m, pos2={}, X={} g/cm2", vTrack.getPosition(0).getCoordinates() / 1_m,
-        vTrack.getPosition(1).getCoordinates() / 1_m, grammageStart / 1_g * square(1_cm));
+    CORSIKA_LOG_TRACE("pos1={} m, pos2={}, X1={} g/cm2, X2={} g/cm2",
+                      vTrack.getPosition(0).getCoordinates() / 1_m,
+                      vTrack.getPosition(1).getCoordinates() / 1_m,
+                      grammageStart / 1_g * square(1_cm),
+                      grammageEnd / 1_g * square(1_cm));
 
     // Note: particle may go also "upward", thus, grammageEnd<grammageStart
     const int binStart = std::ceil(grammageStart / dX_);
diff --git a/corsika/detail/modules/ObservationPlane.inl b/corsika/detail/modules/ObservationPlane.inl
index 33cb556ec0021a6fedf2d254b2d35ff559df18bb..c4da50e940f88e3b8a3d3e9f36ac0018eeb09466 100644
--- a/corsika/detail/modules/ObservationPlane.inl
+++ b/corsika/detail/modules/ObservationPlane.inl
@@ -48,7 +48,6 @@ namespace corsika {
     if (deleteOnHit_) {
       count_ground_++;
       energy_ground_ += energy;
-      particle.erase();
       return ProcessReturn::ParticleAbsorbed;
     } else {
       return ProcessReturn::Ok;
diff --git a/corsika/detail/modules/ParticleCut.inl b/corsika/detail/modules/ParticleCut.inl
index f4d75667518b743a421b429a6afb8170c71e9869..ffbbbed8ddd51cb99ffe45f92217ed426fe2ee91 100644
--- a/corsika/detail/modules/ParticleCut.inl
+++ b/corsika/detail/modules/ParticleCut.inl
@@ -153,7 +153,6 @@ namespace corsika {
     CORSIKA_LOG_TRACE("ParticleCut::DoContinuous");
     if (checkCutParticle(particle)) {
       CORSIKA_LOG_TRACE("removing during continuous");
-      particle.erase();
       // signal to upstream code that this particle was deleted
       return ProcessReturn::ParticleAbsorbed;
     }
diff --git a/corsika/detail/modules/StackInspector.inl b/corsika/detail/modules/StackInspector.inl
index 10b0f1582a31fcc01ada4b638f428917fc369747..caae6c59c8cb43b01cd1e9789366b51db2f9ec14 100644
--- a/corsika/detail/modules/StackInspector.inl
+++ b/corsika/detail/modules/StackInspector.inl
@@ -24,8 +24,8 @@
 namespace corsika {
 
   template <typename TStack>
-  inline StackInspector<TStack>::StackInspector(const int vNStep, const bool vReportStack,
-                                                const HEPEnergyType vE0)
+  inline StackInspector<TStack>::StackInspector(int const vNStep, bool const vReportStack,
+                                                HEPEnergyType const vE0)
       : StackProcess<StackInspector<TStack>>(vNStep)
       , ReportStack_(vReportStack)
       , E0_(vE0)
@@ -35,12 +35,12 @@ namespace corsika {
   inline StackInspector<TStack>::~StackInspector() {}
 
   template <typename TStack>
-  inline void StackInspector<TStack>::doStack(const TStack& vS) {
+  inline void StackInspector<TStack>::doStack(TStack const& vS) {
 
     [[maybe_unused]] int i = 0;
     HEPEnergyType Etot = 0_GeV;
 
-    for (const auto& iterP : vS) {
+    for (auto const& iterP : vS) {
       HEPEnergyType E = iterP.getEnergy();
       Etot += E;
       if (ReportStack_) {
@@ -60,7 +60,7 @@ namespace corsika {
     }
 
     auto const now = std::chrono::system_clock::now();
-    const std::chrono::duration<double> elapsed_seconds = now - StartTime_;
+    std::chrono::duration<double> const elapsed_seconds = now - StartTime_;
     std::time_t const now_time = std::chrono::system_clock::to_time_t(now);
     auto const dE = E0_ - Etot;
     if (dE < dE_threshold_) return;
diff --git a/corsika/detail/modules/energy_loss/BetheBlochPDG.inl b/corsika/detail/modules/energy_loss/BetheBlochPDG.inl
index dff3b2bfb7dddd48309fe91a0b4ca94c0f1fad18..73fbf351707c35c894dd8cf48e0d250589909527 100644
--- a/corsika/detail/modules/energy_loss/BetheBlochPDG.inl
+++ b/corsika/detail/modules/energy_loss/BetheBlochPDG.inl
@@ -64,18 +64,18 @@ namespace corsika {
     double const beta2 = (gamma2 - 1) / gamma2; // 1-1/gamma2    (1-1/gamma)*(1+1/gamma);
                                                 // (gamma_2-1)/gamma_2 = (1-1/gamma2);
     double constexpr c2 = 1;                    // HEP convention here c=c2=1
-    CORSIKA_LOG_DEBUG("BetheBloch beta2={}, gamma2={}", beta2, gamma2);
+    CORSIKA_LOG_TRACE("BetheBloch beta2={}, gamma2={}", beta2, gamma2);
     [[maybe_unused]] double const eta2 = beta2 / (1 - beta2);
     HEPMassType const Wmax =
         2 * me * c2 * beta2 * gamma2 / (1 + 2 * gamma * me / m + me2 / m2);
     // approx, but <<1%    HEPMassType const Wmax = 2*me*c2*beta2*gamma2;      for HEAVY
     // PARTICLES Wmax ~ 2me v2 for non-relativistic particles
-    CORSIKA_LOG_DEBUG("BetheBloch Wmax={}", Wmax);
+    CORSIKA_LOG_TRACE("BetheBloch Wmax={}", Wmax);
 
     // Sternheimer parameterization, density corrections towards high energies
     // NOTE/TODO: when Cbar is 0 it needs to be approximated from parameterization ->
     // MISSING
-    CORSIKA_LOG_DEBUG("BetheBloch p.getMomentum().getNorm()/m{}=",
+    CORSIKA_LOG_TRACE("BetheBloch p.getMomentum().getNorm()/m{}=",
                       p.getMomentum().getNorm() / m);
     double const x = log10(p.getMomentum().getNorm() / m);
     double delta = 0;
@@ -86,7 +86,7 @@ namespace corsika {
     } else if (x < x0) { // and IF conductor (otherwise, this is 0)
       delta = delta0 * pow(100, 2 * (x - x0));
     }
-    CORSIKA_LOG_DEBUG("BetheBloch delta={}", delta);
+    CORSIKA_LOG_TRACE("BetheBloch delta={}", delta);
 
     // with further low energies correction, accurary ~1% down to beta~0.05 (1MeV for p)
 
@@ -142,17 +142,27 @@ namespace corsika {
   inline ProcessReturn BetheBlochPDG::doContinuous(setup::Stack::particle_type& p,
                                                    setup::Trajectory const& t,
                                                    bool const) {
+
+    // if this step was limiting the CORSIKA stepping, the particle is lost
+    /* see Issue https://gitlab.ikp.kit.edu/AirShowerPhysics/corsika/-/issues/389
+    if (limitStep) {
+      fillProfile(t, p.getEnergy());
+      p.setEnergy(p.getMass());
+      return ProcessReturn::ParticleAbsorbed;
+    }
+    */
+
     if (p.getChargeNumber() == 0) return ProcessReturn::Ok;
 
     GrammageType const dX =
         p.getNode()->getModelProperties().getIntegratedGrammage(t, t.getLength());
-    CORSIKA_LOG_DEBUG("EnergyLoss pid={}, z={}, dX={} g/cm2", p.getPID(),
+    CORSIKA_LOG_TRACE("EnergyLoss pid={}, z={}, dX={} g/cm2", p.getPID(),
                       p.getChargeNumber(), dX / 1_g * square(1_cm));
     HEPEnergyType dE = getTotalEnergyLoss(p, dX);
     auto E = p.getEnergy();
     [[maybe_unused]] const auto Ekin = E - p.getMass();
     auto Enew = E + dE;
-    CORSIKA_LOG_DEBUG("EnergyLoss  dE={} MeV, E={} GeV, Ekin={} GeV, Enew={} GeV",
+    CORSIKA_LOG_TRACE("EnergyLoss  dE={} MeV, E={} GeV, Ekin={} GeV, Enew={} GeV",
                       dE / 1_MeV, E / 1_GeV, Ekin / 1_GeV, Enew / 1_GeV);
     p.setEnergy(Enew);
     updateMomentum(p, Enew);
@@ -168,22 +178,17 @@ namespace corsika {
     }
 
     auto constexpr dX = 1_g / square(1_cm);
-    auto const dEdX = -getTotalEnergyLoss(vParticle, dX) / dX; // dE > 0
-    //~ auto const Ekin = vParticle.getEnergy() - vParticle.getMass();
-
-    auto const emCut = get_energy_threshold(vParticle.getPID());
-    // in any case: never go below 0.99*emCut This needs to be
-    // slightly smaller than emCut since, either this Step is limited
-    // by energy_lim, then the particle is stopped in a very short
-    // range (before doing anythin else) and is then removed
-    // instantly. The exact 3D position where it reaches emCut is not very
-    // important, the important fact is that its E_kin is zero
-    // afterwards.
-    //
-    const auto energy = vParticle.getEnergy();
-    auto energy_lim = std::max(0.9 * energy, 0.99 * emCut);
-
-    auto const maxGrammage = (energy - energy_lim) / dEdX;
+    auto const dEdX = -getTotalEnergyLoss(vParticle, dX) / dX;
+    auto const energy = vParticle.getEnergy();
+    auto const energy_lim = std::max(
+        energy * 0.9,                            // either 10% relative loss max., or
+        get_energy_threshold(vParticle.getPID()) // energy thresholds globally defined for
+                                                 // individual particles
+            *
+            0.99 // need to go 1% below global e-cut to assure removal in ParticleCut. The
+                 // 1% does not matter since at cut-time the entire energy is removed.
+    );
+    auto const maxGrammage = (vParticle.getEnergy() - energy_lim) / dEdX;
 
     return vParticle.getNode()->getModelProperties().getArclengthFromGrammage(
         vTrack, maxGrammage);
@@ -219,7 +224,7 @@ namespace corsika {
     if (binEnd < 0) binEnd = 0;
     if (binEnd > maxBin) binEnd = maxBin;
 
-    CORSIKA_LOG_DEBUG("energy deposit of -dE={} between {} and {}", -dE, grammageStart,
+    CORSIKA_LOG_TRACE("energy deposit of -dE={} between {} and {}", -dE, grammageStart,
                       grammageEnd);
 
     auto energyCount = HEPEnergyType::zero();
@@ -230,7 +235,7 @@ namespace corsika {
       profile_[bin] += increment;
       energyCount += increment;
 
-      CORSIKA_LOG_DEBUG("filling bin {} with weight {} : {} ", bin, weight, increment);
+      CORSIKA_LOG_TRACE("filling bin {} with weight {} : {} ", bin, weight, increment);
     };
 
     // fill longitudinal profile
@@ -242,7 +247,7 @@ namespace corsika {
       for (int bin = binStart + 1; bin < binEnd; ++bin) { fill(bin, dX_); }
     }
 
-    CORSIKA_LOG_DEBUG("total energy added to histogram: {} ", energyCount);
+    CORSIKA_LOG_TRACE("total energy added to histogram: {} ", energyCount);
   }
 
   inline void BetheBlochPDG::printProfile() const {
diff --git a/corsika/detail/modules/proposal/ContinuousProcess.inl b/corsika/detail/modules/proposal/ContinuousProcess.inl
index b4b0bf9638fbc6dd00d4d258d465cc6da4e65ca1..0e230a762aae1ca039e06570ea0bb2f87fa54a50 100644
--- a/corsika/detail/modules/proposal/ContinuousProcess.inl
+++ b/corsika/detail/modules/proposal/ContinuousProcess.inl
@@ -124,23 +124,20 @@ namespace corsika::proposal {
     // Limit the step size of a conitnuous loss. The maximal continuous loss seems to be a
     // hyper parameter which must be adjusted.
     //
-    auto const emCut = get_energy_threshold(
-        code); //! energy thresholds globally defined for individual particles
-
-    // in any case: never go below 0.99*emCut This needs to be
-    // slightly smaller than emCut since, either this Step is limited
-    // by energy_lim, then the particle is stopped in a very short
-    // range (before doing anythin else) and is then removed
-    // instantly. The exact position where it reaches emCut is not
-    // important, the important fact is that its E_kin is zero
-    // afterwards.
-    //
-    auto energy_lim = std::max(0.9 * vP.getEnergy(), 0.99 * emCut);
+    auto const energy = vP.getEnergy();
+    auto const energy_lim = std::max(
+        energy * 0.9, // either 10% relative loss max., or
+        get_energy_threshold(
+            code) // energy thresholds globally defined for individual particles
+            *
+            0.99 // need to go 1% below global e-cut to assure removal in ParticleCut. The
+                 // 1% does not matter since at cut-time the entire energy is removed.
+    );
 
     // solving the track integral for giving energy lim
     auto c = getCalculator(vP, calc);
     auto grammage = get<eDISPLACEMENT>(c->second)->SolveTrackIntegral(
-                        vP.getEnergy() / 1_MeV, energy_lim / 1_MeV) *
+                        energy / 1_MeV, energy_lim / 1_MeV) *
                     1_g / square(1_cm);
 
     // return it in distance aequivalent
diff --git a/corsika/detail/modules/pythia8/Decay.inl b/corsika/detail/modules/pythia8/Decay.inl
index d41c149024ff2d932fb259a909e07e6ac2ac2e63..d58ac21d851ff8b19be258e09e9a63a500784b1a 100644
--- a/corsika/detail/modules/pythia8/Decay.inl
+++ b/corsika/detail/modules/pythia8/Decay.inl
@@ -82,7 +82,7 @@ namespace corsika::pythia8 {
 
   inline void Decay::setHandleDecay(Code const vParticleCode) {
     handleAllDecays_ = false;
-    CORSIKA_LOG_INFO("Pythia::Decay: set to handle decay of {} ", vParticleCode);
+    CORSIKA_LOG_DEBUG("Pythia::Decay: set to handle decay of {} ", vParticleCode);
     if (Decay::canHandleDecay(vParticleCode))
       handledDecays_.insert(vParticleCode);
     else
@@ -106,12 +106,12 @@ namespace corsika::pythia8 {
   }
 
   inline void Decay::setUnstable(Code const pCode) {
-    CORSIKA_LOG_INFO("Pythia::Decay: setting {} unstable..", pCode);
+    CORSIKA_LOG_DEBUG("Pythia::Decay: setting {} unstable..", pCode);
     Pythia8::Pythia::particleData.mayDecay(static_cast<int>(get_PDG(pCode)), true);
   }
 
   inline void Decay::setStable(Code const pCode) {
-    CORSIKA_LOG_INFO("Pythia::Decay: setting {} stable..", pCode);
+    CORSIKA_LOG_DEBUG("Pythia::Decay: setting {} stable..", pCode);
     Pythia8::Pythia::particleData.mayDecay(static_cast<int>(get_PDG(pCode)), false);
   }
 
@@ -122,8 +122,8 @@ namespace corsika::pythia8 {
   inline bool Decay::canDecay(Code const pCode) {
     bool const ans =
         Pythia8::Pythia::particleData.canDecay(static_cast<int>(get_PDG(pCode)));
-    CORSIKA_LOG_INFO("Pythia::Decay: checking if particle: {} can decay in PYTHIA? {} ",
-                     pCode, ans);
+    CORSIKA_LOG_DEBUG("Pythia::Decay: checking if particle: {} can decay in PYTHIA? {} ",
+                      pCode, ans);
     return ans;
   }
 
@@ -153,13 +153,13 @@ namespace corsika::pythia8 {
 
       TimeType const t0 = get_lifetime(pid);
       auto const lifetime = gamma * t0;
-      CORSIKA_LOG_INFO("Pythia::Decay: code: {}", particle.getPID());
-      CORSIKA_LOG_INFO("Pythia::Decay: MinStep: t0: {}", t0);
-      CORSIKA_LOG_INFO("Pythia::Decay: MinStep: energy: {} GeV", E / 1_GeV);
-      CORSIKA_LOG_INFO("Pythia::Decay: momentum: {} GeV",
-                       particle.getMomentum().getComponents() / 1_GeV);
-      CORSIKA_LOG_INFO("Pythia::Decay: MinStep: gamma: {}", gamma);
-      CORSIKA_LOG_INFO("Pythia::Decay: MinStep: tau: {} ", lifetime);
+      CORSIKA_LOG_TRACE("Pythia::Decay: code: {}", particle.getPID());
+      CORSIKA_LOG_TRACE("Pythia::Decay: MinStep: t0: {}", t0);
+      CORSIKA_LOG_TRACE("Pythia::Decay: MinStep: energy: {} GeV", E / 1_GeV);
+      CORSIKA_LOG_TRACE("Pythia::Decay: momentum: {} GeV",
+                        particle.getMomentum().getComponents() / 1_GeV);
+      CORSIKA_LOG_TRACE("Pythia::Decay: MinStep: gamma: {}", gamma);
+      CORSIKA_LOG_TRACE("Pythia::Decay: MinStep: tau: {} ", lifetime);
 
       return lifetime;
     } else
@@ -209,7 +209,7 @@ namespace corsika::pythia8 {
     if (!Pythia8::Pythia::next())
       throw std::runtime_error("Pythia::Decay: decay failed!");
     else
-      CORSIKA_LOG_INFO("Pythia::Decay: particles after decay: {} ", event.size());
+      CORSIKA_LOG_DEBUG("Pythia::Decay: particles after decay: {} ", event.size());
 
     if (print_listing_) {
       // list final state
@@ -227,9 +227,10 @@ namespace corsika::pythia8 {
         FourVector const fourMomRest{Erest, pRest};
         auto const fourMomLab = boost.fromCoM(fourMomRest);
 
-        CORSIKA_LOG_INFO("particle: id={} momentum={} energy={} ", pyId,
-                         fourMomLab.getSpaceLikeComponents().getComponents(labCS) / 1_GeV,
-                         fourMomLab.getTimeLikeComponent());
+        CORSIKA_LOG_TRACE(
+            "particle: id={} momentum={} energy={} ", pyId,
+            fourMomLab.getSpaceLikeComponents().getComponents(labCS) / 1_GeV,
+            fourMomLab.getTimeLikeComponent());
 
         view.addSecondary(std::make_tuple(pyId, fourMomLab.getTimeLikeComponent(),
                                           fourMomLab.getSpaceLikeComponents(), decayPoint,
diff --git a/corsika/detail/modules/tracking/TrackingLeapFrogCurved.inl b/corsika/detail/modules/tracking/TrackingLeapFrogCurved.inl
index 415c1ada386c5840dd2c9ded27a28fdf7c3f2236..5770fe439dbc309588e990da8669c9f85ceb619c 100644
--- a/corsika/detail/modules/tracking/TrackingLeapFrogCurved.inl
+++ b/corsika/detail/modules/tracking/TrackingLeapFrogCurved.inl
@@ -176,8 +176,8 @@ namespace corsika {
           CORSIKA_LOG_TRACE("Solution (real) for current Volume: {} ", dist);
           if (numericallyInside) {
             // there must be an entry (negative) and exit (positive) solution
-            if (dist < 0.0001_m) { // security margin to assure transfer to next
-                                   // logical volume
+            if (dist < -0.0001_m) { // security margin to assure transfer to next
+                                    // logical volume
               if (first_entry == 0) {
                 d_enter = dist;
               } else {
@@ -200,7 +200,7 @@ namespace corsika {
 
             // both physical solutions (entry, exit) must be positive, and as small as
             // possible
-            if (dist < 0.0001_m) { // need small numerical margin, to assure transport
+            if (dist < -0.0001_m) { // need small numerical margin, to assure transport
               // into next logical volume
               continue;
             }
diff --git a/corsika/framework/core/ParticleProperties.hpp b/corsika/framework/core/ParticleProperties.hpp
index dafc1f02437fcecc0c926b9b9b94a283997c03b6..e133d68679c27bc597050a46d84c5bba2bfed70e 100644
--- a/corsika/framework/core/ParticleProperties.hpp
+++ b/corsika/framework/core/ParticleProperties.hpp
@@ -48,9 +48,9 @@ namespace corsika {
   using PDGCodeType = std::underlying_type<PDGCode>::type;
 
   // forward declarations to be used in GeneratedParticleProperties
-  int16_t constexpr get_charge_number(Code);     //!< electric charge in units of e
-  ElectricChargeType constexpr get_charge(Code); //!< electric charge
-  HEPMassType constexpr get_mass(Code);          //!< mass
+  int16_t constexpr get_charge_number(Code const);     //!< electric charge in units of e
+  ElectricChargeType constexpr get_charge(Code const); //!< electric charge
+  HEPMassType constexpr get_mass(Code const);          //!< mass
   HEPEnergyType constexpr get_energy_threshold(
       Code const); //!< get energy threshold below which the particle is discarded, by
                    //!< default set to particle mass
@@ -67,24 +67,26 @@ namespace corsika {
   }
 
   //! Particle code according to PDG, "Monte Carlo Particle Numbering Scheme"
-  PDGCode constexpr get_PDG(Code);
-  std::string_view constexpr get_name(Code); //!< name of the particle as string
-  TimeType constexpr get_lifetime(Code);     //!< lifetime
+  PDGCode constexpr get_PDG(Code const);
+  std::string_view constexpr get_name(Code const); //!< name of the particle as string
+  TimeType constexpr get_lifetime(Code const);     //!< lifetime
 
   //! true iff the particle is a hard-coded nucleus or Code::Nucleus
-  bool constexpr is_nucleus(Code);
-  bool constexpr is_hadron(Code);    //!< true iff particle is hadron
-  bool constexpr is_em(Code);        //!< true iff particle is electron, positron or gamma
-  bool constexpr is_muon(Code);      //!< true iff particle is mu+ or mu-
-  bool constexpr is_neutrino(Code);  //!< true iff particle is (anti-) neutrino
-  int constexpr get_nucleus_A(Code); //!< returns A for hard-coded nucleus, otherwise 0
-  int constexpr get_nucleus_Z(Code); //!< returns Z for hard-coded nucleus, otherwise 0
+  bool constexpr is_nucleus(Code const);
+  bool constexpr is_hadron(Code const); //!< true iff particle is hadron
+  bool constexpr is_em(Code const); //!< true iff particle is electron, positron or gamma
+  bool constexpr is_muon(Code const);     //!< true iff particle is mu+ or mu-
+  bool constexpr is_neutrino(Code const); //!< true iff particle is (anti-) neutrino
+  int constexpr get_nucleus_A(
+      Code const); //!< returns A for hard-coded nucleus, otherwise 0
+  int constexpr get_nucleus_Z(
+      Code const); //!< returns Z for hard-coded nucleus, otherwise 0
 
   //! returns mass of (A,Z) nucleus, disregarding binding energy
   HEPMassType get_nucleus_mass(unsigned int const, unsigned int const);
 
   //! convert PDG code to CORSIKA 8 internal code
-  Code convert_from_PDG(PDGCode);
+  Code convert_from_PDG(PDGCode const);
 
   std::initializer_list<Code> constexpr get_all_particles();
 
diff --git a/corsika/framework/process/ContinuousProcessIndex.hpp b/corsika/framework/process/ContinuousProcessIndex.hpp
index bc2617d2bb6ed5366431d1369480ef9abf593426..9d6e84d0f39baaa9a1e0ad7dbf369aba6a967fb3 100644
--- a/corsika/framework/process/ContinuousProcessIndex.hpp
+++ b/corsika/framework/process/ContinuousProcessIndex.hpp
@@ -18,6 +18,8 @@ namespace corsika {
 
   class ContinuousProcessIndex {
   public:
+    ContinuousProcessIndex()
+        : id_(-1) {} // default
     ContinuousProcessIndex(int const id)
         : id_(id) {}
     void setIndex(int const id) { id_ = id; }
diff --git a/corsika/setup/SetupTrajectory.hpp b/corsika/setup/SetupTrajectory.hpp
index 95a91115b0aa422c860448fa8057d70c35f95456..c40351d26f1c7bdef9d9b8ac18d3653caaf1927d 100644
--- a/corsika/setup/SetupTrajectory.hpp
+++ b/corsika/setup/SetupTrajectory.hpp
@@ -38,15 +38,15 @@ namespace corsika::setup {
      The default tracking algorithm.
    */
 
-  typedef corsika::tracking_leapfrog_curved::Tracking Tracking;
+  // typedef corsika::tracking_leapfrog_curved::Tracking Tracking;
   // typedef corsika::tracking_leapfrog_straight::Tracking Tracking;
-  // typedef corsika::tracking_line::Tracking Tracking;
+  typedef corsika::tracking_line::Tracking Tracking;
 
   /**
    The default trajectory.
   */
   /// definition of Trajectory base class, to be used in tracking and cascades
-  // typedef StraightTrajectory Trajectory;
-  typedef corsika::LeapFrogTrajectory Trajectory;
+  typedef StraightTrajectory Trajectory;
+  // typedef corsika::LeapFrogTrajectory Trajectory;
 
 } // namespace corsika::setup
diff --git a/do-clang-format.py b/do-clang-format.py
index 3bff0e619a14137fb9441b394a985875d0bbe7b2..d6ea597535e69da32de80ff31962ba998523305d 100755
--- a/do-clang-format.py
+++ b/do-clang-format.py
@@ -10,6 +10,14 @@ import os
 import sys
 import re
 
+do_progress = False
+try:    
+    from progress.bar import ChargingBar
+    do_progress = True
+except ImportError as e:
+    do_progress = False
+    # no progress bar
+
 parser = argparse.ArgumentParser(description=__doc__)
 parser.add_argument('--apply', action="store_true",
     help="Apply clang-format to files which need changes.")
@@ -85,17 +93,26 @@ version = subp.check_output(cmd.split() + ["--version"]).decode("utf-8")
 print (version)
 print ("Note: the clang-format version has an impact on the result. Make sure you are consistent with current CI. Consider \'--docker\' option.")
 
+
+bar = None
+if do_progress:
+    bar = ChargingBar('Processing', max=len(filelist))
+
 if args.apply:
     for filename in filelist:        
+        if bar: bar.next()
         subp.check_call(cmd.split() + ["-i", filename])
+    if bar: bar.finish()
         
 else:
     # only print files which need formatting
     files_need_formatting = 0
     for filename in filelist:
+        if bar: bar.next()
         a = open(filename, "rb").read()
         b = subp.check_output(cmd.split() + [filename])
         if a != b:
             files_need_formatting += 1
             print(filename)
+    if bar: bar.finish()            
     sys.exit(1 if files_need_formatting > 0 else 0)
diff --git a/examples/vertical_EAS.cpp b/examples/vertical_EAS.cpp
index 641fb95f85ce3e61e1779b21037ffc0ae6b3003c..bdad125b05e7557a4db27da54ee2eecae27d7592 100644
--- a/examples/vertical_EAS.cpp
+++ b/examples/vertical_EAS.cpp
@@ -6,8 +6,6 @@
  * the license.
  */
 
-#define DEBUG 1
-
 /* clang-format off */
 // InteractionCounter used boost/histogram, which
 // fails if boost/type_traits have been included before. Thus, we have
@@ -96,13 +94,15 @@ using MyExtraEnv = MediumPropertyModel<UniformMagneticField<T>>;
 int main(int argc, char** argv) {
 
   corsika_logger->set_pattern("[%n:%^%-8l%$] %s:%#: %v");
-  logging::set_level(logging::level::trace);
+  logging::set_level(logging::level::info);
 
   CORSIKA_LOG_INFO("vertical_EAS");
 
   if (argc < 4) {
-    std::cerr << "usage: vertical_EAS <A> <Z> <energy/GeV> [seed]" << std::endl;
-    std::cerr << "       if no seed is given, a random seed is chosen" << std::endl;
+    std::cerr << "usage: vertical_EAS <A> <Z> <energy/GeV> [seed] \n"
+                 "       if A=0, Z is interpreted as PDG code \n"
+                 "       if no seed is given, a random seed is chosen \n"
+              << std::endl;
     return 1;
   }
   feenableexcept(FE_INVALID);
@@ -131,7 +131,7 @@ int main(int argc, char** argv) {
   builder.addExponentialLayer(1144.9069_g / (1_cm * 1_cm), 878153.55_cm, 10_km);
   builder.addExponentialLayer(1305.5948_g / (1_cm * 1_cm), 636143.04_cm, 40_km);
   builder.addExponentialLayer(540.1778_g / (1_cm * 1_cm), 772170.16_cm, 100_km);
-  builder.addLinearLayer(1e9_cm, 112.8_km+constants::EarthRadius::Mean);
+  builder.addLinearLayer(1e9_cm, 112.8_km + constants::EarthRadius::Mean);
   builder.assemble(env);
 
   CORSIKA_LOG_DEBUG(
@@ -153,11 +153,20 @@ int main(int argc, char** argv) {
   // setup particle stack, and add primary particle
   setup::Stack stack;
   stack.clear();
-  const Code beamCode = Code::Nucleus;
   unsigned short const A = std::stoi(std::string(argv[1]));
-  unsigned short Z = std::stoi(std::string(argv[2]));
-  auto const mass = get_nucleus_mass(A, Z);
-  const HEPEnergyType E0 = 1_GeV * std::stof(std::string(argv[3]));
+  Code beamCode;
+  HEPEnergyType mass;
+  unsigned short Z = 0;
+  if (A > 0) {
+    beamCode = Code::Nucleus;
+    Z = std::stoi(std::string(argv[2]));
+    mass = get_nucleus_mass(A, Z);
+  } else {
+    int pdg = std::stoi(std::string(argv[2]));
+    beamCode = convert_from_PDG(PDGCode(pdg));
+    mass = get_mass(beamCode);
+  }
+  HEPEnergyType const E0 = 1_GeV * std::stof(std::string(argv[3]));
   double theta = 0.;
   auto const thetaRad = theta / 180. * M_PI;
 
@@ -187,17 +196,21 @@ int main(int argc, char** argv) {
 
   std::cout << "point of injection: " << injectionPos.getCoordinates() << std::endl;
 
-  if (A != 1) {
+  if (A > 1) {
     stack.addParticle(std::make_tuple(beamCode, E0, plab, injectionPos, 0_ns, A, Z));
 
   } else {
-    if (Z == 1) {
-      stack.addParticle(std::make_tuple(Code::Proton, E0, plab, injectionPos, 0_ns));
-    } else if (Z == 0) {
-      stack.addParticle(std::make_tuple(Code::Neutron, E0, plab, injectionPos, 0_ns));
+    if (A == 1) {
+      if (Z == 1) {
+        stack.addParticle(std::make_tuple(Code::Proton, E0, plab, injectionPos, 0_ns));
+      } else if (Z == 0) {
+        stack.addParticle(std::make_tuple(Code::Neutron, E0, plab, injectionPos, 0_ns));
+      } else {
+        std::cerr << "illegal parameters" << std::endl;
+        return EXIT_FAILURE;
+      }
     } else {
-      std::cerr << "illegal parameters" << std::endl;
-      return EXIT_FAILURE;
+      stack.addParticle(std::make_tuple(beamCode, E0, plab, injectionPos, 0_ns));
     }
   }
 
@@ -210,8 +223,7 @@ int main(int argc, char** argv) {
 
   // setup processes, decays and interactions
 
-  corsika::qgsjetII::Interaction qgsjet;
-
+  // corsika::qgsjetII::Interaction qgsjet;
   corsika::sibyll::Interaction sibyll;
   InteractionCounter sibyllCounted(sibyll);
 
@@ -259,7 +271,7 @@ int main(int argc, char** argv) {
 
   corsika::urqmd::UrQMD urqmd;
   InteractionCounter urqmdCounted{urqmd};
-  StackInspector<setup::Stack> stackInspect(1000, false, E0);
+  StackInspector<setup::Stack> stackInspect(50000, false, E0);
 
   // assemble all processes into an ordered process list
   struct EnergySwitch {
diff --git a/tests/modules/testParticleCut.cpp b/tests/modules/testParticleCut.cpp
index ef12f58e8489341ad64adcfd0d67194c064514cb..1bc67084bc633c62539ec8a644eb42528a8e4106 100644
--- a/tests/modules/testParticleCut.cpp
+++ b/tests/modules/testParticleCut.cpp
@@ -23,7 +23,7 @@
 
 using namespace corsika;
 
-TEST_CASE("ParticleCut", "[processes]") {
+TEST_CASE("ParticleCut", "processes") {
 
   logging::set_level(logging::level::info);
   corsika_logger->set_pattern("[%n:%^%-8l%$] %v");
@@ -222,7 +222,10 @@ TEST_CASE("ParticleCut", "[processes]") {
     for (auto proType : particleList) {
       auto particle = stack.addParticle(std::make_tuple(
           proType, Eabove, MomentumVector(rootCS, {0_GeV, 0_GeV, 0_GeV}), point0, 0_ns));
-      cut.doContinuous(particle, track);
+
+      if (cut.doContinuous(particle, track) == ProcessReturn::ParticleAbsorbed) {
+        particle.erase();
+      }
     }
 
     CHECK(stack.getEntries() == 9);