/* ============================================================
   China Web Search — B2B Landing Page Stylesheet  v2
   ------------------------------------------------------------
   IMPORTANT: This file MUST stay external.
   Do NOT move these rules back into a <style> block inside
   source/index.md — markdown-it terminates an HTML block at the
   first blank line, then renders the remaining CSS as prose
   (injecting <p>/<br> and converting " into curly quotes),
   which silently breaks font-family and every rule after it.
   ------------------------------------------------------------
   Visual language: Framer-grade editorial B2B.
   Dark hero -> light body -> dark CTA sandwich.
   Namespace: .cws-landing
   ============================================================ */

/* ============================================================
   1. DESIGN TOKENS
   ------------------------------------------------------------
   The token block is shared on purpose. /blog/ and the article pages
   are real Fluid routes, not .cws-landing wrappers, so they opt in
   by BODY CLASS instead of by markup. Only the tokens (custom
   properties, which inherit) are shared — the resets and typography
   below stay scoped to .cws-landing so they can never leak into
   Fluid's navbar, footer or prose.
   ============================================================ */
.cws-landing,
body.cws-blog,
body.cws-article {
  /* -- brand ------------------------------------------------- */
  --cws-brand:       #D32F2F;
  --cws-brand-600:   #B71C1C;
  --cws-brand-hi:    #FF4D4F;   /* on dark surfaces */
  --cws-brand-wash:  #FEF3F2;

  /* -- ink & text -------------------------------------------- */
  --cws-ink:         #05070D;   /* near-black navy */
  --cws-ink-3:       #1B2130;
  --cws-body:        #4C5464;
  --cws-muted:       #7C8595;
  --cws-faint:       #A6AEBD;

  /* -- light surfaces ---------------------------------------- */
  --cws-bg:          #FFFFFF;
  --cws-bg-2:        #F7F8FA;
  --cws-bg-3:        #EFF1F5;
  --cws-line:        rgba(5, 7, 13, 0.10);
  --cws-line-2:      rgba(5, 7, 13, 0.055);

  /* -- dark surfaces ----------------------------------------- */
  --cws-dark:        #05070D;
  --cws-dark-2:      #0C1018;
  --cws-dark-3:      #141926;
  --cws-dark-line:   rgba(255, 255, 255, 0.10);
  --cws-on-dark:     rgba(255, 255, 255, 0.94);
  --cws-on-dark-2:   rgba(255, 255, 255, 0.60);
  --cws-on-dark-3:   rgba(255, 255, 255, 0.38);

  /* -- type -------------------------------------------------- */
  --cws-font-display: "Poppins", "Inter", system-ui, -apple-system,
                      "Segoe UI", Roboto, "Helvetica Neue", Arial,
                      "PingFang SC", "Microsoft YaHei", sans-serif;
  --cws-font-body:    "Figtree", "Inter", system-ui, -apple-system,
                      "Segoe UI", Roboto, "Helvetica Neue", Arial,
                      "PingFang SC", "Microsoft YaHei", sans-serif;
  --cws-font-mono:    "Geist Mono", "JetBrains Mono", ui-monospace,
                      SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --cws-fs-display: clamp(2.6rem, 6.6vw, 5rem);
  --cws-fs-h2:      clamp(2rem, 4.1vw, 3.4rem);
  --cws-fs-h3:      clamp(1.2rem, 1.7vw, 1.5rem);
  --cws-fs-lead:    clamp(1.0625rem, 1.35vw, 1.25rem);
  --cws-fs-body:    1.0625rem;
  --cws-fs-small:   0.9375rem;
  --cws-fs-eyebrow: 0.6875rem;

  /* -- shape ------------------------------------------------- */
  --cws-r-sm:   10px;
  --cws-r:      14px;
  --cws-r-lg:   22px;
  --cws-r-xl:   30px;
  --cws-pill:   999px;

  /* -- elevation: restrained, Framer-like -------------------- */
  --cws-sh-1: 0 1px 2px rgba(5, 7, 13, .04);
  --cws-sh-2: 0 2px 4px rgba(5, 7, 13, .03), 0 8px 20px -8px rgba(5, 7, 13, .08);
  --cws-sh-3: 0 18px 44px -16px rgba(5, 7, 13, .18), 0 2px 6px rgba(5, 7, 13, .04);
  --cws-lift: -5px;

  /* -- layout ------------------------------------------------ */
  --cws-maxw:   1200px;
  --cws-gutter: clamp(20px, 4.5vw, 40px);
  --cws-pad-y:  clamp(76px, 8.5vw, 132px);

  /* -- motion ------------------------------------------------ */
  --cws-ease: cubic-bezier(.22, .61, .36, 1);
  --cws-dur:  .55s;
}

/* ============================================================
   2. BASE / RESET
   ============================================================ */
.cws-landing,
.cws-landing *,
.cws-landing *::before,
.cws-landing *::after { box-sizing: border-box; }

.cws-landing {
  font-family: var(--cws-font-body);
  font-size: var(--cws-fs-body);
  line-height: 1.65;
  color: var(--cws-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "kern" 1, "liga" 1;
  overflow-x: clip;
}

.cws-landing h1,
.cws-landing h2,
.cws-landing h3,
.cws-landing h4 {
  font-family: var(--cws-font-display);
  color: var(--cws-ink);
  font-weight: 600;
  letter-spacing: -0.032em;
  line-height: 1.06;
  margin: 0;
  text-wrap: balance;
}
.cws-landing h3 { letter-spacing: -0.022em; line-height: 1.22; }
.cws-landing h4 { letter-spacing: -0.015em; line-height: 1.3; font-size: 1.0625rem; }
.cws-landing p  { margin: 0; text-wrap: pretty; }
/* ⚠️ The reset above outranks any bare `.cws-*__sub` (0,1,0) rule — always
   scope sub-class margins as `.cws-landing .cws-hero__sub` etc., see hero/contact. */
.cws-landing a  { color: inherit; text-decoration: none; }

/* ⚠️ Specificity guard.
   `.cws-landing a` is (0,1,1) and therefore OUTRANKS `.cws-btn` (0,1,0).
   Without this rule every <a class="cws-btn"> silently inherits its
   container's colour instead of its own --_fg, which turned the white
   hero CTA into white-on-white (invisible). <button class="cws-btn">
   was unaffected, so the bug only showed on link buttons.
   Scoped to .cws-btn so no other link styling is touched. */
.cws-landing .cws-btn { color: var(--_fg); }

.cws-landing img { max-width: 100%; display: block; }
.cws-landing ul { margin: 0; padding: 0; list-style: none; }

/* ============================================================
   3. PRIMITIVES
   ============================================================ */
.cws-wrap {
  width: 100%;
  max-width: var(--cws-maxw);
  margin-inline: auto;
  padding-inline: var(--cws-gutter);
}
.cws-sec { padding-block: var(--cws-pad-y); position: relative; }
.cws-sec--tight { padding-block: clamp(56px, 6vw, 92px); }
.cws-sec--alt { background: var(--cws-bg-2); }
.cws-sec--line { border-top: 1px solid var(--cws-line-2); }

/* mono eyebrow — the single biggest "expensive" signal */
.cws-eyebrow {
  font-family: var(--cws-font-mono);
  font-size: var(--cws-fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cws-muted);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 22px;
}
.cws-eyebrow::before {
  content: "";
  width: 22px;
  height: 1px;
  background: var(--cws-brand);
  flex: none;
}
.cws-eyebrow--plain::before { display: none; }
.cws-eyebrow--light { color: var(--cws-on-dark-3); }

.cws-h2 { font-size: var(--cws-fs-h2); }
.cws-lead {
  font-size: var(--cws-fs-lead);
  line-height: 1.62;
  color: var(--cws-body);
  max-width: 60ch;
  margin-top: 20px;
}

/* section head: left title + right supporting copy */
.cws-head {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(28px, 5vw, 72px);
  align-items: end;
  margin-bottom: clamp(44px, 5vw, 72px);
}
.cws-head__aside { padding-bottom: 6px; }
.cws-head .cws-lead { margin-top: 0; }

/* ---- buttons ---- */
.cws-btn {
  --_bg: var(--cws-brand);
  --_fg: #fff;
  --_bd: var(--cws-brand);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 28px;
  border-radius: var(--cws-pill);
  background: var(--_bg);
  color: var(--_fg);
  border: 1px solid var(--_bd);
  font-family: var(--cws-font-body);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  transition: transform .28s var(--cws-ease),
              background-color .28s var(--cws-ease),
              border-color .28s var(--cws-ease),
              box-shadow .28s var(--cws-ease),
              color .28s var(--cws-ease);
}
.cws-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 26px -10px rgba(211, 47, 47, .55);
}
.cws-btn:active { transform: translateY(0); }
.cws-btn:focus-visible { outline: 2px solid var(--cws-brand); outline-offset: 3px; }
.cws-btn__arrow { transition: transform .28s var(--cws-ease); flex: none; }
.cws-btn:hover .cws-btn__arrow { transform: translateX(4px); }

.cws-btn--ghost { --_bg: transparent; --_fg: var(--cws-ink); --_bd: var(--cws-line); }
.cws-btn--ghost:hover {
  --_bd: rgba(5, 7, 13, .22);
  background: rgba(5, 7, 13, .03);
  box-shadow: none;
}
.cws-btn--light { --_bg: #fff; --_fg: var(--cws-ink); --_bd: #fff; }
.cws-btn--light:hover { box-shadow: 0 12px 30px -12px rgba(255,255,255,.4); }
.cws-btn--outline-light { --_bg: transparent; --_fg: #fff; --_bd: rgba(255, 255, 255, .26); }
.cws-btn--outline-light:hover {
  --_bd: rgba(255, 255, 255, .55);
  background: rgba(255, 255, 255, .06);
  box-shadow: none;
}
.cws-btn--sm { padding: 11px 20px; font-size: 0.875rem; }
.cws-btn--block { width: 100%; }

.cws-cta-row { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }

.cws-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--cws-ink);
  transition: gap .25s var(--cws-ease), color .25s var(--cws-ease);
}
.cws-link:hover { gap: 12px; color: var(--cws-brand); }
.cws-link svg { flex: none; }

/* ============================================================
   4. HERO  (dark, high contrast)
   ============================================================ */
.cws-hero {
  position: relative;
  background: var(--cws-dark);
  color: var(--cws-on-dark);
  /* the Fluid navbar is position:fixed — clear it explicitly */
  padding-top: calc(64px + clamp(28px, 5vw, 64px));
  padding-bottom: clamp(64px, 8vw, 116px);
  overflow: hidden;
  isolation: isolate;
}
.cws-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, rgba(255,255,255,.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.045) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: radial-gradient(120% 90% at 50% 0%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(120% 90% at 50% 0%, #000 20%, transparent 78%);
  z-index: -2;
}
.cws-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(52% 62% at 78% 8%,  rgba(211, 47, 47, .30), transparent 62%),
    radial-gradient(46% 56% at 8% 92%,  rgba(39, 84, 220, .22), transparent 66%);
  z-index: -1;
  pointer-events: none;
}
.cws-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(40px, 6vw, 84px);
  align-items: center;
}
.cws-hero__badge {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 15px 7px 9px;
  border-radius: var(--cws-pill);
  border: 1px solid rgba(255, 255, 255, .16);
  background: rgba(255, 255, 255, .05);
  font-family: var(--cws-font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .78);
  margin-bottom: 28px;
}
.cws-hero__dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--cws-brand-hi);
  box-shadow: 0 0 0 4px rgba(255, 77, 79, .22);
  flex: none;
}
.cws-hero h1 {
  font-size: var(--cws-fs-display);
  color: #fff;
  font-weight: 600;
  letter-spacing: -0.042em;
  line-height: 1.02;
}
.cws-hero h1 em { font-style: normal; color: var(--cws-brand-hi); }
.cws-hero h1 .cws-dim { color: rgba(255, 255, 255, .38); }
.cws-landing .cws-hero__sub {
  margin-top: 26px;
  font-size: var(--cws-fs-lead);
  line-height: 1.62;
  color: var(--cws-on-dark-2);
  max-width: 54ch;
}
.cws-hero__cta { margin-top: 38px; }
.cws-hero__note {
  margin-top: 26px;
  font-family: var(--cws-font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cws-on-dark-3);
}

/* ---- inner-page header ----------------------------------------
   Same dark language as the hero, single column, tighter rhythm.
   Used by /contact/ (and any page tagged cws_marketing).
   Clears the Fluid fixed navbar the same explicit way .cws-hero
   does, so the two never drift apart. */
.cws-pagehead {
  position: relative;
  background: var(--cws-dark);
  color: var(--cws-on-dark);
  padding-top: calc(64px + clamp(40px, 6vw, 78px));
  padding-bottom: clamp(52px, 6vw, 84px);
  overflow: hidden;
  isolation: isolate;
}
.cws-pagehead::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(52% 66% at 82% 6%, rgba(211, 47, 47, .22), transparent 62%);
  z-index: -1;
  pointer-events: none;
}
.cws-pagehead h1 {
  font-size: var(--cws-fs-h2);
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: #fff;
  margin: 0;
  max-width: 22ch;
}
.cws-pagehead .cws-lead {
  color: var(--cws-on-dark-2);
  margin-top: 24px;
  max-width: 58ch;
}
.cws-pagehead .cws-eyebrow { color: var(--cws-on-dark-3); }
.cws-pagehead .cws-eyebrow::before { background: var(--cws-brand-hi); }

/* breadcrumb strip under the page header */
.cws-crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 9px;
  font-size: 0.8125rem;
  color: var(--cws-on-dark-3);
  margin-top: 28px;
}
.cws-crumbs a { color: var(--cws-on-dark-2); text-decoration: none; }
.cws-crumbs a:hover { color: #fff; }
.cws-crumbs span[aria-hidden] { opacity: .45; }

/* hero side panel: live-ish metrics card */
.cws-hero__panel {
  border: 1px solid var(--cws-dark-line);
  border-radius: var(--cws-r-xl);
  background: linear-gradient(160deg, rgba(255,255,255,.07), rgba(255,255,255,.02));
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  padding: 26px;
}
.cws-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cws-on-dark-3);
  padding-bottom: 16px;
  border-bottom: 1px solid var(--cws-dark-line);
}
.cws-panel__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 15px 0;
  border-bottom: 1px dashed rgba(255,255,255,.07);
}
.cws-panel__row:last-child { border-bottom: 0; padding-bottom: 0; }
.cws-panel__k { font-size: 0.9375rem; color: var(--cws-on-dark-2); }
.cws-panel__v {
  font-family: var(--cws-font-display);
  font-size: 1.375rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: #fff;
}
.cws-panel__v span { font-size: 0.75rem; color: var(--cws-brand-hi); margin-left: 6px; }
.cws-panel__bars { display: flex; align-items: flex-end; gap: 6px; height: 62px; margin-top: 6px; }
.cws-panel__bars i {
  flex: 1;
  border-radius: 3px 3px 0 0;
  background: linear-gradient(to top, rgba(255,77,79,.25), rgba(255,77,79,.85));
}

/* ============================================================
   5. TRUST STRIP  (marquee)
   ============================================================ */
.cws-trust {
  background: var(--cws-bg);
  border-bottom: 1px solid var(--cws-line-2);
  padding-block: clamp(30px, 3.2vw, 44px);
}
.cws-trust__label {
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--cws-faint);
  text-align: center;
  margin-bottom: 22px;
}
.cws-marquee {
  position: relative;
  overflow: hidden;
  mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}
.cws-marquee__track {
  display: flex;
  width: max-content;
  gap: clamp(40px, 5vw, 76px);
  animation: cws-marquee 34s linear infinite;
}
.cws-marquee:hover .cws-marquee__track { animation-play-state: paused; }
.cws-marquee__item {
  font-family: var(--cws-font-display);
  font-size: clamp(1rem, 1.5vw, 1.25rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--cws-faint);
  white-space: nowrap;
  transition: color .3s var(--cws-ease);
}
.cws-marquee__item:hover { color: var(--cws-ink); }
@keyframes cws-marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* partner badges (static, cert style) */
.cws-badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 30px;
}
.cws-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 15px;
  border: 1px solid var(--cws-line-2);
  border-radius: var(--cws-pill);
  background: var(--cws-bg-2);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--cws-body);
  transition: border-color .3s var(--cws-ease), color .3s var(--cws-ease);
}
.cws-badge:hover { border-color: var(--cws-line); color: var(--cws-ink); }
.cws-badge svg { flex: none; color: var(--cws-brand); }

/* ============================================================
   6. STATS  (dark band)
   ============================================================ */
.cws-stats { background: var(--cws-dark); color: var(--cws-on-dark); }
.cws-stats__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--cws-dark-line);
  border: 1px solid var(--cws-dark-line);
  border-radius: var(--cws-r-lg);
  overflow: hidden;
}
.cws-stat {
  background: var(--cws-dark);
  padding: clamp(26px, 3vw, 40px) clamp(20px, 2.4vw, 30px);
}
.cws-stat__num {
  font-family: var(--cws-font-display);
  font-size: clamp(2.25rem, 3.6vw, 3.25rem);
  font-weight: 600;
  letter-spacing: -0.045em;
  line-height: 1;
  color: #fff;
  display: flex;
  align-items: baseline;
}
.cws-stat__num i { font-style: normal; color: var(--cws-brand-hi); }
.cws-stat__label {
  margin-top: 14px;
  font-size: 0.9375rem;
  color: var(--cws-on-dark-2);
  line-height: 1.5;
}
.cws-stat__meta {
  margin-top: 6px;
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cws-on-dark-3);
}

/* ============================================================
   7. MANIFESTO  (big statement + two-column argument)
   ============================================================ */
.cws-manifesto__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 76px);
  align-items: start;
}
.cws-manifesto__statement {
  font-family: var(--cws-font-display);
  font-size: clamp(1.5rem, 2.6vw, 2.125rem);
  font-weight: 600;
  letter-spacing: -0.032em;
  line-height: 1.22;
  color: var(--cws-ink);
}
.cws-manifesto__statement b { color: var(--cws-brand); font-weight: 600; }
.cws-manifesto__body p + p { margin-top: 18px; }
.cws-manifesto__body { font-size: var(--cws-fs-body); line-height: 1.72; }
.cws-manifesto__list { margin-top: 26px; display: grid; gap: 12px; }
.cws-manifesto__list li {
  display: flex;
  gap: 12px;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--cws-body);
}
.cws-manifesto__list svg { flex: none; margin-top: 3px; color: var(--cws-brand); }

/* ============================================================
   8. SERVICES GRID
   ============================================================ */
.cws-svc {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 1.8vw, 24px);
}
.cws-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(26px, 2.6vw, 34px);
  border: 1px solid var(--cws-line-2);
  border-radius: var(--cws-r-lg);
  background: var(--cws-bg);
  transition: transform .4s var(--cws-ease),
              border-color .4s var(--cws-ease),
              box-shadow .4s var(--cws-ease);
  will-change: transform;
}
.cws-card:hover {
  transform: translateY(var(--cws-lift));
  border-color: rgba(211, 47, 47, .30);
  box-shadow: var(--cws-sh-3);
}
/* hairline highlight on hover */
.cws-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(150deg, rgba(211,47,47,.55), transparent 42%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity .4s var(--cws-ease);
  pointer-events: none;
}
.cws-card:hover::after { opacity: 1; }

.cws-card__num {
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.18em;
  color: var(--cws-faint);
  margin-bottom: 20px;
}
.cws-card__icon {
  width: 46px;
  height: 46px;
  border-radius: var(--cws-r-sm);
  display: grid;
  place-items: center;
  background: var(--cws-brand-wash);
  color: var(--cws-brand);
  margin-bottom: 20px;
  transition: background-color .35s var(--cws-ease), color .35s var(--cws-ease);
}
.cws-card:hover .cws-card__icon { background: var(--cws-brand); color: #fff; }
.cws-card h3 { font-size: var(--cws-fs-h3); margin-bottom: 12px; }
.cws-card p { font-size: 0.9375rem; line-height: 1.68; color: var(--cws-body); }
.cws-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--cws-line-2);
}
.cws-card__tags span {
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cws-muted);
  padding: 4px 9px;
  border-radius: var(--cws-pill);
  background: var(--cws-bg-2);
}
.cws-card__foot { margin-top: auto; padding-top: 22px; }

/* ============================================================
   9. PROCESS  (sticky heading + numbered steps)
   ============================================================ */
.cws-proc {
  display: grid;
  grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
  gap: clamp(36px, 6vw, 96px);
  align-items: start;
}
.cws-proc__aside { position: sticky; top: 108px; }
.cws-proc__steps { display: grid; }
.cws-step {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr);
  gap: clamp(18px, 2.4vw, 32px);
  padding: clamp(26px, 3vw, 36px) 0;
  border-top: 1px solid var(--cws-line-2);
}
.cws-step:first-child { border-top: 0; padding-top: 0; }
.cws-step__num {
  font-family: var(--cws-font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  color: var(--cws-faint);
  padding-top: 5px;
}
.cws-step h3 { font-size: clamp(1.125rem, 1.6vw, 1.375rem); margin-bottom: 10px; }
.cws-step p { font-size: 0.9375rem; line-height: 1.7; color: var(--cws-body); }
.cws-step__tag {
  display: inline-block;
  margin-top: 14px;
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cws-brand);
}

/* ============================================================
   10. CASE STUDIES
   ============================================================ */
.cws-cases {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 1.8vw, 24px);
}
.cws-case {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--cws-line-2);
  border-radius: var(--cws-r-lg);
  overflow: hidden;
  background: var(--cws-bg);
  transition: transform .4s var(--cws-ease),
              border-color .4s var(--cws-ease),
              box-shadow .4s var(--cws-ease);
}
.cws-case:hover {
  transform: translateY(var(--cws-lift));
  border-color: rgba(211, 47, 47, .30);
  box-shadow: var(--cws-sh-3);
}
.cws-case__media {
  position: relative;
  aspect-ratio: 16 / 10;
  background: linear-gradient(140deg, #10141F, #05070D 60%);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.cws-case__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(60% 70% at 70% 20%, rgba(211,47,47,.34), transparent 62%);
}
.cws-case__ind {
  position: relative;
  z-index: 1;
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255,255,255,.72);
  padding: 7px 14px;
  border: 1px solid rgba(255,255,255,.2);
  border-radius: var(--cws-pill);
}
.cws-case__body { padding: clamp(22px, 2.4vw, 30px); display: flex; flex-direction: column; flex: 1; }
.cws-case__kpis {
  display: flex;
  gap: 24px;
  margin-bottom: 18px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--cws-line-2);
}
.cws-case__kpi b {
  display: block;
  font-family: var(--cws-font-display);
  font-size: 1.625rem;
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1.1;
  color: var(--cws-brand);
}
.cws-case__kpi span {
  display: block;
  margin-top: 4px;
  font-size: 0.75rem;
  color: var(--cws-muted);
  line-height: 1.4;
}
.cws-case h3 { font-size: 1.1875rem; margin-bottom: 10px; }
.cws-case__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.cws-case__tags span {
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cws-muted);
  padding: 4px 9px;
  border-radius: var(--cws-pill);
  background: var(--cws-bg-2);
}
.cws-case p { font-size: 0.9375rem; line-height: 1.68; }
.cws-case__foot { margin-top: auto; padding-top: 22px; }

/* ============================================================
   11. ALIGNMENT  (who we work with)
   ============================================================ */
.cws-fit { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(16px, 2vw, 26px); }
.cws-fit__col {
  border: 1px solid var(--cws-line-2);
  border-radius: var(--cws-r-lg);
  padding: clamp(26px, 3vw, 38px);
  background: var(--cws-bg);
}
.cws-fit__col--no { background: var(--cws-bg-2); }
.cws-fit__col--yes { border-color: rgba(211, 47, 47, .26); background: var(--cws-brand-wash); }
.cws-fit__title {
  display: flex;
  align-items: center;
  gap: 11px;
  font-family: var(--cws-font-display);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--cws-ink);
  margin-bottom: 22px;
}
.cws-fit__title svg { flex: none; }
.cws-fit__col--yes .cws-fit__title svg { color: var(--cws-brand); }
.cws-fit__col--no .cws-fit__title svg { color: var(--cws-muted); }
.cws-fit__list li {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 12px;
  padding: 13px 0;
  border-top: 1px solid var(--cws-line-2);
  font-size: 0.9375rem;
  line-height: 1.6;
}
.cws-fit__list li:first-child { border-top: 0; padding-top: 0; }
.cws-fit__list b { display: block; color: var(--cws-ink); font-weight: 600; margin-bottom: 2px; }
.cws-fit__list span { color: var(--cws-body); }
.cws-fit__mark { margin-top: 4px; flex: none; }

/* ============================================================
   12. CONTACT  (dark, conversion-focused)
   ============================================================ */
.cws-contact {
  background: var(--cws-dark);
  color: var(--cws-on-dark);
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.cws-contact::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(48% 60% at 88% 12%, rgba(211,47,47,.26), transparent 64%);
  z-index: -1;
}
.cws-contact__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(40px, 6vw, 88px);
  align-items: start;
}
.cws-contact h2 { color: #fff; font-size: var(--cws-fs-h2); }
.cws-landing .cws-contact__sub {
  margin-top: 20px;
  font-size: var(--cws-fs-lead);
  line-height: 1.62;
  color: var(--cws-on-dark-2);
  max-width: 46ch;
}
.cws-contact__meta { margin-top: 38px; display: grid; gap: 2px; }
.cws-contact__item {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 16px 0;
  border-top: 1px solid var(--cws-dark-line);
}
.cws-contact__item:last-child { border-bottom: 1px solid var(--cws-dark-line); }
.cws-contact__item svg { flex: none; margin-top: 3px; color: var(--cws-brand-hi); }
.cws-contact__item b {
  display: block;
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cws-on-dark-3);
  margin-bottom: 5px;
  font-weight: 500;
}
.cws-contact__item span { color: var(--cws-on-dark); font-size: 0.9375rem; }

/* ---- form ---- */
.cws-form {
  border: 1px solid var(--cws-dark-line);
  border-radius: var(--cws-r-xl);
  background: rgba(255, 255, 255, .035);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding: clamp(26px, 3vw, 40px);
}
.cws-form__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.cws-field { display: grid; gap: 8px; margin-bottom: 16px; }
.cws-field label {
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cws-on-dark-3);
}
.cws-field input,
.cws-field select,
.cws-field textarea {
  width: 100%;
  padding: 13px 15px;
  border-radius: var(--cws-r-sm);
  border: 1px solid rgba(255, 255, 255, .14);
  background: rgba(255, 255, 255, .04);
  color: #fff;
  font-family: var(--cws-font-body);
  font-size: 0.9375rem;
  line-height: 1.5;
  transition: border-color .25s var(--cws-ease), background-color .25s var(--cws-ease);
  -webkit-appearance: none;
  appearance: none;
}
.cws-field textarea { min-height: 116px; resize: vertical; }
.cws-field select {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%23ffffff' stroke-opacity='.5' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 15px center;
  padding-right: 38px;
}
.cws-field select option { color: #0b0f18; }
.cws-field input::placeholder,
.cws-field textarea::placeholder { color: rgba(255, 255, 255, .30); }
.cws-field input:focus,
.cws-field select:focus,
.cws-field textarea:focus {
  outline: none;
  border-color: rgba(255, 77, 79, .70);
  background: rgba(255, 255, 255, .07);
}
.cws-field--invalid input,
.cws-field--invalid select,
.cws-field--invalid textarea { border-color: #FF6B6B; }
.cws-field__err {
  font-size: 0.75rem;
  color: #FF8A8A;
  min-height: 0;
}
/* honeypot — hidden from humans, visible to bots */
.cws-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.cws-form__foot { margin-top: 20px; display: grid; gap: 14px; }
.cws-form__consent {
  font-size: 0.75rem;
  line-height: 1.55;
  color: var(--cws-on-dark-3);
}
.cws-form__consent a { color: var(--cws-on-dark-2); text-decoration: underline; text-underline-offset: 2px; }
.cws-form__msg {
  font-size: 0.875rem;
  line-height: 1.5;
  padding: 0;
  border-radius: var(--cws-r-sm);
  border: 0;
  display: none;
}
.cws-form__msg.is-ok,
.cws-form__msg.is-err { display: block; padding: 12px 15px; border: 1px solid; }
.cws-form__msg.is-ok { background: rgba(52, 199, 123, .14); color: #6EE7A8; border-color: rgba(52,199,123,.3); }
.cws-form__msg.is-err { background: rgba(255, 107, 107, .12); color: #FF9B9B; border-color: rgba(255,107,107,.3); }
.cws-btn[disabled] { opacity: .6; pointer-events: none; }

/* ============================================================
   13. FAQQ
   ============================================================ */
.cws-faq { max-width: 860px; margin-inline: auto; }
.cws-faq details {
  border-bottom: 1px solid var(--cws-line-2);
}
.cws-faq details:first-of-type { border-top: 1px solid var(--cws-line-2); }
.cws-faq summary {
  list-style: none;
  cursor: pointer;
  padding: 24px 44px 24px 0;
  position: relative;
  font-family: var(--cws-font-display);
  font-size: clamp(1.0625rem, 1.4vw, 1.1875rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--cws-ink);
  transition: color .25s var(--cws-ease);
}
.cws-faq summary::-webkit-details-marker { display: none; }
.cws-faq summary:hover { color: var(--cws-brand); }
.cws-faq summary::after {
  content: "";
  position: absolute;
  right: 6px;
  top: 50%;
  width: 11px;
  height: 11px;
  margin-top: -6px;
  border-right: 2px solid var(--cws-muted);
  border-bottom: 2px solid var(--cws-muted);
  transform: rotate(45deg);
  transition: transform .3s var(--cws-ease), border-color .25s var(--cws-ease);
}
.cws-faq details[open] summary::after { transform: rotate(225deg); margin-top: -2px; border-color: var(--cws-brand); }
.cws-faq details p {
  padding: 0 44px 26px 0;
  font-size: 0.9375rem;
  line-height: 1.72;
  color: var(--cws-body);
}
.cws-faq details p a {
  color: var(--cws-brand);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.cws-faq details p a:hover { color: var(--cws-brand-600); }

/* ============================================================
   14. FINAL CTA BAND
   ============================================================ */
.cws-final {
  background: var(--cws-bg-2);
  border-top: 1px solid var(--cws-line-2);
  text-align: center;
}
.cws-final h2 { font-size: var(--cws-fs-h2); }
.cws-final .cws-lead { margin-inline: auto; }
.cws-final .cws-cta-row { justify-content: center; margin-top: 32px; }

/* ============================================================
   15. SCROLL REVEAL  (Framer-style blur-in)
   ------------------------------------------------------------
   JS adds .is-in when the element enters the viewport.

   The hidden starting state is scoped to html.cws-js, which is
   set by a tiny inline script injected post-render. If JS never
   runs, the selector never matches and the content simply shows
   — the page degrades to plain, fully-visible HTML instead of
   a blank screen. (Never invert this: an unconditional
   opacity:0 plus a JS-dependent reveal makes the whole page
   invisible to crawlers and no-JS users.)
   ============================================================ */
.cws-reveal {
  transition: opacity .7s var(--cws-ease),
              transform .7s var(--cws-ease),
              filter .7s var(--cws-ease);
  transition-delay: var(--d, 0ms);
}
html.cws-js .cws-reveal {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  filter: blur(6px);
}
html.cws-js .cws-reveal.is-in { opacity: 1; transform: none; filter: none; }

/* per-word reveal for display headings */
.cws-word {
  display: inline-block;
  transition: opacity .6s var(--cws-ease),
              transform .6s var(--cws-ease),
              filter .6s var(--cws-ease);
  transition-delay: calc(var(--i, 0) * 42ms);
}
html.cws-js .cws-word {
  opacity: 0;
  transform: translate3d(0, .32em, 0);
  filter: blur(8px);
}
html.cws-js .cws-word.is-in { opacity: 1; transform: none; filter: none; }
.cws-word-wrap { display: inline; }

/* ============================================================
   16. DECORATIVE FX — abstract tech motifs
   ------------------------------------------------------------
   Zero image requests: everything below is CSS paint.
   Drop ONE empty element inside any dark section:

       <span class="cws-fx" aria-hidden="true"></span>

   It paints three motifs at once — a concentric "radar" ring
   stack, a dot matrix and a slow rotating sweep — then masks
   them radially so the copy area stays clean.

   The parent needs `isolation: isolate` (or a stacking context)
   for z-index:-1 to sit above its own background. Dark sections
   here already have it.
   ============================================================ */
.cws-fx {
  position: absolute;
  z-index: -1;
  pointer-events: none;
  top: -24%;
  right: -18%;
  width: min(780px, 78vw);
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  background-image:
    radial-gradient(rgba(255, 255, 255, .21) 1.1px, transparent 1.5px),
    repeating-radial-gradient(circle at 50% 50%,
      rgba(255, 255, 255, .082) 0 1px, transparent 1px 84px);
  background-size: 24px 24px, auto;
  -webkit-mask-image: radial-gradient(circle at 50% 50%,
    #000 6%, rgba(0, 0, 0, .88) 30%, rgba(0, 0, 0, .34) 62%, transparent 88%);
  mask-image: radial-gradient(circle at 50% 50%,
    #000 6%, rgba(0, 0, 0, .88) 30%, rgba(0, 0, 0, .34) 62%, transparent 88%);
  opacity: .92;
}

/* the page head is a short band, so centre the motif inside it.
   Anchoring it off the top corner (as on the tall hero) clips the
   sweep into a stray crescent against the top edge. */
.cws-pagehead .cws-fx {
  top: 50%;
  right: -5%;
  transform: translateY(-50%);
  width: min(540px, 52vw);
  opacity: .72;
}

/* rotating sweep — the "radar" arm */
.cws-fx::before {
  content: "";
  position: absolute;
  inset: 24%;
  border-radius: 50%;
  background: conic-gradient(from 0deg,
    rgba(255, 77, 79, .9),
    rgba(255, 77, 79, .16) 17%,
    transparent 33%,
    transparent 100%);
  -webkit-mask-image: radial-gradient(closest-side,
    transparent 74%, #000 77%, #000 97%, transparent 99%);
  mask-image: radial-gradient(closest-side,
    transparent 74%, #000 77%, #000 97%, transparent 99%);
  animation: cws-fx-spin 24s linear infinite;
}

/* dashed orbit — rotates the other way, much slower */
.cws-fx::after {
  content: "";
  position: absolute;
  inset: 3%;
  border-radius: 50%;
  border: 1px dashed rgba(255, 255, 255, .17);
  animation: cws-fx-spin 96s linear infinite reverse;
}

@keyframes cws-fx-spin { to { transform: rotate(360deg); } }

/* mirror copy, anchored bottom-left, tinted with the secondary glow */
.cws-fx--mirror {
  top: auto;
  right: auto;
  bottom: -30%;
  left: -20%;
  background-image:
    radial-gradient(rgba(255, 255, 255, .12) 1.1px, transparent 1.5px),
    repeating-radial-gradient(circle at 50% 50%,
      rgba(255, 255, 255, .05) 0 1px, transparent 1px 96px);
}
.cws-fx--mirror::before {
  background: conic-gradient(from 180deg,
    rgba(39, 84, 220, .75),
    rgba(39, 84, 220, .12) 17%,
    transparent 33%,
    transparent 100%);
  animation-duration: 34s;
}
.cws-fx--dim { opacity: .45; }

/* connected-node constellation — the clearest "tech" read.
   Uses an inline <svg> child, so no network request. */
.cws-fx--mesh {
  top: auto;
  right: auto;
  bottom: -14%;
  left: -4%;
  width: min(540px, 54vw);
  aspect-ratio: 420 / 320;
  border-radius: 0;
  background-image: none;
  -webkit-mask-image: radial-gradient(72% 76% at 42% 62%, #000 26%, transparent 88%);
  mask-image: radial-gradient(72% 76% at 42% 62%, #000 26%, transparent 88%);
  opacity: .8;
}
.cws-fx--mesh::before,
.cws-fx--mesh::after { content: none; }
.cws-fx--mesh svg { width: 100%; height: 100%; display: block; }

/* pinging nodes on the constellation */
.cws-node {
  transform-box: fill-box;
  transform-origin: center;
  animation: cws-node 4.4s ease-in-out infinite;
}
.cws-node--b { animation-delay: 1.5s; }
.cws-node--c { animation-delay: 2.9s; }
@keyframes cws-node {
  0%, 100% { transform: scale(1);   opacity: .4; }
  50%      { transform: scale(2.2); opacity: 1; }
}

/* ============================================================
   17. SERVICE PAGES — components
   ------------------------------------------------------------
   Built entirely on the tokens above, so the service pages
   inherit the site palette with no new colours.
   ============================================================ */

/* page head: allow longer editorial headlines + a CTA row */
.cws-pagehead h1 { max-width: 25ch; }
.cws-pagehead .cws-cta-row { margin-top: 34px; }
.cws-pagehead__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 30px;
}
.cws-pagehead__meta span {
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .72);
  padding: 6px 12px;
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: var(--cws-pill);
  background: rgba(255, 255, 255, .045);
}

/* dark content band — the service pages alternate light/dark */
.cws-sec--dark {
  background: var(--cws-dark);
  color: var(--cws-on-dark);
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.cws-sec--dark .cws-h2,
.cws-sec--dark .cws-manifesto__statement,
.cws-sec--dark .cws-card h3,
.cws-sec--dark .cws-step h3 { color: #fff; }
.cws-sec--dark .cws-lead,
.cws-sec--dark .cws-manifesto__body,
.cws-sec--dark .cws-card p,
.cws-sec--dark .cws-step p,
.cws-sec--dark .cws-manifesto__list li { color: var(--cws-on-dark-2); }
.cws-sec--dark .cws-manifesto__list svg { color: var(--cws-brand-hi); }
.cws-sec--dark .cws-card {
  background: rgba(255, 255, 255, .04);
  border-color: var(--cws-dark-line);
}
.cws-sec--dark .cws-card:hover {
  border-color: rgba(255, 77, 79, .45);
  box-shadow: 0 24px 60px -30px rgba(0, 0, 0, .9);
}
.cws-sec--dark .cws-card__icon {
  background: rgba(255, 77, 79, .14);
  color: var(--cws-brand-hi);
}
.cws-sec--dark .cws-card__num { color: rgba(255, 255, 255, .38); }
.cws-sec--dark .cws-card__tags { border-top-color: var(--cws-dark-line); }
.cws-sec--dark .cws-card__tags span {
  background: rgba(255, 255, 255, .07);
  color: var(--cws-on-dark-2);
}
.cws-sec--dark .cws-link { color: #fff; }
.cws-sec--dark .cws-link:hover { color: var(--cws-brand-hi); }
.cws-sec--dark .cws-step { border-top-color: var(--cws-dark-line); }
.cws-sec--dark .cws-step__num { color: rgba(255, 255, 255, .38); }
.cws-sec--dark .cws-step__tag {
  background: rgba(255, 255, 255, .07);
  color: var(--cws-on-dark-2);
}
.cws-sec--dark .cws-faq details,
.cws-sec--dark .cws-faq details:first-of-type { border-color: var(--cws-dark-line); }
.cws-sec--dark .cws-faq summary { color: #fff; }
.cws-sec--dark .cws-faq details p { color: var(--cws-on-dark-2); }
.cws-sec--dark .cws-eyebrow { color: rgba(255, 255, 255, .5); }

/* platform logo strip (social page) */
.cws-logos {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.cws-logos figure {
  display: flex;
  align-items: center;
  gap: 11px;
  margin: 0;
  padding: 11px 20px 11px 12px;
  border: 1px solid var(--cws-line-2);
  border-radius: var(--cws-pill);
  background: var(--cws-bg);
  transition: border-color .3s var(--cws-ease), transform .3s var(--cws-ease);
}
.cws-logos figure:hover {
  border-color: var(--cws-line);
  transform: translateY(-2px);
}
.cws-logos img {
  width: 30px;
  height: 30px;
  object-fit: contain;
  border-radius: 8px;
  flex: none;
}
.cws-logos figcaption {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--cws-ink);
}
.cws-sec--dark .cws-logos figure {
  background: rgba(255, 255, 255, .05);
  border-color: var(--cws-dark-line);
}
.cws-sec--dark .cws-logos figcaption { color: #fff; }

/* small print / disclaimer under a CTA */
.cws-note {
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--cws-muted);
  margin-top: 14px;
}
.cws-sec--dark .cws-note,
.cws-endcap .cws-note { color: var(--cws-on-dark-3); }

/* framed media — keeps the WP-era screenshots in the new layout
   without breaking the flat, bordered language of the design */
.cws-figure {
  margin: 0;
  border: 1px solid var(--cws-line-2);
  border-radius: var(--cws-r-lg);
  overflow: hidden;
  background: var(--cws-dark);
}
.cws-figure img {
  width: 100%;
  height: auto;
  display: block;
}
.cws-figure figcaption {
  padding: 14px 20px;
  border-top: 1px solid var(--cws-line-2);
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cws-muted);
  background: var(--cws-bg);
}
.cws-sec--dark .cws-figure { border-color: var(--cws-dark-line); }
.cws-sec--dark .cws-figure figcaption {
  border-top-color: var(--cws-dark-line);
  background: rgba(255, 255, 255, .04);
  color: var(--cws-on-dark-3);
}

/* closing CTA band — dark, no form (the form lives on /contact/) */
.cws-endcap {
  background: var(--cws-dark);
  color: var(--cws-on-dark);
  position: relative;
  overflow: hidden;
  isolation: isolate;
  text-align: center;
}
.cws-endcap h2 {
  font-size: var(--cws-fs-h2);
  color: #fff;
  max-width: 22ch;
  margin-inline: auto;
}
.cws-endcap .cws-lead {
  margin-inline: auto;
  margin-top: 22px;
  color: var(--cws-on-dark-2);
}
.cws-endcap .cws-cta-row {
  justify-content: center;
  margin-top: 34px;
}
.cws-endcap__note {
  margin-top: 28px;
  font-family: var(--cws-font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cws-on-dark-3);
}

/* ============================================================
   18. RESPONSIVE — 6 breakpoints
   ============================================================ */

/* --- 1. extra wide ------------------------------------------------ */
@media (min-width: 1440px) {
  .cws-landing { --cws-fs-display: 5.25rem; --cws-fs-h2: 3.6rem; }
  .cws-hero__grid { gap: 100px; }
}

/* --- 2. small desktop / large laptop ------------------------------ */
@media (max-width: 1200px) {
  .cws-landing { --cws-maxw: 100%; }
  .cws-hero__grid { gap: 48px; }
  .cws-head { gap: 40px; }
  .cws-proc { gap: 56px; }
}

/* --- 3. laptop / landscape tablet --------------------------------- */
@media (max-width: 1024px) {
  .cws-hero__grid { grid-template-columns: 1fr; gap: 44px; }
  .cws-hero__panel { max-width: 520px; }
  .cws-manifesto__grid { grid-template-columns: 1fr; gap: 34px; }
  .cws-proc { grid-template-columns: 1fr; gap: 40px; }
  .cws-proc__aside { position: static; }
  .cws-contact__grid { grid-template-columns: 1fr; gap: 44px; }
  .cws-stats__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cws-svc { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cws-cases { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cws-fx { opacity: .6; }
}

/* --- 4. tablet portrait ------------------------------------------- */
@media (max-width: 860px) {
  .cws-head { grid-template-columns: 1fr; align-items: start; gap: 20px; }
  .cws-head__aside { padding-bottom: 0; }
  .cws-fit { grid-template-columns: 1fr; }
  .cws-step { grid-template-columns: 1fr; gap: 10px; }
  .cws-step__num { padding-top: 0; }
  .cws-final h2 { font-size: clamp(1.75rem, 6vw, 2.5rem); }
  .cws-endcap h2 { font-size: clamp(1.75rem, 6vw, 2.5rem); }
  .cws-logos figure { padding: 9px 16px 9px 10px; gap: 9px; }
  .cws-logos img { width: 26px; height: 26px; }
  .cws-logos figcaption { font-size: 0.8125rem; }
}

/* --- 5. mobile ----------------------------------------------------- */
@media (max-width: 640px) {
  .cws-landing { --cws-fs-body: 1rem; }
  .cws-hero { padding-top: 96px; padding-bottom: 56px; }
  .cws-hero h1 { letter-spacing: -0.034em; }
  .cws-pagehead { padding-top: 92px; padding-bottom: 40px; }
  .cws-pagehead h1 { max-width: none; letter-spacing: -0.026em; }
  .cws-hero__cta { margin-top: 30px; }
  .cws-btn { width: 100%; }
  .cws-hero__cta .cws-btn,
  .cws-final .cws-btn { width: auto; }
  .cws-cta-row { gap: 10px; }
  .cws-svc { grid-template-columns: 1fr; }
  .cws-cases { grid-template-columns: 1fr; }
  .cws-stats__grid { grid-template-columns: 1fr; }
  .cws-form__row { grid-template-columns: 1fr; gap: 0; }
  .cws-form { padding: 22px 18px; }
  .cws-panel__v { font-size: 1.125rem; }
  .cws-marquee__track { animation-duration: 24s; }
  .cws-fx { opacity: .38; width: min(560px, 96vw); }
  .cws-fx:not(.cws-fx--mirror):not(.cws-fx--mesh) { top: -6%; right: -42%; }
  .cws-fx--mirror { top: auto; right: auto; bottom: -18%; left: -38%; }
  .cws-pagehead .cws-fx { top: 14%; right: -34%; width: min(420px, 80vw); opacity: .34; }
  .cws-pagehead__meta { gap: 6px; margin-top: 22px; }
  .cws-pagehead__meta span { font-size: 0.5625rem; padding: 5px 10px; }
  .cws-logos { gap: 8px; }
  .cws-endcap .cws-cta-row .cws-btn { width: 100%; }
}

/* --- 6. small phone ------------------------------------------------ */
@media (max-width: 420px) {
  .cws-landing { --cws-gutter: 16px; --cws-fs-display: 2.35rem; }
  .cws-hero__badge { font-size: 0.5625rem; letter-spacing: .12em; }
  .cws-badge { font-size: 0.75rem; padding: 7px 12px; }
  .cws-card { padding: 22px; }
  .cws-case__kpis { gap: 16px; }
  .cws-case__kpi b { font-size: 1.375rem; }
  .cws-faq summary { padding-right: 34px; }
  .cws-faq details p { padding-right: 20px; }
}

/* ============================================================
   19. ACCESSIBILITY / FALLBACKS
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .cws-landing *,
  .cws-landing *::before,
  .cws-landing *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .cws-reveal, .cws-word { opacity: 1 !important; transform: none !important; filter: none !important; }
  .cws-marquee__track { animation: none; }
}

/* No-JS fallback is structural, not selector-based: the hidden
   state is scoped to html.cws-js (see section 15), so if the
   class is absent nothing is ever hidden.
   scripts/home-body-class.js additionally fires a watchdog that
   force-reveals everything if reveal.js itself fails to load. */

/* guard against Fluid's dark-mode toggle bleeding into the landing page */
.cws-landing { color-scheme: light; }

/* ============================================================
   20. BLOG LIST + ARTICLE PAGES
   ------------------------------------------------------------
   /blog/ (Fluid `index` layout) and the post routes (Fluid `post`
   layout) are real theme routes, so their chrome is neutralised by
   BODY CLASS rather than by markup wrappers:

     body.cws-blog      the paginated post list
     body.cws-article   a single post

   scripts/blog-design.js adds those classes and injects the
   .cws-pagehead / .cws-related / .cws-endcap shells, because
   neither theme layout can render them on its own.

   NOTE the token block in section 1 is shared with these body
   classes. The RESETS in section 2 are not — which is why the
   article prose has to re-declare its own link and list styling
   further down (the injected .cws-landing wrapper would otherwise
   flatten every link and bullet inside the article).
   ============================================================ */

/* ---- 20.1 neutralise Fluid's blog chrome ---- */

/* the 50-70vh default banner, and the shell that wraps navbar+banner.
   The shell's height is an INLINE style (70vh), so it needs !important.
   Collapsing is safe: the navbar is position:fixed and .cws-pagehead
   clears it with its own padding-top. */
body.cws-blog #banner,
body.cws-article #banner { display: none !important; }
body.cws-blog header .header-inner,
body.cws-article header .header-inner { height: auto !important; }

/* the list page is full-bleed, exactly like the landing page */
body.cws-blog main > .container,
body.cws-blog main > .container > #board,
body.cws-blog #board > .container,
body.cws-blog #board .row {
  max-width: none !important;
  width: 100% !important;
  margin: 0 !important;
  padding: 0 !important;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
}
body.cws-blog #board .row > [class*="col-"] {
  flex: 0 0 100% !important;
  max-width: 100% !important;
  width: 100% !important;
  padding: 0 !important;
  margin: 0 !important;
}

/* the article keeps Fluid's 3-column reading grid but loses the card */
body.cws-article #board,
body.cws-article #board-ctn {
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  background: transparent !important;
  padding: 0 !important;
}
body.cws-article .post-content { padding: 0; }
/* mtime-driven "updated" note: restyling a file is not a content update */
body.cws-article #updated-time { display: none !important; }
body.cws-article .post-content > hr { display: none; }

/* THE overlap bug, part 1 of 3. The theme gives #board `margin-top: -2rem`
   so the board slides up and sits *over* the hero banner. We delete the
   banner, so that -2rem had nothing to overlap and instead pulled the first
   block 32px up INSIDE the dark pagehead — the opening line was painted on
   the dark surface and the second line on white, which is what "text
   bleeding into the banner" looked like. Reset it.
   (the theme swaps -2rem for -1rem in a media query; the id selector
   plus !important outranks both.) */
body.cws-article #board { margin-top: 0 !important; }

/* THE overlap bug, part 2 of 3 — the real culprit for headlines.
   Fluid offsets in-page anchors with an invisible spacer pseudo-element on
   every heading:
     .markdown-body h2::before { content:""; display:block;
                                 height:5rem; margin-top:-5rem; visibility:hidden }
   The -5rem is *supposed* to live inside the heading, cancelled by the
   heading's own padding-top + border-top. But our 20.3 rule for the first
   heading (h2:first-child { padding-top:0; border-top:0 }) deletes exactly
   those two properties, so the negative margin COLLAPSES OUT of the <h2>:
   the heading's border box is dragged 80px up (offsetTop = -80, measured)
   while the spacer pushes the text back down. Net result at 1600px: the
   first line's ink starts at y=473, i.e. exactly on the pagehead's bottom
   edge — flush against the black band, and overlapping it the moment the
   viewport shifts the two boxes.
   We already offset anchors the modern way (scroll-margin-top, 20.3), so
   the spacer is redundant. Delete it outright — for headings that DO keep
   their padding-top it was a layout no-op anyway, so this changes nothing
   else. */
body.cws-article .markdown-body h1::before,
body.cws-article .markdown-body h2::before,
body.cws-article .markdown-body h3::before,
body.cws-article .markdown-body h4::before,
body.cws-article .markdown-body h5::before,
body.cws-article .markdown-body h6::before {
  content: none !important;
  display: none !important;
  height: 0 !important;
  margin: 0 !important;
}

/* part 3 of 3 — structural guarantee.
   The pagehead's own padding-bottom is the last thing the eye sees before
   the prose, so with no gap a 31px display heading reads as if it were
   inside the dark band. Reserve real air on the article container itself:
   padding cannot collapse, so no theme negative margin can eat it again.
   (!important because 20.1 sets `padding: 0 !important` on #board to break
   out of Fluid's card — an equal-specificity declaration after it wins.) */
body.cws-article #board { padding-top: clamp(32px, 3.4vw, 52px) !important; }

/* the theme's page shell is #eee — a grey that fights the white landing
   system and makes the framed screenshots look dingy */
body.cws-article { background: var(--cws-bg); }

/* a post whose body has no h2/h3 leaves the TOC rail empty (just the
   "Table of contents" header in a white box, plus a dead column of gutter
   beside the text). blog-design.js flags those posts at build time.
   NOTE the row also carries a *left* spacer with the same .side-col class,
   so match the rail by its contents — hiding .side-col outright would
   shift the whole reading column 230px left. */
body.cws-article--flat .side-col:has(#toc) { display: none !important; }

/* ---- 20.1b the reading column and the pagehead share one grid ----
   Zeroing #board-ctn's padding (needed to break out of Fluid's card) also
   threw away the side gutter, so below the lg breakpoint the prose sat
   flush against the viewport edge. Give the column back the design-system
   gutter, and above lg line the dark pagehead's h1 up with it: the
   pagehead sits on the 1200px design container while the prose sits on
   Fluid's 8/12 grid, which left the two left edges 116px apart. */
body.cws-article .col-lg-8 { padding-inline: 0 !important; }
body.cws-article #board-ctn {
  /* Fluid's #board-ctn is a bootstrap .container: it clamps to 720px at the
     md breakpoint and to 1140px above 1200px, so the column stopped filling
     its 8/12 grid cell and the left edge drifted away from the pagehead
     again (90px at 900px wide, 96px at 2000px). Drop the clamp. */
  max-width: none !important;
  padding-inline: var(--cws-gutter) !important;
}
/* the column grows with the viewport (8/12 of it); the prose should not,
   or a 1920px screen gives ~90-character lines. .post-content ships with
   bootstrap's mx-auto (margin-inline: auto !important), so once the cap
   bites the column drifts right of the pagehead's h1 — override the
   !important to pin it to the left edge instead. */
body.cws-article #board > .post-content { max-width: 60rem; margin-inline: 0 !important; }
@media (min-width: 992px) {
  body.cws-article .cws-pagehead--article .cws-wrap {
    max-width: 66.6667%;
    padding-inline: var(--cws-gutter);
  }
}

/* ---- 20.2 article page head ---- */
.cws-pagehead--article { padding-bottom: clamp(44px, 5vw, 68px); }
.cws-pagehead--article h1 { max-width: 30ch; }
.cws-pagehead__meta--article { gap: 10px; }
.cws-pagehead__meta--article span {
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .74);
  padding: 6px 12px;
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: var(--cws-pill);
  background: rgba(255, 255, 255, .045);
}

/* ---- 20.3 article prose ----
   Everything here is re-declared on purpose: the injected
   .cws-landing wrapper applies the section-2 resets to the article,
   so margins, bullets and link colours must be restored explicitly. */
body.cws-article .markdown-body {
  font-family: var(--cws-font-body);
  font-size: clamp(1.0625rem, 0.4vw + 0.98rem, 1.1875rem);
  line-height: 1.8;
  color: var(--cws-body);
  counter-reset: none;
  text-wrap: pretty;
}

/* The opening paragraph doubles as the standfirst — but only when it really
   IS the opening block. `:first-of-type` also promoted the `*Source data: …*`
   credit line these migrated posts open with, so a 21px "lede" was being set
   between two hairlines ahead of the first real section. Scope it to
   :first-child, and treat a leading italic-only paragraph as what it is:
   a compact, muted credit note. */
body.cws-article .markdown-body > p:first-child {
  font-size: 1.3125rem;
  line-height: 1.58;
  letter-spacing: -0.011em;
  color: var(--cws-ink-3);
  max-width: 60ch;
  margin-bottom: 1.7em;
}
body.cws-article .markdown-body > p:first-of-type:has(> em:only-child) {
  font-size: 0.9375rem;
  line-height: 1.62;
  letter-spacing: 0.004em;
  color: var(--cws-muted);
  max-width: 74ch;
  margin-bottom: 1.4rem;
}
body.cws-article .markdown-body h2,
body.cws-article .markdown-body h3,
body.cws-article .markdown-body h4 {
  font-family: var(--cws-font-display);
  color: var(--cws-ink);
  letter-spacing: -0.028em;
  line-height: 1.18;
  scroll-margin-top: 104px;
}
/* The section rule. margin/padding are in rem, not em, on purpose: em here
   resolves against the heading's own 31px, so `2.3em 0 0.7em` silently became
   71/22px and `padding-top:1.35em` another 42px — 113px of white before every
   heading text, which is what "unnecessary space between paragraphs" was.
   54 + 26 = 80px now, with the hairline floating in the middle of it. */
body.cws-article .markdown-body h2 {
  font-size: clamp(1.5rem, 1.5vw + 1.05rem, 1.9375rem);
  margin: 3.4rem 0 1.15rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--cws-line-2);
  /* github-markdown-css (CDN) paints a hairline *under* every h2 and adds
     .3em of padding-bottom. Combined with our border-top that gave each
     section TWO rules 10px apart, one of them stranded under the article's
     opening headline. Keep the one that carries meaning: the top rule. */
  border-bottom: 0 !important;
  padding-bottom: 0 !important;
}
body.cws-article .markdown-body h2:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
body.cws-article .markdown-body h3 {
  font-size: clamp(1.125rem, 0.7vw + 0.98rem, 1.3125rem);
  margin: 2.6rem 0 0.85rem;
  border-bottom: 0 !important;
  padding-bottom: 0 !important;
}
body.cws-article .markdown-body h4 {
  margin: 2.2rem 0 0.75rem;
  border-bottom: 0 !important;
  padding-bottom: 0 !important;
}
body.cws-article .markdown-body p { margin: 0 0 1.5em; }
body.cws-article .markdown-body > *:first-child { margin-top: 0 !important; }

body.cws-article .markdown-body ul,
body.cws-article .markdown-body ol {
  margin: 0 0 1.5em !important;
  padding-left: 1.4em !important;
}
body.cws-article .markdown-body ul { list-style: disc outside !important; }
body.cws-article .markdown-body ol { list-style: decimal outside !important; }
body.cws-article .markdown-body ul ul { list-style: circle outside !important; }
body.cws-article .markdown-body li { margin-bottom: 0.5em; }
body.cws-article .markdown-body li::marker { color: var(--cws-brand); }

body.cws-article .markdown-body a {
  color: var(--cws-brand);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: rgba(211, 47, 47, .35);
  transition: text-decoration-color .2s var(--cws-ease), color .2s var(--cws-ease);
}
body.cws-article .markdown-body a:hover {
  color: var(--cws-brand-600);
  text-decoration-color: currentColor;
}
body.cws-article .markdown-body strong { color: var(--cws-ink); font-weight: 600; }
body.cws-article .markdown-body em { font-style: italic; }

body.cws-article .markdown-body blockquote {
  margin: 1.9em 0;
  padding: 2px 0 2px 22px;
  border-left: 2px solid var(--cws-brand);
  background: none;
  color: var(--cws-ink-3);
  font-size: 1.0625rem;
}
body.cws-article .markdown-body blockquote p:last-child { margin-bottom: 0; }

/* WP-era screenshots: same frame language as .cws-figure. These posts are
   mostly screenshots of Baidu's UI, so without a real frame a white
   screenshot dissolves into the white page and the article loses all
   structure. Mount them instead: hairline border, rounded corners, a
   long soft shadow, on the white surface. */
body.cws-article .markdown-body img {
  width: auto;
  max-width: 100%;
  height: auto;
  display: block;
  margin: 0 auto;
  border: 1px solid var(--cws-line);
  border-radius: var(--cws-r);
  background: var(--cws-bg);
  box-shadow: 0 28px 56px -36px rgba(5, 7, 13, .34),
              0 2px 6px -2px rgba(5, 7, 13, .05);
}
/* an image that sits alone in its paragraph is a figure, not a sentence:
   move the vertical rhythm onto the <p> so the frame gets real air and
   the text around it breathes.

   ⚠️ Fluid's photo_swipe (`photo_swipe: true` in _config.fluid.yml) rewrites
   every article image at runtime into

       <p><a class="fancybox fancybox.image"><img></a> <em>caption</em></p>

   so the <img> ends up a GRANDCHILD of the <p>. The selector that used to be
   here — `p:has(> img:only-child)` — therefore matched NOTHING on this site:
   the figure air was silently dead on every post, and any caption rule keyed
   on it never fired either. Match the real (wrapped) shape, and keep the bare
   form so the rule still holds if photo_swipe is ever switched off. */
body.cws-article .markdown-body p:has(> a > img),
body.cws-article .markdown-body p:has(> img:only-child) {
  margin: 2.4em 0 2.6em;
}
/* the wrapper is an inline <a>; make it a block so the centred image inside
   it is centred by the paragraph, not by an anonymous inline box */
body.cws-article .markdown-body p:has(> a > img) > a { display: block; }
body.cws-article .markdown-body p:has(> a > img) img,
body.cws-article .markdown-body p:has(> img:only-child) img { margin: 0 auto; }

/* The WP-era posts caption their screenshots from the *same* paragraph as
   the image (the source puts the image and its `*caption*` on consecutive
   lines, so markdown-it keeps both inside one <p>). Left alone that renders
   the caption as full-size body italic glued to the bottom of the frame —
   the single most common "this page still looks like the old site" tell.
   Treat the shape as a figure plate: air around the pair, and the caption
   demoted to the same quiet mono label the .cws-figure component uses. */
body.cws-article .markdown-body p:has(> a > img),
body.cws-article .markdown-body p:has(> img) { margin: 2.4em 0 2.6em; }
body.cws-article .markdown-body p:has(> a > img) > em:last-child,
body.cws-article .markdown-body p:has(> img) > em:last-child {
  display: block;
  margin-top: 0.9rem;
  font-family: var(--cws-font-mono);
  font-size: 0.6875rem;
  font-style: normal;
  line-height: 1.5;
  letter-spacing: 0.08em;
  text-align: center;
  text-transform: uppercase;
  color: var(--cws-muted);
}
/* Data tables. The default (a full 1px grid, left-aligned everywhere, no
   framework) reads as a spreadsheet pasted into prose: borders crossing at
   every corner, numbers ragged-left, header indistinguishable from body.
   Mount it like everything else in the system — one hairline frame, a quiet
   label row, rules only between rows, and the numbers in tabular figures so
   the decimal points line up down the column. */
body.cws-article .markdown-body table {
  width: 100%;
  margin: 2rem 0 2.4rem;
  border: 1px solid var(--cws-line);
  border-radius: var(--cws-r);
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
body.cws-article .markdown-body th,
body.cws-article .markdown-body td {
  padding: 13px 16px;
  border: 0;
  border-bottom: 1px solid var(--cws-line-2);
  text-align: left;
  vertical-align: middle;
}
/* scope to tbody: without it `tr:last-child` also matches the single <tr>
   inside <thead> and snuffs out the label row's divider */
body.cws-article .markdown-body tbody tr:last-child td { border-bottom: 0; }
body.cws-article .markdown-body thead th {
  background: var(--cws-bg-2);
  border-bottom: 1px solid var(--cws-line);
  color: var(--cws-muted);
  font-family: var(--cws-font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  white-space: nowrap;
}
/* an empty <thead> (markdown tables imported from WP often carry one) would
   otherwise render as a 46px band of tinted emptiness above the real header
   row. Hide the row, keep the structure. */
body.cws-article .markdown-body thead tr:not(:has(th:not(:empty))) { display: none; }

/* the first cell is the row key (an engine, a region, a plan) — the rest are
   figures, so they line up on the right edge.
   Scoped to tbody on purpose: `th:first-child` (0,3,2) outranks `thead th`
   (0,2,3), so an unscoped rule repainted the header's own first cell in dark
   ink at 600 — the label row stopped looking like a label row. */
body.cws-article .markdown-body tbody td:first-child {
  color: var(--cws-ink);
  font-weight: 600;
}
body.cws-article .markdown-body tbody td:not(:first-child) { text-align: right; }
body.cws-article .markdown-body tbody tr:nth-child(even) { background: rgba(5, 7, 13, .017); }
body.cws-article .markdown-body tbody tr:hover { background: var(--cws-bg-2); }

/* ---- 20.4 TOC (tocbot) ----
   An index card in the same language as .cws-postcard / .cws-figure: hairline
   frame, a mono label row, one quiet rail down the left that turns brand-red
   for the section you are reading. Three theme behaviours had to go:

   1. LINE CLAMP. The theme clamps the row to two lines with -webkit-box, but
      the box was laid out one line tall while its text overflowed, so every
      long heading left a half-cut third line bleeding into the next row —
      the "ghost fragment" look. Measured: link box 48px vs content 67px. The
      panel already scrolls, so let headings wrap and be done with it.
      (display/overflow/clamp are forced because the clamp's origin could not
      be found in any readable stylesheet — measured display was `flow-root`
      even though every local rule says otherwise.)
   2. TWO ACTIVE INDICATORS. The theme draws a dash with
      `.toc-list-item::before` AND ships a `.toc-toggle` chevron span inside
      every row. Both are hidden: the rail on the anchor is the indicator.
   3. The row rhythm. Each row is a 7px-padded block so the hit area is the
      whole line, not just the glyphs. */
body.cws-article .sidebar { align-self: flex-start; }
body.cws-article #toc {
  position: sticky;
  top: 104px;
  padding: 20px 18px 22px;
  border: 1px solid var(--cws-line);
  border-radius: var(--cws-r-lg);
  background: var(--cws-bg);
  box-shadow: var(--cws-sh-2);
  max-height: calc(100vh - 150px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
body.cws-article #toc .toc-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 14px;
  padding-bottom: 13px;
  border-bottom: 1px solid var(--cws-line-2);
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cws-muted);
}
body.cws-article #toc .toc-header i { font-size: 0.75rem; color: var(--cws-brand); }

body.cws-article #toc .tocbot-list,
body.cws-article #toc .tocbot-list ol {
  list-style: none !important;
  margin: 0 !important;
  padding: 0 !important;
}
/* h3 rows sit one tier in — indentation alone reads as a tree here, so no
   second rail is drawn */
body.cws-article #toc .tocbot-list ol { padding-left: 13px !important; }
body.cws-article #toc .toc-toggle { display: none !important; }

body.cws-article #toc .toc-list-item {
  display: block !important;
  position: relative;
  margin: 0 !important;
  overflow: visible !important;
  -webkit-box-orient: initial !important;
  -webkit-line-clamp: none !important;
}
body.cws-article #toc .toc-list-item::before { display: none !important; }

body.cws-article #toc .tocbot-link {
  display: block !important;
  -webkit-box-orient: initial !important;
  -webkit-line-clamp: none !important;
  overflow: visible !important;
  margin: 0 !important;
  padding: 7px 8px 7px 11px;
  border-left: 2px solid transparent;
  border-radius: 0 var(--cws-r-sm) var(--cws-r-sm) 0;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--cws-muted);
  text-decoration: none;
  text-wrap: pretty;
  transition: color .2s var(--cws-ease), border-color .2s var(--cws-ease),
              background-color .2s var(--cws-ease);
}
body.cws-article #toc .tocbot-list ol .tocbot-link { font-size: 0.78125rem; }
body.cws-article #toc .tocbot-link:hover {
  color: var(--cws-ink);
  border-left-color: var(--cws-line);
  background: var(--cws-bg-2);
}
body.cws-article #toc .tocbot-active-link {
  color: var(--cws-brand) !important;
  border-left-color: var(--cws-brand);
  background: var(--cws-brand-wash);
  font-weight: 600;
}

/* ---- 20.5 post meta / prev-next ---- */
body.cws-article .post-metas {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  margin: 26px 0 0 !important;
  padding-top: 22px;
  border-top: 1px solid var(--cws-line-2);
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cws-muted);
}
body.cws-article .post-metas .iconfont { display: none; }
body.cws-article .post-metas a { color: var(--cws-muted); text-decoration: none; }
body.cws-article .post-metas a:hover { color: var(--cws-brand); }

body.cws-article .post-prevnext {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 30px;
}
body.cws-article .post-prevnext article { max-width: none; flex: none; }
body.cws-article .post-prevnext a {
  display: block;
  height: 100%;
  padding: 16px 18px;
  border: 1px solid var(--cws-line);
  border-radius: var(--cws-r-lg);
  background: var(--cws-bg);
  font-size: 0.875rem;
  line-height: 1.45;
  font-weight: 500;
  color: var(--cws-ink);
  text-decoration: none;
  transition: border-color .25s var(--cws-ease), transform .25s var(--cws-ease);
}
body.cws-article .post-prevnext a:hover {
  border-color: rgba(211, 47, 47, .4);
  transform: translateY(-2px);
}
body.cws-article .post-prevnext .iconfont { display: none; }
body.cws-article .post-next { text-align: right; }

/* ---- 20.6 blog list: cards ---- */
.cws-posts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 328px), 1fr));
  gap: clamp(20px, 2.2vw, 30px);
}
.cws-postcard {
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--cws-line);
  border-radius: var(--cws-r-lg);
  background: var(--cws-bg);
  overflow: hidden;
  transition: transform .3s var(--cws-ease),
              border-color .3s var(--cws-ease),
              box-shadow .3s var(--cws-ease);
}
.cws-postcard:hover {
  transform: translateY(-4px);
  border-color: rgba(211, 47, 47, .34);
  box-shadow: 0 24px 50px -28px rgba(5, 7, 13, .38);
}
.cws-postcard__media {
  position: relative;
  aspect-ratio: 16 / 10;
  background: var(--cws-bg-3);
  overflow: hidden;
}
.cws-postcard__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .55s var(--cws-ease);
}
.cws-postcard:hover .cws-postcard__media img { transform: scale(1.045); }
.cws-postcard__cat {
  position: absolute;
  left: 13px;
  bottom: 13px;
  padding: 6px 11px;
  border-radius: var(--cws-pill);
  background: rgba(5, 7, 13, .6);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  font-family: var(--cws-font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
}
.cws-postcard__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 22px 22px 20px;
}
.cws-postcard__title {
  font-size: 1.1875rem;
  line-height: 1.32;
  letter-spacing: -0.022em;
}
.cws-postcard__title a { color: inherit; transition: color .2s var(--cws-ease); }
.cws-postcard__title a:hover { color: var(--cws-brand); }
/* one link per card: the title carries a full-bleed hit area */
.cws-postcard__title a::after { content: ""; position: absolute; inset: 0; }
.cws-postcard__title a:focus-visible { outline: 2px solid var(--cws-brand); outline-offset: 4px; }
.cws-postcard__excerpt {
  margin-top: 12px;
  font-size: 0.9375rem;
  line-height: 1.62;
  color: var(--cws-body);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.cws-postcard__foot {
  margin-top: auto;
  padding-top: 18px;
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--cws-font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cws-faint);
}
.cws-postcard__foot i {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* ---- 20.7 pager ---- */
.cws-pager {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-top: clamp(38px, 4vw, 56px);
}
.cws-pager a,
.cws-pager span {
  min-width: 42px;
  padding: 10px 15px;
  border: 1px solid var(--cws-line);
  border-radius: var(--cws-pill);
  font-family: var(--cws-font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  color: var(--cws-body);
  text-align: center;
}
.cws-pager a:hover { border-color: rgba(211, 47, 47, .4); color: var(--cws-brand); }
.cws-pager .is-current {
  background: var(--cws-ink);
  border-color: var(--cws-ink);
  color: #fff;
}

/* ---- 20.8 two-up copy block on the list page ---- */
.cws-duo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(28px, 4vw, 64px);
}
.cws-duo__col .cws-h2 { max-width: 18ch; }
.cws-duo__col .cws-lead { margin-top: 18px; max-width: 52ch; }

/* ---- 20.9 responsive ---- */
/* (there used to be a `#toc { position: static }` rule at <=1080px. It was
   self-defeating: the rail lives in `.side-col.d-none.d-lg-block`, so it is
   already gone below 992px — and between 992px and 1080px it silently turned
   the index card into a 800px-tall box that scrolled away with the page.) */
/* the rail is Fluid's col-lg-2, so between 992px and ~1280px it is only
   ~160px wide — tighten the card so headings wrap less */
@media (min-width: 992px) and (max-width: 1279px) {
  body.cws-article #toc { padding: 16px 14px 18px; }
  body.cws-article #toc .tocbot-link { font-size: 0.75rem; padding: 6px 6px 6px 9px; }
}
@media (max-width: 820px) {
  body.cws-article .post-prevnext { grid-template-columns: 1fr; }
  body.cws-article .post-next { text-align: left; }
}
@media (max-width: 640px) {
  .cws-posts { grid-template-columns: 1fr; }
  .cws-postcard__body { padding: 18px 18px 16px; }
  .cws-postcard__title { font-size: 1.0625rem; }
  body.cws-article .markdown-body h2 { margin-top: 2.6rem; padding-top: 1.2rem; }
  /* a 5-column data table cannot hold 16px of side padding on a phone.
     The header nowrap has to be cancelled on the SAME selector as the rule
     that sets it (thead th, 0,2,3) — a bare `th` override loses the
     specificity fight and the last column gets clipped away silently by the
     frame's overflow:hidden. overflow-x stays as a last-resort escape hatch
     so a wider table scrolls instead of vanishing. */
  body.cws-article .markdown-body table { font-size: 0.8125rem; overflow-x: auto; }
  body.cws-article .markdown-body thead th { white-space: normal; font-size: 0.625rem; letter-spacing: 0.06em; }
  body.cws-article .markdown-body th,
  body.cws-article .markdown-body td { padding: 10px 9px; }
  /* the figure rhythm lives on the <p> now (20.3) — shrink that, not the img */
  body.cws-article .markdown-body p:has(> img:only-child) { margin: 1.8em 0 2em; }
  body.cws-article .markdown-body > p:first-child { font-size: 1.1875rem; }
}

/* ============================================================
   21. ABOUT — photo milestone cards
   Two additions only, both opt-in via a modifier class so no
   existing .cws-case (homepage) is touched:
     .cws-cases--2        two-up grid for the 4 milestones
     .cws-case__media--photo  real photograph instead of the
                          synthetic gradient chip, with a
                          legibility gradient for the year pill
   ============================================================ */
.cws-cases--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.cws-case__media--photo { aspect-ratio: 3 / 2; }
.cws-case__media--photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* the base rule paints a red radial wash for the synthetic chip;
   on a real photo that mutes the image, so swap it for a
   bottom-weighted gradient that keeps the year pill readable */
.cws-case__media--photo::after {
  background: linear-gradient(180deg,
    rgba(5, 7, 13, .06) 0%,
    rgba(5, 7, 13, .28) 55%,
    rgba(5, 7, 13, .78) 100%);
}
.cws-case__media--photo .cws-case__ind {
  position: absolute;
  left: 16px;
  bottom: 14px;
  z-index: 2;
  background: rgba(5, 7, 13, .74);
  border-color: rgba(255, 255, 255, .26);
  color: #fff;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

/* !important-free override, but specificity (0,2,0) beats the
   section-18 media queries on .cws-cases (0,1,0), so the
   two-up grid must be told to collapse here or it would stay
   two-column on phones. */
@media (max-width: 860px) {
  .cws-cases--2 { grid-template-columns: 1fr; }
}

