Given a nested dictionary data, return a new flattened dictionary where each nested key path is joined by .. Leaf values should be preserved as-is. If a value is itself a dictionary, continue flattening it recursively.
Assume keys are strings and values are either dictionaries or terminal values such as integers, strings, booleans, or None. The output should contain one entry for every leaf value in the nested structure.