 tag right here instead of the main style.css
             so everything for this section stays together and is easy to find -->
        <style>

            /* the outer wrapper for this whole section — margin pushes it away from the
               content above and below, and the border-top adds a subtle divider line.
               the last two digits of the color (#9940FF22) are the opacity in hex — 22 is very faint */
            .pipeline-section {
                margin: 40px 0;
                border-top: 1px solid #9940FF22;
                padding-top: 36px;
            }
            .pipeline-label {
                font-size: 0.7em;
                font-family: monospace;
                letter-spacing: 2px;
                text-transform: uppercase;
                color: #9940FF;
                margin-bottom: 6px;
            }

            .pipeline-title {
                font-size: 1.3em;
                font-weight: 600;
                color: #C8A79C;
                margin-bottom: 28px;
            }

            /* this is the horizontal container that holds all 5 cards + the arrows between them.
               display: flex puts everything in a row by default.
               overflow-x: auto is what makes it scroll sideways instead of overflowing
               off the edge of the screen when the window is narrow */
            .pipe-row {
                display: flex;
                align-items: stretch; /* makes all cards the same height even if content differs */
                gap: 0;
                overflow-x: auto;
                padding-bottom: 12px; /* room so the scrollbar doesn't sit right on the cards */
                scrollbar-width: thin;
                scrollbar-color: #9940FF33 transparent;
            }

            /* custom scrollbar styling — only works in Chrome/Edge (webkit).
               Firefox uses the scrollbar-width/color above instead */
            .pipe-row::-webkit-scrollbar { height: 3px; }
            .pipe-row::-webkit-scrollbar-track { background: transparent; }
            .pipe-row::-webkit-scrollbar-thumb { background: #9940FF33; border-radius: 2px; }

            /* each individual stage card.
               flex: 1 0 160px means: can grow to fill space, won't shrink below 160px.
               position: relative is needed so the stage number (which uses position: absolute)
               knows what to position itself relative to */
            .p-stage {
                flex: 1 0 160px;
                background: #4C066C;
                border: 1px solid #9940FF33;
                border-radius: 8px;
                padding: 1.4rem 1rem;
                display: flex;
                flex-direction: column; /* stacks number, name, visual, and description vertically */
                align-items: center;
                gap: 0.85rem;
                position: relative;
                transition: border-color .3s, box-shadow .3s; /* smooth hover effect */
                cursor: default; /* keeps the cursor as an arrow, not a text cursor */
            }

            /* hover state — purple glow appears around the card.
               inset on box-shadow means the glow is inside the card, not outside */
            .p-stage:hover {
                border-color: #9940FF;
                box-shadow: 0 0 20px rgba(153,64,255,.15), inset 0 0 24px rgba(153,64,255,.07);
            }

            /* the "01", "02" etc. numbers — position: absolute pulls them out of the
               normal flow and pins them to the top-left corner of the card.
               this only works because the card has position: relative */
            .p-stage-num {
                position: absolute;
                top: .55rem; left: .7rem;
                font-family: monospace;
                font-size: .6em;
                color: #9940FF55; /* very faint purple */
                letter-spacing: .08em;
            }

            .p-stage-name {
                font-family: monospace;
                font-size: .62em;
                letter-spacing: .12em;
                text-transform: uppercase;
                color: #9940FF;
                text-align: center;
            }

            /* the box that holds each animated visual.
               overflow: hidden clips anything that goes outside the box (like the scan beam) */
            .p-visual {
                width: 100%;
                height: 86px;
                display: flex;
                align-items: center;
                justify-content: center;
                position: relative;
                overflow: hidden;
            }

            .p-desc {
                font-size: .72em;
                color: #C8A79C88; /* 88 at the end makes it semi-transparent */
                text-align: center;
                line-height: 1.5;
            }

            /* the connector between stages — it's just a thin horizontal div.
               the actual line and arrowhead are drawn using ::before and ::after
               which are "pseudo-elements" — CSS creates them without any HTML */
            .p-arrow {
                flex: 0 0 26px; /* fixed 26px wide, doesn't grow or shrink */
                display: flex;
                align-items: center;
                justify-content: center;
                position: relative;
                align-self: center;
                height: 2px;
                margin-bottom: 1rem; /* visually centers it with the cards */
            }

            /* ::before draws the line part of the arrow —
               content: '' is required even though it's empty, otherwise the pseudo-element doesn't show */
            .p-arrow::before {
                content: '';
                display: block;
                width: 100%;
                height: 2px;
                background: linear-gradient(90deg, #9940FF66, #9940FF); /* fades from dim to bright */
            }

            /* ::after draws the arrowhead using the "CSS triangle trick" —
               a box with zero width/height and borders on 3 sides creates a triangle shape.
               the left border is solid purple, top and bottom are transparent, which makes it point right */
            .p-arrow::after {
                content: '';
                position: absolute;
                right: -1px;
                width: 0; height: 0;
                border-top: 5px solid transparent;
                border-bottom: 5px solid transparent;
                border-left: 7px solid #9940FF;
                filter: drop-shadow(0 0 4px #9940FF); /* glow effect on the arrowhead */
            }

            /* the glowing dot that slides along the arrow to show "flow".
               it's a real div element (not a pseudo-element) placed inside .p-arrow in the HTML.
               animation moves it from left: 0 to left: 100% while fading out */
            .p-arrow-dot {
                position: absolute;
                width: 6px; height: 6px;
                top: -2px; /* centers it vertically on the 2px line */
                border-radius: 50%; /* makes it a circle */
                background: #9940FF;
                box-shadow: 0 0 8px #9940FF; /* glow */
                animation: pFlowDot 1.8s linear infinite;
                left: 0;
            }

            /* @keyframes defines the animation — "from" is the start, "to" is the end.
               calc(100% - 6px) stops it just before the edge so it doesn't go past the arrow */
            @keyframes pFlowDot {
                from { left: 0; opacity: 1; }
                to   { left: calc(100% - 6px); opacity: .2; }
            }


            /* ============================
               STAGE 1: IMAGE INGESTION
               ============================ */

            /* the container for the animated frame visual — position: relative so
               the children can use position: absolute to stack on top of each other */
            .pv-ingest {
                position: relative;
                width: 70px; height: 70px;
            }

            /* outer frame border that slowly pulses between faint and bright purple */
            .pv-ingest .fi-outer {
                position: absolute; inset: 0; /* inset: 0 is shorthand for top/right/bottom/left: 0 — fills the parent */
                border: 2px solid #9940FF55;
                border-radius: 3px;
                animation: pFramePulse 2.5s ease-in-out infinite;
            }

            /* inner frame — slightly smaller, always slightly visible */
            .pv-ingest .fi-inner {
                position: absolute; inset: 10px; /* 10px inset on all sides = smaller box */
                border: 1px solid #9940FF;
                border-radius: 2px;
                background: rgba(153,64,255,.08); /* rgba lets me set opacity per-color */
                opacity: .7;
            }

            /* the horizontal scan line that sweeps downward — starts near the top
               and moves to the bottom via the pScanV animation */
            .pv-ingest .fi-scan {
                position: absolute;
                left: 0; right: 0; /* stretches full width */
                height: 2px;
                background: linear-gradient(90deg, transparent, #9940FF, transparent); /* fades in and out sideways */
                animation: pScanV 2.2s ease-in-out infinite;
                box-shadow: 0 0 8px rgba(153,64,255,.5);
            }

            /* corner brackets — these 4 divs each show only 2 sides of a border,
               which makes them look like the corners of a targeting reticle.
               the border-width shorthand is: top right bottom left */
            .pv-ingest .fi-corner {
                position: absolute;
                width: 8px; height: 8px;
                border-color: #9940FF;
                border-style: solid;
            }
            .pv-ingest .fi-corner.tl { top:0; left:0; border-width:2px 0 0 2px; } /* top + left only */
            .pv-ingest .fi-corner.tr { top:0; right:0; border-width:2px 2px 0 0; } /* top + right only */
            .pv-ingest .fi-corner.bl { bottom:0; left:0; border-width:0 0 2px 2px; } /* bottom + left only */
            .pv-ingest .fi-corner.br { bottom:0; right:0; border-width:0 2px 2px 0; } /* bottom + right only */

            /* pulses the outer frame border between dim and full purple */
            @keyframes pFramePulse {
                0%,100% { border-color: #9940FF33; }
                50%      { border-color: #9940FF; box-shadow: 0 0 12px rgba(153,64,255,.2); }
            }

            /* moves the scan line from top to bottom */
            @keyframes pScanV {
                0%   { top: 5px;  opacity: .8; }
                100% { top: 65px; opacity: .1; }
            }


            /* ============================
               STAGE 2: REGION CROP
               ============================ */

            .pv-crop {
                position: relative;
                width: 70px; height: 70px;
            }

            /* the full image background — faint outline representing the whole image */
            .pv-crop .cr-full {
                position: absolute; inset: 0;
                border: 1px solid #9940FF33;
                border-radius: 2px;
                opacity: .5;
            }

            /* dark gradient overlay that dims the corners, drawing attention to the center ROI */
            .pv-crop .cr-overlay {
                position: absolute; inset: 0;
                background: linear-gradient(135deg, rgba(49,0,60,.5) 0%, transparent 50%, rgba(49,0,60,.5) 100%);
                border-radius: 2px;
            }

            /* the region-of-interest selection box — positioned in the middle of the image.
               uses percentage-based positioning so it scales with the parent */
            .pv-crop .cr-roi {
                position: absolute;
                top: 28%; left: 34%;
                width: 40%; height: 32%;
                border: 2px solid #C8A79C; /* mauve color to distinguish from the purple elements */
                box-shadow: 0 0 10px rgba(200,167,156,.15), inset 0 0 8px rgba(200,167,156,.1);
                animation: pRoiPulse 2s ease-in-out infinite;
            }

            /* the tiny dot handles at two corners of the selection box */
            .pv-crop .cr-handle {
                position: absolute;
                width: 4px; height: 4px;
                background: #C8A79C;
                border-radius: 50%;
            }
            .pv-crop .cr-handle.tl { top:-2px; left:-2px; }
            .pv-crop .cr-handle.br { bottom:-2px; right:-2px; }

            /* pulses the glow on the ROI box — going brighter at 50% then back */
            @keyframes pRoiPulse {
                0%,100% { box-shadow: 0 0 10px rgba(200,167,156,.15), inset 0 0 8px rgba(200,167,156,.1); }
                50%      { box-shadow: 0 0 18px rgba(200,167,156,.35), inset 0 0 12px rgba(200,167,156,.2); }
            }


            /* ============================
               STAGE 3: ROTATION SCAN
               ============================ */

            /* uses flexbox to center the spinning rectangle inside the orbit ring */
            .pv-rotate {
                position: relative;
                width: 80px; height: 80px;
                display: flex; align-items: center; justify-content: center;
            }

            /* the dashed circle that represents the rotation orbit.
               border-radius: 50% turns a square div into a circle.
               the ::after pseudo-element adds a dot that sits on the orbit and spins with it */
            .pv-rotate .ro-orbit {
                position: absolute; inset: 0;
                border: 1px dashed #9940FF44;
                border-radius: 50%;
                animation: pOrbitSpin 6s linear infinite; /* slow spin */
            }
            .pv-rotate .ro-orbit::after {
                content: '';
                position: absolute;
                top: -3px; left: 50%;
                transform: translateX(-50%); /* centers the dot horizontally on the orbit */
                width: 6px; height: 6px;
                background: #9940FF;
                border-radius: 50%;
                box-shadow: 0 0 8px #9940FF;
            }

            /* the rectangle that spins faster to represent the image being rotated */
            .pv-rotate .ro-rect {
                width: 38px; height: 28px;
                border: 2px solid #9940FF;
                background: rgba(153,64,255,.1);
                box-shadow: 0 0 12px rgba(153,64,255,.15);
                animation: pRectSpin 4s linear infinite; /* spins independently of the orbit */
            }

            /* the "360°" label underneath — white-space: nowrap stops it from line-breaking */
            .pv-rotate .ro-deg {
                position: absolute;
                bottom: -2px;
                font-family: monospace;
                font-size: .55em;
                color: #9940FF;
                letter-spacing: .06em;
                white-space: nowrap;
            }

            @keyframes pOrbitSpin {
                from { transform: rotate(0deg); }
                to   { transform: rotate(360deg); }
            }
            @keyframes pRectSpin {
                from { transform: rotate(0deg); }
                to   { transform: rotate(360deg); }
            }


            /* ============================
               STAGE 4: OCR EXTRACTION
               ============================ */

            /* the box that contains the text bar visuals and the scan beam overlay.
               overflow: hidden is important here — it clips the beam so it doesn't
               go outside the box when it reaches the bottom */
            .pv-ocr {
                position: relative;
                width: 70px; height: 70px;
                background: rgba(0,0,0,.2);
                border: 1px solid #9940FF22;
                border-radius: 3px;
                padding: 8px 6px;
                overflow: hidden;
                display: flex;
                flex-direction: column;
                gap: 5px;
            }

            /* these bars represent lines of text being read — each one is a different
               width to look like words of different lengths */
            .pv-ocr .oc-bar {
                height: 7px;
                border-radius: 2px;
                background: #9940FF44;
                opacity: .6;
            }
            /* nth-child lets me style each bar individually without adding extra classes */
            .pv-ocr .oc-bar:nth-child(1) { width: 85%; }
            .pv-ocr .oc-bar:nth-child(2) { width: 65%; }
            .pv-ocr .oc-bar:nth-child(3) { width: 75%; }
            .pv-ocr .oc-bar:nth-child(4) { width: 50%; }
            .pv-ocr .oc-bar:nth-child(5) { width: 80%; }

            /* the scan beam — same concept as the scan line in stage 1 but this one
               fades side-to-side AND moves top-to-bottom at the same time */
            .pv-ocr .oc-beam {
                position: absolute;
                left: 0; right: 0;
                height: 2px;
                background: linear-gradient(90deg, transparent 5%, #9940FF 50%, transparent 95%);
                box-shadow: 0 0 10px rgba(153,64,255,.4);
                animation: pOcrScan 2s ease-in-out infinite;
            }

            /* a highlight that briefly flashes on a text bar to show a "detection" event */
            .pv-ocr .oc-flash {
                position: absolute;
                height: 7px;
                background: rgba(153,64,255,.25);
                border-radius: 2px;
                animation: pDetectFlash 2s ease-in-out infinite;
            }

            /* beam sweeps down, fading out as it reaches the bottom */
            @keyframes pOcrScan {
                0%   { top: 8px;  opacity: .9; }
                100% { top: 62px; opacity: .2; }
            }

            /* the flash is hidden most of the time (opacity 0), then briefly visible
               between 55% and 65% of the animation cycle */
            @keyframes pDetectFlash {
                0%,100% { opacity: 0; }
                55%,65% { opacity: 1; }
            }


            /* ============================
               STAGE 5: VALIDATION
               ============================ */

            .pv-valid {
                width: 100%;
                display: flex;
                flex-direction: column;
                gap: 4px;
            }

            /* each check row starts nearly invisible (opacity: .15) and fades to fully visible.
               "forwards" means the animation stays at the end state instead of resetting */
            .pv-check-row {
                display: flex;
                align-items: center;
                gap: 5px;
                opacity: .15;
                animation: pCheckOn .4s ease forwards;
            }

            /* each row has a different animation-delay so they light up one after another
               instead of all at once — this creates the "sequential check" effect */
            .pv-check-row:nth-child(1) { animation-delay: .3s; }
            .pv-check-row:nth-child(2) { animation-delay: .7s; }
            .pv-check-row:nth-child(3) { animation-delay: 1.1s; }
            .pv-check-row:nth-child(4) { animation-delay: 1.5s; }
            .pv-check-row:nth-child(5) { animation-delay: 1.9s; }
            .pv-check-row:nth-child(6) { animation-delay: 2.3s; }

            /* just changes opacity from whatever it started at to 1 (fully visible) */
            @keyframes pCheckOn {
                to { opacity: 1; }
            }

            /* the circular checkmark icon next to each row */
            .pv-check-icon {
                width: 12px; height: 12px;
                border-radius: 50%;
                border: 1.5px solid #9adc84; /* green color for "pass" */
                display: flex; align-items: center; justify-content: center;
                flex-shrink: 0; /* stops it from shrinking if the row gets narrow */
                font-size: .45em;
                color: #9adc84;
            }

            /* the line next to each checkmark — flex: 1 makes it fill all remaining space */
            .pv-check-line {
                height: 3px;
                flex: 1;
                border-radius: 2px;
                background: #9940FF33;
            }


            /* ============================
               RESPONSIVE — SMALL SCREENS
               ============================
               @media queries let you override styles when the screen is a certain size.
               everything inside this block only applies when the window is 580px wide or less */
            @media (max-width: 580px) {

                /* switch from horizontal row to vertical column */
                .pipe-row {
                    flex-direction: column;
                    overflow-x: visible; /* no longer need horizontal scroll */
                    align-items: stretch;
                }

                /* each card goes horizontal (number + visual + text side by side)
                   instead of vertical stacking, so it's more compact on a phone */
                .p-stage {
                    flex-direction: row;
                    align-items: flex-start;
                    gap: 14px;
                    padding: 1rem;
                }

                /* on mobile the number can't be absolutely positioned in the corner anymore
                   since the layout changed — position: static puts it back in normal flow */
                .p-stage-num { position: static; font-size: .65em; padding-top: 2px; min-width: 20px; }
                .p-visual { height: 58px; width: 66px; flex-shrink: 0; }
                .p-stage-name { text-align: left; }
                .p-desc { text-align: left; }

                /* the arrow becomes vertical — same div but we give it a fixed height
                   and swap the ::before and ::after styles to point downward instead of right */
                .p-arrow {
                    width: 2px;
                    height: 20px;
                    align-self: center;
                    margin: 0;
                    flex: 0 0 20px;
                }
                .p-arrow::before {
                    width: 2px;
                    height: 100%;
                    background: linear-gradient(180deg, #9940FF66, #9940FF); /* gradient goes top to bottom now */
                }
                .p-arrow::after {
                    right: auto;
                    bottom: -1px;
                    top: auto;
                    /* triangle now points down — top border is solid, left/right are transparent */
                    border-left: 5px solid transparent;
                    border-right: 5px solid transparent;
                    border-top: 7px solid #9940FF;
                    border-bottom: none;
                }

                /* re-animate the flow dot to move vertically instead of horizontally */
                .p-arrow-dot {
                    left: -2px;
                    top: 0;
                    animation: pFlowDotV 1.8s linear infinite;
                }
                @keyframes pFlowDotV {
                    from { top: 0; opacity: 1; }
                    to   { top: calc(100% - 6px); opacity: .2; }
                }
            }
        