
    .sc-placeholder{background:color-mix(in srgb,currentColor 8%,transparent);
      border:1px solid color-mix(in srgb,currentColor 50%,transparent);
      border-radius:2px;box-sizing:border-box;overflow:hidden}
    @keyframes sc-shine{0%{background-position:100% 50%}100%{background-position:0% 50%}}
    html.sc-dc-streaming .sc-placeholder,
    html.sc-dc-streaming .sc-interp.sc-missing{position:relative;
      background:color-mix(in srgb,currentColor 5%,transparent);
      border-color:transparent}
    html.sc-dc-streaming .sc-placeholder::before,
    html.sc-dc-streaming .sc-interp.sc-missing::before{content:'';
      position:absolute;inset:0;pointer-events:none;
      background:linear-gradient(90deg,rgba(217,119,87,0) 25%,rgba(247,225,211,.95) 37%,rgba(217,119,87,0) 63%);
      background-size:400% 100%;animation:sc-shine 1.4s ease infinite}
    html.sc-dc-streaming .sc-placeholder:nth-child(n+9 of .sc-placeholder)::before,
    html.sc-dc-streaming .sc-interp.sc-missing:nth-child(n+9 of .sc-interp.sc-missing)::before{animation:none;
      background:color-mix(in srgb,currentColor 8%,transparent)}
    .sc-placeholder-error{padding:4px 8px;font:11px/1.4 ui-monospace,monospace;
      color:color-mix(in srgb,currentColor 70%,transparent);word-break:break-word}
    .sc-interp.sc-missing{display:inline-block;width:2em;height:1em;overflow:hidden;
      vertical-align:text-bottom;background:rgba(255,255,255,.3);border:1px solid rgba(0,0,0,.5);
      border-radius:2px;box-sizing:border-box;color:transparent;
      user-select:none}
    .sc-interp.sc-unresolved{font-family:ui-monospace,monospace;font-size:.85em;
      color:color-mix(in srgb,currentColor 50%,transparent);
      background:color-mix(in srgb,currentColor 10%,transparent);border-radius:3px;
      padding:0 3px}
    .sc-host.sc-has-error{position:relative}
    .sc-logic-error{position:absolute;top:8px;left:8px;z-index:2147483647;max-width:60ch;
      padding:6px 10px;background:#b00020;color:#fff;font:12px/1.4 ui-monospace,monospace;
      border-radius:4px;white-space:pre-wrap;pointer-events:none}
    /* Mirrors PRINT_BASELINE_CSS in apps/web deck-stage-export.ts — keep both
       in sync until dc-runtime regains a build step. */
    @media print {
      @page { margin: 0.5cm; }
      figure, table { break-inside: avoid; }
      #dc-root, #dc-root > .sc-host { height: auto; }
      *, *::before, *::after {
        print-color-adjust: exact; -webkit-print-color-adjust: exact;
        backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
        animation-delay: -99s !important; animation-duration: .001s !important;
        animation-iteration-count: 1 !important; animation-fill-mode: both !important;
        animation-play-state: running !important; transition-duration: 0s !important;
      }
    }
  
x-dc{display:none!important}
.fx{display:flex}.col{display:flex;flex-direction:column}.grid{display:grid}.ac{align-items:center}.jc{justify-content:center}.jb{justify-content:space-between}.f1{flex:1}.noshrink{flex-shrink:0}.wrap{flex-wrap:wrap}.fw5{font-weight:500}.fw6{font-weight:600}.fw7{font-weight:700}.fw8{font-weight:800}.fs11{font-size:11px}.fs12{font-size:12px}.fs13{font-size:13px}.fs14{font-size:14px}.fs15{font-size:15px}.fs16{font-size:16px}.fs20{font-size:20px}.fs22{font-size:22px}.upper{text-transform:uppercase}.tc{text-align:center}.nowrap{white-space:nowrap}.gap8{gap:8px}.gap10{gap:10px}.gap12{gap:12px}.gap16{gap:16px}.gap24{gap:24px}.m0{margin:0}.mt8{margin-top:8px}.mt12{margin-top:12px}.mt16{margin-top:16px}.mb8{margin-bottom:8px}.mb12{margin-bottom:12px}.mb16{margin-bottom:16px}.posrel{position:relative}.posabs{position:absolute}.round{border-radius:50%}.ohide{overflow:hidden}.bbox{box-sizing:border-box}.pointer{cursor:pointer}.w100{width:100%}.b0{border:none}
html,body{height:100%;margin:0}#dc-root,#dc-root>.sc-host{height:100%}

          /* Dragon Black Roll-Up page. Eight sections, ordered as a cold-traffic
             argument rather than by section type:

               hero          product + offer, with the rating and one review in it
               testimonial   real attributed reviews - proof SECOND, see below
               audience      nine situations - lets the visitor find themselves
               comparison    against the category default, not a named brand
               educational   mechanism, plain English
               how-to        what using it actually costs you, in order
               ingredients   the amounts, off the Drug Facts panel
               guarantee     the last objection, so it goes last

             PROOF MOVED FROM EIGHTH TO SECOND (Adam, 2026-09-04). It used to
             sit after the mechanism, on the reasoning that a review is believed
             more once the reader understands what the product does. That holds
             for problem-aware traffic. It is the wrong shape for the
             solution-aware ads now pointing here: that visitor has already
             accepted that a topical is the answer and is choosing between
             brands, so the question they arrive with is "does this one work for
             people like me", and it should be answered immediately after the
             offer rather than six sections later.

             SecUgc IS GONE, not reordered. "Where people actually use it" held
             the slot proof now occupies and was cut rather than pushed down: a
             lifestyle carousel and a review carousel in one page do the same
             job twice, and only the reviews carry names. SecUgc.dc.html stays
             on disk unimported, like SecLadder - nothing reads it, and it is
             there if the decision reverses.

             THE UGC PHOTOGRAPHY IS STILL IN USE. SecGuarantee runs the same
             four `ugc/` scenes as its top strip and its two support tiles, so
             the images regenerated 2026-09-04 at correct product scale are
             still on the page. Deleting them from Brand HQ storage would break
             the guarantee section, not just this removed one.

             WHY AUDIENCE SITS THIRD. A pain buyer self-selects harder than
             almost any other, and they do it early. Nine situations placed
             before the argument lets them find their own and read the rest as
             being about them; the same grid placed late is a summary of points
             already made.

             WHY HOW-TO FOLLOWS EDUCATIONAL. Mechanism first (what it does),
             then routine (what you do). Reversed, the steps arrive before the
             reader knows why any of it matters.

             WHY INGREDIENTS SITS SEVENTH, NOT SECOND. It is the last factual
             objection before the guarantee - a reader who is still deciding
             does not open an ingredient accordion, and a reader who is nearly
             decided does. Placing it early spends a high-intent section on
             low-intent traffic. (This used to read "the last objection before
             proof". Proof is second now, so the sentence names the guarantee
             instead; the placement reasoning is unchanged.)

             NO RANGE / LADDER / CROSS-SELL SECTION ON THIS PAGE, EVER.
             A cross-sell was built here once and removed. This page takes cold
             paid traffic for ONE product. The visitor does not know Dragon
             sells four strengths, so a section explaining why Extra rather than
             the others answers a question they never asked and plants a doubt
             that did not exist. Even with the outbound links stripped it still
             introduces three alternatives to someone who arrived to buy one
             thing. A range belongs on a homepage or a category page.

             The same reasoning removed a comparison ROW in SecCompare that read
             "Four strengths, so you can move up". The rule is about the idea,
             not about the section that first carried it. SecIngredients names
             the Gold tier ONCE, in the hemp row, because broad spectrum versus
             full spectrum is a factual difference a label-reader will check -
             that is disclosure, not a ladder.

             NOT ON THE PAGE: offer-stack-value-itemization-subscribe-86 fails
             its own capability gate - it requires `real-item-prices:5` and
             Dragon's offer has two honest line items (2 x $41.99 = $83.98 ->
             $58.78). guarantee-badge-support-cards-33 took its place.

             COMPLIANCE: SecAudience's nine tile labels are written to sit
             inside Dragon's approved indication and have NOT been signed off by
             Michelle. Flag on handover.

             Each section is one child file built from its own SPEC.md, so a
             section can be swapped without touching the others. Every section
             owns its vertical padding and responsive behaviour, so the parent
             adds no gaps - gaps set here would fight the sheets. */
          *{box-sizing:border-box}
          html,body{margin:0;padding:0;background:#fff}

          /* NO `overflow-x: hidden` HERE. It was the reflex guard against
             sideways scroll, and it cost the desktop hero its sticky gallery:
             any value other than `visible` makes this element a scroll
             container, and a scroll container silently disables
             `position: sticky` in EVERY descendant. Nothing errors, nothing
             logs - the sticky element simply behaves as `static`.

             It was also unnecessary. Both breakpoints measure
             sc-camel-scroll-width === innerWidth, so there is no overflow to hide; the
             guard was suppressing a problem that does not exist while breaking
             one that does. If a real overflow ever appears, fix the element
             that overflows - clipping the whole page hides the cause and takes
             sticky positioning down with it. See MOBILE-CONTAINER-WIDTH.md. */
          .pg{width:100%;background:#ffffff}
          .pgSec{width:100%}
        

          /* SECTION: testimonial-review-carousel-with-rating-header-19
             Source: Mobile - Piezano LP, Figma RfYupbCnvazkXAMgoRvQPV node 1:18493

             GOLD IS #d1b66c - Dragon's real brass, measured on their live site.
             It was #f5a623, which appears NOWHERE on dragonpainrelief.com.
             Gold TEXT on a light ground uses #8e7940, because #d1b66c on white
             is 1.98:1 and unreadable. Stars are a filled shape, not type, so
             they take the brass directly - their own site runs #e1bd66 there.

             REBUILT to the source COMPOSITION. The first build read the slot
             schema and the measured tables and never opened preview.png, so it
             shipped a centred header over two plain white text cards - a
             different section that happened to use the same slots. What the
             template actually is:

               - header LEFT aligned: star row, then "4.9 / 5.0 based on
                 66 Reviews" with the count UNDERLINED, then a large left
                 headline, then a subhead paragraph
               - each card is a HORIZONTAL SPLIT inside one rounded card:
                 copy column on the left, a tall image filling the right half
                 edge to edge, clipped by the card
               - copy column: star row + numeric rating, bold title, the quote
                 in quote marks, then avatar + name in the ACCENT colour with a
                 credential line beneath
               - footer: two CIRCULAR arrow buttons and a progress bar

             DEVIATION - the source's right half is the reviewer's own photo.
             Dragon has no customer photography, and putting an AI lifestyle
             frame inside a card attributed to a real named person asserts that
             she took it. The right half carries the product instead. Restores
             the moment Michelle's UGC folder is audited.
             DEVIATION - avatar is an initial monogram, same reason. */
          .t,.t *{box-sizing:border-box}
          .t{width:100%;background:#ffffff;padding:56px 0;
             font-family:Lato,-apple-system,'Helvetica Neue',Helvetica,sans-serif;
             font-weight:500;color:#1a1a1a;-webkit-font-smoothing:antialiased}
          .t p{margin:0}
          /* max-width, NOT width - see MOBILE-CONTAINER-WIDTH.md */
          .tin{width:100%;max-width:392px;margin:0 auto;padding:0 16px}

          /* LEFT aligned, not centred */
          .thead{margin-bottom:24px}
          .taggRow{display:flex;align-items:center;gap:8px}
          .tstars{display:flex;gap:2px}
          .tstars svg{width:16px;height:16px;color:#d1b66c}
          .t .tagg{font-size:15px;font-weight:900;letter-spacing:-0.15px}
          .t .tagg span{font-weight:500;color:#6b6b6b}
          .t .tagg u{text-decoration:underline;text-underline-offset:2px;font-weight:700;color:#1a1a1a}
          .t .th{margin-top:14px;font-size:30px;font-weight:900;line-height:1.12;letter-spacing:-0.4px}
          .t .tsub{margin-top:12px;font-size:15px;line-height:1.5;color:#6b6b6b;font-weight:500}

          .trow{display:flex;gap:16px;align-items:stretch;
                margin:0 -16px;padding:0 16px;
                overflow-x:auto;scroll-snap-type:x mandatory;
                -webkit-overflow-scrolling:touch;scrollbar-width:none}
          .trow::-webkit-scrollbar{display:none}

          /* the card IS the split - copy left, image right, one rounded box */
          .tcard{width:330px;flex:0 0 auto;scroll-snap-align:start;
                 background:#f7f7f5;border-radius:8px;box-shadow:inset 0 0 0 1px #e4e2dc;
                 overflow:hidden;display:flex;align-items:stretch}
          .tcopy{flex:1 1 auto;min-width:0;padding:18px;display:flex;flex-direction:column}
          .tshot{width:96px;flex:0 0 auto;background:#ffffff;overflow:hidden;
                 display:flex;align-items:center;justify-content:center}
          .tshot img{max-width:78%;max-height:70%;object-fit:contain;display:block;
                     mix-blend-mode:multiply}

          .tcardTop{display:flex;align-items:center;gap:8px}
          .tcardTop .tstars svg{width:13px;height:13px}
          .t .tnum{font-size:14px;font-weight:900}
          .t .ttitle{margin-top:12px;font-size:16px;font-weight:900;line-height:1.25;letter-spacing:-0.16px}
          .t .tbody{margin-top:10px;font-size:14px;line-height:1.5;color:#1a1a1a;
                    font-weight:500;flex:1 1 auto}
          .twho{margin-top:18px;display:flex;align-items:center;gap:10px}
          .tmono{width:34px;height:34px;border-radius:50%;flex:0 0 auto;background:#f9f6ed;
                 box-shadow:inset 0 0 0 1px #eadebd;color:#8e7940;
                 display:flex;align-items:center;justify-content:center;
                 font-size:13px;font-weight:900}
          /* name in the accent, as the source does - deep gold, because this is
             type on a light card */
          .t .tname{font-size:14px;font-weight:900;line-height:1.2;color:#8e7940}
          .t .tmeta{font-size:12px;color:#6b6b6b;font-weight:500;line-height:1.2;margin-top:2px}

          /* circular arrows + progress bar, not plain dashes */
          .tfoot{margin-top:24px;display:flex;align-items:center;gap:14px}
          .tarrow{width:38px;height:38px;border-radius:50%;flex:0 0 auto;background:#ffffff;
                  box-shadow:0 1px 5px rgba(0,0,0,0.14);border:0;padding:0;cursor:pointer;
                  display:flex;align-items:center;justify-content:center}
          .tarrow svg{width:15px;height:15px;color:#1a1a1a}
          .ttrack{flex:1 1 auto;height:3px;background:#e4e2dc;position:relative;overflow:hidden}
          .ttrack i{position:absolute;left:0;top:0;height:100%;width:50%;background:#a51b17;
                    transition:left .2s ease}
          .ttrack.p2 i{left:50%}

          @media (min-width:768px){
            .tin{max-width:720px;padding:0 24px}
            .trow{margin:0;padding:0;overflow:visible;scroll-snap-type:none}
            .tcard{flex:1 1 0;width:auto}
            .tshot{width:120px}
            .t .th{font-size:36px}
            .tfoot{display:none}
          }
          @media (min-width:1024px){
            .tin{max-width:1120px;padding:0 32px}
            .trow{max-width:1000px}
            .tshot{width:150px}
            .t .th{font-size:42px}
          }
        

          /* SECTION: audience-grid-verticals-3x3-with-cta-89
             Source: Figma 6uIyuYpF0xtl9HiQoR2A1o node 2:622 (B2B supplier)
             Sheet: section-bank/audience-grid/audience-grid-verticals-3x3-with-cta-89/SPEC.md

             ============================================================
             COMPLIANCE - READ BEFORE EDITING ANY LABEL.

             Every tile names a SITUATION or a BODY AREA. Not one names a
             condition. "Knees on stairs" is a situation; "arthritis" is a
             diagnosis, and a 3x3 grid of diagnoses turns an OTC topical into a
             treatment claim for nine named diseases at once - the single
             largest exposure on this page, made in the most natural-looking
             way, because a condition is the obvious label for a tile.

             Dragon's approved indication is "temporary relief of minor aches
             and pains" and every tile sits inside it. The footnote restates it
             under the grid rather than in a distant legal block, so a reader
             who scans the tiles meets the indication in the same view.

             The sheet's gate for regulated products is
             `compliance-approved-segment-labels`. These nine are written to be
             inside the rails but have NOT yet been signed off by Michelle. Flag
             on handover; do not treat this build as approval.
             ============================================================

             MEASURED, from the sheet's LOCKED tables:
               headline    40 / 1.05 / -0.4 tracking
               tile label  16 / 1.2 / -0.16
               headline -> grid 24   tile gap 8   CTA stack 12   CTA pad-x 15.554

             NINE TILES ARE A CLAIM OF BREADTH, and it only lands if the scenes
             are visibly different from each other. Nine variations on one scene
             says the opposite of what the layout asserts. Each of these nine is
             a different room, a different time of day and a different person.

             No product appears in any tile. The grid is about the visitor's
             situation, not the object - and every tile carrying a roll-up would
             turn nine moments of recognition into nine product shots. */
          .v,.v *{box-sizing:border-box}
          .v{width:100%;background:#f7f7f5;padding:56px 0;
             font-family:Lato,-apple-system,'Helvetica Neue',Helvetica,sans-serif;
             font-weight:500;color:#1a1a1a;-webkit-font-smoothing:antialiased}
          .v p{margin:0}
          .vin{width:100%;max-width:392px;margin:0 auto;padding:0 16px}

          .v .vh{font-size:40px;line-height:1.05;font-weight:900;letter-spacing:-0.4px}
          .v .vh em{font-style:italic;font-weight:900;color:#8e7940}
          .v .vsub{margin-top:14px;font-size:15px;line-height:1.5;color:#6b6b6b;font-weight:500}

          .vgrid{margin-top:24px;display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
          .vtile{position:relative;aspect-ratio:3/4;overflow:hidden;border-radius:6px;background:#e4e2dc}
          .vtile img{width:100%;height:100%;object-fit:cover;display:block}
          /* scrim only under the label, so the photograph stays legible - a
             full-tile darken makes nine images look like nine grey squares */
          .vtile::after{content:"";position:absolute;left:0;right:0;bottom:0;height:62%;
                        background:linear-gradient(180deg,rgba(0,0,0,0) 0%,rgba(0,0,0,0.72) 100%)}
          .v .vlabel{position:absolute;left:8px;right:8px;bottom:8px;z-index:2;
                     font-size:16px;line-height:1.2;letter-spacing:-0.16px;
                     font-weight:900;color:#ffffff}

          .v .vfoot{margin-top:16px;font-size:12px;line-height:1.45;color:#6b6b6b;font-weight:500}

          .vcta{margin-top:24px;display:flex;flex-direction:column;gap:12px}
          .vbtn{height:60px;border-radius:8px;padding:0 15.554px;
                display:flex;align-items:center;justify-content:center;gap:10px;
                text-decoration:none;font-size:16px;font-weight:900;
                text-transform:uppercase;letter-spacing:0.6px}
          /* crimson + white, never gold on crimson - see the profile's pairing
             table. The secondary is an outline so the two do not compete. */
          .vprimary{background:#a51b17;color:#ffffff}
          .vprimary svg{width:16px;height:16px}
          .vsecondary{background:transparent;color:#a51b17;box-shadow:inset 0 0 0 1px #a51b17;
                      text-transform:none;letter-spacing:0;font-weight:700;font-size:15px}

          @media (min-width:768px){
            .vin{max-width:720px;padding:0 24px}
            .v .vh{font-size:52px}
            .vgrid{gap:10px}
            .vcta{flex-direction:row;justify-content:center}
            .vbtn{min-width:280px}
          }
          @media (min-width:1024px){
            .vin{max-width:1120px;padding:0 32px}
            .v .vh{font-size:62px;max-width:900px}
            .vgrid{gap:12px}
            .v .vlabel{font-size:19px;left:14px;right:14px;bottom:12px}
          }
        

          /* SECTION: comparison-label-checklist-vs-typical-39
             Sheet: section-bank/comparison/comparison-label-checklist-vs-typical-39/SPEC.md

             GOLD IS #d1b66c - Dragon's real brass, measured on their live site.
             It was #f5a623, which appears NOWHERE on dragonpainrelief.com; that
             value came off a swipe-file preview and was written into the client
             profile as though it had been measured. Gold TEXT on a light ground
             uses #8e7940, because #d1b66c on white is 1.98:1 and unreadable.

             REBUILT against the sheet's measured tables rather than by eye.
             What the extraction changed, none of it visible until measured:

               claim row pitch     was a flat 8px gap -> source runs 33px pitch
                                   (16px gap on a 14/1.2 line)
               guarantee row       source breaks 50px before it, not 33. That
                                   gap separates what the product does from
                                   what happens if it does not, and flattening
                                   it lost the beat.
               logo -> rating      24 (measured: logo bottom 45, rating top 69)
               rating -> claims    27 (measured: 86 -> 112.87)
               typical title->list 18, then the same 33px pitch
               body copy           14 / 1.3 / -0.07 tracking (was 1.35, none)
               claim rows          14 / 1.2 / +0.07 tracking (was 1.25, none)
               typical title       18 / 1.1 / -0.36 tracking (was 1.2, none)

             LOCKED vs TOKEN: every px above is LOCKED and copied exactly. Every
             colour, the font family, the weights and the 8px radius are TOKEN,
             read off dragonpainrelief.com. The source brand's own values live
             in the sheet only so each role is unambiguous.

             DEVIATION - avatar stack omitted. The sheet requires
             `real-review-avatars:5`; Dragon has a real rating but no customer
             photos, and five generated faces beside a real rating would imply
             those people left it.

             CASCADE - `.k p{margin:0}` is (0,1,1) and outranks a bare class, so
             every spacing rule on a <p> is scoped `.k .class` = (0,2,0). */
          .k,.k *{box-sizing:border-box}
          .k{width:100%;background:#ffffff;padding:48px 0;
             font-family:Lato,-apple-system,'Helvetica Neue',Helvetica,sans-serif;
             font-weight:500;color:#1a1a1a;-webkit-font-smoothing:antialiased}
          .k p{margin:0}
          /* max-width, NOT width - 392 is the Figma frame, not a device. See
             MOBILE-CONTAINER-WIDTH.md. */
          .kin{width:100%;max-width:392px;margin:0 auto;padding:0 16px}

          .khead{margin-bottom:24px}
          .k .kh{font-size:32px;line-height:1.1;font-weight:900}
          /* the italic second line is the section's signature - without it the
             headline reads as a table caption */
          .k .kh em{display:block;font-style:italic;font-weight:900;color:#8e7940}
          .k .kbody{margin-top:12px;font-size:14px;line-height:1.3;letter-spacing:-0.07px;
                    color:#6b6b6b;font-weight:500}

          .kcard{width:100%;border-radius:8px;padding:16px;overflow:hidden;position:relative}
          .kcard + .kcard{margin-top:16px}
          /* brand card is tinted, logo'd, badged and photographed. typical card
             is flat. the inequality IS the argument. */
          .kbrand{background:#f9f6ed;box-shadow:inset 0 0 0 1px #eadebd}
          .ktyp{background:#ffffff;box-shadow:inset 0 0 0 1px #e4e2dc}

          .ktop{display:flex;align-items:center;justify-content:space-between;gap:12px;
                position:relative;z-index:3;min-height:29px}
          .klogo{height:24px;width:auto;display:block}
          /* pill hugs its text - a fixed width is what made the hero badge
             overflow when the words changed. Black on gold: a sanctioned
             Dragon pairing, and 9.4:1. */
          .kpill{height:24px;padding:0 12px;border-radius:999px;background:#d1b66c;color:#1a1a1a;
                 font-size:12px;font-weight:900;display:inline-flex;align-items:center;
                 white-space:nowrap;flex:0 0 auto}

          .k .krate{margin-top:24px;display:flex;align-items:center;gap:6px;
                    position:relative;z-index:3}
          .k .krate svg{width:14px;height:14px;color:#d1b66c;flex:0 0 auto}
          .k .krate span{font-size:14px;letter-spacing:-0.07px;font-weight:700;color:#1a1a1a}

          /* 16px gap on a 14/1.2 line reproduces the source's 33px row pitch */
          .klist{margin-top:27px;display:flex;flex-direction:column;gap:16px;
                 position:relative;z-index:2}
          .k .kli{display:flex;gap:8px;align-items:flex-start;font-size:14px;line-height:1.2;
                  letter-spacing:0.07px;font-weight:500}
          /* the source breaks 50px, not 33, before the guarantee row. Do not
             flatten it back to the common pitch. */
          .kbrand .kli:nth-child(5){margin-top:17px}
          .kbadge{width:14px;height:14px;border-radius:50%;flex:0 0 auto;margin-top:2px;
                  display:flex;align-items:center;justify-content:center;padding:0}
          .kbadge svg{width:9px;height:9px;color:#ffffff}
          .kok{background:#3f7d47}
          .kno{background:#b84343}
          /* the reserve keeping claim text clear of the photo goes on .ktext
             ONLY - scoping it to `.kli span` also matched the badge and turned
             a 14px circle into a long green oval */
          .ktext{display:block}
          .kbrand .ktext{max-width:196px}

          /* 151px wide, matching the source, bleeding past the card's corner */
          .kphoto{position:absolute;right:-26px;bottom:-30px;width:151px;height:auto;
                  max-height:74%;object-fit:contain;object-position:bottom right;
                  transform:rotate(12deg);z-index:1;pointer-events:none;
                  mix-blend-mode:multiply}

          .k .ktypTitle{font-size:18px;font-weight:900;line-height:1.1;letter-spacing:-0.36px}
          .ktyp .klist{margin-top:18px}

          @media (min-width:768px){
            .kin{max-width:720px;padding:0 24px}
            .k .kh{font-size:40px}
            .kphoto{width:200px;right:-30px;bottom:-36px}
            .kbrand .ktext{max-width:none;padding-right:200px}
          }
          @media (min-width:1024px){
            .kin{max-width:1120px;padding:0 32px}
            .khead{margin-bottom:28px}
            .kcards{display:flex;gap:24px;align-items:stretch}
            .kcard{flex:1 1 0;min-width:0;padding:24px}
            .kcard + .kcard{margin-top:0}
            .kbrand .ktext{max-width:none;padding-right:130px}
            .kphoto{width:150px;right:-20px;bottom:-22px;max-height:60%}
          }
        

          /* SECTION: educational-mechanism-benefit-blocks-45
             Source: Berberine A advertorial, Figma 6uIyuYpF0xtl9HiQoR2A1o node 1:65
             Sheet: section-bank/educational/educational-mechanism-benefit-blocks-45/SPEC.md

             ============================================================
             SPACING - every gap declared, and why the last two attempts
             at fixing it did nothing:

             `.e p { margin: 0 }` has specificity (0,1,1) - a class AND an
             element. `.etitle { margin-top: 20px }` has (0,1,0) - a class
             alone. The reset WINS, so every margin set on a <p> here was
             silently discarded and every measured gap came back 0px. It
             looked like a taste problem and was a cascade problem.

             Fix: every spacing rule is scoped `.e .class`, which is (0,2,0)
             and outranks the reset. Do not write bare `.etitle{margin}` in
             this file - it will not apply.

             Declared vertical gaps, mobile / desktop:
               heading      -> intro para      16 / 16
               intro para   -> intro para      16 / 16
               intro block  -> first block     40 / 48
               photo        -> title row       24 / n-a (side by side)
               title row    -> body            12 / 12
               block        -> block           40 / 48
               last block   -> footnote        32 / 40
             ============================================================ */
          .e,.e *{box-sizing:border-box}
          .e{width:100%;background:#f7f7f5;padding:56px 0;
             font-family:Lato,-apple-system,'Helvetica Neue',Helvetica,sans-serif;
             font-weight:500;color:#1a1a1a;-webkit-font-smoothing:antialiased}
          .e p{margin:0}
          .ein{width:360px;margin:0 auto;padding:0 16px;display:flex;flex-direction:column;gap:40px}

          .eintro{display:flex;flex-direction:column;gap:16px}
          .e .eh{font-size:28px;font-weight:900;line-height:1.15;letter-spacing:-0.3px}
          .e .ep{font-size:16px;line-height:1.5;font-weight:500}
          /* emphasis is bolding INSIDE a sentence - a pull quote or tinted box
             here breaks the explaining voice the section runs on */
          .e .ep b{font-weight:900}

          .eblocks{display:flex;flex-direction:column;gap:40px}
          .eblock{width:100%}
          .ephoto{width:100%;height:180px;border-radius:8px;overflow:hidden;background:#e4e2dc;display:block}
          .ephoto img{width:100%;height:100%;object-fit:cover;display:block}
          /* 24 under the photo, 12 under the title: the title sits closer to
             its own paragraph than to the image, so it captions the block
             rather than reading as stuck to the picture. */
          .e .etitle{margin-top:24px;display:flex;gap:6px;align-items:flex-start}
          .e .etitle svg{width:14px;height:14px;color:#3f7d47;flex:0 0 auto;margin-top:4px}
          .e .etitle span{font-size:18px;font-weight:900;line-height:1.15}
          .e .ebody{margin-top:12px;font-size:16px;line-height:1.5;font-weight:500}
          .e .efoot{font-size:12px;line-height:1.4;color:#6b6b6b;font-weight:500}

          @media (min-width:768px){
            /* prose caps at 640: past ~75 characters a line stops being read */
            .ein{width:100%;max-width:640px;padding:0 24px}
            .e .eh{font-size:34px}
            .ephoto{height:240px}
          }
          @media (min-width:1024px){
            .ein{max-width:1120px;padding:0 32px;gap:48px}
            .eintro{max-width:640px}
            .e .efoot{max-width:640px}
            .eblocks{gap:48px}
            .eblock{display:flex;gap:40px;align-items:center}
            .eblock > .ephoto{flex:0 0 46%;height:320px}
            .eblockCopy{flex:1 1 54%;min-width:0}
            /* side by side, so the photo gap becomes horizontal and the title
               starts at the top of its column */
            .e .etitle{margin-top:0}
            .e .ebody{margin-top:12px}
            /* alternating sides is what makes three blocks read as a sequence
               rather than as a table */
            .eblock:nth-child(even){flex-direction:row-reverse}
          }
        

          /* SECTION: educational-process-steps-vertical-timeline-03
             Source: Frame 3, Figma 6uIyuYpF0xtl9HiQoR2A1o node 6:716
             Sheet: section-bank/educational/educational-process-steps-vertical-timeline-03/SPEC.md

             WHY THIS SECTION IS ON THIS PAGE. The application format IS the
             product - a stick against a tube of cream is the entire argument the
             comparison section makes. Until now that lived in one carousel slide
             and one FAQ line, so the page argued for a mechanic it never showed.

             It is a SEQUENCE, not a checklist. The connected rail with a node
             per step is load-bearing: it says these happen in order. Swap the
             rail for ticks and it becomes a benefit list, which the page already
             has twice.

             MEASURED, from the sheet's LOCKED tables:
               headline        38 / 1.05
               step title      24 / 1.05
               step body       14 / 1.25
               step chip       12 / 1.25, 8px padding
               closing note    18 / 1.25
               chip -> title   10   |   title -> body 10   |   step -> step 12

             STEPS ARE WHAT THE USER DOES, and they match the Drug Facts panel.
             Frequency is a LABEL fact and is quoted, never written fresh - it
             sits in the closing note with the approved indication. Nothing here
             says what the balm does inside the body; that is the educational
             section's job and saying it in a step turns a direction into a
             mechanism claim.

             Four steps because the product takes four. The sheet warns that
             padding to fill the timeline is this format's standing temptation
             and always reads as padding. */
          .w,.w *{box-sizing:border-box}
          .w{width:100%;background:#f7f7f5;padding:56px 0;
             font-family:Lato,-apple-system,'Helvetica Neue',Helvetica,sans-serif;
             font-weight:500;color:#1a1a1a;-webkit-font-smoothing:antialiased;
             /* The product bleeds 38px past the right edge below 1024, which is
                38px of document-wide horizontal scroll if nothing contains it.
                `clip` and not `hidden`: hidden makes this a scroll container,
                and a scroll container silently disables `position: sticky` in
                every descendant - which is exactly what `.wleft` is at 1024.
                `clip` contains the bleed without creating a scrollport.
                The rule is also lifted at 1024 where there is no bleed to
                contain, so the sticky column never depends on clip semantics.
                Same trap as Page.dc.html - see MOBILE-CONTAINER-WIDTH.md. */
             overflow-x:clip}
          .w p{margin:0}
          .win{width:100%;max-width:392px;margin:0 auto;padding:0 16px;position:relative}

          .whead{position:relative;z-index:2;max-width:250px}
          .w .wh{font-size:38px;line-height:1.05;font-weight:900;letter-spacing:-0.8px}
          .w .wintro{margin-top:14px;font-size:14px;line-height:1.45;color:#6b6b6b;font-weight:500}
          .wchip{display:inline-flex;align-items:center;height:30px;padding:0 14px;margin-top:20px;
                 border-radius:6px;background:#1a1a1a;color:#ffffff;
                 font-size:12px;font-weight:900;letter-spacing:1px;text-transform:uppercase}

          /* product bleeds in from the top right and anchors the sequence to the
             object. NOT a lifestyle slot - a person here competes with the steps. */
          .wprod{position:absolute;right:-38px;top:-6px;width:172px;height:auto;z-index:1;
                 pointer-events:none;mix-blend-mode:multiply}

          /* the RAIL is the format. one continuous line, one node per step. */
          .wsteps{margin-top:24px;position:relative;padding-left:30px}
          .wsteps::before{content:"";position:absolute;left:5px;top:6px;bottom:6px;width:1px;
                          background:#d8d5cc}
          .wstep{position:relative}
          .wstep + .wstep{margin-top:12px}
          .wnode{position:absolute;left:-30px;top:4px;width:11px;height:11px;
                 background:#8e7940;transform:rotate(45deg)}
          .wnum{display:inline-flex;align-items:center;height:22px;padding:0 8px;
                background:#ffffff;box-shadow:inset 0 0 0 1px #e4e2dc;border-radius:4px;
                font-size:12px;line-height:1.25;font-weight:900;letter-spacing:0.6px;
                text-transform:uppercase;color:#1a1a1a}
          .w .wtitle{margin-top:10px;font-size:24px;line-height:1.05;font-weight:900;letter-spacing:-0.4px}
          .wrule{height:1px;background:#e4e2dc;margin-top:10px}
          .w .wbody{margin-top:10px;font-size:14px;line-height:1.25;color:#6b6b6b;font-weight:500}

          .w .wnote{margin-top:26px;font-size:18px;line-height:1.25;font-weight:700;color:#1a1a1a}
          .w .wlegal{margin-top:10px;font-size:12px;line-height:1.4;color:#6b6b6b;font-weight:500}
          .wcta{display:flex;width:100%;height:60px;margin-top:22px;border-radius:8px;
                background:#a51b17;color:#ffffff;align-items:center;justify-content:center;
                text-decoration:none;font-size:16px;font-weight:900;
                text-transform:uppercase;letter-spacing:0.6px}

          @media (min-width:768px){
            .win{max-width:720px;padding:0 24px}
            .whead{max-width:420px}
            .wprod{width:230px;right:-10px}
            .w .wh{font-size:46px}
            .wcta{width:340px}
          }
          @media (min-width:1024px){
            /* no bleed at this width, so no clip - keeps the sticky column below
               independent of how `clip` interacts with sticky */
            .w{overflow-x:visible}
            .win{max-width:1120px;padding:0 32px;display:flex;gap:64px;align-items:flex-start}
            .wleft{flex:0 0 40%;position:sticky;top:32px}
            .whead{max-width:none}
            .wsteps{flex:1 1 60%;margin-top:6px}
            .wprod{position:relative;right:auto;top:auto;width:100%;max-width:300px;
                   margin-top:28px;display:block;mix-blend-mode:normal}
            .w .wh{font-size:52px}
          }
        

          /* SECTION: ingredients-label-accordion-thumbnails-37
             Source: Figma 6uIyuYpF0xtl9HiQoR2A1o, gut-health brand
             Sheet: section-bank/ingredients/ingredients-label-accordion-thumbnails-37/SPEC.md

             CAPABILITY GATE - PASSES. The sheet requires `disclosed-doses OR
             disclosed-ingredient-list` plus `real-ingredient-photography:3+`.
             Dragon publishes actives with amounts on the Drug Facts panel
             (Menthol 11%, Camphor 10%), so the format's promise can be kept.
             A proprietary-blend brand fails this gate and must not run it: the
             headline promises you can read every word, and an accordion that
             then names no amounts breaks its own premise.

             MEASURED, from the sheet's LOCKED tables:
               headline    32 / 1.1     row title 18 / 1.3 / -0.009
               row body    16 / 1.3 / -0.08
               head stack  28 then 16   rows 12 apart
               thumb -> title 39 across, icon gap 10

             FIRST ROW OPEN, rest closed - the open row proves there is substance
             behind the accordion. All closed reads as a nav menu; all open is a
             wall of text the page already carries elsewhere.

             ROWS ARE INGREDIENTS, NEVER BENEFITS. "Menthol, 11%" is a row.
             "Cools on contact" is a claim and belongs to the educational
             section. On a regulated OTC drug that distinction is not stylistic:
             a benefit sitting in an ingredient list reads as a substantiated
             drug claim.

             NO INVENTED AMOUNTS. The two actives carry percentages because the
             label does. The hemp row names its cannabinoids and states no
             amount, because Dragon has not published one. A fabricated
             milligram is the worst output this format can produce - the whole
             section is built to be read as verified.

             FOOTNOTE SITS BELOW THE ROWS. It annotates them, and the first
             build had it in the lead column, where on mobile it stacked between
             the intro and the accordion - legal text interrupting the sentence
             that sets the accordion up, before the reader has seen a single
             row. It is now the last child of the container, and `flex-wrap` at
             1024 lets it drop to a full-width third row under both columns. */
          .n,.n *{box-sizing:border-box}
          .n{width:100%;background:#ffffff;padding:56px 0;
             font-family:Lato,-apple-system,'Helvetica Neue',Helvetica,sans-serif;
             font-weight:500;color:#1a1a1a;-webkit-font-smoothing:antialiased}
          .n p{margin:0}
          .nin{width:100%;max-width:392px;margin:0 auto;padding:0 16px}

          .n .nh{font-size:32px;line-height:1.1;font-weight:900;letter-spacing:-0.5px}
          /* the italic accent half is the format's signature - the challenge in
             the headline is what earns the disclosure below it */
          .n .nh em{font-style:italic;font-weight:900;color:#8e7940}
          .n .nintro{margin-top:28px;font-size:16px;line-height:1.3;letter-spacing:-0.08px;
                     color:#1a1a1a;font-weight:500}

          .nrows{margin-top:28px;display:flex;flex-direction:column;gap:12px}
          .nrow{border-radius:8px;box-shadow:inset 0 0 0 1px #e4e2dc;overflow:hidden;background:#ffffff}
          .nrow.open{box-shadow:inset 0 0 0 1px #eadebd;background:#f9f6ed}
          .nbtn{width:100%;background:none;border:0;padding:0;margin:0;font:inherit;color:inherit;
                display:flex;align-items:center;gap:10px;cursor:pointer;text-align:left;
                -webkit-appearance:none;appearance:none}
          .nthumb{width:78px;height:78px;flex:0 0 auto;overflow:hidden;background:#f7f7f5}
          .nthumb img{width:100%;height:100%;object-fit:cover;display:block}
          .n .nname{flex:1 1 auto;min-width:0;padding:0 6px;
                    font-size:18px;line-height:1.3;letter-spacing:-0.009px;font-weight:900}
          .n .nname b{display:block;font-size:13px;font-weight:700;color:#8e7940;
                      letter-spacing:0.4px;text-transform:uppercase;margin-top:3px}
          .nsign{width:34px;height:34px;flex:0 0 auto;margin-right:12px;border-radius:6px;
                 box-shadow:inset 0 0 0 1px #d8d5cc;position:relative;background:#ffffff}
          .nsign::before,.nsign::after{content:"";position:absolute;background:#1a1a1a;
                 left:50%;top:50%;transform:translate(-50%,-50%)}
          .nsign::before{width:11px;height:1.6px}
          .nsign::after{width:1.6px;height:11px}
          .nbtn[aria-expanded="true"] .nsign::after{display:none}
          .n .nbody{padding:0 16px 18px;font-size:16px;line-height:1.3;letter-spacing:-0.08px;
                    color:#1a1a1a;font-weight:500}

          .n .nfoot{margin-top:20px;font-size:12px;line-height:1.45;color:#6b6b6b;font-weight:500}

          @media (min-width:768px){
            .nin{max-width:720px;padding:0 24px}
            .n .nh{font-size:40px}
            .nthumb{width:96px;height:96px}
          }
          @media (min-width:1024px){
            .nin{max-width:1120px;padding:0 32px;display:flex;flex-wrap:wrap;gap:0 64px;align-items:flex-start}
            .nlead{flex:0 0 42%;position:sticky;top:32px}
            .nrows{flex:1 1 50%;margin-top:0}
            /* full-width third row under both columns */
            .n .nfoot{flex:1 1 100%;margin-top:32px}
            .n .nh{font-size:46px}
          }
        

          /* SECTION: guarantee-badge-support-cards-33
             Source: 221B Tactical HOMEPAGE, Figma 6uIyuYpF0xtl9HiQoR2A1o node 3:664

             ============================================================
             REBUILT 2026-08-22 against preview.png. Three faults, and they are
             worth separating because the first one had me fixing the wrong
             thing twice.

             FAULT 1 - THE COLOUR WAS INHERITED, NOT SOURCED.
             This section ran the source brand's orange, `#f5a623`. That value
             was sitting in Dragon's profile labelled "warm orange-gold",
             recorded as read off their computed styles. It is not on their site
             at all - a sweep of dragonpainrelief.com finds it ZERO times across
             40 distinct colours. It is 221B Tactical's accent. It arrived with
             the template and was written down as though it had been measured.

             Dragon's real gold is BRASS: #d1b66c, used 314 times on the live
             site, alongside #b68c2a, #c9b04e, #b39a50, #e1bd66. All muted. A
             saturated accent is the tell that a colour came from a swipe file.

             The earlier "fix" was to recolour this panel CRIMSON, reasoning
             that black+gold looked like the template. Wrong diagnosis.
             Black+gold is not the template's - it is Dragon's own packaging.
             What looked borrowed was that specific ORANGE. So the panel is
             black again, in Dragon's brass, and now it reads as Dragon because
             the colour is finally Dragon's.

             FAULT 2 - THE CRIMSON PANEL CREATED A PAIRING DRAGON NEVER USES.
             Gold type on a crimson field. Dragon pairs gold with black, or red
             with black or white, and never gold with red. It also measures
             3.83:1, which fails for body copy, where gold on black is 8.8:1.
             The brand convention and the accessible choice agree.
             Crimson now appears ONLY on the CTA, white-on-crimson at 7.58:1,
             which is how their own site uses it. The two loud colours never
             touch.

             FAULT 3 - THE SUPPORT CARDS WERE THE WRONG OBJECT.
             The source's cards are LARGE SQUARE IMAGE TILES - a photograph,
             darkened, with the accent icon and white heading inside it, body
             copy below on the page ground - in a horizontal scroller with
             arrows and a progress bar. This build had them as two 112px black
             boxes side by side with copy underneath. That is what made it boxy
             and clunky on mobile: at 112px the tiles were too small to read as
             images, so they read as chrome, and two side by side at 360px are a
             pair of grey lumps. They are now 1:1 image tiles, one per screen
             with the next peeking, as the source runs them.
             ============================================================ */
          .g,.g *{box-sizing:border-box}
          .g{width:100%;background:#ffffff;padding:0 0 56px;
             font-family:Lato,-apple-system,'Helvetica Neue',Helvetica,sans-serif;
             font-weight:500;color:#1a1a1a;-webkit-font-smoothing:antialiased}
          .g p{margin:0}
          /* max-width, NOT width - see MOBILE-CONTAINER-WIDTH.md */
          .gin{width:100%;max-width:392px;margin:0 auto;padding:0 16px}
          .gblock{position:relative}

          .gstrip{display:flex;gap:2px;width:100%;overflow:hidden}
          .gstrip span{flex:1 1 0;height:118px;overflow:hidden;display:block}
          .gstrip img{width:100%;height:100%;object-fit:cover;display:block}

          /* BLACK, as the source is. The gold is Dragon's brass, not the
             source's amber - that difference is the whole re-brand. */
          .gpanel{position:relative;background:#141414;color:#ffffff;
                  padding:74px 24px 34px;text-align:center}
          /* NO overflow:hidden here. It clipped the shield badge, which sits at
             top:-58px so it straddles the strip/panel seam exactly as the
             source draws it - the tick and the top third vanished. The dot
             texture below is a ::before at inset:0 and cannot spill, so the
             clip was protecting nothing. See GuaranteeBadgeClip.md. */
          .gpanel::before{content:"";position:absolute;inset:0;opacity:0.5;
                          background-image:radial-gradient(#242424 1px,transparent 1px);
                          background-size:6px 6px;pointer-events:none}
          .gpanelIn{position:relative;z-index:1;max-width:640px;margin:0 auto}

          .gbadge{position:absolute;top:-58px;left:50%;transform:translateX(-50%);
                  width:126px;height:146px;z-index:3;
                  display:flex;flex-direction:column;align-items:center;justify-content:center;
                  text-align:center}
          /* shield is DARK with a gold outline, as the source draws it - a solid
             gold shield would put the type on gold and break the pairing */
          .gbadgeBg{position:absolute;inset:0}
          .gbadgeBg svg{width:100%;height:100%;display:block;
                        filter:drop-shadow(0 6px 14px rgba(0,0,0,0.45))}
          .gbadgeTick{position:relative;z-index:1;width:30px;height:30px;color:#d1b66c;margin-bottom:4px}
          .g .gbadgeTerm{position:relative;z-index:1;font-size:23px;font-weight:900;line-height:1;
                         letter-spacing:-0.4px;color:#ffffff}
          .g .gbadgeWord{position:relative;z-index:1;font-size:9px;font-weight:900;
                         letter-spacing:2.4px;text-transform:uppercase;margin-top:4px;color:#d1b66c}

          /* headline splits white / gold mid-phrase, as the source does */
          .g .gh{font-size:29px;font-weight:900;line-height:1.14;letter-spacing:-0.3px;
                 text-transform:uppercase}
          .g .gh em{font-style:normal;color:#d1b66c}
          .g .gbody{margin-top:16px;font-size:15px;line-height:1.6;font-weight:500;
                    color:rgba(255,255,255,0.82)}
          .grate{margin-top:20px;display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap}
          .grate svg{width:15px;height:15px;color:#d1b66c;flex:0 0 auto}
          .g .grateLabel{font-size:14px;font-weight:700;color:#ffffff}
          .g .grateLabel u{text-decoration:underline;text-underline-offset:3px}

          /* SUPPORT CARDS - image tiles in a scroller, one per screen with the
             next peeking. The old version was two 112px boxes side by side. */
          .gcards{display:flex;gap:14px;margin:14px -16px 0;padding:0 16px;
                  overflow-x:auto;scroll-snap-type:x mandatory;
                  -webkit-overflow-scrolling:touch;scrollbar-width:none}
          .gcards::-webkit-scrollbar{display:none}
          .gcol{width:270px;flex:0 0 auto;scroll-snap-align:start}
          .gtile{position:relative;width:100%;aspect-ratio:1/1;border-radius:8px;overflow:hidden;
                 background:#141414;display:flex;flex-direction:column;justify-content:flex-end;
                 padding:20px}
          .gtileImg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
                    filter:grayscale(0.35) brightness(0.42)}
          .gtile svg{position:relative;z-index:1;width:34px;height:34px;color:#d1b66c;margin-bottom:12px}
          .g .gtileH{position:relative;z-index:1;font-size:19px;font-weight:900;
                     text-transform:uppercase;letter-spacing:0.2px;color:#ffffff;line-height:1.15}
          .g .gcardB{margin-top:14px;font-size:14px;line-height:1.5;color:#6b6b6b;font-weight:500}

          /* arrows + progress bar, as the source has */
          .gpag{margin-top:20px;display:flex;align-items:center;justify-content:center;gap:16px}
          .garrow{width:18px;height:18px;flex:0 0 auto;position:relative;cursor:pointer;
                  background:none;border:0;padding:0}
          .garrow::before{content:"";position:absolute;top:50%;left:50%;width:8px;height:8px;
                          border-left:2px solid #8e7940;border-bottom:2px solid #8e7940}
          .gprev::before{transform:translate(-40%,-50%) rotate(45deg)}
          .gnext::before{transform:translate(-60%,-50%) rotate(-135deg)}
          .gbars{display:flex;gap:5px;align-items:center}
          .gbar{height:2.5px;width:30px;background:rgba(209,182,108,0.3);flex:0 0 auto;
                transition:background .15s ease,width .15s ease}
          .gbar.on{width:62px;background:#d1b66c}

          .gcta{margin-top:26px;display:flex;flex-direction:column;align-items:center;gap:12px}
          /* crimson + WHITE. The only crimson in the section, and it never
             touches the gold. */
          .gbtn{width:100%;height:60px;border-radius:8px;background:#a51b17;
                color:#ffffff;display:flex;align-items:center;justify-content:center;
                text-decoration:none;font-size:16px;font-weight:900;
                text-transform:uppercase;letter-spacing:0.6px}
          .gnoteRow{display:flex;align-items:center;gap:7px}
          .gnoteRow svg{width:15px;height:15px;color:#1a1a1a;flex:0 0 auto}
          .g .gnote{font-size:13px;color:#1a1a1a;font-weight:700;text-align:center}

          @media (min-width:768px){
            .gin{max-width:720px;padding:0 24px}
            .gstrip span{height:150px}
            .gpanel{padding:84px 32px 40px}
            .gbadge{top:-64px;width:140px;height:162px}
            .g .gh{font-size:34px}
            .gcards{margin:16px 0 0;padding:0;overflow:visible;scroll-snap-type:none}
            .gcol{flex:1 1 0;width:auto}
            .gpag{display:none}
            .gbtn{width:340px}
          }
          @media (min-width:1024px){
            .gin{max-width:960px;padding:0 32px}
            .gstrip span{height:196px}
            .gpanel{padding:96px 40px 48px}
            .g .gh{font-size:40px}
            .gcards{gap:20px}
            .gtile{padding:26px}
            .g .gtileH{font-size:21px}
          }
        

          /* Dragon Pain Relief - Black Roll-Up PDP hero.
             Sheet: section-bank/hero/hero-pdp-full-mobile-01/SPEC.md

             NOTHING IS COMPOSITED OVER THE GALLERY IMAGE. (Adam, 2026-08-22.)
             An `EXTRA STRENGTH` chip used to sit in the top-right of the frame,
             positioned over whichever slide was showing. It was convenient - one
             element, always aligned, editable without a re-render - and it was a
             box of brand gold parked on top of photographs that had just been
             generated against an approved product grid. It covered the image on
             every slide, and on the cover it clipped the slide's own baked-in
             headline to "Relief Right Wh...".

             If something belongs on a slide it is GENERATED INTO the slide, where
             it is composed with the picture instead of dropped on top of it. The
             strength is already on the product's own label in every render and
             carried explicitly by slide 04, so nothing was lost by deleting it.

             The arrows stay HTML because they are functional navigation - they
             have to be tappable, so they cannot be pixels. They are the only
             thing over the frame, and the carousel sheets reserve bottom-right
             for them. Top-right is no longer reserved anywhere.

             SPACING - `.h p{margin:0}` is (0,1,1) and outranks a bare class, so
             every spacing rule on a <p> is scoped `.h .class` = (0,2,0). Written
             unscoped it silently does nothing; that ate two attempted fixes.
             Measured, not asserted:
               offer heading -> first plan card  32px
               plan card -> plan card            10px

             MARQUEE - two identical groups, animated 0 -> -50%.

             The group has to be at least as wide as the widest viewport, and
             that is the part that is easy to get wrong twice. Build one showed
             a seam at 1440 because it used ONE group with padding-left:100%
             animated to -100%: the translate distance included the padding.
             Build two used two groups and -50%, which is correct, but each
             group held only the two messages and measured 534px, so the whole
             1068px track was narrower than a 1440 viewport and the bar simply
             ran out of content - a stretch of empty black scrolling past.
             Same class of bug, opposite symptom.

             The messages therefore repeat MARQUEE_REPEATS times inside each
             group, sized so a group clears the widest breakpoint. Two messages
             at ~267px each x 3 = ~1602px per group, comfortably over 1440. If a
             message is ever shortened, re-measure rather than assume.

             GALLERY - five slides built from carousel format sheets, all 1:1,
             all generated with the Black Roll-Up reference grid attached:
               01 cover-004   mechanism hero, no copy
               02 howto-002   four step chips
               03 value-001   ticked claim list
               04 value-004   practitioner positioning
               05 compare-001 roll-on vs cream or gel
             The net weight line is framed OUT of every product render. It is
             the smallest text on the label and gpt-image-2 invented it on five
             separate attempts (.2oz, 1.23oz, 3.0oz, 3oz against a real 3.4oz).
             Never show label text the model cannot reproduce faithfully.

             Slide 03 carried a large panel of CLEAR GEL until 2026-09-04. It
             was replaced with a photographic lifestyle frame, because Dragon
             sells a solid balm stick and a translucent gel on the product
             carousel implies a form they do not make. See regen_slide3.py.

             BRAND TOKENS, verified against dragonpainrelief.com with
             scripts/brand_tokens.mjs - not taken on trust from the profile:
             Lato 900/500, ink #1a1a1a, muted #6b6b6b, gold #d1b66c,
             CTA #a51b17 crimson at 8px radius.

             The gold was #f5a623 until 2026-08-22. That value appears NOWHERE
             on their site; it is 221B Tactical's accent, which rode in with a
             section template and was then written into Dragon's profile as if
             it had been measured. #d1b66c is their real brass, 314 uses.

             TWO GOLDS, BY ROLE. #d1b66c is 1.98:1 on white - correct for a
             filled shape, illegible as type. Gold TEXT on a light ground uses
             #8e7940 (4.23:1). Every gold in this file is a shape or a border,
             so it takes the brass; the tint text in `.hsave` takes the deep.

             THIS FILE IS EXPORTED BY `publish-landing-page`, WHICH STRIPS EVERY
             SCRIPT. Anything that depended on the dc runtime therefore has to
             work a second way. Two things did, and both were caught only by
             exporting and reading the output:

               plan selector  one anchor with a recomputed href froze on the
                              default plan, so the monthly plan was visible and
                              unbuyable. Now one anchor PER PLAN, switched by
                              class - see the .hcta note below.
               FAQ            answers lived inside `sc-if`, so the export
                              contained five buttons and no answer text at all.
                              Now always in the DOM, hidden by class.

             Both carry `data-ui-tab` / `data-ui-panel`, the hooks the skill's
             `ui.js` drives on the exported page, ALONGSIDE the dc `onClick`
             that drives them here. The class it toggles is `on` in both
             runtimes, so one stylesheet serves both. Do not "simplify" either
             back onto runtime state. */
          .h,.h *{box-sizing:border-box}
          .h{width:100%;background:#ffffff;
             font-family:Lato,-apple-system,'Helvetica Neue',Helvetica,sans-serif;
             font-weight:500;-webkit-font-smoothing:antialiased;color:#1a1a1a;padding-bottom:32px}
          .h p{margin:0}
          .hin{width:360px;margin:0 auto}

          .hann{width:100%;height:28px;background:#1a1a1a;overflow:hidden;position:relative;display:flex;align-items:center}
          .hannTrack{display:flex;width:max-content;animation:hmar 44s linear infinite}
          .hannGroup{display:flex;gap:48px;padding-right:48px;white-space:nowrap}
          .hannGroup span{color:#ffffff;font-size:12px;font-weight:700;letter-spacing:0.78px;text-transform:uppercase}
          @keyframes hmar{from{transform:translateX(0)}to{transform:translateX(-50%)}}
          @media (prefers-reduced-motion:reduce){
            .hannTrack{animation:none}
          }

          .hnav{height:50px;display:flex;align-items:center;justify-content:space-between;padding:0 15px}
          .hburger{width:20px;display:flex;flex-direction:column;gap:4px;flex:0 0 auto}
          .hburger i{display:block;height:2px;background:#1a1a1a;border-radius:1px}
          .hlogo{height:22px;width:auto;display:block}
          .hcart{width:20px;height:20px;display:block;flex:0 0 auto}

          .hgal{width:328px;margin:8px auto 0;display:flex;gap:8px;align-items:flex-start}
          .hrail{width:50px;height:270px;display:flex;flex-direction:column;gap:6px;flex:0 0 auto}
          .hthumb{flex:1 1 0;min-height:0;overflow:hidden;cursor:pointer;background:#f7f7f5;border-radius:6px;
                  box-shadow:inset 0 0 0 1px #e4e2dc;transition:box-shadow .15s ease;position:relative}
          .hthumb img{width:100%;height:100%;object-fit:cover;display:block}
          .hmain{position:relative;width:270px;height:270px;flex:0 0 auto;border-radius:10px;
                 background:#f7f7f5;box-shadow:inset 0 0 0 1px #e4e2dc;overflow:hidden}
          .hslide{position:absolute;inset:0;opacity:0;transition:opacity .25s ease}
          .hslide img{width:100%;height:100%;object-fit:cover;display:block}
          /* arrows only - the sole thing permitted over the image, because they
             are controls rather than content and have to be tappable */
          .hnav2{position:absolute;right:8px;bottom:8px;display:none;gap:8px;z-index:2}
          .harrow{width:26px;height:26px;border-radius:50%;background:rgba(255,255,255,0.94);
                  box-shadow:0 1px 4px rgba(0,0,0,0.22);cursor:pointer;
                  display:flex;align-items:center;justify-content:center}
          .harrow::before{content:"";width:7px;height:7px;border-left:2px solid #1a1a1a;border-bottom:2px solid #1a1a1a}
          .hprev::before{transform:rotate(45deg);margin-left:2px}
          .hnext::before{transform:rotate(-135deg);margin-right:2px}

          .hcopyrow{width:328px;margin:20px auto 0;display:flex;gap:12px;align-items:stretch}
          .hcopy{width:205px;flex:0 0 auto;display:flex;flex-direction:column;gap:12px}
          .h .htitle{font-size:30px;line-height:1.08;letter-spacing:-0.4px;font-weight:900}
          .h .htag{font-size:15px;font-weight:900;text-transform:uppercase;line-height:1.25;letter-spacing:0.3px}
          .h .hbody{font-size:15px;line-height:1.55;color:#6b6b6b;font-weight:500}

          /* SOCIAL PROOF, PULLED FROM THE BLACK ROLL-UP PDP, NOT WRITTEN.
             Rating and count are the live aggregate off product 5930's
             JSON-LD; the quote is verbatim from that product's review feed.
             Nothing here is composed. If the count is refreshed, take it from
             the same place rather than rounding the old one up. */
          .hrate{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
          .hrate svg{width:14px;height:14px;color:#d1b66c;flex:0 0 auto}
          .h .hrateN{font-size:14px;font-weight:900;color:#1a1a1a}
          .h .hrateC{font-size:13px;font-weight:500;color:#6b6b6b}

          /* gold as a BORDER, not as type - see the two-golds rule above */
          .hquote{margin:0;padding:2px 0 2px 12px;border-left:2px solid #d1b66c}
          .h .hquoteT{font-size:14px;line-height:1.5;font-weight:500;color:#1a1a1a}
          .h .hquoteA{font-size:12px;line-height:1.3;font-weight:700;color:#6b6b6b;margin-top:6px}
          .hbens{width:90px;flex:0 0 auto;display:flex;flex-direction:column;
                 border-left:1px solid #e4e2dc;border-right:1px solid #e4e2dc}
          .hben{flex:1 1 0;display:flex;flex-direction:column;align-items:center;justify-content:center;
                gap:6px;padding:12px 6px;text-align:center}
          .hben + .hben{border-top:1px solid #e4e2dc}
          .hben svg{width:22px;height:22px;display:block;color:#d1b66c;flex:0 0 auto}
          .h .hbent{font-size:12px;line-height:1.25;color:#1a1a1a;font-weight:700}

          .hoffer{width:296px;margin:28px auto 0}
          .h .hoh{font-size:17px;font-weight:900;text-transform:uppercase;letter-spacing:0.6px;
                  margin-bottom:32px}
          .hplan{position:relative;width:100%;background:#ffffff;border:1px solid #e4e2dc;border-radius:8px;
                 padding:16px;cursor:pointer;transition:border-color .15s ease,background .15s ease;overflow:hidden}
          .hplan + .hplan{margin-top:10px}
          .hplanTop{display:flex;align-items:center;gap:10px}
          .hradio{width:18px;height:18px;border-radius:50%;border:2px solid #b9b5a8;flex:0 0 auto;
                  display:flex;align-items:center;justify-content:center}
          .hradio i{display:none;width:8px;height:8px;border-radius:50%;background:#a51b17}
          .hplanName{font-size:17px;font-weight:900;letter-spacing:-0.2px}
          .hsave{font-size:11px;font-weight:900;text-transform:uppercase;letter-spacing:0.4px;
                 background:#f9f6ed;border:1px solid #d1b66c;color:#8e7940;padding:3px 9px;border-radius:999px;white-space:nowrap}
          .hpriceRow{display:flex;align-items:baseline;gap:8px;margin-top:10px}
          .hprice{font-size:30px;font-weight:900;letter-spacing:-0.7px}
          .hwas{font-size:15px;color:#6b6b6b;text-decoration:line-through;font-weight:500}
          .hper{font-size:14px;color:#6b6b6b;font-weight:500}
          .hmeta{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-top:6px}
          .hmeta span{font-size:12px;color:#6b6b6b;font-weight:500}
          .hmeta .hday{font-weight:900;color:#1a1a1a;white-space:nowrap}
          .hrule{height:1px;background:#e4e2dc;margin:14px 0}
          .hlist{display:flex;flex-direction:column;gap:9px}
          .h .hli{display:flex;gap:9px;align-items:flex-start;font-size:14px;line-height:1.35;font-weight:500}
          .h .hli svg{width:14px;height:14px;flex:0 0 auto;margin-top:2px;color:#3f7d47}
          .hribbon{position:absolute;top:0;right:0;background:#a51b17;color:#ffffff;border-bottom-left-radius:8px;
                   font-size:11px;font-weight:900;letter-spacing:0.5px;text-transform:uppercase;padding:5px 10px}
          .honce{display:block;text-align:center;margin:16px 0 0;font-size:15px;font-weight:700;
                 color:#1a1a1a;text-decoration:underline;text-underline-offset:3px}

          .hstock{display:flex;align-items:center;justify-content:center;gap:5px;margin:18px auto 0;font-size:14px}
          .hdot{width:8px;height:8px;border-radius:50%;background:#3f7d47;display:block;flex:0 0 auto}
          .hstock b{font-weight:900}
          .hstock span{color:#6b6b6b;font-weight:500}

          /* ONE CTA PER PLAN, and only the active one is displayed. The page
             used to have a single anchor whose href was recomputed by the dc
             runtime. That cannot survive `publish-landing-page`, which strips
             every script: the exported anchor would freeze on whichever plan
             was default and the other plan became unbuyable. Rendering both and
             switching with a class works identically under the runtime (dc sets
             the class) and after export (ui.js sets it). */
          .hcta{width:296px;height:60px;margin:12px auto 0;background:#a51b17;color:#ffffff;border-radius:8px;
                display:none;align-items:center;justify-content:center;gap:10px;
                font-size:16px;font-weight:900;text-transform:uppercase;letter-spacing:0.6px;
                text-decoration:none;cursor:pointer}
          .hcta.on{display:flex}
          .hcta .hctaDot{width:4px;height:4px;border-radius:50%;background:rgba(255,255,255,0.6)}
          .hcta .hctaWas{font-weight:500;opacity:0.65;text-decoration:line-through}

          .htrust{width:296px;margin:16px auto 4px;display:flex;flex-wrap:wrap;
                  align-items:center;justify-content:center;gap:10px 16px}
          .htrustI{display:flex;align-items:center;gap:6px;font-size:12px;color:#1a1a1a;white-space:nowrap;font-weight:700}
          .htrustI svg{width:14px;height:14px;color:#1a1a1a;flex:0 0 auto}
          .htrustSep{width:1px;height:14px;background:#e4e2dc;flex:0 0 auto}

          .hacc{width:328px;margin:28px auto 0;border-top:1px solid #e4e2dc}
          .haccRow{border-bottom:1px solid #e4e2dc}
          .haccBtn{width:100%;height:56px;background:none;border:0;padding:0;margin:0;font:inherit;color:inherit;
                   display:flex;align-items:center;justify-content:space-between;cursor:pointer;text-align:left;
                   -webkit-appearance:none;appearance:none}
          .haccBtn span.haccL{font-size:15px;font-weight:700}
          .haccIco{width:22px;height:22px;border-radius:50%;border:1px solid #b9b5a8;flex:0 0 auto;position:relative}
          .haccIco::before,.haccIco::after{content:"";position:absolute;background:#1a1a1a;
                   left:50%;top:50%;transform:translate(-50%,-50%)}
          .haccIco::before{width:9px;height:1.5px}
          .haccIco::after{width:1.5px;height:9px}
          .haccBtn[aria-expanded="true"] .haccIco::after{display:none}
          .haccBtn.on .haccIco::after{display:none}
          /* EVERY ANSWER IS IN THE DOM, hidden by class rather than omitted.
             It used to sit inside `sc-if value="{{ f.open }}"`, so with nothing
             open by default the export contained five accordion buttons and
             ZERO answer text - five Q&As silently dropped off the page, the
             shipping and pause-or-cancel objections among them. Never gate
             copy on runtime state in a page that gets exported. */
          .h .haccA{margin:0;padding:0 0 16px;font-size:14px;line-height:1.55;color:#6b6b6b;font-weight:500;
                    display:none}
          .h .haccA.on{display:block}

          .h > input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
          .hslide[data-i="1"]{opacity:1;z-index:1}
          .hnav2[data-i="1"]{display:flex}
          .hthumb[data-i="1"]{box-shadow:inset 0 0 0 2px #a51b17}
          .h:has(input:checked) .hslide[data-i="1"]{opacity:0;z-index:auto}
          .h:has(input:checked) .hnav2[data-i="1"]{display:none}
          .h:has(input:checked) .hthumb[data-i="1"]{box-shadow:inset 0 0 0 1px #e4e2dc}
          #g1:checked ~ .hin .hslide[data-i="1"],#g2:checked ~ .hin .hslide[data-i="2"],
          #g3:checked ~ .hin .hslide[data-i="3"],#g4:checked ~ .hin .hslide[data-i="4"],
          #g5:checked ~ .hin .hslide[data-i="5"]{opacity:1;z-index:1}
          #g1:checked ~ .hin .hnav2[data-i="1"],#g2:checked ~ .hin .hnav2[data-i="2"],
          #g3:checked ~ .hin .hnav2[data-i="3"],#g4:checked ~ .hin .hnav2[data-i="4"],
          #g5:checked ~ .hin .hnav2[data-i="5"]{display:flex}
          #g1:checked ~ .hin .hthumb[data-i="1"],#g2:checked ~ .hin .hthumb[data-i="2"],
          #g3:checked ~ .hin .hthumb[data-i="3"],#g4:checked ~ .hin .hthumb[data-i="4"],
          #g5:checked ~ .hin .hthumb[data-i="5"]{box-shadow:inset 0 0 0 2px #a51b17}

          .hplan.on{border-color:#a51b17;background:#fdf6f5}
          .hplan.on .hradio{border-color:#a51b17}
          .hplan.on .hradio i{display:block}

          @media (min-width:768px){
            .hin{width:100%;max-width:720px;padding:0 24px}
            .hnav{padding:0}
            .hlogo{height:26px}
            .hgal,.hcopyrow,.hoffer,.hcta,.htrust,.hacc{width:100%}
            .hgal{flex-direction:column-reverse;gap:10px}
            .hmain{width:100%;height:auto;aspect-ratio:1/1}
            .hrail{width:100%;height:auto;flex-direction:row;gap:10px}
            .hthumb{flex:1 1 0;aspect-ratio:1/1}
            .hcopyrow{flex-direction:column;gap:20px}
            .hcopy{width:100%}
            .hbens{width:100%;flex-direction:row;border-left:0;border-right:0;
                   border-top:1px solid #e4e2dc;border-bottom:1px solid #e4e2dc}
            .hben + .hben{border-top:0;border-left:1px solid #e4e2dc}
            .h .htitle{font-size:34px}
          }

          @media (min-width:1024px){
            .hin{max-width:1120px;padding:0 32px}
            /* align-items:flex-start is LOAD-BEARING - it is what leaves the
               gallery column shorter than its container, which is the only
               reason the sticky rule below has anywhere to stick. Switching
               this to the default `stretch` disables sticky silently. */
            .hsplit{display:flex;gap:56px;align-items:flex-start;margin-top:8px}
            /* The buy column is far taller than the gallery - copy, benefits,
               two plan cards, CTA, trust row and a five-row FAQ against one
               square and a thumb rail. Left static, the gallery ran out about a
               third of the way down and left dead white beside the price, and
               the product scrolled away exactly when the visitor reached the
               decision. Pinned, it stays next to the plans and the CTA for the
               whole column. Needs no `overflow` other than `visible` on any
               ancestor - see HeroDesktopSticky.md. */
            .hsplit > .hgal{flex:1 1 52%;min-width:0;margin:0;
                            position:sticky;top:24px;align-self:flex-start}
            .hsplit > .hbuy{flex:1 1 48%;min-width:0}
            .hcopyrow,.hoffer,.hcta,.htrust,.hacc{width:100%;margin-left:0;margin-right:0}
            .hcopyrow{margin-top:0}
            .h .htitle{font-size:38px}
          }
        
.xs1 { margin: 0px; }
/* ---------------------------------------------------------------------------
   SELF-HOSTED LATO. The Claude Design source pulls Lato from
   fonts.googleapis.com, which is right for the editor and wrong for the
   deployed page twice over: the exporter strips that <link> as a runtime host,
   and the hardened CSP is style-src 'self' / font-src 'self', so it could not
   load even if it survived. Without these faces the whole page silently falls
   back to Helvetica - measured: zero webfonts loaded, and the hero tagline
   rewrapped from two lines to three.

   Latin subset only, the three real Lato weights. The stylesheet also asks for
   500 in places; Lato has no 500 and Google serves 400 for it, so the browser
   picks 400 here exactly as it did in the preview.

   These rules are appended to assets/page.css by build.sh AFTER export,
   because export regenerates that file every time.
   --------------------------------------------------------------------------- */
@font-face{font-family:'Lato';font-style:normal;font-weight:400;font-display:swap;
           src:url("https://pibenlahiiypwzvsnmym.supabase.co/storage/v1/object/public/aimd-assets/dragon-pain-relief/native-imports/00a187a6-354d-4507-889d-274cc51fd672/20260924T184725Z/d4ae5188a65370ecfe28f42293bbee8297cfd5712c6aadfdb270d48f2bcd88b0.woff2") format('woff2')}
@font-face{font-family:'Lato';font-style:normal;font-weight:700;font-display:swap;
           src:url("https://pibenlahiiypwzvsnmym.supabase.co/storage/v1/object/public/aimd-assets/dragon-pain-relief/native-imports/00a187a6-354d-4507-889d-274cc51fd672/20260924T184725Z/7a7ce1a34f3e9944fe88fc61abbc93b6db383afa2b90815fd7ccea456fbce4e5.woff2") format('woff2')}
@font-face{font-family:'Lato';font-style:normal;font-weight:900;font-display:swap;
           src:url("https://pibenlahiiypwzvsnmym.supabase.co/storage/v1/object/public/aimd-assets/dragon-pain-relief/native-imports/00a187a6-354d-4507-889d-274cc51fd672/20260924T184725Z/bd9a6192274f8f2f3ce31cd3d2cae5ebe32e2fa86fc7c4f60a3c28556e496d56.woff2") format('woff2')}
