From f98b640531e23aef6456f1c63cf82d198ca2ef50 Mon Sep 17 00:00:00 2001 From: Mathias Date: Fri, 12 Jun 2026 10:47:47 +0200 Subject: [PATCH] feat(web): inline-expand summary + Q&A in the list (ADR-031, #16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Click a summarized card → its full summary (summaryBody) + chat dock (chatReveal) expand in place via HTMX (GET /v/{id}/expand → expandedCard), collapse back via GET /v/{id}/card → compact VideoCard. Same
  • , outerHTML swap — the existing list-fragment pattern. The card title carries href=/v/{id} as the no-JS fallback (detail page stays for no-JS + deep links); only summarized cards expand. Reuses summaryBody + chatReveal so the expanded card never drifts from the detail page. BDD: inline_expand.feature un-pended + mapped. TDD: 6 handler/fragment tests (expand/collapse fragments, chat dock, summarized-only, no-JS href, shared body). Minimal CSS only — the TUI/charm restyle is #17. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/use-cases/inline_expand.feature | 8 +- internal/web/handlers.go | 44 + internal/web/inline_expand_test.go | 107 ++ internal/web/view.go | 16 + internal/web/views.templ | 37 +- internal/web/views_templ.go | 1168 ++++++++++++--------- test/acceptance/scenario_coverage_test.go | 8 + 7 files changed, 866 insertions(+), 522 deletions(-) create mode 100644 internal/web/inline_expand_test.go diff --git a/docs/use-cases/inline_expand.feature b/docs/use-cases/inline_expand.feature index 96a7f65..48aeb2b 100644 --- a/docs/use-cases/inline_expand.feature +++ b/docs/use-cases/inline_expand.feature @@ -4,39 +4,33 @@ Feature: Inline-expand summary + Q&A in the list (ADR-031, #16) So that I get the full read and follow-up without leaving the list (SPA-like, no page hop) # HTMX inline-expand, no SPA framework (ADR-031). Each scenario maps to a Go test - # in scenario_coverage_test.go; tagged @pending until the TDD step lands it. + # in scenario_coverage_test.go (the BDD name-coverage gate). - @pending # TestExpandReturnsSummaryBodyFragment Scenario: A summarized card expands to the full summary in place Given a summarized video in my list When I expand its card Then the full summary, highlights, and takeaways are returned as an in-place card fragment, not a full page - @pending # TestCollapseReturnsCompactCard Scenario: An expanded card collapses back to the compact card Given an expanded card When I collapse it Then the compact card fragment is returned in its place - @pending # TestExpandedCardOffersChatDock Scenario: The expanded card offers the Q&A dock Given chat is enabled When a summarized card is expanded Then the expanded card includes the deeper-dive chat affordance for that video - @pending # TestCompactCardExpandOnlyWhenSummarized Scenario: Only a summarized card offers expand Given a discovered but not-yet-summarized card When the card is rendered Then it shows its summarize/queue footer and no expand affordance - @pending # TestCompactCardHasNoJSDetailFallback Scenario: With JS off the card still reaches the full summary Given a summarized card When it is rendered Then its expand affordance carries an href to the detail page as a no-JS fallback - @pending # TestDetailAndExpandShareSummaryBody Scenario: The detail page and the expanded card show the same summary Given a summarized video When I view it on the detail page and as an expanded card diff --git a/internal/web/handlers.go b/internal/web/handlers.go index 6d20c37..e75c1a2 100644 --- a/internal/web/handlers.go +++ b/internal/web/handlers.go @@ -151,6 +151,8 @@ func (a *App) Router() http.Handler { app := http.NewServeMux() app.HandleFunc("GET /{$}", a.handleList) app.HandleFunc("GET /v/{videoId}", a.handleDetail) + app.HandleFunc("GET /v/{videoId}/expand", a.handleExpand) + app.HandleFunc("GET /v/{videoId}/card", a.handleCard) app.HandleFunc("POST /v/{videoId}/action", a.handleAction) app.HandleFunc("POST /v/{videoId}/summarize", a.handleRequestSummarize) app.HandleFunc("POST /v/{videoId}/retry-now", a.handleRetryNow) @@ -283,6 +285,48 @@ func (a *App) handleDetail(w http.ResponseWriter, r *http.Request) { a.render(w, r, DetailPage(*row, a.Chat != nil)) } +// handleExpand returns the inline-expanded card fragment — the full summary + +// chat dock swapped into the list card in place (ADR-031). Only summarized videos +// have a summary to expand; a non-summarized id is a 404 (the compact card never +// offers expand for it). +func (a *App) handleExpand(w http.ResponseWriter, r *http.Request) { + userID, ok := a.currentUserID(w, r) + if !ok { + return + } + videoID := r.PathValue("videoId") + row, err := a.Store.GetSummaryByVideo(r.Context(), userID, videoID) + if errors.Is(err, store.ErrNotFound) { + http.NotFound(w, r) + return + } + if err != nil { + a.serverError(w, r, "get summary", err) + return + } + a.render(w, r, expandedCard(*row, a.Chat != nil)) +} + +// handleCard returns the compact card fragment — the collapse target that returns +// an expanded card to its compact form in the list (ADR-031). +func (a *App) handleCard(w http.ResponseWriter, r *http.Request) { + userID, ok := a.currentUserID(w, r) + if !ok { + return + } + videoID := r.PathValue("videoId") + row, err := a.Store.GetVideoRow(r.Context(), userID, videoID) + if errors.Is(err, store.ErrNotFound) { + http.NotFound(w, r) + return + } + if err != nil { + a.serverError(w, r, "get video", err) + return + } + a.render(w, r, VideoCard(*row)) +} + // handleAction toggles one action: re-clicking an active verb clears it, else it // is set (the store enforces watched↔skipped exclusion atomically). It returns // the refreshed button-group fragment for HTMX; without JS it redirects back to diff --git a/internal/web/inline_expand_test.go b/internal/web/inline_expand_test.go new file mode 100644 index 0000000..5f2dda1 --- /dev/null +++ b/internal/web/inline_expand_test.go @@ -0,0 +1,107 @@ +package web_test + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +// TestExpandReturnsSummaryBodyFragment: GET /v/{id}/expand returns the full +// summary as an in-place card fragment (not a full page) — ADR-031. +func TestExpandReturnsSummaryBodyFragment(t *testing.T) { + ctx := context.Background() + app := newApp(t) + p := rawPool(t) + resetDB(t, p) + require.NoError(t, deliver(ctx, app, videoX, "the full summary text")) + seedVideo(t, p, videoX, "X Title", "https://x", time.Time{}) + + html := body(t, do(t, app, httptest.NewRequest(http.MethodGet, "/v/"+videoX+"/expand", nil))) + require.Contains(t, html, "the full summary text") + require.Contains(t, html, "Takeaways") + require.Contains(t, html, "highlight one") + require.Contains(t, html, "card-expanded", "rendered as the expanded card") + require.Contains(t, html, "/v/"+videoX+"/card", "carries a collapse affordance") + require.NotContains(t, html, " if r.Summarized { - + // Expand the full summary + Q&A in place (ADR-031); href is the no-JS + // fallback to the detail page, so nothing becomes JS-only. + } else {
    { displayTitle(r) }
    } @@ -327,6 +336,32 @@ templ VideoCard(r store.SummaryRow) {
  • } +// expandedCard is a summarized list card opened IN PLACE (ADR-031): the full +// summary body + the deeper-dive chat dock, with a collapse control back to the +// compact card. It shares the
  • with VideoCard so HTMX swaps it outerHTML, +// and reuses summaryBody + chatReveal so it never drifts from the detail page. +// Note: chatReveal uses a single #chat-section id, so this assumes one card open +// at a time; a per-video chat id is a follow-up if simultaneous expansion is wanted. +templ expandedCard(r store.SummaryRow, chatEnabled bool) { +
  • +
    + { displayTitle(r) } + collapse ↑ +
    + @summaryBody(r) + if chatEnabled { + @chatReveal(r.VideoID) + } +
  • +} + // TapirSpinner is the summarizing animation: a Charmbracelet-style TUI panel — // three richly coloured ASCII tapir frames (inline span colours, snout wiggling // ∩→∪→~) cross-faded by CSS, plus a lipgloss-style progress bar whose mint fill diff --git a/internal/web/views_templ.go b/internal/web/views_templ.go index 62efd27..9808046 100644 --- a/internal/web/views_templ.go +++ b/internal/web/views_templ.go @@ -828,129 +828,145 @@ func VideoCard(r store.SummaryRow) templ.Component { return templ_7745c5c3_Err } if r.Summarized { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "\" hx-get=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var30 string - templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) + templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.ResolveAttributeValue(string(expandURL(r.VideoID))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 267, Col: 76} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 272, Col: 42} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var30) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "
    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "\" hx-target=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var31 string - templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) + templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.ResolveAttributeValue("#video-" + r.VideoID) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 269, Col: 44} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 273, Col: 38} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var31) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "
    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if cardMeta(r) != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "\" hx-swap=\"outerHTML\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var32 string - templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(cardMeta(r)) + templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 272, Col: 39} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 275, Col: 22} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "
    ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "
    ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var33 string + templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 278, Col: 44} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } + if cardMeta(r) != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "
    ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var34 string + templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(cardMeta(r)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 281, Col: 39} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "
    ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } if r.Summarized { if p := previewText(r.Summary, 160); p != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var33 string - templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(p) + var templ_7745c5c3_Var35 string + templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(p) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 276, Col: 33} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 285, Col: 33} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if r.Summarized { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if r.AIProvider != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var34 string - templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(r.AIProvider) + var templ_7745c5c3_Var36 string + templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(r.AIProvider) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 283, Col: 38} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 292, Col: 38} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, " ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - if r.FallbackUsed { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "fallback") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -959,125 +975,249 @@ func VideoCard(r store.SummaryRow) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } + if r.FallbackUsed { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "fallback") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, " ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } if len(r.Actions) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var35 string - templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(r.Actions, ", ")) + var templ_7745c5c3_Var37 string + templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(r.Actions, ", ")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 289, Col: 61} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 298, Col: 61} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } } else if r.TranscriptStatus == "none" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, " No transcript available") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, " No transcript available") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if r.SummarizeRequested { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 84, " Queued summarizing shortly") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 86, " Queued summarizing shortly") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else if r.TranscriptStatus == "rate_limited" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 85, " In queue
    In queue
    ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 89, " Not summarized
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var41 string - templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.ResolveAttributeValue("#video-" + r.VideoID) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 319, Col: 38} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var41) + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, " Not summarized
    ") + var templ_7745c5c3_Var41 templ.SafeURL + templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinURLErrs(summarizeURL(r.VideoID)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 326, Col: 37} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "\" hx-post=\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var42 string + templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.ResolveAttributeValue(string(summarizeURL(r.VideoID))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 327, Col: 46} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var42) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "\" hx-target=\"") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var43 string + templ_7745c5c3_Var43, templ_7745c5c3_Err = templ.ResolveAttributeValue("#video-" + r.VideoID) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 328, Col: 38} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var43) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "\" hx-swap=\"outerHTML\" class=\"card-nudge-form\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "
    ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + +// expandedCard is a summarized list card opened IN PLACE (ADR-031): the full +// summary body + the deeper-dive chat dock, with a collapse control back to the +// compact card. It shares the
  • with VideoCard so HTMX swaps it outerHTML, +// and reuses summaryBody + chatReveal so it never drifts from the detail page. +// Note: chatReveal uses a single #chat-section id, so this assumes one card open +// at a time; a per-video chat id is a follow-up if simultaneous expansion is wanted. +func expandedCard(r store.SummaryRow, chatEnabled bool) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var44 := templ.GetChildren(ctx) + if templ_7745c5c3_Var44 == nil { + templ_7745c5c3_Var44 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "
  • ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var46 string + templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 348, Col: 45} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, " collapse ↑
    ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = summaryBody(r).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if chatEnabled { + templ_7745c5c3_Err = chatReveal(r.VideoID).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, "
  • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1106,12 +1246,12 @@ func TapirSpinner() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var42 := templ.GetChildren(ctx) - if templ_7745c5c3_Var42 == nil { - templ_7745c5c3_Var42 = templ.NopComponent + templ_7745c5c3_Var50 := templ.GetChildren(ctx) + if templ_7745c5c3_Var50 == nil { + templ_7745c5c3_Var50 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "
    ")
    +		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, "
    ")
     		if templ_7745c5c3_Err != nil {
     			return templ_7745c5c3_Err
     		}
    @@ -1119,7 +1259,7 @@ func TapirSpinner() templ.Component {
     		if templ_7745c5c3_Err != nil {
     			return templ_7745c5c3_Err
     		}
    -		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "
    ")
    +		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, "
    ")
     		if templ_7745c5c3_Err != nil {
     			return templ_7745c5c3_Err
     		}
    @@ -1127,7 +1267,7 @@ func TapirSpinner() templ.Component {
     		if templ_7745c5c3_Err != nil {
     			return templ_7745c5c3_Err
     		}
    -		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 96, "
    ")
    +		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, "
    ")
     		if templ_7745c5c3_Err != nil {
     			return templ_7745c5c3_Err
     		}
    @@ -1135,33 +1275,33 @@ func TapirSpinner() templ.Component {
     		if templ_7745c5c3_Err != nil {
     			return templ_7745c5c3_Err
     		}
    -		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var44 string - templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(tapirBarFill) + var templ_7745c5c3_Var52 string + templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(tapirBarFill) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 340, Col: 99} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 375, Col: 99} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, "

    Fetching captions… Chewing the cud… Munching leaves… Distilling the gist… Summarizing…

    Summarizing…

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, "

    Fetching captions… Chewing the cud… Munching leaves… Distilling the gist… Summarizing…

    Summarizing…

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1190,69 +1330,69 @@ func processingCard(r store.SummaryRow) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var45 := templ.GetChildren(ctx) - if templ_7745c5c3_Var45 == nil { - templ_7745c5c3_Var45 = templ.NopComponent + templ_7745c5c3_Var53 := templ.GetChildren(ctx) + if templ_7745c5c3_Var53 == nil { + templ_7745c5c3_Var53 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 100, "
  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "\" hx-trigger=\"every 2s\" hx-swap=\"outerHTML\">
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var48 string - templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) + var templ_7745c5c3_Var56 string + templ_7745c5c3_Var56, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 368, Col: 43} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 403, Col: 43} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var48)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var56)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if cardMeta(r) != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 104, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var49 string - templ_7745c5c3_Var49, templ_7745c5c3_Err = templ.JoinStringErrs(cardMeta(r)) + var templ_7745c5c3_Var57 string + templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(cardMeta(r)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 370, Col: 39} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 405, Col: 39} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var49)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var57)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 114, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1261,7 +1401,7 @@ func processingCard(r store.SummaryRow) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "
  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1289,74 +1429,74 @@ func waitingCard(r store.SummaryRow) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var50 := templ.GetChildren(ctx) - if templ_7745c5c3_Var50 == nil { - templ_7745c5c3_Var50 = templ.NopComponent + templ_7745c5c3_Var58 := templ.GetChildren(ctx) + if templ_7745c5c3_Var58 == nil { + templ_7745c5c3_Var58 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "
  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "\" hx-trigger=\"every 30s\" hx-swap=\"outerHTML\">
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var53 string - templ_7745c5c3_Var53, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) + var templ_7745c5c3_Var61 string + templ_7745c5c3_Var61, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 388, Col: 43} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 423, Col: 43} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var53)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var61)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if cardMeta(r) != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var54 string - templ_7745c5c3_Var54, templ_7745c5c3_Err = templ.JoinStringErrs(cardMeta(r)) + var templ_7745c5c3_Var62 string + templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.JoinStringErrs(cardMeta(r)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 390, Col: 39} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 425, Col: 39} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var54)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var62)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "
    ")
    +		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "
    ")
     		if templ_7745c5c3_Err != nil {
     			return templ_7745c5c3_Err
     		}
    @@ -1364,7 +1504,7 @@ func waitingCard(r store.SummaryRow) templ.Component {
     		if templ_7745c5c3_Err != nil {
     			return templ_7745c5c3_Err
     		}
    -		templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 114, "

    Waiting on YouTube rate limits. Tapir keeps trying, slowly and politely, and the summary will appear here on its own.

  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "

    Waiting on YouTube rate limits. Tapir keeps trying, slowly and politely, and the summary will appear here on its own.

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1390,61 +1530,61 @@ func noCaptionsCard(r store.SummaryRow) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var55 := templ.GetChildren(ctx) - if templ_7745c5c3_Var55 == nil { - templ_7745c5c3_Var55 = templ.NopComponent + templ_7745c5c3_Var63 := templ.GetChildren(ctx) + if templ_7745c5c3_Var63 == nil { + templ_7745c5c3_Var63 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "
  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "\">
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var57 string - templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) + var templ_7745c5c3_Var65 string + templ_7745c5c3_Var65, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 405, Col: 43} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 440, Col: 43} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var57)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var65)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if cardMeta(r) != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 127, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var58 string - templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs(cardMeta(r)) + var templ_7745c5c3_Var66 string + templ_7745c5c3_Var66, templ_7745c5c3_Err = templ.JoinStringErrs(cardMeta(r)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 407, Col: 39} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 442, Col: 39} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var58)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var66)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 128, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, "

    No captions available, so Tapir cannot summarize this one.

  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 129, "

    No captions available, so Tapir cannot summarize this one.

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1472,91 +1612,91 @@ func summaryBody(r store.SummaryRow) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var59 := templ.GetChildren(ctx) - if templ_7745c5c3_Var59 == nil { - templ_7745c5c3_Var59 = templ.NopComponent + templ_7745c5c3_Var67 := templ.GetChildren(ctx) + if templ_7745c5c3_Var67 == nil { + templ_7745c5c3_Var67 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 130, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if detailMeta(r) != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 131, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var60 string - templ_7745c5c3_Var60, templ_7745c5c3_Err = templ.JoinStringErrs(detailMeta(r)) + var templ_7745c5c3_Var68 string + templ_7745c5c3_Var68, templ_7745c5c3_Err = templ.JoinStringErrs(detailMeta(r)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 420, Col: 24} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 455, Col: 24} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var60)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var68)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 132, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if r.FallbackUsed { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 124, "fallback") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 133, "fallback") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 134, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if url, ok := embedURL(r.ProviderVideoID); ok { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 137, "\" loading=\"lazy\" referrerpolicy=\"strict-origin-when-cross-origin\" allow=\"accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if r.URL != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 129, "

    watch on source ↗

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 139, "\" rel=\"noopener noreferrer\">watch on source ↗

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1566,77 +1706,77 @@ func summaryBody(r store.SummaryRow) templ.Component { return templ_7745c5c3_Err } if len(r.Takeaways) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 131, "

    Takeaways

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if len(r.Highlights) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 135, "

    Highlights

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 139, "

    Summary

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 148, "

    Summary

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var66 string - templ_7745c5c3_Var66, templ_7745c5c3_Err = templ.JoinStringErrs(r.Summary) + var templ_7745c5c3_Var74 string + templ_7745c5c3_Var74, templ_7745c5c3_Err = templ.JoinStringErrs(r.Summary) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 464, Col: 29} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 499, Col: 29} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var66)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var74)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 140, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 149, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1664,12 +1804,12 @@ func DetailPage(r store.SummaryRow, chatEnabled bool) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var67 := templ.GetChildren(ctx) - if templ_7745c5c3_Var67 == nil { - templ_7745c5c3_Var67 = templ.NopComponent + templ_7745c5c3_Var75 := templ.GetChildren(ctx) + if templ_7745c5c3_Var75 == nil { + templ_7745c5c3_Var75 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var68 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var76 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -1681,20 +1821,20 @@ func DetailPage(r store.SummaryRow, chatEnabled bool) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 141, "

    ← Summaries

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 150, "

    ← Summaries

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var69 string - templ_7745c5c3_Var69, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) + var templ_7745c5c3_Var77 string + templ_7745c5c3_Var77, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 476, Col: 24} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 511, Col: 24} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var69)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var77)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 142, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 151, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1708,13 +1848,13 @@ func DetailPage(r store.SummaryRow, chatEnabled bool) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 143, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 152, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) - templ_7745c5c3_Err = Layout("Tapir — "+displayTitle(r)).Render(templ.WithChildren(ctx, templ_7745c5c3_Var68), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = Layout("Tapir — "+displayTitle(r)).Render(templ.WithChildren(ctx, templ_7745c5c3_Var76), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1743,38 +1883,38 @@ func chatReveal(videoID string) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var70 := templ.GetChildren(ctx) - if templ_7745c5c3_Var70 == nil { - templ_7745c5c3_Var70 = templ.NopComponent + templ_7745c5c3_Var78 := templ.GetChildren(ctx) + if templ_7745c5c3_Var78 == nil { + templ_7745c5c3_Var78 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 144, "
    Dig deeper — ask about this video →
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 155, "\" hx-target=\"#chat-section\" hx-swap=\"outerHTML\">Dig deeper — ask about this video →") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1801,12 +1941,12 @@ func chatSection(v chatView) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var73 := templ.GetChildren(ctx) - if templ_7745c5c3_Var73 == nil { - templ_7745c5c3_Var73 = templ.NopComponent + templ_7745c5c3_Var81 := templ.GetChildren(ctx) + if templ_7745c5c3_Var81 == nil { + templ_7745c5c3_Var81 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 147, "

    Ask about this video

    Answers come only from this video's stored transcript — Tapir never fetches anything new here.

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 156, "

    Ask about this video

    Answers come only from this video's stored transcript — Tapir never fetches anything new here.

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1814,7 +1954,7 @@ func chatSection(v chatView) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 148, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 157, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1841,12 +1981,12 @@ func ChatPage(r store.SummaryRow, v chatView) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var74 := templ.GetChildren(ctx) - if templ_7745c5c3_Var74 == nil { - templ_7745c5c3_Var74 = templ.NopComponent + templ_7745c5c3_Var82 := templ.GetChildren(ctx) + if templ_7745c5c3_Var82 == nil { + templ_7745c5c3_Var82 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var75 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var83 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -1858,20 +1998,20 @@ func ChatPage(r store.SummaryRow, v chatView) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 149, "

    ← Summaries

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 158, "

    ← Summaries

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var76 string - templ_7745c5c3_Var76, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) + var templ_7745c5c3_Var84 string + templ_7745c5c3_Var84, templ_7745c5c3_Err = templ.JoinStringErrs(displayTitle(r)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 522, Col: 24} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 557, Col: 24} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var76)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var84)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 150, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 159, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1883,13 +2023,13 @@ func ChatPage(r store.SummaryRow, v chatView) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 151, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 160, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) - templ_7745c5c3_Err = Layout("Tapir — "+displayTitle(r)).Render(templ.WithChildren(ctx, templ_7745c5c3_Var75), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = Layout("Tapir — "+displayTitle(r)).Render(templ.WithChildren(ctx, templ_7745c5c3_Var83), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -1918,210 +2058,210 @@ func chatPanel(v chatView) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var77 := templ.GetChildren(ctx) - if templ_7745c5c3_Var77 == nil { - templ_7745c5c3_Var77 = templ.NopComponent + templ_7745c5c3_Var85 := templ.GetChildren(ctx) + if templ_7745c5c3_Var85 == nil { + templ_7745c5c3_Var85 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 152, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 161, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if !v.Available { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 153, "

    Chat isn't available for this video — its transcript isn't stored, and chat never fetches new captions. Summarize the video first to store its transcript.

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 162, "

    Chat isn't available for this video — its transcript isn't stored, and chat never fetches new captions. Summarize the video first to store its transcript.

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { if len(v.History) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 154, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 163, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, t := range v.History { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 155, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 164, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var78 string - templ_7745c5c3_Var78, templ_7745c5c3_Err = templ.JoinStringErrs(t.Question) + var templ_7745c5c3_Var86 string + templ_7745c5c3_Var86, templ_7745c5c3_Err = templ.JoinStringErrs(t.Question) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 542, Col: 51} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 577, Col: 51} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var78)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var86)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 156, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 165, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var79 string - templ_7745c5c3_Var79, templ_7745c5c3_Err = templ.JoinStringErrs(t.Answer) + var templ_7745c5c3_Var87 string + templ_7745c5c3_Var87, templ_7745c5c3_Err = templ.JoinStringErrs(t.Answer) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 543, Col: 62} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 578, Col: 62} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var79)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var87)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 157, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 166, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 158, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 167, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 159, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 168, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if v.Truncated { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 160, "

    Working from a bounded portion of a long transcript — answers about the end of the video may be incomplete.

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 169, "

    Working from a bounded portion of a long transcript — answers about the end of the video may be incomplete.

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 161, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 170, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if v.Error != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 162, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 171, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var80 string - templ_7745c5c3_Var80, templ_7745c5c3_Err = templ.JoinStringErrs(v.Error) + var templ_7745c5c3_Var88 string + templ_7745c5c3_Var88, templ_7745c5c3_Err = templ.JoinStringErrs(v.Error) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 551, Col: 48} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 586, Col: 48} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var80)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var88)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 163, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 172, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 164, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 175, "\" hx-target=\"#chat-panel\" hx-swap=\"outerHTML\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, t := range v.History { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 167, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 178, "\"> ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 170, " thinking…
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 185, " Switch models to compare answers on the same transcript. thinking…") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 177, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 186, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -2148,12 +2288,12 @@ func RegisterPage(email, errMsg string) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var87 := templ.GetChildren(ctx) - if templ_7745c5c3_Var87 == nil { - templ_7745c5c3_Var87 = templ.NopComponent + templ_7745c5c3_Var95 := templ.GetChildren(ctx) + if templ_7745c5c3_Var95 == nil { + templ_7745c5c3_Var95 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var88 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var96 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -2165,59 +2305,59 @@ func RegisterPage(email, errMsg string) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 178, "

    Complete your registration

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 187, "

    Complete your registration

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if email != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 179, "

    Signed in as ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 188, "

    Signed in as ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var89 string - templ_7745c5c3_Var89, templ_7745c5c3_Err = templ.JoinStringErrs(email) + var templ_7745c5c3_Var97 string + templ_7745c5c3_Var97, templ_7745c5c3_Err = templ.JoinStringErrs(email) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 590, Col: 40} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 625, Col: 40} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var89)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var97)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 180, ".

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 189, ".

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 181, "

    Choose a display name to finish setting up your Tapir account.

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 190, "

    Choose a display name to finish setting up your Tapir account.

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if errMsg != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 182, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 191, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var90 string - templ_7745c5c3_Var90, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg) + var templ_7745c5c3_Var98 string + templ_7745c5c3_Var98, templ_7745c5c3_Err = templ.JoinStringErrs(errMsg) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 594, Col: 42} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 629, Col: 42} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var90)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var98)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 183, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 192, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 184, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 193, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) - templ_7745c5c3_Err = Layout("Tapir — Register").Render(templ.WithChildren(ctx, templ_7745c5c3_Var88), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = Layout("Tapir — Register").Render(templ.WithChildren(ctx, templ_7745c5c3_Var96), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -2245,12 +2385,12 @@ func AccountPage(displayName, email string, conns []store.Connection, autoSummar }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var91 := templ.GetChildren(ctx) - if templ_7745c5c3_Var91 == nil { - templ_7745c5c3_Var91 = templ.NopComponent + templ_7745c5c3_Var99 := templ.GetChildren(ctx) + if templ_7745c5c3_Var99 == nil { + templ_7745c5c3_Var99 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Var92 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_Var100 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) if !templ_7745c5c3_IsBuffer { @@ -2266,43 +2406,43 @@ func AccountPage(displayName, email string, conns []store.Connection, autoSummar if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 185, "

    Account

    Display name
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 194, "

    Account

    Display name
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var93 string - templ_7745c5c3_Var93, templ_7745c5c3_Err = templ.JoinStringErrs(displayNameOr(displayName)) + var templ_7745c5c3_Var101 string + templ_7745c5c3_Var101, templ_7745c5c3_Err = templ.JoinStringErrs(displayNameOr(displayName)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 618, Col: 36} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 653, Col: 36} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var93)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var101)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 186, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 195, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if email != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 187, "
    Signed in as
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 196, "
    Signed in as
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var94 string - templ_7745c5c3_Var94, templ_7745c5c3_Err = templ.JoinStringErrs(email) + var templ_7745c5c3_Var102 string + templ_7745c5c3_Var102, templ_7745c5c3_Err = templ.JoinStringErrs(email) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 621, Col: 16} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 656, Col: 16} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var94)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var102)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 188, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 197, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 189, "

    Summarization

    Automatic summarizes new videos from about the last week as they are discovered. Older videos stay browsable — summarize them on demand. Manual lets you pick which videos to summarize — every new video appears in your list with a Summarize button.

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 198, "

    Summarization

    Automatic summarizes new videos from about the last week as they are discovered. Older videos stay browsable — summarize them on demand. Manual lets you pick which videos to summarize — every new video appears in your list with a Summarize button.

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -2310,178 +2450,178 @@ func AccountPage(displayName, email string, conns []store.Connection, autoSummar if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 190, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 199, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if len(channelErrors) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 191, "

    Unavailable channels

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 200, "

    Unavailable channels

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var95 string - templ_7745c5c3_Var95, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d channel(s) returned errors on the last discovery pass.", len(channelErrors))) + var templ_7745c5c3_Var103 string + templ_7745c5c3_Var103, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d channel(s) returned errors on the last discovery pass.", len(channelErrors))) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 638, Col: 100} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 673, Col: 100} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var95)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var103)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 192, " These may have been deleted or made private on YouTube.

      ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 201, " These may have been deleted or made private on YouTube.

        ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, ce := range channelErrors { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 193, "
      • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 202, "
      • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var96 string - templ_7745c5c3_Var96, templ_7745c5c3_Err = templ.JoinStringErrs(ce.ChannelName) + var templ_7745c5c3_Var104 string + templ_7745c5c3_Var104, templ_7745c5c3_Err = templ.JoinStringErrs(ce.ChannelName) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 644, Col: 57} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 679, Col: 57} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var96)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var104)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 194, " unavailable since ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 203, " unavailable since ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var97 string - templ_7745c5c3_Var97, templ_7745c5c3_Err = templ.JoinStringErrs(ce.FirstSeen.Format("2006-01-02")) + var templ_7745c5c3_Var105 string + templ_7745c5c3_Var105, templ_7745c5c3_Err = templ.JoinStringErrs(ce.FirstSeen.Format("2006-01-02")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 646, Col: 89} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 681, Col: 89} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var97)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var105)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 195, "
      • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 204, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 196, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 205, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 197, "

    Connected accounts

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 206, "

    Connected accounts

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if len(conns) == 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 198, "

    No connected video accounts yet.

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 207, "

    No connected video accounts yet.

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 199, "
      ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 208, "
        ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, c := range conns { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 200, "
      • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 209, "
      • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var98 string - templ_7745c5c3_Var98, templ_7745c5c3_Err = templ.JoinStringErrs(providerLabel(c.Provider)) + var templ_7745c5c3_Var106 string + templ_7745c5c3_Var106, templ_7745c5c3_Err = templ.JoinStringErrs(providerLabel(c.Provider)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 661, Col: 64} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 696, Col: 64} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var98)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var106)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 201, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 210, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if c.ProviderAccount != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 202, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 211, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var99 string - templ_7745c5c3_Var99, templ_7745c5c3_Err = templ.JoinStringErrs(c.ProviderAccount) + var templ_7745c5c3_Var107 string + templ_7745c5c3_Var107, templ_7745c5c3_Err = templ.JoinStringErrs(c.ProviderAccount) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 663, Col: 49} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 698, Col: 49} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var99)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var107)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 203, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 212, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 204, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 213, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var100 string - templ_7745c5c3_Var100, templ_7745c5c3_Err = templ.JoinStringErrs(c.Status) + var templ_7745c5c3_Var108 string + templ_7745c5c3_Var108, templ_7745c5c3_Err = templ.JoinStringErrs(c.Status) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 665, Col: 38} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 700, Col: 38} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var100)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var108)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 205, "
        connected ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 214, "
        connected ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var101 string - templ_7745c5c3_Var101, templ_7745c5c3_Err = templ.JoinStringErrs(c.ConnectedAt.Format("2006-01-02")) + var templ_7745c5c3_Var109 string + templ_7745c5c3_Var109, templ_7745c5c3_Err = templ.JoinStringErrs(c.ConnectedAt.Format("2006-01-02")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 667, Col: 83} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 702, Col: 83} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var101)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var109)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 206, "
      • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 216, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 208, "
      ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 217, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if !hasYouTube(conns) { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 209, "

    Connect YouTube

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 218, "

    Connect YouTube

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 210, "

    Delete account

    Permanently remove your Tapir account and all of its data — summaries, watch/skip/save actions, and connected accounts. This cannot be undone.

    Delete account…

    This permanently deletes your account and all data. Are you sure?

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 219, "

    Delete account

    Permanently remove your Tapir account and all of its data — summaries, watch/skip/save actions, and connected accounts. This cannot be undone.

    Delete account…

    This permanently deletes your account and all data. Are you sure?

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } return nil }) - templ_7745c5c3_Err = Layout("Tapir — Account").Render(templ.WithChildren(ctx, templ_7745c5c3_Var92), templ_7745c5c3_Buffer) + templ_7745c5c3_Err = Layout("Tapir — Account").Render(templ.WithChildren(ctx, templ_7745c5c3_Var100), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -2509,51 +2649,51 @@ func summarizeModeControl(auto bool) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var103 := templ.GetChildren(ctx) - if templ_7745c5c3_Var103 == nil { - templ_7745c5c3_Var103 = templ.NopComponent + templ_7745c5c3_Var111 := templ.GetChildren(ctx) + if templ_7745c5c3_Var111 == nil { + templ_7745c5c3_Var111 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 211, "

    Current mode: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 220, "

    Current mode: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var104 string - templ_7745c5c3_Var104, templ_7745c5c3_Err = templ.JoinStringErrs(summarizeModeLabel(auto)) + var templ_7745c5c3_Var112 string + templ_7745c5c3_Var112, templ_7745c5c3_Err = templ.JoinStringErrs(summarizeModeLabel(auto)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 705, Col: 53} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/views.templ`, Line: 740, Col: 53} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var104)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var112)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 212, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 223, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -2581,38 +2721,38 @@ func ActionButtons(videoID string, active map[string]bool) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var107 := templ.GetChildren(ctx) - if templ_7745c5c3_Var107 == nil { - templ_7745c5c3_Var107 = templ.NopComponent + templ_7745c5c3_Var115 := templ.GetChildren(ctx) + if templ_7745c5c3_Var115 == nil { + templ_7745c5c3_Var115 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 215, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 226, "\" hx-target=\"#action-buttons\" hx-swap=\"outerHTML\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -2624,7 +2764,7 @@ func ActionButtons(videoID string, active map[string]bool) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 218, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 227, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -2632,7 +2772,7 @@ func ActionButtons(videoID string, active map[string]bool) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 219, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 228, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -2658,81 +2798,81 @@ func actionButton(verb string, isActive bool) templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var110 := templ.GetChildren(ctx) - if templ_7745c5c3_Var110 == nil { - templ_7745c5c3_Var110 = templ.NopComponent + templ_7745c5c3_Var118 := templ.GetChildren(ctx) + if templ_7745c5c3_Var118 == nil { + templ_7745c5c3_Var118 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - var templ_7745c5c3_Var111 = []any{"action", templ.KV("active", isActive)} - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var111...) + var templ_7745c5c3_Var119 = []any{"action", templ.KV("active", isActive)} + templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var119...) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 220, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 233, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/test/acceptance/scenario_coverage_test.go b/test/acceptance/scenario_coverage_test.go index 9ced566..1c46133 100644 --- a/test/acceptance/scenario_coverage_test.go +++ b/test/acceptance/scenario_coverage_test.go @@ -25,6 +25,14 @@ import ( // fails if a scenario is unmapped, a mapped test is missing, or an entry no // longer matches a real non-pending scenario. var scenarioCoverage = map[string]string{ + // inline_expand.feature (ADR-031, #16) + "A summarized card expands to the full summary in place": "TestExpandReturnsSummaryBodyFragment", + "An expanded card collapses back to the compact card": "TestCollapseReturnsCompactCard", + "The expanded card offers the Q&A dock": "TestExpandedCardOffersChatDock", + "Only a summarized card offers expand": "TestCompactCardExpandOnlyWhenSummarized", + "With JS off the card still reaches the full summary": "TestCompactCardHasNoJSDetailFallback", + "The detail page and the expanded card show the same summary": "TestDetailAndExpandShareSummaryBody", + // observability.feature (ADR-030, #15) "Summarization latency is recorded per endpoint": "TestSummarizerRecordsMetric", "A failing summarizer endpoint records its failure outcome": "TestObserveSummarizeRecordsFailureOutcomes",