---
updatedAt: 2026-10-07T18:54:37.000Z
agentTools:
  projectIndex: https://docs.sixfab.com/llms.txt
---

# Deploy Applications

Deploy and manage ARM64 Docker containers on ALPON X5 AI and ALPON X4 edge computers from ALPON Cloud, using Docker Hub images or the private Sixfab Container Registry.

<HTMLBlock>{`
<style>
/* Theme guard: the docs container (.rm-ReadMe) decides light/dark once it carries
   data-color-mode; the html element is only the fallback before hydration. The
   :where(...) parts on the dark selectors below stop a light docs pane inside a
   non-light html element (ReadMe admin view) from picking up dark colors.
   They add no specificity. */
/* ════════════════════════════════════════════════════════════════════════
   ALPON · Deploy Applications — Shared (X4 + X5 AI)
   Page type: Cloud / Platform guide
   Brand surface: ALPON (shared) — sf-aeo--alpon, dual product pills
   Design language: Sixfab docs design system
═══════════════════════════════════════════════════════════════════════ */

/* === FONTS ============================================================== */
@font-face { font-family:'Gilroy'; src:url('https://sixfab.com/wp-content/fonts/Gilroy-Regular.woff2')   format('woff2'); font-weight:400; font-display:swap; }
@font-face { font-family:'Gilroy'; src:url('https://sixfab.com/wp-content/fonts/Gilroy-Medium.woff2')    format('woff2'); font-weight:500; font-display:swap; }
@font-face { font-family:'Gilroy'; src:url('https://sixfab.com/wp-content/fonts/Gilroy-SemiBold.woff2')  format('woff2'); font-weight:600; font-display:swap; }
@font-face { font-family:'Gilroy'; src:url('https://sixfab.com/wp-content/fonts/Gilroy-Bold.woff2')      format('woff2'); font-weight:700; font-display:swap; }
@font-face { font-family:'Gilroy'; src:url('https://sixfab.com/wp-content/fonts/Gilroy-ExtraBold.woff2') format('woff2'); font-weight:800; font-display:swap; }
@font-face { font-family:'JetBrains Mono'; src:url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono@2.304/fonts/webfonts/JetBrainsMono-Regular.woff2') format('woff2'); font-weight:400; font-style:normal; font-display:swap; }
@font-face { font-family:'JetBrains Mono'; src:url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono@2.304/fonts/webfonts/JetBrainsMono-Medium.woff2')  format('woff2'); font-weight:500; font-style:normal; font-display:swap; }

/* === DESIGN TOKENS (scoped to wrapper) ================================== */
.sf-doc {
  /* === TIER 1 — CORE BRAND ============================================== */
  --primary:       #034860;   /* Sixfab Teal */
  --secondary:     #00E0B8;   /* Signal Mint */
  --tertiary:      #1B2D45;   /* Ink Navy */
  --neutral:       #E8F5F0;   /* Mist */

  /* === TIER 2 — NEUTRAL & INTERFACE ===================================== */
  --white:         #FFFFFF;
  --light:         #F6F8F9;
  --line:          #DDE6EC;
  --slate-light:   #94A8B5;
  --slate:         #52667A;
  --deep-ink:      #10202E;

  /* === TIER 3 — AI / PRODUCT ACCENT ===================================== */
  --ai-iris:       #6B47F0;
  --ai-mist:       #F0EDFF;
  --alpon-purple:  #4F008E;   /* ALPON Gradient start (X5 AI key) */
  --alpon-cyan:    #00A6C8;   /* ALPON Gradient end (X4 key) */
  --alpon-cyan-deep: #007A8F; /* cyan surface for white text (WCAG AA 5.0:1) */

  /* === TIER 5 — SEMANTIC ================================================ */
  --success:       #00B894;
  --warning:       #F59E0B;
  --danger:        #DC2626;
  --info:          #429CBF;

  --success-text:  #047857;
  --warning-text:  #92400E;
  --danger-text:   #B91C1C;
  --info-text:     #0E4A66;

  --success-bg:    #E0F5EE;
  --warning-bg:    #FDF1DC;
  --danger-bg:     #FBE5E5;
  --info-bg:       #DCEFF7;

  /* === ON-COLORS ======================================================== */
  --on-primary:    #FFFFFF;
  --on-secondary:  #1B2D45;
  --on-neutral:    #10202E;

  /* === SPACING ========================================================== */
  --xs: 4px; --sm: 8px; --md: 16px; --lg: 24px; --xl: 32px; --2xl: 48px; --3xl: 64px;

  /* === ROUNDED ========================================================== */
  --r-sm:  4px;
  --r-md:  6px;
  --r-lg:  8px;
  --r-xl:  12px;
  --r-2xl: 16px;
  --r-full: 9999px;

  /* === GRADIENTS (named, fixed) ========================================= */
  --grad-edge-cloud:  linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
  --grad-alpon:       linear-gradient(135deg, var(--alpon-purple) 0%, var(--alpon-cyan) 100%);

  /* === SHADOWS ========================================================== */
  --shadow-sm:    0 1px 2px rgba(10, 23, 33, 0.04);
  --shadow-md:    0 4px 12px rgba(10, 23, 33, 0.06);
  --shadow-lg:    0 8px 24px rgba(10, 23, 33, 0.08);

  /* === FONTS ============================================================ */
  --font-sans: 'Gilroy', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace;

  /* === Wrapper geometry ================================================= */
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--deep-ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  width: 100%;
  max-width: none;
  padding: 0 0 var(--3xl);
}
.sf-doc * { box-sizing: border-box; }

/* === BASE TYPOGRAPHY ==================================================== */
.sf-doc h1 {
  font-family: var(--font-sans);
  font-size: 2.5rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.08;
  color: var(--deep-ink);
  margin: 0 0 16px;
}
.sf-doc h2 {
  font-family: var(--font-sans);
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.2;
  color: var(--primary);
  margin: 56px 0 16px;
  padding-bottom: 0;
  border-bottom: 0;
  scroll-margin-top: 24px;
}
.sf-doc h2:first-of-type { margin-top: 32px; }
.sf-doc h3 {
  font-family: var(--font-sans);
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.3;
  color: var(--deep-ink);
  margin: 28px 0 10px;
}
.sf-doc h4 {
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 20px 0 8px;
  color: var(--deep-ink);
}
.sf-doc p {
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--deep-ink);
  margin: 0 0 14px;
}
.sf-doc strong { font-weight: 700; color: var(--deep-ink); }
.sf-doc em { font-style: italic; }
.sf-doc ul, .sf-doc ol { padding-left: 22px; margin: 10px 0 16px; }
.sf-doc ul li, .sf-doc ol li {
  font-size: 0.9375rem;
  color: var(--deep-ink);
  line-height: 1.6;
  margin-bottom: 6px;
}
.sf-doc ul li::marker { color: var(--primary); }
.sf-doc ol li::marker { color: var(--primary); font-weight: 700; }

.sf-doc a {
  color: var(--primary);
  text-decoration: none !important;
  transition: opacity .15s;
  border-bottom: 0 !important;
}
.sf-doc a:hover, .sf-doc a:focus {
  text-decoration: none !important;
  opacity: 0.78;
}
.sf-doc a:visited { color: var(--primary); }

.sf-doc code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  font-weight: 400;
  background: var(--light);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 1px 6px;
  color: var(--primary);
}

.sf-doc hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 40px 0;
}

/* === LEAD PARAGRAPH ===================================================== */
.sf-doc .sf-lead {
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--deep-ink);
  margin: 0 0 20px;
  font-weight: 400;
}

/* === EYEBROW ============================================================ */
.sf-doc .sf-eyebrow {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.6875rem; font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--primary); margin: 0 0 12px;
}

/* === HERO (compact, single-column — Tier 1 default surface) ============= */
.sf-doc .sf-hero {
  padding: var(--xl);
  margin: 0 0 24px;
  background: var(--light);
  border: 1px solid var(--line);
  border-radius: var(--r-2xl);
}
.sf-doc .sf-hero__copy { min-width: 0; }
.sf-doc .sf-hero p.sf-hero__title,
.sf-doc .sf-hero .sf-hero__title {
  font-family: var(--font-sans);
  font-size: 2.5rem; font-weight: 800; line-height: 1.08; letter-spacing: -0.03em;
  color: var(--deep-ink); margin: 0 0 14px;
}
.sf-doc .sf-hero__lead {
  font-size: 1.0625rem; line-height: 1.6;
  color: var(--deep-ink); margin: 0 0 18px;
}
.sf-doc .sf-hero__chips { display: flex; flex-wrap: wrap; gap: 6px; }

/* === META BAR — Quickstart-style badges ================================= */
.sf-doc .sf-meta {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--sm);
  font-family: var(--font-mono);
  font-size: 0.75rem; color: var(--slate);
  margin: 0 0 var(--lg);
}
.sf-doc .sf-meta__badge {
  font-family: var(--font-sans);
  font-weight: 700; font-size: 0.75rem;
  padding: 3px 8px; border-radius: var(--r-sm);
  background: var(--light); color: var(--primary);
  border: 1px solid var(--line);
  text-decoration: none !important;
}
.sf-doc .sf-meta__badge:hover { background: var(--neutral); color: var(--primary); }
.sf-doc .sf-meta__badge--mint {
  background: var(--neutral); color: var(--primary); border-color: var(--neutral);
}
.sf-doc .sf-meta__sep { color: var(--line); }

/* === PILL / BADGE ======================================================= */
.sf-doc .sf-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-sans);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: var(--r-sm);
  background: var(--light);
  color: var(--deep-ink);
  border: 1px solid var(--line);
  white-space: nowrap;
  vertical-align: middle;
  line-height: 1.4;
}
/* Product-keyed pill variants — solid brand color of the product they label.
   ALPON X5 AI uses ALPON Purple (gradient start). ALPON X4 uses ALPON Cyan
   (gradient end). Together they preview the ALPON Gradient. Both carry
   white text — parity keeps the two products visually equal. */
.sf-doc .sf-pill--alpon-x5 {
  background: var(--alpon-purple);
  color: #FFFFFF !important;
  border-color: var(--alpon-purple);
}
.sf-doc .sf-pill--alpon-x4 {
  background: var(--alpon-cyan-deep);
  color: #FFFFFF !important;
  border-color: var(--alpon-cyan-deep);
}
.sf-doc .sf-pill--brand {
  background: var(--primary);
  color: var(--on-primary) !important;
  border-color: var(--primary);
}
.sf-doc .sf-pill--success { background: var(--success-bg); color: var(--success-text); border-color: var(--success-bg); }
.sf-doc .sf-pill--info    { background: var(--info-bg);    color: var(--info-text);    border-color: var(--info-bg); }
.sf-doc .sf-pill--warning { background: var(--warning-bg); color: var(--warning-text); border-color: var(--warning-bg); }

/* === AEO ANSWER BLOCK =================================================== */
.sf-doc .sf-aeo {
  position: relative;
  background: var(--light);
  border: 1px solid var(--line);
  border-left: 4px solid var(--primary);
  border-radius: var(--r-md);
  padding: var(--lg) var(--xl);
  margin: 0 0 var(--xl);
}
.sf-doc .sf-aeo--ai {
  background: var(--ai-mist);
  border-color: rgba(107, 71, 240, 0.20);
  border-left-color: var(--ai-iris);
}
/* The question itself is the heading — readable display type. */
.sf-doc .sf-aeo__label {
  display: block;
  font-family: var(--font-sans);
  font-size: 1.375rem; font-weight: 700;
  line-height: 1.25; letter-spacing: -0.015em;
  text-transform: none;
  color: var(--primary);
  margin: 0 0 var(--sm);
}
.sf-doc .sf-aeo--ai .sf-aeo__label { color: var(--ai-iris); }
.sf-doc .sf-aeo__text { font-size: 1rem; line-height: 1.6; color: var(--deep-ink); margin: 0; }
.sf-doc .sf-aeo__text strong { color: var(--primary); font-weight: 600; }
.sf-doc .sf-aeo--ai .sf-aeo__text strong { color: var(--ai-iris); }
.sf-doc .sf-aeo__text code { font-size: 0.8125rem; }

/* === TOC ================================================================ */
.sf-doc .sf-toc {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 12px 16px;
  background: var(--light);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  margin: 0 0 40px;
}
.sf-doc .sf-toc__label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--slate);
  margin-right: 8px;
}
.sf-doc .sf-toc__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: var(--white);
  border: 0 !important;
  box-shadow: inset 0 0 0 1px var(--line);
  border-radius: var(--r-sm);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--deep-ink) !important;
  text-decoration: none !important;
  transition: background .15s, box-shadow .15s;
  white-space: nowrap;
}
.sf-doc .sf-toc__item:hover {
  background: var(--primary);
  color: var(--on-primary) !important;
  box-shadow: inset 0 0 0 1px var(--primary);
  opacity: 1;
}
.sf-doc .sf-toc__num {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  color: var(--slate);
}
.sf-doc .sf-toc__item:hover .sf-toc__num { color: var(--secondary); }

/* === CARD =============================================================== */
.sf-doc .sf-card {
  background: var(--white);
  color: var(--deep-ink);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  padding: var(--lg);
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.sf-doc .sf-card:hover {
  border-color: var(--slate-light);
  transform: translateY(-1px);
}
.sf-doc .sf-card--highlighted {
  background: var(--neutral);
  color: var(--on-neutral);
  border: 2px solid var(--secondary);
}

/* === METHOD GRID ======================================================== */
.sf-doc .sf-method-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px;
  margin: 16px 0 32px;
}
.sf-doc .sf-method__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
}
.sf-doc .sf-method__title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--deep-ink);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.sf-doc .sf-method__title svg {
  width: 18px;
  height: 18px;
  color: var(--primary);
}
.sf-doc .sf-method-grid p {
  font-size: 0.9375rem;
  margin: 0 0 12px;
  color: var(--deep-ink);
}
.sf-doc .sf-method-grid ul {
  list-style: none !important;
  padding: 0 !important;
  margin: 12px 0 0 !important;
}
.sf-doc .sf-method-grid ul li {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 0.875rem;
  color: var(--deep-ink);
  padding: 6px 0;
  margin: 0 !important;
  border-bottom: 1px solid var(--line);
  font-weight: 500;
}
.sf-doc .sf-method-grid ul li:last-child { border-bottom: 0; }
.sf-doc .sf-method-grid ul li::marker { display: none; content: ''; }
.sf-doc .sf-method-grid ul li svg {
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  color: var(--success);
  margin-top: 4px;
}

/* === QUICK REFERENCE GRID =============================================== */
.sf-doc .sf-quick-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin: 16px 0 28px;
}
.sf-doc .sf-quick-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: border-color .15s, transform .15s;
}
.sf-doc .sf-quick-card:hover {
  border-color: var(--primary);
  transform: translateY(-1px);
}
.sf-doc .sf-quick-card__icon {
  width: 32px;
  height: 32px;
  border-radius: var(--r-md);
  background: var(--neutral);
  color: var(--primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 4px;
}
.sf-doc .sf-quick-card__icon svg { width: 16px; height: 16px; }
.sf-doc .sf-quick-card__title {
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--deep-ink);
}
.sf-doc .sf-quick-card__desc {
  font-size: 0.8125rem;
  color: var(--slate);
  line-height: 1.5;
}
.sf-doc .sf-quick-card__desc strong { color: var(--deep-ink); }

/* === ICON LIST ========================================================== */
.sf-doc .sf-icon-list {
  list-style: none !important;
  padding: 0 !important;
  margin: 14px 0 16px !important;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.sf-doc .sf-icon-list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 0.9375rem;
  color: var(--deep-ink);
  line-height: 1.55;
  padding: 0 !important;
  margin: 0 !important;
}
.sf-doc .sf-icon-list li::marker { display: none; content: ''; }
.sf-doc .sf-icon-list svg {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  color: var(--success);
  margin-top: 2px;
}

/* === CALLOUT ============================================================ */
.sf-doc .sf-callout {
  display: flex;
  flex-direction: column;
  gap: 6px;
  border-radius: var(--r-md);
  padding: 14px 18px;
  margin: 24px 0;
  border-left: 4px solid;
}
.sf-doc .sf-callout__header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1;
}
.sf-doc .sf-callout__header svg { width: 18px; height: 18px; flex-shrink: 0; }
.sf-doc .sf-callout__content {
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--deep-ink);
}
.sf-doc .sf-callout__content p { margin: 0; font-size: 0.9375rem; color: inherit; }
.sf-doc .sf-callout__content p + p { margin-top: 8px; }
.sf-doc .sf-callout--info     { background: var(--info-bg);    border-left-color: var(--info); }
.sf-doc .sf-callout--info     .sf-callout__header { color: var(--info-text); }
.sf-doc .sf-callout--success  { background: var(--success-bg); border-left-color: var(--success); }
.sf-doc .sf-callout--success  .sf-callout__header { color: var(--success-text); }
.sf-doc .sf-callout--warning  { background: var(--warning-bg); border-left-color: var(--warning); }
.sf-doc .sf-callout--warning  .sf-callout__header { color: var(--warning-text); }
.sf-doc .sf-callout--danger   { background: var(--danger-bg);  border-left-color: var(--danger); }
.sf-doc .sf-callout--danger   .sf-callout__header { color: var(--danger-text); }

/* ════════════════════════════════════════════════════════════════════════
   STEP LIST — adopted from ALPON X5 AI OS (sf-step-list--ai)
   AI Iris purple numbered circles. Header row uses grid so the circle and
   the step title share a baseline. Bypasses ReadMe global list overrides.
   ════════════════════════════════════════════════════════════════════════ */
.sf-doc .sf-step-list {
  position: relative;
  padding: 0;
  margin: var(--lg) 0 var(--xl);
  list-style: none !important;
}
.sf-doc .sf-step-list::before {
  content: '';
  position: absolute;
  left: 23px;
  top: 48px;
  bottom: 24px;
  width: 2px;
  background: var(--line);
  z-index: 0;
}
.sf-doc .sf-step-list--ai::before {
  background: linear-gradient(180deg, var(--ai-iris) 0%, rgba(107,71,240,.20) 100%);
}
.sf-doc .sf-step {
  position: relative;
  z-index: 1;
  padding-bottom: var(--2xl);
  scroll-margin-top: 24px;
}
.sf-doc .sf-step:last-child { padding-bottom: 0; }

/* Header row: 48px number + title, both centered on the same baseline. */
.sf-doc .sf-step__header {
  display: grid;
  grid-template-columns: 48px 1fr;
  align-items: center;
  gap: 0 22px;
  margin-bottom: var(--md);
}
.sf-doc .sf-step__num {
  width: 48px; height: 48px;
  border-radius: var(--r-full);
  background: var(--primary);
  color: var(--on-primary);
  font-family: var(--font-sans);
  font-size: 1.0625rem;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 5px var(--white), 0 4px 10px rgba(10,23,33,.10);
  align-self: center;
  flex-shrink: 0;
}
.sf-doc .sf-step-list--ai .sf-step__num {
  background: var(--ai-iris);
  color: var(--white);
  box-shadow: 0 0 0 5px var(--white), 0 6px 14px rgba(107,71,240,.32);
}
.sf-doc .sf-step__title {
  font-family: var(--font-sans);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--deep-ink);
  line-height: 1.15;
  margin: 0;
  padding: 0;
  align-self: center;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.sf-doc .sf-step__title code { font-size: 1.125rem; }
.sf-doc .sf-step__badge {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--ai-mist);
  color: var(--ai-iris);
  padding: 3px 9px;
  border-radius: var(--r-sm);
  border: 1px solid rgba(107,71,240,.20);
}

/* Body content: indented to match the title column (48 + 22 = 70px) */
.sf-doc .sf-step__body {
  padding-left: 70px;
  min-width: 0;
}
.sf-doc .sf-step__body p {
  font-size: 1rem;
  line-height: 1.65;
  margin: 0 0 14px;
}
.sf-doc .sf-step__body ul,
.sf-doc .sf-step__body ol {
  margin: 6px 0 14px;
}
.sf-doc .sf-step__body ul li,
.sf-doc .sf-step__body ol li {
  font-size: 0.9375rem;
  margin-bottom: 4px;
}
.sf-doc .sf-step__hint {
  font-size: 0.875rem;
  color: var(--slate);
  margin: 6px 0 0;
}

/* === TERMINAL =========================================================== */
.sf-doc .sf-terminal {
  background: #0d1117 !important;
  border: 1px solid #30363d;
  border-radius: var(--r-lg);
  margin: 14px 0 18px;
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
.sf-doc .sf-terminal__header {
  display: flex !important;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  background: #161b22 !important;
  border-bottom: 1px solid #30363d;
}
.sf-doc .sf-terminal__dot {
  width: 11px; height: 11px;
  border-radius: var(--r-full);
  flex-shrink: 0;
}
.sf-doc .sf-terminal__title {
  margin-left: 8px;
  font-family: var(--font-mono) !important;
  font-size: 0.75rem !important;
  color: #8B949E !important;
  font-weight: 500;
}
.sf-doc .sf-terminal__body {
  padding: 14px 16px;
  overflow-x: auto;
}
.sf-doc .sf-terminal__body pre {
  margin: 0 !important;
  padding: 0 !important;
  background: transparent !important;
  border: 0 !important;
  font-family: var(--font-mono) !important;
  font-size: 0.825rem !important;
  line-height: 1.65 !important;
  color: #e6edf3 !important;
  white-space: pre;
}
.sf-doc .t-dim   { color: #8B949E !important; }
.sf-doc .t-green { color: #56d364 !important; font-weight: 600; }
.sf-doc .t-blue  { color: #79c0ff !important; }
.sf-doc .t-yel   { color: #e3b341 !important; }
.sf-doc .t-pp    { color: #d2a8ff !important; }
.sf-doc .t-red   { color: #ff7b72 !important; }
.sf-doc .t-hl    { color: #56d364 !important; font-weight: 600; }

/* === FIGURE & LIGHTBOX ================================================== */
.sf-doc .sf-figure {
  margin: 16px 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--white);
}
.sf-doc .sf-figure a {
  display: block;
  cursor: zoom-in;
  text-decoration: none !important;
}
.sf-doc .sf-figure img {
  width: 100%;
  height: auto;
  display: block;
  transition: opacity .15s;
}
.sf-doc .sf-figure a:hover img { opacity: 0.94; }
.sf-doc .sf-figure figcaption {
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  color: var(--slate);
  padding: 10px 14px;
  background: var(--light);
  border-top: 1px solid var(--line);
  line-height: 1.5;
  font-style: italic;
}
.sf-doc .sf-fig-anchor {
  display: block;
  position: relative;
  top: -80px;
  visibility: hidden;
}
.sf-doc .sf-lightbox {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(10, 23, 33, 0.92);
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.sf-doc .sf-lightbox:target { display: flex; }
.sf-doc .sf-lightbox__backdrop {
  position: absolute;
  inset: 0;
  cursor: zoom-out;
}
.sf-doc .sf-lightbox__close {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 36px; height: 36px;
  background: rgba(255,255,255,0.12);
  color: #fff !important;
  border: 1px solid rgba(255,255,255,0.25);
  border-radius: var(--r-full);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
  text-decoration: none !important;
  transition: background .15s, transform .15s;
}
.sf-doc .sf-lightbox__close:hover {
  background: rgba(255,255,255,0.22);
  transform: rotate(90deg);
}
.sf-doc .sf-lightbox__close svg {
  width: 18px; height: 18px;
  stroke: #fff;
  stroke-width: 2.2;
  fill: none;
}
.sf-doc .sf-lightbox__inner {
  position: relative;
  z-index: 1;
  max-width: 1200px;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.sf-doc .sf-lightbox__img-wrap {
  display: block;
  cursor: zoom-out;
  text-decoration: none !important;
  max-width: 100%;
}
.sf-doc .sf-lightbox__img-wrap img {
  display: block;
  max-width: 100%;
  max-height: 78vh;
  height: auto;
  border-radius: var(--r-md);
  border: 1px solid rgba(255,255,255,0.12);
}
.sf-doc .sf-lightbox__caption {
  margin-top: 14px;
  color: rgba(255,255,255,0.85);
  font-size: 0.875rem;
  font-family: var(--font-sans);
  text-align: center;
  max-width: 700px;
  line-height: 1.5;
}

/* === CONFIG REFERENCE =================================================== */
.sf-doc .sf-config-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 16px 0 24px;
}
.sf-doc .sf-config-row {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--white);
}
/* Key column: stack parameter name (top) and type tag (bottom) so neither
   has to fight the 200px column width. Fixes the "REQUIRE D" hard-wrap and
   awkward Container Name line-break shown in the screenshot. */
.sf-doc .sf-config-key {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 8px;
  padding: 14px 16px;
  background: var(--light);
  border-right: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--primary);
  line-height: 1.25;
}
.sf-doc .sf-config-key__name {
  display: block;
  word-break: break-word;
  font-family: var(--font-mono);
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--primary);
  letter-spacing: -0.005em;
}
.sf-doc .sf-config-key__tag {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: var(--r-sm);
  background: var(--neutral);
  color: var(--primary);
  white-space: nowrap;
  line-height: 1;
}
.sf-doc .sf-config-key__tag--req {
  background: var(--success-bg);
  color: var(--success-text);
}
.sf-doc .sf-config-key__tag--adv {
  background: var(--warning-bg);
  color: var(--warning-text);
}
.sf-doc .sf-config-val {
  padding: 12px 14px;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--deep-ink);
}
.sf-doc .sf-port {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: var(--r-sm);
  background: var(--neutral);
  color: var(--primary);
  border: 1px solid var(--line);
}

/* === ACCESS METHOD CARDS ================================================ */
.sf-doc .sf-access-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
  margin: 16px 0 24px;
}
.sf-doc .sf-access-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 16px 18px;
  transition: border-color .15s, transform .15s;
}
.sf-doc .sf-access-card:hover {
  border-color: var(--primary);
  transform: translateY(-1px);
}
.sf-doc .sf-access-card__icon {
  width: 36px;
  height: 36px;
  border-radius: var(--r-md);
  background: var(--neutral);
  color: var(--primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 10px;
}
.sf-doc .sf-access-card__icon svg { width: 18px; height: 18px; stroke: currentColor; stroke-width: 2; fill: none; }
.sf-doc .sf-access-card__title {
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--deep-ink);
  margin-bottom: 4px;
}
.sf-doc .sf-access-card__desc {
  font-size: 0.8125rem;
  color: var(--slate);
  line-height: 1.55;
}

/* === ACTION LIST (lifecycle) ============================================ */
.sf-doc .sf-action-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 10px;
  margin: 16px 0 20px;
}
.sf-doc .sf-action-item {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 12px 14px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.sf-doc .sf-action-item__icon {
  width: 28px;
  height: 28px;
  border-radius: var(--r-md);
  background: var(--neutral);
  color: var(--primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.sf-doc .sf-action-item__icon svg { width: 14px; height: 14px; stroke: currentColor; stroke-width: 2; fill: none; }
.sf-doc .sf-action-item__title {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--deep-ink);
  margin-bottom: 3px;
}
.sf-doc .sf-action-item__desc {
  font-size: 0.8125rem;
  color: var(--slate);
  line-height: 1.5;
}
.sf-doc .sf-action-item__desc code { font-size: 0.75rem; }

/* ════════════════════════════════════════════════════════════════════════
   VIDEO CARD — clickable YouTube thumbnail + chapter timestamps
   (alpon-cloud.html style). No inline iframe. Thumbnail links out to
   YouTube; chapter list shows clickable timestamps deep-linking to the
   video at the given time offset. AI Iris accent on timestamps + hover.
   ════════════════════════════════════════════════════════════════════════ */
/* Single-column stack: head → thumbnail (full-width) → chapters (full-width).
   The video reads as the hero of the card; chapters sit below it as a
   browsable index, no longer competing with the thumbnail for horizontal
   space. Chapter list expands into a responsive multi-column grid since
   it now has the full card width to use. */
.sf-doc .sf-video {
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin: 0 0 var(--xl);
  padding: var(--xl);
  background: var(--light);
  border: 1px solid var(--line);
  border-radius: var(--r-2xl);
}
.sf-doc .sf-video__head {
  margin: 0;
}
.sf-doc .sf-video__head h3 {
  margin: 4px 0 6px;
  color: var(--primary);
  font-size: 1.5rem;
  line-height: 1.15;
  font-weight: 700;
  letter-spacing: -0.015em;
}
.sf-doc .sf-video__head p {
  margin: 0;
  color: var(--slate);
  font-size: 0.9375rem;
}
.sf-doc .sf-video__thumb {
  position: relative;
  display: block;
  border-radius: var(--r-xl);
  overflow: hidden;
  text-decoration: none !important;
  border: 1px solid var(--line);
  background: var(--deep-ink);
  aspect-ratio: 16 / 9;
  width: 100%;
}
.sf-doc .sf-video__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .3s ease, filter .25s ease;
  filter: brightness(0.92);
}
.sf-doc .sf-video__thumb:hover img {
  transform: scale(1.03);
  filter: brightness(1);
}
.sf-doc .sf-video__play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.sf-doc .sf-video__play span {
  width: 72px;
  height: 72px;
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, 0.95);
  color: var(--ai-iris);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 30px rgba(10, 23, 33, 0.35);
  transition: transform .2s ease, background .2s ease;
}
.sf-doc .sf-video__thumb:hover .sf-video__play span {
  transform: scale(1.08);
  background: var(--white);
}
.sf-doc .sf-video__play svg {
  width: 26px;
  height: 26px;
  margin-left: 4px;
  fill: currentColor;
}
.sf-doc .sf-video__chapters {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.sf-doc .sf-video__chap-label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--slate);
  margin: 0 0 10px;
}
.sf-doc .sf-video__chap-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  padding: 0 !important;
  margin: 0 !important;
  list-style: none !important;
}
.sf-doc .sf-video__chap-list li {
  margin: 0 !important;
  padding: 0;
  list-style: none !important;
}
.sf-doc .sf-video__chap-list li::marker { display: none; content: ''; }
.sf-doc .sf-video__chap {
  display: grid;
  grid-template-columns: 56px 1fr;
  align-items: baseline;
  gap: 12px;
  padding: 8px 10px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  font-size: 0.875rem;
  text-decoration: none !important;
  color: var(--deep-ink) !important;
  transition: border-color .15s, transform .15s;
}
.sf-doc .sf-video__chap:hover {
  border-color: var(--ai-iris);
  background: var(--ai-mist);
  transform: translateX(2px);
  opacity: 1;
}
.sf-doc .sf-video__chap-time {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--ai-iris);
  letter-spacing: 0.02em;
}
.sf-doc .sf-video__chap-title {
  font-weight: 600;
  color: var(--deep-ink);
  line-height: 1.4;
}
.sf-doc .sf-video__chap-title code {
  font-size: 0.75rem;
  padding: 1px 5px;
}
/* Group wrapper for consecutive sf-video sections (Part 1 + Part 2) */
.sf-doc .sf-video-group {
  display: flex;
  flex-direction: column;
  gap: var(--lg);
  margin: var(--md) 0 var(--xl);
}
.sf-doc .sf-video-group .sf-video { margin: 0; }


/* ════════════════════════════════════════════════════════════════════════
   ISSUE CARD (accordion redesign — sf-issue + category modifier)
   Adopted from ai-hat-troubleshooting Common issues accordion.

   Element: <details class="sf-issue sf-issue--<cat>">
              <summary class="sf-issue__head"> ... </summary>
              <div class="sf-issue__body"> ... </div>
            </details>

   Pattern: collapsed-by-default accordion. Summary is a single 56px row
   with category dot, category pill, title, and a chevron that rotates
   when open. Stacked items share one rounded shell (sf-issue-group);
   each item opens to reveal Cause / Fix without scrolling past siblings.

   Categories (color-keyed):
     --ai      → AI feature  (--ai-mist / --ai-iris)
     --sw      → Software / Runtime / Auth / Network (--info-bg / --info)
     --hw      → Hardware / Image (--warning-bg / --warning)
     --warning → Port / Quota / Conflict (--warning-bg / --warning)
     --pwr     → Power / Critical (--danger-bg / --danger)
   ════════════════════════════════════════════════════════════════════════ */

/* Group container — single rounded shell, collapse sibling borders */
.sf-doc .sf-issue-group {
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--white);
  box-shadow: var(--shadow-sm);
  margin: var(--md) 0 var(--xl);
}

.sf-doc .sf-issue {
  position: relative;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  margin: 0;
  border-radius: 0;
  overflow: visible;
}
.sf-doc .sf-issue:last-child { border-bottom: 0; }
.sf-doc .sf-issue::before {
  /* Left color rail — appears on hover / open */
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--primary);
  opacity: 0;
  transition: opacity .15s ease;
  pointer-events: none;
}
.sf-doc .sf-issue[open]::before,
.sf-doc .sf-issue:hover::before { opacity: 1; }

/* Summary row — flex, single line, custom chevron (native marker hidden) */
.sf-doc details.sf-issue > summary.sf-issue__head,
.sf-doc .sf-issue > summary.sf-issue__head,
.sf-doc .sf-issue__head {
  display: flex !important;
  flex-wrap: nowrap !important;
  align-items: center !important;
  gap: 14px !important;
  padding: 14px var(--lg) 14px calc(var(--lg) + 6px);
  cursor: pointer;
  user-select: none;
  list-style: none !important;
  transition: background .15s ease;
  outline: 0;
  background: var(--white);
  border: 0;
}
.sf-doc details.sf-issue > summary.sf-issue__head > .sf-issue__dot,
.sf-doc .sf-issue > summary.sf-issue__head > .sf-issue__dot {
  flex: 0 0 10px !important;
  display: block !important;
  align-self: center !important;
}
.sf-doc details.sf-issue > summary.sf-issue__head > .sf-issue__cat,
.sf-doc .sf-issue > summary.sf-issue__head > .sf-issue__cat {
  flex: 0 0 auto !important;
  display: inline-flex !important;
  align-items: center !important;
  align-self: center !important;
}
.sf-doc details.sf-issue > summary.sf-issue__head > .sf-issue__title,
.sf-doc .sf-issue > summary.sf-issue__head > .sf-issue__title {
  flex: 1 1 auto !important;
  display: inline-flex !important;
  align-items: center !important;
  align-self: center !important;
  height: 24px !important;
  margin: 0 !important;
  padding: 0 !important;
}
.sf-doc details.sf-issue > summary.sf-issue__head > .sf-issue__chev,
.sf-doc .sf-issue > summary.sf-issue__head > .sf-issue__chev {
  flex: 0 0 20px !important;
  display: block !important;
  align-self: center !important;
}
.sf-doc .sf-issue__head::-webkit-details-marker { display: none !important; }
.sf-doc .sf-issue__head::marker { content: '' !important; display: none !important; }
.sf-doc .sf-issue:hover .sf-issue__head { background: var(--light); }
.sf-doc .sf-issue[open] .sf-issue__head { background: var(--light); border-bottom: 1px solid var(--line); }
.sf-doc .sf-issue__head:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: -2px;
}

/* Category dot */
.sf-doc .sf-issue__dot {
  width: 10px; height: 10px;
  border-radius: var(--r-full);
  background: var(--primary);
  flex-shrink: 0;
}

/* Category pill */
.sf-doc .sf-issue__cat {
  font-family: var(--font-mono);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase;
  padding: 5px 10px !important;
  border-radius: var(--r-sm);
  white-space: nowrap;
  line-height: 1 !important;
  background: var(--light);
  color: var(--slate);
  display: inline-flex !important;
  align-items: center !important;
  height: 24px !important;
}

/* Title (typography only — layout set on the row above) */
.sf-doc .sf-issue__title {
  font-family: var(--font-sans);
  font-size: 0.9375rem !important;
  font-weight: 600;
  letter-spacing: -0.005em;
  line-height: 1 !important;
  color: var(--deep-ink);
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: none;
}
.sf-doc .sf-issue[open] .sf-issue__title { font-weight: 700; color: var(--primary); }
.sf-doc .sf-issue__title code {
  font-size: 0.8125rem;
  vertical-align: baseline;
  padding: 1px 6px;
  white-space: nowrap;
  line-height: 1;
}

/* Chevron — rotates on open */
.sf-doc .sf-issue__chev {
  width: 20px; height: 20px;
  color: var(--slate);
  flex-shrink: 0;
  transition: transform .2s ease;
}
.sf-doc .sf-issue[open] .sf-issue__chev {
  transform: rotate(180deg);
  color: var(--primary);
}

/* Body — only rendered while [open] (native browser behavior) */
.sf-doc .sf-issue__body {
  padding: var(--lg) var(--lg) var(--xl) calc(var(--lg) + 6px);
  background: var(--white);
}

/* H4 inside issue body — Cause / Fix section beats with colored dot */
.sf-doc .sf-issue__body h4 {
  font-family: var(--font-sans);
  font-size: 0.75rem; font-weight: 800;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--slate);
  margin: var(--lg) 0 10px;
  display: flex; align-items: center; gap: 10px;
  line-height: 1;
}
.sf-doc .sf-issue__body h4:first-child { margin-top: 0; }
.sf-doc .sf-issue__body h4::before {
  content: '';
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: var(--r-full);
  background: var(--primary);
  flex-shrink: 0;
}
.sf-doc .sf-issue__body p {
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--deep-ink);
  margin: 0 0 10px;
}
.sf-doc .sf-issue__body p:last-child { margin-bottom: 0; }
.sf-doc .sf-issue__body strong { color: var(--primary); }
.sf-doc .sf-issue__body code { font-size: 0.8125rem; }

/* Category modifier — rail + dot + cat pill + open-state title + h4 dot */
.sf-doc .sf-issue--ai::before        { background: var(--ai-iris); }
.sf-doc .sf-issue--ai .sf-issue__dot { background: var(--ai-iris); }
.sf-doc .sf-issue--ai .sf-issue__cat { color: var(--ai-iris); background: var(--ai-mist); }
.sf-doc .sf-issue--ai[open] .sf-issue__title { color: var(--ai-iris); }
.sf-doc .sf-issue--ai[open] .sf-issue__chev  { color: var(--ai-iris); }
.sf-doc .sf-issue--ai .sf-issue__body h4::before { background: var(--ai-iris); }

.sf-doc .sf-issue--sw::before        { background: var(--info); }
.sf-doc .sf-issue--sw .sf-issue__dot { background: var(--info); }
.sf-doc .sf-issue--sw .sf-issue__cat { color: var(--info-text); background: var(--info-bg); }
.sf-doc .sf-issue--sw[open] .sf-issue__title { color: var(--info-text); }
.sf-doc .sf-issue--sw[open] .sf-issue__chev  { color: var(--info); }
.sf-doc .sf-issue--sw .sf-issue__body h4::before { background: var(--info); }

.sf-doc .sf-issue--hw::before        { background: var(--warning); }
.sf-doc .sf-issue--hw .sf-issue__dot { background: var(--warning); }
.sf-doc .sf-issue--hw .sf-issue__cat { color: var(--warning-text); background: var(--warning-bg); }
.sf-doc .sf-issue--hw[open] .sf-issue__title { color: var(--warning-text); }
.sf-doc .sf-issue--hw[open] .sf-issue__chev  { color: var(--warning); }
.sf-doc .sf-issue--hw .sf-issue__body h4::before { background: var(--warning); }

.sf-doc .sf-issue--warning::before        { background: var(--warning); }
.sf-doc .sf-issue--warning .sf-issue__dot { background: var(--warning); }
.sf-doc .sf-issue--warning .sf-issue__cat { color: var(--warning-text); background: var(--warning-bg); }
.sf-doc .sf-issue--warning[open] .sf-issue__title { color: var(--warning-text); }
.sf-doc .sf-issue--warning[open] .sf-issue__chev  { color: var(--warning); }
.sf-doc .sf-issue--warning .sf-issue__body h4::before { background: var(--warning); }

.sf-doc .sf-issue--pwr::before        { background: var(--danger); }
.sf-doc .sf-issue--pwr .sf-issue__dot { background: var(--danger); }
.sf-doc .sf-issue--pwr .sf-issue__cat { color: var(--danger-text); background: var(--danger-bg); }
.sf-doc .sf-issue--pwr[open] .sf-issue__title { color: var(--danger-text); }
.sf-doc .sf-issue--pwr[open] .sf-issue__chev  { color: var(--danger); }
.sf-doc .sf-issue--pwr .sf-issue__body h4::before { background: var(--danger); }


/* === CTA CARD =========================================================== */
.sf-doc .sf-cta-card {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px 20px;
  background: var(--white);
  border: 1px solid var(--line);
  border-left: 4px solid var(--primary);
  border-radius: var(--r-lg);
  margin: 12px 0;
  text-decoration: none !important;
  transition: border-color .15s, transform .15s, box-shadow .15s;
}
.sf-doc .sf-cta-card:hover {
  border-color: var(--primary);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
  opacity: 1 !important;
}
.sf-doc .sf-cta-card__icon {
  width: 40px;
  height: 40px;
  border-radius: var(--r-md);
  background: var(--neutral);
  color: var(--primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.sf-doc .sf-cta-card__icon svg { width: 20px; height: 20px; stroke: currentColor; stroke-width: 2; fill: none; }
.sf-doc .sf-cta-card__body {
  flex: 1;
  min-width: 0;
}
.sf-doc .sf-cta-card__eyebrow {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--slate);
  display: block;
  margin-bottom: 3px;
}
.sf-doc .sf-cta-card__title {
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 700;
  color: var(--deep-ink);
}
.sf-doc .sf-cta-card__arrow {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  color: var(--primary);
  transition: transform .15s;
}
.sf-doc .sf-cta-card__arrow svg { stroke: currentColor; stroke-width: 2; fill: none; }
.sf-doc .sf-cta-card:hover .sf-cta-card__arrow { transform: translateX(3px); }

/* === RELATED CARDS ====================================================== */
.sf-doc .sf-related { margin: 56px 0 0; }
.sf-doc .sf-related h2 { margin-top: 0; }
.sf-doc .sf-related__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
  margin-top: 18px;
}
.sf-doc .sf-related__card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  padding: 18px;
  text-decoration: none !important;
  transition: border-color .15s, transform .15s;
}
.sf-doc .sf-related__card:hover {
  border-color: var(--primary);
  transform: translateY(-2px);
  opacity: 1 !important;
}
.sf-doc .sf-related__icon {
  width: 36px; height: 36px;
  border-radius: var(--r-md);
  background: var(--neutral);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 6px;
}
.sf-doc .sf-related__icon svg { width: 18px; height: 18px; stroke: currentColor; stroke-width: 2; fill: none; }
.sf-doc .sf-related__title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--deep-ink) !important;
}
.sf-doc .sf-related__desc {
  font-size: 0.8125rem;
  color: var(--slate);
  line-height: 1.55;
}

/* ════════════════════════════════════════════════════════════════════════
   DARK MODE — token swap + role swap (DESIGN.md §3.5, design-language §9)
   The attribute branch below is mirrored verbatim into the
   prefers-color-scheme branch further down; keep them in sync.
   ════════════════════════════════════════════════════════════════════════ */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc {
  --primary:       #00E0B8;
  --secondary:     #00E0B8;
  --tertiary:      #1B2D45;
  --neutral:       #1F3247;
  --white:         #1B2D45;
  --light:         #14222F;
  --line:          #2A3A4D;
  --slate:         #B5C3CE;
  --slate-light:   #6B8294;
  --deep-ink:      #E8F5F0;

  --ai-iris:       #B59CFF;
  --ai-mist:       #1E1A33;

  --success-bg:    #052E1B;
  --warning-bg:    #2A1F05;
  --danger-bg:     #2A0E0E;
  --info-bg:       #0A2E3F;
  --success-text:  #34D399;
  --warning-text:  #FBBF24;
  --danger-text:   #F87171;
  --info-text:     #5CD3EE;

  --on-primary:    #1B2D45;
  --on-neutral:    #E8F5F0;

  --shadow-sm:     0 1px 2px rgba(0, 0, 0, 0.30);
  --shadow-md:     0 4px 12px rgba(0, 0, 0, 0.40);
  --shadow-lg:     0 8px 24px rgba(0, 0, 0, 0.55);
}

/* Base typography */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc h2 { color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc h3,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc h4 { color: var(--deep-ink); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc p,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc li,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-lead { color: var(--deep-ink); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc strong { color: var(--deep-ink); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc a,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc a:visited { color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc code {
  background: rgba(255, 255, 255, 0.06);
  color: var(--secondary);
  border: 0;
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-eyebrow { color: var(--secondary); }

/* Hero */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-hero { background: var(--light); border-color: var(--line); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-hero p.sf-hero__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-hero .sf-hero__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-hero__lead { color: var(--deep-ink); }

/* Meta bar */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-meta { color: var(--slate); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-meta__badge {
  background: var(--light);
  color: var(--secondary) !important;
  border-color: var(--line);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-meta__badge--mint {
  background: var(--neutral);
  color: var(--secondary) !important;
  border-color: var(--line);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-meta__sep { color: var(--line); }

/* Pills — neutral by default, product/semantic variants keep their surface */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-pill {
  background: rgba(255, 255, 255, 0.06);
  color: var(--deep-ink);
  border-color: var(--line);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-pill--alpon-x5 { background: var(--alpon-purple); color: #FFFFFF !important; border-color: var(--alpon-purple); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-pill--alpon-x4 { background: var(--alpon-cyan-deep); color: #FFFFFF !important; border-color: var(--alpon-cyan-deep); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-pill--brand   { background: var(--primary); color: var(--on-primary) !important; border-color: var(--primary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-pill--success { background: var(--success-bg); color: var(--success-text); border-color: var(--success-bg); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-pill--info    { background: var(--info-bg);    color: var(--info-text);    border-color: var(--info-bg); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-pill--warning { background: var(--warning-bg); color: var(--warning-text); border-color: var(--warning-bg); }

/* AEO answer block — AI variant keeps an Iris tint on dark */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-aeo {
  background: rgba(0, 224, 184, 0.05);
  border-color: var(--line);
  border-left-color: var(--secondary);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-aeo--ai {
  background: var(--ai-mist);
  border-color: rgba(181, 156, 255, 0.28);
  border-left-color: var(--ai-iris);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-aeo__label { color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-aeo--ai .sf-aeo__label { color: var(--ai-iris); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-aeo__text { color: var(--deep-ink); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-aeo__text strong { color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-aeo--ai .sf-aeo__text strong { color: var(--ai-iris); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-aeo--ai code { background: rgba(181, 156, 255, 0.16); color: var(--ai-iris); }

/* TOC pills */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-toc { background: var(--light); border-color: var(--line); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-toc__label { color: var(--slate); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-toc__item {
  background: var(--white);
  color: var(--deep-ink) !important;
  box-shadow: inset 0 0 0 1px var(--line);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-toc__item:hover {
  background: var(--primary);
  color: var(--on-primary) !important;
  box-shadow: inset 0 0 0 1px var(--primary);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-toc__num { color: var(--slate); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-toc__item:hover .sf-toc__num { color: var(--on-primary); }

/* Cards, grids and panels */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-card,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-quick-card,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-access-card,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-action-item,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-config-row,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-cta-card,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-related__card,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-figure { background: var(--white); border-color: var(--line); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-card--highlighted {
  background: var(--neutral);
  color: var(--on-neutral);
  border-color: var(--secondary);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-quick-card__icon,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-access-card__icon,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-action-item__icon,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-cta-card__icon,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-related__icon { background: var(--neutral); color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-quick-card__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-access-card__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-action-item__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-cta-card__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-method__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-step__title { color: var(--deep-ink); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-related__title { color: var(--deep-ink) !important; }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-quick-card__desc,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-access-card__desc,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-action-item__desc,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-related__desc,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-cta-card__eyebrow,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-step__hint { color: var(--slate); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-quick-card__desc strong,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-access-card__desc strong,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-action-item__desc strong { color: var(--deep-ink); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-cta-card__arrow { color: var(--secondary); }

/* Method grid + icon list */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-method__title svg { color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-method-grid p,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-method-grid ul li { color: var(--deep-ink); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-method-grid ul li { border-bottom-color: var(--line); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-method-grid ul li svg,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-icon-list svg { color: var(--success-text); }

/* Step list — AI Iris rail, numbers and badges */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-step-list--ai::before {
  background: linear-gradient(180deg, var(--ai-iris) 0%, rgba(181, 156, 255, 0.18) 100%);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-step__num { box-shadow: 0 0 0 5px var(--light), 0 4px 10px rgba(0, 0, 0, 0.45); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-step-list--ai .sf-step__num {
  background: var(--ai-iris);
  color: #10202E;
  box-shadow: 0 0 0 5px var(--light), 0 6px 14px rgba(107, 71, 240, 0.42);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-step__badge {
  background: var(--ai-mist);
  color: var(--ai-iris);
  border-color: rgba(181, 156, 255, 0.28);
}

/* Figure */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-figure figcaption {
  background: var(--light);
  border-top-color: var(--line);
  color: var(--slate);
}

/* Config reference */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-config-key {
  background: var(--light);
  border-right-color: var(--line);
  color: var(--secondary);
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-config-key__name { color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-config-key__tag { background: var(--neutral); color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-config-key__tag--req { background: var(--success-bg); color: var(--success-text); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-config-key__tag--adv { background: var(--warning-bg); color: var(--warning-text); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-config-val { color: var(--deep-ink); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-port { background: var(--neutral); color: var(--secondary); border-color: var(--line); }

/* Video card */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-video { background: var(--light); border-color: var(--line); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-video__head h3 { color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-video__head p,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-video__chap-label { color: var(--slate); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-video__thumb { background: var(--tertiary); border-color: var(--line); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-video__play span { background: rgba(255, 255, 255, 0.95); color: #6B47F0; }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-video__chap {
  background: var(--white);
  border-color: var(--line);
  color: var(--deep-ink) !important;
}
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-video__chap:hover { background: var(--ai-mist); border-color: var(--ai-iris); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-video__chap-time { color: var(--ai-iris); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-video__chap-title { color: var(--deep-ink); }

/* Issue accordion */
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue-group { background: var(--white); border-color: var(--line); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue { border-bottom-color: var(--line); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue__head { background: var(--white); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue:hover .sf-issue__head,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue[open] .sf-issue__head { background: var(--light); border-bottom-color: var(--line); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue__cat { background: var(--light); color: var(--slate); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue__title { color: var(--deep-ink); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue[open] .sf-issue__title { color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue__chev { color: var(--slate); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue[open] .sf-issue__chev { color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue__body { background: var(--white); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue__body h4 { color: var(--slate); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue__body p { color: var(--deep-ink); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue__body strong { color: var(--secondary); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--ai .sf-issue__cat { background: var(--ai-mist); color: var(--ai-iris); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--ai[open] .sf-issue__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--ai[open] .sf-issue__chev { color: var(--ai-iris); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--sw .sf-issue__cat { background: var(--info-bg); color: var(--info-text); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--sw[open] .sf-issue__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--sw[open] .sf-issue__chev { color: var(--info-text); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--hw .sf-issue__cat,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--warning .sf-issue__cat { background: var(--warning-bg); color: var(--warning-text); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--hw[open] .sf-issue__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--hw[open] .sf-issue__chev,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--warning[open] .sf-issue__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--warning[open] .sf-issue__chev { color: var(--warning-text); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--pwr .sf-issue__cat { background: var(--danger-bg); color: var(--danger-text); }
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--pwr[open] .sf-issue__title,
[data-color-mode="dark"]:where(.rm-ReadMe,:not(:has(.rm-ReadMe:is([data-color-mode="light"],[data-color-mode="system"])))) .sf-doc .sf-issue--pwr[open] .sf-issue__chev { color: var(--danger-text); }

/* === SYSTEM-PREFERENCE FALLBACK (no explicit data-color-mode) ===========
   Mechanical mirror of the attribute branch above — same selectors with the
   html:not([data-color-mode="light"]) prefix, same declarations. ======== */
@media (prefers-color-scheme: dark) {
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc {
    --primary:       #00E0B8;
    --secondary:     #00E0B8;
    --tertiary:      #1B2D45;
    --neutral:       #1F3247;
    --white:         #1B2D45;
    --light:         #14222F;
    --line:          #2A3A4D;
    --slate:         #B5C3CE;
    --slate-light:   #6B8294;
    --deep-ink:      #E8F5F0;

    --ai-iris:       #B59CFF;
    --ai-mist:       #1E1A33;

    --success-bg:    #052E1B;
    --warning-bg:    #2A1F05;
    --danger-bg:     #2A0E0E;
    --info-bg:       #0A2E3F;
    --success-text:  #34D399;
    --warning-text:  #FBBF24;
    --danger-text:   #F87171;
    --info-text:     #5CD3EE;

    --on-primary:    #1B2D45;
    --on-neutral:    #E8F5F0;

    --shadow-sm:     0 1px 2px rgba(0, 0, 0, 0.30);
    --shadow-md:     0 4px 12px rgba(0, 0, 0, 0.40);
    --shadow-lg:     0 8px 24px rgba(0, 0, 0, 0.55);
  }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc h2 { color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc h3,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc h4 { color: var(--deep-ink); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc p,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc li,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-lead { color: var(--deep-ink); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc strong { color: var(--deep-ink); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc a,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc a:visited { color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc code {
    background: rgba(255, 255, 255, 0.06);
    color: var(--secondary);
    border: 0;
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-eyebrow { color: var(--secondary); }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-hero { background: var(--light); border-color: var(--line); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-hero p.sf-hero__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-hero .sf-hero__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-hero__lead { color: var(--deep-ink); }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-meta { color: var(--slate); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-meta__badge {
    background: var(--light);
    color: var(--secondary) !important;
    border-color: var(--line);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-meta__badge--mint {
    background: var(--neutral);
    color: var(--secondary) !important;
    border-color: var(--line);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-meta__sep { color: var(--line); }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-pill {
    background: rgba(255, 255, 255, 0.06);
    color: var(--deep-ink);
    border-color: var(--line);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-pill--alpon-x5 { background: var(--alpon-purple); color: #FFFFFF !important; border-color: var(--alpon-purple); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-pill--alpon-x4 { background: var(--alpon-cyan-deep); color: #FFFFFF !important; border-color: var(--alpon-cyan-deep); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-pill--brand   { background: var(--primary); color: var(--on-primary) !important; border-color: var(--primary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-pill--success { background: var(--success-bg); color: var(--success-text); border-color: var(--success-bg); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-pill--info    { background: var(--info-bg);    color: var(--info-text);    border-color: var(--info-bg); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-pill--warning { background: var(--warning-bg); color: var(--warning-text); border-color: var(--warning-bg); }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-aeo {
    background: rgba(0, 224, 184, 0.05);
    border-color: var(--line);
    border-left-color: var(--secondary);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-aeo--ai {
    background: var(--ai-mist);
    border-color: rgba(181, 156, 255, 0.28);
    border-left-color: var(--ai-iris);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-aeo__label { color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-aeo--ai .sf-aeo__label { color: var(--ai-iris); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-aeo__text { color: var(--deep-ink); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-aeo__text strong { color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-aeo--ai .sf-aeo__text strong { color: var(--ai-iris); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-aeo--ai code { background: rgba(181, 156, 255, 0.16); color: var(--ai-iris); }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-toc { background: var(--light); border-color: var(--line); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-toc__label { color: var(--slate); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-toc__item {
    background: var(--white);
    color: var(--deep-ink) !important;
    box-shadow: inset 0 0 0 1px var(--line);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-toc__item:hover {
    background: var(--primary);
    color: var(--on-primary) !important;
    box-shadow: inset 0 0 0 1px var(--primary);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-toc__num { color: var(--slate); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-toc__item:hover .sf-toc__num { color: var(--on-primary); }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-card,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-quick-card,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-access-card,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-action-item,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-config-row,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-cta-card,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-related__card,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-figure { background: var(--white); border-color: var(--line); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-card--highlighted {
    background: var(--neutral);
    color: var(--on-neutral);
    border-color: var(--secondary);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-quick-card__icon,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-access-card__icon,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-action-item__icon,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-cta-card__icon,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-related__icon { background: var(--neutral); color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-quick-card__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-access-card__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-action-item__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-cta-card__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-method__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-step__title { color: var(--deep-ink); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-related__title { color: var(--deep-ink) !important; }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-quick-card__desc,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-access-card__desc,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-action-item__desc,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-related__desc,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-cta-card__eyebrow,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-step__hint { color: var(--slate); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-quick-card__desc strong,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-access-card__desc strong,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-action-item__desc strong { color: var(--deep-ink); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-cta-card__arrow { color: var(--secondary); }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-method__title svg { color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-method-grid p,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-method-grid ul li { color: var(--deep-ink); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-method-grid ul li { border-bottom-color: var(--line); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-method-grid ul li svg,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-icon-list svg { color: var(--success-text); }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-step-list--ai::before {
    background: linear-gradient(180deg, var(--ai-iris) 0%, rgba(181, 156, 255, 0.18) 100%);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-step__num { box-shadow: 0 0 0 5px var(--light), 0 4px 10px rgba(0, 0, 0, 0.45); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-step-list--ai .sf-step__num {
    background: var(--ai-iris);
    color: #10202E;
    box-shadow: 0 0 0 5px var(--light), 0 6px 14px rgba(107, 71, 240, 0.42);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-step__badge {
    background: var(--ai-mist);
    color: var(--ai-iris);
    border-color: rgba(181, 156, 255, 0.28);
  }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-figure figcaption {
    background: var(--light);
    border-top-color: var(--line);
    color: var(--slate);
  }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-config-key {
    background: var(--light);
    border-right-color: var(--line);
    color: var(--secondary);
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-config-key__name { color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-config-key__tag { background: var(--neutral); color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-config-key__tag--req { background: var(--success-bg); color: var(--success-text); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-config-key__tag--adv { background: var(--warning-bg); color: var(--warning-text); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-config-val { color: var(--deep-ink); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-port { background: var(--neutral); color: var(--secondary); border-color: var(--line); }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-video { background: var(--light); border-color: var(--line); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-video__head h3 { color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-video__head p,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-video__chap-label { color: var(--slate); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-video__thumb { background: var(--tertiary); border-color: var(--line); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-video__play span { background: rgba(255, 255, 255, 0.95); color: #6B47F0; }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-video__chap {
    background: var(--white);
    border-color: var(--line);
    color: var(--deep-ink) !important;
  }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-video__chap:hover { background: var(--ai-mist); border-color: var(--ai-iris); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-video__chap-time { color: var(--ai-iris); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-video__chap-title { color: var(--deep-ink); }

  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue-group { background: var(--white); border-color: var(--line); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue { border-bottom-color: var(--line); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue__head { background: var(--white); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue:hover .sf-issue__head,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue[open] .sf-issue__head { background: var(--light); border-bottom-color: var(--line); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue__cat { background: var(--light); color: var(--slate); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue__title { color: var(--deep-ink); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue[open] .sf-issue__title { color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue__chev { color: var(--slate); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue[open] .sf-issue__chev { color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue__body { background: var(--white); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue__body h4 { color: var(--slate); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue__body p { color: var(--deep-ink); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue__body strong { color: var(--secondary); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--ai .sf-issue__cat { background: var(--ai-mist); color: var(--ai-iris); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--ai[open] .sf-issue__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--ai[open] .sf-issue__chev { color: var(--ai-iris); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--sw .sf-issue__cat { background: var(--info-bg); color: var(--info-text); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--sw[open] .sf-issue__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--sw[open] .sf-issue__chev { color: var(--info-text); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--hw .sf-issue__cat,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--warning .sf-issue__cat { background: var(--warning-bg); color: var(--warning-text); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--hw[open] .sf-issue__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--hw[open] .sf-issue__chev,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--warning[open] .sf-issue__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--warning[open] .sf-issue__chev { color: var(--warning-text); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--pwr .sf-issue__cat { background: var(--danger-bg); color: var(--danger-text); }
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--pwr[open] .sf-issue__title,
  :is(html:not([data-color-mode="light"]):where(:not(:has(.rm-ReadMe[data-color-mode="light"]))),:where(.rm-ReadMe:is([data-color-mode="system"],[data-color-mode="dark"]))) .sf-doc .sf-issue--pwr[open] .sf-issue__chev { color: var(--danger-text); }
}

/* === RESPONSIVE ========================================================= */
@media (max-width: 820px) {
  .sf-doc h1 { font-size: 2rem; }
  .sf-doc h2 { font-size: 1.5rem; margin-top: 44px; }
  .sf-doc .sf-hero { padding: var(--lg); }
  .sf-doc .sf-hero p.sf-hero__title,
  .sf-doc .sf-hero .sf-hero__title { font-size: 2rem; }
  .sf-doc .sf-config-row { grid-template-columns: 1fr; }
  .sf-doc .sf-config-key {
    border-right: 0;
    border-bottom: 1px solid var(--line);
    flex-direction: row;
    align-items: center;
    gap: 10px;
  }
  .sf-doc .sf-method-grid { grid-template-columns: 1fr; }
  .sf-doc .sf-step-list::before { left: 19px; top: 40px; }
  .sf-doc .sf-step__header { grid-template-columns: 40px 1fr; gap: 0 16px; }
  .sf-doc .sf-step__num { width: 40px; height: 40px; font-size: 0.9375rem; }
  .sf-doc .sf-step__title { font-size: 1.25rem; line-height: 1.2; }
  .sf-doc .sf-step__body { padding-left: 56px; }
  .sf-doc .sf-video { padding: var(--lg); gap: 16px; }
  .sf-doc .sf-video__chap-list { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .sf-doc h1 { font-size: 1.75rem; }
  .sf-doc .sf-hero { padding: var(--md) var(--lg); }
  .sf-doc .sf-hero p.sf-hero__title,
  .sf-doc .sf-hero .sf-hero__title { font-size: 1.625rem; }
  .sf-doc .sf-lead { font-size: 1rem; }
  .sf-doc .sf-aeo { padding: var(--md) var(--lg); }
  .sf-doc .sf-aeo__label { font-size: 1.125rem; }
  .sf-doc .sf-aeo__text { font-size: 0.9375rem; }
  .sf-doc .sf-toc { padding: 10px 12px; }
  .sf-doc .sf-step__body { padding-left: 0; }
  .sf-doc .sf-step__title { font-size: 1.0625rem; }
  .sf-doc .sf-action-list { grid-template-columns: 1fr; }
  .sf-doc .sf-access-grid { grid-template-columns: 1fr; }
  .sf-doc .sf-quick-grid { grid-template-columns: 1fr; }
  .sf-doc .sf-cta-card { flex-wrap: wrap; }
  .sf-doc .sf-video__play span { width: 56px; height: 56px; }
  .sf-doc .sf-video__play svg { width: 20px; height: 20px; }
}
</style>

<div class="sf-doc">

  
  <header class="sf-hero">
    <div class="sf-hero__copy">
      <span class="sf-eyebrow">ALPON Cloud · Container deployment</span>
      <p class="sf-hero__title">Deploy Applications on ALPON</p>
      <p class="sf-hero__lead">
        Deploy and manage containerized workloads on <strong>ALPON X5 AI</strong> and <strong>ALPON X4</strong>
        edge computers from <strong>ALPON Cloud</strong>. This guide covers two image sources (Docker Hub and
        the private Sixfab Container Registry), container access, lifecycle management, log streaming, and CI/CD
        patterns for production fleets.
      </p>
      <div class="sf-hero__chips">
        <span class="sf-pill sf-pill--alpon-x5">ALPON X5 AI</span>
        <span class="sf-pill sf-pill--alpon-x4">ALPON X4</span>
        <span class="sf-pill">Docker · ARM64</span>
        <span class="sf-pill">Sixfab Container Registry</span>
      </div>
    </div>
  </header>


  
  <div class="sf-meta">
    <span class="sf-meta__badge">ALPON</span>
    <span class="sf-meta__sep">·</span>
    <span class="sf-meta__badge sf-meta__badge--mint">Platform Guide</span>
    <span class="sf-meta__sep">·</span>
    <span>Deploy Applications</span>
    <span class="sf-meta__sep">·</span>
    <span>Shared (X4 + X5 AI)</span>
    <span class="sf-meta__sep">·</span>
    <span>Updated 2026-09-17</span>
  </div>


  
  <div class="sf-aeo sf-aeo--ai">
    <span class="sf-aeo__label">How do I deploy an application to ALPON?</span>
    <p class="sf-aeo__text">
      <strong>ALPON X5 AI</strong> and <strong>ALPON X4</strong> run application workloads as Docker containers
      managed from <a href="/docs/alpon-cloud" target="_blank" rel="noopener">ALPON Cloud</a> at
      connect.sixfab.com. Open the device's <strong>Applications</strong> tab, click <strong>+ Deploy</strong>, then either
      pull an ARM64-compatible image from Docker Hub by typing its path (e.g. <code>nginx:latest</code>) or select
      a custom image you have pushed to your private Sixfab Container Registry at <code>cr.sixfab.io</code>.
      Configure host ports in the <code>30000–32767</code> range, environment variables, and volumes, then deploy.
      The container starts on the device once the image finishes pulling.
    </p>
  </div>


  
  <div class="sf-callout sf-callout--info">
    <div class="sf-callout__header">
      <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg>
      <span>ARM64 architecture</span>
    </div>
    <div class="sf-callout__content">
      <p>Both ALPON X5 AI (Raspberry Pi CM5 · Cortex-A76) and ALPON X4 (Raspberry Pi CM4 · Cortex-A72) run on
      <strong>ARM64</strong>. Every container image must include a <code>linux/arm64</code> variant. Most official
      images on Docker Hub (nginx, redis, postgres, node) ship multi-arch manifests with ARM64 included. Custom
      images must be built with <code>docker buildx build --platform linux/arm64</code>.</p>
    </div>
  </div>

  
  <nav class="sf-toc" aria-label="On this page">
    <span class="sf-toc__label">In this guide</span>
    <a class="sf-toc__item" href="#video"><span class="sf-toc__num">01</span>Video walkthrough</a>
    <a class="sf-toc__item" href="#overview"><span class="sf-toc__num">02</span>Overview</a>
    <a class="sf-toc__item" href="#methods"><span class="sf-toc__num">03</span>Deployment methods</a>
    <a class="sf-toc__item" href="#docker-hub"><span class="sf-toc__num">04</span>Docker Hub</a>
    <a class="sf-toc__item" href="#registry"><span class="sf-toc__num">05</span>Sixfab Registry</a>
    <a class="sf-toc__item" href="#config"><span class="sf-toc__num">06</span>Configuration</a>
    <a class="sf-toc__item" href="#access"><span class="sf-toc__num">07</span>Access</a>
    <a class="sf-toc__item" href="#manage"><span class="sf-toc__num">08</span>Manage &amp; lifecycle</a>
    <a class="sf-toc__item" href="#logs"><span class="sf-toc__num">09</span>Logs &amp; debug</a>
    <a class="sf-toc__item" href="#cicd"><span class="sf-toc__num">10</span>CI/CD</a>
    <a class="sf-toc__item" href="#troubleshooting"><span class="sf-toc__num">11</span>Troubleshooting</a>
  </nav>


  
  <h2 id="video">Video walkthrough</h2>

  <p>Watch the two-part screen recording for an end-to-end walkthrough of the workflow on ALPON. Click any timestamp to jump to that section of the video.</p>

  <div class="sf-video-group">

    
    <div class="sf-video" role="region" aria-label="Part 1 — Containerize apps for ALPON">
      <div class="sf-video__head">
        <span class="sf-eyebrow">— Part 1 · ~3:30</span>
        <h3>How to containerize apps for ALPON devices</h3>
        <p>Build an ARM64 Docker image on your workstation, log in to the Sixfab Container Registry at <code>cr.sixfab.io</code>, and push the image so it's ready to deploy to any ALPON device. Click a chapter to jump to that section in the video.</p>
      </div>

      <a class="sf-video__thumb" href="https://www.youtube.com/watch?v=rqRMU6B3VOA" target="_blank" rel="noopener" aria-label="Play Part 1 on YouTube — How to containerize apps for ALPON devices">
        <img src="https://img.youtube.com/vi/rqRMU6B3VOA/maxresdefault.jpg" alt="Part 1 — How to containerize apps for ALPON devices, video thumbnail" loading="lazy">
        <span class="sf-video__play" aria-hidden="true">
          <span>
            <svg viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>
          </span>
        </span>
      </a>

      <div class="sf-video__chapters">
        <p class="sf-video__chap-label">Chapter timestamps</p>
        <ul class="sf-video__chap-list">
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA" target="_blank" rel="noopener"><span class="sf-video__chap-time">00:00</span><span class="sf-video__chap-title">Introduction</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=15s" target="_blank" rel="noopener"><span class="sf-video__chap-time">00:15</span><span class="sf-video__chap-title">Docker Desktop</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=31s" target="_blank" rel="noopener"><span class="sf-video__chap-time">00:31</span><span class="sf-video__chap-title">Setting up project folder</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=44s" target="_blank" rel="noopener"><span class="sf-video__chap-time">00:44</span><span class="sf-video__chap-title">Creating Python script</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=63s" target="_blank" rel="noopener"><span class="sf-video__chap-time">01:03</span><span class="sf-video__chap-title">Requirements file</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=77s" target="_blank" rel="noopener"><span class="sf-video__chap-time">01:17</span><span class="sf-video__chap-title"><code>.dockerignore</code> file</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=87s" target="_blank" rel="noopener"><span class="sf-video__chap-time">01:27</span><span class="sf-video__chap-title">Writing the Dockerfile</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=122s" target="_blank" rel="noopener"><span class="sf-video__chap-time">02:02</span><span class="sf-video__chap-title">Building the image</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=138s" target="_blank" rel="noopener"><span class="sf-video__chap-time">02:18</span><span class="sf-video__chap-title">Testing the container locally</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=143s" target="_blank" rel="noopener"><span class="sf-video__chap-time">02:23</span><span class="sf-video__chap-title">Registry setup &amp; login</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=162s" target="_blank" rel="noopener"><span class="sf-video__chap-time">02:42</span><span class="sf-video__chap-title">Tagging the image</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=178s" target="_blank" rel="noopener"><span class="sf-video__chap-time">02:58</span><span class="sf-video__chap-title">Pushing to Sixfab Registry</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rqRMU6B3VOA&amp;t=193s" target="_blank" rel="noopener"><span class="sf-video__chap-time">03:13</span><span class="sf-video__chap-title">Verification &amp; conclusion</span></a></li>
        </ul>
      </div>
    </div>


    
    <div class="sf-video" role="region" aria-label="Part 2 — Deploy and update apps remotely">
      <div class="sf-video__head">
        <span class="sf-eyebrow">— Part 2 · ~3:00</span>
        <h3>How to deploy &amp; update apps remotely</h3>
        <p>Deploy the pushed image to an ALPON device from ALPON Cloud, configure ports, environment variables, volumes, and security toggles, then manage the running container — including rolling back to a previous image tag. Click a chapter to jump to that section in the video. The rollback recipe is written up under <a href="#manage">Manage &amp; lifecycle</a>; connectivity and network-failover behaviour covered in the opening chapter is documented in <a href="/docs/alpon-cloud" target="_blank" rel="noopener">ALPON Cloud</a>.</p>
      </div>

      <a class="sf-video__thumb" href="https://www.youtube.com/watch?v=rsA-vrCu6c4" target="_blank" rel="noopener" aria-label="Play Part 2 on YouTube — How to deploy and update apps remotely">
        <img src="https://img.youtube.com/vi/rsA-vrCu6c4/maxresdefault.jpg" alt="Part 2 — How to deploy and update apps remotely, video thumbnail" loading="lazy">
        <span class="sf-video__play" aria-hidden="true">
          <span>
            <svg viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>
          </span>
        </span>
      </a>

      <div class="sf-video__chapters">
        <p class="sf-video__chap-label">Chapter timestamps</p>
        <ul class="sf-video__chap-list">
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rsA-vrCu6c4" target="_blank" rel="noopener"><span class="sf-video__chap-time">00:00</span><span class="sf-video__chap-title">Introduction &amp; recap</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rsA-vrCu6c4&amp;t=16s" target="_blank" rel="noopener"><span class="sf-video__chap-time">00:16</span><span class="sf-video__chap-title">Reliability &amp; network failover</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rsA-vrCu6c4&amp;t=36s" target="_blank" rel="noopener"><span class="sf-video__chap-time">00:36</span><span class="sf-video__chap-title">Navigating to application deployment</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rsA-vrCu6c4&amp;t=55s" target="_blank" rel="noopener"><span class="sf-video__chap-time">00:55</span><span class="sf-video__chap-title">Selecting custom images from Registry</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rsA-vrCu6c4&amp;t=70s" target="_blank" rel="noopener"><span class="sf-video__chap-time">01:10</span><span class="sf-video__chap-title">Config: env, ports &amp; volumes</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rsA-vrCu6c4&amp;t=83s" target="_blank" rel="noopener"><span class="sf-video__chap-time">01:23</span><span class="sf-video__chap-title">Security: host network &amp; privileged</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rsA-vrCu6c4&amp;t=117s" target="_blank" rel="noopener"><span class="sf-video__chap-time">01:57</span><span class="sf-video__chap-title">Deploying &amp; status monitoring</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rsA-vrCu6c4&amp;t=132s" target="_blank" rel="noopener"><span class="sf-video__chap-time">02:12</span><span class="sf-video__chap-title">Remote management</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rsA-vrCu6c4&amp;t=147s" target="_blank" rel="noopener"><span class="sf-video__chap-time">02:27</span><span class="sf-video__chap-title">Rolling back updates</span></a></li>
          <li><a class="sf-video__chap" href="https://www.youtube.com/watch?v=rsA-vrCu6c4&amp;t=166s" target="_blank" rel="noopener"><span class="sf-video__chap-time">02:46</span><span class="sf-video__chap-title">Conclusion</span></a></li>
        </ul>
      </div>
    </div>

  </div>

  <hr>

  
  <h2 id="overview">Overview</h2>

  <p>ALPON treats every workload as an isolated Docker container. The runtime is preinstalled on each device and
  authenticated against the Sixfab Container Registry out of the box, so deployment is driven entirely from the
  ALPON Cloud dashboard. There is no SSH-based provisioning, no manual <code>docker pull</code>, and no per-device
  credential management.</p>

  <h3>What you can deploy</h3>

  <div class="sf-quick-grid">
    <div class="sf-quick-card">
      <span class="sf-quick-card__icon">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 9h6v6H9z"/></svg>
      </span>
      <span class="sf-quick-card__title">Web services</span>
      <span class="sf-quick-card__desc">nginx, Caddy, Node.js APIs, dashboards, Grafana, n8n.</span>
    </div>
    <div class="sf-quick-card">
      <span class="sf-quick-card__icon">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M3 12h4l3-9 4 18 3-9h4"/></svg>
      </span>
      <span class="sf-quick-card__title">Edge AI workloads</span>
      <span class="sf-quick-card__desc">Computer vision pipelines and on-device inference on the <strong>DEEPX DX-M1 NPU</strong> with models compiled by the DXNN toolchain (ALPON X5 AI).</span>
    </div>
    <div class="sf-quick-card">
      <span class="sf-quick-card__icon">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>
      </span>
      <span class="sf-quick-card__title">Data &amp; messaging</span>
      <span class="sf-quick-card__desc">MQTT brokers, Redis, PostgreSQL, time-series databases, message queues.</span>
    </div>
    <div class="sf-quick-card">
      <span class="sf-quick-card__icon">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
      </span>
      <span class="sf-quick-card__title">IoT collectors</span>
      <span class="sf-quick-card__desc">Protocol bridges, BLE / Modbus / OPC-UA collectors, custom edge agents.</span>
    </div>
  </div>

  <h3>How deployment works</h3>

  <p>Every ALPON device opens a persistent connection to the ALPON Cloud control plane. When a deploy is
  triggered from the dashboard, the platform sends a structured manifest to the device, which then pulls the
  image, applies port and volume mappings, and starts the container. Status streams back to the cloud in real
  time.</p>

  <ul class="sf-icon-list">
    <li>
      <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
      <span><strong>No SSH or VPN required</strong> for deployment. Each device pulls images over its existing outbound TLS connection.</span>
    </li>
    <li>
      <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
      <span><strong>Scoped registry access.</strong> Each device authenticates only to its owner's repositories and to official Sixfab images.</span>
    </li>
    <li>
      <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
      <span><strong>Lifecycle from the cloud.</strong> Start, pause, restart, edit, delete, and stream logs without ever touching the device.</span>
    </li>
    <li>
      <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
      <span><strong>Multiple containers per device.</strong> Run as many workloads as the device's CPU, RAM, and storage allow.</span>
    </li>
  </ul>

  <hr>

  
  <h2 id="methods">Deployment methods</h2>

  <p>ALPON supports two image sources. Both deploy through the same <strong>Applications</strong> tab in
  ALPON Cloud; the difference is where the image lives.</p>

  <div class="sf-method-grid">
    <div class="sf-card">
      <div class="sf-method__head">
        <span class="sf-method__title">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z"/><path d="M3 12h18"/><path d="M12 3a15 15 0 0 1 0 18"/><path d="M12 3a15 15 0 0 0 0 18"/></svg>
          Docker Hub
        </span>
        <span class="sf-pill sf-pill--info">Quick start</span>
      </div>
      <p>Pull any public ARM64 image directly from Docker Hub. Best for trying out off-the-shelf services like
      nginx, Grafana, or MQTT brokers without building anything.</p>
      <ul>
        <li><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>No build step required</li>
        <li><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>Type the image path and deploy</li>
        <li><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>Subject to Docker Hub rate limits</li>
      </ul>
    </div>

    <div class="sf-card sf-card--highlighted">
      <div class="sf-method__head">
        <span class="sf-method__title">
          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>
          Sixfab Container Registry
        </span>
        <span class="sf-pill sf-pill--success">Recommended</span>
      </div>
      <p>Build, push, and deploy custom images from the private registry at <code>cr.sixfab.io</code>. Required for
      proprietary code, custom AI models, fleet-specific configurations, and any production deployment.</p>
      <ul>
        <li><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>Private storage scoped to your own account namespace</li>
        <li><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>Devices auto-authenticate, no per-device login</li>
        <li><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>10 GB / 100 tags default quota</li>
      </ul>
    </div>
  </div>

  <hr>

  
  <h2 id="docker-hub">Deploying from Docker Hub</h2>

  <p>The fastest way to run a container on ALPON. The example below deploys nginx; the same flow applies to any
  ARM64-compatible image.</p>

  <ol class="sf-step-list sf-step-list--ai">

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">1</div>
        <h3 class="sf-step__title">Open the Applications tab</h3>
      </div>
      <div class="sf-step__body">
        <p>Log in to <a href="https://connect.sixfab.com" target="_blank" rel="noopener">connect.sixfab.com</a>,
        open <strong>Assets</strong>, select your registered ALPON device, then switch to the
        <strong>Applications</strong> tab. Click <strong>+ Deploy</strong> to open the configuration panel.</p>
      </div>
    </li>

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">2</div>
        <h3 class="sf-step__title">Configure the container</h3>
      </div>
      <div class="sf-step__body">
        <p>Fill in the deployment form. The minimum required fields are <strong>Container Name</strong>,
        <strong>Image</strong>, and at least one <strong>Port mapping</strong> if the container exposes a service.</p>

        <span class="sf-fig-anchor" id="fig-deploy-form"></span>
        <figure class="sf-figure">
          <a href="#lb-deploy-form" aria-label="Open enlarged image">
            <img src="https://files.readme.io/2a1a12aa93b209a8aca98ad8a61b1970d05576b39b6efc226be2945078289318-Sixfab_ALPON_X4_Manage_and_Deploy_1.webp" alt="Container deployment configuration form in ALPON Cloud with Container Name, Image path, environment variables, and port mapping fields" loading="lazy">
          </a>
          <figcaption>Container deployment form on the Applications tab.</figcaption>
        </figure>

        <ul>
          <li><strong>Container Name:</strong> a descriptive identifier (e.g. <code>my-nginx</code>).</li>
          <li><strong>Image:</strong> check <em>"I would like to use my own container path"</em> and enter the Docker Hub image, e.g. <code>nginx:latest</code> or <code>redis:7-alpine</code>.</li>
          <li><strong>Ports:</strong> map device ports to container ports (e.g. host <span class="sf-port">30800</span> → container <span class="sf-port">80</span>). Host ports must be in <span class="sf-port">30000–32767</span>.</li>
          <li><strong>Environment, Volumes, Host Network, Privileged:</strong> see <a href="#config">Configuration reference</a> for full semantics.</li>
        </ul>

        <span class="sf-fig-anchor" id="fig-deploy-ports"></span>
        <figure class="sf-figure">
          <a href="#lb-deploy-ports" aria-label="Open enlarged image">
            <img src="https://files.readme.io/361f2782e8245728ead2854f91c289a708fc9e75d7b0cbb454ab2b39178dc026-Sixfab_ALPON_X4_Manage_and_Deploy_2.webp" alt="Port mapping and environment variable configuration showing host-to-container port pairs and key-value environment entries" loading="lazy">
          </a>
          <figcaption>Port mapping and environment variable rows.</figcaption>
        </figure>

        <span class="sf-fig-anchor" id="fig-deploy-volumes"></span>
        <figure class="sf-figure">
          <a href="#lb-deploy-volumes" aria-label="Open enlarged image">
            <img src="https://files.readme.io/a3882ccda71a804e18ee575aa69f43f7ccf1a2fe2fa3247a8c5da963ffdf42d6-Sixfab_ALPON_X4_Manage_and_Deploy_3.webp" alt="Volume bind mount, Host Network toggle, and Privileged toggle configuration on the deployment form" loading="lazy">
          </a>
          <figcaption>Volume mounts, Host Network, and Privileged toggles.</figcaption>
        </figure>
      </div>
    </li>

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">3</div>
        <h3 class="sf-step__title">Deploy</h3>
      </div>
      <div class="sf-step__body">
        <p>Review the form and click <strong>+ Deploy</strong>. The device pulls the image and starts the container;
        status flips to <strong>Running</strong> in the Applications list once the container is live.</p>

        <span class="sf-fig-anchor" id="fig-deploy-review"></span>
        <figure class="sf-figure">
          <a href="#lb-deploy-review" aria-label="Open enlarged image">
            <img src="https://files.readme.io/20617d18e1780825f99460bdd1e885f4cf6d27c33979c6e8d1668ec85ea8fce3-Sixfab_ALPON_X4_Manage_and_Deploy_4.webp" alt="Pre-deploy review screen in ALPON Cloud summarizing container name, image, ports, environment variables, and volumes before launch" loading="lazy">
          </a>
          <figcaption>Final review screen before clicking + Deploy.</figcaption>
        </figure>

        <span class="sf-fig-anchor" id="fig-deploy-list"></span>
        <figure class="sf-figure">
          <a href="#lb-deploy-list" aria-label="Open enlarged image">
            <img src="https://files.readme.io/807e7d9583bd8c3732c69d898cb1a8d24db87f7e9eee188ea3b9e2afbf895517-Sixfab_ALPON_X4_Manage_and_Deploy_5.webp" alt="Applications tab listing the deployed container with Running status, image tag, and lifecycle action buttons" loading="lazy">
          </a>
          <figcaption>Deployed container appears in the Applications list with Running status.</figcaption>
        </figure>

        <div class="sf-callout sf-callout--info">
          <div class="sf-callout__header">
            <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z"/></svg>
            <span>First pull may take a minute</span>
          </div>
          <div class="sf-callout__content">
            <p>Initial pulls over cellular links can be slow for large images. After the first pull the image is
            cached on the device, so later restarts reuse the cached image instead of downloading it again.</p>
          </div>
        </div>
      </div>
    </li>

  </ol>

  <hr>

  
  <h2 id="registry">Sixfab Container Registry</h2>

  <p>The <strong>Sixfab Container Registry</strong> is a private OCI-compatible registry hosted at
  <code>cr.sixfab.io</code>, scoped to your account. ALPON devices authenticate against it automatically and pull
  from your own repositories and from official Sixfab images. This section is the canonical reference for registry
  quotas and credentials; other ALPON pages link here.</p>

  <h3>Registry overview</h3>

  <p>The Registry is accessible from <strong>Developer Tools → Registry</strong> in ALPON Cloud. It shows each
  repository with size, creation date, and quota usage.</p>

  <span class="sf-fig-anchor" id="fig-registry-overview"></span>
  <figure class="sf-figure">
    <a href="#lb-registry-overview" aria-label="Open enlarged image">
      <img src="https://files.readme.io/ed02aad55cf98bff8052d2c769c71a91853c56cef36483daaf606c81f0cebe73-Screenshot_2024-12-10_at_1.55.18_AM.png" alt="Sixfab Container Registry overview page in ALPON Cloud showing the repository list with image quota and storage quota in the header" loading="lazy">
    </a>
    <figcaption>Container Registry page in ALPON Cloud: repository list with image and storage quotas.</figcaption>
  </figure>

  <div class="sf-callout sf-callout--info">
    <div class="sf-callout__header">
      <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z"/></svg>
      <span>Default quotas</span>
    </div>
    <div class="sf-callout__content">
      <p>Each account starts with <strong>10 GB total storage</strong> and <strong>100 image tags</strong>. A push
      that would exceed either limit fails. To ask for a quota increase,
      <a href="https://sixfab.com/contact/" target="_blank" rel="noopener">contact Sixfab</a>.</p>
    </div>
  </div>

  <h3>Push an image to the Registry</h3>

  <p>Run the following commands on your build machine (laptop, server, or CI runner) to push a local image to your
  registry namespace.</p>

  <ol class="sf-step-list sf-step-list--ai">

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">1</div>
        <h3 class="sf-step__title">Set the registry password</h3>
      </div>
      <div class="sf-step__body">
        <p>Open <a href="https://connect.sixfab.com/#/registry" target="_blank" rel="noopener">Sixfab Registry</a>
        and click <strong>Reset Password</strong>. The password is shown <strong>once</strong>; copy and store it
        in a secrets manager. Your username is the 6-digit number visible at the top of the Registry page.</p>

        <span class="sf-fig-anchor" id="fig-reg-username"></span>
        <figure class="sf-figure">
          <a href="#lb-reg-username" aria-label="Open enlarged image">
            <img src="https://files.readme.io/2f7cd19106d878f95ff6fbee81617d323f00a0cc69eb2754300095a86db3682a-Sixfab_ALPON_X4_Manage_and_Deploy_App_Username.jpg" alt="Sixfab Registry page header showing the 6-digit username next to the Registry breadcrumb" loading="lazy">
          </a>
          <figcaption>Your registry username is the 6-digit number at the top of the Registry page.</figcaption>
        </figure>

        <span class="sf-fig-anchor" id="fig-reg-reset"></span>
        <figure class="sf-figure">
          <a href="#lb-reg-reset" aria-label="Open enlarged image">
            <img src="https://files.readme.io/4b7a582bc6cf364745bff3f88c84f81dafe17c69bf9df61912cbab3e502a09bf-Sixfab_ALPON_X4_Manage_and_Deploy_12.webp" alt="Reset Password button on the Sixfab Registry page used to issue a new registry credential" loading="lazy">
          </a>
          <figcaption>Reset Password issues a new registry credential.</figcaption>
        </figure>

        <div class="sf-callout sf-callout--warning">
          <div class="sf-callout__header">
            <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg>
            <span>Save the password immediately</span>
          </div>
          <div class="sf-callout__content">
            <p>Registry credentials are independent from your ALPON Cloud account login. If lost, the only
            recovery is to issue a new password via <strong>Reset Password</strong>, which invalidates the previous
            one.</p>
          </div>
        </div>
      </div>
    </li>

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">2</div>
        <h3 class="sf-step__title">Log in to the registry</h3>
      </div>
      <div class="sf-step__body">
        <p>Authenticate Docker against <code>cr.sixfab.io</code>. Replace <code>&lt;your_username&gt;</code> with
        your own 6-digit registry username.</p>

        <div class="sf-terminal">
          <div class="sf-terminal__header">
            <span class="sf-terminal__dot" style="background:#ff5f57"></span>
            <span class="sf-terminal__dot" style="background:#febc2e"></span>
            <span class="sf-terminal__dot" style="background:#28c840"></span>
            <span class="sf-terminal__title">bash</span>
          </div>
          <div class="sf-terminal__body"><pre><span class="t-dim"># 1. Authenticate Docker to the Sixfab Container Registry</span>
<span class="t-green">docker login</span> cr.sixfab.io <span class="t-blue">--username</span> &lt;your_username&gt;
<span class="t-dim"># Password: paste the registry password (input is hidden)</span></pre></div>
        </div>
      </div>
    </li>

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">3</div>
        <h3 class="sf-step__title">Build for ARM64</h3>
      </div>
      <div class="sf-step__body">
        <p>Build the image with Docker Buildx, targeting <code>linux/arm64</code>. The <code>--load</code> flag
        makes the resulting image available locally so you can tag and push it.</p>

        <div class="sf-terminal">
          <div class="sf-terminal__header">
            <span class="sf-terminal__dot" style="background:#ff5f57"></span>
            <span class="sf-terminal__dot" style="background:#febc2e"></span>
            <span class="sf-terminal__dot" style="background:#28c840"></span>
            <span class="sf-terminal__title">bash</span>
          </div>
          <div class="sf-terminal__body"><pre><span class="t-dim"># 1. From the directory containing your Dockerfile</span>
<span class="t-green">docker buildx build</span> <span class="t-blue">--load</span> <span class="t-blue">--platform</span> linux/arm64 &#92;
  <span class="t-blue">-t</span> my-app:latest .</pre></div>
        </div>

        <div class="sf-callout sf-callout--info">
          <div class="sf-callout__header">
            <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z"/></svg>
            <span>Buildx availability</span>
          </div>
          <div class="sf-callout__content">
            <p>Docker Buildx is preinstalled on Windows and macOS with Docker Desktop. On Linux, verify with
            <code>docker buildx version</code>. On an x86 Linux host, also register the ARM emulator once with
            <code>docker run --privileged --rm tonistiigi/binfmt --install arm64</code>; without it,
            <code>RUN</code> steps in an <code>arm64</code> build fail with <code>exec format error</code>.</p>
          </div>
        </div>
      </div>
    </li>

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">4</div>
        <h3 class="sf-step__title">Tag with the registry path</h3>
      </div>
      <div class="sf-step__body">
        <p>Tag the image so Docker knows where to push it. The path format is
        <code>cr.sixfab.io/&lt;your_username&gt;/&lt;image&gt;:&lt;tag&gt;</code>.</p>

        <div class="sf-terminal">
          <div class="sf-terminal__header">
            <span class="sf-terminal__dot" style="background:#ff5f57"></span>
            <span class="sf-terminal__dot" style="background:#febc2e"></span>
            <span class="sf-terminal__dot" style="background:#28c840"></span>
            <span class="sf-terminal__title">bash</span>
          </div>
          <div class="sf-terminal__body"><pre><span class="t-green">docker tag</span> my-app:latest cr.sixfab.io/&lt;your_username&gt;/my-app:latest</pre></div>
        </div>
      </div>
    </li>

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">5</div>
        <h3 class="sf-step__title">Push the image</h3>
      </div>
      <div class="sf-step__body">
        <p>Upload the image to your private repository. Layer caching means subsequent pushes only transfer
        changed layers.</p>

        <div class="sf-terminal">
          <div class="sf-terminal__header">
            <span class="sf-terminal__dot" style="background:#ff5f57"></span>
            <span class="sf-terminal__dot" style="background:#febc2e"></span>
            <span class="sf-terminal__dot" style="background:#28c840"></span>
            <span class="sf-terminal__title">bash</span>
          </div>
          <div class="sf-terminal__body"><pre><span class="t-green">docker push</span> cr.sixfab.io/&lt;your_username&gt;/my-app:latest

<span class="t-dim"># The push refers to repository [cr.sixfab.io/719663/my-app]</span>
<span class="t-hl">571fd9f78ac9</span>: Pushed
latest: digest: sha256:2aeab3830f8eaf2775fd599fda6a516a95c1480239ba5e64a632a68c1f3bd53d size: 1786</pre></div>
        </div>
      </div>
    </li>

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">6</div>
        <h3 class="sf-step__title">Verify in the Registry</h3>
      </div>
      <div class="sf-step__body">
        <p>Refresh the Registry page in ALPON Cloud. The new image appears in the repository list with size, creation
        date, and last-update timestamp. Click <strong>Details</strong> on a repository to inspect tags, digests,
        and the underlying manifest. Each tag shows a <strong>See Usage</strong> button to identify which devices
        run it. Drilling into a tag reveals the full manifest, architecture (<code>arm64</code>), OS
        (<code>linux</code>), runtime <code>Config</code>, and layer-level breakdown.</p>
      </div>
    </li>

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">7</div>
        <h3 class="sf-step__title">Deploy from the Registry</h3>
      </div>
      <div class="sf-step__body">
        <p>Open the device's <strong>Applications</strong> tab and click <strong>+ Deploy</strong>. In the
        <strong>Image</strong> field, leave the custom-path checkbox <em>unchecked</em> to pick from your registry
        dropdown. Select the image and tag, configure ports and environment, then deploy.</p>

        <span class="sf-fig-anchor" id="fig-reg-image-select"></span>
        <figure class="sf-figure">
          <a href="#lb-reg-image-select" aria-label="Open enlarged image">
            <img src="https://files.readme.io/f91c028b2b9e6d3d61a6b3513bb41ff6d6d416cf103cc2727c4f7d8171c80a4b-Screenshot_December_10_2024_23344_AM.png" alt="Image dropdown on the deploy form populated from the Sixfab Registry, listing the user's pushed repositories" loading="lazy">
          </a>
          <figcaption>The Image dropdown lists every repository in your Sixfab Registry namespace.</figcaption>
        </figure>

        <span class="sf-fig-anchor" id="fig-reg-deploy-review"></span>
        <figure class="sf-figure">
          <a href="#lb-reg-deploy-review" aria-label="Open enlarged image">
            <img src="https://files.readme.io/aaf97ee4fb419afad0248a2d6c7f2de79e97d2781d9289374c3d2b02a7e215df-Screenshot_2024-12-10_at_2.33.15_AM.png" alt="Pre-deploy review screen for a Sixfab Registry image with selected tag, port mapping, and environment summary" loading="lazy">
          </a>
          <figcaption>Final review before clicking + Deploy with a Sixfab Registry image.</figcaption>
        </figure>
      </div>
    </li>

  </ol>

  <div class="sf-callout sf-callout--success">
    <div class="sf-callout__header">
      <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>
      <span>Devices auto-authenticate</span>
    </div>
    <div class="sf-callout__content">
      <p>You do <strong>not</strong> need to run <code>docker login</code> on the ALPON device. Every ALPON ships
      preconfigured with credentials scoped to its owner's registry namespace plus official Sixfab images, so a
      device pulls only the images in that namespace.</p>
    </div>
  </div>

  <hr>

  
  <h2 id="config">Configuration reference</h2>

  <p>Every field exposed in the deployment form, with semantics and constraints.</p>

  <div class="sf-config-list">

    <div class="sf-config-row">
      <div class="sf-config-key">
        <span class="sf-config-key__name">Container Name</span>
        <span class="sf-config-key__tag sf-config-key__tag--req">Required</span>
      </div>
      <div class="sf-config-val">A descriptive identifier for the workload. Must be unique on the device. Use lowercase, hyphens, and digits (e.g. <code>my-nginx</code>, <code>vision-pipeline-v2</code>).</div>
    </div>

    <div class="sf-config-row">
      <div class="sf-config-key">
        <span class="sf-config-key__name">Image</span>
        <span class="sf-config-key__tag sf-config-key__tag--req">Required</span>
      </div>
      <div class="sf-config-val">Either the registry path (e.g. <code>cr.sixfab.io/&lt;your_username&gt;/my-app:latest</code>) when picking from the dropdown, or a Docker Hub path (e.g. <code>nginx:latest</code>) when "I would like to use my own container path" is checked. Always ARM64.</div>
    </div>

    <div class="sf-config-row">
      <div class="sf-config-key">
        <span class="sf-config-key__name">Ports</span>
        <span class="sf-config-key__tag">Optional</span>
      </div>
      <div class="sf-config-val">Maps device (host) ports to container ports. Host port range: <span class="sf-port">30000–32767</span>. Each host port can be used by only one container at a time. Container ports are unrestricted (e.g. host <span class="sf-port">30800</span> → container <span class="sf-port">80</span>).</div>
    </div>

    <div class="sf-config-row">
      <div class="sf-config-key">
        <span class="sf-config-key__name">Environment</span>
        <span class="sf-config-key__tag">Optional</span>
      </div>
      <div class="sf-config-val">Key/value pairs injected into the container at runtime. Use this for runtime config and secrets (e.g. <code>DATABASE_URL=postgres://...</code>, <code>API_KEY=...</code>). Values are sent to the device over its outbound TLS connection, and are shown again in the form whenever you reopen <strong>Edit Deployment</strong>.</div>
    </div>

    <div class="sf-config-row">
      <div class="sf-config-key">
        <span class="sf-config-key__name">Volumes</span>
        <span class="sf-config-key__tag">Optional</span>
      </div>
      <div class="sf-config-val">Bind-mounts a path from the device filesystem into the container: you supply a host path and a container path, and the container reads and writes the device's own files (this is how <code>/dev/gpiomem</code> is handed to a GPIO workload). The host path must already exist on the device. Container writes survive restart and redeploy. The form does not create named Docker volumes.</div>
    </div>

    <div class="sf-config-row">
      <div class="sf-config-key">
        <span class="sf-config-key__name">Host Network</span>
        <span class="sf-config-key__tag sf-config-key__tag--adv">Advanced</span>
      </div>
      <div class="sf-config-val">When enabled, the container shares the device's network stack directly (no port mapping needed). Useful for protocols requiring low-level network access (mDNS, broadcast, custom L2). <strong>Disables port isolation.</strong></div>
    </div>

    <div class="sf-config-row">
      <div class="sf-config-key">
        <span class="sf-config-key__name">Privileged</span>
        <span class="sf-config-key__tag sf-config-key__tag--adv">Advanced</span>
      </div>
      <div class="sf-config-val">Grants the container root-equivalent access to host devices and kernel capabilities. Required for GPIO, push-button, and USB work: enable it and bind-mount <code>/dev/gpiomem</code> — see <a href="/docs/alpon-access-gpio-buttons-usb-docker-containers" target="_blank" rel="noopener">Access GPIO, Push Buttons, and USB from Docker Containers</a>. Two hardware limits still apply inside a privileged container: the GPIO Add-on port's 5 V rail and signal path only come up once <code>GPIO 21</code> is driven HIGH, and ALPON X4 supplies 5 V at 1 A in total, shared across both USB ports. <strong>Significant security risk; enable only when necessary.</strong></div>
    </div>

  </div>

  <h3>Port range explained</h3>

  <p>The deployment form accepts host ports in the <span class="sf-port">30000–32767</span> range. Map the
  container's own port (unrestricted) to a host port in that range, then use the host port when you reach the
  service from the local network or from the device itself.</p>

  <hr>

  
  <h2 id="access">Access the container</h2>

  <p>Once a container is running, three options are available depending on your network position relative to the
  device.</p>

  <div class="sf-access-grid">

    <div class="sf-access-card">
      <span class="sf-access-card__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
      </span>
      <div class="sf-access-card__title">Local network</div>
      <div class="sf-access-card__desc">Browse to the device IP from any machine on the same LAN. Fastest, lowest latency.</div>
    </div>

    <div class="sf-access-card">
      <span class="sf-access-card__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>
      </span>
      <div class="sf-access-card__title">Remote terminal</div>
      <div class="sf-access-card__desc">The ALPON Cloud browser-based terminal tunnels through the device's outbound TLS connection. Works from anywhere.</div>
    </div>

    <div class="sf-access-card">
      <span class="sf-access-card__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
      </span>
      <div class="sf-access-card__title">Connected display</div>
      <div class="sf-access-card__desc">Plug a monitor into the device's HDMI port and open a browser locally. Useful for kiosk and signage workloads.</div>
    </div>

  </div>

  <h3>Access from the local network</h3>

  <p>Find the device's IP on the <strong>Network</strong> tab of the Asset Detail page, then open a browser on
  any machine in the same network.</p>

  <span class="sf-fig-anchor" id="fig-access-ip"></span>
  <figure class="sf-figure">
    <a href="#lb-access-ip" aria-label="Open enlarged image">
      <img src="https://files.readme.io/2860cc16318d42550e57a02cf17ebf559ad31a0ea597e9ac14bc816dc09864df-Sixfab_ALPON_X4_Manage_and_Deploy_6.webp" alt="Network tab on the Asset Detail page showing the device's local IP address used to reach the container from the same network" loading="lazy">
    </a>
    <figcaption>The device IP appears on the Network tab of the Asset Detail page.</figcaption>
  </figure>

  <div class="sf-terminal">
    <div class="sf-terminal__header">
      <span class="sf-terminal__dot" style="background:#ff5f57"></span>
      <span class="sf-terminal__dot" style="background:#febc2e"></span>
      <span class="sf-terminal__dot" style="background:#28c840"></span>
      <span class="sf-terminal__title">browser</span>
    </div>
    <div class="sf-terminal__body"><pre><span class="t-dim"># Replace &lt;device_ip&gt; with the value from the Network tab</span>
<span class="t-blue">http://</span>&lt;device_ip&gt;:30800</pre></div>
  </div>

  <span class="sf-fig-anchor" id="fig-access-nginx"></span>
  <figure class="sf-figure">
    <a href="#lb-access-nginx" aria-label="Open enlarged image">
      <img src="https://files.readme.io/a1e9f3dc6226517116f694e0f084da21cd19f15c944096ffd7cce0d5dc15831e-Sixfab_ALPON_X4_Manage_and_Deploy_7.webp" alt="nginx default welcome page served from the ALPON device, opened in a browser on the same local network" loading="lazy">
    </a>
    <figcaption>nginx welcome page served by the deployed container on ALPON.</figcaption>
  </figure>

  <h3>Access via the remote terminal</h3>

  <p>If the device is offsite or behind NAT, open the <strong>Device</strong> tab and click <strong>Open Remote
  Terminal</strong>. The terminal session runs on the device itself, so <code>127.0.0.1</code> resolves to the
  device.</p>

  <span class="sf-fig-anchor" id="fig-access-rt-btn"></span>
  <figure class="sf-figure">
    <a href="#lb-access-rt-btn" aria-label="Open enlarged image">
      <img src="https://files.readme.io/1653192bdd56aad436e397ce14a1f48c4efe5c7abb67f0913dd34206a59cc0e9-Sixfab_ALPON_X4_Manage_and_Deploy_8.webp" alt="Open Remote Terminal button on the Device tab of the Asset Detail page" loading="lazy">
    </a>
    <figcaption>Open Remote Terminal button on the Device tab.</figcaption>
  </figure>

  <div class="sf-terminal">
    <div class="sf-terminal__header">
      <span class="sf-terminal__dot" style="background:#ff5f57"></span>
      <span class="sf-terminal__dot" style="background:#febc2e"></span>
      <span class="sf-terminal__dot" style="background:#28c840"></span>
      <span class="sf-terminal__title">remote-terminal</span>
    </div>
    <div class="sf-terminal__body"><pre><span class="t-dim"># 1. Verify the container is reachable on the device itself</span>
<span class="t-green">curl</span> http://127.0.0.1:30800
<span class="t-dim"># &lt;!DOCTYPE html&gt;
# &lt;html&gt;
# &lt;head&gt;&lt;title&gt;Welcome to nginx!&lt;/title&gt;...</span></pre></div>
  </div>

  <span class="sf-fig-anchor" id="fig-access-curl"></span>
  <figure class="sf-figure">
    <a href="#lb-access-curl" aria-label="Open enlarged image">
      <img src="https://files.readme.io/600d38df13d7586f54f8acc644124660cc9069d540bc4b579073c2441c72300e-Sixfab_ALPON_X4_Manage_and_Deploy_9.webp" alt="curl response from the remote terminal showing the container is running and serving the nginx default page" loading="lazy">
    </a>
    <figcaption>Successful curl response confirms the container is reachable on the device.</figcaption>
  </figure>

  <h3>Access via a connected display</h3>

  <p>Connect a monitor to the device, open a browser locally, and navigate to <code>http://127.0.0.1:30800</code>.
  Suitable for digital signage, kiosk dashboards, and on-device debugging.</p>

  <hr>

  
  <h2 id="manage">Manage &amp; lifecycle</h2>

  <p>Every running container exposes lifecycle controls in the <strong>Applications</strong> tab. Operations are
  issued from the cloud and applied as soon as the device receives the command.</p>

  <span class="sf-fig-anchor" id="fig-manage-panel"></span>
  <figure class="sf-figure">
    <a href="#lb-manage-panel" aria-label="Open enlarged image">
      <img src="https://files.readme.io/19eba8431503aebeac2b7727ff8e3a7c103c0620755ac9354322d22874870f80-Sixfab_ALPON_X4_Manage_and_Deploy_10.webp" alt="Container management panel on the Applications tab with Start, Pause, Restart, Edit Deployment, and Remove buttons next to a running container" loading="lazy">
    </a>
    <figcaption>Container management panel with full lifecycle controls.</figcaption>
  </figure>

  <div class="sf-action-list">

    <div class="sf-action-item">
      <span class="sf-action-item__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><polygon points="5 3 19 12 5 21 5 3"/></svg>
      </span>
      <div>
        <div class="sf-action-item__title">Start / Run</div>
        <div class="sf-action-item__desc">Boot a stopped container without redeploying. The image is already cached.</div>
      </div>
    </div>

    <div class="sf-action-item">
      <span class="sf-action-item__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg>
      </span>
      <div>
        <div class="sf-action-item__title">Pause</div>
        <div class="sf-action-item__desc">Freeze the container's processes. State stays in memory; resuming continues from the frozen state without a restart.</div>
      </div>
    </div>

    <div class="sf-action-item">
      <span class="sf-action-item__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>
      </span>
      <div>
        <div class="sf-action-item__title">Restart</div>
        <div class="sf-action-item__desc">Stop and immediately start the container. Useful after a config change or to clear runtime state.</div>
      </div>
    </div>

    <div class="sf-action-item">
      <span class="sf-action-item__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>
      </span>
      <div>
        <div class="sf-action-item__title">Edit deployment</div>
        <div class="sf-action-item__desc">Reopen the deploy form to change image tag, ports, environment, or volumes without removing the container.</div>
      </div>
    </div>

    <div class="sf-action-item">
      <span class="sf-action-item__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/></svg>
      </span>
      <div>
        <div class="sf-action-item__title">Delete</div>
        <div class="sf-action-item__desc">Permanently remove the container. The image stays cached for fast redeployment.</div>
      </div>
    </div>

    <div class="sf-action-item">
      <span class="sf-action-item__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>
      </span>
      <div>
        <div class="sf-action-item__title">Shell</div>
        <div class="sf-action-item__desc">Open an interactive shell <em>inside</em> the running container from its detail view in the dashboard.</div>
      </div>
    </div>

    <div class="sf-action-item">
      <span class="sf-action-item__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 3v18h18"/><polyline points="7 14 11 10 15 14 21 8"/></svg>
      </span>
      <div>
        <div class="sf-action-item__title">View status</div>
        <div class="sf-action-item__desc">Live CPU, memory, and network stats per container. Used to spot regressions and resource leaks.</div>
      </div>
    </div>

    <div class="sf-action-item">
      <span class="sf-action-item__icon">
        <svg viewBox="0 0 24 24" aria-hidden="true"><polyline points="14 2 14 8 20 8"/><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><line x1="9" y1="13" x2="15" y2="13"/><line x1="9" y1="17" x2="15" y2="17"/></svg>
      </span>
      <div>
        <div class="sf-action-item__title">Logs</div>
        <div class="sf-action-item__desc">Stream <code>stdout</code>/<code>stderr</code> live or download historical logs. See <a href="#logs">Logs &amp; debug</a>.</div>
      </div>
    </div>

  </div>

  <h3>Updating to a new image version</h3>

  <p>Two patterns work, depending on how you tag releases:</p>

  <ol>
    <li><strong>Mutable tag (<code>:latest</code>):</strong> push a new image with the same tag, then click <strong>Restart</strong>. The device pulls the new digest and recreates the container.</li>
    <li><strong>Immutable tag (<code>:v1.2.3</code>):</strong> push a new tag, click <strong>Edit Deployment</strong> on the running container, change the image tag, and save. Recommended for production traceability.</li>
  </ol>

  <div class="sf-callout sf-callout--warning">
    <div class="sf-callout__header">
      <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 0 0 0-1.41l-2.34-2.34a1 1 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg>
      <span>Prefer immutable tags in production</span>
    </div>
    <div class="sf-callout__content">
      <p>Mutable tags like <code>:latest</code> make rollback impossible if a regression slips in. Tag every
      release with an immutable identifier (semver, git SHA, or build number) and update deployments explicitly.</p>
    </div>
  </div>

  <h3>Rolling back to a previous version</h3>

  <p>Rollback uses the same <strong>Edit Deployment</strong> path, pointed at an older tag that is still in the
  Registry:</p>

  <ol>
    <li>Open <strong>Developer Tools → Registry</strong>, select the repository, and note the immutable tag of the last known-good build (e.g. <code>:v1.2.2</code>).</li>
    <li>On the device's <strong>Applications</strong> tab, click <strong>Edit Deployment</strong> on the running container.</li>
    <li>Change the image tag to that previous tag, leave the rest of the form unchanged, and save. The device pulls the older tag and recreates the container.</li>
    <li>Open <strong>Logs</strong> and confirm the container reaches a healthy start.</li>
  </ol>

  <p>This works only while the previous tag still exists and has not been overwritten, which is why every release
  should carry its own immutable tag.</p>

  <hr>

  
  <h2 id="logs">Logs &amp; debug</h2>

  <p>Containerized applications write to <code>stdout</code> and <code>stderr</code>; ALPON captures both streams
  and exposes them in the dashboard. For deeper inspection, open the container's <strong>Shell</strong>.</p>

  <h3>Stream logs from the dashboard</h3>

  <p>On the <strong>Applications</strong> tab, click <strong>Logs</strong> next to the container. The view tails
  the last 1000 lines and streams new output in real time. Use it to confirm startup, watch request traffic, or
  catch crash loops.</p>

  <h3>Inspect a running container</h3>

  <p>Open the container's <strong>Shell</strong> from its detail view in the dashboard to drop into an interactive
  session. It uses the image's default shell (typically <code>/bin/sh</code> for Alpine, <code>/bin/bash</code>
  for Debian-based images).</p>

  <div class="sf-terminal">
    <div class="sf-terminal__header">
      <span class="sf-terminal__dot" style="background:#ff5f57"></span>
      <span class="sf-terminal__dot" style="background:#febc2e"></span>
      <span class="sf-terminal__dot" style="background:#28c840"></span>
      <span class="sf-terminal__title">container-shell</span>
    </div>
    <div class="sf-terminal__body"><pre><span class="t-dim"># 1. Inspect environment</span>
<span class="t-green">env</span> | <span class="t-green">grep</span> -i <span class="t-blue">DATABASE</span>

<span class="t-dim"># 2. Tail application log files written inside the container</span>
<span class="t-green">tail</span> -f /var/log/app.log

<span class="t-dim"># 3. Check listening ports</span>
<span class="t-green">netstat</span> -tlnp 2&gt;/dev/null || <span class="t-green">ss</span> -tlnp</pre></div>
  </div>

  <h3>Use the device terminal for Docker-level operations</h3>

  <p>The <strong>Shell</strong> session runs <em>inside</em> the container. To inspect Docker itself (image cache,
  volumes, networks), open the <strong>Remote Terminal</strong> on the <strong>Device</strong> tab.</p>

  <div class="sf-terminal">
    <div class="sf-terminal__header">
      <span class="sf-terminal__dot" style="background:#ff5f57"></span>
      <span class="sf-terminal__dot" style="background:#febc2e"></span>
      <span class="sf-terminal__dot" style="background:#28c840"></span>
      <span class="sf-terminal__title">device-terminal</span>
    </div>
    <div class="sf-terminal__body"><pre><span class="t-dim"># 1. List running containers on the device</span>
<span class="t-green">docker ps</span>

<span class="t-dim"># 2. Inspect a specific container's runtime config</span>
<span class="t-green">docker inspect</span> &lt;container_name&gt;

<span class="t-dim"># 3. View resource usage live</span>
<span class="t-green">docker stats</span></pre></div>
  </div>

  <hr>

  
  <h2 id="cicd">CI/CD integration</h2>

  <p>The Sixfab Container Registry is a standard OCI registry, so any CI system that can run Docker can build and
  push to it. Both examples below register the ARM emulator before building: hosted runners are x86_64, and an
  <code>arm64</code> build without <code>binfmt</code> registered fails with <code>exec format error</code>.</p>

  <h3>GitHub Actions: build &amp; push to Sixfab Registry</h3>

  <p>Store the registry password in repository secrets as <code>SIXFAB_REGISTRY_PASSWORD</code> and your username
  as <code>SIXFAB_REGISTRY_USERNAME</code>.</p>

  <div class="sf-terminal">
    <div class="sf-terminal__header">
      <span class="sf-terminal__dot" style="background:#ff5f57"></span>
      <span class="sf-terminal__dot" style="background:#febc2e"></span>
      <span class="sf-terminal__dot" style="background:#28c840"></span>
      <span class="sf-terminal__title">.github/workflows/release.yml</span>
    </div>
    <div class="sf-terminal__body"><pre><span class="t-pp">name</span>: Build and push to Sixfab Registry

<span class="t-pp">on</span>:
  <span class="t-pp">push</span>:
    <span class="t-pp">tags</span>: [<span class="t-blue">'v*'</span>]

<span class="t-pp">jobs</span>:
  <span class="t-pp">build</span>:
    <span class="t-pp">runs-on</span>: ubuntu-latest
    <span class="t-pp">steps</span>:
      - <span class="t-pp">uses</span>: actions/checkout@v4

      - <span class="t-pp">name</span>: Set up QEMU (arm64 emulation)
        <span class="t-pp">uses</span>: docker/setup-qemu-action@v3
        <span class="t-pp">with</span>:
          <span class="t-pp">platforms</span>: arm64

      - <span class="t-pp">name</span>: Set up Docker Buildx
        <span class="t-pp">uses</span>: docker/setup-buildx-action@v3

      - <span class="t-pp">name</span>: Log in to Sixfab Registry
        <span class="t-pp">uses</span>: docker/login-action@v3
        <span class="t-pp">with</span>:
          <span class="t-pp">registry</span>: cr.sixfab.io
          <span class="t-pp">username</span>: &#36;&#123;&#123; secrets.SIXFAB_REGISTRY_USERNAME &#125;&#125;
          <span class="t-pp">password</span>: &#36;&#123;&#123; secrets.SIXFAB_REGISTRY_PASSWORD &#125;&#125;

      - <span class="t-pp">name</span>: Build and push (linux/arm64)
        <span class="t-pp">uses</span>: docker/build-push-action@v5
        <span class="t-pp">with</span>:
          <span class="t-pp">context</span>: .
          <span class="t-pp">platforms</span>: linux/arm64
          <span class="t-pp">push</span>: <span class="t-yel">true</span>
          <span class="t-pp">tags</span>: |
            cr.sixfab.io/&#36;&#123;&#123; secrets.SIXFAB_REGISTRY_USERNAME &#125;&#125;/my-app:&#36;&#123;&#123; github.ref_name &#125;&#125;
            cr.sixfab.io/&#36;&#123;&#123; secrets.SIXFAB_REGISTRY_USERNAME &#125;&#125;/my-app:latest
          <span class="t-dim"># The moving :latest tag is optional. Keep it only if you use the Restart-based rollout below.</span></pre></div>
  </div>

  <h3>GitLab CI example</h3>

  <div class="sf-terminal">
    <div class="sf-terminal__header">
      <span class="sf-terminal__dot" style="background:#ff5f57"></span>
      <span class="sf-terminal__dot" style="background:#febc2e"></span>
      <span class="sf-terminal__dot" style="background:#28c840"></span>
      <span class="sf-terminal__title">.gitlab-ci.yml</span>
    </div>
    <div class="sf-terminal__body"><pre><span class="t-pp">build_arm64</span>:
  <span class="t-pp">image</span>: docker:24
  <span class="t-pp">services</span>: [docker:24-dind]
  <span class="t-pp">before_script</span>:
    - <span class="t-green">echo</span> <span class="t-blue">"$SIXFAB_REGISTRY_PASSWORD"</span> | docker login cr.sixfab.io &#92;
        -u <span class="t-blue">"$SIXFAB_REGISTRY_USERNAME"</span> --password-stdin
  <span class="t-pp">script</span>:
    - docker run --privileged --rm tonistiigi/binfmt --install arm64
    - docker buildx create --use
    - docker buildx build --platform linux/arm64 &#92;
        -t cr.sixfab.io/$SIXFAB_REGISTRY_USERNAME/my-app:$CI_COMMIT_TAG &#92;
        --push .</pre></div>
  </div>

  <h3>Triggering deployment from CI</h3>

  <p>Pushing a new tag does not automatically redeploy running containers. For automated rollout you have two
  choices:</p>

  <ul>
    <li><strong>Edit Deployment from the dashboard</strong> after CI publishes the new tag. Suitable for staged or manual rollouts.</li>
    <li><strong>Use mutable tags (<code>:latest</code>) plus the Restart action.</strong> CI overwrites <code>:latest</code>, then <strong>Restart</strong> the container from the device's <strong>Applications</strong> tab to force a fresh pull. That restart step is manual: there is no documented ALPON Cloud API endpoint for restarting a container. Sacrifices traceability for speed.</li>
  </ul>

  <hr>

  
  <h2 id="troubleshooting">Troubleshooting</h2>

  <p>Common failure modes and their fixes.</p>

  <div class="sf-issue-group">

    
    <details class="sf-issue sf-issue--hw" id="issue-exec-format">
      <summary class="sf-issue__head">
        <span class="sf-issue__dot" aria-hidden="true"></span>
        <span class="sf-issue__cat">Image</span>
        <h3 class="sf-issue__title">Image fails to start with "exec format error"</h3>
        <svg class="sf-issue__chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
      </summary>
      <div class="sf-issue__body">
        <h4>Cause</h4>
        <p>The image was built for <code>linux/amd64</code> instead of <code>linux/arm64</code>. ALPON runs on ARM64 (Raspberry Pi CM5 or CM4) and cannot execute x86 binaries.</p>
        <h4>Fix</h4>
        <p>Rebuild with <code>docker buildx build --platform linux/arm64</code> (on an x86 host, register the emulator first: <code>docker run --privileged --rm tonistiigi/binfmt --install arm64</code>). Confirm the result with <code>docker buildx imagetools inspect &lt;image&gt;</code>, which prints the platform of every manifest in the image; the listing must include <code>linux/arm64</code>.</p>
      </div>
    </details>

    
    <details class="sf-issue sf-issue--sw" id="issue-unauthorized-push">
      <summary class="sf-issue__head">
        <span class="sf-issue__dot" aria-hidden="true"></span>
        <span class="sf-issue__cat">Auth</span>
        <h3 class="sf-issue__title">"unauthorized: authentication required" on push</h3>
        <svg class="sf-issue__chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
      </summary>
      <div class="sf-issue__body">
        <h4>Cause</h4>
        <p>The local Docker session is not authenticated against <code>cr.sixfab.io</code>, or the password has been reset since you last logged in.</p>
        <h4>Fix</h4>
        <p>Run <code>docker login cr.sixfab.io --username &lt;your_username&gt;</code> and paste a current password. Use <strong>Reset Password</strong> on the Registry page if you have lost it.</p>
      </div>
    </details>

    
    <details class="sf-issue sf-issue--warning" id="issue-port-in-use">
      <summary class="sf-issue__head">
        <span class="sf-issue__dot" aria-hidden="true"></span>
        <span class="sf-issue__cat">Port</span>
        <h3 class="sf-issue__title">Port already in use; cannot deploy on port 30800</h3>
        <svg class="sf-issue__chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
      </summary>
      <div class="sf-issue__body">
        <h4>Cause</h4>
        <p>Another container on the device is bound to the same host port. Each host port can be used by only one container at a time.</p>
        <h4>Fix</h4>
        <p>Pick a different port within <span class="sf-port">30000–32767</span> (e.g. <span class="sf-port">30900</span>), or stop / edit the conflicting container first.</p>
      </div>
    </details>

    
    <details class="sf-issue sf-issue--sw" id="issue-pull-slow">
      <summary class="sf-issue__head">
        <span class="sf-issue__dot" aria-hidden="true"></span>
        <span class="sf-issue__cat">Network</span>
        <h3 class="sf-issue__title">Pull stuck or extremely slow over cellular</h3>
        <svg class="sf-issue__chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
      </summary>
      <div class="sf-issue__body">
        <h4>Cause</h4>
        <p>Large images over cellular links (especially uncompressed AI model weights) can take many minutes per layer. Large layers over cellular simply take time — the pull is usually still progressing rather than stuck.</p>
        <h4>Fix</h4>
        <p>Minimize image size with multi-stage builds, <code>.dockerignore</code>, and slim base images. For first-time provisioning of large images, attach the device to Wi-Fi or Ethernet temporarily; subsequent updates only transfer changed layers.</p>
      </div>
    </details>

    
    <details class="sf-issue sf-issue--warning" id="issue-quota">
      <summary class="sf-issue__head">
        <span class="sf-issue__dot" aria-hidden="true"></span>
        <span class="sf-issue__cat">Quota</span>
        <h3 class="sf-issue__title">Quota exceeded on push (10 GB / 100 tags)</h3>
        <svg class="sf-issue__chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
      </summary>
      <div class="sf-issue__body">
        <h4>Cause</h4>
        <p>The registry account has hit the default storage or tag-count quota.</p>
        <h4>Fix</h4>
        <p>Delete unused tags or whole repositories from the Registry page. Images currently in use by a deployed device are protected and cannot be deleted; stop the deployment first. To ask for a quota increase, <a href="https://sixfab.com/contact/" target="_blank" rel="noopener">contact Sixfab</a>.</p>
      </div>
    </details>

    
    <details class="sf-issue sf-issue--sw" id="issue-container-exits">
      <summary class="sf-issue__head">
        <span class="sf-issue__dot" aria-hidden="true"></span>
        <span class="sf-issue__cat">Runtime</span>
        <h3 class="sf-issue__title">Container starts then exits immediately</h3>
        <svg class="sf-issue__chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
      </summary>
      <div class="sf-issue__body">
        <h4>Cause</h4>
        <p>The application crashed during startup or the entrypoint completed without keeping the process alive.</p>
        <h4>Fix</h4>
        <p>Open <strong>Logs</strong> on the container to see the exit reason. Common cases: missing environment variable, invalid config file path, port already bound inside the container, missing volume source on the device. Fix and use <strong>Edit Deployment</strong> to relaunch.</p>
      </div>
    </details>

  </div>

  
  <section class="sf-related">
    <h2>Related guides</h2>
    <div class="sf-related__grid">
      <a class="sf-related__card" href="/docs/alpon-app-containerization-dockerfile-templates" target="_blank" rel="noopener">
        <div class="sf-related__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 4h16v16H4z"/><path d="M8 9h8M8 13h5"/></svg></div>
        <div class="sf-related__title">Containerize Apps for ALPON</div>
        <div class="sf-related__desc">Dockerfile templates for ARM64 builds, slim base images, and smaller layers.</div>
      </a>
      <a class="sf-related__card" href="/docs/alpon-update-containers-from-sixfab-registry" target="_blank" rel="noopener">
        <div class="sf-related__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12a9 9 0 1 1-3-6.7"/><path d="M21 4v5h-5"/></svg></div>
        <div class="sf-related__title">Update Containers from the Registry</div>
        <div class="sf-related__desc">Push a new tag and move a running container onto it from ALPON Cloud.</div>
      </a>
      <a class="sf-related__card" href="/docs/alpon-access-gpio-buttons-usb-docker-containers" target="_blank" rel="noopener">
        <div class="sf-related__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="4" y="4" width="16" height="16" rx="2"/><path d="M9 2v2M15 2v2M9 20v2M15 20v2M2 9h2M2 15h2M20 9h2M20 15h2"/></svg></div>
        <div class="sf-related__title">GPIO, Buttons &amp; USB in Containers</div>
        <div class="sf-related__desc">Privileged mode, the <code>/dev/gpiomem</code> mount, and on-board button reads.</div>
      </a>
      <a class="sf-related__card" href="/docs/alpon-cloud" target="_blank" rel="noopener">
        <div class="sf-related__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z"/></svg></div>
        <div class="sf-related__title">ALPON Cloud</div>
        <div class="sf-related__desc">Fleet onboarding, monitoring, OTA updates, and connectivity management.</div>
      </a>
    </div>
  </section>


</div>




<div class="sf-doc">

  <div class="sf-lightbox" id="lb-deploy-form" role="dialog" aria-label="Enlarged image: container deployment form">
    <a class="sf-lightbox__backdrop" href="#fig-deploy-form" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-deploy-form" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-deploy-form" aria-label="Close"><img src="https://files.readme.io/2a1a12aa93b209a8aca98ad8a61b1970d05576b39b6efc226be2945078289318-Sixfab_ALPON_X4_Manage_and_Deploy_1.webp" alt="Container deployment configuration form in ALPON Cloud"></a>
      <div class="sf-lightbox__caption">Container deployment form on the Applications tab.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-deploy-ports" role="dialog" aria-label="Enlarged image: port and environment configuration">
    <a class="sf-lightbox__backdrop" href="#fig-deploy-ports" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-deploy-ports" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-deploy-ports" aria-label="Close"><img src="https://files.readme.io/361f2782e8245728ead2854f91c289a708fc9e75d7b0cbb454ab2b39178dc026-Sixfab_ALPON_X4_Manage_and_Deploy_2.webp" alt="Port mapping and environment variable configuration"></a>
      <div class="sf-lightbox__caption">Port mapping and environment variable rows.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-deploy-volumes" role="dialog" aria-label="Enlarged image: volume and network configuration">
    <a class="sf-lightbox__backdrop" href="#fig-deploy-volumes" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-deploy-volumes" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-deploy-volumes" aria-label="Close"><img src="https://files.readme.io/a3882ccda71a804e18ee575aa69f43f7ccf1a2fe2fa3247a8c5da963ffdf42d6-Sixfab_ALPON_X4_Manage_and_Deploy_3.webp" alt="Volume bind mount, Host Network toggle, and Privileged toggle"></a>
      <div class="sf-lightbox__caption">Volume mounts, Host Network, and Privileged toggles.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-deploy-review" role="dialog" aria-label="Enlarged image: pre-deploy review">
    <a class="sf-lightbox__backdrop" href="#fig-deploy-review" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-deploy-review" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-deploy-review" aria-label="Close"><img src="https://files.readme.io/20617d18e1780825f99460bdd1e885f4cf6d27c33979c6e8d1668ec85ea8fce3-Sixfab_ALPON_X4_Manage_and_Deploy_4.webp" alt="Pre-deploy review screen in ALPON Cloud"></a>
      <div class="sf-lightbox__caption">Final review screen before clicking + Deploy.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-deploy-list" role="dialog" aria-label="Enlarged image: applications list with deployed container">
    <a class="sf-lightbox__backdrop" href="#fig-deploy-list" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-deploy-list" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-deploy-list" aria-label="Close"><img src="https://files.readme.io/807e7d9583bd8c3732c69d898cb1a8d24db87f7e9eee188ea3b9e2afbf895517-Sixfab_ALPON_X4_Manage_and_Deploy_5.webp" alt="Applications tab listing the deployed container with Running status"></a>
      <div class="sf-lightbox__caption">Deployed container appears in the Applications list with Running status.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-registry-overview" role="dialog" aria-label="Enlarged image: Sixfab Container Registry overview">
    <a class="sf-lightbox__backdrop" href="#fig-registry-overview" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-registry-overview" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-registry-overview" aria-label="Close"><img src="https://files.readme.io/ed02aad55cf98bff8052d2c769c71a91853c56cef36483daaf606c81f0cebe73-Screenshot_2024-12-10_at_1.55.18_AM.png" alt="Sixfab Container Registry overview page in ALPON Cloud"></a>
      <div class="sf-lightbox__caption">Container Registry page in ALPON Cloud.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-reg-username" role="dialog" aria-label="Enlarged image: Registry username">
    <a class="sf-lightbox__backdrop" href="#fig-reg-username" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-reg-username" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-reg-username" aria-label="Close"><img src="https://files.readme.io/2f7cd19106d878f95ff6fbee81617d323f00a0cc69eb2754300095a86db3682a-Sixfab_ALPON_X4_Manage_and_Deploy_App_Username.jpg" alt="Sixfab Registry page header showing the 6-digit username"></a>
      <div class="sf-lightbox__caption">Your registry username appears at the top of the Registry page.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-reg-reset" role="dialog" aria-label="Enlarged image: Registry Reset Password button">
    <a class="sf-lightbox__backdrop" href="#fig-reg-reset" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-reg-reset" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-reg-reset" aria-label="Close"><img src="https://files.readme.io/4b7a582bc6cf364745bff3f88c84f81dafe17c69bf9df61912cbab3e502a09bf-Sixfab_ALPON_X4_Manage_and_Deploy_12.webp" alt="Reset Password button on the Sixfab Registry page"></a>
      <div class="sf-lightbox__caption">Reset Password issues a new registry credential.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-reg-image-select" role="dialog" aria-label="Enlarged image: Registry image dropdown on deploy form">
    <a class="sf-lightbox__backdrop" href="#fig-reg-image-select" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-reg-image-select" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-reg-image-select" aria-label="Close"><img src="https://files.readme.io/f91c028b2b9e6d3d61a6b3513bb41ff6d6d416cf103cc2727c4f7d8171c80a4b-Screenshot_December_10_2024_23344_AM.png" alt="Image dropdown on the deploy form populated from the Sixfab Registry"></a>
      <div class="sf-lightbox__caption">Image dropdown lists every repository pushed to your Sixfab Registry namespace.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-reg-deploy-review" role="dialog" aria-label="Enlarged image: Registry deploy review">
    <a class="sf-lightbox__backdrop" href="#fig-reg-deploy-review" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-reg-deploy-review" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-reg-deploy-review" aria-label="Close"><img src="https://files.readme.io/aaf97ee4fb419afad0248a2d6c7f2de79e97d2781d9289374c3d2b02a7e215df-Screenshot_2024-12-10_at_2.33.15_AM.png" alt="Pre-deploy review screen for a Sixfab Registry image"></a>
      <div class="sf-lightbox__caption">Final review with a Sixfab Registry image.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-access-ip" role="dialog" aria-label="Enlarged image: Network tab device IP">
    <a class="sf-lightbox__backdrop" href="#fig-access-ip" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-access-ip" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-access-ip" aria-label="Close"><img src="https://files.readme.io/2860cc16318d42550e57a02cf17ebf559ad31a0ea597e9ac14bc816dc09864df-Sixfab_ALPON_X4_Manage_and_Deploy_6.webp" alt="Network tab on the Asset Detail page showing the device IP"></a>
      <div class="sf-lightbox__caption">Device IP on the Network tab of the Asset Detail page.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-access-nginx" role="dialog" aria-label="Enlarged image: nginx welcome page">
    <a class="sf-lightbox__backdrop" href="#fig-access-nginx" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-access-nginx" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-access-nginx" aria-label="Close"><img src="https://files.readme.io/a1e9f3dc6226517116f694e0f084da21cd19f15c944096ffd7cce0d5dc15831e-Sixfab_ALPON_X4_Manage_and_Deploy_7.webp" alt="nginx default welcome page served from the ALPON device"></a>
      <div class="sf-lightbox__caption">nginx welcome page served from ALPON over the local network.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-access-rt-btn" role="dialog" aria-label="Enlarged image: Open Remote Terminal button">
    <a class="sf-lightbox__backdrop" href="#fig-access-rt-btn" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-access-rt-btn" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-access-rt-btn" aria-label="Close"><img src="https://files.readme.io/1653192bdd56aad436e397ce14a1f48c4efe5c7abb67f0913dd34206a59cc0e9-Sixfab_ALPON_X4_Manage_and_Deploy_8.webp" alt="Open Remote Terminal button on the Device tab"></a>
      <div class="sf-lightbox__caption">Open Remote Terminal button on the Device tab.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-access-curl" role="dialog" aria-label="Enlarged image: curl response from container">
    <a class="sf-lightbox__backdrop" href="#fig-access-curl" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-access-curl" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-access-curl" aria-label="Close"><img src="https://files.readme.io/600d38df13d7586f54f8acc644124660cc9069d540bc4b579073c2441c72300e-Sixfab_ALPON_X4_Manage_and_Deploy_9.webp" alt="curl response from the remote terminal showing the container is running"></a>
      <div class="sf-lightbox__caption">curl response confirms the container is reachable on the device.</div>
    </div>
  </div>

  <div class="sf-lightbox" id="lb-manage-panel" role="dialog" aria-label="Enlarged image: container management panel">
    <a class="sf-lightbox__backdrop" href="#fig-manage-panel" aria-label="Close"></a>
    <a class="sf-lightbox__close" href="#fig-manage-panel" aria-label="Close enlarged image">
      <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
    </a>
    <div class="sf-lightbox__inner">
      <a class="sf-lightbox__img-wrap" href="#fig-manage-panel" aria-label="Close"><img src="https://files.readme.io/19eba8431503aebeac2b7727ff8e3a7c103c0620755ac9354322d22874870f80-Sixfab_ALPON_X4_Manage_and_Deploy_10.webp" alt="Container management panel on the Applications tab"></a>
      <div class="sf-lightbox__caption">Container management panel with full lifecycle controls.</div>
    </div>
  </div>

</div>



`}</HTMLBlock>

<br />