{# Session Receipt 800x500 (v0.2.21 risograph-canonical). Thin render: zero math, zero hex.
   Geometry from compose/treemap.py + bar_chart.py; colors from var(--dna-*).
   Same structure for ALL skins; palette swaps via genome JSON.
   Specimen: tier2/telemetry/telemetry-redesign/receipt-genome-risograph.svg #}
{% extends "document.svg.j2" %}

{% block defs %}
{% include "partials/provider-glyphs.svg.j2" %}
{# Card-shape clipPath — defines the receipt's rounded outline so any element
   that paints to the SVG edges (substrate, top accent strip) inherits the
   rounding instead of poking out as square corners around the rounded card.
   Matches the claude-code v9 specimen's #card-shape pattern. The card_border
   outer stroke uses the same rx=5.5 so all three edges align. #}
<clipPath id="receipt-card-shape">
  <rect width="{{ width }}" height="{{ height }}" rx="{{ receipt_geom.card_rx }}" ry="{{ receipt_geom.card_rx }}"/>
</clipPath>
{# Atmosphere gradient (v0.2.23, codex skin). Diagonal linear gradient
   painted behind the substrate when the genome declares ``atmosphere_stops``.
   Empty list = no atmosphere = current behavior preserved across other skins. #}
{% if atmosphere_stops %}
<linearGradient id="receipt-atmosphere" x1="0" y1="0" x2="1" y2="1">
{% for stop in atmosphere_stops %}
  <stop offset="{{ stop.offset }}" stop-color="{{ stop.color }}"/>
{% endfor %}
</linearGradient>
{% endif %}
{# Radial bloom overlays — additive lightness over the atmosphere
   (v9 codex bloom-cool + bloom-violet). #}
{% for bloom in atmosphere_blooms %}
<radialGradient id="receipt-{{ bloom.id }}" cx="{{ bloom.cx }}" cy="{{ bloom.cy }}" r="{{ bloom.r }}">
{% for stop in bloom.stops %}
  <stop offset="{{ stop.offset }}" stop-color="{{ stop.color }}" stop-opacity="{{ stop.opacity }}"/>
{% endfor %}
</radialGradient>
{% endfor %}
{# Card top highlight — surface-light→transparent gradient suggesting a glass
   edge. Sources --dna-card-top-highlight (the genome's card_top_highlight_color),
   NOT --dna-ink-primary: ink is text tone (near-black on light skins), so
   routing the edge through ink turned codex's white glass edge into a dark
   wash. The highlight is a surface-light role with its own token. #}
{% if card_top_highlight %}
<linearGradient id="receipt-card-top-highlight" x1="0" y1="0" x2="0" y2="1">
  <stop offset="0%" stop-color="var(--dna-card-top-highlight)" stop-opacity="0.35"/>
  <stop offset="100%" stop-color="var(--dna-card-top-highlight)" stop-opacity="0"/>
</linearGradient>
{% endif %}
{% endblock %}

{% block content %}
{# Atmosphere backdrop (v0.2.23): full-canvas gradient painted FIRST, then the
   substrate inset by ``card_inset`` so the atmosphere is visible as a colored
   ring around the card. Both fields default to empty/zero — other skins keep
   their current full-canvas substrate behavior unchanged. #}
{% if atmosphere_stops %}
<rect width="{{ width }}" height="{{ height }}" rx="{{ receipt_geom.card_rx }}" ry="{{ receipt_geom.card_rx }}" fill="url(#receipt-atmosphere)"/>
{% for bloom in atmosphere_blooms %}
<rect width="{{ width }}" height="{{ height }}" rx="{{ receipt_geom.card_rx }}" ry="{{ receipt_geom.card_rx }}" fill="url(#receipt-{{ bloom.id }})"/>
{% endfor %}
<rect x="{{ card_inset }}" y="{{ card_inset }}" width="{{ card_inner_w }}" height="{{ card_inner_h }}" rx="{{ receipt_geom.card_inner_rx }}" ry="{{ receipt_geom.card_inner_rx }}" fill="var(--dna-surface)"/>
{% if card_top_highlight %}
<rect x="{{ card_inset }}" y="{{ card_inset }}" width="{{ card_inner_w }}" height="{{ receipt_geom.card_top_highlight_h }}" rx="{{ receipt_geom.card_inner_rx }}" ry="{{ receipt_geom.card_inner_rx }}" fill="url(#receipt-card-top-highlight)" pointer-events="none"/>
{% endif %}
{% else %}
<rect width="{{ width }}" height="{{ height }}" rx="{{ receipt_geom.card_rx }}" ry="{{ receipt_geom.card_rx }}" fill="var(--dna-surface)"/>
{% endif %}

{# ═══ HERO ZONE (translate 24, 18 — risograph-canonical) ═══ #}
{% if has_glyph %}
<use href="#{{ glyph_id }}" x="{{ left_margin }}" y="{{ receipt_geom.glyph_y }}" width="{{ receipt_geom.glyph_size }}" height="{{ receipt_geom.glyph_size }}"/>
{% endif %}
<text x="{{ provider_label_x }}" y="{{ receipt_geom.provider_y }}" class="s ink1" font-size="14" font-weight="700">{{ provider_label }}</text>
{% if model_label %}
<text x="{{ model_label_x }}" y="{{ receipt_geom.model_y }}" class="m ink2" font-size="11" letter-spacing="0.04em">· {{ model_label }}</text>
{% endif %}
{# Phase pill at top-right — token-driven, branch-free.
   Voltage (titanium spec): layered structure — dark outer base + thin frame
   stroke + champagne phosphor inner + white/orange hairlines + dark text.
   Claude-code: single bright pill — outer/stroke/rules transparent, solid
   terra-coral inner + white text. The v9 specimen used rx=11 (full pill);
   the canonical v0.2.21 silhouette is square (rx=0) across all skins for
   cross-skin coherence (locked by test_pill_rx_normalized_to_square_across_skins).
   Cream (risograph spec): layered like voltage but with cream-shifted base,
   dark-brown frame, fluoro-orange phosphor inner, light cream text + hairlines.
   "transparent" tokens render the rect but paint no pixels — same template,
   three different identities, zero conditionals. #}
<g transform="translate({{ pill_x }}, {{ receipt_geom.pill_group_y }})" data-hw-zone="phase-pill">
  <rect width="{{ pill_w }}" height="{{ receipt_geom.pill_h }}" rx="{{ pill_rx }}" fill="var(--dna-pill-outer-bg)"/>
  <rect width="{{ pill_w }}" height="{{ receipt_geom.pill_h }}" rx="{{ pill_rx }}" fill="none" stroke="var(--dna-pill-outer-stroke)" stroke-width="0.75"/>
  <rect class="anchor-live" x="{{ receipt_geom.pill_inner_x }}" y="{{ receipt_geom.pill_inner_y }}" width="{{ pill_inner_w }}" height="{{ receipt_geom.pill_inner_h }}" rx="{{ pill_rx }}" fill="var(--dna-pill-inner-bg)"/>
  <rect x="{{ receipt_geom.pill_inner_x }}" y="{{ receipt_geom.pill_rule_top_y }}" width="{{ pill_inner_w }}" height="{{ receipt_geom.pill_rule_h }}" fill="var(--dna-pill-rule-top)"/>
  <rect x="{{ receipt_geom.pill_inner_x }}" y="{{ receipt_geom.pill_rule_bottom_y }}" width="{{ pill_inner_w }}" height="{{ receipt_geom.pill_rule_h }}" fill="var(--dna-pill-rule-bottom)"/>
  <text class="m" x="{{ pill_center_x }}" y="{{ receipt_geom.pill_text_y }}" text-anchor="middle" font-size="9" font-weight="800" letter-spacing="0.28em" fill="var(--dna-pill-text)">{{ pill_label }}</text>
</g>
{# Hero headline: "token volume · $cost" (signal color on cost). v0.3.5 renamed
   from "tokens billed" — same megatoken anchor, no false billing-equivalence claim. #}
<text x="{{ left_margin }}" y="{{ receipt_geom.hero_headline_y }}" class="s ink1" font-size="26" font-weight="800" letter-spacing="-0.02em"><tspan>{{ headline_tokens }}</tspan><tspan fill="var(--dna-signal)">{{ headline_cost }}</tspan></text>
{# v0.3.5 hero decomp strip: four cells (IN / OUT / CACHED / WRITTEN)
   with ink-tertiary dividers between them. Zero buckets (Codex WRITTEN,
   mostly) render the cell text in muted ink. ink3 (matching the
   original v0.3.4 subline) lets the hero number dominate — the decomp
   is supporting information, not a competing focal point. y=92 distributes
   the left-side vertical rhythm — ~14-unit visual gap above (from hero
   descender) and ~10-unit gap below (to the rule), proportional to
   adjacent visual mass. Hero-right row 3 baselines near y=92 to ground
   the bottom band across both columns. #}
<text x="{{ left_margin }}" y="{{ receipt_geom.decomp_y }}" class="m ink3" font-size="10" letter-spacing="0.04em" font-weight="500">
{%- for cell in decomp_cells -%}
{%- if loop.first -%}
<tspan{% if cell.is_zero %} fill="var(--dna-ink-tertiary)"{% endif %}>{{ cell.label }} {{ cell.value }}</tspan>
{%- else -%}
<tspan dx="8" fill="var(--dna-ink-tertiary)" font-weight="400">│</tspan><tspan dx="8"{% if cell.is_zero %} fill="var(--dna-ink-tertiary)"{% endif %}>{{ cell.label }} {{ cell.value }}</tspan>
{%- endif -%}
{%- endfor -%}
</text>
{# Hero-right stats (right-aligned mono ink2 lines at y=60/74/88). Row 3
   shares its y with the decomp strip on the left so the hero zone's bottom
   reads as a single horizontal band rather than two staggered rows. #}
<g data-hw-zone="hero-right">
{% for stat in hero_right_stats | default([]) %}
<text x="{{ content_right_x }}" y="{{ stat.y }}" class="m ink2" font-size="10" text-anchor="end" letter-spacing="0.02em"
  {% if stat.accent == 'failing' %}fill="var(--dna-status-failing-core)" font-weight="600"{% endif %}>{{ stat.text }}</text>
{% endfor %}
</g>
<line x1="{{ left_margin }}" y1="{{ receipt_geom.hero_rule_y }}" x2="{{ content_right_x }}" y2="{{ receipt_geom.hero_rule_y }}" stroke="var(--dna-border)" stroke-width="1"/>

{# ═══ TREEMAP ZONE (translate 24, 104 — header INSIDE zone) ═══ #}
<g transform="translate({{ left_margin }},{{ receipt_geom.treemap_group_y }})" data-hw-zone="treemap">
  {# Header row: "TOKEN MAP ·" + 4 inline color-class chips + ✗N hint.
     v0.3.5: single <text> element with inline tspans matching the SESSION
     RHYTHM header pattern. Each chip is a colored ▍ block character (carries
     the class color) followed by its label tspan. dx values control inter-
     segment spacing for consistent visual rhythm — no absolute x's. The
     "BY TOOL · N SOURCES" subtitle that v9 had lives elsewhere (placement
     pending resolver-side text measurement). #}
  <text y="{{ receipt_geom.treemap_header_y }}" class="m ink3">
    <tspan font-size="7" font-weight="700" letter-spacing="0.22em">{{ treemap_header_label }}</tspan>
{% for chip in treemap_header_chips | default([]) %}
    <tspan dx="{% if loop.first %}2{% else %}6{% endif %}" fill="var(--dna-tool-{{ chip.tool_class }})" font-size="9">▍</tspan>
    <tspan dx="2" font-size="9" letter-spacing="0.04em">{{ chip.label }}</tspan>
{% endfor %}
  </text>
  <text class="m ink3" x="{{ content_w }}" y="{{ receipt_geom.treemap_header_y }}" font-size="9" text-anchor="end"><tspan fill="var(--dna-status-failing-core)" opacity="0.85" font-weight="700">✗N</tspan><tspan dx="3">= failed tool calls</tspan></text>

  {# Tier cells — full-width top accent on every cell, hero metric on tier-1 #}
{% for cell in treemap_cells | default([]) %}
  <g transform="translate({{ cell.x }}, {{ cell.y }})" data-hw-tier="{{ cell.tier }}" data-hw-tool="{{ cell.name }}"{% if cell.is_overflow %} data-hw-overflow="true"{% endif %}>
    <rect width="{{ cell.w }}" height="{{ cell.h }}" fill="var(--dna-surface-deep)"/>
    <rect width="{{ cell.accent_w }}" height="{{ cell.accent_h }}" fill="var(--dna-tool-{{ cell.tool_class }})" opacity="0.85"/>
    <rect width="{{ cell.w }}" height="{{ cell.h }}" fill="none" stroke="var(--dna-border)" stroke-width="0.5"/>
{# Cell text — positions/sizes are computed in compose/treemap.py per cell;
   the template never decides geometry, only renders what was decided. The
   ``show_detail`` flag is False when the cell can't fit both label + detail
   without overflow (catches small cells safely). #}
{% if cell.is_hero %}
    {# Tier-1 hero treatment: percentage at tier-1 hero font size in tool color,
       label and detail at compose-computed offsets. v9 specimen: pct y=58 size=36,
       detail y=72 size=10 — 6px gap between pct baseline and detail top. #}
    <text class="m ink1" font-size="{{ cell.label_size }}" font-weight="600" x="{{ receipt_geom.treemap_cell_hero_text_x }}" y="{{ cell.label_y }}">{{ cell.label }}</text>
    <text class="s" font-size="{{ cell.pct_size }}" font-weight="800" fill="var(--dna-tool-{{ cell.tool_class }})" x="{{ receipt_geom.treemap_cell_hero_text_x }}" y="{{ cell.pct_y }}" letter-spacing="-0.02em">{{ cell.pct }}%</text>
{% if cell.show_detail %}
    <text class="m ink3" font-size="{{ cell.detail_size }}" x="{{ receipt_geom.treemap_cell_hero_text_x }}" y="{{ cell.detail_y }}">{{ cell.detail }}</text>
{% endif %}
{% if cell.errors %}
    <g transform="translate({{ cell.hero_error_group_x }}, {{ cell.hero_error_group_y }})">
      <rect x="{{ receipt_geom.hero_error_rect_x }}" y="{{ receipt_geom.hero_error_rect_y }}" width="{{ receipt_geom.hero_error_rect_w }}" height="{{ receipt_geom.hero_error_rect_h }}" fill="var(--dna-surface-deep)" stroke="var(--dna-status-failing-core)" stroke-opacity="0.35" stroke-width="0.5"/>
      <text class="m" font-size="8" font-weight="700" fill="var(--dna-status-failing-core)" x="{{ receipt_geom.hero_error_text_x }}" y="{{ receipt_geom.hero_error_text_y }}" text-anchor="middle">✗{{ cell.errors }}</text>
    </g>
{% endif %}
{% else %}
    {# Tier-2 + Tier-3: name + (optional) detail + inline error badge #}
    <text class="m ink1" font-size="{{ cell.label_size }}" font-weight="600" x="{{ receipt_geom.treemap_cell_text_x }}" y="{{ cell.label_y }}">{{ cell.label }}</text>
{% if cell.show_detail %}
    <text class="m ink3" font-size="{{ cell.detail_size }}" x="{{ receipt_geom.treemap_cell_text_x }}" y="{{ cell.detail_y }}">{{ cell.detail }}</text>
{% endif %}
{% if cell.errors %}
    <text class="m" font-size="8" font-weight="700" fill="var(--dna-status-failing-core)" x="{{ cell.inline_error_x }}" y="{{ cell.label_y }}" text-anchor="end">✗{{ cell.errors }}</text>
{% endif %}
{% endif %}
  </g>
{% endfor %}
</g>
<line x1="{{ left_margin }}" y1="{{ bottom_divider_y }}" x2="{{ content_right_x }}" y2="{{ bottom_divider_y }}" stroke="var(--dna-border)" stroke-width="1"/>

{# ═══ RHYTHM ZONE (translate 24, 306 — risograph-canonical) ═══ #}
<g transform="translate({{ left_margin }},{{ rhythm_group_y }})" data-hw-zone="rhythm">
  {# Header composite: LEFT lab + RIGHT mono total/peak #}
  <text class="m ink3" font-size="7" font-weight="700" letter-spacing="0.22em">{{ rhythm_header_left }}</text>
  <text class="m ink3" x="{{ content_w }}" y="{{ receipt_geom.rhythm_header_right_y }}" font-size="7.5" text-anchor="end" letter-spacing="0.18em">{{ rhythm_header_right }}</text>

  {# Time axis labels ABOVE the bar track at major intervals #}
{% for tick in time_axis_ticks | default([]) %}
{% if tick.is_major %}
  <text class="m ink3" x="{{ tick.x }}" y="{{ receipt_geom.axis_tick_y }}" font-size="8"{% if loop.first %}{% elif loop.last %} text-anchor="end"{% else %} text-anchor="middle"{% endif %}>{{ tick.label }}</text>
{% endif %}
{% endfor %}

  {# Vertical grid lines at major time intervals (across bar track only) #}
{% for grid in rhythm_grid_lines | default([]) %}
  <line x1="{{ grid.x }}" y1="{{ receipt_geom.grid_y1 }}" x2="{{ grid.x }}" y2="{{ rhythm_baseline_y }}" stroke="var(--dna-border-tint)" stroke-width="0.5" opacity="0.55"/>
{% endfor %}

  {# Baseline rule across full track width #}
  <line x1="{{ receipt_geom.track_x1 }}" y1="{{ rhythm_baseline_y }}" x2="{{ content_w }}" y2="{{ rhythm_baseline_y }}" stroke="var(--dna-border)" stroke-width="1"/>

  {# Variable-height bars (opacity from BarChartCell) #}
  <g data-hw-field="bars">
{% for bar in rhythm_bars | default([]) %}
    <rect x="{{ bar.x }}" y="{{ bar.y }}" width="{{ bar.w }}" height="{{ bar.h }}" fill="var(--dna-tool-{{ bar.tool_class }})" opacity="{{ bar.opacity }}" rx="{{ receipt_geom.bar_rx }}"/>
{% endfor %}
  </g>

  {# Peak marker: 1.5px signal-color tick at top of max-tokens bar #}
{% if rhythm_peak_marker %}
  <rect x="{{ rhythm_peak_marker.x }}" y="{{ rhythm_peak_marker.y }}" width="{{ rhythm_peak_marker.w }}" height="{{ rhythm_peak_marker.h }}" fill="var(--dna-signal)"/>
{% endif %}

  {# Error ticks: dedicated band ABOVE bars (1.2x5px red marks) #}
  <g data-hw-field="errors">
{% for tick in rhythm_error_ticks | default([]) %}
    <rect x="{{ tick.x }}" y="{{ tick.y }}" width="{{ tick.w }}" height="{{ tick.h }}" fill="var(--dna-status-failing-core)" opacity="0.85"/>
{% endfor %}
  </g>

  {# Legend at panel bottom: 4 tool swatches + error-tick swatch + DOMINANT label #}
  <g transform="translate({{ receipt_geom.legend_group_x }}, {{ rhythm_legend_y }})" data-hw-zone="legend">
{% for entry in phase_legend | default([]) %}
{% if entry.kind == 'error' %}
    <rect x="{{ entry.x }}" y="{{ receipt_geom.legend_marker_y }}" width="{{ receipt_geom.legend_error_w }}" height="{{ receipt_geom.legend_marker_h }}" fill="var(--dna-status-failing-core)"/>
    <text class="m ink3" x="{{ entry.text_x }}" y="{{ receipt_geom.legend_text_y }}" font-size="8.5">{{ entry.label }}</text>
{% else %}
    <rect x="{{ entry.x }}" y="{{ receipt_geom.legend_marker_y }}" width="{{ receipt_geom.legend_marker_w }}" height="{{ receipt_geom.legend_marker_h }}" fill="var(--dna-tool-{{ entry.id }})"/>
    <text class="m ink3" x="{{ entry.text_x }}" y="{{ receipt_geom.legend_text_y }}" font-size="8.5">{{ entry.label }}</text>
{% endif %}
{% endfor %}
    <text class="m" x="{{ content_w }}" y="{{ receipt_geom.legend_dominant_y }}" font-size="9" font-weight="700" fill="var(--dna-signal)" text-anchor="end" letter-spacing="0.14em">{{ rhythm_dominant_label }}</text>
  </g>
</g>

{# ═══ FOOTER (4-quadrant) ═══ #}
<line x1="{{ left_margin }}" y1="{{ receipt_geom.footer_rule_y }}" x2="{{ content_right_x }}" y2="{{ receipt_geom.footer_rule_y }}" stroke="var(--dna-border)" stroke-width="0.5"/>
<text x="{{ left_margin }}" y="{{ receipt_geom.footer_top_y }}" class="m ink3" font-size="9" letter-spacing="0.04em">{{ footer_tl }}</text>
<text x="{{ content_right_x }}" y="{{ receipt_geom.footer_top_y }}" class="m ink3" font-size="9" text-anchor="end" letter-spacing="0.04em">{{ footer_tr }}</text>
<text x="{{ left_margin }}" y="{{ receipt_geom.footer_bottom_y }}" class="m ink3" font-size="9" font-style="italic" letter-spacing="0.04em" opacity="0.75">{{ footer_bl }}</text>
<text x="{{ content_right_x }}" y="{{ receipt_geom.footer_bottom_y }}" class="m ink2" font-size="9" text-anchor="end" letter-spacing="0.04em">{{ footer_br }}</text>

{# Card chrome — token-driven, branch-free.
   Top accent strip: rendered for every skin; transparent on voltage + cream
   (no top stripe per their specimens), terra-coral on claude-code per the v9
   specimen. The rect always emits — its visibility comes from the genome.
   Outer frame: 1px stroke at the SVG edge. Rendered for every skin;
   the genome chooses the color. #}
<rect x="{{ receipt_geom.card_top_strip_x }}" y="{{ receipt_geom.card_top_strip_y }}" width="{{ width }}" height="{{ receipt_geom.card_top_strip_h }}" fill="var(--dna-card-border-top)" fill-opacity="0.85" clip-path="url(#receipt-card-shape)"/>
<rect x="{{ receipt_geom.card_border_x }}" y="{{ receipt_geom.card_border_y }}" width="{{ inner_w }}" height="{{ inner_h }}" rx="{{ receipt_geom.card_rx }}" ry="{{ receipt_geom.card_rx }}" fill="none" stroke="var(--dna-card-border)" stroke-width="1"/>
{% endblock %}
