"""Generate Contracts analysis PDF for Kate W. (May 27, 2026)."""

from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.lib.colors import HexColor
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable
)
import os

# ── Color palette ──────────────────────────────────────────────────────
NAVY       = "#1a2744"
GOLD       = "#c9a227"
MED_TEXT   = "#2d3748"
LIGHT_TEXT = "#4a5568"
BORDER     = "#d4cfc5"
WARM_BG    = "#fdf6ee"
COOL_BG    = "#eef5ee"
ACTION_BG  = "#f0f4ff"
REWRITE_BEFORE = "#fce8e8"
REWRITE_AFTER  = "#e2f0e2"

# ── Output ─────────────────────────────────────────────────────────────
OUTPUT_DIR = os.path.dirname(os.path.abspath(__file__))
OUTPUT_FILE = os.path.join(OUTPUT_DIR, "Kate_Contracts_Analysis.pdf")

# ── Styles ─────────────────────────────────────────────────────────────
sTitle = ParagraphStyle("Title", fontName="Helvetica-Bold", fontSize=20,
                        leading=26, textColor=HexColor(NAVY), alignment=TA_LEFT)
sSubtitle = ParagraphStyle("Subtitle", fontName="Helvetica", fontSize=10,
                           leading=14, textColor=HexColor(LIGHT_TEXT),
                           spaceAfter=6)
sH1 = ParagraphStyle("H1", fontName="Helvetica-Bold", fontSize=13,
                      leading=18, textColor=HexColor(NAVY), spaceBefore=10,
                      spaceAfter=4)
sH2 = ParagraphStyle("H2", fontName="Helvetica-Bold", fontSize=11,
                      leading=15, textColor=HexColor(MED_TEXT), spaceBefore=6,
                      spaceAfter=3)
sBody = ParagraphStyle("Body", fontName="Helvetica", fontSize=9.5,
                        leading=14, textColor=HexColor(MED_TEXT),
                        alignment=TA_JUSTIFY, spaceAfter=4)
sBlock = ParagraphStyle("Block", fontName="Helvetica", fontSize=9,
                         leading=13.5, textColor=HexColor(MED_TEXT),
                         alignment=TA_JUSTIFY)
sAction = ParagraphStyle("Action", fontName="Helvetica", fontSize=9,
                          leading=13.5, textColor=HexColor(MED_TEXT),
                          alignment=TA_LEFT)
sLabel = ParagraphStyle("Label", fontName="Helvetica-Bold", fontSize=8.5,
                         leading=12, textColor=HexColor(LIGHT_TEXT),
                         spaceAfter=2)
sRewriteLabel = ParagraphStyle("RewriteLabel", fontName="Helvetica-Bold",
                                fontSize=8, leading=11,
                                textColor=HexColor(LIGHT_TEXT))
sRewriteText = ParagraphStyle("RewriteText", fontName="Helvetica",
                               fontSize=9.5, leading=14,
                               textColor=HexColor(MED_TEXT),
                               alignment=TA_JUSTIFY)
sFooter = ParagraphStyle("Footer", fontName="Helvetica", fontSize=8,
                          leading=10, textColor=HexColor(LIGHT_TEXT),
                          alignment=TA_LEFT)

# ── Helpers ────────────────────────────────────────────────────────────
def gold_hr(width="25%"):
    return HRFlowable(width=width, thickness=1.5, color=HexColor(GOLD),
                      spaceAfter=8, spaceBefore=4)

def thin_hr():
    return HRFlowable(width="100%", thickness=0.5, color=HexColor(BORDER),
                      spaceAfter=6, spaceBefore=8)

def shaded_block(label_text, body_text, bg_color):
    label = Paragraph(label_text, sLabel)
    body  = Paragraph(body_text, sBlock)
    inner = Table([[label], [body]], colWidths=["100%"])
    inner.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, -1), HexColor(bg_color)),
        ("TOPPADDING",    (0, 0), (-1, 0), 6),
        ("BOTTOMPADDING", (0, -1), (-1, -1), 8),
        ("LEFTPADDING",   (0, 0), (-1, -1), 10),
        ("RIGHTPADDING",  (0, 0), (-1, -1), 10),
        ("BOX", (0, 0), (-1, -1), 0.5, HexColor(BORDER)),
    ]))
    return inner

def action_box(text):
    body = Paragraph(text, sAction)
    t = Table([[body]], colWidths=["100%"])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, -1), HexColor(ACTION_BG)),
        ("TOPPADDING",    (0, 0), (-1, -1), 8),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 8),
        ("LEFTPADDING",   (0, 0), (-1, -1), 10),
        ("RIGHTPADDING",  (0, 0), (-1, -1), 10),
        ("BOX", (0, 0), (-1, -1), 0.5, HexColor(BORDER)),
    ]))
    return t

def rewrite_pair(before_text, after_text):
    bLabel = Paragraph("CONCLUSORY", sRewriteLabel)
    bText  = Paragraph(before_text, sRewriteText)
    before_block = Table([[bLabel], [bText]], colWidths=["100%"])
    before_block.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, -1), HexColor(REWRITE_BEFORE)),
        ("TOPPADDING",    (0, 0), (-1, 0), 5),
        ("BOTTOMPADDING", (0, -1), (-1, -1), 7),
        ("LEFTPADDING",   (0, 0), (-1, -1), 10),
        ("RIGHTPADDING",  (0, 0), (-1, -1), 10),
        ("BOX", (0, 0), (-1, -1), 0.5, HexColor(BORDER)),
    ]))
    aLabel = Paragraph("REWRITTEN", sRewriteLabel)
    aText  = Paragraph(after_text, sRewriteText)
    after_block = Table([[aLabel], [aText]], colWidths=["100%"])
    after_block.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, -1), HexColor(REWRITE_AFTER)),
        ("TOPPADDING",    (0, 0), (-1, 0), 5),
        ("BOTTOMPADDING", (0, -1), (-1, -1), 7),
        ("LEFTPADDING",   (0, 0), (-1, -1), 10),
        ("RIGHTPADDING",  (0, 0), (-1, -1), 10),
        ("BOX", (0, 0), (-1, -1), 0.5, HexColor(BORDER)),
    ]))
    return [before_block, Spacer(1, 4), after_block]


# ── Build document ─────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUTPUT_FILE, pagesize=letter,
    leftMargin=0.65*inch, rightMargin=0.65*inch,
    topMargin=0.55*inch, bottomMargin=0.5*inch,
)

story = []

# Title block
story.append(Paragraph("Deepening Your Analysis: Contracts", sTitle))
story.append(gold_hr("25%"))
story.append(Paragraph("Kate W.&nbsp;&nbsp;|&nbsp;&nbsp;Band 5/6&nbsp;&nbsp;|&nbsp;&nbsp;May 27, 2026", sSubtitle))
story.append(Spacer(1, 6))

# Intro
story.append(Paragraph(
    "This report walks through your Contracts essay side by side with a model "
    "Band 6 analysis. For each issue, you will see your analysis, the model "
    "analysis, and targeted commentary on what to sharpen. The goal is not to "
    "rewrite your essay -- it is to show you the specific analytical moves that "
    "separate a strong answer from a top-band answer. At the end, you will find "
    "concrete rewrite examples that turn conclusory sentences into the kind of "
    "element-by-element reasoning graders reward.",
    sBody
))
story.append(Spacer(1, 4))


# ═══════════════════════════════════════════════════════════════════════
# ISSUE 1: Parol Evidence Rule -- Oral Label Agreement
# ═══════════════════════════════════════════════════════════════════════
story.append(thin_hr())
story.append(Paragraph("Issue 1: Parol Evidence Rule -- Enforceability of the Oral Label Agreement", sH1))

# Student analysis
story.append(Spacer(1, 4))
story.append(shaded_block("YOUR ANALYSIS",
    "Under the parol evidence rule, evidence of prior contemporaneous written or oral agreements "
    "is barred if the agreement is a final and complete integration of all terms in the agreement. "
    "A final and complete integration is one where all the terms to the agreement were included "
    "but were not exclusive. If the agreement is not complete, it is a partial integration where "
    "not all the terms were included. The presence of a merger clause or statement of final "
    "integration are usually included in a final integration. However, if this clause or statement "
    "is missing, then one can reasonably conclude that the agreement is a partial integration. "
    "If an agreement is a partial integration, extrinsic evidence of a supplement can be "
    "introduced with consistent additional terms.<br/><br/>"
    "Here, the seller is trying to introduce extrinsic evidence that there was an oral agreement "
    "that the buyer continue to use the seller's label as long as he sells red wines. The written "
    "agreement did not include any of these terms and did not include any merger clauses or "
    "statements of a complete agreement. Since this clause or statement is missing a court can "
    "assume that the agreement is a partial integration. The buyer may argue that the terms are "
    "not consistent additional terms and are intended to modify the agreement. However, the "
    "extrinsic evidence can be introduced because the terms reflect the additional terms that "
    "were left out of the agreement.",
    WARM_BG
))
story.append(Spacer(1, 6))

# Model analysis
story.append(shaded_block("MODEL ANALYSIS",
    "Under the Parol Evidence Rule, extrinsic evidence of prior or contemporaneous oral "
    "agreements may not be introduced to contradict or vary the terms of a written contract "
    "that the parties intended to be the final expression of their agreement. The scope of "
    "the PER depends on the degree of integration. A <b>completely integrated</b> writing is "
    "final as to all terms, while a <b>partially integrated</b> writing is final only as to "
    "the terms it contains. Where a writing is only partially integrated, evidence of "
    "<b>consistent additional terms</b> is admissible -- particularly if such terms are part of "
    "a collateral agreement that would not ordinarily be expected to appear in the main written "
    "document.<br/><br/>"
    "Here, the written agreement does not contain a merger or integration clause, which would "
    "typically indicate that the parties intended it to be the complete and exclusive expression "
    "of all terms. The absence of this clause supports the conclusion that the writing is only "
    "partially integrated.<br/><br/>"
    "The oral agreement regarding the label <b>does not contradict</b> any term of the written "
    "agreement -- the writing is entirely silent on the label issue, meaning the oral term "
    "supplements rather than contradicts the writing. Furthermore, a personal labeling "
    "arrangement is the type of term that <b>might naturally be omitted</b> from a lengthy "
    "business sale contract, as it relates to a specific marketing preference rather than the "
    "core financial terms of the transaction. This supports treating it as a <b>collateral "
    "agreement</b> -- one that parties would not ordinarily include in the main contract.<br/><br/>"
    "Because the writing is only partially integrated and the oral label agreement is a "
    "consistent additional term that does not contradict the writing, the evidence of the "
    "oral agreement is admissible under the PER, and the agreement is enforceable.",
    COOL_BG
))
story.append(Spacer(1, 6))

# Commentary
story.append(Paragraph("COMMENTARY", sLabel))
story.append(Paragraph(
    "Your rule statement and issue identification are strong. You correctly identified that the "
    "absence of a merger clause points toward partial integration, and you reached the right "
    "conclusion. To move from Band 5 to Band 6, focus on two analytical gaps:<br/><br/>"
    "<b>First, explain <i>why</i> the oral term does not contradict the writing.</b> You mention "
    "that the buyer might argue the terms are not consistent, but you dismiss this without "
    "explaining the key point: the writing is <i>silent</i> on the label issue, so the oral "
    "term supplements rather than contradicts. This distinction matters to graders -- it shows "
    "you understand the difference between adding a new term and changing an existing one.<br/><br/>"
    "<b>Second, apply the collateral agreement analysis.</b> The model answer explains <i>why</i> "
    "a labeling arrangement might naturally be left out of a business sale contract -- it is a "
    "marketing preference, not a core financial term. This is the kind of fact-to-rule connection "
    "that demonstrates analytical depth. Your answer asserts the terms were \"left out\" but does "
    "not explain why that omission makes sense, which is what makes the collateral agreement "
    "argument persuasive.",
    sBody
))
story.append(Spacer(1, 4))

story.append(action_box(
    "<b>Build this habit:</b> After identifying a term as a \"consistent additional term,\" "
    "always add a sentence explaining why that term would naturally be left out of the main "
    "contract. Try this template: <i>\"This type of term -- [describe it] -- would not ordinarily "
    "be expected in a [type of contract] because [reason], which supports treating it as a "
    "collateral agreement.\"</i>"
))
story.append(Spacer(1, 6))


# ═══════════════════════════════════════════════════════════════════════
# ISSUE 2: Contract Interpretation -- Fair Share Ambiguity
# ═══════════════════════════════════════════════════════════════════════
story.append(thin_hr())
story.append(Paragraph("Issue 2: Contract Interpretation -- Ambiguity of \"Fair Share\"", sH1))

story.append(Spacer(1, 4))
story.append(shaded_block("YOUR ANALYSIS",
    "Under the Parole Evidence Rule (PER), extrinsic evidence of prior contemporaneous written "
    "or oral agreements is barred when an agreement is a final integration. However, extrinsic "
    "evidence may be introduced by the court if a term is ambiguous between the parties. The "
    "evidence is used not to modify the contract but to clarify and give meaning to the "
    "ambiguous term. Even if the contract is fully integrated courts allow extrinsic evidence "
    "to be introduced. Prior negotiations between parties are an acceptable source of extrinsic "
    "evidence to interpret an ambiguous term.<br/><br/>"
    "Here, the term fair share is ambiguous and extrinsic evidence can be introduced to clarify "
    "the term. The parties included in their written contract that \"fair share of the winery's "
    "profits\" would be given to the seller. The parties are disputing the fair share of the "
    "amount, the buyer saying 20%, while the seller says it is 25%. Since fair share is "
    "ambiguous and the parties are both disputing the term, extrinsic evidence can be "
    "introduced to clarify the meaning.",
    WARM_BG
))
story.append(Spacer(1, 6))

story.append(shaded_block("MODEL ANALYSIS",
    "Under the PER, extrinsic evidence is generally barred to contradict or vary the terms of "
    "an integrated writing. However, an important exception exists for the <b>interpretation of "
    "ambiguous terms</b>. A term is ambiguous when it is <b>reasonably susceptible to more than "
    "one meaning</b>. When a term is found to be ambiguous, the PER does not bar the admission "
    "of extrinsic evidence -- including evidence of prior negotiations -- to ascertain the "
    "meaning the parties intended.<br/><br/>"
    "Here, the written agreement provides that Buyer will pay Seller a \"fair share\" of the "
    "winery's first-year profits. This term is ambiguous because it <b>does not define what "
    "percentage or amount</b> constitutes a \"fair share,\" and <b>reasonable minds could differ</b> "
    "on its meaning. Indeed, the parties themselves assigned different values during negotiations "
    "-- Buyer suggested 20% and Seller suggested 25%. The fact that the writing does not define "
    "\"fair share\" with any specificity means the term is susceptible to multiple reasonable "
    "interpretations.<br/><br/>"
    "Because \"fair share\" is ambiguous, the PER exception for interpretation applies. Evidence "
    "of the negotiations is <b>directly relevant</b> to explaining the meaning the parties "
    "intended when they agreed to this term. This evidence is not being used to add a new term "
    "or contradict the writing -- it is being used to <b>give meaning to a term the parties "
    "included but left undefined</b>.<br/><br/>"
    "Therefore, Seller may introduce evidence of the negotiations under the interpretation "
    "exception to the PER.",
    COOL_BG
))
story.append(Spacer(1, 6))

story.append(Paragraph("COMMENTARY", sLabel))
story.append(Paragraph(
    "You identified the correct exception and reached the right conclusion. Your rule statement "
    "is solid, and you correctly noted that even fully integrated contracts allow extrinsic "
    "evidence to interpret ambiguous terms. Two refinements would elevate this to Band 6:<br/><br/>"
    "<b>First, explain <i>why</i> the term is ambiguous -- do not just assert it.</b> You wrote "
    "that \"fair share is ambiguous\" as a starting premise, but the grader needs to see the "
    "analytical step that gets you there. The model answer explains that the contract does not "
    "define what percentage or amount constitutes a \"fair share\" and that <i>reasonable minds "
    "could differ</i> on its meaning. That one sentence -- explaining what makes the term "
    "susceptible to multiple interpretations -- is the difference between asserting ambiguity "
    "and <i>proving</i> it.<br/><br/>"
    "<b>Second, connect the specific evidence to the specific interpretive task.</b> You mention "
    "the 20%/25% dispute, but the model answer explicitly frames this evidence as being used "
    "\"to give meaning to a term the parties included but left undefined\" -- not to add a new "
    "term or contradict the writing. This framing shows the grader you understand precisely "
    "<i>why</i> the evidence falls within the exception.",
    sBody
))
story.append(Spacer(1, 4))

story.append(action_box(
    "<b>Build this habit:</b> Whenever you identify a term as ambiguous, immediately follow "
    "with the reason. Try: <i>\"The term '[X]' is ambiguous because the contract does not "
    "define [what it means], and it is reasonably susceptible to more than one interpretation "
    "-- as demonstrated by [specific factual evidence of different meanings].\"</i>"
))
story.append(Spacer(1, 6))


# ═══════════════════════════════════════════════════════════════════════
# ISSUE 3: Non-Compete Enforceability
# ═══════════════════════════════════════════════════════════════════════
story.append(thin_hr())
story.append(Paragraph("Issue 3: Enforceability of the Non-Compete Agreement", sH1))

story.append(Spacer(1, 4))
story.append(shaded_block("YOUR ANALYSIS",
    "A covenant for a non-compete agreement is a restraint on trade and is only enforceable "
    "if there is a reasonable scope, duration, and a limitation on the geographic area. Courts "
    "are more likely to enforce a noncompete agreement if it is in the interest of the sale of "
    "a business and the buyer has a legitimate interest in protecting that interest when buying "
    "the property. The scope and the geographic limitation must not go further than to protect "
    "the buyer's interest. The duration must be reasonable. Courts will likely void or modify a "
    "non-compete agreement if any of the elements are found to be unreasonable.<br/><br/>"
    "Here, the buyers claim that the seller was in breach of the non-compete agreement because "
    "the seller was set to retire, which may not be a breach due to the unreasonableness of the "
    "terms. The Seller would not own or operate a winery anywhere in the United States for ten "
    "years after closing. The elements of reasonableness may be unreasonable because it severely "
    "limits the geographic scope and the duration. The geographic scope set to the entire United "
    "States is unreasonable because it limits the seller to not operate in an entire country. "
    "The duration may also be unreasonable because ten years is a very long period. However, "
    "buyer may argue that the woman was set to retire anyway and her entering the market again "
    "would severely impact his business. The court can modify or void the terms of the "
    "non-compete to make it more reasonable.",
    WARM_BG
))
story.append(Spacer(1, 6))

story.append(shaded_block("MODEL ANALYSIS",
    "Covenants not to compete are restraints on trade and are strictly construed. A non-compete "
    "is enforceable only if it is reasonable in three respects: (1) it must be necessary to "
    "protect a <b>legitimate business interest</b>; (2) it must be reasonable in <b>geographic "
    "scope</b>; and (3) it must be reasonable in <b>duration</b>. In the context of the sale "
    "of a business, courts are generally <b>more willing</b> to enforce non-competes than in "
    "the employment context, because the buyer has a legitimate interest in protecting the "
    "goodwill of the business purchased.<br/><br/>"
    "Here, Buyer has a legitimate interest in protecting the goodwill of the winery he purchased "
    "for $3 million. Seller's personal reputation was closely tied to the business -- as "
    "evidenced by the use of her picture on the wine label. Buyer's interest in preventing "
    "Seller from capitalizing on that reputation to divert customers is legitimate.<br/><br/>"
    "However, the geographic scope -- \"anywhere in the United States\" -- is likely "
    "unreasonable. The scope should be <b>no broader than necessary</b> to protect the buyer's "
    "legitimate interest. Buyer purchased a <b>single winery in a specific location</b>. "
    "Preventing Seller from operating any winery in the entire country goes far beyond what is "
    "needed to protect that goodwill. Seller opened her new winery \"in another state...far from "
    "her original winery,\" which suggests the new venture does not directly threaten Buyer's "
    "customer base. A more narrowly tailored restriction -- perhaps covering the state or region "
    "surrounding the original winery -- would be sufficient.<br/><br/>"
    "The 10-year duration is questionable, though courts in sale-of-business cases may allow "
    "longer durations because the seller's goodwill can have lingering value. However, combined "
    "with the overbroad geographic scope, the overall restraint is excessive.<br/><br/>"
    "Because the geographic scope is unreasonably broad, the covenant is likely unenforceable. "
    "Some courts may modify the restriction to make it reasonable (blue pencil doctrine), but "
    "if the court declines to modify, Buyer would not prevail because the underlying covenant "
    "is unenforceable.",
    COOL_BG
))
story.append(Spacer(1, 6))

story.append(Paragraph("COMMENTARY", sLabel))
story.append(Paragraph(
    "You identified the correct framework and reached a defensible conclusion. Your rule "
    "statement includes all three prongs of the reasonableness test, and you correctly noted "
    "that courts can modify overbroad non-competes. Three refinements would push this to "
    "Band 6:<br/><br/>"
    "<b>First, develop the legitimate business interest analysis with specific facts.</b> "
    "You mention that buyer has a legitimate interest, but the model answer connects this to "
    "<i>specific facts</i>: the $3 million purchase price, Seller's picture on the label, and "
    "the goodwill tied to her personal reputation. Graders reward this kind of fact-specific "
    "reasoning because it shows you are applying the law to <i>this</i> situation, not "
    "reciting a general rule.<br/><br/>"
    "<b>Second, avoid circular reasoning on geographic scope.</b> You wrote that the scope is "
    "\"unreasonable because it limits the seller to not operate in an entire country\" -- but "
    "that restates the scope rather than analyzing it. The model answer explains <i>why</i> "
    "a national scope is excessive: Buyer purchased a <i>single winery in one location</i>, "
    "so a national ban goes far beyond protecting the goodwill of that one business. The "
    "fact that Seller's new winery is \"far from\" the original further supports this -- it "
    "does not threaten Buyer's actual customer base.<br/><br/>"
    "<b>Third, acknowledge the sale-of-business distinction.</b> Courts treat non-competes in "
    "business sales differently than employment non-competes. Longer durations and broader "
    "scopes are more tolerable when a buyer paid for goodwill. The model answer uses this "
    "nuance to strengthen the analysis -- even in this more permissive context, a national "
    "scope for a single winery is excessive. Showing the grader you understand this distinction "
    "demonstrates analytical sophistication.",
    sBody
))
story.append(Spacer(1, 4))

story.append(action_box(
    "<b>Build this habit:</b> When analyzing reasonableness, never just label something as "
    "\"unreasonable.\" Instead, use this structure: <i>\"The [element] is unreasonable because "
    "[specific fact about the restriction] exceeds what is necessary to protect [specific "
    "interest], given that [specific fact about the business context].\"</i> This forces you "
    "to connect scope to interest on every prong."
))
story.append(Spacer(1, 8))


# ═══════════════════════════════════════════════════════════════════════
# CONCLUSORY vs. PROPER ANALYSIS
# ═══════════════════════════════════════════════════════════════════════
story.append(HRFlowable(width="100%", thickness=1.5, color=HexColor(GOLD),
                        spaceAfter=10, spaceBefore=10))

story.append(Paragraph("Conclusory Analysis vs. Proper Analysis", sH1))
story.append(Paragraph(
    "Below are four sentences from your essay rewritten to show the difference between "
    "asserting a conclusion and building toward one. In each pair, the analytical step that "
    "is missing from the original is the step that graders are looking for.",
    sBody
))
story.append(Spacer(1, 6))

# Rewrite 1
story.append(Paragraph("<b>1. Integration status</b>", sH2))
story.extend(rewrite_pair(
    "\"Since this clause or statement is missing a court can assume that the agreement "
    "is a partial integration of the agreement.\"",

    "\"The written agreement does not contain a merger or integration clause -- which would "
    "typically indicate that the parties intended the writing to be the complete and exclusive "
    "expression of all terms. Without such a clause, the writing is final as to the terms it "
    "contains but is not necessarily a complete expression of every term the parties agreed "
    "upon, supporting the conclusion that it is only partially integrated.\""
))
story.append(Spacer(1, 8))

# Rewrite 2
story.append(Paragraph("<b>2. Ambiguity identification</b>", sH2))
story.extend(rewrite_pair(
    "\"Since fair share is ambiguous and the parties are both disputing the term, extrinsic "
    "evidence can be introduced to clarify the meaning.\"",

    "\"The term 'fair share' is ambiguous because the contract does not define what percentage "
    "or amount it encompasses, and reasonable minds could differ on its meaning -- as "
    "demonstrated by the parties' own differing proposals of 20% and 25% during negotiations. "
    "Because the term is reasonably susceptible to more than one interpretation, the PER "
    "exception for interpretation applies, and extrinsic evidence of the parties' prior "
    "negotiations is admissible to ascertain the meaning they intended.\""
))
story.append(Spacer(1, 8))

# Rewrite 3
story.append(Paragraph("<b>3. Geographic scope analysis</b>", sH2))
story.extend(rewrite_pair(
    "\"The geographic scope set to the entire United States is unreasonable because it limits "
    "the seller to not operate in an entire country.\"",

    "\"The geographic scope of 'anywhere in the United States' extends far beyond what is "
    "necessary to protect Buyer's legitimate business interest. Buyer purchased a single winery "
    "in one location, so a nationwide restriction is not necessary to protect the goodwill of "
    "that one business. The fact that Seller opened her new winery in a distant state further "
    "demonstrates that the restriction is overbroad -- her new venture does not threaten "
    "Buyer's actual customer base or the goodwill he purchased.\""
))
story.append(Spacer(1, 8))

# Rewrite 4
story.append(Paragraph("<b>4. Buyer's counterargument</b>", sH2))
story.extend(rewrite_pair(
    "\"However, buyer may argue that the woman was set to retire anyway and her entering the "
    "market again would severely impact his business.\"",

    "\"Buyer could argue that he has a legitimate interest in protecting the winery's goodwill, "
    "given that Seller's personal reputation was closely tied to the business -- as evidenced "
    "by her picture on the wine label. Buyer paid $3 million for this goodwill, and Seller's "
    "return to the wine industry could divert customers who associate quality with Seller's "
    "name. However, this legitimate interest must be weighed against the overbroad scope of "
    "the restriction, which goes far beyond protecting the goodwill of a single winery.\""
))
story.append(Spacer(1, 10))


# ═══════════════════════════════════════════════════════════════════════
# CLOSING
# ═══════════════════════════════════════════════════════════════════════
story.append(thin_hr())

story.append(Paragraph(
    "Kate, this is a strong first submission. You identified every issue correctly, your rule "
    "statements are well-organized, and your conclusions are sound. A Band 5 means you are "
    "already above passing expectations -- the distance to Band 6 is not about learning new "
    "law. It is about <b>depth of application</b>.<br/><br/>"
    "The pattern across all three issues is the same: you state the rule accurately, apply it "
    "to the facts in general terms, and reach the right conclusion -- but the analytical step "
    "between rule and conclusion needs more development. Graders are looking for the specific "
    "reasoning that connects <i>these particular facts</i> to <i>these particular legal "
    "elements</i>. Three specific habits to build:<br/><br/>"
    "<b>1. Prove, do not assert.</b> When you identify something (ambiguous, unreasonable, "
    "partially integrated), immediately follow with the reason. \"X is ambiguous <i>because</i> "
    "the contract does not define it and reasonable minds differ\" is stronger than \"X is "
    "ambiguous.\"<br/><br/>"
    "<b>2. Use specific facts as evidence.</b> The dollar amounts, the label with Seller's "
    "picture, the distance between the wineries -- these are the facts that make your analysis "
    "specific to this problem. Every time you state a conclusion, ask yourself: <i>which fact "
    "in the prompt proves this?</i><br/><br/>"
    "<b>3. Develop both sides before concluding.</b> Your non-compete analysis would be "
    "stronger if you fully developed Buyer's legitimate interest before explaining why the "
    "scope still exceeds it. Acknowledging the strongest counterargument and then explaining "
    "why your conclusion survives it is what makes analysis persuasive.<br/><br/>"
    "Keep writing. You have the issue-spotting and organization. The analytical depth will "
    "come with repetition.",
    sBody
))
story.append(Spacer(1, 14))

# Footer
story.append(Paragraph("Bar Prep by SHEP&nbsp;&nbsp;|&nbsp;&nbsp;May 27, 2026", sFooter))


# ── Generate ───────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF generated: {OUTPUT_FILE}")
