To solve this problem, we first need to define the decision variables and the objective function. Let's denote:

- $x_1$ as the number of pounds of family mix to be made.
- $x_2$ as the number of pounds of party mix to be made.

The objective is to maximize profit. Given that the family mix sells for $4.5 a pound and the party mix sells for $6 a pound, our objective function can be written as:

Maximize: $4.5x_1 + 6x_2$

Now, let's consider the constraints:

1. **Butter Popcorn Constraint**: The total amount of butter popcorn used in both mixes cannot exceed 35 pounds. Since the family mix has 50% butter popcorn and the party mix has 20% butter popcorn, this constraint can be written as:
   - $0.5x_1 + 0.2x_2 \leq 35$

2. **Caramel Popcorn Constraint**: The total amount of caramel popcorn used in both mixes cannot exceed 45 pounds. Given that the family mix has 50% caramel popcorn and the party mix has 80% caramel popcorn, this constraint can be written as:
   - $0.5x_1 + 0.8x_2 \leq 45$

3. **Non-Negativity Constraints**: Since we cannot produce a negative amount of either mix, both $x_1$ and $x_2$ must be non-negative:
   - $x_1 \geq 0$
   - $x_2 \geq 0$

Here's how we can translate this problem into Gurobi code in Python:

```python
from gurobipy import *

# Create a model
m = Model("popcorn_mix")

# Define the decision variables
x1 = m.addVar(vtype=GRB.CONTINUOUS, name="family_mix")
x2 = m.addVar(vtype=GRB.CONTINUOUS, name="party_mix")

# Set the objective function
m.setObjective(4.5*x1 + 6*x2, GRB.MAXIMIZE)

# Add constraints
m.addConstr(0.5*x1 + 0.2*x2 <= 35, "butter_popcorn")
m.addConstr(0.5*x1 + 0.8*x2 <= 45, "caramel_popcorn")

# Optimize the model
m.optimize()

# Print the results
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Family mix: {x1.x} pounds")
    print(f"Party mix: {x2.x} pounds")
    print(f"Maximum profit: ${4.5*x1.x + 6*x2.x}")
else:
    print("No optimal solution found")

```