{# =========================================================================== jobs/_row_detail.html — DEEP-DIVE TIER (tier 2 of 2) =========================================================================== Replaces the triage row via outerHTML swap when "Open full detail" is clicked (GET /jobs//detail_inline). This is an INLINE row, NOT a separate page — we deliberately keep the repo's existing inline-detail model (the redesign README floated a /jobs/ route; we did NOT introduce one, to avoid inventing a route + view the backend doesn't have). ⚑ See PORT-MANIFEST. DESIGN DECISION #1 (deep-dive half): everything the triage tier omits lives HERE and ONLY here — full JD, full AI analysis (incl. talking points + resume priority skills), sub-score breakdown (repeat OK), pipeline timeline, notes, and the full source list. Content is the SAME as the original detail row; it is restyled and re-sectioned, nothing dropped. PRESERVED contracts: • Collapse back to triage -> hx-get jobs.expand, target closest tr, outerHTML. • Status select -> jobs/_status_cell.html (unchanged hx-post). • Notes -> jobs/_notes_panel.html (unchanged save_notes). • Timeline -> `events` list passed by the detail_inline view. • Sources + direct-link badge -> jobs/_direct_link_badge.html include kept. #} {% import "components/_score_macros.html" as sm %} {% set composite = sm.composite(job.sub_scores_json) | int %} {% set scored = job.sub_scores_json is not none and job.sub_scores_json != '' %} {% set sub_scores = job.sub_scores_json | from_json if job.sub_scores_json else {} %} {% set sources_list = job.sources | from_json if job.sources else [] %} {% set urls_list = job.source_urls | from_json if job.source_urls else [] %} {# Apply target — apply_url_for() (Jinja global) enforces the precedence: strict direct_url (verified company posting) > first source_url (aggregator). #} {% set apply_url = apply_url_for(job) %} {# Score band (same 3-band split as the chip). #} {% set band = 'success' if composite >= 24 else ('warning' if composite >= 17 else 'error') %} {% set band_text = {'success':'text-emerald-400','warning':'text-amber-400','error':'text-red-400'}[band] %} {% set band_bg = {'success':'bg-emerald-400/15','warning':'bg-amber-400/15','error':'bg-red-400/15'}[band] %} {% set band_bd = {'success':'border-emerald-400/40','warning':'border-amber-400/40','error':'border-red-400/40'}[band] %} {% set band_dot = {'success':'bg-emerald-400','warning':'bg-amber-400','error':'bg-red-400'}[band] %} {% set band_label= {'success':'Strong fit','warning':'Moderate fit','error':'Weak fit'}[band] %} {# Classification pill — KEPT as a secondary signal (distinct from the score band). #} {% set cls = job.classification %} {% set cls_map = { 'apply': ('Apply', 'bg-emerald-900 text-emerald-200 border-emerald-700'), 'consider': ('Consider', 'bg-amber-900 text-amber-200 border-amber-700'), 'skip': ('Skip', 'bg-slate-800 text-slate-300 border-slate-600'), 'reject': ('Reject', 'bg-red-900 text-red-200 border-red-700') } %} {% set sub_score_dims = [ ('title_fit','Title fit'), ('location_fit','Location fit'), ('comp_fit','Compensation'), ('domain_match','Domain'), ('seniority_match','Seniority'), ('skills_match','Skills') ] %} {% set jd_key_safe = job.dedup_key | urlencode | replace('%', '') %}
{# Back to triage (was "Collapse Full Detail"). #} {# ---- Header: chip + band badge + title + meta · status + Apply ---- #}
{% if scored %}
{{ composite }}
{{ band_label }} · {{ composite }}/30 {% else %} Unscored {% endif %} {% if cls and cls in cls_map %} {{ cls_map[cls][0] }} {% endif %}

{{ job.title }}

{{ job.company }} · {{ job.location }} {% if job.salary_min or job.salary_max %} · {% if job.salary_min and job.salary_max %}${{ "{:,}".format(job.salary_min) }} – ${{ "{:,}".format(job.salary_max) }} {% elif job.salary_max %}up to ${{ "{:,}".format(job.salary_max) }} {% else %}${{ "{:,}".format(job.salary_min) }}+{% endif %} {% endif %}

{% include "jobs/_status_cell.html" %}
{% if apply_url %} Apply {% endif %}
{# ---- Body: 2-col grid (read | rail) ---- #}
{# ===== LEFT: JD · AI analysis · breakdown · notes ===== #}
{# Full Job Description — KEPT. Render the longer of jd_full / description. #} {% set _jdf = job.jd_full or '' %} {% set _desc = job.description or '' %} {% set jd_display = _desc if (_desc | length) > (_jdf | length) else _jdf %} {% if jd_display %}

Job description

{{ jd_display | format_description }}
{% endif %} {# AI fit analysis — FULL: strengths · gaps · talking points · resume skills. DESIGN DECISION: talking points + resume skills live HERE (moved out of triage). Resume skills render as indigo (accent) chips. #} {% if job.fit_analysis %} {% set analysis = job.fit_analysis | from_json %} {% if analysis.strengths or analysis.gaps or analysis.talking_points or analysis.resume_priority_skills %}

AI fit analysis

{% if analysis.strengths %}

Strengths

    {% for s in analysis.strengths %}
  • +{{ s }}
  • {% endfor %}
{% endif %} {% if analysis.gaps %}

Gaps

    {% for g in analysis.gaps %}
  • {{ g }}
  • {% endfor %}
{% endif %} {% if analysis.talking_points %}

Talking points

    {% for t in analysis.talking_points %}
  • {{ t }}
  • {% endfor %}
{% endif %} {% if analysis.resume_priority_skills %}

Resume priority skills

{% for skill in analysis.resume_priority_skills %} {{ skill }} {% endfor %}
{% endif %}
{% endif %} {% endif %} {# Fit breakdown — repeat of the triage component, in a card. #} {% if sub_scores %}

Fit breakdown

{% for key, label in sub_score_dims %} {% set v = sub_scores.get(key, 0) | int %} {% set fill = 'bg-emerald-500' if v >= 4 else ('bg-amber-500' if v == 3 else 'bg-red-500') %}
{{ label }} {{ v }}
{% endfor %}
{% endif %} {# Notes — KEPT (shared partial, unchanged contract). #}

Notes

{% include "jobs/_notes_panel.html" %}
{# ===== RIGHT RAIL: timeline · sources · dates ===== #}