Girona had not won in 13 matches and looked on course for a seventh straight defeat when Casemiro headed a dominant Madrid ahead in the first half.
But complacency set in, and Girona took full advantage as Cristhian Stuani scored a penalty and Portu nodded in at the back post, leaving the European champions scrapping even for a point before Sergio Ramos was sent off in the 90th minute.
They failed even to muster that, with defeat here a major act of self-harm for what was beginning to look like a serious resurgence in La Liga’s title race.
Barcelona had beaten Real Valladolid by a single goal on Saturday but their stodgy display continued a period of uncertainty for the Catalans, who still have to go to the Bernabeu later this month.
That Clasico will be a lot less nervy now, given Barca’s cushion has been extended to nine points over Real, with Atletico jumping back above them into second, seven points off the top.
The frustration for coach Santiago Solari will be that his team had this game in the palm of their hands, in control against a Girona side that celebrated at the end as if they had secured survival.
Their first league victory since November pushes them four points clear of the bottom three.
Solari will take some of the blame after he fielded a rotated line-up following the Champions League win over Ajax in midweek, their seventh win in eight games.
Gareth Bale and Vinicius Junior both started on the bench, while Luka Modric was suspended.
Madrid barely broke sweat in the first half, in control but playing within themselves as long spells of possession were only occasionally turned into a clear-cut chance.
The best move was marked by two scoops, the first by Toni Kroos, who lifted the ball over Pere Pons and squared for Lucas Vazquez, who repeated the trick, dinking it between two defenders, only for his finish to be saved by Bono.
Girona threatened in flashes. Stuani drew a decent stop from Thibaut Courtois and Alex Granell’s drive whistled past the post.
But Madrid never looked troubled and it was no surprise when Casemiro nodded in Kroos’ cross after Bono elected to punch rather than catch the initial ball in.
Comfortable to complacent
Eusebio brought on both Aleix Garcia and Anthony Lozano at half-time, and the impact was almost instant, as Garcia blazed over the rebound after Lozano’s header.
Madrid slipped from comfortable to complacent and shortly after the hour they were punished. Stuani’s header spilled out to Douglas Luiz, whose finish was blocked by the hand of Ramos.
Ramos’ yellow card might have been red, the defender perhaps only spared by two white shirts behind him on the line. Stuani made no mistake with the penalty.
Girona almost scored again, Portu’s shot rattling the outside of the post, and then they did. Casemiro missed a tackle in midfield and Lozano’s shot was parried to Portu. Marcelo dangled a leg but failed to stop the header, which crept inside the post.
Vinicius and Bale both came on but Vinicius three times missed the target from good positions, while Bale was whistled at one point after losing possession.
Casemiro wanted a penalty when he felt Pedro Alcala’s hand on his shoulder and moments later Ramos was sent off, drawing a second yellow card for attempting to volley and instead catching Alcala in the face.
Even Courtois was allowed up for a late corner and he got his head on it too but the ball flashed wide. The surprised applause quickly turned to groans at the full-time whistle.
For more news your way, download The Citizen’s app for iOS and Android.
Download our app and read this and other great stories on the move. Available for Android and iOS.