> ## 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.

# Credentials Vault

> Store API keys and tokens once, use them across every agent, MCP server, skill, and channel — with rotation that propagates instantly and secrets that are never exposed.

<div className="mxp-hero xc-border">
  <div className="exp-eyebrow mxp-rise">ZERO RE-WIRING</div>

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

  <p className="mxp-hero-dek mxp-rise" style={{animationDelay:'0.13s'}}>
    Paste a token once. Every agent, MCP server, skill, and channel that needs it picks it up automatically. Rotate the key from one screen and every consumer updates on the next invocation — no re-binding, no config sweeps.
  </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">What lives in the vault.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      The Credentials Vault is the single place where Actionist stores every secret your agents need to reach the outside world. There are two kinds of objects you will find there.
    </p>
  </div>

  <Columns cols={2}>
    <Card title="Credentials" icon="key">
      A raw secret you own and manage — an API key, personal access token, header secret, or client credentials pair. You paste the value; Actionist encrypts it. The value is never shown again after save.
    </Card>

    <Card title="Connections" icon="link">
      An OAuth account object the backend holds after you complete an OAuth consent screen. Created by the OAuth install flow, not by typing a value. Both appear on the same Credentials Vault page.
    </Card>
  </Columns>

  <div className="mt-8">
    <h3 className="text-xl font-semibold tracking-tight text-gray-900 dark:text-gray-50 mb-5">The four credential kinds</h3>

    <div className="mxs-tiers">
      <div className="mxs-tier" style={{borderTopColor:'#24A4FF'}}>
        <strong>API key</strong>
        <p>Long-lived key issued by a service. Examples: SendGrid, Stripe.</p>
      </div>

      <div className="mxs-tier" style={{borderTopColor:'#9000FF'}}>
        <strong>Token</strong>
        <p>Short-lived or scoped bearer token, PAT, or bot token. Examples: GitHub PAT, Slack bot token.</p>
      </div>

      <div className="mxs-tier" style={{borderTopColor:'#AC00D9'}}>
        <strong>Header secret</strong>
        <p>A static secret sent as a custom HTTP header to an MCP or webhook endpoint.</p>
      </div>

      <div className="mxs-tier" style={{borderTopColor:'#E3008E'}}>
        <strong>Client credentials</strong>
        <p>OAuth 2.0 client ID + secret pair for server-to-server flows.</p>
      </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">Try it · lifecycle</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Reading a credential card.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Each card shows a color-coded key medallion, display name, status badge, binding-count pill, provider/kind slug, and relative last-updated time. Five action buttons appear on every card: <strong>Rename</strong>, <strong>Rotate</strong>, <strong>Test now</strong>, <strong>Disable / Enable</strong>, and <strong>Delete</strong>. The available actions shift with the credential's state. Pick a state:
    </p>
  </div>

  <div className="xcr-card-demo exp-tool-shell xc-try" style={{marginTop:0}}>
    <div className="mxp-srch-chips" style={{marginBottom:20}}>
      <label htmlFor="xcr-st-active" style={{"--xc":"110 227 181","--xcc":"#1a8a5e","--xccd":"#6EE3B5"}}><input className="mxp-r" type="radio" name="xcr-st" id="xcr-st-active" defaultChecked />Active</label>
      <label htmlFor="xcr-st-invalid" style={{"--xc":"239 68 68","--xcc":"#c0392b","--xccd":"#F87171"}}><input className="mxp-r" type="radio" name="xcr-st" id="xcr-st-invalid" />Invalid</label>
      <label htmlFor="xcr-st-disabled" style={{"--xc":"128 128 144","--xcbo":".45","--xcbg":".14"}}><input className="mxp-r" type="radio" name="xcr-st" id="xcr-st-disabled" />Disabled</label>
      <label htmlFor="xcr-st-reauth" style={{"--xc":"251 191 36","--xcc":"#b07a00","--xccd":"#FBBF24"}}><input className="mxp-r" type="radio" name="xcr-st" id="xcr-st-reauth" />Needs re-auth</label>
    </div>

    <div className="xcr-vault-card">
      <div className="xcr-card-top">
        <div className="xcr-card-meta" style={{display:'flex',alignItems:'center',gap:10,flexWrap:'wrap'}}>
          <span className="xcr-card-name">SendGrid — production</span>
          <span className="xcr-card-slug">sendgrid · api-key</span>
          <span className="xcr-binding-pill">6 bindings</span>
        </div>

        <div>
          <span className="xcr-badge xcr-badge-active"><span className="xcr-badge-dot" />Active</span>
          <span className="xcr-badge xcr-badge-invalid"><span className="xcr-badge-dot" />Invalid</span>
          <span className="xcr-badge xcr-badge-disabled"><span className="xcr-badge-dot" />Disabled</span>
          <span className="xcr-badge xcr-badge-reauth"><span className="xcr-badge-dot" />Needs re-auth</span>
        </div>
      </div>

      <div className="xcr-card-actions xcr-action-row-active">
        <span className="xcr-action-btn">Rename</span>
        <span className="xcr-action-btn">Rotate</span>
        <span className="xcr-action-btn">Test now</span>
        <span className="xcr-action-btn">Disable</span>
        <span className="xcr-action-btn xcr-danger xcr-locked" data-tip="Unbind consumers first">Delete</span>
      </div>

      <div className="xcr-card-actions xcr-action-row-invalid">
        <span className="xcr-action-btn">Rename</span>
        <span className="xcr-action-btn">Rotate</span>
        <span className="xcr-action-btn">Test now</span>
        <span className="xcr-action-btn">Disable</span>
        <span className="xcr-action-btn xcr-danger xcr-locked" data-tip="Unbind consumers first">Delete</span>
      </div>

      <div className="xcr-card-actions xcr-action-row-disabled">
        <span className="xcr-action-btn">Rename</span>
        <span className="xcr-action-btn xcr-locked" data-tip="Re-enable to rotate">Rotate</span>
        <span className="xcr-action-btn">Enable</span>
        <span className="xcr-action-btn xcr-danger xcr-locked" data-tip="Unbind consumers first">Delete</span>
      </div>

      <div className="xcr-card-actions xcr-action-row-reauth">
        <span className="xcr-action-btn">Rename</span>
        <span className="xcr-action-btn xcr-locked" data-tip="No re-auth button — create fresh credential">Rotate</span>
        <span className="xcr-action-btn">Disable</span>
        <span className="xcr-action-btn xcr-danger xcr-locked" data-tip="Unbind consumers first">Delete</span>
      </div>

      <div className="xcr-state-panel xcr-panel-active" style={{"--xp":"110 227 181","--xpo":".08","--xpb":".22"}}>
        <strong>Active</strong> — available for new and existing bindings. All five actions are available. Delete is locked because this credential still has 6 active bindings — hover it to see the tooltip.
      </div>

      <div className="xcr-state-panel xcr-panel-invalid" style={{"--xp":"239 68 68","--xpo":".06","--xpb":".2"}}>
        <strong>Invalid</strong> — the backend determined the secret is no longer valid (expired, revoked, or quota-blocked). Run <strong>Test now</strong> to see the failure reason, then <strong>Rotate</strong> with a fresh value to restore it. All bindings remain intact while you rotate.
      </div>

      <div className="xcr-state-panel xcr-panel-disabled" style={{"--xp":"128 128 144","--xpo":".07","--xpb":".22"}}>
        <strong>Disabled</strong> — paused manually. Cannot be selected in new bindings, but all binding metadata is preserved. <strong>Rotate</strong> is locked: re-enable the credential first, then rotate the value. Click Enable to restore instantly.
      </div>

      <div className="xcr-state-panel xcr-panel-reauth" style={{"--xp":"251 191 36","--xpo":".08","--xpb":".22"}}>
        <strong>Needs re-auth</strong> — the stored token requires re-authorization. There is no Re-authenticate button. Workaround: create a fresh credential for the same provider with Add credential, then re-bind every consumer to it. Disable or delete the stale credential once migrated.
      </div>
    </div>
  </div>

  <Info>
    The value field reads <em>"Saved encrypted; never shown after save."</em> This is by design. To update a saved secret, use <strong>Rotate</strong> — not delete-and-recreate.
  </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">The page</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Open the vault.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Navigate to <strong>Settings</strong>, then select the <strong>Credentials Vault</strong> tab. The toolbar at the top shows how many credentials are stored and how many active bindings are currently in use.
    </p>
  </div>

  <div className="exp-tool-shell" style={{padding:0}}>
    <div className="xcr-toolbar" style={{display:'flex',alignItems:'center',justifyContent:'space-between',flexWrap:'wrap',gap:10,padding:'12px 16px',borderRadius:'12px 12px 0 0',border:'1px solid rgb(200 200 210 / 0.6)',borderBottom:'none',background:'rgb(250 250 252)',fontSize:'12.5px'}}>
      <div style={{display:'flex',gap:12,flexWrap:'wrap'}}>
        <div style={{display:'flex',alignItems:'center',gap:5,opacity:.75}}><b className="xc-count" style={{"--xc-to":"4"}} data-suffix=" credentials stored"><span className="xc-real">4 credentials stored</span></b></div>
        <div style={{display:'flex',alignItems:'center',gap:5,opacity:.75}}><b className="xc-count" style={{"--xc-to":"6"}} data-suffix=" active bindings"><span className="xc-real">6 active bindings</span></b></div>
      </div>

      <div style={{display:'flex',gap:7}}>
        <span className="xcr-action-btn xcr-toolbar-btn">Refresh</span>
        <span className="xcr-action-btn xcr-toolbar-btn primary">Add credential</span>
      </div>
    </div>

    <div style={{padding:'16px 16px 20px', borderRadius:'0 0 12px 12px', border:'1px solid rgb(128 128 144 / 0.22)', borderTop:'none'}}>
      <div style={{display:'flex',flexDirection:'column',gap:10}}>
        <div className="xcr-vault-card">
          <div className="xcr-card-top">
            <div className="xcr-card-meta" style={{display:'flex',alignItems:'center',gap:10,flexWrap:'wrap'}}>
              <span className="xcr-card-name">SendGrid — production</span>
              <span className="xcr-card-slug">sendgrid · api-key</span>
              <span className="xcr-binding-pill">3 bindings</span>
            </div>

            <span className="xcr-badge xcr-badge-active" style={{display:'inline-flex'}}><span className="xcr-badge-dot" />Active</span>
          </div>

          <div className="xcr-card-actions" style={{display:'flex'}}>
            <span className="xcr-action-btn">Rename</span>
            <span className="xcr-action-btn">Rotate</span>
            <span className="xcr-action-btn">Test now</span>
            <span className="xcr-action-btn">Disable</span>
            <span className="xcr-action-btn xcr-danger xcr-locked" data-tip="Unbind consumers first">Delete</span>
          </div>
        </div>

        <div className="xcr-vault-card">
          <div className="xcr-card-top">
            <div className="xcr-card-meta" style={{display:'flex',alignItems:'center',gap:10,flexWrap:'wrap'}}>
              <span className="xcr-card-name">GitHub PAT — work</span>
              <span className="xcr-card-slug">github · token</span>
              <span className="xcr-binding-pill">0 bindings</span>
            </div>

            <span className="xcr-badge xcr-badge-disabled" style={{display:'inline-flex'}}><span className="xcr-badge-dot" />Disabled</span>
          </div>

          <div className="xcr-card-actions" style={{display:'flex'}}>
            <span className="xcr-action-btn">Rename</span>
            <span className="xcr-action-btn xcr-locked" data-tip="Re-enable to rotate">Rotate</span>
            <span className="xcr-action-btn">Enable</span>
            <span className="xcr-action-btn xcr-danger">Delete</span>
          </div>
        </div>

        <div className="xcr-vault-card">
          <div className="xcr-card-top">
            <div className="xcr-card-meta" style={{display:'flex',alignItems:'center',gap:10,flexWrap:'wrap'}}>
              <span className="xcr-card-name">Stripe — live</span>
              <span className="xcr-card-slug">stripe · api-key</span>
              <span className="xcr-binding-pill">2 bindings</span>
            </div>

            <span className="xcr-badge xcr-badge-invalid" style={{display:'inline-flex'}}><span className="xcr-badge-dot" />Invalid</span>
          </div>

          <div className="xcr-card-actions" style={{display:'flex'}}>
            <span className="xcr-action-btn">Rename</span>
            <span className="xcr-action-btn">Rotate</span>
            <span className="xcr-action-btn">Test now</span>
            <span className="xcr-action-btn">Disable</span>
            <span className="xcr-action-btn xcr-danger xcr-locked" data-tip="Unbind consumers first">Delete</span>
          </div>
        </div>
      </div>
    </div>
  </div>

  <Note>
    Most users find the vault nearly empty at first. When you paste a token while installing an MCP or configuring an agent's bot channel, Actionist saves it automatically. Use the vault to manage what has already been saved, or to add credentials you want available before you start building.
  </Note>

  {/* TODO(image): vault-overview — IMAGE SPEC: Full-width screenshot of Settings → Credentials Vault showing 3–4 credential cards in mixed states (one Active, one Disabled, one Invalid), the toolbar with count badges ('4 credentials stored', '6 active bindings'), the Refresh button, and the 'Add credential' button top-right. Show the color-coded key medallion, status badges, and binding-count pills on each card. — replace this CSS mock with the real screenshot */}

  <div className="exp-tool-shell" style={{padding:0,margin:'24px 0'}}>
    <div className="xcr-toolbar" style={{display:'flex',alignItems:'center',justifyContent:'space-between',flexWrap:'wrap',gap:10,padding:'12px 16px',borderRadius:'14px 14px 0 0',border:'1px solid rgb(200 200 210 / 0.6)',borderBottom:'none',background:'rgb(250 250 252)',fontSize:'12.5px'}}>
      <div style={{display:'flex',gap:12,flexWrap:'wrap'}}>
        <span style={{display:'flex',alignItems:'center',gap:5,opacity:1}}><b className="xc-count" style={{"--xc-to":"4"}} data-suffix=" credentials stored"><span className="xc-real">4 credentials stored</span></b></span>
        <span style={{display:'flex',alignItems:'center',gap:5,opacity:1}}><b className="xc-count" style={{"--xc-to":"6"}} data-suffix=" active bindings"><span className="xc-real">6 active bindings</span></b></span>
      </div>

      <div style={{display:'flex',gap:7}}>
        <span className="xcr-action-btn xcr-toolbar-btn">Refresh</span>
        <span className="xcr-action-btn xcr-toolbar-btn primary">Add credential</span>
      </div>
    </div>

    <div style={{display:'flex',flexDirection:'column',gap:10,padding:'10px 12px 12px',borderRadius:'0 0 14px 14px',border:'1px solid rgb(200 200 210 / 0.6)',borderTop:'none'}}>
      <div className="xcr-vault-card" style={{borderRadius:12}}>
        <div className="xcr-card-top">
          <div className="xcr-card-meta" style={{display:'flex',alignItems:'center',gap:10,flexWrap:'wrap'}}>
            <span className="xcr-card-name">SendGrid — production</span>
            <span className="xcr-card-slug">sendgrid · api-key</span>
            <span className="xcr-binding-pill">3 bindings</span>
          </div>

          <span className="xcr-badge xcr-badge-active" style={{display:'inline-flex'}}><span className="xcr-badge-dot" />Active</span>
        </div>
      </div>

      <div className="xcr-vault-card" style={{borderRadius:12}}>
        <div className="xcr-card-top">
          <div className="xcr-card-meta" style={{display:'flex',alignItems:'center',gap:10,flexWrap:'wrap'}}>
            <span className="xcr-card-name">GitHub PAT — work</span>
            <span className="xcr-card-slug">github · token</span>
            <span className="xcr-binding-pill">0 bindings</span>
          </div>

          <span className="xcr-badge xcr-badge-disabled" style={{display:'inline-flex'}}><span className="xcr-badge-dot" />Disabled</span>
        </div>
      </div>

      <div className="xcr-vault-card" style={{borderRadius:12}}>
        <div className="xcr-card-top">
          <div className="xcr-card-meta" style={{display:'flex',alignItems:'center',gap:10,flexWrap:'wrap'}}>
            <span className="xcr-card-name">Stripe — live</span>
            <span className="xcr-card-slug">stripe · api-key</span>
            <span className="xcr-binding-pill">2 bindings</span>
          </div>

          <span className="xcr-badge xcr-badge-invalid" style={{display:'inline-flex'}}><span className="xcr-badge-dot" />Invalid</span>
        </div>
      </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">Lifecycle</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">The full credential lifecycle.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      From first save to eventual deletion — every action you can take on a credential, and exactly how each one works.
    </p>
  </div>

  <h3 className="text-xl font-semibold tracking-tight text-gray-900 dark:text-gray-50 mb-4">Add a credential</h3>

  Click <strong>Add credential</strong> in the toolbar. An inline form expands with four required fields: <strong>Display name</strong> (e.g. <code>GitHub PAT — work</code>), <strong>Provider</strong> (lowercase identifier: <code>github</code>, <code>sendgrid</code>, <code>slack</code>), <strong>Kind</strong> (dropdown), and <strong>Value</strong> (password-masked). Click <strong>Save credential</strong>. The credential appears with an <strong>Active</strong> badge immediately.

  <div className="mt-8">
    <h3 className="text-xl font-semibold tracking-tight text-gray-900 dark:text-gray-50 mb-5">Everything else you can do</h3>

    <AccordionGroup>
      <Accordion title="Rename" icon="pen-line">
        Click <strong>Rename</strong>. The display name becomes an inline input. Press <strong>Enter</strong> to save or <strong>Escape</strong> to cancel. Provider tag and kind are unchanged — all bound consumers keep working.
      </Accordion>

      <Accordion title="Rotate" icon="refresh-cw">
        <strong>Rotate</strong> replaces the stored secret while keeping every binding intact. The next time any bound consumer runs, it picks up the new value automatically — no re-wiring needed.

        Click <strong>Rotate</strong>, paste the new secret in the <strong>New value</strong> field, and press <strong>Enter</strong>. The banner confirms: <em>"Existing bindings keep working — they pick up the new value on next use."</em>

        <Tip>Rotation is the only way to update a saved secret. You cannot rotate a disabled credential — re-enable it first.</Tip>

        {/* TODO(image): rotate-inline-form — IMAGE SPEC: Close-up of a credential card with the Rotate inline form expanded: the 'New value' field (password-masked, with show/hide toggle icon) and the 'Existing bindings keep working — they pick up the new value on next use.' info banner below it. — replace this CSS mock with the real screenshot */}

        <div className="exp-tool-shell" style={{padding:'16px 18px',margin:'24px 0'}}>
          <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:14,paddingBottom:12,borderBottom:'1px solid rgb(200 200 210 / 0.4)'}}>
            <span style={{fontSize:13,fontWeight:600}}>SendGrid — production</span>
            <span className="xcr-badge xcr-badge-active" style={{display:'inline-flex'}}><span className="xcr-badge-dot" />Active</span>
          </div>

          <div style={{display:'flex',flexDirection:'column',gap:10}}>
            <div style={{display:'flex',flexDirection:'column',gap:5}}>
              <span style={{fontSize:11,fontWeight:600,letterSpacing:'0.06em',textTransform:'uppercase',color:'rgb(120 120 140)'}}>New value</span>

              <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',padding:'8px 12px',borderRadius:8,border:'1px solid rgb(180 180 200 / 0.5)',background:'rgb(255 255 255)',fontFamily:'"JetBrains Mono",monospace'}}>
                <span style={{fontSize:13,letterSpacing:'0.15em',opacity:0.5}}>••••••••••••••••••••••••</span>
                <span style={{fontSize:'10.5px',fontWeight:600,color:'#7C00D9',cursor:'default'}}>Show</span>
              </div>
            </div>

            <div style={{fontSize:13,opacity:0.7,padding:'9px 12px',borderRadius:9,borderLeft:'3px solid rgb(144 0 255 / 0.5)',background:'rgb(144 0 255 / 0.05)',margin:0,lineHeight:1.6}}>
              Existing bindings keep working — they pick up the new value on next use.
            </div>

            <div style={{display:'flex',gap:7}}>
              <span className="xcr-action-btn xcr-toolbar-btn primary">Save</span>
              <span className="xcr-action-btn xcr-toolbar-btn">Cancel</span>
            </div>
          </div>
        </div>
      </Accordion>

      <Accordion title="Disable and re-enable" icon="toggle-left">
        Click <strong>Disable</strong>. The status changes to <strong>Disabled</strong> and the button becomes <strong>Enable</strong> (green). Disabled credentials cannot be selected in new bindings, but all binding metadata is preserved. Click <strong>Enable</strong> to restore — instant and reversible.

        <Tip>Prefer <strong>Disable</strong> over <strong>Delete</strong> for temporary pauses. Re-enabling is instant; deleting requires re-binding every consumer.</Tip>
      </Accordion>

      <Accordion title="Delete" icon="trash-2">
        Delete is permanent and guarded by two conditions — both must be true before the button activates:

        1. <strong>No active bindings.</strong> If any consumer is bound, the button tooltip reads <em>"Unbind consumers first"</em>. The message: <em>"Can't delete — still bound to N consumer(s). Unbind first."</em>
        2. <strong>Usage data loaded.</strong> If the binding count has not fully loaded, the tooltip reads <em>"Refresh to verify usage before deleting"</em>. Click <strong>Refresh</strong> in the toolbar and try again.

        Once active, click <strong>Delete</strong>, confirm the dialog (e.g. <em>Delete "GitHub PAT — work"? This is permanent.</em>), and it is done. The credential is permanently removed.

        <Danger>
          Deletion is irreversible. Any bound consumer that was not unbound first will show a <strong>StaleBindingChip</strong>: <em>"Bound credential not found — re-bind required."</em> Use <strong>Disable</strong> if you are not certain.
        </Danger>
      </Accordion>
    </AccordionGroup>
  </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">Try it · delete guard</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Delete is guarded by bindings.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      The Delete button only activates when there are zero active bindings. Toggle the binding count below and watch the button lock or unlock — hover the locked button to see the exact tooltip text the UI shows.
    </p>
  </div>

  <div className="xcr-delete-guard exp-tool-shell xc-try" style={{marginTop:0}}>
    <div className="mxp-srch-chips" style={{marginBottom:18}}>
      <label htmlFor="xcr-dg-3"><input className="mxp-r" type="radio" name="xcr-dg" id="xcr-dg-3" defaultChecked />Bindings: 3</label>
      <label htmlFor="xcr-dg-0"><input className="mxp-r" type="radio" name="xcr-dg" id="xcr-dg-0" />Bindings: 0</label>
    </div>

    <div className="xcr-dg-card exp-tool-shell" style={{margin:0,padding:'16px 18px'}}>
      <div className="xcr-dg-row" style={{display:'flex',alignItems:'center',justifyContent:'space-between',gap:12,flexWrap:'wrap'}}>
        <div style={{display:'flex',flexDirection:'column',gap:3}}>
          <span style={{fontSize:14,fontWeight:600}} className="xcr-dg-title">Stripe — live</span>

          <span style={{fontFamily:'"JetBrains Mono",monospace',fontSize:11,opacity:0.55}}>
            stripe · api-key ·&#x20;
            <span className="xcr-dg-count-3">3 active bindings</span>
            <span className="xcr-dg-count-0">0 active bindings</span>
          </span>
        </div>

        <button className="xcr-dg-del" type="button">Delete</button>
      </div>

      <div className="xcr-dg-banner xcr-dg-banner-locked">
        Can't delete — still bound to 3 consumer(s). Unbind first. Go to each agent, MCP, or skill that uses this credential and clear the binding, then return here.
      </div>

      <div className="xcr-dg-banner xcr-dg-banner-clear">
        No active bindings — delete is available. This action is permanent and cannot be undone.
      </div>
    </div>
  </div>

  <div className="exp-surface-grid" style={{marginTop:'22px'}}>
    <div className="exp-surface-tile">
      <strong>The guard is automatic.</strong> Actionist counts live bindings on every card render — you never have to remember to check.
    </div>

    <div className="exp-surface-tile">
      <strong>Prefer Disable.</strong> If you are not certain you want permanent removal, Disable stops usage without losing binding metadata. Re-enable is instant.
    </div>

    <div className="exp-surface-tile">
      <strong>Stale chips, not silent failures.</strong> If you delete a bound credential anyway, each consumer shows a red StaleBindingChip so the break is visible, not silent.
    </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">Validation</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Test a key before an agent does.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Clicking <strong>Test now</strong> on a credential card triggers a live probe against the provider's API. For supported providers, the backend makes a real API call to verify the key is active and has access. For other providers, it performs structural and format validation.
    </p>
  </div>

  <div className="exp-tool-shell" style={{padding:'18px 20px'}}>
    <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">test · SendGrid — production</span>
      </div>

      <div className="mxp-window-body" style={{minHeight:'auto',padding:'14px 18px'}}>
        <div className="mxp-stream-line mxp-s1"><span className="mxp-stream-time">req</span><span className="mxp-stream-text">GET api.sendgrid.com/v3/scopes — checking key scope...</span></div>
        <div className="mxp-stream-line mxp-s2"><span className="mxp-stream-time">200</span><span className="mxp-stream-text">Response OK. Key is active and has <em>the expected scopes</em>.</span></div>
        <div className="mxp-stream-line mxp-s3"><span className="mxp-stream-time">val</span><span className="mxp-stream-text"><em>Validated 0 min ago</em> — badge set on card.<span className="mxp-caret" /></span></div>
      </div>
    </div>

    <div style={{fontSize:13,opacity:0.7,padding:'9px 12px',borderRadius:9,borderLeft:'3px solid rgb(144 0 255 / 0.5)',background:'rgb(144 0 255 / 0.05)',marginTop:14,lineHeight:1.6}}>
      Failure path: if the key is wrong, expired, or quota-blocked, the card shows an amber <em>"Validation failed: \{reason}"</em> badge with the exact reason from the provider.
    </div>
  </div>

  {/* TODO(image): validation-badge — IMAGE SPEC: Close-up of a single credential card after 'Test now' showing both result states rendered side by side (or as a split view): left shows the green success badge ('Validated X min ago'), right shows the amber failure badge ('Validation failed: reason'). The 'Test now' button should be visible on the card. — replace this CSS mock with the real screenshot */}

  <div className="exp-tool-shell" style={{display:'flex',overflow:'hidden',padding:0,margin:'24px 0'}}>
    <div style={{flex:1,padding:20,background:'rgb(248 252 250)'}}>
      <div style={{fontSize:10,fontWeight:700,letterSpacing:'0.12em',textTransform:'uppercase',opacity:0.45,marginBottom:10}}>Success state</div>
      <div style={{fontSize:13,fontWeight:600,marginBottom:8}}>SendGrid — production</div>

      <div className="xcr-badge xcr-badge-active" style={{display:'inline-flex',marginBottom:12}}>
        <span className="xcr-badge-dot" />Validated 2 min ago
      </div>

      <div style={{display:'flex',gap:5,flexWrap:'wrap'}}>
        <span className="xcr-action-btn">Rename</span>
        <span className="xcr-action-btn">Rotate</span>
        <span className="xcr-action-btn" style={{borderColor:'rgb(144 0 255 / 0.4)',color:'#7C00D9',background:'rgb(144 0 255 / 0.07)'}}>Test now</span>
      </div>
    </div>

    <div style={{width:1,background:'rgb(200 200 210 / 0.4)',flexShrink:0}} />

    <div style={{flex:1,padding:20,background:'rgb(252 248 248)'}}>
      <div style={{fontSize:10,fontWeight:700,letterSpacing:'0.12em',textTransform:'uppercase',opacity:0.45,marginBottom:10}}>Failure state</div>
      <div style={{fontSize:13,fontWeight:600,marginBottom:8}}>Stripe — live</div>

      <div className="xcr-badge xcr-badge-reauth" style={{display:'inline-flex',marginBottom:12}}>
        <span className="xcr-badge-dot" />Validation failed: key revoked
      </div>

      <div style={{display:'flex',gap:5,flexWrap:'wrap'}}>
        <span className="xcr-action-btn">Rename</span>
        <span className="xcr-action-btn">Rotate</span>
        <span className="xcr-action-btn" style={{borderColor:'rgb(144 0 255 / 0.4)',color:'#7C00D9',background:'rgb(144 0 255 / 0.07)'}}>Test now</span>
      </div>
    </div>
  </div>

  <Tip>
    Run <strong>Test now</strong> immediately after pasting a new API key — before you build anything on top of it. It catches copy-paste errors and expired keys in seconds, before a failed agent run makes the problem hard to diagnose.
  </Tip>
</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">How it flows</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Rotate once. Every consumer updates.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      When you rotate a credential in the vault, you change one encrypted value. Every agent, MCP server, skill, and channel that holds a binding picks up the new secret on their next invocation — silently, with no re-wiring. Watch the pulse propagate:
    </p>
  </div>

  <div className="xcr-fan" style={{display:'flex',flexDirection:'column',gap:0,margin:'26px 0 10px'}}>
    <div className="exp-glass-card" style={{padding:'14px 18px',marginBottom:10,textAlign:'center',borderRadius:12}}>
      <strong style={{display:'block',fontSize:14,fontWeight:600}}>Vault — SendGrid production key rotated</strong>
      <span style={{fontSize:12,opacity:0.65}}>New value encrypted · SHA-256 hash updated · bindings intact</span>
    </div>

    <div className="xcr-fan-arrow" style={{display:'flex',justifyContent:'center',margin:'4px 0'}}>
      <svg width="20" height="28" viewBox="0 0 20 28" fill="none" xmlns="http://www.w3.org/2000/svg">
        <line x1="10" y1="0" x2="10" y2="20" stroke="rgb(144 0 255 / 0.5)" strokeWidth="2" />

        <polyline points="4,16 10,24 16,16" fill="none" stroke="rgb(144 0 255 / 0.5)" strokeWidth="2" strokeLinejoin="round" />
      </svg>
    </div>

    <div className="xcr-fan-consumers">
      <div className="xcr-fan-consumer">
        <strong>Agent — Maya</strong>
        <span>Picks up new key on next run</span>
      </div>

      <div className="xcr-fan-consumer" style={{"--ci":"1"}}>
        <strong>Skill — email-summarise</strong>
        <span>Resolves from vault on invocation</span>
      </div>

      <div className="xcr-fan-consumer" style={{"--ci":"2"}}>
        <strong>MCP — sendgrid-proxy</strong>
        <span>New value injected at connection time</span>
      </div>

      <div className="xcr-fan-consumer" style={{"--ci":"3"}}>
        <strong>Agent — Digest Bot</strong>
        <span>Picks up new key on next run</span>
      </div>

      <div className="xcr-fan-consumer" style={{"--ci":"4"}}>
        <strong>Workflow — weekly-report</strong>
        <span>Vault lookup at trigger time</span>
      </div>
    </div>
  </div>

  <div className="mt-6">
    <div className="exp-tool-shell" style={{display:'flex',flexDirection:'column',alignItems:'center',gap:0,padding:'24px 16px',margin:'18px 0'}}>
      <div className="xcr-flow-node xcr-flow-node-start">Install MCP / configure skill</div>

      <div style={{width:2,height:20,background:'linear-gradient(180deg,rgb(144 0 255 / .3),rgb(144 0 255 / .15))',borderRadius:999,margin:'0 auto'}} />

      <div className="xcr-flow-node">CredentialPicker appears</div>

      <div className="xcr-flow-branch">
        <div style={{flex:1,display:'flex',flexDirection:'column',alignItems:'center',gap:8,padding:'12px 10px',borderRadius:10,border:'1px dashed rgb(110 227 181 / 0.4)',background:'rgb(110 227 181 / 0.04)'}}>
          <div style={{fontSize:'10.5px',fontWeight:600,letterSpacing:'.06em',opacity:.6,textAlign:'center'}}>1–4 matches — ReuseHint banner</div>
          <div className="xcr-flow-node xcr-flow-node-reuse">Select existing → reused</div>
        </div>

        <div style={{flex:1,display:'flex',flexDirection:'column',alignItems:'center',gap:8,padding:'12px 10px',borderRadius:10,border:'1px dashed rgb(251 191 36 / 0.4)',background:'rgb(251 191 36 / 0.04)'}}>
          <div style={{fontSize:'10.5px',fontWeight:600,letterSpacing:'.06em',opacity:.6,textAlign:'center'}}>No match</div>
          <div className="xcr-flow-node xcr-flow-node-paste">Paste new value → created</div>
        </div>
      </div>

      <div style={{width:2,height:20,background:'linear-gradient(180deg,rgb(144 0 255 / .3),rgb(144 0 255 / .15))',borderRadius:999,margin:'0 auto'}} />

      <div className="xcr-flow-node xcr-flow-node-bound">Credential bound</div>

      <div style={{width:2,height:20,background:'linear-gradient(180deg,rgb(144 0 255 / .3),rgb(144 0 255 / .15))',borderRadius:999,margin:'0 auto'}} />

      <div className="xcr-flow-node xcr-flow-node-end">Agent / MCP uses it on run</div>
    </div>
  </div>

  <p className="text-base text-gray-600 dark:text-gray-400 mt-4 mb-2">
    The picker filters by provider and kind. If 1–4 existing active credentials match the slot, a <strong>CredentialReuseHint</strong> banner appears with one-click reuse. Selecting an existing credential records the binding without an API call. Pasting a new value with no picker selection creates and binds a new credential in one step.
  </p>

  {/* TODO(image): reuse-hint-banner — IMAGE SPEC: An MCP install modal (or skill credential drawer) with the CredentialReuseHint banner visible at the top of the credential slot: banner reads 'You already have a sendgrid credential — use it?' with a 'Use this credential' button. The CredentialPicker dropdown is visible below the banner with a matching credential pre-highlighted. — replace this CSS mock with the real screenshot */}

  <div className="exp-tool-shell" style={{background:'rgb(252 252 255)',padding:0,borderRadius:14,margin:'24px 0'}}>
    <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',padding:'12px 16px',borderBottom:'1px solid rgb(200 200 210 / 0.4)',background:'rgb(248 248 252)'}}>
      <span style={{fontSize:13,fontWeight:600}}>Install MCP · sendgrid-proxy</span>
      <span style={{fontSize:13,opacity:0.4}}>✕</span>
    </div>

    <div style={{padding:16,display:'flex',flexDirection:'column',gap:12}}>
      <div style={{display:'flex',alignItems:'center',gap:10,padding:'10px 14px',borderRadius:10,background:'rgb(144 0 255 / 0.07)',border:'1px solid rgb(144 0 255 / 0.25)',flexWrap:'wrap'}}>
        <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#7C00D9" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
          <polyline points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
        </svg>

        <span style={{fontSize:'12.5px',flex:1,color:'#7C00D9',fontWeight:500}}>You already have a sendgrid credential — use it?</span>
        <span className="xcr-action-btn xcr-toolbar-btn primary" style={{fontSize:'10.5px',padding:'3px 9px'}}>Use this credential</span>
      </div>

      <div style={{display:'flex',flexDirection:'column',gap:6}}>
        <span style={{fontSize:11,fontWeight:600,letterSpacing:'0.06em',textTransform:'uppercase',color:'rgb(120 120 140)'}}>CredentialPicker</span>

        <div style={{borderRadius:10,border:'1px solid rgb(200 200 210 / 0.5)',overflow:'hidden'}}>
          <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',padding:'9px 13px',background:'rgb(144 0 255 / 0.06)',borderBottom:'1px solid rgb(200 200 210 / 0.3)'}}>
            <span style={{fontSize:'12.5px',fontWeight:500}}>SendGrid — production</span>
            <span className="xcr-badge xcr-badge-active" style={{fontSize:9,padding:'1px 6px'}}><span className="xcr-badge-dot" />Active</span>
          </div>

          <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',padding:'9px 13px'}}>
            <span style={{fontSize:'12.5px',fontWeight:500}}>SendGrid — staging</span>
            <span className="xcr-badge xcr-badge-active" style={{fontSize:9,padding:'1px 6px'}}><span className="xcr-badge-dot" />Active</span>
          </div>
        </div>
      </div>
    </div>
  </div>

  <Note>
    <strong>Picker wins.</strong> If you have a credential selected in the picker and also paste a new value into the secret field, the picker selection takes precedence — the pasted value is silently ignored. The banner explains: <em>"A saved credential is selected. The pasted value will be ignored. To replace the bound value, rotate it from the credentials vault."</em>
  </Note>
</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 practice</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">One rotation, instant everywhere.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      How the vault pays off the moment a key changes — and how the delete guard keeps a live agent running.
    </p>
  </div>

  <div className="xc-quote">
    <p>"Rotated the SendGrid key at 9:02. All six consumers were on the new key by 9:03."</p>
    <span>Sam · Solo founder — after a scheduled key cycle</span>
  </div>

  <p className="text-base text-gray-600 dark:text-gray-400 mt-4 mb-2">
    The same principle holds whether you are managing one workspace or twelve. Here is how the vault pays off in practice:
  </p>

  <div className="xc-recipes" style={{marginTop:'16px'}}>
    <div className="xc-recipe">
      <div className="xc-recipe-who">
        <i style={{background:'linear-gradient(135deg,#9000FF,#00DBFF)'}} />

        Omar · Agency owner
      </div>

      <div className="xc-recipe-flow">
        A client rotates their SendGrid key. Omar pastes the new value into the vault — one <em>Rotate</em> on the shared credential — and all twelve agents across that client's workspace pick up the new key on their next run. <em>Zero config sweeps, zero re-binding.</em>
      </div>

      <span className="xc-recipe-save">saves \~40 min per key cycle</span>
    </div>

    <div className="xc-recipe">
      <div className="xc-recipe-who">
        <i style={{background:'linear-gradient(135deg,#FD840C,#E3008E)'}} />

        Felix · Finance & Ops
      </div>

      <div className="xc-recipe-flow">
        Felix tries to delete an old Stripe credential. The <em>Delete button is locked</em> — the vault shows it still has two active bindings. He checks the bound consumers, migrates them to the new key, and only then does <em>Delete</em> unlock. The live reconciliation agent keeps running without interruption.
      </div>

      <span className="xc-recipe-save">one broken agent avoided</span>
    </div>
  </div>
</div>

<hr className="xc-divider" />

<div id="stale-and-needs-re-auth" className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Edge cases</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Stale bindings and Needs re-auth.</h2>
  </div>

  <AccordionGroup>
    <Accordion title="Stale binding chip" icon="circle-alert">
      If a credential that was bound to a consumer (agent, MCP, or skill) has since been deleted or revoked, the consumer shows a red <strong>StaleBindingChip</strong>: <em>"Bound credential not found — re-bind required."</em> A <strong>Clear binding</strong> button lets you remove the stale reference so you can select a fresh credential. Nothing is fixed until you actively re-bind — clearing just removes the broken pointer.
    </Accordion>

    <Accordion title="Needs re-auth" icon="refresh-cw">
      A credential in <strong>Needs re-auth</strong> status means the stored token needs to be re-authorized. The card shows the <strong>Needs re-auth</strong> badge and an explanatory note.

      <Warning>
        There is currently no <strong>Re-authenticate</strong> button on credentials in this state. The workaround: create a fresh credential for the same provider and use <strong>Rotate</strong> on any affected consumer bindings to point them at the new credential.
      </Warning>
    </Accordion>
  </AccordionGroup>
</div>

<hr className="xc-divider" />

<div id="pair-a-runtime" className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Machine identities</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Pair a VPS runtime.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Agents running on a remote server — a Telegram bot or a cloud runtime you have provisioned — need to resolve vault credentials without the desktop being open. The <strong>Paired runtimes</strong> panel at the bottom of the Credentials Vault page lets you issue a one-time pairing code that grants a remote machine secure credential-resolution access.
    </p>
  </div>

  <p className="text-base text-gray-600 dark:text-gray-400 mb-6">
    The backend stores only a SHA-256 hash of the pairing code — the plaintext is never persisted after display.
  </p>

  <div className="exp-tool-shell" style={{padding:'18px 20px',marginBottom:'20px'}}>
    <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">Pairing code — VPS Telegram bot</span>
      </div>

      <div className="mxp-window-body" style={{minHeight:'auto',padding:'14px 18px'}}>
        <div className="mxp-stream-line mxp-s1"><span className="mxp-stream-time">sys</span><span className="mxp-stream-text">Label: <em>VPS — Telegram bot</em> · Host hint: fra1-bot-01.example.com</span></div>
        <div className="mxp-stream-line mxp-s2"><span className="mxp-stream-time">code</span><span className="mxp-stream-text"><em>Shown only once. Paste it into the runtime now — once you close this it's gone.</em></span></div>

        <div className="mxp-s3" style={{margin:'10px 0'}}>
          <span className="xcr-pair-code" style={{fontFamily:'"JetBrains Mono",monospace',fontSize:13,padding:'10px 16px',borderRadius:10,border:'1px solid rgb(144 0 255 / 0.35)',background:'rgb(144 0 255 / 0.05)',letterSpacing:'0.08em',color:'#7C00D9',display:'inline-block',margin:'8px 0'}}>AM-PAIR-7f4a93e2-bf01-48cd-90c0-12e4a7f63b88</span>
        </div>

        <div className="mxp-stream-line mxp-s4"><span className="mxp-stream-time">hash</span><span className="mxp-stream-text">SHA-256 hash stored. Plaintext not persisted.<span className="mxp-caret" /></span></div>
      </div>
    </div>
  </div>

  <Steps>
    <Step title="Open the Paired runtimes panel" icon="server">
      Scroll to the bottom of the <strong>Credentials Vault</strong> page. The <strong>Paired runtimes</strong> section lists all machines paired to your account.
    </Step>

    <Step title="Pair a new runtime" icon="plus">
      Click <strong>Pair runtime</strong>. Enter a <strong>Label</strong> (e.g. <code>VPS — Telegram bot</code>) and an optional <strong>Host hint</strong>, then click <strong>Issue pairing code</strong>.
    </Step>

    <Step title="Copy and paste the code" icon="key">
      The code appears once with a <strong>Copy</strong> button and the warning: <em>"Shown only once. Paste it into the runtime now — once you close this it's gone."</em> Copy immediately and paste into your runtime configuration, then click <strong>Done</strong>.
    </Step>

    <Step title="Confirm the pairing" icon="check">
      The runtime appears with its label, host hint, <strong>Active</strong> badge, and last-seen timestamp. The badge shows <strong>Online</strong> or <strong>Offline</strong> based on live polling.
    </Step>
  </Steps>

  <Warning>
    The pairing code is shown once and only once. If you close the dialog before copying it, you will need to issue a new pairing code. There is no way to retrieve the original.
  </Warning>

  {/* TODO(image): paired-runtimes-panel — IMAGE SPEC: The 'Paired runtimes' panel at the bottom of the Credentials Vault page. Show one active runtime row with: a label ('VPS — Telegram bot'), a host hint ('fra1-bot-01.example.com'), a green Online status badge, a last-seen timestamp ('2 min ago'), and a Revoke button on the right. The 'Pair runtime' button should be visible in the panel header. — replace this CSS mock with the real screenshot */}

  <div className="exp-tool-shell" style={{padding:0,margin:'24px 0'}}>
    <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',padding:'12px 16px',borderBottom:'1px solid rgb(200 200 210 / 0.4)',background:'rgb(248 248 252)'}}>
      <span style={{fontSize:'13.5px',fontWeight:600}}>Paired runtimes</span>
      <span className="xcr-action-btn xcr-toolbar-btn primary" style={{fontSize:'10.5px',padding:'3px 9px'}}>Pair runtime</span>
    </div>

    <div style={{display:'flex',alignItems:'center',gap:12,padding:'14px 16px',flexWrap:'wrap'}}>
      <div style={{flexShrink:0,width:32,height:32,borderRadius:8,background:'rgb(144 0 255 / 0.08)',border:'1px solid rgb(144 0 255 / 0.2)',display:'flex',alignItems:'center',justifyContent:'center',color:'#7C00D9'}}>
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <rect x="2" y="2" width="20" height="8" rx="2" />

          <rect x="2" y="14" width="20" height="8" rx="2" />

          <line x1="6" y1="6" x2="6.01" y2="6" />

          <line x1="6" y1="18" x2="6.01" y2="18" />
        </svg>
      </div>

      <div style={{flex:1,display:'flex',flexDirection:'column',gap:2,minWidth:0}}>
        <span style={{fontSize:13,fontWeight:600}}>VPS — Telegram bot</span>
        <span style={{fontFamily:'"JetBrains Mono",monospace',fontSize:'10.5px',opacity:0.5}}>fra1-bot-01.example.com · last seen 2 min ago</span>
      </div>

      <span className="xcr-badge xcr-badge-active" style={{display:'inline-flex'}}><span className="xcr-badge-dot" />Online</span>
      <span className="xcr-action-btn xcr-danger" style={{fontSize:'10.5px',padding:'3px 9px'}}>Revoke</span>
    </div>
  </div>

  <p className="text-base text-gray-600 dark:text-gray-400 mt-6">
    To revoke a runtime, click <strong>Revoke</strong> on its row and confirm: <em>"Revoke this runtime? It will lose access to your credentials immediately."</em> Access is cut off instantly — other runtimes and the desktop are unaffected. A revoked runtime can re-pair with a fresh code.
  </p>
</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">Best practices</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Get the most out of the vault.</h2>
  </div>

  <AccordionGroup>
    <Accordion title="Add shared credentials before installing multiple MCPs" icon="layers">
      If several MCP servers share the same API key, add the credential in Settings → Credentials Vault first. The <strong>CredentialReuseHint</strong> banner surfaces it automatically in each install modal — one paste, reused everywhere.
    </Accordion>

    <Accordion title="Use accurate provider tags" icon="tag">
      The <strong>Provider</strong> field is how the picker surfaces the right credential in the right slot. Tag credentials with the lowercase service identifier: <code>sendgrid</code>, <code>github</code>, <code>slack</code>, <code>stripe</code>. A wrong or vague tag means the picker will not auto-surface it.
    </Accordion>

    <Accordion title="Rotate, never delete and recreate" icon="refresh-cw">
      When a secret changes, use <strong>Rotate</strong>. Rotation preserves every binding — all consumers pick up the new value on next invocation, with no re-binding. Deleting and recreating requires manually re-binding every consumer.
    </Accordion>

    <Accordion title="Disable for temporary pauses, delete only when certain" icon="toggle-left">
      <strong>Disable</strong> stops a credential from being used without losing its bindings. Re-enabling is instant. Reserve <strong>Delete</strong> for credentials you are certain you will never use again — it is irreversible.
    </Accordion>

    <Accordion title="Test now immediately after saving a new key" icon="flask-conical">
      For supported providers, the backend makes a live API call to verify the key. Running <strong>Test now</strong> right after paste catches copy-paste errors and quota issues before an agent run fails.
    </Accordion>

    <Accordion title="Needs re-auth: create fresh and re-bind" icon="circle-alert">
      There is no re-authenticate button for <strong>Needs re-auth</strong> credentials. The workaround: create a fresh credential for the same provider with <strong>Add credential</strong>, then re-bind consumers to it. Disable or delete the stale credential once all consumers are migrated.
    </Accordion>
  </AccordionGroup>
</div>

<div className="w-full py-10">
  <div className="actionist-cta-panel xc-border">
    <div className="relative z-10 flex flex-col items-center gap-5 max-w-2xl mx-auto">
      <span className="actionist-eyebrow">Always in sync</span>

      <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-white leading-tight">
        One vault. Zero re-wiring.
      </h2>

      <p className="text-base md:text-lg text-white/85">
        Add a credential once. Rotate from one screen. Every consumer stays in sync on the next invocation — agents, MCPs, skills, and channels.
      </p>

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

          <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-2 pb-6">
  <p className="actionist-trust-line">
    Encrypted at rest · Never shown after save · Scoped to your workspace.<br />
    Available on the desktop app — credentials management is not available in the web app.
  </p>
</div>

<div className="w-full pb-16">
  <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="MCP servers" icon="plug" href="/Folders/mcp">
      Install MCP servers for Slack, Notion, Linear, and more — the CredentialPicker handles binding automatically during setup.
    </Card>

    <Card title="Skills" icon="puzzle" href="/Folders/skills">
      Wire credentials to skill slots so every agent that loads a skill picks up the right secret automatically.
    </Card>

    <Card title="Channels" icon="messages-square" href="/Folders/channels">
      Telegram and Slack bot tokens are stored in the vault — set up a channel and your bot token stays encrypted.
    </Card>

    <Card title="Cloud runtime" icon="cloud" href="/Folders/cloud">
      Run agents unattended on a VPS. Machine identity pairing gives the server credential-resolution access without storing raw secrets.
    </Card>
  </Columns>
</div>
