{{/* The results region, rendered two ways from one definition. index.html includes it, so a scriptless form submit gets it inside the page; GET /search executes it alone, so search.js can swap it in on every keystroke. One definition because the two must agree about which result is primed — if they disagreed, where Enter goes would depend on whether the script had loaded yet. */}} {{/* One sentence, two places that must not disagree: the callout the server renders when store.Search fails, and the attribute search.js reads when its own fetch fails. Both mean "the search did not run", and a page with two wordings for that would be two pages. */}} {{define "searchFailed"}}The search did not run. Nothing was found because nothing was searched.{{end}} {{define "results"}} {{if .SearchFailed}}

{{template "searchFailed"}}

{{else if .Searched}} {{/* The count heading only when there is something to count. A zero is said once, below, as one quiet line (spec §4): "0 results for “rev”" over a callout was what live search showed on every partial keystroke. */}} {{if .Results}}

{{len .Results}} result{{if ne (len .Results) 1}}s{{end}} for “{{.Query}}”

{{end}} {{/* §6.5's loud withholding, above the results rather than below them. A reader who scrolls past the last result has already decided what the page means; the notice has to arrive before the list it is about. What each line says is decided in Go (sibling.Outcome), so one wording lives in one place — and every line names an app and never a document, because naming the document would report the existence of a passage this person may not have. */}} {{if .Notices}}
{{range .Notices}}

{{.}}

{{end}}
{{end}} {{/* §8.8's fact box. BELOW the notices and above the list, both deliberately: a confident single answer rendered above the line saying the page is partial is the withholding notice's own argument with the order reversed. Inside this define rather than above it, so search.js swaps box and list together. A box outside it would leave query N-1's answer sitting over query N's results on every keystroke. Every character here is the document's — the label it wrote, the span byte for byte, its own title and heading trail. The link is the ONLY link, and it must never wear rst-result-title: search.js reads that attribute to decide where Enter goes, and §8.8 rules that Enter still goes to the first result and not to a box. */}} {{if .Facts}}
{{range .Facts}} {{/* A row a model pointed at is marked, and names its model — §8.9: it does not inherit the deterministic layer's guarantees (the model can omit, and "this is an address" is its judgement), so the reader must be able to tell the two kinds of claim apart at a glance. Decision 4: every answer names its provider. */}}

{{.Label}} {{.Span}} {{if .Model}}🤖 {{.Provider}} · {{.Model}}{{end}} {{.Title}}{{if .Trail}} › {{.Trail}}{{end}}

{{/* §8.8's narrowing line, under the row it describes: the box chose this row on the reader's own words, and how many it left out. It keeps the others visible, which is the one thing standing between a planted label and a single confident answer. */}} {{with .Note}}

{{.Text}}

{{end}} {{end}}
{{end}} {{if not .Results}} {{/* Not a callout: one muted line (spec §4). Three sentences, and which one is true depends on why the page is empty. The first — "no matches" — is only true when nothing was withheld and the count could be read: a page emptied by withholding is not an absence, and a count that failed is not a zero (AGENTS.md). Same rule as ever; plainer words. rst-search-empty marks it for search.js, which holds it back while the person is still typing: whole-token matching means "rev" finds nothing on the way to "revenue", and saying so on every keystroke is noise, not an answer. A submitted search, and a pause, show it. */}}

{{if .Notices}} Nothing that could be shown matched “{{.Query}}”. Some passages were withheld (see above), so there may be more than this. {{else if lt .Chunks 0}} No matches for “{{.Query}}” — but the passage count could not be read, so the index may be empty. {{else}} No matches for “{{.Query}}”. {{end}}

{{end}}
    {{range $i, $r := .Results}}
  1. {{/* Ancestry above the title, heading trail below it. Both, and in that order, because they answer different questions: the path says which part of the workspace this came from, the heading says where in the page. A result showing only the second is two indistinguishable "Week one"s under different handbooks. */}} {{if $r.Path}}{{$r.Path}}{{end}} {{$r.Title}} {{if $r.Heading}}{{$r.Heading}}{{end}}

    {{$r.Snippet | safeSnippet}}

    {{$r.Source}} · passage {{$r.Ordinal}}

  2. {{end}}
{{end}} {{end}}