Sri Lanka's hopes of winning the first Test against India faded dramatically as openers Shikhar Dhawan and KL Rahul shared a partnership of 166 on day four in Kolkata.
Having limited their hosts to just 172 in a match affected by rain and bad light, Sri Lanka secured a first-innings lead of 122 by reaching 294 all out on Sunday, thanks largely to Rangana Herath's 67.
However, Dhawan and Rahul counter-attacked effectively to wipe out the deficit and establish a handy lead.
Dhawan fell agonisingly short of a century, caught behind for 94 aiming a wild heave at Dasun Shanaka, but Rahul remained unbeaten on 73 when poor light again forced an early close with India 171-1 and ahead by 49. They will now hope to apply pressure on the final day.
All 10 Sri Lanka first-innings wickets fell to seam bowling, Bhuvneshwar Kumar and Mohammed Shami returning 4-88 and 4-100 respectively as Umesh Yadav picked up the other two scalps.
The tourists began the fourth day on 165-4 but were wobbling at 201-7 after losing Niroshan Dickwella (35), Shanaka (0) and skipper Dinesh Chandimal (28) in the space of 10 deliveries - Shami striking twice either side of Bhuvneshwar's third breakthrough.
Yet Herath shared useful stands with Dilruwan Perera, who successfully reviewed an lbw decision despite initially walking off, and Suranga Lakmal to add handy runs to Sri Lanka's total.
Herath hit nine fours in his 105-ball innings, which was finally brought to an end by Bhuvneshwar before Shami wrapped up the innings in the next over.
The tone for India's second innings was set by Rahul, who struck Lahiru Gamage for three fours in the second over.
Gamage went on to put down a tough return chance when Rahul was on 22, while Dhawan survived two optimistic reviews as Sri Lanka failed to make inroads.
India were looking increasingly comfortable when a mighty six over long-on from Dhawan moved them into the lead and the left-hander soon cleared the ropes for a second time off Herath.
However, Dhawan could not reach stumps or three figures. Needing six to bring up his hundred, he stepped out of his crease to drive Shanaka, but got a thin edge behind that was spotted by umpire Nigel Llong despite the bowler failing to join the appeal. Dhawan reviewed immediately, but to no avail.