"""The eight public tabs: what each one is computed from, and how it fails.

Traced from the live code, not from the UI — the "fails as" column is the
important one, because almost every failure mode here is SILENT. A missing
field usually removes a tile or produces a confident wrong number; it almost
never shows an error.
"""

# (tab, audience, what the buyer sees, [powered by], [check], (failure headline, failure detail))
TAB_SPECS = [
    (
        "Overview", "Everyone",
        "The first impression: hero image, key facts, description, facilities and the map.",
        ["Hero / gallery media", "tenure · property type · developer",
         "Bedroom + size range (derived from layouts)", "Handover per block, or completion year",
         "Total units · management fee · parking", "latitude / longitude", "Description or AI summary"],
        [("Hero image present.", "No media at all shows “No images yet” on the very first screen."),
         ("The pin is on the SITE,", "not the sales gallery. Everything spatial hangs off it."),
         ("Facts you cannot verify, leave empty.", "Each empty fact is dropped silently — a half-filled grid looks deliberate.")],
        ("An under-filled Overview looks finished",
         "Empty facts are removed rather than marked missing, so a project with three facts "
         "and one with nine both look complete. Nothing on screen says anything is absent."),
    ),
    (
        "Units · Price", "Members",
        "Every unit type with price, PSF, entry cost, instalment, estimated rent and gross yield.",
        ["Layout name · sqft · bedrooms · bathrooms · car parks",
         "price · asking PSF", "Floor-plan image per layout",
         "Live rental estimate (needs price + sqft + coordinates)", "sale_process for the payment plan"],
        [("Every layout priced,", "or the calculator does not render at all."),
         ("Floor-plan image attached to the LAYOUT,", "not dropped in the gallery."),
         ("Layout names as the developer sells them.", "“Type A”, not the portal's “3B”.")],
        ("Every unit is badged “Available” — including sold-out ones",
         "The page reads a “sold” flag the catalogue never supplies, so the badge is always "
         "“Available”. Known defect, logged. Do not rely on it, and warn advisors."),
    ),
    (
        "Investment Analysis", "Members",
        "Market value against comparables, rental outlook, Airbnb potential, and a summary verdict.",
        ["Exactly five inputs: latitude, longitude, layout price, layout sqft, layout bedrooms",
         "Comparable transactions (EdgeProp)", "Demand intelligence + location outlook"],
        [("Price and sqft on the layout.", "Missing either and the whole tab is an empty state."),
         ("Bedrooms exact.", "It selects the comparable set — see the next two slides."),
         ("Read the verdict yourself", "before submitting. If it says “Insufficient data”, say so in your note.")],
        ("A thin comparable set reads as a bad investment",
         "With too few comparables the score clamps to 0 and several tiles print 0 rather "
         "than hiding — indistinguishable from a genuinely poor project."),
    ),
    (
        "Financial Projection", "Members",
        "Loan amortisation, equity build-up, cashflow, and how fast rent recycling clears the loan.",
        ["Layout price", "Monthly rent, in strict order: stored rental_price → live estimate → fallback",
         "Fixed assumptions: 90% LTV, 4.2%, 35 years, 3.5% appreciation"],
        [("Sanity-check the monthly rent", "against what that unit really lets for."),
         ("A price of 0", "flat-lines the entire chart instead of erroring."),
         ("If rent looks like exactly 0.35% of price,", "it is the fallback, not a real estimate.")],
        ("The silent 0.35% fallback",
         "With no stored rent and no live estimate, EVERY projection runs on price × 0.35% per "
         "month — RM 3,500 on a RM 1m unit — with no caveat on screen. Payoff month, cashflow "
         "and “years early” all inherit it."),
    ),
    (
        "New Supply", "Members",
        "Competing launches within 3 km, with their prices, sizes, completion and unit mix.",
        ["Subject coordinates", "Neighbours must be PUBLISHED",
         "Neighbours must be tagged market_segment = new_project", "Neighbour hero media, prices, completion"],
        [("Coordinates right —", "this draws a 3 km circle around them."),
         ("market_segments includes new_project,", "or this project never appears in anyone else's New Supply."),
         ("Expect it to look empty early on.", "Nothing is published yet.")],
        ("A dense corridor can look empty",
         "Only PUBLISHED neighbours are counted. Today that is zero, so this tab is empty for "
         "everyone. It fills in as we publish — which is why we publish in geographic clusters."),
    ),
    (
        "Amenities", "Members",
        "What is around the project — schools, transport, retail — plus demand signals and an AI outlook.",
        ["Coordinates", "At least one layout with price AND sqft",
         "Curated catalysts nearby", "An EdgeProp source within 2 km for the AI prompt"],
        [("It needs one analysable layout.", "No priced layout means no amenity intelligence at all."),
         ("“No rail stations within 1km”", "can mean genuinely none, or nothing mapped. Check the map."),
         ("Read the AI outlook", "before submitting; it is written to a buyer, not to us.")],
        ("Neighbours on one corner share a narrative",
         "The AI outlook is cached for 7 days against the coordinate rounded to ~11 m. Two "
         "projects on the same junction will show the same write-up."),
    ),
    (
        "Developer Record", "Everyone",
        "The developer's other projects — a track record a buyer uses to judge credibility.",
        ["The developer PIVOT row, not the scraped text label",
         "Published siblings: name, area, price, completion, media", "Unpublished siblings: name and area only"],
        [("The developer name is standardised.", "The tab groups on the linked developer, not the typed string."),
         ("One brand, one spelling.", "“Sdn Bhd” vs “Sdn. Bhd.” splits a track record in two."),
         ("Check the count looks right", "for a developer you know.")],
        ("A 92-project developer can show an empty track record",
         "If the record is linked to a mis-standardised developer, the query matches nothing "
         "and the tab reads “no other projects recorded” — the worst possible impression."),
    ),
    (
        "Contact Advisor", "Everyone",
        "How a buyer reaches us — advisor cards and a LINE call-to-action.",
        ["Nothing from the catalogue", "A configured LINE URL"],
        [("Nothing to review here.", "This tab cannot be wrong for a badly filled project."),
         ("The advisors shown are placeholders", "— not the real roster."),
         ("Flag it", "if a client asks about the names on it.")],
        ("Placeholder people are on a public page",
         "The advisor cards are hard-coded samples, and the real location-aware agent roster "
         "is built but not connected to this tab. Product decision needed before launch."),
    ),
]

# Compact one-line-per-tab matrix for the overview slide.
TAB_MATRIX = [
    ("Overview",             "Media · facts · coordinates",        "Facts vanish silently"),
    ("Units · Price",        "Layout price · sqft · images",       "No calculator at all"),
    ("Investment Analysis",  "lat/lng + price + sqft + bedrooms",  "Thin data scores as 0"),
    ("Financial Projection", "Price + monthly rent",               "Silent 0.35% fallback"),
    ("New Supply",           "Coordinates + PUBLISHED neighbours", "Dense area looks empty"),
    ("Amenities",            "Coordinates + one priced layout",    "No insight at all"),
    ("Developer Record",     "The developer pivot link",           "Empty track record"),
    ("Contact Advisor",      "Nothing from the catalogue",         "Placeholder advisors"),
]
