In the fictional city of Oblya, a once-magical place modernizing under Rodinyan influence, 23-year-old Marlinchen Vashchenko lives sequestered with her two sisters and their father, Zmiy Vashchenko, in a crumbling manor with an enchanted garden. Zmiy is Oblya's last true wizard, cursed by a rival witch named Titka Whiskers so that he can never feel sated after eating, rested after sleeping, or genuine affection for his daughters. He forbids them from leaving, warning the outside world is dangerous. Each sister practices a different form of witchcraft for paying clients: Undine, the eldest, is a water-diviner; Rose, the middle sister, is an herbalist; and Marlinchen, who also serves as household cook and cleaner, is a flesh diviner whose magic requires skin-to-skin contact to read people's secrets. Zmiy controls their earnings, guards their virginity with a potion he claims will expose whether they have been "ruined," and keeps them isolated.
One night, Undine drags Marlinchen to the ballet theater to see
Bogatyr Ivan. Marlinchen is transfixed by the principal dancer, Sevastyan Rezkin, a 21-year-old member of Oblya's Yehuli minority, a group her father despises. After the show, she encounters Sevas drunk in an alley, and her hair ribbon falls loose.
Days later, Sevas arrives as a client with his handler, Ihor Derkach. Derkach wants Marlinchen to diagnose why Sevas falls ill after performances. Her magic reveals a disturbing vision: Derkach's face surfacing in Sevas's mind alongside revulsion when a woman touches Sevas intimately. Marlinchen lies about the diagnosis. Sevas returns her ribbon and invites her to the theater again. When the visitors leave, Zmiy erupts, denouncing Sevas and casting spells: Anyone from the ballet who crosses the threshold will turn into vipers, and no one may leave the house without a bowl of black sand from Oblya's beaches.
Years earlier, Zmiy destroyed Titka Whiskers's livelihood to monopolize witchcraft, earning her curse. He turned the sisters' mother into a white bird, claiming the transformation was accidental. Marlinchen tended her bird-mother in a third-floor cage until one morning the cage was empty. Zmiy said the bird flew away, but Marlinchen found a dark red drop on the floor. That evening, he served her
varenyky, a type of filled dumpling, with a filling she could not remember making.
Marlinchen discovers black sand washing off her body in the bath and collects it in her mother's clamshell compact. Rose helps her leave the house once, on three conditions: destroy the sand, return by 3 AM, and bring nothing back. Marlinchen warns Sevas about the viper spell, and he takes her to a tavern and the boardwalk, where she is overtaken by a vivid memory of standing on the shore with blood on her hands. She breaks all three of Rose's promises: She returns late, keeps a feather from Sevas's costume, and buries the compact under the garden's juniper tree instead of destroying the sand.
The family's crisis deepens when Zmiy devours everything in the house overnight. Marlinchen sells her mother's charm bracelet to a broker and kills the spiny-tailed monster under her bed to feed her father, the violence coming with disturbing ease. On a house call, she discovers Sevas is her client Fedir Holovaty's flatmate. Zmiy announces a competition: Men may stay three nights, and whoever discovers how his daughters escaped will win a bride and the estate. Marlinchen notices the bracelet has impossibly reappeared in her drawer and finds the broker's business card in Zmiy's pocket. A newspaper reports the broker has gone missing.
Backstory reveals that when Marlinchen was 16, a physician named Dr. Bakay visited the house under the pretense of studying witchcraft's effects on female anatomy, fondling and cutting Marlinchen while Zmiy watched or left them alone. Dr. Bakay now arrives as one of the suitors. Marlinchen counts plates at dinner and finds one fewer than expected; a gentle young suitor she privately calls Sobaka is missing. Zmiy claims he sent the man away, but Marlinchen finds a massive rib bone clogging the kitchen sink.
When Dr. Bakay corners Marlinchen in the foyer, her terror propels her to flee. She digs up the compact and runs to the theater. Sevas sees her mid-performance, leaps off the stage, and embraces her. Backstage, Derkach confronts Sevas, who smashes the dressing room mirrors and quits. Derkach kisses Sevas, declares his love, and leaves. Marlinchen tells Sevas about Dr. Bakay's abuse; Sevas insists what happened was violation, not magic. They make love among the broken glass.
The next morning, a mutilated body is found in the theater rafters, its heart and liver removed, matching killings reported across Oblya. Oblya's Grand Inspector—the city's chief law enforcement official—investigates the murders and publicly offers a three-hundred-ruble reward for information leading to the killer's capture. Marlinchen and Sevas return to the house. Sevas enters the competition as a suitor while they plan to steal the mirror that never lies from the third floor and sell it to fund their escape. When Marlinchen crosses the threshold, Zmiy's magic overwhelms her; she falls to her knees and kisses his boot. Inside, Zmiy feeds her a black juice he has given her before, a potion tied to her monstrous transformations. He confesses he orchestrated Dr. Bakay's abuse to ensure she would never leave.
Marlinchen catches Undine with Indrik, a half-man, half-goat creature from the garden. Undine reveals Zmiy's virginity potion never had real magic, and both she and Rose have known for years. Marlinchen tells Undine about Sevas; Undine attacks her and threatens to expose everything to Zmiy. Hours later, Undine's body is found mangled at the base of the juniper tree. Zmiy turns the iron fence into living vipers, trapping everyone inside.
Marlinchen tells Sevas she fears she killed Undine, though she has no memory of it. She approaches the fiery serpent, a telepathic creature in the garden, asking for the courage to face the truth. Upstairs, she uncovers the mirror that never lies. Her reflection shows a black-scaled, winged monster. The mirror reveals she killed the men on the boardwalk, the broker, the man in the theater, and Undine, her monstrous form pursuing desires she could not control. Sevas refuses to leave her.
She confronts Rose, who admits she made the black juice on Zmiy's orders. Rose explains the potion worked like rain on a seed: It could not have created the monster if the capacity had not already existed within Marlinchen. Together they strip the juniper tree's berries, and Marlinchen cooks them into the
varenyky she serves Zmiy and Dr. Bakay.
After eating, Dr. Bakay transforms into a monstrous creature. Rose throws a paralyzing potion, and the Grand Inspector's men, whom Derkach summoned, shoot Dr. Bakay dead. Zmiy transforms next and kills Derkach. Bullets pass through Zmiy harmlessly; as a wizard, mortal weapons cannot kill him. Marlinchen grabs a knife but freezes. Sevas takes it and plunges the blade into Zmiy's belly. The wizard collapses, scales fading, wings shriveling.
Zmiy survives and is sentenced to prison for life. Marlinchen, Rose, and Sevas split the reward and sell the house. Rose builds an independent herbalism practice; when she begs forgiveness, Marlinchen leaves without answering. Marlinchen visits Zmiy in prison and tells him the curse has swallowed him whole. She and Sevas take an apartment near the boardwalk, navigating their traumas. Some nights one holds the other; other nights, touch is unbearable. They plan to leave Oblya for Askoldir. At the train station, Marlinchen carries a goblin swaddled to her breast and follows Sevas onto the platform, watching the steppe unfold like blank parchment.