<!-- SPEC: PJ2026-010405 云端控制台. -->
<!-- Implementation reference: draft-2026-07-13-p0-cloud-console. -->
<script setup lang="ts">
import { Cpu, Grid2X2, List, Rows3, Rows4 } from "lucide-vue-next";
import { computed, onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { providerProfilesAPI } from "@/api";
import ApiErrorDiagnostic from "@/components/common/ApiErrorDiagnostic.vue";
import AsyncBoundary from "@/components/common/AsyncBoundary.vue";
import BaseDialog from "@/components/common/BaseDialog.vue";
import ConfirmDialog from "@/components/common/ConfirmDialog.vue";
import ContentViewer from "@/components/common/ContentViewer.vue";
import DataGrid from "@/components/common/DataGrid.vue";
import type { DataGridColumn } from "@/components/common/DataGrid.vue";
import EmptyState from "@/components/common/EmptyState.vue";
import EntityCard from "@/components/common/EntityCard.vue";
import ResourceCollection from "@/components/common/ResourceCollection.vue";
import ViewModeSwitch from "@/components/console/ViewModeSwitch.vue";
import PageCommandBar from "@/components/layout/PageCommandBar.vue";
import TablePageLayout from "@/components/layout/TablePageLayout.vue";
import { useForm } from "@/composables/useForm";
import { useConsoleViewState } from "@/composables/useConsoleViewState";
import { useTableLoader } from "@/composables/useTableLoader";
import { mergeProviderRow, normalizeProviderConfig, normalizeProviderProfilePayload, normalizeProviderProfiles, normalizeProviderValidation, orderProviderProfiles, validationComplete, type ProviderConfigView, type ProviderProfileRow, type ProviderValidationView } from "@/stores/provider-profiles-view";
import type { ApiError, ErrorDiagnostic, ProviderProfile } from "@/types";

const columns: DataGridColumn[] = [
  { key: "profile", label: "Profile" },
  { key: "configured", label: "状态" },
  { key: "secret", label: "SecretRef" },
  { key: "hash", label: "Fingerprint" },
  { key: "bridge", label: "Bridge" },
  { key: "validation", label: "Validation" },
  { key: "actions", label: "操作", align: "right" }
];

const route = useRoute();
const router = useRouter();
const viewState = useConsoleViewState({ filter: "all" });
const table = useTableLoader<ProviderProfileRow>(loadProfiles);
const selectedProfile = ref<ProviderProfileRow | null>(null);
const credentialDialogOpen = ref(false);
const configDialogOpen = ref(false);
const removeDialogOpen = ref(false);
const testDialogOpen = ref(false);
const apiKeyInput = ref("");
const configText = ref("");
const testModel = ref("");
const testPrompt = ref("");
const configInfo = ref<ProviderConfigView | null>(null);
const validation = ref<ProviderValidationView | null>(null);
const testResult = ref<ProviderValidationView | null>(null);
const validationError = ref<string | null>(null);
const validationApiError = ref<ApiError | null>(null);
const validationDiagnostic = ref<ErrorDiagnostic | null>(null);
const validatingProfile = ref<string | null>(null);
const credentialForm = useForm();
const configForm = useForm();
const removeForm = useForm();
const testForm = useForm();

const rows = computed(() => orderProviderProfiles(table.rows.value));
const query = computed({
  get: () => viewState.q.value,
  set: (value: string) => void viewState.update({ q: value.trim() })
});
const statusFilter = computed({
  get: () => viewState.filter.value || "all",
  set: (value: string) => void viewState.update({ filter: value === "all" ? "" : value })
});
const viewMode = computed<"cards" | "list">({
  get: () => viewState.view.value,
  set: (value) => void viewState.update({ view: value === "cards" ? undefined : value })
});
const density = computed<"compact" | "comfortable">({
  get: () => viewState.density.value,
  set: (value) => void viewState.update({ density: value === "comfortable" ? undefined : value })
});
const filteredRows = computed(() => {
  const needle = query.value.trim().toLowerCase();
  return rows.value.filter((row) => {
    const configured = row.configured ? "configured" : "missing";
    if (statusFilter.value !== "all" && statusFilter.value !== configured) return false;
    return !needle || [row.profile, row.secretRefText, row.bridgeText, row.validationStatus, row.failureKind].join(" ").toLowerCase().includes(needle);
  });
});
const tableState = computed(() => {
  if (table.loading.value) return rows.value.length ? "refreshing" : "initial-loading";
  if (table.error.value) return rows.value.length ? "partial" : "error";
  return rows.value.length ? "ready" : "empty";
});

onMounted(async () => {
  await table.reload();
  restoreSelectedProfile();
});
watch(() => route.params.profile, restoreSelectedProfile);

async function loadProfiles(): Promise<ProviderProfileRow[]> {
  const response = await providerProfilesAPI.list();
  if (!response.ok) throw response;
  return normalizeProviderProfiles(response.data);
}

function rowKey(row: ProviderProfileRow): string {
  return row.profile;
}

function openCredential(row: ProviderProfileRow): void {
  selectProfile(row);
  selectedProfile.value = row;
  apiKeyInput.value = "";
  credentialDialogOpen.value = true;
}

function openRemove(row: ProviderProfileRow): void {
  selectProfile(row);
  selectedProfile.value = row;
  removeDialogOpen.value = true;
  removeForm.error.value = null;
}

function openTest(row: ProviderProfileRow): void {
  selectProfile(row);
  selectedProfile.value = row;
  testModel.value = "";
  testPrompt.value = `请用一句中文回复：HWLAB provider profile ${row.profile} 测试通过。`;
  testResult.value = null;
  testForm.error.value = null;
  testForm.apiError.value = null;
  testForm.diagnostic.value = null;
  testDialogOpen.value = true;
}

async function saveCredential(): Promise<void> {
  const row = selectedProfile.value;
  if (!row || !apiKeyInput.value.trim()) return;
  const ok = await credentialForm.submit(async () => {
    const response = await providerProfilesAPI.setKey(row.profile, apiKeyInput.value);
    if (!response.ok) throw response;
    table.rows.value = mergeProviderRow(table.rows.value, normalizeProviderProfilePayload(response.data));
  }, "Credential updated");
  if (ok) {
    apiKeyInput.value = "";
    credentialDialogOpen.value = false;
  }
}

async function openConfig(row: ProviderProfileRow): Promise<void> {
  selectProfile(row);
  selectedProfile.value = row;
  configDialogOpen.value = true;
  configForm.error.value = null;
  configForm.apiError.value = null;
  configForm.diagnostic.value = null;
  configInfo.value = null;
  configText.value = "";
  const response = await providerProfilesAPI.config(row.profile);
  if (!response.ok) {
    configForm.error.value = response.error ?? `HTTP ${response.status}`;
    configForm.apiError.value = response.apiError ?? null;
    configForm.diagnostic.value = response.diagnostic ?? null;
    return;
  }
  const config = normalizeProviderConfig(response.data, row.profile);
  configInfo.value = config;
  configText.value = config.configToml;
}

async function saveConfig(): Promise<void> {
  const row = selectedProfile.value;
  if (!row) return;
  const ok = await configForm.submit(async () => {
    const response = await providerProfilesAPI.setConfig(row.profile, configText.value);
    if (!response.ok) throw response;
    table.rows.value = mergeProviderRow(table.rows.value, normalizeProviderProfilePayload(response.data));
  }, "Config updated");
  if (ok) configDialogOpen.value = false;
}

async function removeProfile(): Promise<void> {
  const row = selectedProfile.value;
  if (!row) return;
  const ok = await removeForm.submit(async () => {
    const response = await providerProfilesAPI.remove(row.profile);
    if (!response.ok) throw response;
    table.rows.value = table.rows.value.filter((item) => item.profile !== row.profile);
  }, "Profile removed");
  if (ok) {
    removeDialogOpen.value = false;
    selectedProfile.value = null;
  }
}

async function validateProfile(row: ProviderProfileRow): Promise<void> {
  selectProfile(row);
  validatingProfile.value = row.profile;
  validationError.value = null;
  validationApiError.value = null;
  validationDiagnostic.value = null;
  validation.value = null;
  const submit = await providerProfilesAPI.validate(row.profile);
  if (!submit.ok) {
    validationError.value = submit.error ?? `HTTP ${submit.status}`;
    validationApiError.value = submit.apiError ?? null;
    validationDiagnostic.value = submit.diagnostic ?? null;
    validatingProfile.value = null;
    return;
  }
  let current = normalizeProviderValidation(submit.data, row.profile);
  validation.value = current;
  const validationId = current.validationId;
  for (let attempt = 0; validationId && attempt < 30 && !validationComplete(current.status); attempt += 1) {
    await delay(2000);
    const poll = await providerProfilesAPI.validation(row.profile, validationId);
    if (!poll.ok) {
      validationError.value = poll.error ?? `HTTP ${poll.status}`;
      validationApiError.value = poll.apiError ?? null;
      validationDiagnostic.value = poll.diagnostic ?? null;
      break;
    }
    current = normalizeProviderValidation(poll.data, row.profile);
    validation.value = current;
  }
  validatingProfile.value = null;
  void table.reload();
}

async function runRealTest(): Promise<void> {
  const row = selectedProfile.value;
  if (!row || !testModel.value.trim() || !testPrompt.value.trim()) return;
  testResult.value = null;
  await testForm.submit(async () => {
    const submit = await providerProfilesAPI.test(row.profile, testModel.value.trim(), testPrompt.value.trim());
    if (!submit.ok) throw submit;
    let current = normalizeProviderValidation(submit.data, row.profile);
    testResult.value = current;
    const validationId = current.validationId;
    for (let attempt = 0; validationId && attempt < 45 && !validationComplete(current.status); attempt += 1) {
      await delay(2000);
      const poll = await providerProfilesAPI.validation(row.profile, validationId);
      if (!poll.ok) throw poll;
      current = normalizeProviderValidation(poll.data, row.profile);
      testResult.value = current;
    }
  }, "Profile test finished");
}

function delay(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

function displayDate(value: string): string {
  if (!value) return "-";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" });
}

function selectProfile(row: ProviderProfileRow): void {
  selectedProfile.value = row;
  if (route.params.profile !== row.profile) void router.push({ name: "ProviderProfileDetail", params: { profile: row.profile }, query: route.query });
}

function restoreSelectedProfile(): void {
  const profile = typeof route.params.profile === "string" ? route.params.profile : "";
  selectedProfile.value = profile ? rows.value.find((row) => row.profile === profile) ?? null : null;
}

</script>

<template>
  <section class="route-stack provider-admin-page">
    <PageCommandBar eyebrow="Admin" title="Provider Profiles" description="Provider credential/config 由 Cloud API 鉴权后委托 AgentRun；页面只显示 SecretRef、fingerprint 和 validation 摘要。" />
    <AsyncBoundary :state="tableState" :has-content="Boolean(rows.length)" label="加载 Provider Profiles" empty-title="暂无 Provider Profile" empty-description="Provider Profile API 当前未返回任何条目。" @retry="table.reload">
      <template #error><section class="data-panel admin-crud-panel">
        <EmptyState title="Provider Profiles 加载失败" :description="table.error.value || '请求未完成'" :api-error="table.apiError.value" :diagnostic="table.diagnostic.value" action-label="重试" @action="table.reload" />
        <p class="muted-box">当前错误会保留为委托链路状态，不再用 raw JSON dump 作为页面主体。</p>
      </section></template>
    <TablePageLayout title="Profiles" subtitle="AgentRun provider profile registry；API 未提供 cursor，本页展示当前响应全集。">
      <template #actions>
        <button class="table-action" type="button" :disabled="table.loading.value" @click="table.reload">刷新</button>
      </template>
      <template #filters>
        <div class="provider-filter-bar">
          <label><span>状态</span><select v-model="statusFilter"><option value="all">全部</option><option value="configured">configured</option><option value="missing">missing</option></select></label>
          <label><span>搜索</span><input v-model="query" type="search" placeholder="profile、SecretRef、bridge 或 validation" /></label>
          <ViewModeSwitch :model-value="viewMode" :options="[{ value: 'cards', label: '卡片', icon: Grid2X2 }, { value: 'list', label: '列表', icon: List }]" label="Provider 显示模式" @update:model-value="viewMode = $event as 'cards' | 'list'" />
          <ViewModeSwitch :model-value="density" :options="[{ value: 'comfortable', label: '舒适密度', icon: Rows4 }, { value: 'compact', label: '紧凑密度', icon: Rows3 }]" label="Provider 显示密度" @update:model-value="density = $event as 'compact' | 'comfortable'" />
        </div>
      </template>
      <DataGrid v-if="viewMode === 'list'" :columns="columns" :rows="filteredRows" :row-key="rowKey" :selected-id="selectedProfile?.profile" :density="density" empty-text="暂无 provider profile。" @select="selectProfile">
        <template #cell-profile="{ row }">
          <strong>{{ (row as ProviderProfileRow).profile }}</strong>
          <small>{{ displayDate((row as ProviderProfileRow).updatedAt) }}</small>
        </template>
        <template #cell-configured="{ row }">
          <span class="status-pill" :data-status="(row as ProviderProfileRow).configured ? 'active' : 'disabled'">{{ (row as ProviderProfileRow).configured ? "configured" : "missing" }}</span>
        </template>
        <template #cell-secret="{ row }">
          <code>{{ (row as ProviderProfileRow).secretRefText }}</code>
          <small>{{ (row as ProviderProfileRow).resourceVersion || "rv -" }}</small>
        </template>
        <template #cell-hash="{ row }">
          <span>key {{ (row as ProviderProfileRow).credentialHashSuffix || "-" }}</span>
          <small>config {{ (row as ProviderProfileRow).configHashSuffix || "-" }}</small>
        </template>
        <template #cell-bridge="{ row }">
          {{ (row as ProviderProfileRow).bridgeText || "-" }}
        </template>
        <template #cell-validation="{ row }">
          <span class="status-pill" :data-status="(row as ProviderProfileRow).validationStatus || 'pending'">{{ (row as ProviderProfileRow).validationStatus || "not run" }}</span>
          <small v-if="(row as ProviderProfileRow).failureKind">{{ (row as ProviderProfileRow).failureKind }}</small>
        </template>
        <template #cell-actions="{ row }">
          <div class="table-actions-inline">
            <button class="table-action" type="button" @click="openCredential(row as ProviderProfileRow)">Key</button>
            <button class="table-action" type="button" @click="openConfig(row as ProviderProfileRow)">Config</button>
            <button class="table-action" type="button" data-testid="provider-profile-test-open" @click="openTest(row as ProviderProfileRow)">测试</button>
            <button class="table-action" type="button" :disabled="validatingProfile !== null" @click="validateProfile(row as ProviderProfileRow)">{{ validatingProfile === (row as ProviderProfileRow).profile ? "验证中" : "Validate" }}</button>
            <button class="table-action danger" type="button" @click="openRemove(row as ProviderProfileRow)">Remove</button>
          </div>
        </template>
      </DataGrid>
      <ResourceCollection v-else-if="filteredRows.length" :items="filteredRows" :item-key="rowKey" view="cards" :density="density" :selected-id="selectedProfile?.profile" :show-controls="false" aria-label="Provider Profile 卡片" @select="selectProfile">
        <template #card="{ item: row }">
          <EntityCard
            :icon="Cpu"
            :title="row.profile"
            :subtitle="row.secretRefText"
            :status="row.configured ? 'active' : 'disabled'"
            :status-label="row.configured ? 'configured' : 'missing'"
            :selected="selectedProfile?.profile === row.profile"
            @select="selectProfile(row)"
          >
            <dl class="industrial-fact-row">
              <div><dt>Fingerprint</dt><dd>key {{ row.credentialHashSuffix || '-' }} / cfg {{ row.configHashSuffix || '-' }}</dd></div>
              <div><dt>Bridge</dt><dd>{{ row.bridgeText || '-' }}</dd></div>
              <div><dt>Validation</dt><dd>{{ row.validationStatus || 'not run' }}<small v-if="row.failureKind">{{ row.failureKind }}</small></dd></div>
            </dl>
            <template #footer>
              <div class="table-actions-inline">
                <button class="table-action" type="button" @click="openCredential(row)">Key</button>
                <button class="table-action" type="button" @click="openConfig(row)">Config</button>
                <button class="table-action" type="button" @click="openTest(row)">测试</button>
                <button class="table-action" type="button" :disabled="validatingProfile !== null" @click="validateProfile(row)">{{ validatingProfile === row.profile ? '验证中' : 'Validate' }}</button>
                <button class="table-action danger" type="button" @click="openRemove(row)">Remove</button>
              </div>
            </template>
          </EntityCard>
        </template>
      </ResourceCollection>
      <EmptyState v-else title="没有匹配 Profile" description="调整配置状态或搜索；凭据仅显示 SecretRef 与 fingerprint。" />
    </TablePageLayout>

    <section id="provider-validation-summary" class="data-panel admin-crud-panel provider-validation-panel">
      <header class="panel-header">
        <div><h2>{{ selectedProfile?.profile || 'Validation' }}</h2><small>{{ selectedProfile ? `${selectedProfile.secretRefText} / ${selectedProfile.bridgeText}` : '选择 profile 查看或运行 validation' }}</small></div>
        <span class="status-pill" :data-status="validation?.status || (validationError ? 'failed' : 'pending')">{{ validation?.status || (validationError ? "failed" : "idle") }}</span>
      </header>
      <ApiErrorDiagnostic v-if="validationError" :error="validationError" :api-error="validationApiError" :diagnostic="validationDiagnostic" compact />
      <dl v-if="validation" class="field-grid">
        <div><dt>validationId</dt><dd>{{ validation.validationId || "-" }}</dd></div>
        <div><dt>runId</dt><dd>{{ validation.runId || "-" }}</dd></div>
        <div><dt>commandId</dt><dd>{{ validation.commandId || "-" }}</dd></div>
        <div><dt>jobName</dt><dd>{{ validation.jobName || "-" }}</dd></div>
        <div><dt>traceId</dt><dd>{{ validation.traceId || "-" }}</dd></div>
        <div><dt>failureKind</dt><dd>{{ validation.failureKind || validation.terminalStatus || "-" }}</dd></div>
      </dl>
      <p v-else-if="!validationError" class="muted-box">尚未触发本页 validate workflow。</p>
    </section>
    </AsyncBoundary>

    <BaseDialog :open="credentialDialogOpen" title="Provider Credential" :description="selectedProfile?.profile || ''" @close="credentialDialogOpen = false">
      <form class="admin-form" @submit.prevent="saveCredential">
        <label>
          <span>API key</span>
          <input id="provider-api-key-input" v-model="apiKeyInput" type="password" autocomplete="off" placeholder="输入后只用于本次提交">
        </label>
        <ApiErrorDiagnostic v-if="credentialForm.error.value" :error="credentialForm.error.value" :api-error="credentialForm.apiError.value" :diagnostic="credentialForm.diagnostic.value" compact />
        <p v-if="credentialForm.notice.value" class="form-notice">{{ credentialForm.notice.value }}</p>
      </form>
      <template #footer>
        <button class="table-action" type="button" :disabled="credentialForm.loading.value" @click="credentialDialogOpen = false">取消</button>
        <button class="table-action" type="button" :disabled="credentialForm.loading.value || !apiKeyInput.trim()" @click="saveCredential">{{ credentialForm.loading.value ? "保存中" : "保存" }}</button>
      </template>
    </BaseDialog>

    <BaseDialog :open="configDialogOpen" title="Provider config.toml" :description="selectedProfile?.profile || ''" wide @close="configDialogOpen = false">
      <form class="admin-form" @submit.prevent="saveConfig">
        <label>
          <span>config.toml</span>
          <textarea id="provider-config-toml" v-model="configText" rows="14" spellcheck="false" />
        </label>
        <p v-if="configInfo" class="muted-box">config fingerprint: {{ configInfo.configHashSuffix || "-" }} / valuesPrinted={{ configInfo.valuesPrinted ? "true" : "false" }}</p>
        <ApiErrorDiagnostic v-if="configForm.error.value" :error="configForm.error.value" :api-error="configForm.apiError.value" :diagnostic="configForm.diagnostic.value" compact />
        <p v-if="configForm.notice.value" class="form-notice">{{ configForm.notice.value }}</p>
      </form>
      <template #footer>
        <button class="table-action" type="button" :disabled="configForm.loading.value" @click="configDialogOpen = false">取消</button>
        <button class="table-action" type="button" :disabled="configForm.loading.value" @click="saveConfig">{{ configForm.loading.value ? "保存中" : "保存" }}</button>
      </template>
    </BaseDialog>

    <BaseDialog :open="testDialogOpen" title="真实 Responses 测试" :description="selectedProfile?.profile || ''" wide @close="testDialogOpen = false">
      <form class="admin-form" data-testid="provider-profile-test-dialog" @submit.prevent="runRealTest">
        <label>
          <span>模型</span>
          <input id="provider-profile-test-model" v-model="testModel" data-testid="provider-profile-test-model" autocomplete="off" placeholder="gpt-5.4-mini">
        </label>
        <p class="muted-box">Provider Profile 管理契约不声明默认模型；请按目标通道显式填写，页面不会从 profile 名称或配置摘要推断。</p>
        <label>
          <span>测试提示词</span>
          <textarea id="provider-profile-test-prompt" v-model="testPrompt" data-testid="provider-profile-test-prompt" rows="5" spellcheck="false" />
        </label>
        <ApiErrorDiagnostic v-if="testForm.error.value" :error="testForm.error.value" :api-error="testForm.apiError.value" :diagnostic="testForm.diagnostic.value" compact />
        <section v-if="testResult" class="muted-box" data-testid="provider-profile-test-result">
          <strong>{{ testResult.status }}</strong>
          <dl class="field-grid">
            <div><dt>profile</dt><dd>{{ testResult.profile || selectedProfile?.profile || "-" }}</dd></div>
            <div><dt>model</dt><dd>{{ testResult.model || testModel || "-" }}</dd></div>
            <div><dt>validationId</dt><dd>{{ testResult.validationId || "-" }}</dd></div>
            <div><dt>runId</dt><dd>{{ testResult.runId || "-" }}</dd></div>
            <div><dt>commandId</dt><dd>{{ testResult.commandId || "-" }}</dd></div>
            <div><dt>jobName</dt><dd>{{ testResult.jobName || "-" }}</dd></div>
            <div><dt>elapsedMs</dt><dd>{{ testResult.elapsedMs || "-" }}</dd></div>
            <div><dt>failureKind</dt><dd>{{ testResult.failureKind || testResult.terminalStatus || "-" }}</dd></div>
          </dl>
          <ContentViewer v-if="testResult.outputText" :content="testResult.outputText" mode="text" title="Provider final response" filename="provider-response.txt" :line-numbers="false" />
          <p v-else>等待终端回复，或当前结果未包含 final response。</p>
        </section>
        <p v-if="testForm.notice.value" class="form-notice">{{ testForm.notice.value }}</p>
      </form>
      <template #footer>
        <button class="table-action" type="button" :disabled="testForm.loading.value" @click="testDialogOpen = false">关闭</button>
        <button class="table-action" type="button" data-testid="provider-profile-test-submit" :disabled="testForm.loading.value || !testModel.trim() || !testPrompt.trim()" @click="runRealTest">{{ testForm.loading.value ? "测试中" : "测试" }}</button>
      </template>
    </BaseDialog>

    <ConfirmDialog :open="removeDialogOpen" title="Remove provider profile" :message="`删除 ${selectedProfile?.profile || 'profile'} 的管理配置；内建能力仍由后端决定是否保留。`" confirm-label="删除" :pending="removeForm.loading.value" @close="removeDialogOpen = false" @confirm="removeProfile" />
    <ApiErrorDiagnostic v-if="removeForm.error.value" class="admin-action-error" :error="removeForm.error.value" :api-error="removeForm.apiError.value" :diagnostic="removeForm.diagnostic.value" compact />
  </section>
</template>

<style scoped>
.provider-admin-page { min-width: 0; }
.provider-filter-bar { display: grid; grid-template-columns: 180px minmax(260px, 1fr) auto; gap: 8px; align-items: end; }
.provider-filter-bar label { display: grid; gap: 4px; color: #60717a; font-size: 9px; font-weight: 850; letter-spacing: 0; text-transform: uppercase; }
.provider-filter-bar select,
.provider-filter-bar input { width: 100%; height: 34px; border: 1px solid #b8c5cc; border-radius: 6px; background: #fff; padding: 0 9px; color: #1c3038; }
.provider-validation-panel { box-shadow: inset 3px 0 #1ba39e; }
.provider-test-output {
  max-height: 180px;
  overflow: auto;
  margin: 12px 0 0;
  padding: 10px 12px;
  border: 1px solid var(--border-muted, #d8dee8);
  border-radius: 6px;
  background: var(--surface-muted, #f7f9fc);
  color: var(--text-primary, #172033);
  white-space: pre-wrap;
  word-break: break-word;
}
@media (max-width: 680px) {
  .provider-filter-bar { grid-template-columns: 1fr; }
}
</style>
