import type { C1ProjectOverviewPayload, C1TaskFixturePayload, SurfaceState } from "./model.js";
import { escapeHtml, titleCase } from "./html.js";
import { withQuery } from "./router.js";
import type { AccountListItem } from "./render-accounts.js";

const projectTabs = [
  "overview",
  "vision",
  "goals",
  "plans",
  "work",
  "factory-runs",
  "reviews",
  "decisions",
  "ci",
  "delivery",
  "settings",
] as const;

const projectNavGroups = (projectId: string) =>
  [
    [
      "Home",
      [
        ["Overview", `/projects/${projectId}`, "▣"],
        ["Needs your attention", "#attention", "♧"],
      ],
    ],
    [
      "Work",
      [
        ["Projects", "/projects", "▣"],
        ["Plans", `/projects/${projectId}?tab=plans`, "≋"],
        ["Accounts", `/accounts?project=${projectId}`, "◎"],
        ["Work Items", `/projects/${projectId}?tab=work`, "≋"],
        ["Queue (Next Up)", `/projects/${projectId}/queue`, "≋"],
        ["Saved views", "#planned-saved", "≋"],
      ],
    ],
    [
      "Execution",
      [
        ["FactoryRuns", `/projects/${projectId}?tab=factory-runs`, "◷"],
        ["Agents", `/projects/${projectId}?tab=factory-runs`, "◉"],
        ["CI", "#planned-ci", "⊙"],
      ],
    ],
    [
      "Delivery",
      [
        ["Releases / Changes", `/projects/${projectId}?tab=reviews`, "⌘"],
        ["Deployments", "#planned-deployments", "◇"],
      ],
    ],
    [
      "Operations",
      [
        ["Queues", `/projects/${projectId}/queue`, "≋"],
        ["Health", "#planned-health", "⌁"],
      ],
    ],
    [
      "Intelligence",
      [
        ["Reports", "#planned-reports", "▥"],
        ["Analytics", "#planned-analytics", "◉"],
      ],
    ],
    ["Settings", [["Project Settings", `/projects/${projectId}?tab=settings`, "⚙"]]],
  ] as const;

const stateTone = (state: string): string => {
  if (["active", "achieved", "completed", "DONE"].includes(state)) return "green";
  if (["ready", "running", "READY", "RUNNING"].includes(state)) return "blue";
  if (["blocked", "BLOCKED_DEPENDENCY", "BLOCKED_POLICY"].includes(state)) return "red";
  if (["waiting", "WAITING_USER", "paused", "PAUSED"].includes(state)) return "amber";
  return "purple";
};

const skeletonPanels =
  (): string => `<div class="dashboard" aria-busy="true" aria-label="Loading Project Overview">
  <div class="row3">${["Current Goals", "Needs Your Attention", "Blockers"].map((title) => `<section class="panel skeleton-panel"><div class="panel-head">${title}</div><div class="skeleton-lines"><span></span><span></span><span></span><span></span></div></section>`).join("")}</div>
  <div class="row3 second">${["Active Plans", "FactoryRuns", "Recently Completed"].map((title) => `<section class="panel skeleton-panel"><div class="panel-head">${title}</div><div class="skeleton-lines"><span></span><span></span><span></span></div></section>`).join("")}</div>
  <section class="panel queue-panel skeleton-panel"><div class="queue-head">Queue / Next Up</div><div class="skeleton-lines"><span></span><span></span></div></section>
</div>`;

const emptyPanel = (title: string, text: string, action?: string): string =>
  `<section class="panel empty-panel"><div class="panel-head">${title}</div><div class="empty-copy"><strong>${text}</strong>${action ? `<button class="hbtn primary" type="button" data-command="new-plan">${action}</button>` : ""}</div></section>`;

const projectSidebar = (
  projectId: string,
): string => `<aside class="sidebar" aria-label="Primary navigation">
  <div class="brand"><span class="brand-mark" aria-hidden="true"></span><span>AWP</span></div>
  <nav class="side-scroll">${projectNavGroups(projectId)
    .map(
      ([label, links]) =>
        `<div class="side-group"><div class="side-label">${label}</div>${links
          .map(([text, href, icon]) => {
            const planned = href.startsWith("#planned-");
            const active = text === "Projects";
            return `<a class="side-link${active ? " active" : ""}" href="${href}"${active ? ' aria-current="page"' : ""}${planned ? ' aria-disabled="true" title="Planned for a later increment"' : ""}><span class="si" aria-hidden="true">${icon}</span><span>${text}</span>${planned ? '<span class="planned-chip">Planned</span>' : ""}</a>`;
          })
          .join("")}</div>`,
    )
    .join('<div class="side-divider"></div>')}</nav>
  <div class="sidebar-foot"><span>I1 dogfood</span><span aria-hidden="true">≪</span></div>
</aside>`;

const projectTopbar = (name: string): string =>
  `<header class="topbar"><div class="breadcrumbs"><span class="root">WORK</span><span class="sep">/</span><span>Projects</span><span class="sep">/</span><span class="current">${escapeHtml(name)}</span></div><label class="search-box planned-search" title="Search activates in I3"><span aria-hidden="true">⌕</span><input aria-label="Search — planned for I3" aria-disabled="true" disabled placeholder="Search projects, plans, tasks, runs, decisions…"><span class="kbd">⌘K</span></label><div class="top-actions"><button class="top-icon" aria-label="Notifications" type="button">♧</button><button class="top-icon" aria-label="Help" type="button">?</button><div class="user"><span class="avatar" aria-hidden="true">O</span><span class="user-meta"><strong>Owner</strong><span>Product Owner</span></span><span class="chev" aria-hidden="true">⌄</span></div></div></header>`;

const repositoryLabel = (repositoryUrl: string): string => {
  try {
    const parsed = new URL(repositoryUrl);
    return `${parsed.host}${parsed.pathname}`.replace(/\.git$/u, "").replace(/^github\.com\//u, "");
  } catch {
    return repositoryUrl;
  }
};
const projectHeader = (
  project: C1ProjectOverviewPayload["project"],
  tab: string,
  mutationsDisabled: boolean,
): string =>
  `<section class="project-header"><div class="project-main"><div class="project-identity"><div class="project-icon" aria-hidden="true"><span class="project-cube">A</span></div><div><div class="project-title-line"><span class="project-title">${escapeHtml(project.name)}</span><span aria-label="Favorite project">☆</span></div><div class="project-subtitle">Agentic software delivery project</div><div class="project-meta"><span>▣ ${escapeHtml(repositoryLabel(project.repositoryUrl))}</span><span class="dot">•</span><span>Canonical Project ${escapeHtml(project.id)}</span><span class="dot">•</span><span>Status: ${titleCase(project.status)}</span></div></div></div><div class="header-buttons"><button class="hbtn primary" type="button" data-command="new-plan" data-dialog-target="#new-plan-dialog"${mutationsDisabled ? ' disabled aria-disabled="true"' : ""}>＋ New Plan</button><a class="hbtn" href="/accounts?project=${project.id}">◎ Accounts</a><a class="hbtn planned-action" href="#planned-decisions" aria-disabled="true" title="Decision Log activates in I3">⚖ Decisions <span class="planned-chip">I3</span></a></div></div><nav class="tabs" aria-label="Project tabs">${projectTabs.map((current) => `<a class="tab${tab === current ? " active" : ""}" href="${withQuery(`/projects/${project.id}`, { tab: current === "overview" ? undefined : current })}"${tab === current ? ' aria-current="page"' : ""}>${current === "factory-runs" ? "FactoryRuns" : titleCase(current)}</a>`).join("")}</nav></section>`;

const projectStateBanner = (state: SurfaceState): string => {
  if (state === "stale")
    return `<div class="u1-state-banner warning" role="status"><strong>Project data is stale</strong><span>Last-known state is readable. Protected changes are disabled until refresh confirms current authority.</span><button type="button" class="hbtn" data-command="refresh">↻ Refresh</button></div>`;
  if (state === "error")
    return `<div class="u1-state-banner error" role="alert"><strong>Some Project sections failed to refresh</strong><span>Last-known C1 data is preserved so context is not lost.</span><button type="button" class="hbtn" data-command="refresh">Retry</button></div>`;
  if (state === "permission")
    return `<div class="u1-state-banner warning" role="status"><strong>Read-only Project access</strong><span>Your current Principal can inspect this Project but cannot execute protected actions.</span></div>`;
  return "";
};

const goalsPanel = (model: C1ProjectOverviewPayload): string =>
  `<section class="panel"><div class="panel-head">◎ Current Goals</div><div class="goal-list">${model.goals.map((goal) => `<a class="goal-row" href="/projects/${model.project.id}?tab=goals#${goal.id}"><span class="circle-check" aria-hidden="true">✓</span><span class="goal-name">${escapeHtml(goal.title)}</span><span class="status ${stateTone(goal.status)}">${titleCase(goal.status)}</span></a>`).join("")}</div><a class="panel-foot-link" href="/projects/${model.project.id}?tab=goals">View all goals →</a></section>`;

const attentionPanel = (
  model: C1ProjectOverviewPayload,
  accounts: readonly AccountListItem[],
  mutationsDisabled: boolean,
): string => {
  const draftPlans = model.plans.filter((plan) => plan.status === "draft");
  const items: Array<{
    title: string;
    description: string;
    href: string;
    action: string;
    priority: "High" | "Medium";
  }> = [];

  if (draftPlans.length > 0 && accounts.length === 0) {
    items.push({
      title: "Execution account required",
      description: `${draftPlans.length} draft Plan${draftPlans.length === 1 ? " is" : "s are"} waiting for an account before owner approval can start a real FactoryRun.`,
      href: `/accounts?project=${encodeURIComponent(model.project.id)}`,
      action: "Add account",
      priority: "High",
    });
  } else {
    for (const plan of draftPlans) {
      items.push({
        title: `Approve & start ${plan.title}`,
        description:
          "A draft Plan is ready for the explicit owner launch boundary. Execution after approval remains autonomous.",
        href: `/projects/${encodeURIComponent(model.project.id)}?tab=plans#${encodeURIComponent(plan.id)}`,
        action: "Review Plan",
        priority: "Medium",
      });
    }
  }

  if (items.length === 0)
    return `<section class="panel" id="attention"><div class="panel-head">△ Needs Your Attention<span class="head-spacer"></span><span class="count-badge zero">0</span></div><div class="quiet-state"><strong>No owner action required</strong><span>Current I1 Project state has no active owner authority boundary.</span></div></section>`;

  return `<section class="panel" id="attention"><div class="panel-head">△ Needs Your Attention<span class="head-spacer"></span><span class="count-badge">${items.length}</span></div><div class="attention-list">${items
    .map(
      (item) =>
        `<div class="attention-row"><span class="severity-dot ${item.priority === "High" ? "amber" : "blue"}"></span><div><div class="blocker-title">${escapeHtml(item.title)}</div><div class="blocker-desc">${escapeHtml(item.description)}</div></div><span class="priority${item.priority === "Medium" ? " medium" : ""}">${item.priority}</span>${mutationsDisabled ? '<span class="state-text muted">Unavailable</span>' : `<a class="action-btn attention-action" href="${item.href}">${escapeHtml(item.action)}</a>`}</div>`,
    )
    .join("")}</div></section>`;
};

const blockersPanel = (
  model: C1ProjectOverviewPayload,
  tasks: readonly C1TaskFixturePayload[],
): string => {
  const blocked = model.queue.filter((entry) => entry.readinessState.startsWith("BLOCKED"));
  if (blocked.length === 0)
    return `<section class="panel"><div class="panel-head">▣ Blockers<span class="head-spacer"></span><span class="count-badge zero">0</span></div><div class="quiet-state"><strong>No blocked Tasks</strong><span>Current C1 queue projection has no dependency or policy blocker.</span></div><a class="panel-foot-link" href="/projects/${model.project.id}/queue">View Queue / Graph →</a></section>`;
  return `<section class="panel"><div class="panel-head">▣ Blockers<span class="head-spacer"></span><span class="count-badge">${blocked.length}</span></div><div class="blockers">${blocked
    .map((entry) => {
      const task = tasks.find((item) => item.id === entry.taskId);
      return `<div class="blocker-row"><span class="severity-dot red"></span><div><div class="blocker-title">${escapeHtml(task?.title ?? entry.taskId)}</div><div class="blocker-desc">Blocked by ${entry.unsatisfiedDependencyIds.map(escapeHtml).join(", ") || "authoritative policy"}.</div><div class="blocker-next">Next: satisfy the authoritative prerequisite</div></div></div>`;
    })
    .join("")}</div></section>`;
};

const plansPanel = (model: C1ProjectOverviewPayload): string =>
  `<section class="panel"><div class="panel-head">Active Plans<span class="head-spacer"></span><a class="head-link" href="/projects/${model.project.id}?tab=plans">View all plans →</a></div><div class="table-wrap"><table class="data-table"><caption class="sr-only">Active Plans</caption><thead><tr><th>Plan</th><th>Progress</th><th>Status</th><th>Goal linkage</th></tr></thead><tbody>${model.plans.map((plan) => `<tr><td><a class="row-link" href="/projects/${model.project.id}?tab=plans#${plan.id}">${escapeHtml(plan.title)}</a></td><td><span class="not-exposed" title="Progress is not exposed by the C1 read model">—</span></td><td><span class="state-text ${stateTone(plan.status)}">${titleCase(plan.status)}</span></td><td>${plan.goalIds.length} Goal${plan.goalIds.length === 1 ? "" : "s"}</td></tr>`).join("")}</tbody></table></div></section>`;

const planLaunchPanel = (
  model: C1ProjectOverviewPayload,
  accounts: readonly AccountListItem[],
  mutationsDisabled: boolean,
): string => {
  const draftPlans = model.plans.filter((plan) => plan.status === "draft");
  if (draftPlans.length === 0) {
    return `<section class="panel"><div class="panel-head">Run setup</div><div class="quiet-state"><strong>No draft Plan is waiting to start.</strong><span>Approved or completed Plans retain their recorded execution provenance.</span></div></section>`;
  }
  if (accounts.length === 0) {
    return `<section class="panel"><div class="panel-head">Run setup</div><div class="u1-state-banner warning" role="status"><strong>An account is required before the first real FactoryRun.</strong><span>The dedicated K3s Subrouter has no available accounts. No fixture account will be substituted.</span><a class="hbtn primary" href="/accounts?project=${encodeURIComponent(model.project.id)}">＋ Add account</a></div></section>`;
  }
  const options = accounts
    .map(
      (account) =>
        `<option value="${escapeHtml(account.accountKey)}">${escapeHtml(account.label)} — ${escapeHtml(account.accountKey)}</option>`,
    )
    .join("");
  return `<section class="panel"><div class="panel-head">Run setup<span class="head-spacer"></span><a class="head-link" href="/accounts?project=${encodeURIComponent(model.project.id)}">Manage accounts →</a></div><div class="panel-body">${draftPlans
    .map(
      (plan) =>
        `<form class="run-launch-grid" data-plan-launch data-project-id="${escapeHtml(model.project.id)}" data-plan-id="${escapeHtml(plan.id)}"><label>Account<select name="accountId" required>${options}</select></label><label>Model<input name="model" placeholder="Provider default" autocomplete="off"></label><button class="hbtn primary" type="submit"${mutationsDisabled ? ' disabled aria-disabled="true"' : ""}>Approve &amp; start FactoryRun</button><div class="error" data-plan-launch-error role="alert"></div><div class="subtle">${escapeHtml(plan.title)} · selected account will be written to Attempt provenance and preserved across automatic task dispatch.</div></form>`,
    )
    .join('<div class="side-divider"></div>')}</div></section>`;
};

const projectMutationPanel = (
  model: C1ProjectOverviewPayload,
  tasks: readonly C1TaskFixturePayload[],
  tab: string,
  mutationsDisabled: boolean,
  visionSummary?: string,
): string => {
  const projectId = encodeURIComponent(model.project.id);
  const disabled = mutationsDisabled ? ' disabled aria-disabled="true"' : "";
  if (tab === "vision") {
    return `<section class="panel setup-panel"><div class="panel-head">ProjectVision</div><form class="setup-form" data-live-form action="/internal/projects/${projectId}/vision"><label>Vision<textarea name="summary" rows="6" required>${escapeHtml(visionSummary ?? "")}</textarea></label><div class="setup-actions"><button class="hbtn primary" type="submit"${disabled}>Save ProjectVision</button><div class="error" data-form-error role="alert"></div></div></form></section>`;
  }
  if (tab === "goals") {
    return `<section class="panel setup-panel"><div class="panel-head">Create Goal</div><form class="setup-form two-column" data-live-form action="/internal/projects/${projectId}/goals"><label>Goal title<input name="title" required></label><label>Launch criteria<textarea name="successCriteria" rows="4" required></textarea></label><div class="setup-actions"><button class="hbtn primary" type="submit"${disabled}>Create Goal</button><div class="error" data-form-error role="alert"></div></div></form></section>`;
  }
  if (tab !== "plans") return "";
  const dependencyRows = tasks
    .map((task) => {
      const options = tasks
        .filter((candidate) => candidate.id !== task.id)
        .map(
          (candidate) =>
            `<option value="${escapeHtml(candidate.id)}">${escapeHtml(candidate.title)}</option>`,
        )
        .join("");
      const prerequisites = task.dependencyIds.length
        ? task.dependencyIds
            .map((id) => tasks.find((candidate) => candidate.id === id)?.title ?? id)
            .map(escapeHtml)
            .join(", ")
        : "none";
      return `<div class="dependency-row" data-task-id="${escapeHtml(task.id)}"><div><strong>${escapeHtml(task.title)}</strong><span class="state-text ${stateTone(task.status)}">${titleCase(task.status)}</span><small>Prerequisites: ${prerequisites}</small></div>${options ? `<form class="dependency-form" data-live-form action="/internal/projects/${projectId}/tasks/${encodeURIComponent(task.id)}/dependencies"><label>Add prerequisite<select name="prerequisiteTaskId" required><option value="">Choose Task</option>${options}</select></label><button class="hbtn" type="submit"${disabled}>Add dependency</button><div class="error" data-form-error role="alert"></div></form>` : ""}</div>`;
    })
    .join("");
  return `<section class="panel setup-panel" id="new-plan"><div class="panel-head">Plan authoring</div><form class="setup-form two-column" data-live-form action="/internal/projects/${projectId}/plans"><label>Plan title<input name="title" required></label><label>Tasks (one per line, at least three)<textarea name="taskTitles" rows="5" required></textarea></label><div class="setup-actions"><button class="hbtn primary" type="submit"${disabled}>Create Plan</button><div class="error" data-form-error role="alert"></div></div></form>${dependencyRows ? `<div class="dependency-editor"><div class="setup-subhead">Task dependencies</div>${dependencyRows}</div>` : ""}</section>`;
};

const factoryPanel = (model: C1ProjectOverviewPayload): string =>
  `<section class="panel"><div class="panel-head">FactoryRuns (What's running now)<span class="head-spacer"></span><a class="head-link" href="/projects/${model.project.id}?tab=factory-runs">View all →</a></div><div class="table-wrap"><table class="data-table"><caption class="sr-only">Current FactoryRuns</caption><thead><tr><th>Run ID</th><th>Status</th><th>Reason</th><th>Provider detail</th></tr></thead><tbody>${model.factoryRuns.map((run) => `<tr><td><a class="row-link" href="/factory-runs/${run.id}?project=${encodeURIComponent(model.project.id)}">${escapeHtml(run.id)}</a></td><td><span class="run-pill ${stateTone(run.status)}">${titleCase(run.status)}</span></td><td>${escapeHtml(run.reason ?? "—")}</td><td><span class="not-exposed" title="Model/account detail is not part of C1 Project Overview">See FactoryRun</span></td></tr>`).join("")}</tbody></table></div><a class="panel-foot-link" href="/projects/${model.project.id}?tab=factory-runs">Open FactoryRuns →</a></section>`;

const completedPanel = (tasks: readonly C1TaskFixturePayload[]): string => {
  const completed = tasks.filter((task) => task.status === "completed");
  return `<section class="panel"><div class="panel-head">Recently Completed</div><div class="table-wrap"><table class="data-table"><caption class="sr-only">Recently completed work</caption><thead><tr><th>Task</th><th>State</th><th>Revision</th></tr></thead><tbody>${completed.map((task) => `<tr><td><span class="completed-check" aria-hidden="true">✓</span>${escapeHtml(task.title)}</td><td>Completed</td><td>r${task.revision}</td></tr>`).join("")}</tbody></table></div>${completed.length === 0 ? '<div class="quiet-state">No completed work yet.</div>' : ""}</section>`;
};

const queuePanel = (
  model: C1ProjectOverviewPayload,
  tasks: readonly C1TaskFixturePayload[],
): string => {
  const groups = [
    ["Now (Ready)", ["READY", "RUNNING"], "green"],
    ["Next", ["BLOCKED_DEPENDENCY"], "blue"],
    ["Later", ["PAUSED"], "purple"],
    ["Waiting (External)", ["WAITING_USER"], "amber"],
    ["Blocked", ["BLOCKED_POLICY"], "red"],
  ] as const;
  return `<section class="panel queue-panel" id="queue"><div class="queue-head">Queue / Next Up (What is to be done soon)<a class="head-link" href="/projects/${model.project.id}/queue">View full queue →</a></div><div class="queue-cols">${groups
    .map(([name, states, tone]) => {
      const entries = model.queue.filter((entry) => states.includes(entry.readinessState as never));
      return `<div class="queue-col"><div class="queue-col-head"><span class="qdot ${tone}" aria-hidden="true"></span>${name}<span class="qcount">${entries.length}</span></div><div class="qitems">${
        entries.length
          ? entries
              .map((entry) => {
                const task = tasks.find((item) => item.id === entry.taskId);
                return `<a class="qitem" href="/projects/${model.project.id}/queue?task=${entry.taskId}"><span class="num">${entry.position + 1}</span><span class="task">${escapeHtml(task?.title ?? entry.taskId)}</span><span class="plan">${escapeHtml(entry.planRevisionId)}</span></a>`;
              })
              .join("")
          : '<div class="qempty">No work</div>'
      }</div></div>`;
    })
    .join("")}</div></section>`;
};

export function renderProjectOverview(
  model: C1ProjectOverviewPayload,
  tasks: readonly C1TaskFixturePayload[],
  requestedState: string,
  tab = "overview",
  runAccounts: readonly AccountListItem[] = [],
  visionSummary?: string,
): string {
  const state = (["ready", "loading", "error", "stale", "permission", "empty"] as const).includes(
    requestedState as SurfaceState,
  )
    ? (requestedState as SurfaceState)
    : "ready";
  const mutationsDisabled = state === "stale" || state === "permission" || state === "error";
  const header = `${projectSidebar(model.project.id)}<main class="main" id="main-content">${projectTopbar(model.project.name)}${projectHeader(model.project, tab, mutationsDisabled)}`;
  if (state === "loading")
    return `<div class="screen project-shell"><a class="skip-link" href="#main-content">Skip to main content</a>${header}${skeletonPanels()}</main></div>`;
  if (state === "empty") {
    const emptyModel = {
      ...model,
      goals: [],
      plans: [],
      queue: [],
      factoryRuns: [],
    } satisfies C1ProjectOverviewPayload;
    return `<div class="screen project-shell"><a class="skip-link" href="#main-content">Skip to main content</a>${header}<div class="dashboard"><div class="u1-state-banner" role="status"><strong>New Project</strong><span>No Goals, Plans, queueable Tasks, or FactoryRuns exist yet.</span></div><div class="row3">${emptyPanel("Current Goals", "No active Goals yet")}${emptyPanel("Needs Your Attention", "Nothing needs attention")}${emptyPanel("Blockers", "No blockers")}</div><div class="row3 second">${emptyPanel("Active Plans", "No Plans yet", mutationsDisabled ? undefined : "＋ New Plan")}${emptyPanel("FactoryRuns", "No FactoryRuns yet")}${emptyPanel("Recently Completed", "No completed work yet")}</div>${queuePanel(emptyModel, [])}</div></main></div>`;
  }
  const mutations = projectMutationPanel(model, tasks, tab, mutationsDisabled, visionSummary);
  const runSetup = tab === "plans" ? planLaunchPanel(model, runAccounts, mutationsDisabled) : "";
  return `<div class="screen project-shell"><a class="skip-link" href="#main-content">Skip to main content</a>${header}<div class="dashboard">${projectStateBanner(state)}${mutations}${runSetup}<div class="row3">${goalsPanel(model)}${attentionPanel(model, runAccounts, mutationsDisabled)}${blockersPanel(model, tasks)}</div><div class="row3 second">${plansPanel(model)}${factoryPanel(model)}${completedPanel(tasks)}</div>${queuePanel(model, tasks)}<footer class="bottom-status"><div class="health">Project Health <span class="health-dot" aria-hidden="true"></span><span>${state === "stale" ? "Stale" : "Healthy"}</span></div><div class="updated"><span>Read model:</span><span>Authoritative Project state</span><button class="icon-button" aria-label="Refresh Project" type="button" data-command="refresh">↻</button></div><div class="timezone"><span>Project timezone: inherited</span><a class="customize" href="/projects/${model.project.id}?tab=settings">⚙ Customize</a></div></footer></div></main></div>`;
}
