---
updatedAt: 2026-09-18T07:52:21.000Z
agentTools:
  projectIndex: https://docs.sixfab.com/llms.txt
---

# Master Unit for PLC Network Management

Use ALPON X5 AI and ALPON X4 as a Modbus TCP/RTU master to poll PLCs, sensors, and energy meters — with Modpoll for quick tests and Pymodbus for custom workflows.

<HTMLBlock>{`
<style>
/* ══════════════════════════════════════════════════════════════════════════
   SIXFAB DOCS · ALPON TUTORIAL STYLESHEET (canonical, shared by every page
   under ALPON › Tutorials). Do not edit per page: change it here and re-stamp
   into all tutorials so the block stays byte-identical.
   Components: hero · meta · pill · aeo · toc · step-list · terminal · callout
   · spec-card · figure/lightbox · issue · stack · path · table · related guides.
   Page-specific components go AFTER the "END CANONICAL" marker.
   ══════════════════════════════════════════════════════════════════════════ */
/* ════════════════════════════════════════════════════════════════════════
   FONTS - Gilroy (5 weights) + JetBrains Mono (2 weights)
   Per design language §1.1 starter boilerplate.
═════════════════════════════════════════════════════════════════════════ */
@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 - six-tier system, scoped to .sf-doc
═════════════════════════════════════════════════════════════════════════ */
.sf-doc {
  --primary:       #034860;
  --secondary:     #00E0B8;
  --tertiary:      #1B2D45;
  --neutral:       #E8F5F0;
  --white:         #FFFFFF;
  --light:         #F6F8F9;
  --line:          #DDE6EC;
  --slate-light:   #94A8B5;
  --slate:         #52667A;
  --deep-ink:      #10202E;
  --ai-iris:       #6B47F0;
  --ai-mist:       #F0EDFF;
  --alpon-purple:  #4F008E;
  --alpon-cyan:    #00A6C8;   /* ALPON Gradient end */
  --alpon-cyan-deep: #007A8F; /* cyan surface for white text (WCAG AA 5.0:1) */
  --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-primary:    #FFFFFF;

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

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

  --shadow-sm: 0 1px 2px rgba(10,23,33,.04);
  --shadow-md: 0 4px 12px rgba(10,23,33,.06);
  --shadow-lg: 0 8px 24px rgba(10,23,33,.08);

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

  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--deep-ink);
  -webkit-font-smoothing: antialiased;
}
.sf-doc * { box-sizing: border-box; }

/* ════════════════════════════════════════════════════════════════════════
   BASE TYPOGRAPHY
═════════════════════════════════════════════════════════════════════════ */
.sf-doc h1 {
  font-size: 3rem; font-weight: 800; letter-spacing: -0.03em;
  line-height: 1.08; color: var(--deep-ink); margin: 0 0 16px;
}
.sf-doc h2 {
  font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em;
  line-height: 1.2; color: var(--primary);
  margin: 56px 0 16px; padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}
.sf-doc h2:first-of-type { margin-top: 0; }
.sf-doc h3 {
  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-size: 0.875rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--slate);
  margin: 18px 0 6px;
}
.sf-doc p {
  font-size: 1rem; font-weight: 400; line-height: 1.6;
  color: var(--deep-ink); margin: 0 0 14px;
}
.sf-doc ul, .sf-doc ol { padding-left: 24px; margin: 8px 0 16px; }
.sf-doc li { font-size: 1rem; line-height: 1.6; color: var(--deep-ink); margin-bottom: 6px; }
.sf-doc ul li::marker { color: var(--primary); }
.sf-doc a { color: var(--primary); text-decoration: none; }
.sf-doc a:hover { color: var(--deep-ink); text-decoration: underline; }
.sf-doc code {
  font-family: var(--font-mono); font-size: 0.875rem;
  background: var(--light); color: var(--primary);
  padding: 1px 5px; border-radius: var(--r-sm); border: 0;
}
.sf-doc strong { color: var(--deep-ink); font-weight: 700; }
.sf-doc hr { border: 0; height: 1px; background: var(--line); margin: 48px 0; }

/* ════════════════════════════════════════════════════════════════════════
   META BAR
═════════════════════════════════════════════════════════════════════════ */
.sf-doc .sf-meta {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  font-family: var(--font-mono); font-size: 0.75rem;
  color: var(--slate); margin: 0 0 24px;
}
.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); letter-spacing: 0;
  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); }

/* ════════════════════════════════════════════════════════════════════════
   HERO - compact, default Tier 1 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 p.sf-hero__lead,
.sf-doc .sf-hero .sf-hero__lead {
  font-size: 1.0625rem; line-height: 1.6;
  color: var(--deep-ink); margin: 0 0 18px;
  text-align: justify;
  hyphens: auto;
  -webkit-hyphens: auto;
}
.sf-doc .sf-hero__chips { display: flex; flex-wrap: wrap; gap: 6px; }

/* ════════════════════════════════════════════════════════════════════════
   PILLS
═════════════════════════════════════════════════════════════════════════ */
.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: 4px 10px; 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;
}
.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--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 - default Tier 1
═════════════════════════════════════════════════════════════════════════ */
.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__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__text {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--deep-ink);
  margin: 0;
  text-align: justify;
  hyphens: auto;
  -webkit-hyphens: auto;
}
.sf-doc .sf-aeo__text strong { color: var(--primary); font-weight: 600; }
.sf-doc .sf-aeo__text code { font-size: 0.8125rem; }

/* ════════════════════════════════════════════════════════════════════════
   IN THIS GUIDE - sf-toc
═════════════════════════════════════════════════════════════════════════ */
.sf-doc .sf-toc {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  padding: var(--md) var(--lg);
  background: var(--light); border: 1px solid var(--line);
  border-radius: var(--r-lg); margin: 0 0 var(--xl);
}
.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: var(--sm);
}
.sf-doc .sf-toc__item {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; background: var(--white);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  font-size: 0.8125rem; font-weight: 600;
  color: var(--deep-ink) !important; text-decoration: none !important;
  transition: border-color .15s, box-shadow .15s; white-space: nowrap;
}
.sf-doc .sf-toc__item:hover,
.sf-doc .sf-toc__item:focus {
  background: var(--primary); color: var(--white) !important;
  border-color: var(--primary); text-decoration: none !important;
}
.sf-doc .sf-toc__item:hover .sf-toc__num,
.sf-doc .sf-toc__item:focus .sf-toc__num { color: var(--secondary); }
.sf-doc .sf-toc__num {
  font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500;
  color: var(--slate);
}

/* ════════════════════════════════════════════════════════════════════════
   ICONS
═════════════════════════════════════════════════════════════════════════ */
.sf-doc .sf-icon { width: 16px; height: 16px; flex-shrink: 0; vertical-align: -2px; }
.sf-doc .sf-icon--stroke { fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }

/* ════════════════════════════════════════════════════════════════════════
   SPEC CARDS - identical to alpon-x4-specifications.html tables
═════════════════════════════════════════════════════════════════════════ */
.sf-doc .sf-spec-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px; margin: 0 0 24px;
}
.sf-doc .sf-spec-card {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xl); padding: 20px 22px;
  display: flex; flex-direction: column;
  margin: 16px 0 24px; transition: border-color .15s;
}
.sf-doc .sf-spec-grid .sf-spec-card { margin: 0; }
.sf-doc .sf-spec-card:hover { border-color: var(--slate-light); }
.sf-doc .sf-spec-card__head {
  display: flex; align-items: center; gap: 10px;
  padding-bottom: 14px; border-bottom: 1px solid var(--line);
  margin-bottom: 14px;
}
.sf-doc .sf-spec-card__icon {
  width: 32px; height: 32px; border-radius: var(--r-md);
  background: var(--light); color: var(--primary);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.sf-doc .sf-spec-card__icon svg { width: 18px; height: 18px; }
.sf-doc .sf-spec-card__title {
  font-size: 1rem; font-weight: 700;
  color: var(--primary); letter-spacing: -0.01em;
}
.sf-doc .sf-spec-card__body { display: flex; flex-direction: column; }
.sf-doc .sf-spec-row {
  display: grid; grid-template-columns: minmax(160px, 30%) 1fr;
  gap: 24px; align-items: baseline;
  padding: 11px 0; border-bottom: 1px dashed var(--line);
}
.sf-doc .sf-spec-row:first-child { padding-top: 4px; }
.sf-doc .sf-spec-row:last-child { border-bottom: 0; padding-bottom: 4px; }
.sf-doc .sf-spec-row__key {
  font-size: 0.9375rem; font-weight: 700;
  color: var(--deep-ink); line-height: 1.5;
}
.sf-doc .sf-spec-row__val {
  font-size: 0.9375rem; font-weight: 500;
  color: var(--deep-ink); line-height: 1.55;
  text-align: left; min-width: 0;
}
.sf-doc .sf-spec-row__val code { font-size: 0.875rem; }
.sf-doc .sf-spec-row__val em { font-style: italic; color: var(--slate); font-weight: 500; }

/* ════════════════════════════════════════════════════════════════════════
   CALLOUT
═════════════════════════════════════════════════════════════════════════ */
.sf-doc .sf-callout {
  display: flex; flex-direction: column; gap: 6px;
  border-radius: var(--r-md); padding: 14px 18px;
  margin: 20px 0; border-left: 4px solid;
}
.sf-doc .sf-callout__header {
  display: flex; align-items: center; gap: 8px;
  font-size: 0.875rem; font-weight: 700; line-height: 1;
}
.sf-doc .sf-callout__header svg { width: 16px; height: 16px; 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 0 6px; font-size: 0.9375rem; color: inherit; }
.sf-doc .sf-callout__content p:last-child { margin-bottom: 0; }
.sf-doc .sf-callout__content code { background: rgba(0,0,0,0.06); border: 0; }
.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
═════════════════════════════════════════════════════════════════════════ */
.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 {
  position: relative; z-index: 1;
  padding-bottom: var(--2xl); scroll-margin-top: 24px;
}
.sf-doc .sf-step:last-child { padding-bottom: 0; }
.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__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__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; }

/* ════════════════════════════════════════════════════════════════════════
   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; }

/* ════════════════════════════════════════════════════════════════════════
   COMPARISON GRID - Stripe-style two-column path picker
═════════════════════════════════════════════════════════════════════════ */
.sf-doc .sf-paths {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px;
  margin: 16px 0 32px;
}
.sf-doc .sf-path {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-xl); padding: 22px 24px;
  display: flex; flex-direction: column;
  transition: border-color .15s, box-shadow .15s;
}
.sf-doc .sf-path:hover { border-color: var(--slate-light); box-shadow: var(--shadow-md); }
.sf-doc .sf-path__tag {
  font-family: var(--font-mono); font-size: 0.6875rem;
  font-weight: 500; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--slate);
  margin-bottom: 8px;
}
.sf-doc .sf-path__title {
  font-size: 1.125rem; font-weight: 700;
  color: var(--deep-ink); margin: 0 0 8px;
  letter-spacing: -0.01em;
}
.sf-doc .sf-path__desc {
  font-size: 0.9375rem; line-height: 1.55;
  color: var(--slate); margin: 0 0 14px;
}
.sf-doc .sf-path__list {
  list-style: none !important;
  padding: 0 !important;
  margin: 0 0 14px !important;
}
.sf-doc .sf-path__list li {
  font-size: 0.9375rem;
  color: var(--deep-ink);
  padding: 6px 0 6px 28px;
  position: relative;
  margin: 0;
  line-height: 1.5;
  list-style: none !important;
}
.sf-doc .sf-path__list li::marker { content: '' !important; }
.sf-doc .sf-path__list li::before {
  content: ''; position: absolute;
  left: 0; top: 10px;
  width: 16px; height: 16px;
  background: var(--neutral);
  border-radius: var(--r-full);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23034860' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 11px;
  flex-shrink: 0;
}
.sf-doc .sf-path__foot {
  margin-top: auto; padding-top: 14px;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono); font-size: 0.75rem;
  color: var(--slate);
}
.sf-doc .sf-path__foot strong { color: var(--primary); font-weight: 600; }

/* ════════════════════════════════════════════════════════════════════════
   DOCKERFILE STACK PICKER
═════════════════════════════════════════════════════════════════════════ */
.sf-doc .sf-stack-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px; margin: 16px 0 24px;
}
.sf-doc .sf-stack {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 18px 20px;
  text-decoration: none !important;
  transition: border-color .15s, transform .15s, box-shadow .15s;
  display: flex; align-items: center; gap: 14px;
  color: var(--deep-ink) !important;
}
.sf-doc .sf-stack__badge {
  width: 44px; height: 44px;
  border-radius: var(--r-md);
  background: var(--neutral);
  color: var(--primary);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono);
  font-size: 1rem; font-weight: 700;
  letter-spacing: -0.02em; flex-shrink: 0;
}
.sf-doc .sf-stack__copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sf-doc .sf-stack:hover {
  border-color: var(--primary); transform: translateY(-2px);
  box-shadow: var(--shadow-md); text-decoration: none !important;
}
.sf-doc .sf-stack__lang {
  font-family: var(--font-sans); font-size: 0.9375rem;
  font-weight: 700; color: var(--deep-ink); letter-spacing: -0.01em;
}
.sf-doc .sf-stack__base {
  font-family: var(--font-mono); font-size: 0.75rem;
  color: var(--slate); font-weight: 500;
}

/* ════════════════════════════════════════════════════════════════════════
   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;
}

/* ════════════════════════════════════════════════════════════════════════
   ISSUE / TROUBLESHOOTING - mirrors alpon-create-wifi-hotspot pattern
   summary + tag pill + Symptom/Cause/Fix body
═════════════════════════════════════════════════════════════════════════ */
.sf-doc .sf-issue {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  margin: 0 0 12px;
  overflow: hidden;
  transition: border-color .15s, box-shadow .15s;
}
.sf-doc .sf-issue:hover { border-color: var(--slate-light); }
.sf-doc .sf-issue[open] {
  border-color: var(--primary);
  box-shadow: var(--shadow-sm);
}
.sf-doc .sf-issue__summary {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 20px;
  font-family: var(--font-sans);
  font-size: 1rem; font-weight: 700;
  color: var(--deep-ink);
  cursor: pointer; list-style: none;
}
.sf-doc .sf-issue__summary::-webkit-details-marker { display: none; }
.sf-doc .sf-issue__summary > span:nth-child(2) {
  flex: 1; line-height: 1.45; font-weight: 700;
}
.sf-doc .sf-issue__tag {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: var(--r-sm);
  background: var(--info-bg);
  color: var(--info-text);
  border: 1px solid var(--info-bg);
  flex-shrink: 0;
  white-space: nowrap;
}
.sf-doc .sf-issue__tag--hw {
  background: var(--danger-bg); color: var(--danger-text); border-color: var(--danger-bg);
}
.sf-doc .sf-issue__tag--sw {
  background: var(--ai-mist); color: var(--ai-iris); border-color: var(--ai-mist);
}
.sf-doc .sf-issue__tag--auth {
  background: var(--warning-bg); color: var(--warning-text); border-color: var(--warning-bg);
}
.sf-doc .sf-issue__tag--net {
  background: var(--info-bg); color: var(--info-text); border-color: var(--info-bg);
}
.sf-doc .sf-issue__tag--config {
  background: var(--neutral); color: var(--primary); border-color: var(--neutral);
}
.sf-doc .sf-issue__chev {
  width: 18px; height: 18px;
  color: var(--slate);
  flex-shrink: 0;
  transition: transform .2s;
}
.sf-doc .sf-issue[open] .sf-issue__chev {
  transform: rotate(180deg);
  color: var(--primary);
}
.sf-doc .sf-issue__body {
  padding: 4px 20px 20px;
  border-top: 1px solid var(--line);
}
.sf-doc .sf-issue__body h4 {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--slate);
  margin: 18px 0 8px;
}
.sf-doc .sf-issue__body h4:first-child { margin-top: 14px; }
.sf-doc .sf-issue__body p {
  font-size: 0.9375rem;
  line-height: 1.65;
  margin: 0 0 8px;
  color: var(--deep-ink);
}
.sf-doc .sf-issue__body p:last-child { margin-bottom: 0; }
.sf-doc .sf-issue__body code { font-size: 0.8125rem; }
.sf-doc .sf-issue__body .sf-terminal { margin: 10px 0 0; }

/* ════════════════════════════════════════════════════════════════════════
   DARK MODE
═════════════════════════════════════════════════════════════════════════ */
[data-color-mode="dark"] .sf-doc {
  --primary: #034860; --secondary: #00E0B8; --tertiary: #1B2D45;
  --neutral: #E8F5F0; --white: #FFFFFF; --light: #14222F;
  --line: #2A3A4D; --slate-light: #94A8B5; --slate: #B5C3CE;
  --deep-ink: #E8F5F0;
  --success-bg: #052E1B; --warning-bg: #2A1F05;
  --danger-bg: #2A0E0E; --info-bg: #0A2E3F;
  --success-text: #34D399; --warning-text: #FBBF24;
  --danger-text: #F87171; --info-text: #5CD3EE;
  --ai-iris: #B59CFF; --ai-mist: #1F1A33;
  color: var(--deep-ink);
}
[data-color-mode="dark"] .sf-doc h1,
[data-color-mode="dark"] .sf-doc h3,
[data-color-mode="dark"] .sf-doc h4,
[data-color-mode="dark"] .sf-doc strong { color: #FFFFFF; }
[data-color-mode="dark"] .sf-doc h2 { color: var(--secondary); border-color: var(--line); }
[data-color-mode="dark"] .sf-doc p,
[data-color-mode="dark"] .sf-doc li,
[data-color-mode="dark"] .sf-doc .sf-aeo__text,
[data-color-mode="dark"] .sf-doc .sf-callout__content { color: var(--neutral); }
html[data-color-mode="dark"] .sf-doc a { color: var(--secondary); }
[data-color-mode="dark"] .sf-doc code { background: rgba(255,255,255,0.06); color: var(--secondary); }
[data-color-mode="dark"] .sf-doc hr { background: var(--line); }
[data-color-mode="dark"] .sf-doc ul li::marker { color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-meta__badge { background: rgba(255,255,255,0.06); color: var(--secondary); border-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-aeo { background: rgba(255,255,255,0.04); border-color: var(--line); border-left-color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-aeo__label { color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-aeo__text strong { color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-hero { background: rgba(255,255,255,0.04); border-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-hero p.sf-hero__title,
[data-color-mode="dark"] .sf-doc .sf-hero .sf-hero__title { color: #FFFFFF; }
[data-color-mode="dark"] .sf-doc .sf-hero p.sf-hero__lead,
[data-color-mode="dark"] .sf-doc .sf-hero .sf-hero__lead { color: var(--neutral); }
[data-color-mode="dark"] .sf-doc .sf-toc { background: rgba(255,255,255,0.04); border-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-toc__item { background: transparent; color: var(--neutral) !important; border-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-toc__item:hover { background: var(--secondary); color: var(--tertiary) !important; border-color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-toc__item:hover .sf-toc__num { color: var(--tertiary); }
[data-color-mode="dark"] .sf-doc .sf-spec-card { background: rgba(255,255,255,0.04); border-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-spec-card:hover { border-color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-spec-card__head { border-bottom-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-spec-card__icon { background: rgba(0,224,184,0.10); color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-spec-card__title { color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-spec-row { border-bottom-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-spec-row__key { color: #FFFFFF; }
[data-color-mode="dark"] .sf-doc .sf-spec-row__val { color: var(--neutral); }
[data-color-mode="dark"] .sf-doc .sf-spec-row__val code { background: rgba(255,255,255,0.06); color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-pill { background: rgba(255,255,255,0.06); color: var(--neutral); border-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-path { background: rgba(255,255,255,0.04); border-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-path__list li { color: var(--neutral); }
[data-color-mode="dark"] .sf-doc .sf-path__list li::before { background: rgba(0,224,184,0.14); background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300E0B8' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>"); }
[data-color-mode="dark"] .sf-doc .sf-path__foot { border-top-color: var(--line); color: var(--slate); }
[data-color-mode="dark"] .sf-doc .sf-path__foot strong { color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-stack { background: rgba(255,255,255,0.04); border-color: var(--line); color: var(--neutral) !important; }
[data-color-mode="dark"] .sf-doc .sf-stack:hover { border-color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-stack__lang { color: #FFFFFF; }
[data-color-mode="dark"] .sf-doc .sf-stack__base { color: var(--slate); }
[data-color-mode="dark"] .sf-doc .sf-stack__badge { background: rgba(0,224,184,0.12); color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-issue { background: rgba(255,255,255,0.04); border-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-issue:hover { border-color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-issue[open] { border-color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-issue__summary { color: #FFFFFF; }
[data-color-mode="dark"] .sf-doc .sf-issue__body { border-top-color: var(--line); }
[data-color-mode="dark"] .sf-doc .sf-issue__body p { color: var(--neutral); }
[data-color-mode="dark"] .sf-doc .sf-issue__body code { background: rgba(255,255,255,0.06); color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-issue__tag--sw { background: rgba(107,71,240,0.18); color: #B59CFF; border-color: rgba(107,71,240,0.30); }
[data-color-mode="dark"] .sf-doc .sf-issue__tag--config { background: rgba(0,224,184,0.12); color: var(--secondary); border-color: rgba(0,224,184,0.22); }
[data-color-mode="dark"] .sf-doc .sf-issue[open] .sf-issue__chev { color: var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-step__num { box-shadow: 0 0 0 5px var(--tertiary), 0 4px 10px rgba(0,0,0,.40); }

@media (prefers-color-scheme: dark) {
  html:not([data-color-mode="light"]) .sf-doc {
    --primary: #034860; --secondary: #00E0B8; --tertiary: #1B2D45;
    --neutral: #E8F5F0; --white: #FFFFFF; --light: #14222F;
    --line: #2A3A4D; --slate-light: #94A8B5; --slate: #B5C3CE;
    --deep-ink: #E8F5F0;
    --success-bg: #052E1B; --warning-bg: #2A1F05;
    --danger-bg: #2A0E0E; --info-bg: #0A2E3F;
    --success-text: #34D399; --warning-text: #FBBF24;
    --danger-text: #F87171; --info-text: #5CD3EE;
  --ai-iris: #B59CFF; --ai-mist: #1F1A33;
    color: var(--deep-ink);
  }
  html:not([data-color-mode="light"]) .sf-doc h1,
  html:not([data-color-mode="light"]) .sf-doc h3,
  html:not([data-color-mode="light"]) .sf-doc h4,
  html:not([data-color-mode="light"]) .sf-doc strong { color: #FFFFFF; }
  html:not([data-color-mode="light"]) .sf-doc h2 { color: var(--secondary); border-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc p,
  html:not([data-color-mode="light"]) .sf-doc li,
  html:not([data-color-mode="light"]) .sf-doc .sf-aeo__text,
  html:not([data-color-mode="light"]) .sf-doc .sf-callout__content { color: var(--neutral); }
  html:not([data-color-mode="light"]) .sf-doc a { color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc code { background: rgba(255,255,255,0.06); color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc hr { background: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc ul li::marker { color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-meta__badge { background: rgba(255,255,255,0.06); color: var(--secondary); border-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-aeo { background: rgba(255,255,255,0.04); border-color: var(--line); border-left-color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-aeo__label { color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-aeo__text strong { color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-hero { background: rgba(255,255,255,0.04); border-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-hero p.sf-hero__title,
  html:not([data-color-mode="light"]) .sf-doc .sf-hero .sf-hero__title { color: #FFFFFF; }
  html:not([data-color-mode="light"]) .sf-doc .sf-hero p.sf-hero__lead,
  html:not([data-color-mode="light"]) .sf-doc .sf-hero .sf-hero__lead { color: var(--neutral); }
  html:not([data-color-mode="light"]) .sf-doc .sf-toc { background: rgba(255,255,255,0.04); border-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-toc__item { background: transparent; color: var(--neutral) !important; border-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-toc__item:hover { background: var(--secondary); color: var(--tertiary) !important; border-color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-toc__item:hover .sf-toc__num { color: var(--tertiary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-spec-card { background: rgba(255,255,255,0.04); border-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-spec-card:hover { border-color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-spec-card__head { border-bottom-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-spec-card__icon { background: rgba(0,224,184,0.10); color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-spec-card__title { color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-spec-row { border-bottom-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-spec-row__key { color: #FFFFFF; }
  html:not([data-color-mode="light"]) .sf-doc .sf-spec-row__val { color: var(--neutral); }
  html:not([data-color-mode="light"]) .sf-doc .sf-spec-row__val code { background: rgba(255,255,255,0.06); color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-pill { background: rgba(255,255,255,0.06); color: var(--neutral); border-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-path { background: rgba(255,255,255,0.04); border-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-path__list li { color: var(--neutral); }
  html:not([data-color-mode="light"]) .sf-doc .sf-path__list li::before { background: rgba(0,224,184,0.14); background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300E0B8' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>"); }
  html:not([data-color-mode="light"]) .sf-doc .sf-path__foot { border-top-color: var(--line); color: var(--slate); }
  html:not([data-color-mode="light"]) .sf-doc .sf-path__foot strong { color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-stack { background: rgba(255,255,255,0.04); border-color: var(--line); color: var(--neutral) !important; }
  html:not([data-color-mode="light"]) .sf-doc .sf-stack:hover { border-color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-stack__lang { color: #FFFFFF; }
  html:not([data-color-mode="light"]) .sf-doc .sf-stack__base { color: var(--slate); }
  html:not([data-color-mode="light"]) .sf-doc .sf-stack__badge { background: rgba(0,224,184,0.12); color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-issue { background: rgba(255,255,255,0.04); border-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-issue:hover { border-color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-issue[open] { border-color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-issue__summary { color: #FFFFFF; }
  html:not([data-color-mode="light"]) .sf-doc .sf-issue__body { border-top-color: var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-issue__body p { color: var(--neutral); }
  html:not([data-color-mode="light"]) .sf-doc .sf-issue__body code { background: rgba(255,255,255,0.06); color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-issue__tag--sw { background: rgba(107,71,240,0.18); color: #B59CFF; border-color: rgba(107,71,240,0.30); }
  html:not([data-color-mode="light"]) .sf-doc .sf-issue__tag--config { background: rgba(0,224,184,0.12); color: var(--secondary); border-color: rgba(0,224,184,0.22); }
  html:not([data-color-mode="light"]) .sf-doc .sf-issue[open] .sf-issue__chev { color: var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-step__num { box-shadow: 0 0 0 5px var(--tertiary), 0 4px 10px rgba(0,0,0,.40); }
}

/* ════════════════════════════════════════════════════════════════════════
   RESPONSIVE
═════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
  .sf-doc h1 { font-size: 2.25rem; }
  .sf-doc h2 { font-size: 1.25rem; margin-top: 48px; }
  .sf-doc .sf-hero { padding: var(--md); }
  .sf-doc .sf-hero p.sf-hero__title,
  .sf-doc .sf-hero .sf-hero__title { font-size: 1.75rem; }
  .sf-doc .sf-aeo { padding: var(--md) var(--lg); }
  .sf-doc .sf-aeo__label { font-size: 1.125rem; }
  .sf-doc .sf-toc { gap: 4px; padding: 10px; }
  .sf-doc .sf-spec-card { padding: 16px 18px; }
  .sf-doc .sf-spec-row { grid-template-columns: 1fr; gap: 4px; padding: 12px 0; }
  .sf-doc .sf-spec-row__key { font-size: 0.875rem; }
  .sf-doc .sf-spec-row__val { font-size: 0.9375rem; }
  .sf-doc .sf-paths { grid-template-columns: 1fr; }
  .sf-doc .sf-stack-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; }
}
@media (max-width: 480px) {
  .sf-doc .sf-hero p.sf-hero__title,
  .sf-doc .sf-hero .sf-hero__title { font-size: 1.5rem; }
  .sf-doc .sf-step__body { padding-left: 0; }
}

/* ═══════════════════════════════════════════════════════════════
   TABLES · .sf-table inside .sf-table-wrap (core component)
   Real <table> markup needs the ReadMe reset at the end of this
   section: ReadMe ships table { display:block; width:max-content }.
   ═══════════════════════════════════════════════════════════════ */
.sf-doc .sf-table-wrap { display:block; width:100%; overflow-x:auto; border:1px solid var(--line); border-radius:var(--r-lg); background:var(--white); margin:16px 0 24px; }
.sf-doc .sf-table { width:100% !important; border-collapse:separate; border-spacing:0; font-size:0.9375rem; margin:0 !important; }
.sf-doc .sf-table thead th { padding:12px 16px; font-family:var(--font-sans); font-size:0.8125rem; font-weight:700; letter-spacing:0; text-transform:none; color:var(--slate); background:var(--light); text-align:left; border-bottom:1px solid var(--line); white-space:nowrap; }
.sf-doc .sf-table td { padding:12px 16px; border-bottom:1px solid var(--line); font-size:0.9375rem; color:var(--deep-ink); vertical-align:top; }
.sf-doc .sf-table tbody th, .sf-doc .sf-table th[scope="row"] { padding:12px 16px; border-bottom:1px solid var(--line); font-family:var(--font-sans); font-size:0.9375rem; font-weight:600; text-align:left; color:var(--primary); background:var(--light); width:32%; vertical-align:top; white-space:normal; }
.sf-doc .sf-table tr:last-child td, .sf-doc .sf-table tr:last-child th { border-bottom:0; }
.sf-doc .sf-table code { font-size:0.8125rem; }
.sf-doc .sf-table--data { table-layout:fixed !important; width:100% !important; min-width:100% !important; }
.sf-doc .sf-table--data thead th { white-space:normal !important; }
.sf-doc .sf-table--data td:nth-child(1), .sf-doc .sf-table--data th:nth-child(1) { width:22% !important; }
.sf-doc .sf-table--data td:nth-child(2), .sf-doc .sf-table--data th:nth-child(2) { width:39% !important; }
.sf-doc .sf-table--data td:nth-child(3), .sf-doc .sf-table--data th:nth-child(3) { width:39% !important; }
.sf-doc .sf-table--data tbody tr td:first-child { font-weight:600; color:var(--primary); }
.sf-doc .sf-table-wrap { display:block !important; width:100% !important; overflow-x:auto !important; }

[data-color-mode="dark"] .sf-doc .sf-table-wrap { background:rgba(255,255,255,0.04); border-color:var(--line); }
[data-color-mode="dark"] .sf-doc .sf-table thead th { background:rgba(255,255,255,0.06); color:var(--slate); border-bottom-color:var(--line); }
[data-color-mode="dark"] .sf-doc .sf-table td { color:var(--neutral); border-bottom-color:var(--line); }
[data-color-mode="dark"] .sf-doc .sf-table tbody th, [data-color-mode="dark"] .sf-doc .sf-table th[scope="row"] { background:rgba(255,255,255,0.06); color:var(--secondary); border-bottom-color:var(--line); }
[data-color-mode="dark"] .sf-doc .sf-table--data tbody tr td:first-child { color:var(--secondary); }
@media (prefers-color-scheme: dark) {
  html:not([data-color-mode="light"]) .sf-doc .sf-table-wrap { background:rgba(255,255,255,0.04); border-color:var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-table thead th { background:rgba(255,255,255,0.06); color:var(--slate); border-bottom-color:var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-table td { color:var(--neutral); border-bottom-color:var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-table tbody th, html:not([data-color-mode="light"]) .sf-doc .sf-table th[scope="row"] { background:rgba(255,255,255,0.06); color:var(--secondary); border-bottom-color:var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-table--data tbody tr td:first-child { color:var(--secondary); }
}
@media (max-width: 640px) {
  .sf-doc .sf-table td, .sf-doc .sf-table th { padding:9px 12px; font-size:0.8125rem; }
}

/* ReadMe table reset */
.markdown-body table { margin-bottom:0 !important; }
.sf-doc table.sf-table { display:table !important; width:100% !important; table-layout:auto !important; }
.sf-doc table.sf-table.sf-table--data { table-layout:fixed !important; }
/* Modifiers used by several tutorials but missing from the base lineage */
.sf-doc .sf-step__hint { font-size: 0.875rem; color: var(--slate); margin: 6px 0 0; }
.sf-doc .sf-terminal__dot--r { background: #ff5f56; }
.sf-doc .sf-terminal__dot--y { background: #ffbd2e; }
.sf-doc .sf-terminal__dot--g { background: #27c93f; }
.sf-doc .sf-terminal__lang { margin-left: auto; font-family: var(--font-mono) !important; font-size: 0.6875rem !important; color: #c9d1d9 !important; background: rgba(255,255,255,0.06); padding: 2px 8px; border-radius: var(--r-sm); font-weight: 600; letter-spacing: 0.05em; }
[data-color-mode="dark"] .sf-doc .sf-step__hint { color: var(--slate); }
@media (prefers-color-scheme: dark) {
  html:not([data-color-mode="light"]) .sf-doc .sf-step__hint { color: var(--slate); }
}
/* ════════════════════════════════════════════════════════════════════════
   RELATED GUIDES — shared discovery footer
═════════════════════════════════════════════════════════════════════════ */
.sf-doc .sf-related { position:relative; margin:56px 0 8px; padding:28px; border:1px solid var(--line); border-radius:var(--r-2xl); background:linear-gradient(135deg, rgba(3,72,96,.055) 0%, rgba(0,224,184,.075) 100%); overflow:hidden; }
.sf-doc .sf-related::before { content:''; position:absolute; width:220px; height:220px; right:-90px; top:-120px; border-radius:50%; background:radial-gradient(circle, rgba(0,224,184,.18) 0%, rgba(0,224,184,0) 70%); pointer-events:none; }
.sf-doc .sf-related__head { position:relative; display:grid; grid-template-columns:minmax(0, .8fr) minmax(260px, 1.2fr); gap:24px; align-items:end; margin-bottom:22px; }
.sf-doc .sf-related__eyebrow { display:block; margin-bottom:7px; font-family:var(--font-mono); font-size:.6875rem; font-weight:500; line-height:1.4; letter-spacing:.13em; text-transform:uppercase; color:var(--primary); }
.sf-doc .sf-related__title { margin:0; padding:0; border:0; font-size:1.625rem; line-height:1.15; color:var(--deep-ink); }
.sf-doc .sf-related__intro { margin:0; color:var(--slate); font-size:.9375rem; line-height:1.55; }
.sf-doc .sf-related__grid { position:relative; display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:12px; }
.sf-doc .sf-related__card { position:relative; display:grid; grid-template-rows:auto auto auto 1fr auto; min-width:0; min-height:190px; padding:18px; background:var(--white); border:1px solid var(--line); border-radius:var(--r-xl); color:var(--deep-ink); text-decoration:none !important; box-shadow:var(--shadow-sm); overflow:hidden; transition:transform .2s ease, border-color .2s ease, box-shadow .2s ease; }
.sf-doc .sf-related__card::before { content:''; position:absolute; inset:0 0 auto; height:3px; background:linear-gradient(90deg, var(--primary), var(--secondary)); transform:scaleX(0); transform-origin:left; transition:transform .2s ease; }
.sf-doc .sf-related__card:hover { color:var(--deep-ink); border-color:rgba(3,72,96,.38); box-shadow:0 12px 28px rgba(3,72,96,.12); transform:translateY(-3px); }
.sf-doc .sf-related__card:hover::before { transform:scaleX(1); }
.sf-doc .sf-related__icon { display:flex; align-items:center; justify-content:center; width:38px; height:38px; margin-bottom:16px; border-radius:var(--r-lg); background:var(--neutral); color:var(--primary); }
.sf-doc .sf-related__icon svg { width:19px; height:19px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.sf-doc .sf-related__kicker { margin-bottom:5px; font-family:var(--font-mono); font-size:.625rem; font-weight:500; line-height:1.4; letter-spacing:.1em; text-transform:uppercase; color:var(--slate); }
.sf-doc .sf-related__card-title { display:block; margin-bottom:7px; color:var(--deep-ink); font-family:var(--font-sans); font-size:1rem; font-weight:700; line-height:1.25; }
.sf-doc .sf-related__desc { color:var(--slate); font-size:.8125rem; line-height:1.5; }
.sf-doc .sf-related__action { display:flex; align-items:center; gap:6px; margin-top:16px; color:var(--primary); font-family:var(--font-sans); font-size:.75rem; font-weight:700; }
.sf-doc .sf-related__action svg { width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:2; transition:transform .2s ease; }
.sf-doc .sf-related__card:hover .sf-related__action svg { transform:translateX(3px); }
.sf-doc .sf-related__grid--four { grid-template-columns:repeat(2, minmax(0, 1fr)); }
[data-color-mode="dark"] .sf-doc .sf-related { background:linear-gradient(135deg, rgba(0,224,184,.08) 0%, rgba(0,166,200,.045) 100%); border-color:var(--line); }
[data-color-mode="dark"] .sf-doc .sf-related__eyebrow, [data-color-mode="dark"] .sf-doc .sf-related__action { color:var(--secondary); }
[data-color-mode="dark"] .sf-doc .sf-related__card { background:rgba(255,255,255,.045); border-color:var(--line); box-shadow:none; }
[data-color-mode="dark"] .sf-doc .sf-related__card:hover { border-color:rgba(0,224,184,.5); box-shadow:0 12px 28px rgba(0,0,0,.28); }
[data-color-mode="dark"] .sf-doc .sf-related__icon { background:rgba(0,224,184,.1); color:var(--secondary); }
@media (prefers-color-scheme: dark) {
  html:not([data-color-mode="light"]) .sf-doc .sf-related { background:linear-gradient(135deg, rgba(0,224,184,.08) 0%, rgba(0,166,200,.045) 100%); border-color:var(--line); }
  html:not([data-color-mode="light"]) .sf-doc .sf-related__eyebrow, html:not([data-color-mode="light"]) .sf-doc .sf-related__action { color:var(--secondary); }
  html:not([data-color-mode="light"]) .sf-doc .sf-related__card { background:rgba(255,255,255,.045); border-color:var(--line); box-shadow:none; }
  html:not([data-color-mode="light"]) .sf-doc .sf-related__card:hover { border-color:rgba(0,224,184,.5); box-shadow:0 12px 28px rgba(0,0,0,.28); }
  html:not([data-color-mode="light"]) .sf-doc .sf-related__icon { background:rgba(0,224,184,.1); color:var(--secondary); }
}
@media (max-width: 820px) { .sf-doc .sf-related__grid { grid-template-columns:1fr 1fr; } }
@media (max-width: 640px) {
  .sf-doc .sf-related { margin-top:40px; padding:22px 18px; }
  .sf-doc .sf-related__head { grid-template-columns:1fr; gap:10px; }
  .sf-doc .sf-related__grid { grid-template-columns:1fr; }
  .sf-doc .sf-related__card { min-height:0; }
}
/* ══ END CANONICAL TUTORIAL STYLESHEET ══ */
</style>

<div class="sf-doc">

  
  <header class="sf-hero">
    <div class="sf-hero__copy">
      <p class="sf-hero__title">ALPON as a Modbus Master for PLC Networks</p>
      <p class="sf-hero__lead">
        With support for <strong>Modbus TCP</strong> and <strong>RTU</strong>, your
        <strong>ALPON X5 AI</strong> or <strong>ALPON X4</strong> can act as a reliable <strong>master unit</strong>
        for PLC networks — polling data from field devices, writing to their registers, and bridging a local PLC
        network to any platform. This guide covers <strong>Modpoll</strong> for quick tests and
        <strong>Pymodbus</strong> for custom workflows.
      </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">Modbus TCP · RTU</span>
        <span class="sf-pill">Modpoll · Pymodbus</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">Tutorial</span>
    <span class="sf-meta__sep">·</span>
    <span>Modbus</span>
    <span class="sf-meta__sep">·</span>
    <span>PLC</span>
  </div>


  
  <div class="sf-aeo">
    <span class="sf-aeo__label">How do I use ALPON as a Modbus master?</span>
    <p class="sf-aeo__text">
      Connect your <strong>ALPON X5 AI</strong> or <strong>ALPON X4</strong> to the PLC network over Ethernet or
      serial. For a quick test, install <strong>Modpoll</strong> and run a single <code>modpoll -m tcp</code>
      command against the device IP. For production, use the <strong>Pymodbus</strong> Python library to build a
      custom master that reads holding registers and writes values on a schedule. Both approaches speak Modbus TCP
      and RTU, and run identically on ALPON X5 AI and ALPON X4.
    </p>
  </div>


  
  <div class="sf-callout sf-callout--warning">
    <div class="sf-callout__header">
      <svg class="sf-icon" 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>Avoid overlapping subnets</span>
    </div>
    <div class="sf-callout__content">
      <p>Make sure your Modbus devices sit on the same subnet as the ALPON — or can reach it over TCP/IP — and that
      their addresses do not collide with the Sixfab platform's default subnets
      (<code>100.0.0.0/16</code> and <code>10.42.0.0/24</code>). An overlap can make either the Modbus devices or
      the platform services unreachable.</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="#overview"><span class="sf-toc__num">01</span>Overview</a>
    <a class="sf-toc__item" href="#prereqs"><span class="sf-toc__num">02</span>Prerequisites</a>
    <a class="sf-toc__item" href="#modpoll"><span class="sf-toc__num">03</span>Method 1 · Modpoll</a>
    <a class="sf-toc__item" href="#pymodbus"><span class="sf-toc__num">04</span>Method 2 · Pymodbus</a>
    <a class="sf-toc__item" href="#best-practices"><span class="sf-toc__num">05</span>Best practices</a>
    <a class="sf-toc__item" href="#troubleshooting"><span class="sf-toc__num">06</span>Troubleshooting</a>
  </nav>


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

  <p>Acting as a Modbus <strong>master unit</strong>, an <strong>ALPON X5 AI</strong> or <strong>ALPON X4</strong>
  can:</p>
  <ul>
    <li><strong>Poll data</strong> from one or more Modbus-compatible devices such as PLCs, sensors, or energy meters.</li>
    <li><strong>Control actuators</strong> and other devices by writing to their registers.</li>
    <li><strong>Bridge</strong> a local PLC network to any platform.</li>
  </ul>

  <p>The sections below show two approaches: <strong>Modpoll</strong>, a lightweight command-line client for
  testing and polling, and <strong>Pymodbus</strong>, a Python library for building custom master applications.
  The procedure is identical on ALPON X4 and ALPON X5 AI.</p>


  
  <h2 id="prereqs">Prerequisites</h2>

  <div class="sf-spec-card">
    <div class="sf-spec-card__body">
      <div class="sf-spec-row">
        <span class="sf-spec-row__key">Hardware</span>
        <span class="sf-spec-row__val">One or more Modbus-compatible devices (PLCs, sensors, energy meters), connected to the ALPON over Ethernet or serial.</span>
      </div>
      <div class="sf-spec-row">
        <span class="sf-spec-row__key">Operating system</span>
        <span class="sf-spec-row__val">ALPON X5 AI or ALPON X4 running the latest OS. Check for updates via <a href="https://connect.sixfab.com" target="_blank" rel="noopener">ALPON Cloud</a>.</span>
      </div>
      <div class="sf-spec-row">
        <span class="sf-spec-row__key">Tools</span>
        <span class="sf-spec-row__val"><strong>Modpoll</strong> (method 1) or <strong>Pymodbus</strong> (method 2).</span>
      </div>
    </div>
  </div>


  
  <h2 id="modpoll">Method 1 · Modpoll for basic master functionality</h2>

  <p><strong>Modpoll</strong> is a straightforward command-line tool for testing and polling Modbus-compatible
  devices.</p>

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

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">1</div>
        <h3 class="sf-step__title">Install Modpoll</h3>
      </div>
      <div class="sf-step__body">
        <p>Download and extract Modpoll on the ALPON:</p>
        <div class="sf-terminal">
          <div class="sf-terminal__header">
            <span class="sf-terminal__dot sf-terminal__dot--r"></span>
            <span class="sf-terminal__dot sf-terminal__dot--y"></span>
            <span class="sf-terminal__dot sf-terminal__dot--g"></span>
            <span class="sf-terminal__title">bash · install modpoll</span>
          </div>
          <div class="sf-terminal__body">
<pre>wget https://www.modbusdriver.com/downloads/modpoll.tgz
tar xzf modpoll.tgz
cd modpoll/arm-linux-gnueabihf/</pre>
          </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">Run Modpoll</h3>
      </div>
      <div class="sf-step__body">
        <p>Read data from a PLC device:</p>
        <div class="sf-terminal">
          <div class="sf-terminal__header">
            <span class="sf-terminal__dot sf-terminal__dot--r"></span>
            <span class="sf-terminal__dot sf-terminal__dot--y"></span>
            <span class="sf-terminal__dot sf-terminal__dot--g"></span>
            <span class="sf-terminal__title">bash · poll a device</span>
          </div>
          <div class="sf-terminal__body">
<pre>./modpoll -m tcp -a 1 -r 100 -c 10 -t 4:float <span class="t-yel">&lt;DEVICE_IP&gt;</span></pre>
          </div>
        </div>

        <h4>Parameter reference</h4>
        <div class="sf-spec-card">
          <div class="sf-spec-card__body">
            <div class="sf-spec-row">
              <span class="sf-spec-row__key"><code>-m tcp</code></span>
              <span class="sf-spec-row__val">Uses Modbus TCP mode.</span>
            </div>
            <div class="sf-spec-row">
              <span class="sf-spec-row__key"><code>-a 1</code></span>
              <span class="sf-spec-row__val">Sets the slave address to <code>1</code>.</span>
            </div>
            <div class="sf-spec-row">
              <span class="sf-spec-row__key"><code>-r 100</code></span>
              <span class="sf-spec-row__val">Starts reading from register <code>100</code>.</span>
            </div>
            <div class="sf-spec-row">
              <span class="sf-spec-row__key"><code>-c 10</code></span>
              <span class="sf-spec-row__val">Reads <code>10</code> consecutive registers.</span>
            </div>
            <div class="sf-spec-row">
              <span class="sf-spec-row__key"><code>-t 4:float</code></span>
              <span class="sf-spec-row__val">Interprets the data as floating-point values.</span>
            </div>
          </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">Verify communication</h3>
      </div>
      <div class="sf-step__body">
        <p>Confirm that the data returned from the device is accurate and matches the expected values.</p>
      </div>
    </li>

  </ol>


  
  <h2 id="pymodbus">Method 2 · Advanced configuration with Pymodbus</h2>

  <p>For advanced use cases, <strong>Pymodbus</strong> — a Python library — lets you build custom Modbus master
  applications.</p>

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

    <li class="sf-step">
      <div class="sf-step__header">
        <div class="sf-step__num">1</div>
        <h3 class="sf-step__title">Install dependencies</h3>
      </div>
      <div class="sf-step__body">
        <p>Create a virtual environment and install Pymodbus:</p>
        <div class="sf-terminal">
          <div class="sf-terminal__header">
            <span class="sf-terminal__dot sf-terminal__dot--r"></span>
            <span class="sf-terminal__dot sf-terminal__dot--y"></span>
            <span class="sf-terminal__dot sf-terminal__dot--g"></span>
            <span class="sf-terminal__title">bash · virtualenv + pymodbus</span>
          </div>
          <div class="sf-terminal__body">
<pre>python3 -m venv venv
source venv/bin/activate
pip3 install pymodbus</pre>
          </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">Write a master application</h3>
      </div>
      <div class="sf-step__body">
        <p>Save the following as <code>modbus_master.py</code>:</p>
        <div class="sf-terminal">
          <div class="sf-terminal__header">
            <span class="sf-terminal__dot sf-terminal__dot--r"></span>
            <span class="sf-terminal__dot sf-terminal__dot--y"></span>
            <span class="sf-terminal__dot sf-terminal__dot--g"></span>
            <span class="sf-terminal__title">python · modbus_master.py</span>
          </div>
          <div class="sf-terminal__body">
<pre><span class="t-pp">from</span> pymodbus.client.sync <span class="t-pp">import</span> ModbusTcpClient

<span class="t-dim"># Configure Modbus TCP client</span>
client = ModbusTcpClient(<span class="t-yel">'&lt;DEVICE_IP&gt;'</span>, port=<span class="t-blue">502</span>)

<span class="t-dim"># Connect to the device</span>
<span class="t-pp">if</span> client.connect():
    <span class="t-dim"># Read 10 holding registers starting from address 100</span>
    response = client.read_holding_registers(<span class="t-blue">100</span>, <span class="t-blue">10</span>, unit=<span class="t-blue">1</span>)
    <span class="t-pp">if</span> <span class="t-pp">not</span> response.isError():
        <span class="t-pp">print</span>(<span class="t-green">"Data:"</span>, response.registers)
    <span class="t-pp">else</span>:
        <span class="t-pp">print</span>(<span class="t-green">"Error:"</span>, response)

    <span class="t-dim"># Write a value to register 200</span>
    client.write_register(<span class="t-blue">200</span>, <span class="t-blue">42</span>, unit=<span class="t-blue">1</span>)
    <span class="t-pp">print</span>(<span class="t-green">"Value written successfully."</span>)

    client.close()
<span class="t-pp">else</span>:
    <span class="t-pp">print</span>(<span class="t-green">"Connection failed."</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">Run the script</h3>
      </div>
      <div class="sf-step__body">
        <div class="sf-terminal">
          <div class="sf-terminal__header">
            <span class="sf-terminal__dot sf-terminal__dot--r"></span>
            <span class="sf-terminal__dot sf-terminal__dot--y"></span>
            <span class="sf-terminal__dot sf-terminal__dot--g"></span>
            <span class="sf-terminal__title">bash · run</span>
          </div>
          <div class="sf-terminal__body">
<pre>python3 modbus_master.py</pre>
          </div>
        </div>

        <div class="sf-callout sf-callout--info">
          <div class="sf-callout__header">
            <svg class="sf-icon" 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>Why Pymodbus for production</span>
          </div>
          <div class="sf-callout__content">
            <ul>
              <li>Flexible, customizable workflows.</li>
              <li>Supports both Modbus TCP and RTU.</li>
              <li>Easy integration with databases and cloud platforms for advanced analytics.</li>
            </ul>
          </div>
        </div>
      </div>
    </li>

  </ol>


  
  <h2 id="best-practices">Best practices</h2>

  <h3>Network configuration</h3>
  <ul>
    <li>Use a reliable Ethernet connection for Modbus TCP.</li>
    <li>Keep Modbus devices on the same subnet as the ALPON, or reachable over TCP/IP.</li>
    <li>Avoid overlapping the Sixfab default subnets (<code>100.0.0.0/16</code> and <code>10.42.0.0/24</code>) with your Modbus devices.</li>
  </ul>

  <h3>Security</h3>
  <ul>
    <li>Use a firewall to restrict access to critical ports (e.g. <code>502</code> for Modbus TCP).</li>
    <li>Keep the ALPON updated with the latest patches.</li>
  </ul>

  <h3>Containerized deployment</h3>
  <ul>
    <li>Deploy Modbus master applications in isolated containers using the ALPON's container environment.</li>
  </ul>


  <hr>


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

  <details class="sf-issue">
    <summary class="sf-issue__summary">
      <span class="sf-issue__tag">Error</span>
      <span>No response from devices</span>
      <svg class="sf-issue__chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
    </summary>
    <div class="sf-issue__body">
      <h4>Fix</h4>
      <p>Verify the IP address, port, and slave ID, and check the cable connections between the ALPON and the
      Modbus device.</p>
    </div>
  </details>

  <details class="sf-issue">
    <summary class="sf-issue__summary">
      <span class="sf-issue__tag">Error</span>
      <span>Data mismatch</span>
      <svg class="sf-issue__chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
    </summary>
    <div class="sf-issue__body">
      <h4>Fix</h4>
      <p>Ensure the register type and starting address match the device's register map.</p>
    </div>
  </details>

  <details class="sf-issue">
    <summary class="sf-issue__summary">
      <span class="sf-issue__tag sf-issue__tag--sw">Debug</span>
      <span>Inspecting logs for error analysis</span>
      <svg class="sf-issue__chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
    </summary>
    <div class="sf-issue__body">
      <h4>Fix</h4>
      <p>Follow the system log in real time to watch for connection and protocol errors:</p>
      <div class="sf-terminal">
        <div class="sf-terminal__header">
          <span class="sf-terminal__dot sf-terminal__dot--r"></span>
          <span class="sf-terminal__dot sf-terminal__dot--y"></span>
          <span class="sf-terminal__dot sf-terminal__dot--g"></span>
          <span class="sf-terminal__title">bash · follow logs</span>
        </div>
        <div class="sf-terminal__body">
<pre>tail -f /var/log/syslog</pre>
        </div>
      </div>
    </div>
  </details>


</div>
`}</HTMLBlock>

<HTMLBlock>{`
<div class="sf-doc">
  <section class="sf-related" aria-labelledby="related-guides-heading">
    <div class="sf-related__head">
      <div>
        <span class="sf-related__eyebrow">Continue exploring</span>
        <h2 class="sf-related__title" id="related-guides-heading">Related guides</h2>
      </div>
      <p class="sf-related__intro">Build on this workflow with deployment, fleet-management, and hardware guidance for the ALPON platform.</p>
    </div>
    <div class="sf-related__grid">
      <a class="sf-related__card" href="/docs/alpon-deploy-applications">
        <span class="sf-related__icon" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M12 3v12"/><path d="m7 10 5 5 5-5"/><path d="M5 21h14"/></svg></span>
        <span class="sf-related__kicker">Workflow</span>
        <strong class="sf-related__card-title">Deploy Applications on ALPON</strong>
        <span class="sf-related__desc">Push an ARM64 image, configure its runtime, and launch it from ALPON Cloud.</span>
        <span class="sf-related__action">Open guide <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14"/><path d="m13 6 6 6-6 6"/></svg></span>
      </a>
      <a class="sf-related__card" href="/docs/alpon-cloud">
        <span class="sf-related__icon" aria-hidden="true"><svg viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 9h18"/><path d="M8 14h3"/></svg></span>
        <span class="sf-related__kicker">Platform</span>
        <strong class="sf-related__card-title">ALPON Cloud</strong>
        <span class="sf-related__desc">Manage devices, applications, connectivity, and remote operations from one workspace.</span>
        <span class="sf-related__action">Open guide <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14"/><path d="m13 6 6 6-6 6"/></svg></span>
      </a>
      <a class="sf-related__card" href="/docs/alpon-device-comparison">
        <span class="sf-related__icon" aria-hidden="true"><svg viewBox="0 0 24 24"><rect x="5" y="3" width="14" height="18" rx="2"/><path d="M9 7h6M9 11h6M9 15h3"/></svg></span>
        <span class="sf-related__kicker">Hardware</span>
        <strong class="sf-related__card-title">Compare ALPON devices</strong>
        <span class="sf-related__desc">Compare ALPON X4 and ALPON X5 AI capabilities for your edge workload.</span>
        <span class="sf-related__action">Open guide <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14"/><path d="m13 6 6 6-6 6"/></svg></span>
      </a>
    </div>
  </section>
</div>
`}</HTMLBlock>