/* Shondalai Professional — shell and EasyCommerce SPA skin. */
body{background:var(--ec-page);color:var(--ec-ink);font-family:var(--ec-font-body)}
.ts-container{max-width:var(--ec-cw)}
.ts-topbar{background:#101a35;color:#fff;border:0}.ts-topbar__inner{min-height:34px;font-size:.72rem}.ts-topbar__announcement{font-weight:600}.ts-topbar a{color:#c9d8ff}
.ts-header{background:color-mix(in srgb,var(--ec-surface) 96%,transparent);border-bottom:1px solid var(--ec-border);box-shadow:none}
.ts-header__inner{min-height:76px}.ts-brand,.ts-brand__name{font-family:var(--ec-font-heading);font-weight:700;letter-spacing:-.04em;color:var(--ec-ink)}.ts-brand__name{font-size:1.25rem}
.ts-nav a,.ts-nav button{font-weight:600;font-size:.86rem}.ts-nav a:hover,.ts-nav a[aria-current="page"]{color:var(--ec-brand)}
.ts-header-actions a,.ts-header-actions button{border-color:var(--ec-border)}.ts-header-actions a:hover,.ts-header-actions button:hover{background:var(--ec-surface-soft);border-color:var(--ec-brand)}
.ts-btn{border-radius:var(--ec-radius-sm);font-weight:700;box-shadow:none}.ts-shell:not(.ts-shell--storefront) .ts-main{min-width:0;padding:clamp(18px,2.4vw,34px);border:1px solid #d9e2ee;border-radius:var(--ec-radius-lg);background:linear-gradient(145deg,rgb(255 255 255 / .82),rgb(239 244 250 / .94));box-shadow:0 18px 48px rgb(16 26 53 / .065)}.ts-footer{position:relative;width:100%;max-width:var(--ec-cw);margin-inline:auto;overflow:hidden;border:0;background:transparent;color:#fff}.ts-footer:before{content:"";position:absolute;z-index:0;inset:0 var(--ec-gut);background:radial-gradient(circle at 12% 0%,rgb(var(--ec-brand-rgb) / .2),transparent 32%),linear-gradient(135deg,#0b1630 0%,#101f43 58%,#173469 100%);box-shadow:0 -12px 45px rgb(16 26 53 / .08)}.ts-footer:after{content:"";position:absolute;z-index:1;inset:0 var(--ec-gut) auto;height:3px;background:linear-gradient(90deg,var(--ec-brand),#7ca0ff,var(--ec-accent))}.ts-footer>.ts-container{position:relative;z-index:2;width:100%;max-width:none;padding-inline:var(--ec-gut)}.ts-footer__cols,.ts-footer__bottom,.ts-footer__main{margin-inline:32px}.ts-footer h5,.ts-footer .ts-module__title,.ts-footer .ts-footer__col h5{color:#e8efff}.ts-footer p,.ts-footer__blurb{color:#aebbd4}.ts-footer a{color:#b9c7df;transition:color var(--ec-dur-1),transform var(--ec-dur-1)}.ts-footer li a{display:inline-block}.ts-footer a:hover{color:#fff;transform:translateX(2px)}.ts-footer__brand .ts-brand,.ts-footer__brand .ts-brand__text{color:#78a0ff}.ts-footer__bottom{border-color:#324464;color:#91a0bc}.ts-footer .ts-footer__legal{color:#9eacc5}.ts-footer__pay li{border-color:#415475;background:rgb(255 255 255 / .06);color:#cbd6e9}.ts-shell--storefront{min-height:0;padding-block:0}.ts-shell--storefront+.ts-footer{border-top:0}.ts-shell--storefront+.ts-footer:before,.ts-shell--storefront+.ts-footer:after{inset-inline:0}
.sp-home{margin-inline:calc(var(--ec-gutter) * -1)}
.sp-hero{min-height:680px;padding:clamp(70px,8vw,120px) var(--ec-gutter);display:grid;grid-template-columns:minmax(0,1fr) minmax(460px,.9fr);gap:clamp(40px,7vw,110px);align-items:center;background:linear-gradient(135deg,#fbfcff 0%,#edf3ff 100%);overflow:hidden}
.sp-eyebrow{display:flex;gap:.55rem;align-items:center;color:var(--ec-brand);font-size:.72rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase}.sp-hero h1{font-size:clamp(3.5rem,6.2vw,6.8rem);line-height:.93;letter-spacing:-.075em;margin:.9rem 0 1.6rem;max-width:850px}.sp-hero__desc{font-size:clamp(1rem,1.35vw,1.25rem);line-height:1.75;color:var(--ec-ink-muted);max-width:660px}.sp-actions{display:flex;gap:.8rem;align-items:center;margin-top:2rem}.sp-btn-primary{display:inline-flex;align-items:center;gap:1.1rem;background:var(--ec-brand);color:#fff!important;padding:.9rem 1.25rem;text-decoration:none}.sp-btn-primary:hover{background:#2353c7;transform:translateY(-1px)}.sp-btn-secondary{padding:.85rem 1rem;border:1px solid var(--ec-border);border-radius:var(--ec-radius-sm);background:#fff;color:var(--ec-ink);font-weight:700;text-decoration:none}
.sp-proof{display:flex;gap:1.6rem;margin-top:3rem;padding-top:1.4rem;border-top:1px solid var(--ec-border)}.sp-proof span{display:flex;flex-direction:column;color:var(--ec-ink-muted);font-size:.72rem}.sp-proof b{font:700 1.45rem var(--ec-font-heading);color:var(--ec-ink)}
.sp-hero__visual{position:relative}.sp-admin{background:#fff;border:1px solid #d5ddeb;box-shadow:var(--ec-shadow-3);transform:rotate(1deg);border-radius:var(--ec-radius-md);overflow:hidden}.sp-admin__bar{height:40px;background:#e9edf4;display:flex;align-items:center;gap:5px;padding:0 13px;color:#7d899e;font-size:.65rem}.sp-admin__bar i{width:6px;height:6px;border-radius:50%;background:#b5becd}.sp-admin__bar i:first-child{background:var(--ec-accent)}.sp-admin__bar span{margin-left:auto}.sp-admin__body{display:flex;min-height:430px}.sp-admin__body>aside{width:72px;background:#101a35;padding:17px}.sp-admin__body>aside b{display:grid;place-items:center;width:38px;height:38px;border-radius:9px;background:var(--ec-accent);color:#fff}.sp-admin__body>aside i{display:block;height:5px;border-radius:4px;background:#41506d;margin-top:24px}.sp-admin__body>main{flex:1;padding:28px}.sp-admin__body main header{display:flex;justify-content:space-between}.sp-admin__body main header span{width:72px;height:20px;background:#edf0f5}.sp-admin__stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:35px 0}.sp-admin__stats i{height:68px;border:1px solid var(--ec-border);border-radius:6px}.sp-admin__chart{height:190px;display:flex;align-items:end;gap:8px;border-bottom:1px solid var(--ec-border)}.sp-admin__chart i{height:var(--h);flex:1;background:var(--ec-brand);border-radius:3px 3px 0 0}.sp-float{position:absolute;background:#fff;border:1px solid var(--ec-border);box-shadow:var(--ec-shadow-2);padding:.9rem 1rem;border-radius:10px}.sp-float small{display:block;font-size:.58rem;color:var(--ec-ink-muted)}.sp-float b{font-size:1.1rem}.sp-float em{color:var(--ec-success);font-size:.7rem}.sp-float--revenue{left:-34px;bottom:38px}.sp-float--license{right:-20px;top:40px;display:flex;align-items:center;gap:.65rem}.sp-float--license span{display:grid;place-items:center;width:28px;height:28px;border-radius:50%;background:#dcf8ec;color:var(--ec-success)}
.sp-trust{padding:1.8rem var(--ec-gutter);background:linear-gradient(90deg,#f4f7fb 0%,#edf2f8 50%,#f4f7fb 100%);border-block:1px solid #dbe3ee;text-align:center}.sp-trust>span{font-size:.72rem;color:#748096}.sp-trust>div{display:flex;justify-content:space-around;gap:1.5rem;margin-top:1.1rem}.sp-trust b{font-size:.78rem;letter-spacing:.04em;color:#536078}
.sp-section{padding:var(--ec-section-space) var(--ec-gutter)}.sp-products{background:radial-gradient(circle at 88% 8%,rgb(16 26 53 / .065),transparent 36%),linear-gradient(145deg,#f2f5f9 0%,#e5ebf3 100%);border-block:1px solid #d1dae7}.sp-section__head{display:flex;justify-content:space-between;align-items:end;gap:3rem;margin-bottom:3rem}.sp-section__head small,.sp-easycommerce small,.sp-cta small{color:var(--ec-brand);font-weight:800;letter-spacing:.1em}.sp-section__head h2,.sp-easycommerce h2,.sp-cta h2{font-size:clamp(2.5rem,4.4vw,4.6rem);line-height:1.04;letter-spacing:-.06em;margin:.65rem 0 0}.sp-section__head p{max-width:490px;color:var(--ec-ink-muted);line-height:1.75}.sp-product-grid{display:grid;grid-template-columns:repeat(var(--ec-grid,3),minmax(0,1fr));gap:1.25rem}.sp-text-link{display:flex;width:max-content;gap:1rem;margin:2.5rem auto 0;color:var(--ec-ink);font-weight:700;text-decoration:none;border-bottom:1px solid}
.ts-pcard{display:flex;min-width:0;flex-direction:column;background:#fff;border:1px solid var(--ec-border);border-radius:var(--ec-radius-md) var(--ec-radius-md) 0 0;overflow:hidden;box-shadow:none;transition:transform var(--ec-dur-2),box-shadow var(--ec-dur-2)}.ts-pcard:hover{transform:translateY(-5px);box-shadow:var(--ec-shadow-2)}.ts-pcard__media{position:relative;display:block;width:100%;aspect-ratio:16/9;overflow:hidden;background:var(--ec-surface-soft);text-decoration:none}.ts-pcard__media img{display:block;width:100%;height:100%;max-width:none;object-fit:cover;object-position:center top}.ts-pcard__placeholder{position:absolute;inset:0;display:grid;place-items:center;font:700 3rem var(--ec-font-heading);color:var(--ec-brand)}.ts-pcard__body{display:flex;flex:1;min-width:0;flex-direction:column;padding:1.65rem}.ts-pcard__meta{display:flex;align-items:center;justify-content:space-between;gap:1rem}.ts-pcard__category{color:var(--ec-ink-muted);font-size:.72rem}.ts-pcard__price{margin:0;white-space:nowrap;font-size:.72rem}.ts-pcard__title{margin:.8rem 0 .7rem;font-size:clamp(1.35rem,1.7vw,1.8rem);line-height:1.15}.ts-pcard__title a{color:inherit;text-decoration:none}.ts-pcard__summary{min-height:3.5em;margin:0;color:var(--ec-ink-muted);font-size:.86rem;line-height:1.65}.ts-pcard__amount{color:var(--ec-brand);font-weight:800}.ts-pcard__features{display:flex;flex-wrap:wrap;gap:.45rem 1rem;min-height:2.2rem;margin:auto 0 1.25rem;padding:1.7rem 0 0;list-style:none;color:#536079;font-size:.68rem}.ts-pcard__features li{display:flex;align-items:center;gap:.35rem}.ts-pcard__features li span{color:var(--ec-success);font-weight:800}.ts-pcard__learn{display:flex;align-items:center;justify-content:space-between;padding-top:1rem;border-top:1px solid var(--ec-border);color:var(--ec-ink);font-size:.76rem;font-weight:800;text-decoration:none}.ts-pcard__learn:hover{color:var(--ec-brand)}.ts-pcard__stock{display:none}.ts-pcard__add{border-radius:8px;background:var(--ec-brand);color:#fff;border:0}
.sp-easycommerce{padding:var(--ec-section-space) var(--ec-gutter);background:radial-gradient(circle at 8% 12%,rgb(var(--ec-brand-rgb) / .11),transparent 30%),linear-gradient(135deg,#edf2ff 0%,#dfe8fb 100%);border-block:1px solid #cfdaef;display:grid;grid-template-columns:.75fr 1.25fr;gap:7vw;align-items:center}.sp-easycommerce p{color:var(--ec-ink-muted);line-height:1.75}.sp-easycommerce ul{list-style:none;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:.7rem;margin:2rem 0}.sp-easycommerce li{font-size:.86rem}.sp-ec-showcase{position:relative;margin:0;border:1px solid #c4d1e8;border-radius:var(--ec-radius-lg);background:#f7faff;box-shadow:0 28px 70px rgb(16 26 53 / .18);overflow:visible}.sp-ec-showcase img{display:block;width:100%;aspect-ratio:3/2;object-fit:cover;border-radius:inherit}.sp-ec-showcase figcaption{position:absolute;right:clamp(12px,2vw,28px);bottom:clamp(-18px,-1.3vw,-10px);padding:.85rem 1rem;border-radius:8px;background:#101a35;color:#fff;font-size:.7rem;font-weight:800;box-shadow:0 12px 28px rgb(16 26 53 / .22)}
.sp-slot{padding:var(--ec-section-space) var(--ec-gutter);background:#fff}.sp-slot--soft{background:var(--ec-surface-soft)}.sp-cta{text-align:center;padding:var(--ec-section-space) var(--ec-gutter);background:linear-gradient(135deg,#101a35,#243f82);color:#fff}.sp-cta h2{color:#fff}.sp-cta p{color:#c1cbe0;max-width:700px;margin:1.2rem auto 2rem}.sp-cta .sp-btn-primary{background:var(--ec-accent);color:#fff}
/* EasyCommerce SPA: the product layout engine owns content; this layer owns the visual system. */
#ec-store-root{--background:218 33% 98%;--foreground:224 43% 16%;--card:0 0% 100%;--card-foreground:224 43% 16%;--primary:222 80% 55%;--primary-foreground:0 0% 100%;--secondary:218 65% 96%;--secondary-foreground:224 43% 16%;--muted:218 24% 94%;--muted-foreground:220 13% 46%;--accent:12 87% 59%;--accent-foreground:0 0% 100%;--border:220 22% 89%;--ring:222 80% 55%;font-family:var(--ec-font-body)}
#ec-store-root h1,#ec-store-root h2,#ec-store-root h3{font-family:var(--ec-font-heading);letter-spacing:-.045em}
#ec-store-root [data-section-type]{scroll-margin-top:96px}
#ec-store-root [data-section-type="hero"],#ec-store-root [data-section-type="product-hero"]{background:linear-gradient(135deg,#fbfcff,#edf3ff)}
#ec-store-root [data-section-type="feature-grid"] [class*="grid"]>*,#ec-store-root [data-section-type="use-cases"] [class*="grid"]>*,#ec-store-root [data-section-type="faq"] [class*="border"]{border-color:var(--ec-border);border-radius:var(--ec-radius-md)}
#ec-store-root [data-section-type="statistics"]{background:#101a35;color:#fff}
#ec-store-root [data-section-type="testimonials"]{background:#eaf0ff}
#ec-store-root [data-section-type="pricing-purchase"],#ec-store-root [data-section-type="pricing-table"]{background:#f1f4f9}
#ec-store-root button,#ec-store-root [role="button"]{border-radius:8px}
@media(max-width:1024px){.sp-hero{grid-template-columns:1fr}.sp-hero__visual{max-width:720px}.sp-product-grid{grid-template-columns:repeat(2,1fr)}.sp-easycommerce{grid-template-columns:1fr}.sp-float--license{right:8px}}
@media(max-width:640px){.sp-home{margin-inline:calc(var(--ec-gutter) * -1)}.sp-hero{padding:64px var(--ec-gutter)}.sp-hero h1{font-size:3.5rem}.sp-actions{align-items:flex-start;flex-direction:column}.sp-proof{gap:1rem;flex-wrap:wrap}.sp-admin__body{min-height:330px}.sp-float{display:none}.sp-trust>div{flex-wrap:wrap}.sp-section__head{align-items:flex-start;flex-direction:column}.sp-product-grid{grid-template-columns:1fr}.sp-easycommerce ul{grid-template-columns:1fr}.sp-ec-showcase figcaption{position:static;margin:.75rem;text-align:center}}

/* ------------------------------------------------------------------ *
 * Flush content shell + container-width chrome (requested).
 * ------------------------------------------------------------------ */
.ts-shell:not(.ts-shell--storefront) {
    /* Top stays flush (the header meets the content; .ts-main and the
       sidebars carry their own small top inset). Bottom keeps the content
       clear of the footer band, which is a body-level sibling after the
       shell, so content never butts straight against it. */
    padding-block: 0 clamp(2rem, 4vw, 3.5rem);
    display: flex;
    flex-direction: column;
}

/* The main region runs from the header to the footer with no card and no
   empty band. A small top inset keeps the content clear of the menu. */
.ts-shell:not(.ts-shell--storefront) .ts-main {
    flex: 1 0 auto;
    min-width: 0;
    padding: clamp(1rem, 2vw, 1.5rem) 0 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
}

/* Escape the container gutter (the sp-home idiom) so the main region lines up
   with the full layout box, exactly like the home page.
   Done PER SIDE: a side may only escape when no sidebar sits there, otherwise
   main would spill out of its grid track and overlap the sidebar card. So a
   page with a right sidebar still escapes on the left (keeping its left edge
   aligned with every other page) but stays inside its track on the right. */
.ts-shell:not(.ts-shell--storefront) .ts-row:not(:has(.ts-pos-sidebar-left)) .ts-pos-main > .ts-main {
    margin-left: calc(var(--ec-gut) * -1);
}

.ts-shell:not(.ts-shell--storefront) .ts-row:not(:has(.ts-pos-sidebar-right)) .ts-pos-main > .ts-main {
    margin-right: calc(var(--ec-gut) * -1);
}

/* A sidebar is the outermost column on its side, so it has to escape the
   gutter there too. Without this main meets the layout box on the left while
   the sidebar stops one gutter short on the right, leaving a lopsided margin
   against the header/footer bands. Both extend into the shell's own padding,
   so nothing overflows the shell and no horizontal scrollbar appears. */
.ts-shell:not(.ts-shell--storefront) .ts-pos-sidebar-right {
    margin-right: calc(var(--ec-gut) * -1);
}

.ts-shell:not(.ts-shell--storefront) .ts-pos-sidebar-left {
    margin-left: calc(var(--ec-gut) * -1);
}

/* The sidebars are content too. The shell is flush and only .ts-main carries
   the top inset above, so without this a sidebar module butts straight against
   the header while the component sits 24px lower. Mirror the same inset (same
   clamp) to keep every column in the content row on one baseline. */
.ts-shell:not(.ts-shell--storefront) .ts-pos-sidebar-left,
.ts-shell:not(.ts-shell--storefront) .ts-pos-sidebar-right {
    padding-top: clamp(1rem, 2vw, 1.5rem);
}

/* One boxed column at the layout width (--ec-cw) on every page: the header +
   topbar bands, the storefront sections and the footer band all span the full
   box, and their content keeps the standard side gutter. Tracks the layout
   setting automatically (edge-to-edge when it is set to full width). */
.ts-topbar,
.ts-header {
    max-width: var(--ec-cw);
    margin-inline: auto;
}

/* Footer band fills the full box too, so it lines up with the header and the
   storefront rather than sitting inset. */
.ts-footer::before,
.ts-footer::after {
    inset-inline: 0;
}

/* Keep the positioned header above later page chrome (for example the CjForum
   sticky toolbar) so its menus paint above content but below modals and toasts.
   Do not add filters here: they would contain the fixed mobile navigation. */
.ts-header {
    position: relative;
    z-index: 950;
}

/* ------------------------------------------------------------------ *
 * Footer payment methods: a single inline row of brand icons. The text
 * label stays in the DOM as an accessible fallback (moved off-screen).
 * ------------------------------------------------------------------ */
.ts-footer .ts-footer__pay {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    width: auto;
    grid-template-columns: none;
    margin: 0;
    padding: 0;
    list-style: none;
}

.ts-footer__pay li {
    width: 40px;
    height: 26px;
    padding: 0;
    border: 0;
    border-radius: 4px;
    background: transparent center / contain no-repeat;
    box-shadow: 0 1px 2px rgb(0 0 0 / .25);
    text-indent: 200%;
    white-space: nowrap;
    overflow: hidden;
}

.ts-footer__pay li[data-pay="visa"]       { background-image: url(../images/payments/visa.svg); }
.ts-footer__pay li[data-pay="mastercard"] { background-image: url(../images/payments/mastercard.svg); }
.ts-footer__pay li[data-pay="amex"]       { background-image: url(../images/payments/amex.svg); }
.ts-footer__pay li[data-pay="discover"]   { background-image: url(../images/payments/discover.svg); }
.ts-footer__pay li[data-pay="paypal"]     { background-image: url(../images/payments/paypal.svg); }
.ts-footer__pay li[data-pay="stripe"]     { background-image: url(../images/payments/stripe.svg); }

/* ------------------------------------------------------------------ *
 * Product page presentation. Two goals:
 *   1. FLUID width - EasyCommerce sections cap content at .container-custom
 *      (1280px); on the shondalai shell that reads as narrow / over-padded.
 *      Fill the container at whatever width it is (1600, 1440, ...).
 *   2. CONNECTED + REFINED, like the home page - header, component and footer
 *      flow as one continuous surface (no floating card, no gaps) on one calm
 *      background. Neutralise EC's tint bands + the template's dark stats band;
 *      rein in text/split sections so full width does not read sparse; and lift
 *      every card with one consistent soft shadow.
 * Scoped to .product-layout so shop/category views keep their own widths;
 * inner text blocks keep their max-w-* so copy stays readable.
 * ------------------------------------------------------------------ */
.ts-shell .product-layout,
.ts-shell .product-layout .product-layout__main,
.ts-shell .product-layout .container-custom {
    max-width: 100%;
}

/* Connect header -> component -> footer flush, like the home page: no floating
   card, no gaps. The non-storefront .ts-main adds a 24px pad above main; drop it
   only for product pages (via :has) so the hero meets the header. */
.ts-shell:not(.ts-shell--storefront) .ts-main:has(.product-layout) {
    padding-top: 0 !important;
}

.ts-shell .product-layout {
    background: transparent;
    /* !important overrides the prior deployed panel rule + EC preflight so no
       card outline remains and the component reads flush. */
    border: 0 !important;
    border-radius: 0;
    box-shadow: none;
    margin: 0;
}

/* Neutralise EC's tint overlays and the template's dark statistics band so
   every section blends into the continuous flow. */
.ts-shell .product-layout [class*="bg-muted"],
.ts-shell .product-layout .bg-background {
    background-color: transparent !important;
}

.ts-shell .product-layout [data-section-type="statistics"] {
    color: var(--ec-fg) !important;
}

/* Every product-layout section fills the container for one consistent width.
   EasyCommerce caps genuine prose itself (description -> max-w-4xl,
   content-block -> max-w-4xl/5xl, cta content -> max-w-3xl), so no per-section
   width cap is applied here - that only made the page read wide/narrow/wide. */

/* Calm the very airy 96px section padding. */
.ts-shell .product-layout .py-16 {
    padding-top: 4rem;
    padding-bottom: 4rem;
}

/* Lift every card with one consistent soft shadow + refined border, so the
   page reads as premium cards on a calm background rather than flat blocks. */
.ts-shell .product-layout .bg-card {
    border-color: #e6ecf5 !important;
    box-shadow: 0 10px 30px rgb(16 26 53 / .06) !important;
}

/* FAQ accordion rows stay lighter so a stack of them does not feel heavy. */
.ts-shell .product-layout [data-section-type="faq"] .bg-card {
    box-shadow: 0 4px 14px rgb(16 26 53 / .04) !important;
}

/* ------------------------------------------------------------------ *
 * Product sections: per-block-type pass. Appended after the fluid +
 * connected baseline above; that block stays authoritative for widths
 * and flushness, this one owns each section's voice. Lives in skin.css
 * because the SPA product pages load the template preset (skin.css) -
 * store.css is the PHP storefront fallback and is only enqueued for
 * the storefront-home takeover.
 *
 * Coverage map for the 33 section types:
 *   bespoke ........ hero, statistics, feature-grid, image-text-split,
 *                    media-showcase, steps, faq, tabs-section,
 *                    pricing-purchase, pricing-table, cta-block,
 *                    testimonials, sticky-purchase-bar, changelog
 *   card family .... use-cases, upsell-crosssell, related-resources,
 *   (card idiom +    resources, bundle-contents, compatibility,
 *   hover lift)      instructor, curriculum, security-compliance,
 *                    shipping-info, quickstart, contact-quote, reviews
 *   table family ... comparison-table, specs-table
 *   prose family ... description, content-block, custom-html
 *   strip .......... brand-logos (keeps its hairline border-y band)
 *   every type ..... heading voice, button voice, surface re-provides
 *                    and the dark completion at the end of this block
 *
 * Specificity: EC compiles utilities as ":is(#ec-store-root,...) .u"
 * (1,1,0), so rules here carry the mount id and outrank utilities
 * without !important. !important appears only where a rule must beat
 * an !important neutralisation in the baseline block (surface
 * re-provides, card chrome) or pin a hard measure cap.
 * ------------------------------------------------------------------ */
#ec-store-root .product-layout {
    /* Brand ink for large figures, links and motifs; the dark completion
       below lifts it to the preset accentDark for contrast on navy. */
    --sp-brand-ink: var(--ec-brand);
}

/* Uniform vertical rhythm. The baseline ".py-16" calm loses to the
   scoped lg:py-24 utility at large screens; carrying the mount id here
   wins at every breakpoint and tracks the template rhythm token. */
#ec-store-root .product-layout [data-section-type] > section.py-16 {
    padding-top: var(--ec-sect-y);
    padding-bottom: var(--ec-sect-y);
}

/* ---- heading voice (every type) ---------------------------------- */
#ec-store-root .product-layout [data-section-type] h2 {
    font-weight: 700;
    letter-spacing: -0.05em;
}

/* The storefront eyebrow-rule motif, restated as a short brand bar
   under centred section heads. */
#ec-store-root .product-layout [data-section-type] .text-center > h2::after,
#ec-store-root .product-layout [data-section-type] h2.text-center::after {
    content: "";
    display: block;
    width: 2.5rem;
    height: 3px;
    margin: 1.1rem auto 0;
    border-radius: 2px;
    background: var(--sp-brand-ink);
}

/* On the CTA band the bar reads from the panel ink, so it stays legible
   on navy, on the solid variant and on the plain minimal variant. */
#ec-store-root .product-layout [data-section-type="cta-block"] .text-center > h2::after {
    background: color-mix(in srgb, currentColor 40%, transparent);
}

/* ---- surface re-provides (every type) ----------------------------- */
/* The baseline flattens every "bg-muted*" and ".bg-background" to keep
   the page continuous, which also blanks rest-state control surfaces
   (pill trays, form panels, zebra rows, progress tracks). Re-provide
   those on non-section elements. The class-start / leading-space match
   deliberately skips hover:/focus: variants, so hover-only surfaces
   stay flat. */
#ec-store-root .product-layout [data-section-type] :is([class^="bg-muted"], [class*=" bg-muted"]):not(section) {
    background-color: color-mix(in srgb, var(--ec-surface-soft) 62%, transparent) !important;
}

/* Active pill and carousel arrow surfaces carry exact .bg-background. */
#ec-store-root .product-layout [data-section-type] :is(button, [role="button"]).bg-background {
    background-color: var(--ec-surface) !important;
    box-shadow: var(--ec-shadow-1);
}

/* Form fields sit on a real surface behind the template hairline. */
#ec-store-root .product-layout [data-section-type] :is(input:not([type="checkbox"]):not([type="radio"]), textarea, select) {
    background-color: var(--ec-surface) !important;
    border-color: var(--ec-border);
}

/* ---- button voice (every type) ------------------------------------ */
/* Template buttons: 8px radius, bold label, flat rest state, one pixel
   lift and a deepened brand on hover (the .sp-btn-primary hover). */
#ec-store-root .product-layout [data-section-type] :is(button, a).rounded-xl {
    border-radius: var(--ec-radius-sm);
}

#ec-store-root .product-layout [data-section-type] :is(button, a).bg-primary {
    font-weight: 700;
    box-shadow: none;
    transition: background-color var(--ec-dur-1) var(--ec-ease), transform var(--ec-dur-1) var(--ec-ease),
                box-shadow var(--ec-dur-1) var(--ec-ease), filter var(--ec-dur-1) var(--ec-ease);
}

#ec-store-root .product-layout [data-section-type] :is(button, a).bg-primary:hover:not(:disabled) {
    background-color: #2353c7;
    transform: translateY(-1px);
}

#ec-store-root .product-layout [data-section-type] :is(button, a).bg-primary:active:not(:disabled) {
    transform: translateY(0);
}

/* ---- card idiom (card family + every card) ------------------------ */
#ec-store-root .product-layout [data-section-type] .bg-card:is(.rounded-2xl, .rounded-xl) {
    border-radius: var(--ec-radius-md);
}

/* Icon chips take the .ts-feature__num geometry. Small square divs
   only, so buttons and media tiles are untouched. */
#ec-store-root .product-layout [data-section-type] div.rounded-xl:is(.w-10, .w-12, .w-14) {
    border-radius: 9px;
}

/* Grid cards lift like .ts-pcard / .ts-feature. Kept off single-panel,
   quote and plan cards where a lift reads as noise. */
#ec-store-root .product-layout :is([data-section-type="feature-grid"], [data-section-type="use-cases"], [data-section-type="upsell-crosssell"], [data-section-type="related-resources"], [data-section-type="resources"], [data-section-type="bundle-contents"], [data-section-type="compatibility"], [data-section-type="instructor"], [data-section-type="curriculum"], [data-section-type="security-compliance"], [data-section-type="shipping-info"], [data-section-type="quickstart"]) .bg-card {
    transition: transform var(--ec-dur-2) var(--ec-ease), box-shadow var(--ec-dur-2) var(--ec-ease),
                border-color var(--ec-dur-2) var(--ec-ease);
}

#ec-store-root .product-layout :is([data-section-type="feature-grid"], [data-section-type="use-cases"], [data-section-type="upsell-crosssell"], [data-section-type="related-resources"], [data-section-type="resources"], [data-section-type="bundle-contents"], [data-section-type="compatibility"], [data-section-type="instructor"], [data-section-type="curriculum"], [data-section-type="security-compliance"], [data-section-type="shipping-info"], [data-section-type="quickstart"]) .bg-card:hover {
    transform: translateY(-3px);
    /* !important beats the baseline card chrome, which is !important. */
    box-shadow: var(--ec-shadow-2) !important;
    border-color: var(--ec-border-strong) !important;
}

/* ---- band rhythm --------------------------------------------------- */
/* The template's own bands (pale blue testimonials, slate pricing) get
   the storefront band edges; the leftover EC washes inside them go. */
#ec-store-root .product-layout :is([data-section-type="testimonials"], [data-section-type="pricing-purchase"], [data-section-type="pricing-table"]) {
    border-block: 1px solid var(--ec-border);
}

#ec-store-root .product-layout :is([data-section-type="statistics"], [data-section-type="pricing-purchase"]) > section {
    background-image: none;
}

/* ---- hero: SaaS product masthead ----------------------------------- */
#ec-store-root .product-layout [data-section-type="hero"] h1 {
    letter-spacing: -0.055em;
}

#ec-store-root .product-layout [data-section-type="hero"] nav {
    font-size: 0.78rem;
}

/* Gallery stage in the admin-mock framing: hairline, 12px, deep ambient
   shadow, minus the home page rotation. */
#ec-store-root .product-layout [data-section-type="hero"] .relative.rounded-2xl {
    border: 1px solid var(--ec-border);
    border-radius: var(--ec-radius-md);
    box-shadow: var(--ec-shadow-3);
}

/* Price row in the display face, like .ts-featured__price. */
#ec-store-root .product-layout [data-section-type="hero"] .text-4xl.font-bold {
    font-family: var(--ec-font-heading);
    letter-spacing: -0.04em;
}

/* Variation picker: one hairline on the pale blue wash instead of the
   double border + primary tint EC ships. div-only, buttons keep theirs. */
#ec-store-root .product-layout [data-section-type="hero"] div.border-2.rounded-xl {
    border-width: 1px;
    border-color: rgb(var(--ec-brand-rgb) / 0.3);
    border-radius: var(--ec-radius-md);
    background-color: var(--ec-surface-soft);
}

/* Add to cart carries a soft branded glow instead of the grey lg/xl
   shadow pair. */
#ec-store-root .product-layout [data-section-type="hero"] :is(button, a).bg-primary {
    box-shadow: 0 10px 24px rgb(var(--ec-brand-rgb) / 0.25);
}

/* Secondary purchase action in the .sp-btn-secondary idiom: hairline,
   surface, ink; brand only on hover. */
#ec-store-root .product-layout :is([data-section-type="hero"], [data-section-type="pricing-purchase"]) :is(button, a).border-2.text-primary {
    border-width: 1px;
    border-color: var(--ec-border);
    background-color: var(--ec-surface);
    color: var(--ec-ink);
    font-weight: 700;
}

#ec-store-root .product-layout :is([data-section-type="hero"], [data-section-type="pricing-purchase"]) :is(button, a).border-2.text-primary:hover:not(:disabled) {
    border-color: var(--ec-brand);
    background-color: var(--ec-surface-soft);
    color: var(--ec-ink);
    transform: translateY(-1px);
}

/* ---- statistics: the storefront proof row -------------------------- */
/* Completes the baseline neutralisation: the legacy skin rule near the
   top of this file still paints the outer band navy. */
#ec-store-root .product-layout [data-section-type="statistics"] {
    background: transparent;
}

#ec-store-root .product-layout [data-section-type="statistics"] .font-bold {
    font-family: var(--ec-font-heading);
    letter-spacing: -0.05em;
    color: var(--sp-brand-ink);
}

#ec-store-root .product-layout [data-section-type="statistics"] .text-muted-foreground {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Grid variant reads as the .ts-stat rule-above-figure motif. */
#ec-store-root .product-layout [data-section-type="statistics"] .text-center.p-6 {
    border-top: 1px solid var(--ec-border);
    text-align: left;
}

/* ---- feature-grid / use-cases: soft chip icons ---------------------- */
/* Filled icon chips flip to the .ts-feature__num language: soft blue
   square, brand glyph. div-only so primary buttons keep their fill. */
#ec-store-root .product-layout :is([data-section-type="feature-grid"], [data-section-type="use-cases"]) div.bg-primary.text-primary-foreground {
    background-color: rgb(var(--ec-brand-rgb) / 0.1);
    color: var(--ec-brand);
    border-radius: 9px;
}

/* ---- image-text-split ----------------------------------------------- */
#ec-store-root .product-layout [data-section-type="image-text-split"] .rounded-2xl.overflow-hidden {
    border: 1px solid var(--ec-border);
    border-radius: var(--ec-radius-md);
    /* the baseline blanked the .bg-muted letterbox */
    background-color: var(--ec-surface-soft) !important;
    box-shadow: var(--ec-shadow-2);
}

/* Item subtitles become the storefront eyebrow with its leading rule. */
#ec-store-root .product-layout [data-section-type="image-text-split"] p.uppercase {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.1em;
}

#ec-store-root .product-layout [data-section-type="image-text-split"] p.uppercase::before {
    content: "";
    width: 1.4rem;
    height: 2px;
    background: currentColor;
}

/* ---- media-showcase -------------------------------------------------- */
#ec-store-root .product-layout [data-section-type="media-showcase"] :is(.rounded-2xl, .rounded-xl).overflow-hidden {
    border: 1px solid var(--ec-border);
    border-radius: var(--ec-radius-md);
    box-shadow: var(--ec-shadow-2);
}

/* ---- steps ----------------------------------------------------------- */
/* Step markers as soft blue chips with brand numerals, not solid fills. */
#ec-store-root .product-layout [data-section-type="steps"] div.rounded-full.bg-primary {
    background-color: var(--ec-surface-soft);
    border: 1px solid rgb(var(--ec-brand-rgb) / 0.35);
    color: var(--ec-brand);
    font-family: var(--ec-font-heading);
}

/* ---- faq -------------------------------------------------------------- */
#ec-store-root .product-layout [data-section-type="faq"] .bg-card button span {
    font-family: var(--ec-font-heading);
    font-weight: 700;
    letter-spacing: -0.02em;
}

/* Row hover; the always-on baseline transparent kills the utility. */
#ec-store-root .product-layout [data-section-type="faq"] .bg-card > button:hover {
    background-color: color-mix(in srgb, var(--ec-surface-soft) 65%, transparent) !important;
}

/* Open item rings in brand, the .ts-faq__item[open] behaviour. */
#ec-store-root .product-layout [data-section-type="faq"] .bg-card:has(svg.rotate-180) {
    border-color: var(--ec-brand) !important;
    box-shadow: var(--ec-shadow-1) !important;
}

/* ---- tabs-section ------------------------------------------------------ */
#ec-store-root .product-layout [data-section-type="tabs-section"] .overflow-x-auto > button {
    font-weight: 600;
}

/* ---- tables family: comparison-table + specs-table --------------------- */
/* Zebra rows come back through the surface re-provide above; headers
   take the display face. */
#ec-store-root .product-layout :is([data-section-type="comparison-table"], [data-section-type="specs-table"]) thead th {
    font-family: var(--ec-font-heading);
    letter-spacing: -0.02em;
}

/* ---- pricing-table ------------------------------------------------------ */
#ec-store-root .product-layout [data-section-type="pricing-table"] :is(.text-4xl, .text-5xl) {
    font-family: var(--ec-font-heading);
    letter-spacing: -0.05em;
}

/* Non-popular plan buttons: ghost on surface, not the blanked muted. */
#ec-store-root .product-layout [data-section-type="pricing-table"] :is(button, a):is([class^="bg-muted"], [class*=" bg-muted"]) {
    border: 1px solid var(--ec-border);
    background-color: var(--ec-surface) !important;
    font-weight: 700;
}

#ec-store-root .product-layout [data-section-type="pricing-table"] :is(button, a):is([class^="bg-muted"], [class*=" bg-muted"]):hover {
    border-color: var(--ec-brand);
    background-color: var(--ec-surface-soft) !important;
}

/* ---- conversion surfaces: pricing-purchase, sticky bar, cta-block ------- */
/* The closing purchase actions flip to the orange conversion accent,
   exactly as the storefront featured band and CTA do. Scoped to the
   .rounded-xl CTAs so selected variation chips stay brand blue. */
#ec-store-root .product-layout :is([data-section-type="pricing-purchase"], [data-section-type="cta-block"]) :is(button, a).bg-primary.rounded-xl,
#ec-store-root .product-layout [data-section-type="sticky-purchase-bar"] :is(button, a).bg-primary {
    background-color: var(--ec-accent);
    color: var(--ec-accent-contrast);
}

#ec-store-root .product-layout :is([data-section-type="pricing-purchase"], [data-section-type="cta-block"]) :is(button, a).bg-primary.rounded-xl:hover:not(:disabled),
#ec-store-root .product-layout [data-section-type="sticky-purchase-bar"] :is(button, a).bg-primary:hover:not(:disabled) {
    background-color: var(--ec-accent);
    filter: brightness(0.92);
    transform: translateY(-1px);
}

/* ---- cta-block: the navy closing band ----------------------------------- */
/* The gradient variant repaints from brand blue to the .sp-cta navy
   pair, which holds on both schemes. */
#ec-store-root .product-layout [data-section-type="cta-block"] .bg-gradient-to-br {
    background-image: linear-gradient(135deg, #101a35, #243f82);
    border-radius: var(--ec-radius-lg);
}

/* Its white primary becomes the conversion accent under a warm glow.
   :not(.border-2) skips the selected variation chips, which are also
   white buttons on this band. */
#ec-store-root .product-layout [data-section-type="cta-block"] :is(button, a).bg-white:not(.border-2) {
    background-color: var(--ec-accent);
    color: var(--ec-accent-contrast);
    font-weight: 700;
    box-shadow: 0 12px 28px rgb(241 95 58 / 0.28);
}

#ec-store-root .product-layout [data-section-type="cta-block"] :is(button, a).bg-white:not(.border-2):hover:not(:disabled) {
    background-color: var(--ec-accent);
    color: var(--ec-accent-contrast);
    filter: brightness(0.92);
    transform: translateY(-1px);
}

/* Outlined variant: hairline brand panel at the band radius. */
#ec-store-root .product-layout [data-section-type="cta-block"] div.border-2.border-primary {
    border-width: 1px;
    border-color: rgb(var(--ec-brand-rgb) / 0.4);
    border-radius: var(--ec-radius-lg);
}

/* ---- testimonials -------------------------------------------------------- */
#ec-store-root .product-layout [data-section-type="testimonials"] .bg-card > svg.absolute {
    color: rgb(var(--ec-brand-rgb) / 0.16);
}

/* ---- changelog ------------------------------------------------------------ */
/* Row cards stay lighter than feature cards, like the FAQ stack. */
#ec-store-root .product-layout [data-section-type="changelog"] .bg-card {
    box-shadow: 0 4px 14px rgb(16 26 53 / 0.04) !important;
}

/* ---- sticky-purchase-bar --------------------------------------------------- */
#ec-store-root .product-layout [data-section-type="sticky-purchase-bar"] .border-t {
    border-top-color: var(--ec-border-strong);
    box-shadow: 0 -14px 40px rgb(16 26 53 / 0.16);
}

/* ---- prose family: description, content-block, custom-html ----------------- */
/* Long-form measure: the baseline widened every container to 100%. */
#ec-store-root .product-layout :is([data-section-type="description"], [data-section-type="content-block"]) .container-custom {
    max-width: 980px !important;
}

#ec-store-root .product-layout .prose {
    --tw-prose-headings: var(--ec-ink);
    --tw-prose-bold: var(--ec-ink);
    --tw-prose-links: var(--sp-brand-ink);
    --tw-prose-quote-borders: rgb(var(--ec-brand-rgb) / 0.35);
    --tw-prose-bullets: rgb(var(--ec-brand-rgb) / 0.5);
}

/* ---- small screens ---------------------------------------------------------- */
@media (max-width: 640px) {
    #ec-store-root .product-layout [data-section-type="cta-block"] .bg-gradient-to-br,
    #ec-store-root .product-layout [data-section-type="cta-block"] div.border-2.border-primary {
        border-radius: var(--ec-radius-md);
    }
}

@media (prefers-reduced-motion: reduce) {
    #ec-store-root .product-layout [data-section-type] :is(button, a).bg-primary,
    #ec-store-root .product-layout [data-section-type] .bg-card {
        transition: none;
    }

    #ec-store-root .product-layout [data-section-type] :is(button, a):hover,
    #ec-store-root .product-layout [data-section-type] .bg-card:hover {
        transform: none;
    }
}

/* ------------------------------------------------------------------ *
 * Dark scheme completion. The SPA palette block near the top of this
 * file pins light HSL values on #ec-store-root unconditionally, so a
 * dark shell would keep light section internals over the navy page.
 * The remap is the tokens.css dark set in the HSL triplet form the
 * compiled EC utilities consume; brand ink lifts to the preset
 * accentDark (#6f96ff) for contrast on navy.
 * ------------------------------------------------------------------ */
:is([data-color-scheme="dark"], .dark) #ec-store-root {
    --background: 223 55% 10%;
    --foreground: 225 100% 98%;
    --card: 224 54% 14%;
    --card-foreground: 225 100% 98%;
    --primary: 224 100% 72%;
    --primary-foreground: 0 0% 100%;
    --secondary: 222 50% 17%;
    --secondary-foreground: 225 100% 98%;
    --muted: 222 50% 17%;
    --muted-foreground: 221 25% 73%;
    --accent: 12 87% 59%;
    --accent-foreground: 0 0% 100%;
    --border: 220 33% 28%;
    --ring: 224 100% 72%;
}

:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout {
    --sp-brand-ink: #6f96ff;
}

/* The generic brand-deepen hover is too dark against the lifted dark
   primary; nudge down from #6f96ff instead. */
:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout [data-section-type] :is(button, a).bg-primary:hover:not(:disabled) {
    background-color: #5f88fa;
}

/* Hardcoded light bands from the legacy skin rules repaint on tokens. */
:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout [data-section-type="hero"] {
    background: linear-gradient(135deg, var(--ec-surface), var(--ec-surface-soft));
}

:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout [data-section-type="testimonials"] {
    background: var(--ec-surface-soft);
}

:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout :is([data-section-type="pricing-purchase"], [data-section-type="pricing-table"]) {
    background: var(--ec-surface);
}

/* The baseline card chrome hardcodes a light hairline and navy-tinted
   shadow; both flip here. Same importance, later order, wider scope. */
:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout .bg-card {
    border-color: var(--ec-border) !important;
    box-shadow: 0 10px 30px rgb(0 0 0 / 0.4) !important;
}

:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout :is([data-section-type="faq"], [data-section-type="changelog"]) .bg-card {
    box-shadow: 0 4px 14px rgb(0 0 0 / 0.3) !important;
}

:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout [data-section-type="sticky-purchase-bar"] .border-t {
    box-shadow: 0 -14px 40px rgb(0 0 0 / 0.5);
}

:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout .prose {
    --tw-prose-invert-headings: var(--ec-ink);
    --tw-prose-invert-bold: var(--ec-ink);
    --tw-prose-invert-links: var(--sp-brand-ink);
    --tw-prose-invert-quote-borders: rgb(var(--ec-brand-rgb) / 0.45);
    --tw-prose-invert-bullets: rgb(var(--ec-brand-rgb) / 0.6);
}

/* ================================================================== *
 * CONNECTED BANDS for the EasyCommerce PRODUCT page.
 * Turns the product sections into one continuous, full-bleed surface
 * flowing header -> bands -> footer, like the shondalai HOME page.
 * Reuses the home .sp-* gradient/hairline idiom on the product sections:
 * a positional two-tone zebra (cool-gray / light-blue) for the mids, so
 * the alternation holds for whichever of the 33 section types a product
 * renders, plus navy anchors that OPEN on ink (statistics) and CLOSE
 * into the dark footer (cta-block).
 *
 * Appended last so it supersedes the earlier bg-muted / bg-background ->
 * transparent neutralisation with real bands. Paint target is the inner
 * > section (the element EC ships bg-muted on, and it is full container
 * width) so the band runs edge to edge while .container-custom keeps the
 * content gutter. The zebra carries :nth-of-type() (one extra weight
 * column), so each section-type anchor also carries :nth-of-type(n) to
 * match it and wins on later source order. Backgrounds are !important to
 * beat the neutralisation; navy-anchor text is !important to beat the
 * pinned color:var(--ec-fg) on statistics. No per-section width cap is
 * added, so the fluid width is preserved.
 * ================================================================== */
#ec-store-root .product-layout {
    --sp-band-hero: linear-gradient(135deg, #fbfcff 0%, #eaf1ff 100%);
    --sp-band-hero-line: #d4e0f2;
    /* Refined professional blue-gray pair: desaturated slate tones, no brand
       radial glow. The earlier saturated periwinkle blue read as gaudy on a
       pro software store; these two cohere as one calm blue-gray palette while
       staying distinct enough to alternate. */
    --sp-band-gray: linear-gradient(155deg, #eff1f6 0%, #e2e7ef 100%);
    --sp-band-gray-line: #ccd3df;
    --sp-band-blue: linear-gradient(135deg, #e7ecf4 0%, #d6dfec 100%);
    --sp-band-blue-line: #c4cedd;
    --sp-band-ink: linear-gradient(135deg, #101a35, #243f82);
    --sp-band-ink-line: rgb(255 255 255 / .08);
}

/* zebra default: every section is a band, mids alternate; the hairline is
   what makes the tint read as a distinct connected panel. ODD -> cool-gray. */
#ec-store-root .product-layout [data-section-type]:nth-of-type(2n+1) > section {
    background: var(--sp-band-gray) !important;
    border-block: 1px solid var(--sp-band-gray-line);
}
/* EVEN -> light-blue. */
#ec-store-root .product-layout [data-section-type]:nth-of-type(2n) > section {
    background: var(--sp-band-blue) !important;
    border-block: 1px solid var(--sp-band-blue-line);
}

/* testimonials/pricing carried a wrapper hairline in the beauty pass; the
   zebra section now owns the band + its hairline, so drop the doubled edge. */
#ec-store-root .product-layout :is([data-section-type="testimonials"], [data-section-type="pricing-purchase"], [data-section-type="pricing-table"]) {
    border-block: 0;
}

/* anchor: hero -> the home masthead gradient. Bottom hairline only (the
   header owns the seam above). */
#ec-store-root .product-layout [data-section-type="hero"]:nth-of-type(n) > section,
#ec-store-root .product-layout [data-section-type="product-hero"]:nth-of-type(n) > section {
    background: var(--sp-band-hero) !important;
    border-block: 0;
    border-bottom: 1px solid var(--sp-band-hero-line);
}

/* anchor: statistics -> the navy proof band that OPENS on ink. */
#ec-store-root .product-layout [data-section-type="statistics"]:nth-of-type(n) > section {
    background: var(--sp-band-ink) !important;
    border-block: 1px solid var(--sp-band-ink-line);
    color: #eaf0ff !important;
    --sp-brand-ink: #86a9ff;
}

/* anchor: cta-block -> the navy band that CLOSES into the footer. Top
   hairline only, no bottom, so the ink meets the navy ts-footer flush. */
#ec-store-root .product-layout [data-section-type="cta-block"]:nth-of-type(n) > section {
    background: var(--sp-band-ink) !important;
    border-block: 0;
    border-top: 1px solid var(--sp-band-ink-line);
    --sp-brand-ink: #86a9ff;
}

/* text legibility on the two navy anchors: flip explicit foreground + muted
   utilities to light (EC tokens alone leave dark type on navy). */
#ec-store-root .product-layout :is([data-section-type="statistics"], [data-section-type="cta-block"]) > section :is(.text-foreground, .text-card-foreground) {
    color: #eaf0ff !important;
}
#ec-store-root .product-layout :is([data-section-type="statistics"], [data-section-type="cta-block"]) > section .text-muted-foreground {
    color: rgb(255 255 255 / .68) !important;
}
/* the statistics rule-above-figure divider reads too hot on navy; soften it. */
#ec-store-root .product-layout [data-section-type="statistics"] > section .text-center.p-6 {
    border-top-color: rgb(255 255 255 / .16);
}

/* white cards stay legible: no band is pure white, so the premium beauty-pass
   cards keep an edge everywhere; on the navy anchors, deepen the seat. */
#ec-store-root .product-layout :is([data-section-type="statistics"], [data-section-type="cta-block"]) .bg-card {
    box-shadow: 0 16px 38px rgb(0 0 0 / .30) !important;
}

/* Dark scheme: flip the light bands to token surfaces by redefining the band
   custom properties once; the navy anchors already suit dark and stay navy. */
:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout {
    --sp-band-hero: linear-gradient(135deg, var(--ec-surface), var(--ec-surface-soft));
    --sp-band-hero-line: var(--ec-border);
    --sp-band-gray: var(--ec-surface);
    --sp-band-gray-line: var(--ec-border);
    --sp-band-blue: var(--ec-surface-soft);
    --sp-band-blue-line: var(--ec-border);
}
:is([data-color-scheme="dark"], .dark) #ec-store-root .product-layout :is([data-section-type="statistics"], [data-section-type="cta-block"]) .bg-card {
    box-shadow: 0 16px 38px rgb(0 0 0 / .5) !important;
}

/* ---- Catalog storefront (shop / category): the same connected container --- *
 * The shop/category catalog rendered flat, with product cards floating on the
 * page background. Band the storefront root so the cards pop and the page reads
 * as a connected panel like the product page: header -> hero masthead (keeps its
 * own light bg + border-b) -> cool-gray catalog band -> footer (0px seam, the
 * root runs flush to the flush .ts-main bottom). Same gray as the product
 * feature band. Scoped to the storefront root that has NO product-layout, so
 * product pages (which own their band sequence above) are untouched; if :has()
 * is unsupported the whole selector is dropped and the catalog just stays flat. */
#ec-store-root > div.min-h-screen:not(:has(.product-layout)) {
    background: linear-gradient(155deg, #eff1f6 0%, #e2e7ef 100%) !important;
}
:is([data-color-scheme="dark"], .dark) #ec-store-root > div.min-h-screen:not(:has(.product-layout)) {
    background: var(--ec-surface) !important;
}

/* ================================================================== *
 * CONNECTED BLOG (Journal): FEATURED-HERO HYBRID.
 * The blog category rendered flat, with the featured card and grid
 * cards floating as white boxes on the light page. This turns the
 * editorial view into one connected container to match the product /
 * shop pages, without borrowing storefront chrome (this is com_content,
 * not the SPA).
 *
 * Structure: .ts-journal itself becomes the CALM connected surface (the
 * same cool-gray the catalog storefront uses) that runs full-bleed
 * because .ts-main is flush at container width. The masthead band (the
 * category header + the featured lead article) paints the home HERO
 * gradient OVER the top of that calm surface, so header -> masthead ->
 * calm grid/list -> navy footer read as one flowing panel. The lead card
 * DISSOLVES its chrome and becomes the hero content (accent kicker, large
 * title, filled read-more); grid cards and the "more" list POP off the
 * calm surface as premium cards.
 *
 * Appended last so it supersedes the refined components.css base with
 * bands. Scoped under .ts-journal / .ts-post* / .ts-pager only, so the
 * single article (.ts-article) and category grid (.ts-catlist) are
 * untouched. Bands go edge to edge by painting the full-width children
 * and holding the readable column with padding-inline:var(--ec-gut);
 * inset panels (list, pager) use margin-inline:var(--ec-gut) so every
 * content edge lines up on the same gutter.
 * ================================================================== */
.ts-journal {
    /* Band vocabulary, redefined once for dark below. */
    --tsj-band-hero: linear-gradient(135deg, #fbfcff 0%, #eaf1ff 100%);
    --tsj-band-hero-line: #d4e0f2;
    --tsj-band-calm: linear-gradient(155deg, #eff1f6 0%, #e2e7ef 100%);
    --tsj-card-shadow: 0 10px 30px rgb(16 26 53 / .08);
    --tsj-card-shadow-hover: var(--ec-shadow-2);
    --tsj-pill-bg: #fff;
    --tsj-pill-border: #d4e0f2;

    background: var(--tsj-band-calm);
    /* space before the navy footer meets the calm surface flush */
    padding-block-end: var(--ec-sect-y);
}

/* --- Masthead band: category header ------------------------------------ *
 * Hero gradient painted over the calm surface; flows straight into the
 * lead below (no seam). When NO lead follows, the header alone is the
 * masthead and closes with a hairline. */
.ts-journal .ts-journal__head {
    margin: 0;
    padding: clamp(2.5rem, 5vw, 4rem) var(--ec-gut) clamp(1.5rem, 3vw, 2.25rem);
    background: var(--tsj-band-hero);
    border-bottom: 0;
}

.ts-journal .ts-journal__head:not(:has(+ .ts-postgrid--lead)) {
    border-bottom: 1px solid var(--tsj-band-hero-line);
}

/* Count pill blends into the hero tint; give it a white chip so it reads. */
.ts-journal .ts-journal__head .ts-journal__count {
    background: var(--tsj-pill-bg);
    border: 1px solid var(--tsj-pill-border);
}

/* --- Masthead band: featured lead becomes the hero content ------------- *
 * Continues the hero gradient, closes with a hairline into the calm grid.
 * The card chrome dissolves so the media + large title ARE the masthead. */
.ts-journal .ts-postgrid--lead {
    margin: 0;
    padding: 0 var(--ec-gut) clamp(2.75rem, 5vw, 4rem);
    background: var(--tsj-band-hero);
    border-bottom: 1px solid var(--tsj-band-hero-line);
}

.ts-journal .ts-postgrid--lead .ts-postcard {
    gap: clamp(1.75rem, 4vw, 3.5rem);
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
    align-items: center;
}

/* No card-lift on the hero: it is the masthead, not a tile. */
.ts-journal .ts-postgrid--lead .ts-postcard:hover {
    transform: none;
    box-shadow: none;
}

/* Media reads as a framed hero image with real depth. */
.ts-journal .ts-postgrid--lead .ts-postcard__media {
    border-radius: var(--ec-radius-lg);
    overflow: hidden;
    min-height: 18rem;
    box-shadow: 0 24px 60px rgb(16 26 53 / .16);
}

.ts-journal .ts-postgrid--lead .ts-postcard__body {
    padding: 0;
    gap: 1rem;
}

/* Accent kicker for the masthead (DOM is sparse; supply the label). */
.ts-journal .ts-postgrid--lead .ts-postcard__body::before {
    content: "Featured";
    order: -1;
    font-family: var(--ec-font-body);
    font-weight: 700;
    font-size: 12px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--ec-accent);
}

/* Large display title for the hero. */
.ts-journal .ts-postgrid--lead .ts-postcard .page-header h1,
.ts-journal .ts-postgrid--lead .ts-postcard .page-header h2,
.ts-journal .ts-postgrid--lead .ts-postcard .page-header h3 {
    font-size: clamp(1.9rem, 3vw, 2.75rem);
    letter-spacing: -0.03em;
    line-height: 1.08;
}

.ts-journal .ts-postgrid--lead .ts-postcard__body .page-header a {
    -webkit-line-clamp: 3;
    line-clamp: 3;
}

.ts-journal .ts-postgrid--lead .ts-postcard__excerpt {
    max-height: calc(1.7em * 4);
    font-size: 1rem;
    line-height: 1.7;
}

/* Prominent read-more: the .sp-btn-primary idiom (filled brand pill with
   sliding arrow), out-ranking the accent-link readmore on the base card. */
.ts-journal .ts-postgrid--lead .ts-postcard .readmore {
    padding-top: 4px;
}

.ts-journal .ts-postgrid--lead .ts-postcard .readmore a {
    min-height: 44px;
    padding: 0 1.35rem;
    border-radius: var(--ec-btn-radius);
    background: var(--ec-brand);
    color: var(--ec-brand-contrast);
    font-size: 14px;
    font-weight: 700;
}

.ts-journal .ts-postgrid--lead .ts-postcard .readmore a:hover {
    gap: 0.7rem;
    background: #2353c7;
    color: var(--ec-brand-contrast);
}

@media (max-width: 767.98px) {
    .ts-journal .ts-postgrid--lead .ts-postcard {
        gap: 1.5rem;
    }
    .ts-journal .ts-postgrid--lead .ts-postcard__media {
        min-height: 0;
    }
}

/* --- Calm surface: grid cards pop -------------------------------------- *
 * The grid sits directly on the journal's calm surface (transparent, the
 * band shows through). Give resting depth so cards lift off the gray. */
.ts-journal .ts-postgrid:not(.ts-postgrid--lead) {
    margin: 0;
    padding: var(--ec-sect-y) var(--ec-gut) 0;
    background: none;
}

.ts-journal .ts-postcard {
    box-shadow: var(--tsj-card-shadow);
}

.ts-journal .ts-postcard:hover {
    box-shadow: var(--tsj-card-shadow-hover);
}

/* The featured card is chrome-less; it must not carry the grid shadow. */
.ts-journal .ts-postgrid--lead .ts-postcard {
    box-shadow: none;
}

/* --- "More articles" list becomes a premium panel on the calm surface -- */
.ts-journal .items-more {
    margin: var(--ec-sect-y) var(--ec-gut) 0;
    padding: clamp(1.25rem, 2.5vw, 2rem) clamp(1.25rem, 2.5vw, 2rem);
    background: var(--ec-surface);
    border: 1px solid var(--ec-border);
    border-radius: var(--ec-radius);
    box-shadow: var(--tsj-card-shadow);
}

/* The panel supplies the top edge; drop the list's own top hairline. */
.ts-journal .items-more .ts-postlinks {
    border-top: 0;
}

.ts-journal .items-more .ts-postlinks__item:last-child {
    border-bottom: 0;
}

/* --- Pager: aligned to the gutter on the calm surface ------------------ */
.ts-journal .ts-pager {
    margin: var(--ec-sect-y) var(--ec-gut) 0;
    padding-top: 1.5rem;
    border-top: 1px solid var(--ec-border-strong);
}

/* Optional sub-category / submit blocks stay on the gutter too. */
.ts-journal .ts-journal__section,
.ts-journal .ts-journal__actions {
    margin-inline: var(--ec-gut);
}

/* --- Dark scheme: redefine the band vocabulary once -------------------- *
 * Calm surface -> the darkest page tone so cards (surface) read lighter
 * and still pop; hero -> a subtle surface lift; chips/hairlines -> tokens.
 * Navy anchors already suit dark, so no flip needed there. */
:is([data-color-scheme="dark"], .dark) .ts-journal {
    --tsj-band-hero: linear-gradient(135deg, var(--ec-surface), var(--ec-surface-soft));
    --tsj-band-hero-line: var(--ec-border);
    --tsj-band-calm: var(--ec-page);
    --tsj-card-shadow: 0 10px 30px rgb(0 0 0 / .28);
    --tsj-card-shadow-hover: 0 18px 44px rgb(0 0 0 / .40);
    --tsj-pill-bg: var(--ec-surface-soft);
    --tsj-pill-border: var(--ec-border);
}

:is([data-color-scheme="dark"], .dark) .ts-journal .ts-postgrid--lead .ts-postcard__media {
    box-shadow: 0 24px 60px rgb(0 0 0 / .45);
}
