> ## Documentation Index
> Fetch the complete documentation index at: https://learn.actionist.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Web app

> Chat with your cloud agents from any browser. The full Actionist interface, with no desktop install required.

<div className="mxp-hero xc-border">
  <div className="exp-eyebrow mxp-rise">BROWSER-NATIVE</div>

  <h2 className="mxp-hero-title mxp-rise" style={{animationDelay:'0.06s'}}>
    Your agents, from <span style={{background:'linear-gradient(90deg,#24A4FF,#9000FF,#E3008E)',WebkitBackgroundClip:'text',backgroundClip:'text',color:'transparent'}}>any browser.</span>
  </h2>

  <p className="mxp-hero-dek mxp-rise" style={{animationDelay:'0.13s'}}>
    Agent studio, marketplace, real-time chat, file attachments, the full Actionist interface in a browser tab. No install. No setup. Open a tab and your cloud agents are right there.
  </p>
</div>

<div className="w-full py-10">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">The idea</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">The same interface, wherever you are.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Actionist is a web app. The browser gives you the whole interface: agent studio, marketplace, workflow viewer, calendar, and chat. A short list of features still needs the desktop build, and that list is below.
    </p>
  </div>

  <div className="xwb-stat-row">
    <div className="xwb-stat-tile">
      <div className="xwb-stat-num"><b className="xc-count" style={{"--xc-to":"7"}} data-suffix=""><span className="xc-real">7</span></b></div>
      <div className="xwb-stat-label">features fully available in the browser today</div>
    </div>

    <div className="xwb-stat-tile">
      <div className="xwb-stat-num"><b className="xc-count" style={{"--xc-to":"3"}} data-suffix=""><span className="xc-real">3</span></b></div>
      <div className="xwb-stat-label">surfaces coming soon, shown rather than hidden</div>
    </div>

    <div className="xwb-stat-tile">
      <div className="xwb-stat-num"><b className="xc-count" style={{"--xc-to":"1"}} data-suffix=""><span className="xc-real">1</span></b></div>
      <div className="xwb-stat-label">surface that needs a local machine</div>
    </div>

    <div className="xwb-stat-tile">
      <div className="xwb-stat-num"><b className="xc-count" style={{"--xc-to":"0"}} data-suffix=""><span className="xc-real">0</span></b></div>
      <div className="xwb-stat-label">broken buttons, because gap cards replace them</div>
    </div>
  </div>

  <Columns cols={2}>
    <Card title="Full interface on day one" icon="monitor-smartphone">
      Agent studio, marketplace, workflow viewer, calendar, and the Cloud Runtime tab all work in the browser today. Set up agents, browse skills, and manage your cloud runtime without installing anything.
    </Card>

    <Card title="Honest gap cards, not broken buttons" icon="shield-check">
      Where a surface is not ready in the browser yet, you get a card explaining why instead of a button that does nothing. You can always tell what works today and what is still coming.
    </Card>
  </Columns>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Try it · surfaces</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Same agent. Two surfaces.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      The same agent card renders differently depending on where you are. Switch between the two to compare.
    </p>
  </div>

  <div className="xwb-switch exp-tool-shell xc-try">
    <div className="mxp-srch-chips">
      <label htmlFor="xwb-sb"><input className="mxp-r" type="radio" name="xwb-surf" id="xwb-sb" defaultChecked />Web app</label>
      <label htmlFor="xwb-sa"><input className="mxp-r" type="radio" name="xwb-surf" id="xwb-sa" />Desktop app</label>
    </div>

    {/* WEB panel. Shows VPS card + gap card */}

    <div className="xwb-panel xwb-panel-b">
      <div className="xwb-cards">
        <div className="xwb-card">
          <div className="xwb-card-top">
            <div className="xwb-card-avatar">M</div>

            <div className="xwb-card-meta">
              <div className="xwb-card-name">Maya</div>
              <div className="xwb-card-sub">CRM agent</div>
            </div>

            <span className="xwb-vps-badge">
              <span className="xwb-vps-badge-dot" />

              VPS
            </span>
          </div>

          <a className="xwb-chat-btn" href="https://app.actionist.ai" target="_blank" rel="noreferrer">
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
              <path d="m3 14 10 2 2-10" />

              <circle cx="18" cy="5" r="3" />
            </svg>

            Chat with agent
          </a>
        </div>

        <div className="xwb-card">
          <div className="xwb-card-top">
            <div className="xwb-card-avatar" style={{background:'linear-gradient(135deg,#486EFF,#C800B3)'}}>R</div>

            <div className="xwb-card-meta">
              <div className="xwb-card-name">Rover</div>
              <div className="xwb-card-sub">Research agent · local</div>
            </div>
          </div>

          <div className="xwb-gap-card">
            <div className="xwb-gap-kicker">Coming soon</div>
            <div className="xwb-gap-text">Browser chat for agents running on your own machine is coming. Cloud agents can chat here today.</div>
          </div>
        </div>
      </div>

      <div className="xwb-switch-note">web app · app.actionist.ai · Agents tab</div>
    </div>

    {/* DESKTOP panel. Both cards show Chat, no VPS badge needed */}

    <div className="xwb-panel xwb-panel-a">
      <div className="xwb-cards">
        <div className="xwb-card">
          <div className="xwb-card-top">
            <div className="xwb-card-avatar">M</div>

            <div className="xwb-card-meta">
              <div className="xwb-card-name">Maya</div>
              <div className="xwb-card-sub">CRM agent · VPS</div>
            </div>
          </div>

          <a className="xwb-chat-btn" href="https://app.actionist.ai" target="_blank" rel="noreferrer">
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
              <path d="m3 14 10 2 2-10" />

              <circle cx="18" cy="5" r="3" />
            </svg>

            Chat with agent
          </a>
        </div>

        <div className="xwb-card">
          <div className="xwb-card-top">
            <div className="xwb-card-avatar" style={{background:'linear-gradient(135deg,#486EFF,#C800B3)'}}>R</div>

            <div className="xwb-card-meta">
              <div className="xwb-card-name">Rover</div>
              <div className="xwb-card-sub">Research agent · local</div>
            </div>
          </div>

          <a className="xwb-chat-btn" href="https://app.actionist.ai" target="_blank" rel="noreferrer">
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
              <path d="m3 14 10 2 2-10" />

              <circle cx="18" cy="5" r="3" />
            </svg>

            Chat with agent
          </a>
        </div>
      </div>

      <div className="xwb-switch-note">desktop app · Agents tab · all agents can chat locally</div>
    </div>
  </div>

  <Info>
    The three "coming soon" surfaces show a purple informational card in the browser. Not an error. You can continue using the rest of the app normally.
  </Info>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Desktop vs web</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">What works where.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Everything you can do in each surface today. Three of these gaps are being closed, so treat them as temporary rather than permanent.
    </p>
  </div>

  | Feature                                             | Web app                                   | Desktop app                               |
  | --------------------------------------------------- | ----------------------------------------- | ----------------------------------------- |
  | Sign in (same Clerk account)                        | Yes                                       | Yes                                       |
  | Agent studio: identity, tools, skills, schedule     | Yes                                       | Yes                                       |
  | Marketplace, browse and install MCP servers         | Yes                                       | Yes                                       |
  | Workflow viewer                                     | Yes                                       | Yes                                       |
  | Calendar                                            | Yes                                       | Yes                                       |
  | Cloud Runtime tab                                   | Yes                                       | Yes                                       |
  | Chat with a cloud agent                             | Yes                                       | Yes                                       |
  | Chat with an agent running on your own machine      | Coming soon                               | Yes                                       |
  | Agent memory for agents running on your own machine | Coming soon                               | Yes                                       |
  | Add a custom MCP server                             | Coming soon                               | Yes                                       |
  | Screen recording and local computer use             | Needs the desktop app                     | Yes                                       |
  | Move agent to VPS                                   | Not a user action; placement is automatic | Not a user action; placement is automatic |
</div>

{/* TODO(image): agent-card-vps-badge. IMAGE SPEC: Agents tab in the browser showing two adjacent agent cards. Left card: VPS badge chip visible, 'Chat' button active and labelled 'Chat with agent'. Right card: no cloud badge, and below the card the purple 'Chat is coming to the web' gap card is expanded inline with its icon and copy visible. Replace this CSS mock with the real screenshot */}

<div className="w-full py-4 xc-rise">
  <div className="mxp-window">
    <div className="mxp-window-bar">
      <span className="mxp-window-dot" />

      <span className="mxp-window-dot" />

      <span className="mxp-window-dot" />

      <span className="mxp-window-title" style={{flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>app.actionist.ai/agents</span>
    </div>

    <div className="xwb-mock-body">
      <div className="xwb-mock-tab-row">
        <span className="xwb-mock-tab xwb-mock-tab-active">Agents</span>
        <span className="xwb-mock-tab">Marketplace</span>
        <span className="xwb-mock-tab">Workflows</span>
        <span className="xwb-mock-tab">Calendar</span>
      </div>

      <div className="xwb-mock-cards-row">
        <div className="xwb-card">
          <div className="xwb-card-top" style={{marginBottom:0}}>
            <div className="xwb-card-avatar">M</div>

            <div className="xwb-card-meta">
              <div className="xwb-card-name">Maya</div>
              <div className="xwb-card-sub">CRM agent</div>
            </div>

            <span className="xwb-vps-badge"><span className="xwb-vps-badge-dot" />VPS</span>
          </div>

          <div className="xwb-mock-row-divider" />

          <a className="xwb-chat-btn xwb-mock-chat-btn" href="https://app.actionist.ai" target="_blank" rel="noreferrer">
            <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
              <path d="m3 14 10 2 2-10" />

              <circle cx="18" cy="5" r="3" />
            </svg>

            Chat with agent
          </a>
        </div>

        <div className="xwb-card">
          <div className="xwb-card-top" style={{marginBottom:0}}>
            <div className="xwb-card-avatar" style={{background:'linear-gradient(135deg,#486EFF,#C800B3)'}}>R</div>

            <div className="xwb-card-meta">
              <div className="xwb-card-name">Rover</div>
              <div className="xwb-card-sub">Research agent · local</div>
            </div>
          </div>

          <div className="xwb-mock-row-divider" />

          <div className="xwb-gap-card">
            <div className="xwb-gap-kicker">
              <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{display:'inline',verticalAlign:'middle',marginRight:'4px'}}>
                <circle cx="12" cy="12" r="10" />

                <path d="M12 16v-4M12 8h.01" />
              </svg>

              Coming soon
            </div>

            <div className="xwb-gap-text">Browser chat for agents running on your own machine is coming. Cloud agents can chat here today.</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<hr className="xc-divider" />

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Browser chat</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Watch the connection open.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Cloud agents are fully chat-enabled from the browser. Step through the live flow, from Connecting to Working to a completed reply with a file attachment uploaded.
    </p>
  </div>

  <div className="xwb-chat-shell exp-tool-shell xc-try">
    <div className="mxp-srch-chips" style={{marginBottom:'4px'}}>
      <label htmlFor="xwb-a"><input className="mxp-r" type="radio" name="xwb-cs" id="xwb-a" defaultChecked />1. Connecting</label>
      <label htmlFor="xwb-b"><input className="mxp-r" type="radio" name="xwb-cs" id="xwb-b" />2. Connected</label>
      <label htmlFor="xwb-c"><input className="mxp-r" type="radio" name="xwb-cs" id="xwb-c" />3. Sending</label>
      <label htmlFor="xwb-d"><input className="mxp-r" type="radio" name="xwb-cs" id="xwb-d" />4. Working</label>
      <label htmlFor="xwb-e"><input className="mxp-r" type="radio" name="xwb-cs" id="xwb-e" />5. Reply</label>
    </div>

    <div className="mxp-window" style={{marginTop:'20px'}}>
      <div className="mxp-window-bar">
        <span className="mxp-window-dot" />

        <span className="mxp-window-dot" />

        <span className="mxp-window-dot" />

        <span className="mxp-window-title" style={{flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>app.actionist.ai/agents/maya/chat</span>
      </div>

      <div className="xwb-chat-header">
        <div className="xwb-chat-header-left">
          <span className="xwb-agent-label">Maya</span>
          <span className="xwb-conn-badge xwb-badge-connecting"><span className="xwb-conn-dot" />Connecting…</span>
          <span className="xwb-conn-badge xwb-badge-connected"><span className="xwb-conn-dot" />Connected</span>
          <span className="xwb-working-label">Working…</span>
        </div>

        <div style={{display:'flex',alignItems:'center',gap:'8px'}}>
          <span className="xwb-stop-btn">
            <svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor">
              <rect x="3" y="3" width="18" height="18" rx="2" />
            </svg>

            Stop
          </span>

          <span className="xwb-fresh-btn">Start fresh</span>
        </div>
      </div>

      <div className="xwb-convo">
        {/* Step 1: Connecting */}

        <div className="xwb-state-block xwb-s-connecting">
          <div className="xwb-connecting-row">
            <span className="xwb-spinner" />

            <span>Connecting to Maya…</span>
          </div>
        </div>

        {/* Step 2: Connected, history loaded */}

        <div className="xwb-state-block xwb-s-connected">
          <div style={{fontSize:'11px',opacity:'0.4',marginBottom:'8px',fontFamily:'"JetBrains Mono",monospace',letterSpacing:'0.03em'}}>session open · last 200 messages loaded</div>

          <div className="xwb-msg">
            <span className="xwb-msg-who">You</span>
            <span className="xwb-msg-text xwb-user">Can you pull the Northwind account summary?</span>
          </div>

          <div className="xwb-msg">
            <span className="xwb-msg-who">Maya</span>
            <span className="xwb-msg-text xwb-agent">Sure, fetching from CRM now.</span>
          </div>

          <div style={{fontSize:'11.5px',opacity:'0.5',marginTop:'4px'}}>Composer active. Drop files or send a message.</div>
        </div>

        {/* Step 3: Sending with file */}

        <div className="xwb-state-block xwb-s-sending">
          <div className="xwb-msg">
            <span className="xwb-msg-who">You</span>
            <span className="xwb-msg-text xwb-user">Can you pull the Northwind account summary?</span>
          </div>

          <div className="xwb-msg">
            <span className="xwb-msg-who">Maya</span>
            <span className="xwb-msg-text xwb-agent">Sure, fetching from CRM now.</span>
          </div>

          <div className="xwb-msg" style={{marginTop:'4px'}}>
            <span className="xwb-msg-who">You</span>
            <span className="xwb-msg-text xwb-user">Also attach this for context.</span>
          </div>

          <div className="xwb-attach-chip">
            <span className="xwb-attach-chip-dot" />

            northwind-q3-brief.pdf, uploading…
          </div>
        </div>

        {/* Step 4: Working */}

        <div className="xwb-state-block xwb-s-working">
          <div className="xwb-msg">
            <span className="xwb-msg-who">You</span>
            <span className="xwb-msg-text xwb-user">Can you pull the Northwind account summary and cross-reference the Q3 brief I just attached?</span>
          </div>

          <div className="xwb-attach-chip" style={{marginBottom:'10px'}}>
            <span className="xwb-attach-chip-dot" />

            northwind-q3-brief.pdf, uploaded
          </div>

          <div className="xwb-msg">
            <span className="xwb-msg-who">Maya</span>

            <div className="xwb-working-dots">
              <span />

              <span />

              <span />
            </div>
          </div>
        </div>

        {/* Step 5: Done */}

        <div className="xwb-state-block xwb-s-done">
          <div className="xwb-msg">
            <span className="xwb-msg-who">You</span>
            <span className="xwb-msg-text xwb-user">Can you pull the Northwind account summary and cross-reference the Q3 brief I just attached?</span>
          </div>

          <div className="xwb-attach-chip" style={{marginBottom:'10px'}}>
            <span className="xwb-attach-chip-dot" />

            northwind-q3-brief.pdf, uploaded
          </div>

          <div className="xwb-msg">
            <span className="xwb-msg-who">Maya</span>
            <span className="xwb-msg-text xwb-agent">Northwind: enterprise tier, renewal October, champion Dana Voss. Q3 brief matches: slide format confirmed, renewal risk flagged. Two open invoices. Want me to draft the renewal prep email?</span>
          </div>
        </div>
      </div>

      <div className="xwb-composer">
        <span className="xwb-composer-input">Message Maya…</span>

        <span className="xwb-composer-send" />
      </div>
    </div>
  </div>

  <div className="exp-surface-grid" style={{marginTop:'18px'}}>
    <div className="exp-surface-tile">
      <strong>"Connected" and "Working" are independent.</strong> Connected = the SSE stream is open. Working = the agent is running. A brief reconnect during a run auto-resyncs without losing context.
    </div>

    <div className="exp-surface-tile">
      <strong>Upload only after "Connected".</strong> Files silently no-op if the header still shows "Connecting…". Wait for the green dot before dropping attachments.
    </div>

    <div className="exp-surface-tile">
      <strong>Retry uses the original key.</strong> A failed message shows an error chip. Always use Retry, never retype. The deduplicate key prevents double-sends even if the original was stored before the ack failed.
    </div>
  </div>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">In the wild</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Run your store from a sun lounger.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      A cloud agent keeps running while you are away. Open the web app on your phone, ask a question, approve what needs approving, done.
    </p>
  </div>

  <div className="xc-phone">
    <div className="xc-phone-head">
      <div className="xc-phone-ava" style={{background:'linear-gradient(135deg,#E3008E,#FD840C)'}}>J</div>

      <div>
        <strong>June</strong>
        <div className="handle">@june\_actionist\_bot</div>
      </div>

      <div className="xc-phone-online">ONLINE</div>
    </div>

    <div className="xc-phone-body">
      <div className="xc-bub me">
        Give me the weekend order summary. Friday close to now.
        <span className="t">10:14</span>
      </div>

      <div className="xc-phone-badge">SEEN · READING CONTEXT</div>

      <div className="xc-phone-badge">TOOL · FETCH\_ORDERS</div>

      <div className="xc-bub them">
        Weekend snapshot (Fri 18:00 – Sun 10:14):<br />
        <strong>Orders placed:</strong> 312<br />
        <strong>Fulfilled:</strong> 287<br />
        <strong>Awaiting fulfilment:</strong> 22<br />
        <strong>Refund requests:</strong> 3 (1 flagged for manual review)
        <span className="t">10:14</span>
      </div>

      <div className="xc-bub me">
        Show me the flagged refund.
        <span className="t">10:15</span>
      </div>

      <div className="xc-phone-badge">TOOL · GET\_REFUND\_DETAIL</div>

      <div className="xc-phone-card">
        <div className="xc-phone-card-body">
          <strong>Refund request #RF-4471</strong>
          <span>Order #ORD-9820 · placed Fri 14:32</span>

          <span style={{marginTop:'5px',display:'block',opacity:'1',fontSize:'13px'}}>
            Item: Linen tote bag (qty 1). Carrier marked delivered but customer reports non-arrival. Tracking last ping: local depot Fri 17:11. No further scan.
          </span>

          <span style={{marginTop:'4px',display:'block'}}>Flagged: carrier gap over 48 h</span>
        </div>

        <div className="xc-phone-actions">
          <span style={{color:'#2da876'}}>Approve</span>
          <span style={{color:'#FB6962'}}>Deny</span>
        </div>
      </div>

      <div className="xc-bub me">
        Approve it: carrier's fault, not theirs.
        <span className="t">10:16</span>
      </div>

      <div className="xc-phone-badge">TOOL · ISSUE\_REFUND</div>

      <div className="xc-bub them">
        Done. Refund issued for order #ORD-9820. Customer notified automatically. 2 remaining refund requests are standard policy, no manual review needed.
        <span className="t">10:16</span>
      </div>
    </div>
  </div>
</div>

<Info>
  The web app works on any mobile browser. No app store install required. Open app.actionist.ai, sign in once, and your VPS agents are available from any device.
</Info>

{/* TODO(image): web-chat-active. IMAGE SPEC: Browser showing the /agents/:agentId/chat page. Header: agent name on the left, 'Connected' badge (green dot) + 'Working…' label visible. A short conversation thread with 2–3 turns. The message composer at the bottom shows 'Message [name]…' placeholder and one completed-upload file chip. The Stop button is visible in the header right side. Replace this CSS mock with the real screenshot */}

<div className="w-full py-4 xc-rise">
  <div className="mxp-window">
    <div className="mxp-window-bar">
      <span className="mxp-window-dot" />

      <span className="mxp-window-dot" />

      <span className="mxp-window-dot" />

      <span className="mxp-window-title" style={{flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>app.actionist.ai/agents/maya/chat</span>
    </div>

    <div className="xwb-mock-body">
      <div className="xwb-chat-header" style={{padding:'12px 4px',marginBottom:'8px'}}>
        <div className="xwb-chat-header-left">
          <span className="xwb-agent-label">Maya</span>
          <span style={{display:'inline-flex',alignItems:'center',gap:'6px',padding:'3px 10px',borderRadius:'999px',fontSize:'11px',fontWeight:600,letterSpacing:'.03em',border:'1px solid rgba(20,160,100,.45)',background:'rgba(20,160,100,.08)',color:'#0e8a56'}}><span style={{width:'7px',height:'7px',borderRadius:'999px',background:'#16a870',display:'inline-block'}} />Connected</span>
          <span style={{display:'inline',fontSize:'12px',fontWeight:600,color:'rgb(100 0 200)',letterSpacing:'.03em'}}>Working…</span>
        </div>

        <div style={{display:'flex',alignItems:'center',gap:'8px'}}>
          <span style={{display:'inline-flex',alignItems:'center',gap:'5px',padding:'5px 12px',borderRadius:'7px',border:'1px solid rgba(144,0,255,.3)',background:'rgba(144,0,255,.05)',color:'rgb(100 0 200)',fontSize:'12px',fontWeight:600,cursor:'pointer'}}>
            <svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor">
              <rect x="3" y="3" width="18" height="18" rx="2" />
            </svg>

            Stop
          </span>

          <span style={{display:'inline-flex',alignItems:'center',gap:'5px',padding:'5px 12px',borderRadius:'7px',border:'1px solid rgba(0,0,0,.15)',background:'transparent',fontSize:'12px',fontWeight:600,opacity:.6,cursor:'pointer'}}>Start fresh</span>
        </div>
      </div>

      <div className="xwb-convo" style={{minHeight:'unset',padding:'12px 4px'}}>
        <div className="xwb-msg">
          <span className="xwb-msg-who">You</span>
          <span className="xwb-msg-text xwb-user">Can you pull the Northwind account summary and cross-reference the Q3 brief?</span>
        </div>

        <div className="xwb-attach-chip" style={{marginBottom:'6px'}}>
          <span className="xwb-attach-chip-dot" />

          northwind-q3-brief.pdf, uploaded
        </div>

        <div className="xwb-msg">
          <span className="xwb-msg-who">Maya</span>
          <span className="xwb-msg-text xwb-agent">Northwind: enterprise tier, renewal October, champion Dana Voss. Q3 brief matches: slide format confirmed, renewal risk flagged.</span>
        </div>

        <div className="xwb-msg" style={{marginTop:'4px'}}>
          <span className="xwb-msg-who">You</span>
          <span className="xwb-msg-text xwb-user">Draft the renewal prep email.</span>
        </div>

        <div className="xwb-msg">
          <span className="xwb-msg-who">Maya</span>

          <div className="xwb-working-dots">
            <span />

            <span />

            <span />
          </div>
        </div>
      </div>

      <div className="xwb-composer">
        <span className="xwb-composer-input">Message Maya…</span>

        <span className="xwb-composer-send" />
      </div>
    </div>
  </div>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">The flow</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Chatting with a cloud agent.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Cloud agents are fully chat-enabled from the browser. Here is the full flow from landing on the Agents tab to having a conversation.
    </p>
  </div>

  <Steps>
    <Step title="Sign in" icon="key">
      Open the web app in any browser. The Clerk sign-in page appears. Use the same email/password or SSO as your desktop app. Your agents, settings, and workspace carry across automatically.
    </Step>

    <Step title="Find a cloud agent" icon="cloud">
      On the <strong>Agents</strong> tab, look for a cloud badge on the agent card. Only cloud agents support browser chat today. If the Chat button is inactive, the agent is not running in the cloud.
    </Step>

    <Step title="Open the chat" icon="message-square">
      Click <strong>Chat</strong>. The browser navigates to the agent's chat page. The header shows "Connecting to \[name]…" while the session opens, then "Connected" once it is ready. The conversation history loads up to the last 200 messages.
    </Step>

    <Step title="Send a message" icon="send">
      The composer placeholder reads "Message \[name]…". Type a message and send it; use a newline for multi-line messages. The header switches to "Working…" while the agent runs.
    </Step>

    <Step title="Attach files" icon="paperclip">
      Drop files onto the composer at any time after "Connected" appears. Each file shows a progress chip while uploading. A failed attachment shows an error chip with the file name. It does not block other attachments from sending.
    </Step>

    <Step title="Stop or start over" icon="square">
      Click <strong>Stop</strong> (visible while "Working…") to halt the agent mid-run. The header briefly shows "Stopping…". To clear the conversation and start a blank session, click <strong>Start fresh</strong> in the top-right. A confirmation dialog appears before the session resets.
    </Step>
  </Steps>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Controls</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Understanding the chat header.</h2>
  </div>

  <div className="xwb-ctrl-grid">
    <div className="exp-surface-tile xwb-ctrl-tile" style={{padding:'18px 18px 16px'}}>
      <strong>Connected / Connecting…</strong>
      <span>Reflects the SSE stream health, not whether the agent is running. A brief reconnect during a run is normal. Run state auto-resyncs.</span>
    </div>

    <div className="exp-surface-tile xwb-ctrl-tile" style={{padding:'18px 18px 16px'}}>
      <strong>Working…</strong>
      <span>Shown alongside Stop when the agent is actively executing. Independent of the connection indicator.</span>
    </div>

    <div className="exp-surface-tile xwb-ctrl-tile" style={{padding:'18px 18px 16px'}}>
      <strong>Stop</strong>
      <span>Sends a halt signal mid-run. Header shows "Stopping…" briefly, then a terminal chip: Stopped, Completed, Turn limit reached, Timed out, or Failed.</span>
    </div>

    <div className="exp-surface-tile xwb-ctrl-tile" style={{padding:'18px 18px 16px'}}>
      <strong>Start fresh</strong>
      <span>Creates a new session ID and clears the visible log. Agent memory is not deleted. Terminal chips do not persist across reload.</span>
    </div>
  </div>

  <AccordionGroup>
    <Accordion title="Connection indicator — 'Connected' / 'Connecting…'" icon="wifi" defaultOpen={true}>
      The header shows <strong>"Connecting…"</strong> while the SSE stream is opening and <strong>"Connected"</strong> once it is live. This is independent of run state. "Connected" simply means the channel is open. A brief reconnect during a run is normal; the app auto-resyncs run state from the backend without losing context.
    </Accordion>

    <Accordion title="Stop — halt a run mid-flight" icon="square">
      While the agent is running, a <strong>Stop</strong> button appears in the header alongside the <strong>"Working…"</strong> label. Clicking it sends a stop signal. The header transitions to <strong>"Stopping…"</strong> briefly, then shows a terminal chip (<strong>"Stopped"</strong>) when the run ends. Other possible terminal chips: <strong>"Completed"</strong>, <strong>"Turn limit reached"</strong>, <strong>"Timed out"</strong>, <strong>"Failed"</strong>.

      <Note>
        Terminal chips are client-only state and do not persist across page reload. Reload the page to clear them.
      </Note>
    </Accordion>

    <Accordion title="Start fresh — reset to a new session" icon="rotate-ccw">
      <strong>"Start fresh"</strong> in the top-right opens a confirmation dialog before clearing the chat. Confirming creates a new session ID and discards the client-side history. The agent's memory is not deleted, only the visible conversation log is cleared.

      <Warning>
        A failed message from the old session cannot be retried after <strong>Start fresh</strong>. If you have a pending retry, use <strong>Dismiss</strong> first if you do not want to send it, then start fresh.
      </Warning>
    </Accordion>

    <Accordion title="Retry — recover from a send failure" icon="refresh-cw">
      If a message fails to send, a red error chip appears: <strong>"Your message didn't send. Try again."</strong> with <strong>Retry</strong> and <strong>Dismiss</strong> buttons. Always use <strong>Retry</strong> rather than retyping the message. The retry carries the original deduplicate key, so the backend will not create a duplicate even if the original was persisted before the acknowledgement failed.
    </Accordion>
  </AccordionGroup>
</div>

<hr className="xc-divider" />

<div className="w-full py-10 xc-rise" id="move-to-cloud">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Cloud placement</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Where an agent runs.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      An agent placed in the cloud keeps running when your computer is off, so its schedules, triggers, and channel bots carry on without you. Placement is handled for you. There is no Move to VPS button in Agent Studio and no migration dialog to work through.
    </p>
  </div>

  <Info>
    If you are looking for a control to move an agent to the cloud, there is not one. Check the agent's current placement in <strong>Settings → Cloud Runtime</strong>, which is available in the web app.
  </Info>

  <Card title="Cloud runtime in depth" icon="cloud" href="/Folders/cloud" horizontal>
    Placement, status, and what changes when an agent runs in the cloud.
  </Card>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Status</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Checking Cloud Runtime status.</h2>
  </div>

  <div className="xwb-rt-steps">
    <div className="mxp-pipe-node xwb-rt-step is-done" style={{textAlign:'center'}}>
      <div className="xwb-rt-step-num">1</div>
      <strong>Provisioning</strong>
      <span>VPS allocated</span>
    </div>

    <div className="mxp-pipe-link" style={{width:'28px'}} />

    <div className="mxp-pipe-node xwb-rt-step is-done" style={{textAlign:'center'}}>
      <div className="xwb-rt-step-num">2</div>
      <strong>Starting</strong>
      <span>Runtime booting</span>
    </div>

    <div className="mxp-pipe-link d2" style={{width:'28px'}} />

    <div className="mxp-pipe-node xwb-rt-step is-done" style={{textAlign:'center'}}>
      <div className="xwb-rt-step-num">3</div>
      <strong>Active</strong>
      <span>Process live</span>
    </div>

    <div className="mxp-pipe-link d3" style={{width:'28px'}} />

    <div className="mxp-pipe-node xwb-rt-step is-active" style={{textAlign:'center'}}>
      <div className="xwb-rt-step-num">4</div>
      <strong>Ready</strong>
      <span>Heartbeat within 90 s</span>
    </div>
  </div>

  <Steps>
    <Step title="Open Cloud Runtime" icon="server">
      Go to <strong>Settings → Cloud Runtime</strong>. The tab is available from both the web app and the desktop app.
    </Step>

    <Step title="Read the provisioning stepper" icon="list-ordered">
      The stepper shows four stages: <strong>Provisioning → Starting → Active → Ready</strong>. The page auto-polls every 4 seconds while the status is Provisioning or Starting. You can leave the page, provisioning continues in the background.
    </Step>

    <Step title="Verify Ready status" icon="circle-check">
      <strong>Ready</strong> means the runtime is active and the last heartbeat arrived within the past 90 seconds. If the runtime is active but the heartbeat is stale, the UI shows "Starting" until a fresh heartbeat arrives. Click <strong>Refresh</strong> to manually re-poll.
    </Step>
  </Steps>

  <AccordionGroup>
    <Accordion title="Plan does not include a cloud runtime" icon="lock">
      The Cloud Runtime tab shows: "Your plan doesn't include a cloud runtime" with an <strong>Upgrade plan</strong> button that opens the billing upgrade flow. You must be on a plan that includes the hosted runtime before provisioning begins. See [Billing](/Folders/billing) for plan details.
    </Accordion>

    <Accordion title="Runtime is suspended" icon="circle-pause">
      A suspended runtime shows: "Your cloud runtime is suspended." Update your billing to resume your hosted runtime. Your data is retained while suspended.
    </Accordion>
  </AccordionGroup>
</div>

{/* TODO(image): cloud-runtime-ready. IMAGE SPEC: Settings → Cloud Runtime tab in the web app. The four-step provisioning stepper is fully lit at 'Ready'. Below it: Region, version, and last heartbeat rows with values. Telegram channel row showing 'Connected' in green. Refresh button visible in the top-right of the panel. Replace this CSS mock with the real screenshot */}

<div className="w-full py-4 xc-rise">
  <div className="mxp-window">
    <div className="mxp-window-bar">
      <span className="mxp-window-dot" />

      <span className="mxp-window-dot" />

      <span className="mxp-window-dot" />

      <span className="mxp-window-title" style={{flex:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>app.actionist.ai/settings/cloud-runtime</span>
    </div>

    <div className="xwb-mock-body">
      <div className="xwb-mock-tab-row">
        <span className="xwb-mock-tab">Account</span>
        <span className="xwb-mock-tab">Billing</span>
        <span className="xwb-mock-tab xwb-mock-tab-active">Cloud Runtime</span>
      </div>

      <div className="xwb-rt-steps" style={{margin:'8px 0 20px'}}>
        <div className="mxp-pipe-node xwb-rt-step is-done" style={{textAlign:'center'}}>
          <div className="xwb-rt-step-num">✓</div>
          <span>Provisioning</span>
        </div>

        <div className="mxp-pipe-link" style={{width:'28px',background:'linear-gradient(90deg,rgba(10,140,90,.5),rgba(10,140,90,.15))'}} />

        <div className="mxp-pipe-node xwb-rt-step is-done" style={{textAlign:'center'}}>
          <div className="xwb-rt-step-num">✓</div>
          <span>Starting</span>
        </div>

        <div className="mxp-pipe-link" style={{width:'28px',background:'linear-gradient(90deg,rgba(10,140,90,.5),rgba(10,140,90,.15))'}} />

        <div className="mxp-pipe-node xwb-rt-step is-done" style={{textAlign:'center'}}>
          <div className="xwb-rt-step-num">✓</div>
          <span>Active</span>
        </div>

        <div className="mxp-pipe-link" style={{width:'28px'}} />

        <div className="mxp-pipe-node xwb-rt-step is-active" style={{textAlign:'center'}}>
          <div className="xwb-rt-step-num">
            <span className="xwb-vps-badge-dot" style={{width:'8px',height:'8px'}} />
          </div>

          <span>Ready</span>
        </div>
      </div>

      <div className="xwb-mock-info-rows">
        <div className="xwb-mock-info-row">
          <span className="xwb-mock-info-label">Region</span>
          <span className="xwb-mock-info-val">eu-west-1</span>
        </div>

        <div className="xwb-mock-info-row">
          <span className="xwb-mock-info-label">Version</span>
          <span className="xwb-mock-info-val">runtime-2.4.1</span>
        </div>

        <div className="xwb-mock-info-row">
          <span className="xwb-mock-info-label">Last heartbeat</span>
          <span className="xwb-mock-info-val xwb-mock-info-green">12 s ago</span>
        </div>

        <div className="xwb-mock-info-row">
          <span className="xwb-mock-info-label">Telegram</span>
          <span className="xwb-mock-info-val xwb-mock-info-green">Connected</span>
        </div>
      </div>
    </div>
  </div>
</div>

<hr className="xc-divider" />

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Best practices</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Tips for the web app.</h2>
  </div>

  <AccordionGroup>
    <Accordion title="Save before you navigate away" icon="save">
      Agent Studio shows a save state in the header. Wait for it to report that changes are saved before leaving the page, or the edits you just made may not be applied to the next run.
    </Accordion>

    <Accordion title="Retry is safe; retyping is not" icon="refresh-cw">
      After a send failure, always use the <strong>Retry</strong> button in the error chip rather than retyping the message. Retry reuses the original deduplicate key, so the backend will not create a duplicate message even if the original was stored before the acknowledgement failed. A retyped message carries a new key and creates a second message.
    </Accordion>

    <Accordion title="Wait for 'Connected' before attaching files" icon="paperclip">
      File uploads start only after the session is open. If you drop a file while the header still shows "Connecting…", the upload silently no-ops. Wait for "Connected" before attaching anything.
    </Accordion>

    <Accordion title="Connection and run indicators are independent" icon="wifi">
      <strong>"Connected" / "Connecting…"</strong> reflects the health of the SSE stream; <strong>"Working…"</strong> reflects whether the agent is actively running. A brief reconnect during a run is normal. The app auto-resyncs run state from the backend and restores "Working…" without you doing anything.
    </Accordion>

    <Accordion title="Reload is safe during a run" icon="rotate-cw">
      Reloading the page during an active run is safe. The chat hook re-fetches the last 200 messages and re-checks the active run ID on mount, so the "Working…" state is restored automatically.
    </Accordion>

    <Accordion title="Upgrade before moving if your plan does not include a runtime" icon="circle-arrow-up">
      If the Cloud Runtime tab shows the "Upgrade plan" CTA, upgrade your plan first. Moving an agent to VPS requires an entitlement. The move is blocked until the plan includes a hosted runtime.
    </Accordion>
  </AccordionGroup>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-cta-panel xc-border">
    <div className="relative z-10 flex flex-col gap-5 max-w-3xl">
      <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-white leading-tight">
        Your agents don't clock out.
      </h2>

      <p className="text-base md:text-lg text-white/85">
        Move an agent to the cloud. Close your laptop. Open any browser and pick up where you left off.
      </p>

      <div className="flex flex-wrap items-center gap-3 pt-2">
        <a className="actionist-cta-btn-primary" href="https://app.actionist.ai" target="_blank" rel="noreferrer">
          Open the web app

          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M5 12h14" />

            <path d="m12 5 7 7-7 7" />
          </svg>
        </a>

        <a className="actionist-cta-btn-secondary" href="mailto:support@actionist.ai">
          Email the team
        </a>
      </div>
    </div>
  </div>
</div>

<div className="w-full pt-4 pb-8 xc-rise">
  <p className="actionist-trust-line">
    Same account. Same agents. Any browser.<br />
    Honest about gaps · No broken buttons · Auto-resync on reconnect.
  </p>
</div>

<div className="w-full pb-20 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Keep going</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Next steps.</h2>
  </div>

  <Columns cols={4}>
    <Card title="Cloud Runtime" icon="cloud" href="/Folders/cloud">
      Provision and manage the hosted runtime that keeps your cloud agents running 24/7.
    </Card>

    <Card title="Agents" icon="users" href="/Folders/agents">
      Configure Agent Studio, pick the tools an agent can use, and set its approval mode.
    </Card>

    <Card title="Channels" icon="messages-square" href="/Folders/channels">
      Connect Telegram or Slack so an agent is reachable from your phone.
    </Card>

    <Card title="Billing" icon="credit-card" href="/Folders/billing">
      Upgrade to a plan that includes a hosted runtime and unlock browser chat for all your agents.
    </Card>
  </Columns>
</div>
