#!/usr/bin/env python3
# ---------------------------------------------------------------------------
# sidebar-inner.html — option sheet for the inner service page's sidebar.
#
# Adi asked two things at once, and the second one answers the first:
#   "buatkan opsi tampilan untuk sidebar ... menurutmu apakah tetap perlu ada
#    form? karena di bagian hero sudah ada form dan ... sudah ada ctatab"
#
# So the options span the whole range — no form, the smallest possible form,
# and the form exactly as it is — and the sheet carries the count that makes
# the question answerable rather than a matter of taste.
#
# Every option is shown IN CONTEXT: the real 1280 container, the real 832px
# article column beside it at real type size, the sidebar at its real 384px.
# A sidebar judged out of context tells you nothing about a sidebar.
#
# The sheet's own chrome (page-head, boxes, option labels, stage) is LIFTED
# from the hero option sheet's generator so the two sheets read as one series.
# ---------------------------------------------------------------------------
import io, sys

OUT   = "/srv/apps/leaguelaw/wp-content/prototype/sidebar-inner.html"
R1GEN = "/srv/apps/leaguelaw/prototyping/gen_heroinner.py"
TEL   = "tel:+12508880002"

INJURY = [
    ("Car Accident Claims",        True),  ("Motorcycle Accident Claims", False),
    ("Cyclist Accident Claims",    False), ("Passenger Injury Claims",    False),
    ("Pedestrian Injury Claims",   False), ("Hit and Run Injury Claims",  False),
    ("Slip and Fall",              False), ("Premises Liability Claims",  False),
    ("School Accident Claims",     False), ("Product Liability",          False),
    ("Dog Attack",                 False), ("Boat Accidents",             False),
    ("Assault &amp; Battery",      False),
]

BENCH = [
    ("Darren Williams",  "/wp-content/uploads/DARRENorangebowtie.jpg"),
    ("Joji Kawaguchi",   "/wp-content/uploads/Joji-20220126-028-Hi-Res-scaled-e1709583455555-761x1024.jpg"),
    ("Matthew Melnyk",   "/wp-content/uploads/matthew-melnyk-sm.jpg"),
    ("Reid Warren",      "/wp-content/uploads/Reid-20240403-030-Hi-Res-scaled-e1715983076700-761x1024.jpg"),
    ("Georgia Lockhart", "/wp-content/uploads/Georgia-20260119-069-Hi-Res-V2-BW-scaled-e1773087958989-761x1024.jpg"),
]

# the article's real opening, so the column beside each option is the real one
PROSE = """<p>Being involved in a car accident can be scary and often those injured in motor vehicle
accidents are unaware of how to ensure the best recovery possible.&nbsp; Those injured in car accidents
in British Columbia, whether as a driver, passenger, pedestrian or cyclist are entitled to pursue
compensation for their injuries.&nbsp; Car accident victims who are injured may claim for pain and
suffering, out-of-pocket expenses, loss of housekeeping capacity, loss of income and diminished earning
capacity, and for cost of future care.</p>
<p>Typically those involved in car accidents in British Columbia may make two types of claims &ndash; a
Tort claim and a Part 7 claim.</p>
<p>A Tort claim is available for those who are injured and who can prove that another person was, at
least partly, at fault or responsible for causing the accident.&nbsp; The person must also establish
that they suffered damages, and that those damages were the result of the accident.</p>"""


def lift_chrome():
    """The sheet chrome from the hero option sheet — same series, same look."""
    src = io.open(R1GEN, encoding="utf-8").read()
    i = src.index('CSS = r"""') + len('CSS = r"""')
    j = src.index("  /* ---------- header stand-in", i)
    css = src[i:j]
    assert ".page-head h1" in css and ".opt-label .tag" in css and ".stage {" in css, \
        "the sheet chrome did not survive the lift"
    return css


SIDEBAR_CSS = r"""
  /* =====================================================================
     THE PAGE, AS CONTEXT
     832 article + 64 gutter + 384 sidebar = 1280. The article is real copy at
     real size, dimmed — the point of comparison is the 384px column, but a
     384px column only means something next to the 832 it has to hold its own
     against.
     ===================================================================== */
  .pg { background:#fff; padding:40px 0 46px; }
  .pg .cols { display:flex; }
  .pg .col { width:832px; flex:none; }
  .pg .rail { width:384px; margin-left:64px; flex:none; }
  .pg .prose { font-size:16.5px; line-height:1.9; color:#4A453F; opacity:.42; }
  .pg .prose p { margin-bottom:22px; }
  .pg .h2 { font-family:Raleway,sans-serif; font-weight:400; font-size:22px; line-height:1.5;
            color:var(--brown); margin-bottom:16px; opacity:.42; }

  /* ---------- the sidebar vocabulary, home_v1's ---------- */
  .fh { font-family:Raleway,sans-serif; font-weight:700; font-size:11.5px; letter-spacing:.14em;
        text-transform:uppercase; color:#8D867E; padding-bottom:11px; margin-bottom:4px;
        border-bottom:1px solid var(--line); }
  .rlist a { display:block; position:relative; font-size:13.5px; font-weight:600; color:#4A453F;
             padding:11px 2px 11px 19px; border-bottom:1px solid #EEECE7; transition:color .14s ease; }
  .rlist a:before { content:""; position:absolute; left:0; top:50%; width:9px; height:10.392px;
                    background:var(--orange); clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
                    transform:translateY(-50%) translateX(-7px) scale(0); transition:transform .14s ease; }
  .rlist a:hover { color:var(--orange); }
  .rlist a:hover:before, .rlist a.cur:before { transform:translateY(-50%) translateX(0) scale(1); }
  .rlist a.cur { color:var(--orange); }

  .rcard { background:var(--paper); border:1px solid var(--line); border-top:4px solid var(--orange);
           padding:24px 26px 26px; }
  .rcard .rh { font-family:Raleway,sans-serif; font-weight:800; font-size:18px; color:var(--brown);
               letter-spacing:.02em; margin-bottom:8px; }
  .rcard p { font-size:13.5px; line-height:1.75; color:var(--muted); margin-bottom:16px; }
  .rcard .rphone { display:block; font-family:Raleway,sans-serif; font-weight:800; font-size:26px;
                   line-height:32px; color:var(--orange); }
  .rcard .rphone .cn { display:block; color:var(--teal); font-weight:600; font-size:10.5px;
                       line-height:14px; letter-spacing:.16em; text-transform:uppercase; }
  .rcard .rsafe { display:block; font-size:11.5px; line-height:16px; color:#9A948B; margin-top:12px; }

  .swarmbtn { display:inline-block; position:relative; background:var(--brown); color:#fff;
              font-family:Raleway,sans-serif; font-weight:700; font-size:13px; line-height:17px;
              letter-spacing:.06em; text-transform:uppercase; padding:12px 44px 12px 20px;
              cursor:pointer; border:0; }
  .swarmbtn.wide { display:block; width:100%; text-align:left; }
  .swarmbtn i { position:absolute; display:block; width:9px; height:10.392px; background:var(--orange);
                clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%); transition:all .25s ease; }
  .swarmbtn .w1 { right:12px; top:6px;  transform:rotate(14deg); }
  .swarmbtn .w2 { right:26px; top:16px; transform:rotate(-20deg); }
  .swarmbtn .w3 { right:8px;  top:24px; transform:rotate(32deg); }
  .swarmbtn:hover .w1 { right:16px;   top:5px;    transform:rotate(0); }
  .swarmbtn:hover .w2 { right:21.5px; top:14.6px; transform:rotate(0); }
  .swarmbtn:hover .w3 { right:10.5px; top:14.6px; transform:rotate(0); }

  /* ---------- S2's bench card ---------- */
  .who { margin-top:30px; }
  .who .faces { display:flex; gap:6px; margin:14px 0 14px; }
  .who .faces span { flex:1; position:relative; overflow:hidden; }
  .who .faces img { width:100%; height:74px; object-fit:cover; filter:grayscale(1); display:block; }
  .who .nm { font-size:12px; line-height:1.7; color:var(--muted); }
  .who .nm b { color:var(--brown); font-weight:600; }
  .who .more { display:inline-block; margin-top:12px; font-family:Raleway,sans-serif; font-weight:700;
               font-size:11.5px; line-height:16px; letter-spacing:.1em; text-transform:uppercase;
               color:var(--brown); box-shadow:inset 0 -2px 0 var(--orange); padding-bottom:2px; }

  /* ---------- S3's one-field callback ---------- */
  .oneline { margin-top:30px; background:var(--brown); color:#fff; padding:22px 24px 24px; }
  .oneline .rh { font-family:Raleway,sans-serif; font-weight:800; font-size:17px; line-height:22px;
                 margin-bottom:5px; }
  .oneline p { font-size:12.5px; line-height:18px; color:#C9C3BB; margin-bottom:14px; }
  .oneline .row { display:flex; }
  .oneline input { flex:1; min-width:0; border:0; font-family:"Open Sans",sans-serif; font-size:13px;
                   padding:12px 13px; color:#444; outline:none; background:#fff; }
  .oneline input::placeholder { color:#9A948B; }
  .oneline button { flex:none; border:0; background:var(--orange); color:#fff; cursor:pointer;
                    font-family:Raleway,sans-serif; font-weight:700; font-size:12px; line-height:16px;
                    letter-spacing:.06em; text-transform:uppercase; padding:12px 16px; }

  /* ---------- S4's full form — the live one, in the new vocabulary ------- */
  .bigform { margin-top:30px; border:1px solid var(--line); }
  .bigform .fhead { background:var(--orange); color:#fff; padding:18px 22px 16px; }
  .bigform .fhead img { width:180px; height:auto; display:block; margin-bottom:10px; }
  .bigform .fhead p { font-family:Raleway,sans-serif; font-weight:600; font-size:14px; line-height:19px;
                      letter-spacing:.04em; }
  .bigform .fbody { padding:20px 22px 22px; background:#fff; }
  .bigform .legend { font-size:11px; line-height:15px; color:#9A948B; margin-bottom:12px; }
  .bigform .gf { display:flex; margin-bottom:12px; }
  .bigform .gf .icon { width:38px; flex:none; background:var(--orange); color:#fff; display:flex;
                       align-items:flex-start; justify-content:center; padding-top:12px; font-size:14px; }
  .bigform .gf input, .bigform .gf textarea { flex:1; min-width:0; border:1px solid var(--line);
        border-left:0; font-family:"Open Sans",sans-serif; font-size:13px; padding:11px 12px;
        color:#444; outline:none; }
  .bigform .gf textarea { height:110px; resize:vertical; }
  .bigform .safe { display:block; font-size:11.5px; line-height:16px; color:#9A948B; margin-bottom:12px; }

  /* ---------- S5's sticky rail ---------- */
  .stickynote { margin-top:14px; font-size:11.5px; line-height:17px; color:#9A948B;
                border-left:2px solid var(--line); padding-left:11px; }

  /* the tab, drawn on the stage so its role in the argument is visible */
  .tabghost { position:absolute; right:0; top:50%; transform:translateY(-50%); background:var(--orange);
              color:#fff; font-family:Raleway,sans-serif; font-weight:700; font-size:13px;
              letter-spacing:.1em; writing-mode:vertical-rl; padding:20px 14px; z-index:5;
              box-shadow:-4px 4px 16px rgba(0,0,0,.22); }
  .stage { position:relative; }
"""


def nav(cur=True):
    rows = "".join('<a href="#"%s>%s</a>' % (' class="cur"' if c else '', n) for n, c in INJURY)
    return '<div class="fh">Injury claims</div><div class="rlist">%s</div>' % rows


def card(head, body, btn=True):
    b = ('<button class="swarmbtn wide" type="button">Book Consultation'
         '<i class="w1"></i><i class="w2"></i><i class="w3"></i></button>') if btn else ""
    return ('<div class="rcard"><div class="rh">%s</div>%s'
            '<a class="rphone" href="%s"><span class="cn">Call now</span>250-888-0002</a>'
            '<span class="rsafe">&#128274; Your information is kept safe.</span>%s</div>'
            % (head, body, TEL, b))


def S1():
    return ('<div class="rail">' + nav() +
            '<div style="margin-top:30px">' +
            card("We&rsquo;ve got your back",
                 "<p>Free consultations for those injured in car accidents. Our email is monitored "
                 "seven days a week.</p>") +
            '</div></div>')


def S2():
    faces = "".join('<span><img src="%s" alt=""></span>' % src for _, src in BENCH)
    return ('<div class="rail">' + nav() +
            '<div class="who"><div class="fh">Who handles this claim</div>'
              '<div class="faces">' + faces + '</div>'
              '<p class="nm">Five lawyers take injury claims: <b>Darren Williams</b>, '
              '<b>Joji Kawaguchi</b>, <b>Matthew Melnyk</b>, <b>Reid Warren</b> and '
              '<b>Georgia Lockhart</b>.</p>'
              '<a class="more" href="/lawyers/">Meet the injury team</a></div>'
            '<div style="margin-top:30px">' +
            card("We&rsquo;ve got your back", "", btn=False) +
            '</div></div>')


def S3():
    return ('<div class="rail">' + nav() +
            '<div class="oneline"><div class="rh">Rather be called?</div>'
              '<p>Leave a number. One field, nothing else &mdash; a lawyer calls you back.</p>'
              '<div class="row"><input placeholder="Your number">'
              '<button type="button">Call me</button></div></div></div>')


def S4():
    return ('<div class="rail">' + nav() +
            '<div class="bigform">'
              '<div class="fhead"><img src="/wp-content/uploads/logo-white.png" alt="League and Williams Lawyers">'
                '<p>Contact us for a Consultation</p></div>'
              '<div class="fbody"><div class="legend">&ldquo;<em>*</em>&rdquo; indicates required fields</div>'
                '<div class="gf"><span class="icon"><i class="fa fa-user"></i></span><input placeholder="NAME"></div>'
                '<div class="gf"><span class="icon"><i class="fa fa-envelope"></i></span><input placeholder="EMAIL"></div>'
                '<div class="gf"><span class="icon"><i class="fa fa-phone"></i></span><input placeholder="PHONE"></div>'
                '<div class="gf"><span class="icon"><i class="fa fa-comments"></i></span><textarea placeholder="MESSAGE"></textarea></div>'
                '<span class="safe">&#128274; Your information is kept safe.</span>'
                '<button class="swarmbtn wide" type="button">Send Message'
                  '<i class="w1"></i><i class="w2"></i><i class="w3"></i></button>'
              '</div></div></div>')


def S5():
    return ('<div class="rail"><div style="position:sticky;top:20px">' + nav() +
            '<p class="stickynote">Sticky: the list stays with the reader for the whole '
            '1,534px of article. Contact is the tab on the right edge.</p>'
            '</div></div>')


OPTIONS = [
    ("S1", "Navigation, then one card", "no form",
     "The thirteen sibling claims, then a single card carrying the phone and one Book Consultation "
     "button &mdash; which opens the same modal the tab opens. No fields in the sidebar at all.",
     "This is the recommendation. The card keeps a <b>visible</b> call to action in the column (the tab "
     "is on the screen edge and easy to read past) without asking for four fields the page already asks "
     "for twice elsewhere.", S1),

    ("S2", "Navigation, then who takes the case", "no form",
     "The claims list, then the five lawyers who actually handle injury work, as faces, with a link to "
     "the team &mdash; and a small card with the phone under it.",
     "The only option that puts something in the sidebar that <b>exists nowhere else on the page</b>. "
     "&ldquo;Who would I be dealing with&rdquo; is a real question on a claims page and nothing on this "
     "page answers it. The faces are the live site&rsquo;s own headshots, monochrome so they sit behind "
     "the type rather than in front of it.", S2),

    ("S3", "Navigation, then one field", "1 field",
     "The claims list, then a brown block asking for a phone number and nothing else &mdash; the "
     "smallest ask on the page.",
     "If a form has to stay, this is the one that does not duplicate anything: the footer already asks "
     "for name, email, phone and message. Asking for <b>one</b> field is a different offer, not the same "
     "offer twice &mdash; and it matches the hero&rsquo;s own Call&nbsp;Me&nbsp;Back promise.", S3),

    ("S4", "Navigation, then the form as it is", "4 fields",
     "The status quo: the claims list, then the four-field form the live sidebar carries, redrawn in the "
     "new vocabulary so the comparison is about the form and not about the styling.",
     "Kept in the sheet so the cost is visible rather than argued. This form is <b>character-for-character "
     "the footer&rsquo;s form</b> &mdash; same four fields, same legend, same &ldquo;Your information is "
     "kept safe&rdquo;, same button. Two identical components on one page.", S4),

    ("S5", "Navigation only, sticky", "no form",
     "Nothing but the claims list &mdash; but it sticks, so it stays beside the reader for the whole "
     "article instead of scrolling away after the first screen.",
     "The article column is <b>1,534px</b>; the claims list is about 500. In every other option the "
     "bottom two thirds of the sidebar is empty space that scrolls past. This is the only option that "
     "uses the column&rsquo;s real length &mdash; and the only one where the sibling claims are reachable "
     "from anywhere in the article.", S5),
]


HEAD = """<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<title>League Law &mdash; inner service sidebar options</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;500;600;700;800&amp;family=Open+Sans:wght@400;600;700&amp;display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>__CSS__</style>
</head>
<body>

<div class="page-head">
  <h1>Inner service sidebar &mdash; options</h1>
  <p>Adi asked for sidebar options and, in the same breath, the question that decides them:
  <i>does the sidebar still need a form, now that the hero has one and the consultation tab is on
  every screen?</i> Below is the count that makes that answerable, then five options spanning
  <b>no form</b> to <b>the form exactly as it is</b>.</p>

  <div class="box warn"><b>The answer is no &mdash; and it is a count, not an opinion.</b>
  Here is every way the page as it stands asks to be contacted:
  <table>
    <tr><th>where</th><th>what it asks for</th></tr>
    <tr><td>hero contact panel</td><td>phone at display size + <b>2 fields</b> + Call Me Back</td></tr>
    <tr><td>article, opening line</td><td>&ldquo;Contact us today for a consultation&rdquo; + the number</td></tr>
    <tr><td>article, closing line</td><td>&ldquo;may be contacted by phone &hellip; or via email&rdquo;</td></tr>
    <tr><td><b>sidebar form</b></td><td><b>4 fields</b> + Send Message</td></tr>
    <tr><td>contact strip, full width</td><td>phone + email</td></tr>
    <tr><td>Get in touch</td><td>&ldquo;Please contact us for more information&rdquo;</td></tr>
    <tr><td>footer form</td><td><b>4 fields</b> + Send Message</td></tr>
    <tr><td>footer bottom</td><td>phone, fax, email, address</td></tr>
    <tr><td><b>consultation tab</b> (new)</td><td>always on screen &rarr; modal with <b>4 fields</b></td></tr>
  </table>
  Nine places. <b>14 input fields. The phone number 11 times.</b> Four submit buttons.
  <ul>
    <li><b>The sidebar form is not merely one of several &mdash; it is a literal duplicate.</b> It has the
    same four fields, the same &ldquo;<em>*</em> indicates required fields&rdquo; legend, the same
    &ldquo;Your information is kept safe&rdquo; and the same SEND MESSAGE button as the footer form. The
    page ships the same component twice.</li>
    <li><b>The tab does the sidebar form&rsquo;s job better.</b> A sidebar form is on screen for part of
    the scroll; the tab is on screen for all of it, and opens the same four fields.</li>
    <li><b>Three forms is three different definitions of &ldquo;enough&rdquo;</b> &mdash; the hero asks
    two fields, the sidebar and footer ask four. That is a decision pushed onto the reader.</li>
    <li><b>The sidebar has a job nothing else can do:</b> it is the only route to the other
    <b>twelve</b> injury claims. Today the form pushes that list up and competes with it.</li>
  </ul>
  <b>Recommendation: S1</b> &mdash; navigation, then one card with the phone and a Book Consultation
  button that opens the tab&rsquo;s modal. If a form has to stay, <b>S3</b>: one field, which is a
  different offer rather than the same offer a third time.
  </div>

  <div class="box"><b>How the column is spent.</b> The article column on this page is
  <b>1,534px</b> tall. The claims list is about 500 of that, so what an option does with the other
  1,000 is the real question.
  <table>
    <tr><th>option</th><th>sidebar height</th><th>column left empty</th><th>fields</th></tr>
    <tr><td>S5 &mdash; navigation only, sticky</td><td>__H5__</td><td>follows the reader instead</td><td>0</td></tr>
    <tr><td>S1 &mdash; navigation + one card</td><td>__H1__</td><td>__E1__</td><td>0</td></tr>
    <tr><td>S3 &mdash; navigation + one field</td><td>__H3__</td><td>__E3__</td><td>1</td></tr>
    <tr><td>S2 &mdash; navigation + who takes the case</td><td>__H2__</td><td>__E2__</td><td>0</td></tr>
    <tr><td>S4 &mdash; navigation + the form as it is</td><td>__H4__</td><td>__E4__</td><td>4</td></tr>
  </table>
  </div>

  <div class="box ask"><b>Two things this sheet does not decide:</b>
    <ul>
      <li><b>The article still opens with its own contact line</b> &mdash; teal hexagon, then
      &ldquo;Contact us today for a consultation &middot; (250)&nbsp;888-0002&rdquo; &mdash; about 200px
      under a hero that has just given the same number at 54px. That is the article&rsquo;s part, not the
      sidebar&rsquo;s, and it is still the replica.</li>
      <li><b>Whether the footer form stays either.</b> If the sidebar form goes because the tab does its
      job, the same argument reaches the footer form. Worth deciding once, for both.</li>
    </ul>
  </div>

  <div class="box"><b>Reading the frames:</b> each stage is the real page geometry &mdash;
  <code>832 + 64 + 384 = 1280</code> &mdash; with the article column in real copy at real size, dimmed,
  because a 384px column only means something next to the 832 it sits beside. The orange tab is drawn on
  the right edge of every frame: it is on the page now, and it is half the argument.</div>
</div>

<div class="roundhead">Sidebar &mdash; S1 &hellip; S5</div>
"""


def build(heights):
    out = [HEAD.replace("__CSS__", lift_chrome() + SIDEBAR_CSS)]
    for k, v in heights.items():
        out[0] = out[0].replace(k, v)
    for tag, name, hint, what, note, fn in OPTIONS:
        out.append(
            '\n<div class="opt">\n'
            '  <div class="opt-label"><span class="tag">%s</span><span class="name">%s</span>'
            '<span class="h">%s</span><span class="what">%s</span></div>\n'
            '  <div class="stage"><span class="tabghost">WE&rsquo;VE GOT YOUR BACK</span>'
            '<div class="pg"><div class="wrap"><div class="cols">'
            '<div class="col"><div class="h2">League &amp; Williams are Experienced Car Accident '
            'Injury Claims Lawyers</div><div class="prose">%s</div></div>'
            '%s</div></div></div></div>\n'
            '  <p class="opt-note">%s</p>\n'
            '</div>\n' % (tag, name, hint, what, PROSE, fn(), note))
    out.append("\n</body>\n</html>\n")
    return "".join(out)


if __name__ == "__main__":
    # placeholders filled in after the browser measures them
    h = {"__H%d__" % i: "&mdash;" for i in range(1, 6)}
    h.update({"__E%d__" % i: "&mdash;" for i in range(1, 6)})
    import json, os
    if os.path.exists("sidebar_heights.json"):
        h.update(json.load(open("sidebar_heights.json")))
    html = build(h)
    dest = sys.argv[1] if len(sys.argv) > 1 else OUT
    io.open(dest, "w", encoding="utf-8").write(html)
    print("wrote %s (%d bytes)" % (dest, len(html)))
