{{define "title"}}{{.Title}}{{end}}

{{define "content"}}
{{$page := .Page}}
<div class="max-w-[1280px] mx-auto px-8 pt-7 pb-14">

  {{/* ---------- breadcrumbs ---------- */}}
  <div class="crumbs">
    <a href="/">Dashboard</a><span class="sep">/</span>
    {{if $page.Form}}
      <a href="/settings">Settings</a><span class="sep">/</span>
      <a href="/settings/notifications">notifications</a><span class="sep">/</span>
      {{if $page.Form.ID}}
        <span class="text-ink-mid">{{$page.Form.Name}}</span>
      {{else}}
        <span class="text-ink-mid">new channel</span>
      {{end}}
    {{else}}
      <a href="/settings">Settings</a><span class="sep">/</span>
      <span class="text-ink-mid">notifications</span>
    {{end}}
  </div>

  {{/* ---------- page header ---------- */}}
  <div class="flex items-baseline justify-between mt-3.5">
    {{if $page.Form}}
      <h1 class="text-[22px] font-medium tracking-[-0.005em]">
        {{if $page.Form.ID}}Edit channel · <span class="mono text-ink-mid">{{$page.Form.Name}}</span>{{else}}Add channel{{end}}
      </h1>
    {{else}}
      <h1 class="text-[22px] font-medium tracking-[-0.005em]">Settings</h1>
      <a href="/settings/notifications/new" class="btn btn-primary">+ Add channel</a>
    {{end}}
  </div>

  {{/* ---------- sub-tab nav ---------- */}}
  <div class="flex items-end mt-3.5 border-b border-line-soft">
    <a class="sub-tab {{if eq $page.ActiveTab "notifications"}}active{{end}}" href="/settings/notifications">
      Notifications
      {{if not $page.Form}}<span class="mono text-ink-fade text-[11px] ml-1">{{len $page.Channels}}</span>{{end}}
    </a>
    <a href="/settings/users" class="sub-tab {{if eq $page.ActiveTab "users"}}active{{end}}">Users</a>
    <span class="sub-tab text-ink-fade cursor-default" title="lands later">Authentication</span>
  </div>

  {{/* ---------- sub-tab body ---------- */}}
  <div class="mt-5">
    {{if $page.Form}}
      {{template "notification_edit_form" $page}}
    {{else}}
      {{template "notification_list_body" $page}}
    {{end}}
  </div>

</div>
{{end}}

{{/* ================================================================
     notification_list_body — channel list (embedded in settings.html)
     Receives $page (settingsPage).
     ================================================================ */}}
{{define "notification_list_body"}}
  <p class="text-[12.5px] text-ink-mute mb-4 leading-[1.6] max-w-[720px]">
    Notification channels fire when the alert engine raises an alert.
    All channels apply globally — every alert that meets the engine's thresholds is sent to every enabled channel.
  </p>

  {{if not .Channels}}
    <div class="empty-state mt-2">
      <h3 class="text-[16px] font-medium">No channels configured.</h3>
      <p class="text-ink-mute text-[13px] mt-2 mx-auto max-w-[480px] leading-[1.6]">
        Alerts are still raised in the dashboard, but nothing is pushed to chat / phone / email.
        Add a channel to get notified.
      </p>
      <div class="mt-5">
        <a href="/settings/notifications/new" class="btn btn-primary">+ Add your first channel</a>
      </div>
    </div>
  {{else}}
    <div class="panel rounded-[7px] overflow-hidden">
      <div class="ch-row head">
        <div></div>
        <div>Name</div>
        <div>Endpoint</div>
        <div>Enabled</div>
        <div>Last fired</div>
        <div></div>
      </div>
      {{range .Channels}}
        {{$ch := .}}
        <div class="ch-row clickable">
          <a class="row-link" href="/settings/notifications/{{$ch.ID}}/edit">edit {{$ch.Name}}</a>
          <div>
            {{if eq $ch.Kind "webhook"}}<span class="ch-icon webhook">WH</span>
            {{else if eq $ch.Kind "ntfy"}}<span class="ch-icon ntfy">NT</span>
            {{else}}<span class="ch-icon smtp">@</span>{{end}}
          </div>
          <div class="text-ink font-medium">{{$ch.Name}}</div>
          <div class="mono text-ink-mute" style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
            {{if eq $ch.Kind "webhook"}}webhook · click to edit{{else if eq $ch.Kind "ntfy"}}ntfy · click to edit{{else}}smtp · click to edit{{end}}
          </div>
          <div class="row-action">
            {{if $ch.Enabled}}
              <span class="toggle on" hx-post="/settings/notifications/{{$ch.ID}}/toggle"
                    hx-target="this" hx-swap="outerHTML"
                    onclick="event.stopPropagation()" style="cursor:pointer"
                    title="click to disable"></span>
            {{else}}
              <span class="toggle" hx-post="/settings/notifications/{{$ch.ID}}/toggle"
                    hx-target="this" hx-swap="outerHTML"
                    onclick="event.stopPropagation()" style="cursor:pointer"
                    title="click to enable"></span>
            {{end}}
          </div>
          <div class="mono text-ink-mid">
            {{if $ch.LastFiredAt}}{{relTime $ch.LastFiredAt}}{{else}}<span class="text-ink-fade">never</span>{{end}}
          </div>
          <div class="row-action flex gap-1.5 justify-end">
            <a href="/settings/notifications/{{$ch.ID}}/edit" class="btn">Edit</a>
            <a href="/settings/notifications/{{$ch.ID}}/edit#delete-panel" class="btn btn-danger">Delete</a>
          </div>
        </div>
      {{end}}
    </div>
  {{end}}
{{end}}

{{/* ================================================================
     notification_edit_form — create/edit form (embedded in settings.html)
     Receives $page (settingsPage).
     ================================================================ */}}
{{define "notification_edit_form"}}
{{$f := .Form}}
{{$isEdit := ne $f.ID ""}}

  {{if .FormError}}
    <div class="rounded-[6px] px-3.5 py-3 text-[13px] mb-4"
         style="border: 1px solid color-mix(in oklch, var(--bad), transparent 60%); background: color-mix(in oklch, var(--bad), transparent 92%);">
      {{.FormError}}
    </div>
  {{end}}
  {{if .DeleteError}}
    <div class="rounded-[6px] px-3.5 py-3 text-[13px] mb-4"
         style="border: 1px solid color-mix(in oklch, var(--bad), transparent 60%); background: color-mix(in oklch, var(--bad), transparent 92%);">
      {{.DeleteError}}
    </div>
  {{end}}

  <div class="grid gap-6 items-start" style="grid-template-columns: 1fr 380px;">
    <div>

      {{/* ---------- kind picker ---------- */}}
      <div class="mb-5">
        <div class="field-label mb-2.5">Channel kind</div>
        <div class="kind-grid">

          {{/* Webhook card */}}
          <label class="kind-card {{if eq $f.Kind "webhook"}}selected{{end}}">
            <input type="radio" name="kind" value="webhook" class="hidden kind-radio"
                   {{if eq $f.Kind "webhook"}}checked{{end}} />
            <div class="flex items-center gap-3">
              <span class="radio-pip {{if eq $f.Kind "webhook"}}on{{end}}"></span>
              <span class="ch-icon webhook">WH</span>
              <div>
                <div class="text-ink text-[13px] font-medium">Webhook</div>
                <div class="text-ink-mute text-[11.5px] mt-0.5">POST a JSON envelope to your URL.</div>
              </div>
            </div>
          </label>

          {{/* Ntfy card */}}
          <label class="kind-card {{if eq $f.Kind "ntfy"}}selected{{end}}" style="{{if eq $f.Kind "ntfy"}}border-color: color-mix(in oklch, var(--warn), transparent 50%); background: color-mix(in oklch, var(--warn), transparent 95%);{{end}}">
            <input type="radio" name="kind" value="ntfy" class="hidden kind-radio"
                   {{if eq $f.Kind "ntfy"}}checked{{end}} />
            <div class="flex items-center gap-3">
              <span class="radio-pip {{if eq $f.Kind "ntfy"}}on{{end}}" style="{{if eq $f.Kind "ntfy"}}border-color: var(--warn);{{end}}"></span>
              <span class="ch-icon ntfy">NT</span>
              <div>
                <div class="text-ink text-[13px] font-medium">Ntfy</div>
                <div class="text-ink-mute text-[11.5px] mt-0.5">Push to ntfy.sh or your self-hosted ntfy server.</div>
              </div>
            </div>
          </label>

          {{/* SMTP card */}}
          <label class="kind-card {{if eq $f.Kind "smtp"}}selected{{end}}" style="{{if eq $f.Kind "smtp"}}border-color: color-mix(in oklch, var(--ok), transparent 50%); background: color-mix(in oklch, var(--ok), transparent 95%);{{end}}">
            <input type="radio" name="kind" value="smtp" class="hidden kind-radio"
                   {{if eq $f.Kind "smtp"}}checked{{end}} />
            <div class="flex items-center gap-3">
              <span class="radio-pip {{if eq $f.Kind "smtp"}}on{{end}}" style="{{if eq $f.Kind "smtp"}}border-color: var(--ok);{{end}}"></span>
              <span class="ch-icon smtp">@</span>
              <div>
                <div class="text-ink text-[13px] font-medium">SMTP email</div>
                <div class="text-ink-mute text-[11.5px] mt-0.5">Plain-text email via your SMTP relay.</div>
              </div>
            </div>
          </label>

        </div>
      </div>

      {{/* ---------- per-kind fields ---------- */}}
      {{if $isEdit}}
        <form method="post" action="/settings/notifications/{{$f.ID}}/edit" id="ch-form">
      {{else}}
        <form method="post" action="/settings/notifications/new" id="ch-form">
      {{end}}

      {{/* hidden kind field updated by JS */}}
      <input type="hidden" name="kind" id="kind-hidden" value="{{$f.Kind}}" />

      {{/* Webhook fields */}}
      <div id="fields-webhook" class="{{if ne $f.Kind "webhook"}}hidden{{end}}">
        <div class="panel rounded-[7px] p-[18px] space-y-4">
          <div>
            <label class="field-label" for="wh-name">Name</label>
            <input id="wh-name" name="name" type="text" class="field"
                   value="{{if eq $f.Kind "webhook"}}{{$f.Name}}{{end}}"
                   placeholder="e.g. team-slack-bridge" />
            <div class="field-help">Operator-friendly label shown in the channel list and audit log.</div>
          </div>
          <div>
            <label class="field-label" for="wh-url">URL</label>
            <input id="wh-url" name="webhook_url" type="url" class="field mono"
                   value="{{$f.WebhookURL}}" placeholder="https://hooks.example.com/…" />
            <div class="field-help">We POST the JSON envelope shown on the right. 5s timeout; failures are logged but not retried.</div>
          </div>
          <div>
            <label class="field-label" for="wh-bearer">Bearer token <span class="text-ink-fade font-normal">· optional</span></label>
            <input id="wh-bearer" name="webhook_bearer_token" type="password" class="field mono"
                   placeholder="{{if and $isEdit (eq $f.Kind "webhook")}}•••••••• · stored, leave blank to keep{{else}}leave blank if not needed{{end}}" />
            <div class="field-help">If set, sent as <span class="mono text-ink-mid">Authorization: Bearer …</span> on every POST.</div>
          </div>
          <div>
            <label class="field-label">Custom header <span class="text-ink-fade font-normal">· optional</span></label>
            <div class="grid grid-cols-2 gap-2.5">
              <input type="text" name="webhook_header_name" class="field mono"
                     value="{{$f.WebhookHeaderName}}" placeholder="X-Header-Name" />
              <input type="text" name="webhook_header_value" class="field mono"
                     placeholder="value" />
            </div>
            <div class="field-help">Single extra header in v1.</div>
          </div>
        </div>
      </div>

      {{/* Ntfy fields */}}
      <div id="fields-ntfy" class="{{if ne $f.Kind "ntfy"}}hidden{{end}}">
        <div class="panel rounded-[7px] p-[18px] space-y-4">
          <div>
            <label class="field-label" for="nt-name">Name</label>
            <input id="nt-name" name="name" type="text" class="field"
                   value="{{if eq $f.Kind "ntfy"}}{{$f.Name}}{{end}}"
                   placeholder="e.g. phone-bzzt" />
          </div>
          <div class="grid grid-cols-2 gap-3.5">
            <div>
              <label class="field-label" for="nt-server">Server URL</label>
              <input id="nt-server" name="ntfy_server_url" type="url" class="field mono"
                     value="{{if $f.NtfyServerURL}}{{$f.NtfyServerURL}}{{else}}https://ntfy.sh{{end}}" />
              <div class="field-help">Default <span class="mono">https://ntfy.sh</span>; change for self-hosted.</div>
            </div>
            <div>
              <label class="field-label" for="nt-topic">Topic</label>
              <input id="nt-topic" name="ntfy_topic" type="text" class="field mono"
                     value="{{$f.NtfyTopic}}" placeholder="restic-manager-fleet" />
              <div class="field-help">Subscribe to this topic in the ntfy app.</div>
            </div>
          </div>
          <div>
            <label class="field-label" for="nt-token">Access token <span class="text-ink-fade font-normal">· optional</span></label>
            <input id="nt-token" name="ntfy_access_token" type="password" class="field mono"
                   placeholder="{{if and $isEdit (eq $f.Kind "ntfy")}}tk_… · stored, leave blank to keep{{else}}tk_… · required for protected topics{{end}}" />
            <div class="field-help">Use this OR username+password below. Token wins when both are set.</div>
          </div>
          <div class="grid grid-cols-2 gap-3.5">
            <div>
              <label class="field-label" for="nt-user">Username <span class="text-ink-fade font-normal">· optional</span></label>
              <input id="nt-user" name="ntfy_username" type="text" class="field mono"
                     value="{{$f.NtfyUsername}}" placeholder="ntfy basic-auth user" />
            </div>
            <div>
              <label class="field-label" for="nt-pass">Password <span class="text-ink-fade font-normal">· optional</span></label>
              <input id="nt-pass" name="ntfy_password" type="password" class="field mono"
                     placeholder="{{if and $isEdit (eq $f.Kind "ntfy")}}stored, leave blank to keep{{else}}ntfy basic-auth password{{end}}" />
              <div class="field-help">Sent as HTTP Basic auth when no token is set.</div>
            </div>
          </div>
          <div>
            <label class="field-label" for="nt-priority">Default priority</label>
            <select id="nt-priority" name="default_priority" class="field">
              <option value="default" {{if eq $f.DefaultPriority "default"}}selected{{end}}>default</option>
              <option value="min"     {{if eq $f.DefaultPriority "min"}}selected{{end}}>min</option>
              <option value="low"     {{if eq $f.DefaultPriority "low"}}selected{{end}}>low</option>
              <option value="high"    {{if eq $f.DefaultPriority "high"}}selected{{end}}>high · maps to severity=warning</option>
              <option value="urgent"  {{if eq $f.DefaultPriority "urgent"}}selected{{end}}>urgent · maps to severity=critical</option>
            </select>
            <div class="field-help">Per-alert severity overrides this — critical alerts always go out at urgent regardless of the default.</div>
          </div>
        </div>
      </div>

      {{/* SMTP fields */}}
      <div id="fields-smtp" class="{{if ne $f.Kind "smtp"}}hidden{{end}}">
        <div class="panel rounded-[7px] p-[18px] space-y-4">
          <div>
            <label class="field-label" for="sm-name">Name</label>
            <input id="sm-name" name="name" type="text" class="field"
                   value="{{if eq $f.Kind "smtp"}}{{$f.Name}}{{end}}"
                   placeholder="e.g. overnight-digest" />
            <div class="field-help">One channel = one recipient — add another channel for a second mailbox.</div>
          </div>
          <div class="grid gap-3.5" style="grid-template-columns: 2fr 1fr 1fr;">
            <div>
              <label class="field-label" for="sm-host">SMTP host</label>
              <input id="sm-host" name="smtp_host" type="text" class="field mono"
                     value="{{$f.SMTPHost}}" placeholder="smtp.example.com" />
            </div>
            <div>
              <label class="field-label" for="sm-port">Port</label>
              <input id="sm-port" name="smtp_port" type="number" class="field mono"
                     value="{{if $f.SMTPPort}}{{$f.SMTPPort}}{{else}}587{{end}}" min="1" max="65535" />
            </div>
            <div>
              <label class="field-label" for="sm-enc">Encryption</label>
              <select id="sm-enc" name="smtp_encryption" class="field">
                <option value="starttls" {{if eq $f.SMTPEncryption "starttls"}}selected{{end}}>STARTTLS · 587</option>
                <option value="tls"      {{if eq $f.SMTPEncryption "tls"}}selected{{end}}>Implicit TLS · 465</option>
                <option value="none"     {{if eq $f.SMTPEncryption "none"}}selected{{end}}>None · 25 (plain)</option>
              </select>
            </div>
          </div>
          <div class="grid grid-cols-2 gap-3.5">
            <div>
              <label class="field-label" for="sm-user">Username</label>
              <input id="sm-user" name="smtp_username" type="text" class="field mono"
                     value="{{$f.SMTPUsername}}" placeholder="alerts@example.com" />
            </div>
            <div>
              <label class="field-label" for="sm-pass">Password</label>
              <input id="sm-pass" name="smtp_password" type="password" class="field mono"
                     placeholder="{{if and $isEdit (eq $f.Kind "smtp")}}•••••••• · stored, leave blank to keep{{else}}app password{{end}}" />
              <div class="field-help">App password recommended for Gmail / M365.</div>
            </div>
          </div>
          <div class="grid grid-cols-2 gap-3.5">
            <div>
              <label class="field-label" for="sm-from">From</label>
              <input id="sm-from" name="smtp_from" type="text" class="field mono"
                     value="{{$f.SMTPFrom}}" placeholder="Restic-Manager &lt;alerts@example.com&gt;" />
            </div>
            <div>
              <label class="field-label" for="sm-to">To</label>
              <input id="sm-to" name="smtp_to" type="text" class="field mono"
                     value="{{$f.SMTPTo}}" placeholder="ops@example.com" />
              <div class="field-help">Single address or distribution list.</div>
            </div>
          </div>
        </div>
      </div>

      {{/* ---------- enabled + test ---------- */}}
      <div class="panel rounded-[7px] p-[18px] mt-3.5">
        <div class="flex items-center gap-3">
          <label class="flex items-center gap-3 cursor-pointer">
            <input type="hidden" name="enabled" value="0" />
            <input type="checkbox" name="enabled" value="1" {{if $f.Enabled}}checked{{end}}
                   class="hidden enabled-check" id="enabled-check" />
            <span class="toggle {{if $f.Enabled}}on{{end}}" id="enabled-toggle"></span>
          </label>
          <div>
            <div class="text-ink text-[13px]">Enabled</div>
            <div class="text-ink-mute text-[11.5px] mt-0.5">When off, this channel is skipped on alert dispatch.</div>
          </div>
        </div>

        {{if $isEdit}}
          <div class="mt-4 pt-4 border-t border-line-soft">
            <div class="flex items-center gap-3">
              <button type="button" class="btn"
                      hx-post="/api/notifications/{{$f.ID}}/test"
                      hx-target="#test-result"
                      hx-swap="innerHTML">Send test notification</button>
              <div id="test-result"></div>
            </div>
            <div class="text-[11.5px] text-ink-fade mt-2">
              Sends severity=info, kind=test_notification, message="Test from restic-manager".
            </div>
          </div>
        {{end}}
      </div>

      {{/* ---------- action row ---------- */}}
      <div class="mt-5 flex items-center justify-between">
        <a href="/settings/notifications" class="btn">Cancel</a>
        <div class="flex gap-2">
          {{if $isEdit}}
            <button type="button" class="btn btn-danger" id="delete-btn"
                    onclick="document.getElementById('delete-panel').classList.toggle('hidden')">Delete channel…</button>
          {{end}}
          <button type="submit" class="btn btn-primary btn-lg">
            {{if $isEdit}}Save changes{{else}}Create channel{{end}}
          </button>
        </div>
      </div>

      {{/* ---------- typed-confirm delete ---------- */}}
      </form>{{/* close ch-form — delete panel must live OUTSIDE because HTML forbids nested forms */}}

      {{if $isEdit}}
        <div id="delete-panel" class="hidden mt-4 panel rounded-[7px] p-[18px]"
             style="border-color: color-mix(in oklch, var(--bad), transparent 60%);">
          <div class="text-[13px] font-medium text-bad mb-2">Delete channel</div>
          <p class="text-[12.5px] text-ink-mute mb-3 leading-[1.55]">
            Type the channel name to confirm permanent deletion. This cannot be undone.
          </p>
          <form method="post" action="/settings/notifications/{{$f.ID}}/delete">
            <input type="text" name="confirm_name" class="field mono mb-3"
                   placeholder="{{$f.Name}}" autocomplete="off" />
            <button type="submit" class="btn btn-danger">Delete permanently</button>
          </form>
        </div>
      {{end}}
    </div>

    {{/* ---------- right rail — payload preview ----------
         All three are rendered; the kind-switcher JS toggles which is
         visible. Server-side {{if}} would freeze the panel at whichever
         kind was loaded, so flipping the picker leaves it stale. */}}
    <aside>
      <div id="preview-webhook" class="{{if ne $f.Kind "webhook"}}hidden{{end}}">
        <div class="panel rounded-[7px] p-4">
          <div class="text-[11px] text-ink-fade uppercase tracking-[0.08em] mb-2.5">Payload preview</div>
          <div class="text-[12.5px] text-ink-mute mb-3 leading-[1.6]">
            Every alert raise POSTs this JSON envelope.
            Switch on <span class="mono text-ink-mid">severity</span> or
            <span class="mono text-ink-mid">kind</span> in your bridge.
          </div>
          <div class="snippet">
            <div class="snippet-head">application/json</div>
            <pre>{
  "event":       "alert.raised",
  "alert_id":    "01KQTABCDEFGHJ",
  "severity":    "warning",
  "kind":        "backup_failed",
  "host_id":     "01KQPCD5T1QRYH9",
  "host_name":   "alfa-01",
  "message":     "Backup 'system-config' failed: …",
  "raised_at":   "2026-05-04T15:42:01Z",
  "link":        "https://restic-manager.example/alerts/01KQTABCDEFGHJ"
}</pre>
          </div>
          <div class="text-[11px] text-ink-fade mt-2.5 leading-[1.55]">
            On <span class="mono text-ink-mid">alert.acknowledged</span> /
            <span class="mono text-ink-mid">alert.resolved</span> the same shape is sent
            with the updated event field.
          </div>
        </div>
      </div>
      <div id="preview-ntfy" class="{{if ne $f.Kind "ntfy"}}hidden{{end}}">
        <div class="panel rounded-[7px] p-4">
          <div class="text-[11px] text-ink-fade uppercase tracking-[0.08em] mb-2.5">Ntfy delivery shape</div>
          <div class="text-[12.5px] text-ink-mute mb-3 leading-[1.6]">
            Ntfy POSTs use the standard publish format — title, body, click-URL, tags.
            Tap the notification to open the alert in the UI.
          </div>
          <div class="snippet">
            <div class="snippet-head">POST /&lt;topic&gt; HTTP/1.1</div>
            <pre>Host: ntfy.sh

Title:    [warning] alfa-01 backup failed
Priority: 4
Tags:     warning,backup_failed
Click:    https://restic-manager.example/alerts/01KQTABCDEFGHJ

Backup 'system-config' failed: rest-server returned 401</pre>
          </div>
        </div>
      </div>
      <div id="preview-smtp" class="{{if ne $f.Kind "smtp"}}hidden{{end}}">
        <div class="panel rounded-[7px] p-4">
          <div class="text-[11px] text-ink-fade uppercase tracking-[0.08em] mb-2.5">Email shape</div>
          <div class="text-[12.5px] text-ink-mute mb-3 leading-[1.6]">
            Plain text only in v1. Message-ID includes the alert id so the
            raised → acknowledged → resolved exchange threads in mail clients.
          </div>
          <div class="snippet">
            <div class="snippet-head">RFC 5322 message</div>
            <pre>From: Restic-Manager &lt;alerts@example.com&gt;
To: ops-overnight@example.com
Subject: [restic-manager] [warning] alfa-01: backup_failed
Message-ID: &lt;01KQTABCDEFGHJ@restic-manager.example&gt;
Date: Mon, 04 May 2026 15:42:01 +0000

Backup 'system-config' failed: rest-server returned 401

—
Raised at: 2026-05-04T15:42:01Z
Severity:  warning
Host:      alfa-01
Kind:      backup_failed

Open in restic-manager:
https://restic-manager.example/alerts/01KQTABCDEFGHJ</pre>
          </div>
        </div>
      </div>
    </aside>

  </div>

{{/* JS: kind-picker interactivity + enabled toggle + HTMX test-result rendering */}}
<script>
(function() {
  var kinds = ['webhook', 'ntfy', 'smtp'];

  // Kind switcher
  var radios = document.querySelectorAll('.kind-radio');
  radios.forEach(function(radio) {
    radio.closest('label').addEventListener('click', function() {
      var kind = radio.value;
      document.getElementById('kind-hidden').value = kind;

      // Show/hide field panels + matching right-rail payload preview.
      kinds.forEach(function(k) {
        var fields  = document.getElementById('fields-'  + k);
        var preview = document.getElementById('preview-' + k);
        if (fields)  fields .classList.toggle('hidden', k !== kind);
        if (preview) preview.classList.toggle('hidden', k !== kind);
      });

      // Update card styles
      radios.forEach(function(r) {
        var card = r.closest('label');
        var pip  = card.querySelector('.radio-pip');
        var k    = r.value;
        card.classList.toggle('selected', k === kind);
        if (k === kind) {
          r.checked = true;
          if (pip) pip.classList.add('on');
          if (k === 'webhook') { card.style.borderColor = ''; card.style.background = ''; }
          else if (k === 'ntfy')    { card.style.borderColor = 'color-mix(in oklch, var(--warn), transparent 50%)'; card.style.background = 'color-mix(in oklch, var(--warn), transparent 95%)'; }
          else if (k === 'smtp')    { card.style.borderColor = 'color-mix(in oklch, var(--ok),   transparent 50%)'; card.style.background = 'color-mix(in oklch, var(--ok),   transparent 95%)'; }
        } else {
          if (pip) pip.classList.remove('on');
          pip && (pip.style.borderColor = '');
          card.style.borderColor = '';
          card.style.background  = '';
        }
      });
    });
  });

  // Enabled toggle: the visual <span class="toggle"> is inside a <label>
  // wrapping a hidden checkbox, so clicking the span already flips the
  // checkbox via the label's native behaviour. We only need to mirror
  // that into the .on class — listening on the toggle's own click would
  // race the label and cancel out, leaving check.checked at its original
  // value (so Save would persist the unchanged setting).
  var check = document.getElementById('enabled-check');
  var tog   = document.getElementById('enabled-toggle');
  if (check && tog) {
    check.addEventListener('change', function() {
      tog.classList.toggle('on', check.checked);
    });
  }

  // HTMX test-result: render JSON from the API as a coloured pill
  document.body.addEventListener('htmx:afterRequest', function(evt) {
    if (!evt.detail.elt || !evt.detail.elt.hasAttribute('hx-target')) return;
    if (evt.detail.elt.getAttribute('hx-target') !== '#test-result') return;
    var target = document.getElementById('test-result');
    if (!target) return;
    try {
      var data = JSON.parse(evt.detail.xhr.responseText);
      if (data.ok) {
        target.innerHTML = '<span class="test-pill test-pill-ok">✓ delivered' +
          (data.latency_ms ? ' · ' + data.latency_ms + ' ms' : '') +
          (data.status_code ? ' · HTTP ' + data.status_code : '') + '</span>';
      } else {
        var msg = (data.error || 'unknown error');
        target.innerHTML = '<span class="test-pill test-pill-fail">✗ failed · ' + msg + '</span>';
      }
    } catch(e) {
      target.innerHTML = '<span class="test-pill test-pill-fail">✗ unexpected response</span>';
    }
  });
})();
</script>
{{end}}
