/* ZeroSite base stylesheet.
 *
 * Structure for every block, in neutral form: enough that a page is correct and
 * readable on its own, with nothing that belongs to one theme's personality.
 * A layout theme (styles/themes/<id>.css) is concatenated after this at build
 * time and overrides from here.
 *
 * Consumes the CSS variables site.css emits (colours, fonts, radius), so a
 * colour preset repaints every theme without any theme knowing about it. */

*, *::before, *::after { box-sizing: border-box; }

:root {
  /* How wide running text is allowed to get. Not in site.css because it's a
     legibility constant, not a brand choice. */
  --zs-measure: 46rem;

  /* Band colours, resolved once here so a band can redeclare the palette for
     everything inside it without repainting itself: these tokens compute
     against the root's palette, the redeclarations only reach descendants.
     A theme overrides these to say what its own "dark" actually is. */
  --zs-tone-soft: var(--zs-color-surface);
  --zs-tone-dark: var(--zs-color-secondary);
  --zs-tone-brand: var(--zs-color-primary);
  --zs-tone-on-dark: #f8fafc;
  /* The accent, lightened enough to read on a dark band. A band can't derive
     this itself: redeclaring --zs-color-primary in terms of --zs-color-primary
     is a cycle, and CSS drops the whole declaration. */
  --zs-tone-accent-on-dark: color-mix(in srgb, var(--zs-color-primary) 40%, #fff);
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--zs-font-body);
  font-size: var(--zs-font-size-base);
  line-height: 1.75;
  color: var(--zs-color-text);
  background: var(--zs-color-background);
  word-break: thai;
  overflow-wrap: break-word;
}

img, video { max-width: 100%; height: auto; }

h1, h2, h3, h4, h5, h6 {
  font-family: var(--zs-font-heading);
  line-height: 1.35;
  color: var(--zs-color-secondary);
  margin: 1.5em 0 0.5em;
}
h1 { font-size: 2.25rem; margin-top: 0.5em; }
h2 { font-size: 1.6rem; }
h3 { font-size: 1.3rem; }
h4 { font-size: 1.1rem; }

a { color: var(--zs-color-primary); }
a:hover { opacity: 0.85; }

.zs-container {
  max-width: var(--zs-container-max);
  margin: 0 auto;
  padding: 0 1.25rem;
}

/* ---------- Header ---------- */
.zs-header {
  border-bottom: 1px solid color-mix(in srgb, var(--zs-color-muted) 25%, transparent);
  background: var(--zs-color-background);
}
.zs-header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 4rem;
  position: relative;
}
.zs-logo { display: inline-flex; align-items: center; text-decoration: none; }
.zs-logo-text {
  font-family: var(--zs-font-heading);
  font-weight: 700;
  font-size: 1.35rem;
  color: var(--zs-color-secondary);
}
.zs-nav-list {
  list-style: none;
  display: flex;
  gap: 1.5rem;
  margin: 0;
  padding: 0;
}
.zs-nav-list a {
  text-decoration: none;
  color: var(--zs-color-text);
  font-weight: 500;
}
.zs-nav-list a:hover { color: var(--zs-color-primary); }

/* centered header variant */
.zs-header-centered .zs-header-inner {
  flex-direction: column;
  padding: 0.75rem 0;
}

/* mobile nav (no JS — checkbox toggle) */
.zs-nav-toggle { display: none; }
.zs-nav-burger { display: none; cursor: pointer; padding: 0.5rem; }
.zs-nav-burger span {
  display: block;
  width: 22px;
  height: 2px;
  margin: 5px 0;
  background: var(--zs-color-secondary);
}
@media (max-width: 720px) {
  .zs-nav-burger { display: block; }
  .zs-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--zs-color-background);
    border-bottom: 1px solid color-mix(in srgb, var(--zs-color-muted) 25%, transparent);
    padding: 1rem 1.25rem;
    z-index: 50;
  }
  .zs-nav-toggle:checked ~ .zs-nav { display: block; }
  .zs-nav-list { flex-direction: column; gap: 0.75rem; }
  .zs-header-centered .zs-header-inner { flex-direction: row; }
}

/* ---------- Content ---------- */
main { min-height: 60vh; padding: 2rem 0 4rem; }

/* A post is an essay: one column, capped at a comfortable measure. */
.zs-article { max-width: var(--zs-measure); margin: 0 auto; }
/* Scoped away from pages: this selector is more specific than .zs-article-page
   below, so without the :not it silently re-caps a page at 56rem and the
   sections inside it stop lining up with the full-bleed bands around them. */
.zs-width-wide .zs-article:not(.zs-article-page) {
  max-width: calc(var(--zs-measure) + 10rem);
}

/* A page is a layout, not an essay. Capping the whole article was quietly
   overruling the site's container width for everything below the header: a
   six-item service grid had 46rem to work with while the theme was set to
   1280px, so it rendered as three thumbnails in a narrow strip with dead space
   on both sides. The cap belongs on the running text, not on the layout. */
.zs-article-page { max-width: none; }

/* So the measure moves down to the prose blocks themselves, wherever they sit —
   loose in the article or inside a section — and centres in whatever box holds
   them. Composite blocks (grids, bands, media strips) are deliberately absent
   from this list: filling their container is the whole point of them. */
.zs-article-page .zs-content > :is(p, h1, h2, h3, h4, h5, h6, ul, ol, blockquote, pre, .zs-figure, .zs-table-wrap),
.zs-article-page .zs-section-stack > .zs-section-inner > :is(p, h1, h2, h3, h4, h5, h6, ul, ol, blockquote, pre, .zs-figure, .zs-table-wrap) {
  max-width: var(--zs-measure);
  margin-inline: auto;
}
/* Except where the author asked for edge-to-edge — a photo strip, a map. */
.zs-section-content-full > .zs-section-inner > * { max-width: none; }

.zs-content p { margin: 0 0 1.1em; }
.zs-content ul, .zs-content ol { padding-left: 1.5rem; margin: 0 0 1.1em; }
.zs-content blockquote {
  margin: 1.5em 0;
  padding: 0.5em 1.25em;
  border-left: 4px solid var(--zs-color-primary);
  background: var(--zs-color-surface);
  border-radius: 0 var(--zs-radius) var(--zs-radius) 0;
}
.zs-content pre {
  background: var(--zs-color-secondary);
  color: #f1f5f9;
  padding: 1rem 1.25rem;
  border-radius: var(--zs-radius);
  overflow-x: auto;
  font-size: 0.9em;
}
.zs-content code { font-family: ui-monospace, monospace; }
.zs-content p code {
  background: var(--zs-color-surface);
  padding: 0.15em 0.4em;
  border-radius: 4px;
  font-size: 0.9em;
}

.zs-figure { margin: 1.75em 0; }
.zs-figure img, .zs-figure video {
  border-radius: var(--zs-radius);
  display: block;
  margin: 0 auto;
}
.zs-figure figcaption {
  text-align: center;
  font-size: 0.875rem;
  color: var(--zs-color-muted);
  margin-top: 0.5rem;
}

.zs-table-wrap { overflow-x: auto; margin: 1.5em 0; }
.zs-table-wrap table { border-collapse: collapse; width: 100%; }
.zs-table-wrap th, .zs-table-wrap td {
  border: 1px solid color-mix(in srgb, var(--zs-color-muted) 30%, transparent);
  padding: 0.5rem 0.75rem;
  text-align: left;
}
.zs-table-wrap th { background: var(--zs-color-surface); }

/* ══════════ Composite layout blocks ══════════
   These lay themselves out and collapse to a single column on small screens, so
   a page built from them is responsive without any per-device settings. */

/* Break out of the article's reading column — sections span the page. */
.zs-hero,
.zs-cards-section,
.zs-imagetext,
.zs-ctaband {
  margin: 2.5em 0;
}

/* ---------- Hero ---------- */
.zs-hero-title {
  font-size: clamp(2.1rem, 1.2rem + 3.6vw, 4rem);
  margin: 0 0 0.35em;
  line-height: 1.1;
  letter-spacing: -0.025em;
}
.zs-hero-sub {
  font-size: clamp(1.05rem, 1rem + .35vw, 1.25rem);
  color: var(--zs-color-muted);
  margin: 0 0 1.8em;
  max-width: 40rem;
}
.zs-hero-center { text-align: center; }
.zs-hero-center .zs-hero-sub { margin-left: auto; margin-right: auto; }
.zs-hero-actions {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
}
.zs-hero-center .zs-hero-actions { justify-content: center; }
.zs-hero-right .zs-hero-actions { justify-content: flex-end; }

/* A hero carrying its own photo. The picture is a background rather than an
   <img> because the text has to sit on top of it and stay readable at every
   width — an overlay over a background does that with no positioning, and the
   image is decorative here, so nothing is lost from the document. */
.zs-hero-bg {
  position: relative;
  background-size: cover;
  background-position: center;
  isolation: isolate;
  padding-block: clamp(4.5rem, 2rem + 9vw, 9rem);
  display: flex;
  align-items: center;
}
.zs-hero-bg::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    180deg,
    rgb(2 6 23 / var(--zs-hero-veil-top, .55)),
    rgb(2 6 23 / var(--zs-hero-veil-bottom, .72))
  );
}
.zs-hero-overlay-light { --zs-hero-veil-top: .25; --zs-hero-veil-bottom: .42; }
.zs-hero-overlay-medium { --zs-hero-veil-top: .5; --zs-hero-veil-bottom: .68; }
.zs-hero-overlay-strong { --zs-hero-veil-top: .7; --zs-hero-veil-bottom: .85; }
/* A photo hero is edge-to-edge whatever it's wrapped in: it breaks out the same
   way a full-bleed section does, which is a no-op when the section already did
   it and the escape hatch when the author left the section boxed. */
.zs-hero-bg {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  margin-block: 0;
}
.zs-hero-bg > .zs-hero-body {
  position: relative;
  width: 100%;
  max-width: var(--zs-container-max);
  margin-inline: auto;
  padding-inline: 1.25rem;
}
.zs-hero-h-tall { min-height: 70vh; }
.zs-hero-h-full { min-height: 100svh; }

.zs-hero-media { margin-bottom: 1.75rem; }
.zs-hero-media img {
  width: 100%;
  border-radius: var(--zs-radius);
  aspect-ratio: 21/9;
  object-fit: cover;
  display: block;
}
@media (max-width: 720px) {
  .zs-hero-media img { aspect-ratio: 16/10; }
}

/* ---------- Cards ---------- */
.zs-section-title {
  text-align: center;
  margin: 0 0 1.2em;
}
.zs-cards {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(var(--cols, 3), 1fr);
}
.zs-cards-2 { --cols: 2; }
.zs-cards-3 { --cols: 3; }
.zs-cards-4 { --cols: 4; }
@media (max-width: 900px) {
  .zs-cards-3, .zs-cards-4 { --cols: 2; }
}
@media (max-width: 640px) {
  .zs-cards { --cols: 1; }
}
.zs-card {
  background: var(--zs-color-surface);
  border-radius: var(--zs-radius);
  padding: 1.4rem;
}
.zs-card h3 { margin: 0 0 0.4em; font-size: 1.05rem; }
.zs-card p { margin: 0; color: var(--zs-color-muted); font-size: 0.95rem; }

/* ---------- Image + text ---------- */
.zs-imagetext {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
  align-items: center;
}
/* No picture yet — a template ships with the image slot empty, and half a grid
   is worse than no grid: the text stayed in a narrow column with a blank half
   beside it. One column, measured like any other prose, until an image lands. */
.zs-imagetext:not(:has(.zs-imagetext-media)) {
  grid-template-columns: 1fr;
}
.zs-imagetext:not(:has(.zs-imagetext-media)) .zs-imagetext-body {
  max-width: var(--zs-measure);
}
/* Source order puts the image first so it leads when stacked on mobile;
   on desktop, "right" simply moves it across. */
.zs-imagetext-right .zs-imagetext-media { order: 2; }
.zs-imagetext-media img {
  width: 100%;
  border-radius: var(--zs-radius);
  aspect-ratio: 4/3;
  object-fit: cover;
  display: block;
}
.zs-imagetext-body h2 { margin-top: 0; }
.zs-imagetext-body p { color: var(--zs-color-muted); }
@media (max-width: 720px) {
  .zs-imagetext { grid-template-columns: 1fr; gap: 1.25rem; }
  .zs-imagetext-right .zs-imagetext-media { order: 0; }
}

/* ---------- CTA band ---------- */
.zs-ctaband {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  background: var(--zs-color-primary);
  color: #fff;
  border-radius: var(--zs-radius);
  padding: 2rem 2.25rem;
}
.zs-ctaband h2 { color: #fff; margin: 0 0 0.3em; }
.zs-ctaband p { margin: 0; color: rgb(255 255 255 / 0.85); }
.zs-btn-invert {
  background: #fff;
  color: var(--zs-color-primary);
  white-space: nowrap;
}
@media (max-width: 640px) {
  .zs-ctaband { padding: 1.5rem; }
}

/* ---------- Spacer ---------- */
.zs-spacer-sm { height: 1.5rem; }
.zs-spacer-md { height: 3rem; }
.zs-spacer-lg { height: 5rem; }

/* ---------- FAQ ---------- */
.zs-faq {
  border: 1px solid color-mix(in srgb, var(--zs-color-muted) 30%, transparent);
  border-radius: var(--zs-radius);
  margin: 0.75em 0;
  background: var(--zs-color-surface);
}
.zs-faq summary {
  cursor: pointer;
  padding: 0.85em 1.1em;
  font-weight: 600;
  font-family: var(--zs-font-heading);
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.zs-faq summary::-webkit-details-marker { display: none; }
.zs-faq summary::after {
  content: "+";
  font-size: 1.25em;
  line-height: 1;
  color: var(--zs-color-primary);
  transition: transform 150ms ease;
}
.zs-faq[open] summary::after { transform: rotate(45deg); }
.zs-faq-answer {
  padding: 0 1.1em 0.95em;
  color: var(--zs-color-text);
}

/* ---------- CTA ---------- */
.zs-cta { margin: 1.75em 0; }
.zs-cta-center { text-align: center; }
.zs-cta-left { text-align: left; }
.zs-cta-right { text-align: right; }

/* ---------- Embed (click-to-play poster, no third-party JS) ---------- */
.zs-embed-link {
  position: relative;
  display: block;
  border-radius: var(--zs-radius);
  overflow: hidden;
}
.zs-embed-link img {
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
  display: block;
}
.zs-embed-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  color: #fff;
  background: rgb(0 0 0 / 0.35);
  transition: background 150ms ease;
}
.zs-embed-link:hover .zs-embed-play { background: rgb(0 0 0 / 0.5); }
.zs-embed-fallback { word-break: break-all; }

/* ---------- Breadcrumbs ---------- */
.zs-breadcrumbs { font-size: 0.875rem; margin-bottom: 1rem; }
.zs-breadcrumbs ol {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin: 0;
  padding: 0;
  color: var(--zs-color-muted);
}
.zs-breadcrumbs li + li::before { content: "›"; margin: 0 0.4rem; }
.zs-breadcrumbs a { color: var(--zs-color-muted); text-decoration: none; }
.zs-breadcrumbs a:hover { color: var(--zs-color-primary); }

/* ---------- Posts ---------- */
.zs-post-meta { color: var(--zs-color-muted); font-size: 0.9rem; }
.zs-cover img { width: 100%; }

.zs-list-header { text-align: center; margin-bottom: 2.5rem; }
.zs-post-grid { display: grid; gap: 1.5rem; }
.zs-postlist-cards .zs-post-grid {
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.zs-post-card {
  background: var(--zs-color-surface);
  border-radius: var(--zs-radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.zs-postlist-list .zs-post-card { flex-direction: row; gap: 1rem; }
.zs-post-card-img img {
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
  display: block;
}
.zs-postlist-list .zs-post-card-img { flex: 0 0 220px; }
.zs-post-card-body { padding: 1.25rem; }
.zs-post-card h2 { margin: 0 0 0.5rem; font-size: 1.15rem; }
.zs-post-card h2 a { color: var(--zs-color-secondary); text-decoration: none; }
.zs-post-card h2 a:hover { color: var(--zs-color-primary); }
.zs-post-card p { margin: 0 0 0.5rem; font-size: 0.925rem; }

.zs-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  margin-top: 3rem;
  color: var(--zs-color-muted);
}
.zs-pagination a { text-decoration: none; font-weight: 500; }

/* ---------- Buttons ---------- */
.zs-btn {
  display: inline-block;
  background: var(--zs-color-primary);
  color: #fff;
  padding: 0.65rem 1.5rem;
  border-radius: var(--zs-radius);
  text-decoration: none;
  font-weight: 600;
}
.zs-btn:hover { opacity: 0.9; }

/* The outlined companion to the primary action. Declared after .zs-btn on
   purpose: same specificity, so source order is what decides. */
.zs-btn-ghost {
  background: transparent;
  color: currentColor;
  border: 1px solid color-mix(in srgb, currentColor 45%, transparent);
}
.zs-btn-ghost:hover {
  background: color-mix(in srgb, currentColor 12%, transparent);
  opacity: 1;
}

/* ---------- Footer ---------- */
.zs-footer {
  border-top: 1px solid color-mix(in srgb, var(--zs-color-muted) 25%, transparent);
  background: var(--zs-color-surface);
  padding: 2.5rem 0;
  margin-top: 2rem;
}
.zs-footer-inner { display: grid; gap: 1.5rem; }
.zs-footer .zs-nav-list {
  display: grid;
  grid-template-columns: repeat(var(--zs-footer-columns), 1fr);
  gap: 0.5rem 2rem;
}
.zs-footer .zs-nav-list a { font-weight: 400; font-size: 0.925rem; }
.zs-copyright { color: var(--zs-color-muted); font-size: 0.875rem; margin: 0; }

/* ---------- 404 ---------- */
.zs-404 { text-align: center; padding: 4rem 0; }
.zs-404 h1 { font-size: 5rem; margin: 0; }

/* ---------- Sections ---------- */
/* A section is a band of the page holding blocks. Its layout options are
   classes here rather than generated per page, so they cost nothing per page
   and stay consistent across the site; only the free-form Style tab values
   compile into per-page rules. */
.zs-section { --zs-section-gap: 1.25rem; }
.zs-section-inner { display: flex; flex-direction: column; gap: var(--zs-section-gap); }

/* Boxed is a pass-through: the section sits inside the page's container and
   article, which already set the width and the side padding. Adding our own
   would inset the text a second time and shift every page that got wrapped
   into a section automatically. */

/* Full has to break OUT of those ancestors — a child can't be wider than its
   parent, so "full width" is only reachable by pulling the element back to the
   viewport's edges. Margins rather than a positioned left/right offset, so the
   section still takes part in normal vertical flow. */
.zs-section-full {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
}
/* 100vw counts the scrollbar's width, so a full-bleed section is a few pixels
   wider than what you can see and the page picks up a horizontal scrollbar.
   Clipping the overflow at the root is the cheap fix; it doesn't break sticky
   positioning the way overflow on <body> does. */
html { overflow-x: clip; }

/* With the section itself at viewport width, the content inside it either goes
   along or comes back to the page's normal width. Boxed is the default: a band
   of colour edge to edge with the text still lining up with everything above
   it, which is what a full-bleed section is almost always for. */
.zs-section-full > .zs-section-inner { padding: 0 1.25rem; }
.zs-section-full.zs-section-content-boxed > .zs-section-inner {
  max-width: var(--zs-container-max);
  margin-inline: auto;
}
/* Content set to full means full: the side padding above is the guard that
   keeps text off the screen edge, but choosing this explicitly is asking for
   edge-to-edge (a photo strip, a map) — so no padding to quietly re-inset it. */
.zs-section-full.zs-section-content-full > .zs-section-inner { padding: 0; }

/* ---------- Section tone: the bands a page is built from ----------
   A page reads as designed when its sections alternate rather than running as
   one uninterrupted sheet. Each tone repaints the palette for its own subtree,
   so everything inside — headings, muted captions, cards, buttons — follows
   without any block knowing which band it landed in. */
.zs-section-band {
  padding-block: clamp(3rem, 1.5rem + 5vw, 6rem);
  color: var(--zs-color-text);
  background: var(--zs-band-bg);
}
/* The band supplies its own vertical space, so the blocks inside it shouldn't
   also push the usual gap against its padding. */
.zs-section-band > .zs-section-inner > :first-child { margin-top: 0; }
.zs-section-band > .zs-section-inner > :last-child { margin-bottom: 0; }

.zs-section-tone-soft { --zs-band-bg: var(--zs-tone-soft); }
/* Surface is the tint that cards sit on; inside a tinted band they'd vanish, so
   cards go back to the page colour and the tint becomes the backdrop. */
.zs-section-tone-soft { --zs-color-surface: var(--zs-color-background); }

.zs-section-tone-dark {
  --zs-band-bg: var(--zs-tone-dark);
  --zs-color-text: var(--zs-tone-on-dark);
  --zs-color-secondary: var(--zs-tone-on-dark);
  --zs-color-muted: color-mix(in srgb, var(--zs-tone-on-dark) 60%, transparent);
  --zs-color-surface: color-mix(in srgb, #fff 8%, transparent);
  --zs-color-background: color-mix(in srgb, #fff 6%, transparent);
  --zs-color-primary: var(--zs-tone-accent-on-dark);
}
.zs-section-tone-brand {
  --zs-band-bg: var(--zs-tone-brand);
  --zs-color-text: #fff;
  --zs-color-secondary: #fff;
  --zs-color-muted: color-mix(in srgb, #fff 72%, transparent);
  --zs-color-surface: color-mix(in srgb, #fff 12%, transparent);
  --zs-color-background: color-mix(in srgb, #fff 10%, transparent);
  /* On the brand band the accent IS the background, so it can only be white. */
  --zs-color-primary: #fff;
}
/* A solid button in the band's own colour is invisible against it. */
.zs-section-tone-brand .zs-btn {
  background: #fff;
  color: var(--zs-tone-brand);
}
.zs-section-tone-dark .zs-btn,
.zs-section-tone-brand .zs-btn { box-shadow: none; }
.zs-section-tone-dark :is(.zs-card, .zs-service, .zs-testimonial, .zs-plan, .zs-accordion-item),
.zs-section-tone-brand :is(.zs-card, .zs-service, .zs-testimonial, .zs-plan, .zs-accordion-item) {
  border-color: color-mix(in srgb, #fff 18%, transparent);
  box-shadow: none;
}

/* The page's own top padding would show as a light strip above a band that
   opens the page — a hero especially. Pull it off when that's the shape. */
main:has(.zs-content > .zs-section-band:first-child),
main:has(.zs-content > *:first-child .zs-hero-bg) { padding-top: 0; }
/* Consecutive bands of the same tone should read as one, not as a seam. */
.zs-section-band + .zs-section-band { margin-top: 0; }

/* A photo hero paints its own band and sets its own height, so the section's
   padding only shows up as a strip of flat colour above and below it. */
.zs-section-band:has(> .zs-section-inner > .zs-hero-bg:only-child) {
  padding-block: 0;
}

/* Columns collapse before the text gets too narrow to read, same as .zs-cards.
   The author picks the count; the collapse isn't theirs to break. */
.zs-section-cols > .zs-section-inner {
  display: grid;
  grid-template-columns: repeat(var(--zs-section-cols, 2), minmax(0, 1fr));
  align-items: start;
}
.zs-section-cols-2 { --zs-section-cols: 2; }
.zs-section-cols-3 { --zs-section-cols: 3; }
.zs-section-cols-4 { --zs-section-cols: 4; }

.zs-section-v-top > .zs-section-inner { justify-content: flex-start; }
.zs-section-v-center > .zs-section-inner { justify-content: center; }
.zs-section-v-bottom > .zs-section-inner { justify-content: flex-end; }
/* A min-height only means something if the inner box fills the section. */
.zs-section-v-center,
.zs-section-v-bottom { display: flex; flex-direction: column; }
.zs-section-v-center > .zs-section-inner,
.zs-section-v-bottom > .zs-section-inner { flex: 1; }

@media (max-width: 900px) {
  .zs-section-cols-3 { --zs-section-cols: 2; }
  .zs-section-cols-4 { --zs-section-cols: 2; }
}
@media (max-width: 640px) {
  .zs-section-cols > .zs-section-inner { --zs-section-cols: 1; }
}

/* Present for assistive tech and crawlers, absent from the visual layout —
   the standard clip-rect recipe. Used by the "show title" page setting. */
.zs-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ══════════ Content blocks ══════════
   Structure only: grids, rhythm, and the CSS that makes the interactive ones
   work without JS. Colour and character come from the theme layer. */

/* Shared section head + column counts. Every grid below collapses on the same
   two breakpoints, so a page reflows as one piece rather than block by block. */
.zs-blockhead { margin: 0 0 2.5rem; }
.zs-blockhead h2 {
  margin: 0 0 .35em;
  font-size: clamp(1.6rem, 1.15rem + 1.7vw, 2.35rem);
  letter-spacing: -0.015em;
}
.zs-blockhead-sub {
  margin: 0;
  color: var(--zs-color-muted);
  max-width: 44rem;
  font-size: 1.05rem;
}
/* The eyebrow is a label, not a sentence: small, spaced out, and paired with a
   short rule so it reads as a section marker rather than a lost line of text. */
.zs-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .6em;
  margin: 0 0 .7em;
  font-size: .78rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--zs-color-primary);
  font-weight: 700;
}
.zs-eyebrow::before {
  content: "";
  width: 1.8em;
  height: 2px;
  background: currentColor;
  opacity: .6;
}

/* ---------- Icons ----------
   One badge for every icon in the system: a tinted disc holding a monoline
   glyph. Emoji left over from older documents land in the same badge, so a page
   part-way through being updated doesn't look half-broken. */
.zs-icon-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 999px;
  margin-bottom: 1rem;
  background: color-mix(in srgb, var(--zs-color-primary) 12%, transparent);
  color: var(--zs-color-primary);
  flex: none;
}
.zs-icon { width: 1.6rem; height: 1.6rem; display: block; }
.zs-icon-text { font-size: 1.5rem; line-height: 1; width: auto; height: auto; }
/* On a dark or brand band the tint has nothing to sit on, so the disc borrows
   the band's own light instead of the accent. */
.zs-section-tone-dark .zs-icon-badge,
.zs-section-tone-brand .zs-icon-badge {
  background: color-mix(in srgb, #fff 14%, transparent);
  color: var(--zs-color-text);
}

.zs-cols-1 { --zs-cols: 1; }
.zs-cols-2 { --zs-cols: 2; }
.zs-cols-3 { --zs-cols: 3; }
.zs-cols-4 { --zs-cols: 4; }
.zs-cols-5 { --zs-cols: 5; }
.zs-cols-6 { --zs-cols: 6; }

.zs-stats-grid, .zs-steps-list, .zs-team-grid, .zs-testimonial-grid,
.zs-services-grid, .zs-pricing-grid, .zs-gallery-grid, .zs-contactinfo-grid,
.zs-feature-items {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: repeat(var(--zs-cols, 3), minmax(0, 1fr));
}
@media (max-width: 900px) {
  .zs-stats-grid, .zs-steps-list, .zs-team-grid, .zs-testimonial-grid,
  .zs-services-grid, .zs-pricing-grid, .zs-gallery-grid, .zs-contactinfo-grid {
    --zs-cols: 2;
  }
}
@media (max-width: 640px) {
  .zs-stats-grid, .zs-steps-list, .zs-team-grid, .zs-testimonial-grid,
  .zs-services-grid, .zs-pricing-grid, .zs-gallery-grid, .zs-contactinfo-grid,
  .zs-feature-items {
    --zs-cols: 1;
  }
}

.zs-stats, .zs-steps, .zs-team, .zs-testimonials, .zs-logos, .zs-services,
.zs-pricing, .zs-gallery, .zs-accordion, .zs-contactinfo, .zs-timeline,
.zs-tabs, .zs-featurelist { margin: 3em 0; }

/* ---------- Stats ---------- */
.zs-stat { text-align: center; }
.zs-stat-value {
  margin: 0;
  font-family: var(--zs-font-heading);
  font-size: clamp(2rem, 1.4rem + 2vw, 3rem);
  font-weight: 700;
  line-height: 1.1;
  color: var(--zs-color-primary);
}
.zs-stat-suffix { font-size: .7em; }
.zs-stat-label { margin: .35em 0 0; color: var(--zs-color-muted); }

/* ---------- Steps ---------- */
.zs-steps-list { list-style: none; padding: 0; margin: 0; counter-reset: none; }
.zs-step { position: relative; padding-top: .5rem; }
.zs-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 999px;
  background: var(--zs-color-primary);
  color: #fff;
  font-weight: 700;
  margin-bottom: .75rem;
}
/* With an icon present the position number becomes a chip on its corner —
   two discs in a row read as two separate things, which they aren't. */
.zs-step:has(.zs-step-icon) .zs-step-num {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  width: 1.6rem;
  height: 1.6rem;
  font-size: .78rem;
  box-shadow: 0 0 0 3px var(--zs-color-background);
}
.zs-step:has(.zs-step-icon) .zs-step-icon { margin-left: .4rem; margin-top: .4rem; }

.zs-step h3 { margin: 0 0 .4em; font-size: 1.2rem; }
.zs-step p { margin: 0; color: var(--zs-color-muted); font-size: 1rem; }

/* ---------- Team ---------- */
.zs-team-card { text-align: center; }
.zs-team-photo { margin-bottom: .85rem; }
.zs-team-photo img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--zs-radius);
  display: block;
}
.zs-team-card h3 { margin: 0 0 .2em; font-size: 1.05rem; }
.zs-team-role { margin: 0; color: var(--zs-color-muted); font-size: .9rem; }
.zs-team-link { display: inline-block; margin-top: .5rem; font-size: .85rem; }

/* ---------- Testimonials ---------- */
.zs-testimonial {
  margin: 0;
  padding: 1.5rem;
  background: var(--zs-color-surface);
  border-radius: var(--zs-radius);
}
.zs-testimonial blockquote {
  margin: 0 0 1rem;
  padding: 0;
  border: 0;
  background: none;
  font-size: 1.02rem;
}
.zs-testimonial figcaption { display: flex; align-items: center; gap: .75rem; }
.zs-testimonial-avatar img {
  width: 44px; height: 44px; border-radius: 999px; object-fit: cover; display: block;
}
.zs-testimonial-role { display: block; color: var(--zs-color-muted); font-size: .85rem; }
.zs-rating { margin: 0 0 .5rem; color: var(--zs-color-accent); letter-spacing: .1em; }

/* A slider is a scroll-snap strip: swipeable and keyboard-scrollable with no
   JS. The runtime script only adds auto-advance on top of this. */
.zs-slider {
  display: flex;
  gap: 1.5rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  padding-bottom: .5rem;
}
.zs-slider > * {
  flex: 0 0 min(100%, 26rem);
  scroll-snap-align: start;
}
.zs-slider::-webkit-scrollbar { height: 6px; }
.zs-slider::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--zs-color-muted) 40%, transparent);
  border-radius: 999px;
}

/* ---------- Logos ---------- */
.zs-logos-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 2.5rem;
}
.zs-logo img { max-height: 44px; width: auto; display: block; }

/* ---------- Services ---------- */
.zs-service {
  display: block;
  padding: 1.5rem;
  background: var(--zs-color-surface);
  border-radius: var(--zs-radius);
  text-decoration: none;
  color: inherit;
}
.zs-service-link:hover { background: color-mix(in srgb, var(--zs-color-primary) 8%, var(--zs-color-surface)); }
.zs-service-media { margin: -1.5rem -1.5rem 1rem; }
.zs-service-media img {
  width: 100%; aspect-ratio: 16/10; object-fit: cover; display: block;
  border-radius: var(--zs-radius) var(--zs-radius) 0 0;
}
.zs-service h3 { margin: 0 0 .45em; font-size: 1.25rem; letter-spacing: -.01em; }
.zs-service p { margin: 0; color: var(--zs-color-muted); font-size: 1rem; }

/* ---------- Pricing ---------- */
.zs-plan {
  padding: 1.75rem;
  background: var(--zs-color-surface);
  border-radius: var(--zs-radius);
  border: 1px solid transparent;
  display: flex;
  flex-direction: column;
  gap: .75rem;
}
.zs-plan-featured { border-color: var(--zs-color-primary); }
.zs-plan h3 { margin: 0; font-size: 1.05rem; }
.zs-plan-price {
  margin: 0;
  font-family: var(--zs-font-heading);
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.1;
}
.zs-plan-period { font-size: .9rem; font-weight: 400; color: var(--zs-color-muted); }
.zs-plan-features { list-style: none; padding: 0; margin: 0; flex: 1; }
.zs-plan-features li { padding-left: 1.4em; position: relative; margin-bottom: .4em; }
.zs-plan-features li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--zs-color-primary);
}
.zs-plan .zs-btn { align-self: flex-start; }

/* ---------- Gallery ---------- */
.zs-gallery-item { margin: 0; }
.zs-gallery-item img {
  width: 100%; aspect-ratio: 4/3; object-fit: cover; display: block;
  border-radius: var(--zs-radius);
}
.zs-gallery-item figcaption {
  margin-top: .4rem; font-size: .85rem; color: var(--zs-color-muted);
}

/* ---------- Accordion ---------- */
.zs-accordion-list { display: grid; gap: .6rem; }
.zs-accordion-item {
  background: var(--zs-color-surface);
  border-radius: var(--zs-radius);
  padding: .9rem 1.1rem;
}
.zs-accordion-item summary {
  cursor: pointer;
  font-weight: 600;
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: 1rem;
}
.zs-accordion-item summary::-webkit-details-marker { display: none; }
.zs-accordion-item summary::after { content: "+"; color: var(--zs-color-primary); }
.zs-accordion-item[open] summary::after { content: "−"; }
.zs-accordion-answer { padding-top: .7rem; color: var(--zs-color-muted); }

/* ---------- Contact info ---------- */
.zs-contact-item { text-align: center; }
.zs-contact-icon { margin-inline: auto; margin-bottom: .75rem; }
.zs-contact-label {
  margin: 0 0 .2em; font-weight: 600; font-size: .95rem;
}
.zs-contact-value { margin: 0; color: var(--zs-color-muted); }
.zs-contact-value a { text-decoration: none; }

/* ---------- Timeline ---------- */
.zs-timeline-list { list-style: none; padding: 0; margin: 0; }
.zs-timeline-item {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: 1.5rem;
  padding: 0 0 1.75rem 0;
  position: relative;
}
/* The rail is drawn on the item, not a pseudo-element on the list, so the last
   entry can stop it rather than leaving a line hanging into whitespace. */
.zs-timeline-item::before {
  content: "";
  position: absolute;
  left: calc(7rem - .75rem);
  top: .6rem;
  bottom: -.6rem;
  width: 2px;
  background: color-mix(in srgb, var(--zs-color-muted) 25%, transparent);
}
.zs-timeline-item:last-child::before { display: none; }
.zs-timeline-year {
  margin: 0;
  font-weight: 700;
  color: var(--zs-color-primary);
  font-family: var(--zs-font-heading);
}
.zs-timeline-body h3 { margin: 0 0 .3em; font-size: 1.05rem; }
.zs-timeline-body p { margin: 0; color: var(--zs-color-muted); }
@media (max-width: 640px) {
  .zs-timeline-item { grid-template-columns: 1fr; gap: .4rem; }
  .zs-timeline-item::before { display: none; }
}

/* ---------- Tabs (radio-driven, no JS) ---------- */
.zs-tabs-wrap { display: flex; flex-wrap: wrap; }
.zs-tab-input { position: absolute; opacity: 0; pointer-events: none; }
.zs-tab-label {
  order: -1;
  cursor: pointer;
  padding: .6rem 1.1rem;
  border-bottom: 2px solid transparent;
  color: var(--zs-color-muted);
  font-weight: 600;
}
.zs-tab-panel { display: none; width: 100%; padding-top: 1.25rem; }
.zs-tab-input:checked + .zs-tab-label {
  color: var(--zs-color-primary);
  border-bottom-color: var(--zs-color-primary);
}
.zs-tab-input:checked + .zs-tab-label + .zs-tab-panel { display: block; }
/* Keyboard users must see which tab has focus — the label is the only visible
   control, since the input itself is off-screen. */
.zs-tab-input:focus-visible + .zs-tab-label {
  outline: 2px solid var(--zs-color-primary);
  outline-offset: 2px;
}
.zs-tab-media img { width: 100%; border-radius: var(--zs-radius); display: block; margin-bottom: 1rem; }

/* ---------- Feature list ---------- */
.zs-feature-items { list-style: none; padding: 0; margin: 0; gap: .6rem 2rem; }
.zs-feature-items li { padding-left: 1.6em; position: relative; }
.zs-feature-items li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--zs-color-primary);
  font-weight: 700;
}

/* ---------- Buttons ---------- */
.zs-buttons { display: flex; flex-wrap: wrap; gap: .75rem; margin: 1.5em 0; }
.zs-buttons-center { justify-content: center; }
.zs-buttons-right { justify-content: flex-end; }
.zs-btn-outline {
  background: transparent;
  border: 2px solid currentColor;
  color: var(--zs-color-primary);
}

/* ---------- Marquee ---------- */
.zs-marquee {
  overflow: hidden;
  margin: 3em 0;
  padding: .9rem 0;
  background: var(--zs-color-secondary);
  color: #fff;
}
.zs-marquee-track { display: flex; width: max-content; animation: zs-marquee 26s linear infinite; }
.zs-marquee-run { display: flex; }
.zs-marquee-word {
  padding: 0 2rem;
  font-family: var(--zs-font-heading);
  font-weight: 600;
  white-space: nowrap;
}
.zs-marquee-word::after { content: "•"; margin-left: 2rem; opacity: .45; }
@keyframes zs-marquee {
  from { transform: translateX(0); }
  /* Exactly one run's width, so the second copy lands where the first started. */
  to { transform: translateX(-50%); }
}
/* Motion that never stops is a genuine accessibility problem, so respect the
   system setting rather than animating regardless. */
@media (prefers-reduced-motion: reduce) {
  .zs-marquee-track { animation: none; }
  .zs-slider { scroll-behavior: auto; }
}

/* ---------- Page header ---------- */
.zs-pageheader {
  padding: 3.5rem 1.25rem;
  background: var(--zs-color-surface);
  background-size: cover;
  background-position: center;
  border-radius: var(--zs-radius);
  margin: 0 0 2.5em;
}
.zs-pageheader-image { position: relative; color: #fff; }
/* The scrim is a pseudo-element so the author's background image stays a single
   background declaration and the text keeps its contrast over any photo. */
.zs-pageheader-image::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgb(0 0 0 / .45);
  border-radius: inherit;
}
.zs-pageheader-inner { position: relative; }
.zs-pageheader-image .zs-pageheader-title { color: #fff; }
.zs-pageheader-title { margin: 0; font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.4rem); }
.zs-pageheader-sub { margin: .5em 0 0; opacity: .9; }
/* A logo with no file yet — keeps the row from collapsing while a site is
   still being filled in. */
.zs-logo-name {
  font-family: var(--zs-font-heading);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--zs-color-muted);
  letter-spacing: .01em;
}

/* Theme: โปร่ง ทันสมัย (cargo)
 *
 * Modelled on the airier of the two reference templates: oversized headings,
 * generous vertical rhythm, soft cards that lift off a tinted page, and a
 * header that reads as a floating bar rather than a rule across the top.
 *
 * Everything here is personality over base.css — no block's markup or grid is
 * redefined, so blocks added later inherit this theme's shape for free. */

body {
  background: color-mix(in srgb, var(--zs-color-surface) 55%, var(--zs-color-background));
}

/* Bigger, tighter headings — the single strongest signal of this look. */
h1, h2, h3 { letter-spacing: -0.02em; }
h1 { font-size: clamp(2.4rem, 1.6rem + 3vw, 3.6rem); line-height: 1.12; }
h2 { font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.4rem); }

/* Sections breathe. The base sets 3em; here the page is paced more slowly. */
.zs-stats, .zs-steps, .zs-team, .zs-testimonials, .zs-logos, .zs-services,
.zs-pricing, .zs-gallery, .zs-accordion, .zs-contactinfo, .zs-timeline,
.zs-tabs, .zs-featurelist, .zs-cards-section, .zs-imagetext, .zs-ctaband {
  margin: 5em 0;
}
.zs-blockhead { margin-bottom: 2.75rem; text-align: center; }
.zs-blockhead-sub { margin-inline: auto; }

/* Header: a floating bar with a soft edge instead of a hard border. */
.zs-header {
  border-bottom: 0;
  box-shadow: 0 1px 0 color-mix(in srgb, var(--zs-color-muted) 15%, transparent);
  background: color-mix(in srgb, var(--zs-color-background) 92%, transparent);
  backdrop-filter: saturate(140%) blur(8px);
  position: sticky;
  top: 0;
  z-index: 40;
}
.zs-header-inner { min-height: 4.75rem; }
.zs-nav-list a { font-weight: 500; }

/* Cards and panels: raised, rounded, hairline-free. */
.zs-card, .zs-service, .zs-testimonial, .zs-plan, .zs-accordion-item {
  background: var(--zs-color-background);
  border-radius: calc(var(--zs-radius) * 1.6);
  box-shadow: 0 1px 2px rgb(15 23 42 / .04), 0 8px 24px -12px rgb(15 23 42 / .18);
  border: 0;
}
.zs-service, .zs-card { padding: 1.75rem; }
.zs-service-media { margin: -1.75rem -1.75rem 1.25rem; }
.zs-service-media img { border-radius: calc(var(--zs-radius) * 1.6) calc(var(--zs-radius) * 1.6) 0 0; }
.zs-service-link:hover {
  background: var(--zs-color-background);
  box-shadow: 0 2px 4px rgb(15 23 42 / .05), 0 16px 36px -16px rgb(15 23 42 / .28);
}

/* Buttons: pill-shaped, which reads as the modern-SaaS cue in this style. */
.zs-btn {
  border-radius: 999px;
  padding: .75rem 1.6rem;
  font-weight: 600;
}

/* Stats sit on a panel rather than floating on the page. */
.zs-stats {
  background: var(--zs-color-background);
  border-radius: calc(var(--zs-radius) * 1.6);
  padding: 2.5rem 1.75rem;
  box-shadow: 0 8px 30px -18px rgb(15 23 42 / .25);
}
.zs-stat-value { font-size: clamp(2.2rem, 1.5rem + 2.4vw, 3.4rem); }

/* Numbered steps as light outlines — quieter than the base's solid discs. */
.zs-step-num {
  background: transparent;
  color: var(--zs-color-primary);
  border: 2px solid color-mix(in srgb, var(--zs-color-primary) 35%, transparent);
}

.zs-hero-title { letter-spacing: -0.03em; }
.zs-hero-media img { border-radius: calc(var(--zs-radius) * 1.6); }

.zs-ctaband { border-radius: calc(var(--zs-radius) * 1.6); padding: 3rem 2.5rem; }

.zs-footer { border-top: 0; box-shadow: 0 -1px 0 color-mix(in srgb, var(--zs-color-muted) 15%, transparent); }

/* ══════════ Bands ══════════
   What "dark" and "brand" mean in this theme. Airy and cool: a deep slate the
   hero and closing bands sit on, with a soft gradient so a full-width band
   doesn't read as a flat rectangle. */
:root {
  --zs-tone-soft: color-mix(in srgb, var(--zs-color-surface) 70%, var(--zs-color-background));
  --zs-tone-dark: linear-gradient(160deg,
    color-mix(in srgb, var(--zs-color-secondary) 92%, #000),
    var(--zs-color-secondary) 55%,
    color-mix(in srgb, var(--zs-color-secondary) 78%, var(--zs-color-primary)));
  --zs-tone-brand: linear-gradient(135deg,
    var(--zs-color-primary),
    color-mix(in srgb, var(--zs-color-primary) 70%, var(--zs-color-accent)));
}
.zs-section-band { padding-block: clamp(4rem, 2rem + 6vw, 7.5rem); }

/* Panels inside a dark band lift with light rather than shadow — a drop shadow
   on a dark surface is invisible. */
.zs-section-tone-dark :is(.zs-card, .zs-service, .zs-testimonial, .zs-plan),
.zs-section-tone-brand :is(.zs-card, .zs-service, .zs-testimonial, .zs-plan) {
  background: color-mix(in srgb, #fff 8%, transparent);
  backdrop-filter: blur(2px);
}

/* The stats panel is a page-level card in this theme; inside a band it's
   already on a surface, so it drops back to being plain content. */
.zs-section-band .zs-stats { background: none; box-shadow: none; padding: 0; }

/* Type: the display sizes are where this theme's confidence comes from. */
.zs-blockhead h2 { font-size: clamp(1.9rem, 1.3rem + 2.2vw, 2.9rem); }
.zs-blockhead-sub { font-size: 1.12rem; }
.zs-eyebrow { letter-spacing: .18em; }
/* Centred heads means a rule on one side only reads as a mistake. */
.zs-blockhead .zs-eyebrow::after, .zs-hero-center .zs-eyebrow::after {
  content: "";
  width: 1.8em;
  height: 2px;
  background: currentColor;
  opacity: .6;
}
.zs-blockhead .zs-eyebrow, .zs-hero-center .zs-eyebrow { display: inline-flex; }

.zs-icon-badge { width: 3.75rem; height: 3.75rem; }
.zs-icon { width: 1.75rem; height: 1.75rem; }
