/*==============================================================================
  CSIGNAL SKIN
  ----------------------------------------------------------------------------
  A pure visual override for the Charle homepage. Loaded AFTER style.css,
  new-home.css and service.css, and scoped entirely to body.cs-skin, so it
  cannot leak onto any other page and removing the one <link> reverts the
  page completely.

  RULE FOR THIS FILE: colours, type, borders and decoration only.
  Do not change layout, spacing, DOM order, copy or links here. Those are the
  things Google reads, and the whole point of the skin is that they stay
  byte-identical to index.php so the reskin is invisible to search.

  Palette is taken from /csignal/assets/page.css so the homepage and the
  CSignal page agree:
    ink        #0E1C16   the ground
    ink-2      #122419   raised surfaces on ink
    lime       #D3F502   accent, CTAs
    paper      #F3F5EE   light sections and text on ink
    blue       #2F6BFF   rare secondary
    coral      #FF5A2C   rare secondary
==============================================================================*/

body.cs-skin {
  /* One step below ink. For panels that sit ON ink and need to be read as a
     separate surface, the nav dropdown above all. */
  --ink-0: #0A140F;
  --ink: #0E1C16;
  --ink-2: #122419;
  --ink-3: #1B3226;
  --lime: #D3F502;
  --lime-dim: #B8D802;
  --paper: #F3F5EE;
  --paper-2: #E8ECE1;
  --blue: #2F6BFF;
  --coral: #FF5A2C;

  --cs-display: "Bricolage Grotesque", "Season Serif", Georgia, serif;
  --cs-body: "Hanken Grotesk", "Season Sans", -apple-system, BlinkMacSystemFont, sans-serif;
  /* The Metric role from the guidelines: counters, stat chips, filter labels. */
  --cs-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Text roles */
  --on-ink: var(--paper);
  --on-ink-muted: rgba(243, 245, 238, 0.62);
  --on-paper: var(--ink);
  --on-paper-muted: rgba(14, 28, 22, 0.62);

  --line-on-ink: rgba(243, 245, 238, 0.12);
  --line-on-paper: rgba(14, 28, 22, 0.12);
}

/*------------------------------------------------------------------------------
  1. Global ground and type
------------------------------------------------------------------------------*/

body.cs-skin {
  background-color: var(--ink);
  color: var(--on-ink);
  font-family: var(--cs-body);
}

body.cs-skin h1,
body.cs-skin h2,
body.cs-skin h3,
body.cs-skin h4 {
  font-family: var(--cs-display);
  font-weight: 600;
  letter-spacing: -0.015em;
}

/* --- Font sweep -------------------------------------------------------------
   Season is named in three places at once: 49 selectors across style.css,
   new-home.css and service.css, eight inline style blocks inside the page
   itself, and around thirty more inside includes/footer.php, which is a shared
   include we cannot edit without changing every page on the site.

   Listing selectors could never catch all of that, and one of them is an ID
   rule that would outrank anything single-class anyway. So the sweep is a
   scoped universal: no Season anywhere under .cs-skin, whatever declared it.

   There are no icon or mono webfaces on this page, every icon is inline SVG,
   so nothing is caught in the blast. The display face is reasserted directly
   below at higher specificity. */

body.cs-skin,
body.cs-skin * { font-family: var(--cs-body) !important; }

/* Descendants matter as much as the headings themselves: a <span> or <em>
   inside an h2 matches the universal above and would drop back to the body
   face, which is what happened to the highlighted phrase in the About heading. */
body.cs-skin h1, body.cs-skin h1 *,
body.cs-skin h2, body.cs-skin h2 *,
body.cs-skin h3, body.cs-skin h3 *,
body.cs-skin h4, body.cs-skin h4 *,
body.cs-skin .cs-h1,
body.cs-skin .cs-h1 *,
body.cs-skin .cs-kicker,
body.cs-skin .cs-kicker *,
body.cs-skin .cs-reco__h,
body.cs-skin .cs-geo__h,
body.cs-skin .cs-reco__big,
body.cs-skin .about-charle__stat-number,
body.cs-skin .accordion__title { font-family: var(--cs-display) !important; }

body.cs-skin .mobile-navigation__link,
body.cs-skin .new-mobile-navigation__link,
body.cs-skin .services__navigation__link,
body.cs-skin .faqs__left__heading,
body.cs-skin .service-faqs__left__heading,
body.cs-skin .search-first__see-work,
body.cs-skin .about-charle__stat-label,
body.cs-skin .floating-cta__text svg text { font-family: var(--cs-body); }

body.cs-skin .btn,
body.cs-skin .mobile-navigation__badge,
body.cs-skin .mobile-submenu__title-badge,
body.cs-skin .new-mobile-navigation__badge,
body.cs-skin .new-mobile-submenu__title-badge,
body.cs-skin .navigation__badge,
body.cs-skin .experts__subtitle,
body.cs-skin .services__heading,
body.cs-skin .link-badges a,
body.cs-skin .service-faqs__heading,
body.cs-skin .about-charle__offer,
body.cs-skin .podcast__details,
body.cs-skin .intro__subheading,
body.cs-skin .intro__offer,
body.cs-skin .pricing__option_heading,
body.cs-skin .testimonial__author,
body.cs-skin .testimonial__play,
body.cs-skin .intro__serif { font-family: var(--cs-body); }

/* The display face is for headings and the big numbers, nothing else. */
body.cs-skin .partners__title,
body.cs-skin .faqs__heading,
body.cs-skin .about-charle__stat-number { font-family: var(--cs-display); }

/* Season Serif was used as a decorative label face in several places.
   A small uppercase mono-ish label carries that job now. */
/* .partners__subtitle is NOT a label. Everywhere else on the page __subtitle
   is the small kicker above a heading, but the partners block inverts it:
   partners__title is the 26px kicker and partners__subtitle is the 60px
   statement. Swept in with the labels it collapsed to 12px uppercase lime,
   which is why that section read as having lost its heading. */
body.cs-skin .feature__subheading,
body.cs-skin .people__subtitle,
body.cs-skin .partners__title,
body.cs-skin .about-charle__subheading,
body.cs-skin .search-first__subtitle {
  font-family: var(--cs-body);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 12px;
}

/*------------------------------------------------------------------------------
  2. Header
  style.css paints .header.filled #1a1b1e and rgba(26,26,26,0.8) at >=1024.
------------------------------------------------------------------------------*/

/* Solid CSignal green once scrolled, not frosted glass. style.css paints the
   scrolled bar translucent and .header carries backdrop-filter: blur(10px),
   which is the old brand's glassmorphism. CSignal is flat, so both go. */

body.cs-skin .header {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

body.cs-skin .header.filled { background: var(--ink-2); }

@media screen and (min-width: 1024px) {
  body.cs-skin .header.filled { background: var(--ink-2); }
}

/* Nav links. The families already matched once body switched to Hanken; what
   was off was weight and size. These are the /csignal/ .cs-nav__links values
   verbatim, including the clamp, so the two bars tighten identically between
   1080 and 1400. Charle's nav fades to 0.6 opacity on hover, CSignal goes to
   lime, so the opacity transition is cancelled. */
body.cs-skin .navigation__link {
  color: rgba(255, 255, 255, 0.72);
  font-size: clamp(13.5px, 1.1vw, 15px);
  font-weight: 600;
  white-space: nowrap;
}

body.cs-skin .navigation__link:hover,
body.cs-skin .navigation__item:hover > .navigation__link {
  color: var(--lime);
  opacity: 1;
}

/* "Work with Charle". The nav button on /csignal/ is plain .cs-btn.cs-btn--lime.
   Only the hero CTA carries .cs-btn--lg, so the clamped large values do not
   belong up here: 15px / 13px 24px is the bar. */
/* Below 1024 the original CTA is hidden and the burger menu takes over, so the
   actions pair must stay hidden too. Forcing it visible pushed it out of a pill
   that carries overflow:hidden at this width, which is why it was clipped. */
body.cs-skin .header__acts { display: none; }

@media screen and (min-width: 1024px) {
  body.cs-skin .header__acts {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    justify-self: end;
  }
}

body.cs-skin .header__get-in-touch {
  /* THE size difference: style.css .btn is display:block, so in the header grid
     the button stretched to fill its cell. /csignal/ .cs-btn is inline-block and
     hugs its text. Everything else here was already right. */
  display: inline-block;
  width: auto;

  background-color: var(--lime);
  color: var(--ink);
  font-family: var(--cs-body);
  font-weight: 700;
  font-size: 15px;
  /* /csignal/ .cs-btn declares no line-height, so it inherits the browser
     normal. style.css .btn pins 1.2, and my earlier 1 made the pill about 5px
     shorter than the landing page. Matching the landing page. */
  line-height: normal;
  padding: 13px 24px;
  border-radius: 999px;
  white-space: nowrap;
  transition: background 0.12s ease-out;
}

/* .btn:hover fades to 0.8 opacity. CSignal shifts the lime instead. */
body.cs-skin .header__get-in-touch:hover {
  background-color: #E2FF3A;
  opacity: 1;
}

/* Log in, sitting to the left of the button exactly as on /csignal/. */
body.cs-skin .cs-nav__login {
  display: inline-block;
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  padding: 12px 18px;
  white-space: nowrap;
  text-decoration: none;
  transition: color 0.12s ease-out;
}

body.cs-skin .cs-nav__login:hover { color: var(--lime); }

/* The actions column was pinned at a fixed 152px (grid-template-columns:
   152px auto 152px), which is why "Get in touch" wrapped to two lines and why
   Log in plus the button then ran off the edge.

   Both outer tracks now size to their content, and each gets an equal 1fr of
   the slack on the inside. That keeps the nav optically centred the way the
   original 152px/152px pair did, instead of shoving it left the way a single
   1fr track does. */
/* The bar becomes flex rather than grid at desktop, which is exactly what
   .cs-nav does on /csignal/: logo and actions are fixed, the links are the only
   shrinkable track. A grid with a max-content track sizes to its content and
   then overflows the viewport rather than giving way, which is why the button
   kept getting cut off at the right edge however the tracks were arranged. */
@media screen and (min-width: 1024px) {
  body.cs-skin .header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: clamp(14px, 2vw, 30px);
  }

  /* THE BUG. style.css pins BOTH outer boxes to a fixed 152px:
        .header__brand, .header__buttons { width: 152px; }
     The CTA lives inside .header__buttons, so Log in plus the button, about
     250px, were overflowing a 152px box. .header carries overflow:visible at
     this width, so instead of being clipped it spilled off the right of the
     screen. Rearranging .header__inner never touched it because the constraint
     is one level further in. */
  body.cs-skin .header__buttons {
    width: auto;
    display: flex;
    align-items: center;
    justify-content: flex-end;
  }

  body.cs-skin .header__brand,
  body.cs-skin .header__buttons,
  body.cs-skin .header__acts { flex: none; }

  body.cs-skin .navigation {
    width: auto;
    flex: 1 1 auto;
    min-width: 0;
    justify-content: center;
  }

  body.cs-skin .navigation__list { gap: clamp(16px, 2.1vw, 32px); }
}

/* Bar padding, in CSignal proportions. The Charle header is a floating pill
   rather than a full-width bar, so the 60px side padding from .cs-nav would
   look wrong inside it; the vertical figure is matched and the horizontal one
   is scaled to the pill. */
@media screen and (min-width: 1024px) {
  body.cs-skin .header { padding: 18px 28px; }
}

body.cs-skin .navigation__badge {
  background-color: var(--lime);
  color: var(--ink);
}

/* --- Mega menu --------------------------------------------------------------
   The panel was three unrelated darks at once: a #1a1b1e body, a pure black
   footer bar, and both sitting on a green page. One ground now, with the footer
   bar a step up rather than a different colour.

   The Search / Launch / Sitelab / Helpdesk / Retain marks stay. They are a real
   sub-brand, not decoration, so only the rule under them is restated.
------------------------------------------------------------------------------*/

/* The dropdown was var(--ink), the same value as the dark sections it opens
   over, so its edge disappeared the moment it was not over a light one. A step
   darker plus the drop shadow separates it; a hairline ring was tried too and
   read as a border rather than an edge. */
body.cs-skin .new-nav-dropdown {
  background: var(--ink-0);
  border: 0;
  outline: 0;
  border-radius: 22px;
  box-shadow: 0 28px 64px rgba(0, 0, 0, 0.45);
}

/* The little pointer triangle is drawn as a border colour, so it has to be
   repainted separately or it stays charcoal against the new ground. */
body.cs-skin .new-nav-dropdown::before { border-bottom-color: var(--ink-0); }
body.cs-skin .nav-resources.new-nav-dropdown::before { border-bottom-color: var(--ink-0); }

body.cs-skin .nav-resources.new-nav-dropdown { border-radius: 22px; }

body.cs-skin .new-nav-dropdown__column-header {
  border-bottom-color: var(--line-on-ink);
}

body.cs-skin .new-nav-dropdown__link-title {
  font-weight: 600;
  transition: color 0.12s ease-out;
}

body.cs-skin .new-nav-dropdown__link:hover .new-nav-dropdown__link-title,
body.cs-skin .new-nav-dropdown__item:hover .new-nav-dropdown__link-title {
  color: var(--lime);
}

body.cs-skin .new-nav-dropdown__link-description { color: var(--on-ink-muted); }

body.cs-skin .new-nav-dropdown__item-ai { border-top-color: var(--line-on-ink); }

/* Footer bar: raised plane, not a second colour. */
body.cs-skin .new-nav-dropdown__cta { background: var(--ink-2); }

body.cs-skin .nav-services .new-nav-dropdown__cta { border-radius: 0 0 22px 22px; }
body.cs-skin .nav-resources .new-nav-dropdown__cta { border-radius: 0 22px 22px 0; }

body.cs-skin .new-nav-dropdown__cta-description { color: var(--on-ink-muted); }

body.cs-skin .new-nav-dropdown__cta-description a { text-decoration-color: rgba(243, 245, 238, 0.4); }
body.cs-skin .new-nav-dropdown__cta-description a:hover { color: var(--lime); }

body.cs-skin .new-nav-dropdown__cta-image { border-radius: 14px; }


/*------------------------------------------------------------------------------
  3. Hero
  The stock hero runs a teal-to-purple blurred orb. CSignal has no gradients or
  blurs in it, so the orb is switched off rather than recoloured and the hero
  sits flat on ink. The element stays in the DOM untouched, so reverting is
  still just removing this stylesheet.
------------------------------------------------------------------------------*/

body.cs-skin .search-first,
body.cs-skin .hero-text { background-color: var(--ink); }

body.cs-skin .search-first__gradient,
body.cs-skin .hero-text__gradient { display: none; }

/* --- Clearance under the fixed header ---------------------------------------
   Two separate problems stack up here.

   First, style.css pins body padding-top to 93px / 106px with !important. That
   figure predates the announcement bar, so the bar pushes the header down 40px
   without the page below it moving, and the top of every page loses 40px behind
   the header. Fixed properly here, and switched back off when the bar is
   dismissed so the page does not keep reserving space for something that is
   no longer on screen.

   Second, .cs-hero carries 66px of top padding because on /csignal/ the nav
   sits above it in normal flow. Here the nav is fixed and overlays the hero, so
   the deck cards and the floating shapes ran up under it. */

body.cs-skin { padding-top: calc(93px + var(--cs-anno-h, 0px)) !important; }

@media screen and (min-width: 1024px) {
  body.cs-skin { padding-top: calc(106px + var(--cs-anno-h, 0px)) !important; }
}

.cs-anno-off body.cs-skin { padding-top: 93px !important; }

@media screen and (min-width: 1024px) {
  .cs-anno-off body.cs-skin { padding-top: 106px !important; }
}

/* Body padding already clears the fixed header and the announcement bar, so the
   hero only needs enough of its own to breathe. Anything more and the fold
   opens with a void. */
body.cs-skin .cs-hero {
  padding-top: clamp(24px, 3vw, 56px);
  padding-bottom: clamp(32px, 4vw, 64px);
}

/* MOBILE. csignal-hero.css sets padding: 66px 60px 90px, and the 60px side
   figure is a desktop gutter doing duty on a 390px screen: it eats a third of
   the width and is what makes the hero read as over-margined on a phone.

   The eyebrow's -16px pull is measured against the desktop display size. At
   mobile heading sizes the same 16px bites proportionally much deeper, which
   is the squash: the label ends up sitting on the headline rather than above
   it. Both are scaled to the width rather than removed. */
@media screen and (max-width: 767px) {
  body.cs-skin .cs-hero {
    padding-left: 22px;
    padding-right: 22px;
  }

}

@media screen and (min-width: 768px) and (max-width: 1023px) {
  body.cs-skin .cs-hero {
    padding-left: 34px;
    padding-right: 34px;
  }

}

/* --- Floating "Get in touch" badge ------------------------------------------
   The rotating circular CTA pinned bottom left, from includes/header.php.
   Hidden for now. It is the last piece of old-brand furniture on the page and
   it competes with the CSignal side tab on the opposite edge.

   Hidden rather than removed: the markup is in a shared include, so deleting
   it would take the badge off every other page on the site too. */

body.cs-skin .floating-cta { display: none !important; }

/* Eyebrow. This is the page's H1 and its only job is to be read, by a person
   and by Google, without competing with the display line underneath it. */
body.cs-skin .cs-eyebrow {
  display: block;
  /* Negative, not zero. The display line carries a large line-height, so its
     first line box sits well above the cap height and a 0 margin still reads
     as a gap. This pulls the label onto the headline's shoulder. */
  margin: 0 0 -16px;
  font-family: var(--cs-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--lime);
}

/* The lede wraps a link to /shopify-plus-agency/. page.css never anticipated
   an anchor in there, so it was rendering in the browser's default visited
   purple. The link stays, it just stops announcing itself. */
body.cs-skin .cs-lede a,
body.cs-skin .cs-lede a:visited { color: inherit; text-decoration: none; }

body.cs-skin .cs-lede a:hover { color: var(--paper); }

body.cs-skin .search-first__description,
body.cs-skin .search-first__description a { color: var(--on-ink-muted); }

body.cs-skin .search-first__description a:hover { color: var(--paper); }

/* --- Trusted by: logo marquee -----------------------------------------------
   Sits under the hero, above the text marquee. Same construction as .cs-mq:
   two identical runs inside one track, translated -50%, so the loop is seamless.
   Logos are knocked to white and held back, because they are reassurance rather
   than the thing being read. */

body.cs-skin .cs-lg {
  padding: 30px 0 26px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

body.cs-skin .cs-lg__label {
  margin: 0 0 20px;
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.32);
}

body.cs-skin .cs-lg__wrap {
  position: relative;
  overflow: hidden;
}

body.cs-skin .cs-lg__track {
  display: flex;
  width: max-content;
  animation: cslogos 58s linear infinite;
}

body.cs-skin .cs-lg__run {
  display: flex;
  align-items: center;
  gap: 3rem;
  padding-right: 3rem;
}

/* Every logo gets the same BOX rather than the same height. Constrained on both
   axes, a wide wordmark hits the width ceiling and a compact mark hits the
   height ceiling, so they end up occupying roughly equal area. Sizing on height
   alone is what made the wide ones overbearing and the square ones look lost:
   at a shared 26px tall, a wordmark covers about four times the area of a
   monogram. */

body.cs-skin .cs-lg__item {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 108px;
  height: 34px;
}

body.cs-skin .cs-lg__item img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  display: block;
  filter: brightness(0) invert(1);
  opacity: 0.42;
  transition: opacity 0.3s ease;
}

@media screen and (max-width: 767px) {
  body.cs-skin .cs-lg__item { width: 88px; height: 28px; }
}

/* RNLI carries a #333333 inner detail. A white knockout flattens that away and
   the mark becomes a solid blob, so it opts out, exactly as it does in the
   sv6 bar further down the page. */
body.cs-skin .cs-lg__item img.no-filter { filter: none; opacity: 0.75; }

body.cs-skin .cs-lg__item img:hover { opacity: 0.85; }

body.cs-skin .cs-lg__item img.no-filter:hover { opacity: 1; }

/* Lime asterisk between logos, the same device the text marquee used. */
body.cs-skin .cs-lg__sep {
  flex-shrink: 0;
  color: var(--lime);
  font-size: 14px;
  font-style: normal;
  line-height: 1;
  user-select: none;
}

@keyframes cslogos {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  body.cs-skin .cs-lg__track { animation: none; }
}

/* --- Hero actions -----------------------------------------------------------
   One lime primary, then the four services as outline pills on a second row.
   Both are straight .cs-btn variants from /csignal/, so there is nothing here
   that can drift from the landing page.

   Second row rather than five pills in one, so the primary stays primary. Five
   abreast reads as a menu and the lime stops being the obvious next step. */

body.cs-skin .cs-acts { margin-top: 26px; }

body.cs-skin .cs-svcs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}

/* Held back a little so the lime pair stays the loudest thing in the fold.
   Full strength on hover, so they still feel live rather than disabled. */
body.cs-skin .cs-svcs .cs-btn--outline {
  opacity: 0.62;
  transition: opacity 0.15s ease-out, border-color 0.12s ease-out, color 0.12s ease-out;
}

body.cs-skin .cs-svcs .cs-btn--outline:hover,
body.cs-skin .cs-svcs .cs-btn--outline:focus-visible { opacity: 1; }

@media screen and (max-width: 520px) {
  body.cs-skin .cs-svcs { gap: 6px; }
  body.cs-skin .cs-svcs .cs-btn { font-size: 12px; padding: 9px 14px; }
}

/* --- Services bar (superseded, kept only so the old markup degrades) ---------
   Restyled as one long outline pill, so it reads as a sibling of the
   "See how it works" CTA rather than as a filled panel. Same 1px
   rgba(255,255,255,0.25) hairline, same full radius, same lime on hover, from
   .cs-btn--outline on /csignal/.

   The stock bar draws its dividers as a 1px grid gap with a background showing
   through, which cannot work once the fill is transparent. Gap goes to zero and
   the dividers become real borders on the cells instead. */

body.cs-skin .search-first__pillars {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 20px;
  gap: 0;
  overflow: hidden;
}

body.cs-skin .search-first__pillar {
  background: transparent;
  padding: 1.1rem 1.25rem;
  border-left: 1px solid rgba(255, 255, 255, 0.25);
  transition: background 0.12s ease-out;
}

/* Two columns at mobile, so every odd cell opens a row and must lose its rule.
   Four across from 768, where only the first does. */
body.cs-skin .search-first__pillar:nth-child(2n + 1) { border-left: 0; }

body.cs-skin .search-first__pillar:nth-child(-n + 2) { border-top: 0; }

body.cs-skin .search-first__pillar:nth-child(n + 3) {
  border-top: 1px solid rgba(255, 255, 255, 0.25);
}

@media screen and (min-width: 768px) {
  /* Full pill once it is a single row. The outer cells take extra padding so
     their text clears the curve. */
  body.cs-skin .search-first__pillars { border-radius: 999px; }

  body.cs-skin .search-first__pillar {
    border-top: 0;
    border-left: 1px solid rgba(255, 255, 255, 0.25);
  }

  body.cs-skin .search-first__pillar:first-child {
    border-left: 0;
    padding-left: 2rem;
  }

  body.cs-skin .search-first__pillar:last-child { padding-right: 2rem; }
}

body.cs-skin .search-first__pillar:hover { background: rgba(255, 255, 255, 0.04); }

body.cs-skin .search-first__pillar-label {
  color: var(--paper);
  font-weight: 700;
}

body.cs-skin .search-first__pillar-desc { color: rgba(255, 255, 255, 0.5); }

body.cs-skin .search-first__pillar:hover .search-first__pillar-label,
body.cs-skin .search-first__pillar:hover .search-first__pillar-desc {
  color: var(--lime);
}

body.cs-skin .search-first__see-work { color: var(--on-ink-muted); }
body.cs-skin .search-first__see-work:hover { color: var(--lime); }

/*------------------------------------------------------------------------------
  4. Light sections: paper, not white
  about-charle, projects and faqs are the white bands in the stock page.
------------------------------------------------------------------------------*/

body.cs-skin .about-charle,
body.cs-skin .faqs { background-color: var(--paper); }

/* Lime on a paper ground is close to invisible. Ink, held back. */
body.cs-skin .about-charle__subheading { color: rgba(14, 28, 22, 0.55); }

body.cs-skin .about-charle__heading,
body.cs-skin .about-charle__description,
body.cs-skin .projects__heading,
body.cs-skin .faqs__heading,
body.cs-skin .faqs__left__heading { color: var(--on-paper); }

body.cs-skin .about-charle__description { color: var(--on-paper-muted); }

/* --- About: CSignal treatment -----------------------------------------------
   Modelled on the second section of /csignal/. Treatment only: no copy, no
   links and no heading text changed, so the section reads to Google exactly as
   it did before.
------------------------------------------------------------------------------*/

/* Stats as cards rather than a hairline row, with the ink highlight travelling
   left to right, three seconds on each.

   One 12s loop shared by all four. Each card is "on" for the first 25% of the
   loop, and negative delays offset them so only one is lit at a time:
   0s, -9s, -6s, -3s puts card 1 at 0-3s, card 2 at 3-6s, and so on. Negative
   rather than positive, because a positive delay would hold every card in the
   0% state (lit) until its start time, so they would all be ink on load.

   The delay lives in a custom property on the card. Custom properties inherit,
   so the number and label read the same --d without needing their own
   nth-child rules. */

body.cs-skin .about-charle__stats {
  gap: 12px;
  border-top: 0;
  padding-top: 0;
}

body.cs-skin .about-charle__stat {
  background: #EDF0E6;
  border: 0;
  border-radius: 14px;
  padding: 18px 16px 16px;
  animation: cs-stat-bg 12s linear infinite;
  animation-delay: var(--d, 0s);
}

body.cs-skin .about-charle__stat:nth-child(1) { --d: 0s; }
body.cs-skin .about-charle__stat:nth-child(2) { --d: -9s; }
body.cs-skin .about-charle__stat:nth-child(3) { --d: -6s; }
body.cs-skin .about-charle__stat:nth-child(4) { --d: -3s; }

body.cs-skin .about-charle__stat-number {
  font-family: var(--cs-display);
  font-weight: 800;
  letter-spacing: -0.02em;
  animation: cs-stat-num 12s linear infinite;
  animation-delay: var(--d, 0s);
}

body.cs-skin .about-charle__stat-label {
  animation: cs-stat-lbl 12s linear infinite;
  animation-delay: var(--d, 0s);
}

/* 1.5% of a 12s loop is about 0.18s, which is a flick rather than a fade. */
@keyframes cs-stat-bg {
  0%, 25%    { background: #0E1C16; }
  26.5%, 98.5% { background: #EDF0E6; }
  100%       { background: #0E1C16; }
}

@keyframes cs-stat-num {
  0%, 25%    { color: #D3F502; }
  26.5%, 98.5% { color: #0E1C16; }
  100%       { color: #D3F502; }
}

@keyframes cs-stat-lbl {
  0%, 25%    { color: rgba(243, 245, 238, 0.6); }
  26.5%, 98.5% { color: rgba(14, 28, 22, 0.62); }
  100%       { color: rgba(243, 245, 238, 0.6); }
}

/* --- Hover takeover ---------------------------------------------------------
   Hovering the row pauses the cycle and hands the highlight to whichever card
   is under the cursor. Leaving resumes from exactly where it paused.

   !important is doing real work here rather than being lazy: a running
   animation outranks normal author declarations in the cascade, so a plain
   rule would be ignored even while paused. !important is the one level that
   beats an animation.

   The two hover rules also have to be ordered by specificity, not by intent:
   .about-charle__stats:hover .about-charle__stat is 0,3,0 and would beat a
   bare .about-charle__stat:hover at 0,2,0, so the hovered card is written as a
   descendant of the hovered row to reach 0,4,0. */

body.cs-skin .about-charle__stat,
body.cs-skin .about-charle__stat-number,
body.cs-skin .about-charle__stat-label {
  transition: background 0.18s ease-out, color 0.18s ease-out;
}

/* Row hovered: everything goes quiet and the cycle holds. */
body.cs-skin .about-charle__stats:hover .about-charle__stat {
  animation-play-state: paused;
  background: #EDF0E6 !important;
}

body.cs-skin .about-charle__stats:hover .about-charle__stat-number {
  animation-play-state: paused;
  color: #0E1C16 !important;
}

body.cs-skin .about-charle__stats:hover .about-charle__stat-label {
  animation-play-state: paused;
  color: rgba(14, 28, 22, 0.62) !important;
}

/* The card actually under the cursor takes the highlight. */
body.cs-skin .about-charle__stats:hover .about-charle__stat:hover {
  background: #0E1C16 !important;
}

body.cs-skin .about-charle__stats:hover .about-charle__stat:hover .about-charle__stat-number {
  color: #D3F502 !important;
}

body.cs-skin .about-charle__stats:hover .about-charle__stat:hover .about-charle__stat-label {
  color: rgba(243, 245, 238, 0.6) !important;
}

/* Nothing cycling for anyone who has asked for stillness: the third card just
   stays lit, as it was before. */
@media (prefers-reduced-motion: reduce) {
  body.cs-skin .about-charle__stat,
  body.cs-skin .about-charle__stat-number,
  body.cs-skin .about-charle__stat-label { animation: none; }

  body.cs-skin .about-charle__stat-number { color: var(--ink); }
  body.cs-skin .about-charle__stat-label { color: var(--on-paper-muted); }
  body.cs-skin .about-charle__stat:nth-child(3) { background: var(--ink); }
  body.cs-skin .about-charle__stat:nth-child(3) .about-charle__stat-number { color: var(--lime); }
  body.cs-skin .about-charle__stat:nth-child(3) .about-charle__stat-label { color: rgba(243, 245, 238, 0.6); }
}


/* --- Taupe slab -------------------------------------------------------------
   The cream block behind the right of the section, from /csignal/. Same values
   as .cs-secdeco / .cs-sdeco--slab on the landing page, including the scaleX(-1)
   that turns the staircase to face inward.

   .about-charle needs position and overflow-x: clip so the slab is contained
   and cropped, and the container is lifted above it. */

body.cs-skin .about-charle {
  position: relative;
  overflow-x: clip;
}

body.cs-skin .cs-secdeco {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

body.cs-skin .cs-sdeco { position: absolute; display: block; }

body.cs-skin .cs-sdeco--slab {
  top: 24px;
  right: -150px;
  transform: scaleX(-1);
}

/* The same slab on the projects band, offset left instead. Not flipped: the
   staircase already steps down to the right, which is inward from this edge,
   so scaleX(-1) would turn it back out again. */
body.cs-skin .projects > .container {
  position: relative;
  z-index: 1;
}

/* top:0, not a negative. .cs-secdeco is inset:0 with overflow:hidden, so a
   negative top was cropped by the wrapper and the crop showed as a hard
   horizontal line with a band of plain paper above it. Flush with the section
   top, the slab's own edge lands exactly on the join, where the stepped divider
   covers it and it reads as running up underneath. */
body.cs-skin .cs-sdeco--slab-l {
  top: 0;
  left: -190px;
}

body.cs-skin .about-charle > .container { position: relative; z-index: 1; }

@media screen and (max-width: 1023px) {
  body.cs-skin .cs-secdeco { display: none; }
}

/* --- Arrow buttons ----------------------------------------------------------
   style.css absolutely positions .btn-arrow svg at right: 1.5rem and reserves
   room for it with padding-right: 3rem. Restating the padding as the /csignal/
   13px 24px removed that reservation, so the arrow landed on top of the label.
   /csignal/ does not position its arrow at all: .cs-btn__ext is a 15px inline
   mark with a 6px left margin. Same here. */

body.cs-skin .btn-arrow svg {
  position: static;
  width: 15px;
  height: 15px;
  margin-left: 6px;
  vertical-align: -2px;
  transform: none;
  transition: transform 0.2s ease;
}

body.cs-skin .btn-arrow { padding-right: 24px; }

body.cs-skin .btn-arrow:hover svg { transform: translate(2px, -2px); right: auto; }

/* .cs-hl and .cs-kicker, lifted verbatim from /csignal/ page.css so the
   highlight and the badge are the same components, not lookalikes. */

body.cs-skin .cs-hl {
  position: relative;
  display: inline-block;
  line-height: .84;
  padding: .1em 12px .16em;
  background: var(--lime);
  color: var(--ink);
  border-radius: 10px;
}

/* Back in the About column, in normal flow where the Search-First lockup was. */
body.cs-skin .cs-kicker-hit {
  display: inline-flex;
  cursor: pointer;
  text-decoration: none;
}

body.cs-skin .cs-kicker {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font-family: var(--cs-display), sans-serif;
  font-weight: 800;
  font-size: 13px;
  line-height: 1.3;
  letter-spacing: .03em;
  text-transform: uppercase;
  text-align: center;
  color: var(--lime);
  background: var(--ink);
  border-radius: 14px;
  padding: 11px 18px;
  box-shadow: 0 0 0 5px #fff, 0 10px 22px rgba(14, 28, 22, 0.18);
  transform: rotate(-3.6deg);
  transform-origin: 0% 50%;
  transition: transform .22s cubic-bezier(.2,.9,.2,1), box-shadow .22s ease-out;
  pointer-events: none;
  margin: 0 0 26px;
}

body.cs-skin .cs-kicker em { font-style: normal; color: #fff; }

body.cs-skin .cs-kicker__mark { flex: none; display: block; }

body.cs-skin .cs-kicker-hit:hover .cs-kicker {
  transform: rotate(2.4deg) scale(1.03);
  box-shadow: 0 0 0 5px #fff, 0 16px 30px rgba(14, 28, 22, 0.26);
}

@media (prefers-reduced-motion: reduce) {
  body.cs-skin .cs-kicker { transition: none; }
  body.cs-skin .cs-kicker-hit:hover .cs-kicker { transform: rotate(-3.6deg); }
}

@media (max-width: 720px) {
  body.cs-skin .cs-kicker {
    font-size: 11px;
    gap: 10px;
    padding: 9px 13px;
    border-radius: 12px;
    box-shadow: 0 0 0 4px #fff, 0 8px 18px rgba(14, 28, 22, 0.18);
  }
  body.cs-skin .cs-kicker__mark { height: 26px; width: auto; }
}

/* Punctuation: small bright marks in the margins, the way that section uses
   them. Not background shapes, so they stay small and fully lit. */
body.cs-skin .cs-pun {
  position: absolute;
  line-height: 0;
  pointer-events: none;
  z-index: 1;
}

body.cs-skin .cs-pun--1 { top: 13%;  left: 2.5vw;  transform: rotate(-16deg); }
body.cs-skin .cs-pun--2 { top: 62%;  left: 1.5vw;  transform: rotate(22deg); }
body.cs-skin .cs-pun--3 { bottom: 12%; right: 3vw; transform: rotate(-8deg); }
body.cs-skin .cs-pun--4 { top: 22%;  right: 6vw;   transform: rotate(12deg); }

@media screen and (max-width: 1023px) {
  body.cs-skin .cs-pun { display: none; }
}


/*------------------------------------------------------------------------------
  5. Services grid (sv6) and the wireframe animations
  Kept exactly as built. Recoloured only: the cells sit on ink, the highlight
  state and every animated accent move from the old brand colours to lime.
------------------------------------------------------------------------------*/

body.cs-skin .sv6 {
  background: var(--ink);
  position: relative;
  padding-top: clamp(3rem, 6vw, 6rem);

  /* .section sets overflow:hidden, which would clip the stepped edge since it
     sits above the section's own box. overflow:clip with a clip-margin keeps
     the horizontal clipping that rule is there for while letting the edge
     escape upward. Browsers without overflow-clip-margin simply clip as before
     and lose the edge, which is a clean degradation rather than a break. */
  overflow: clip;
  overflow-clip-margin: 60px;
}

/* --- Stepped edge -----------------------------------------------------------
   The ink reaches up into the paper section above in irregular steps, which is
   the staircase motif the brand shapes are built from rather than a decorative
   wave. Sits outside the section's own box, so the section needs no extra room
   for it, and it stretches to any width because the SVG is preserveAspectRatio:
   none. pointer-events none so it can never intercept a click on the section
   above it. */

body.cs-skin .cs-edge {
  position: absolute;
  left: 0;
  right: 0;
  /* Tucked 1px into its own section, for every edge rather than just the paper
     one. Flush at bottom:100% the two boxes meet on a fractional device pixel
     and at some widths the browser leaves a hairline of the section ABOVE
     showing through the join, which is the light line under the teeth. */
  bottom: calc(100% - 1px);
  /* Above .cs-secdeco, which carries z-index 0 and comes later in the markup.
     Left to DOM order the backdrop slab painted over the teeth. */
  z-index: 3;
  height: clamp(22px, 2.6vw, 44px);
  line-height: 0;
  pointer-events: none;
}

body.cs-skin .cs-edge svg {
  display: block;
  width: 100%;
  height: 100%;
}

body.cs-skin .cs-edge path { fill: var(--ink); }

/* The mirror of it, for a paper section arriving under an ink one: the paper
   steps DOWN into the ink instead. index.css hands .projects a 35px top radius
   and pulls it up by the same amount, which is the soft curve this replaces, so
   both go. The step run is deliberately a different rhythm from the edge at the
   top of the services section; the same one mirrored reads as a fold. */
body.cs-skin .projects {
  position: relative;
  z-index: 1;
  border-radius: 0;
  margin-top: 0;
  background-color: var(--paper);

  /* Same reason as .sv6: .section sets overflow:hidden, and the edge lives
     outside this section's box at bottom:100%, so hidden clipped it away. */
  overflow: clip;
  overflow-clip-margin: 60px;
}

body.cs-skin .cs-edge--paper path { fill: var(--paper); }

/* .cs-edge--paper had its own 1px tuck; it is on the base rule now. */

/* --- Section heading --------------------------------------------------------
   The markup already carries "Delivering Growth / Our Services" as an eyebrow
   and an h2. It was set to display:none and only switched on below 1024, so
   desktop never saw it. Shown at every width and restyled, which is better than
   adding a second h2 the page would then have to rank. */

/* The badge sits on the heading's baseline row rather than above it, so it
   costs no vertical space of its own. max-width moves off the row and onto the
   text column, or the heading would stop wrapping where it used to. */
body.cs-skin .sv6__mobile-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  margin-bottom: clamp(2rem, 4vw, 3.5rem);
}

body.cs-skin .sv6__mobile-heading-text {
  max-width: 900px;
  min-width: 0;
}

body.cs-skin .sv6__mobile-heading-sub {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--lime);
  margin-bottom: 14px;
}

body.cs-skin .sv6__mobile-heading-main {
  font-size: clamp(34px, 5.2vw, 68px);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.025em;
  color: var(--paper);
}

/* --- Cards ------------------------------------------------------------------
   Eight identical dark cards on a dark ground is what made this read flat. Two
   of them take an accent ground for rhythm, the way /csignal/ alternates its
   three. Only the text-only cells are eligible: cells 1, 4, 7 and 8 carry dark
   wireframe graphics that would break on a light ground, and repainting those
   is the second pass.
------------------------------------------------------------------------------*/

/* Light by default, on the ink ground. Two lime accents and one ink, which is
   the /csignal/ ratio: paper leads, the accents punctuate.

     1 SEO & GEO        paper   (graphic)
     2 New Stores       paper
     3 Migrations       LIME
     4 CRO              paper   (graphic)
     5 Theme Dev        INK
     6 Support          LIME
     7 UI / UX          paper   (graphic)
     8 Email & SMS      paper   (graphic)

   Every badge mark is swapped to its dark file in the markup, since white
   artwork on paper is invisible. The five in sv6__products-item stay white:
   that row is still on the dark ground. */

body.cs-skin .sv6__cell {
  background: var(--paper);
  border-color: transparent !important;
  transition: background 0.18s ease-out, transform 0.18s ease-out;
}

/* No hover state on the cards at all. The page's inline CSS lightens the
   ground, whitens the text, shifts the arrow and dims the graphic; every one of
   those is neutralised here rather than edited out of the page. */
body.cs-skin .sv6__cell:hover { background: var(--paper); color: inherit; }
body.cs-skin .sv6__cell--2:hover,
body.cs-skin .sv6__cell--5:hover,
body.cs-skin .sv6__cell--6:hover { background: var(--ink-2); }

body.cs-skin .sv6__cell:hover .sv6__cell-name,
body.cs-skin .sv6__cell:hover .sv6__cell-number,
body.cs-skin .sv6__cell:hover .sv6__cell-arrow { color: var(--ink); }

body.cs-skin .sv6__cell--2:hover .sv6__cell-name,
body.cs-skin .sv6__cell--2:hover .sv6__cell-number,
body.cs-skin .sv6__cell--2:hover .sv6__cell-arrow,
body.cs-skin .sv6__cell--5:hover .sv6__cell-name,
body.cs-skin .sv6__cell--5:hover .sv6__cell-number,
body.cs-skin .sv6__cell--5:hover .sv6__cell-arrow,
body.cs-skin .sv6__cell--6:hover .sv6__cell-name,
body.cs-skin .sv6__cell--6:hover .sv6__cell-number,
body.cs-skin .sv6__cell--6:hover .sv6__cell-arrow { color: var(--paper); }

body.cs-skin .sv6__cell:hover .sv6__cell-desc { color: rgba(14, 28, 22, 0.66); }
body.cs-skin .sv6__cell--2:hover .sv6__cell-desc,
body.cs-skin .sv6__cell--5:hover .sv6__cell-desc,
body.cs-skin .sv6__cell--6:hover .sv6__cell-desc { color: var(--on-ink-muted); }

body.cs-skin .sv6__cell:hover .sv6__cell-badge { border-color: transparent; }
body.cs-skin .sv6__cell:hover .sv6__cell-badge img { filter: brightness(0); opacity: 0.8; }
body.cs-skin .sv6__cell--2:hover .sv6__cell-badge img,
body.cs-skin .sv6__cell--5:hover .sv6__cell-badge img,
body.cs-skin .sv6__cell--6:hover .sv6__cell-badge img { filter: none; opacity: 1; }
body.cs-skin .sv6__cell:hover .sv6__graphic { opacity: 1; }
/* Arrow: bottom right, and only on hover. The page pins it top right and keeps
   it permanently visible; both are restated here. Applied to every cell rather
   than just SEO & GEO, so one card does not behave differently from the rest. */
body.cs-skin .sv6__cell-arrow {
  top: auto;
  bottom: 1.8rem;
  right: 1.8rem;
  width: 40px;
  height: 40px;
  /* 2px rather than the stock 1px hairline. CSignal draws its shapes at weight,
     and a 1px ring around a solid mark reads as two different line languages in
     the same badge. */
  border: 2px solid currentColor;
  opacity: 0;
  transform: translate(4px, -4px);
  transition: opacity 0.18s ease-out, transform 0.18s ease-out;
}

/* The mark is the cursor from the CSignal logo rather than a generic chevron.
   Its natural orientation points north-west, so +90deg turns it to north-east,
   which is where an outbound arrow should point. */
body.cs-skin .sv6__cell-arrow svg {
  display: block;
  transform: rotate(90deg);
  transition: transform 0.18s ease-out;
}

body.cs-skin .sv6__cell:hover .sv6__cell-arrow svg { transform: rotate(90deg) translateX(1.5px); }

body.cs-skin .sv6__cell:hover .sv6__cell-arrow {
  opacity: 1;
  transform: none;
  border-color: currentColor;
}
body.cs-skin .sv6__cell-arrow svg,
body.cs-skin .sv6__cell:hover .sv6__cell-arrow svg { color: inherit; }

/* Cell 8 only. The page gives that cell's graphic position:relative and
   z-index:1, the same z-index the text column carries, and the graphic is the
   later sibling, so it painted over the hover arrow. Lifting the text column
   above it puts the arrow back on top; the arrow's own z-index is scoped to
   that column's stacking context, so it has to be raised there, not here. */
body.cs-skin .sv6__cell--8 .sv6__cell-content { z-index: 3; }
body.cs-skin .sv6__cell-arrow { z-index: 4; }

body.cs-skin .sv6__cell-name,
body.cs-skin .sv6__cell-number,
body.cs-skin .sv6__cell-arrow { color: var(--ink); }

body.cs-skin .sv6__cell-desc { color: rgba(14, 28, 22, 0.66); }

body.cs-skin .sv6__cell-number { opacity: 0.35; }

/* Every logo-*.svg is white artwork, the so-called dark variants included, so
   the filenames are misleading. Black on the light cards has to come from a
   filter rather than from picking a different file. */
body.cs-skin .sv6__cell-badge img { filter: brightness(0); opacity: 0.8; }

/* No lime card in this grid any more. Cell 3 (Shopify Migrations) was the last
   one and is now paper, so it inherits the .sv6__cell base and its description
   takes the same 0.66 tone as every other light card. The accent in this
   section comes from the shape kit instead, one colour per card. */

/* Ink. Cells 2 (New Stores), 5 (Theme Development) and 6 (Support &
   Maintenance). Six was lime and moved here so the dark cards sit one per row
   rather than two of the three accents landing in the same column. */
body.cs-skin .sv6__cell--2,
body.cs-skin .sv6__cell--5,
body.cs-skin .sv6__cell--6 {
  background: var(--ink-2);
  border-color: var(--line-on-ink) !important;
}

body.cs-skin .sv6__cell--2 .sv6__cell-name,
body.cs-skin .sv6__cell--2 .sv6__cell-number,
body.cs-skin .sv6__cell--2 .sv6__cell-arrow,
body.cs-skin .sv6__cell--5 .sv6__cell-name,
body.cs-skin .sv6__cell--5 .sv6__cell-number,
body.cs-skin .sv6__cell--5 .sv6__cell-arrow,
body.cs-skin .sv6__cell--6 .sv6__cell-name,
body.cs-skin .sv6__cell--6 .sv6__cell-number,
body.cs-skin .sv6__cell--6 .sv6__cell-arrow { color: var(--paper); }

body.cs-skin .sv6__cell--2 .sv6__cell-desc,
body.cs-skin .sv6__cell--5 .sv6__cell-desc,
body.cs-skin .sv6__cell--6 .sv6__cell-desc { color: var(--on-ink-muted); }

/* The four wireframe graphics are still dark panels. On a paper card they now
   read as a screenshot sitting on the card, so they get a radius and a hairline
   to make that deliberate. Rebuilding them light is the second pass. */
body.cs-skin .sv6__graphic {
  border-radius: 14px;
  overflow: hidden;
}

/* The ported cards bring their own white grounds and shadows, so the wrapper
   must not clip or round them. */
body.cs-skin .sv6__graphic.cs-find,
body.cs-skin .sv6__graphic.cs-dsn,
body.cs-skin .sv6__graphic.cs-flow {
  border-radius: 0;
  overflow: visible;
}

/*==============================================================================
  CRO graphic: the roadmap
  ----------------------------------------------------------------------------
  The "Recommendations, in real time" panel from /csignal/. Three jobs cycling
  through the top slot on one 8.4s loop, offset by their inline delays, so
  whichever is at the top is lime and the other two sit back.

  Ported verbatim apart from the ground: on /csignal/ it lives on an ink card
  and uses rgba(255,255,255,.06), which would be invisible on a paper card, so
  it carries its own ink panel here.
==============================================================================*/

body.cs-skin .sv6__graphic.cs-road {
  position: relative;
  display: block;
  height: 150px;
  border-radius: 14px;
  padding: 14px;
  overflow: hidden;
  background: var(--ink-2);
  opacity: 1;
}

body.cs-skin .cs-road__n {
  position: absolute;
  left: 14px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
  font-size: 10px;
  color: rgba(255, 255, 255, 0.35);
  line-height: 30px;
}

body.cs-skin .cs-road__n:nth-of-type(1) { top: 24px; }
body.cs-skin .cs-road__n:nth-of-type(2) { top: 58px; }
body.cs-skin .cs-road__n:nth-of-type(3) { top: 92px; }

body.cs-skin .cs-road__job {
  position: absolute;
  top: 24px;
  left: 44px;
  right: 14px;
  height: 30px;
  display: flex;
  align-items: center;
  padding: 0 12px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  animation: cs-road 8.4s cubic-bezier(.7,0,.3,1) infinite;
}

@keyframes cs-road {
  0%, 26%   { transform: translateY(0);    background: var(--lime); color: var(--ink); }
  33%, 59%  { transform: translateY(34px); background: rgba(255,255,255,.1); color: #fff; }
  66%, 92%  { transform: translateY(68px); background: rgba(255,255,255,.1); color: #fff; }
  100%      { transform: translateY(0);    background: var(--lime); color: var(--ink); }
}

@media (prefers-reduced-motion: reduce) {
  body.cs-skin .cs-road__job { animation: none; }
  body.cs-skin .cs-road__job:nth-of-type(4) { background: var(--lime); color: var(--ink); }
  body.cs-skin .cs-road__job:nth-of-type(5) { transform: translateY(34px); background: rgba(255,255,255,.1); color: #fff; }
  body.cs-skin .cs-road__job:nth-of-type(6) { transform: translateY(68px); background: rgba(255,255,255,.1); color: #fff; }
}

body.cs-skin .sv6__cell-name { font-weight: 800; letter-spacing: -0.02em; }

/*==============================================================================
  SEO & GEO graphic: the Search and AI cards
  ----------------------------------------------------------------------------
  Ported from /new-era/mockup/. Two 2:1 cards side by side: a Google result list
  that climbs to position one, and an AI answer that cites you.

  Two changes from the source. There, the animations are gated on body.cs-goog
  and body.cs-ai, which a scene script toggles; here they run on their own, so
  those prefixes are dropped. And the source sizes everything in cqh against a
  full-height stage, so each card declares its own container-type: size.
==============================================================================*/

/* align-items must NOT be stretch. container-type: size contains the card, so
   its height cannot come from its contents; with stretch, the height then comes
   from the row, whose height comes from the contained cards. That circle
   resolves to zero, every cqh computes to 0, and the cards render as empty
   white boxes. flex-start lets aspect-ratio set a real height off the width. */
body.cs-skin .cs-find {
  display: flex;
  gap: 14px;
  width: 100%;
  align-items: flex-start;
}

/* Height is an explicit clamp, not aspect-ratio. container-type: size needs a
   definite size on BOTH axes before container units resolve, and a height
   derived from aspect-ratio does not reliably count once the box is
   size-contained. With it unresolved every descendant cqh computed to 0, which
   is why the cards rendered as empty white boxes.

   The card's OWN padding and radius are in px on purpose: an element's
   container units resolve against its ANCESTOR container, not itself, so cqh
   here would measure the wrong box. Only the descendants query this card. */
body.cs-skin .cs-lc {
  flex: 1 1 0;
  min-width: 0;
  height: clamp(150px, 17vw, 215px);
  container-type: size;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  padding: 16px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 6px 18px rgba(14, 28, 22, 0.08);
}

@media screen and (max-width: 760px) {
  body.cs-skin .cs-find { flex-direction: column; }

  /* flex: 1 1 0 has to go, not just be joined by a height. Once .cs-find turns
     column the main axis becomes the vertical one, so that flex-basis of 0 is a
     HEIGHT of 0 and it outranks the height property. The container's own height
     is auto, so the items grow to fill a box whose size comes from the items:
     that resolves to zero, every cqh computes to 0, and both cards render as
     empty white bars. Exactly the failure the desktop rule above documents,
     arriving by a different route. */
  body.cs-skin .cs-lc {
    flex: 0 0 auto;
    width: 100%;
    height: clamp(160px, 46vw, 220px);
  }

  /* One card, not two stacked. Side by side the pair is the point, Google and
     an AI answer read together; stacked they are just the same card twice at
     half the size. The AI one stays because it is the half that is new. */
  body.cs-skin .cs-lc--goog { display: none; }
}

/* --- shared ---------------------------------------------------------------*/
body.cs-skin .sr-top { display: flex; align-items: center; justify-content: space-between; gap: 5cqh; }

body.cs-skin .sr-k {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
  font-size: 5cqh; letter-spacing: .14em; text-transform: uppercase;
  color: #8496B5; white-space: nowrap;
}

body.cs-skin .sr-pill {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
  font-size: 5cqh; letter-spacing: .09em; text-transform: uppercase;
  padding: 2.5cqh 5cqh; border-radius: 10cqh;
  background: #C9F73B; color: #2A3A10; white-space: nowrap;
  animation: sr-breathe 1.9s ease-in-out .9s infinite;
}

body.cs-skin .sr-q {
  display: block;
  font-weight: 700; font-size: 10.5cqh; letter-spacing: -.02em;
  color: #14211B; white-space: nowrap;
}

/* --- Google card ----------------------------------------------------------*/
body.cs-skin .sr-rows { display: flex; flex-direction: column; gap: 3cqh; position: relative; }
body.cs-skin .sr-row { display: flex; align-items: center; gap: 5cqh; }

body.cs-skin .sr-n {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
  font-size: 5.5cqh; color: #A8B2C4; width: 6cqh; flex: none;
}

body.cs-skin .sr-b {
  flex: 1; height: 8cqh; border-radius: 3.5cqh;
  position: relative; overflow: hidden;
  transform-origin: left center; transform: scaleX(0);
  background-color: #EEF1F6;
  animation: sr-in .5s cubic-bezier(.7,0,.3,1) both;
}

body.cs-skin .sr-b::after,
body.cs-skin .ai-ty::after {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 45%;
  background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.75) 50%, rgba(255,255,255,0) 100%);
  animation: sr-sweep 1.75s linear infinite;
}

body.cs-skin .sr-rows .sr-row:nth-child(1) .sr-b { animation-delay: .05s; }
body.cs-skin .sr-rows .sr-row:nth-child(2) .sr-b { animation-delay: .13s; }
body.cs-skin .sr-rows .sr-row:nth-child(3) .sr-b { animation-delay: .34s; }
body.cs-skin .sr-rows .sr-row:nth-child(4) .sr-b { animation-delay: .21s; }
body.cs-skin .sr-rows .sr-row:nth-child(5) .sr-b { animation-delay: .29s; }

body.cs-skin .sr-climb {
  position: absolute; left: 0; right: 0; top: 0;
  display: flex; align-items: center; gap: 5cqh;
  animation: sr-climb 9s cubic-bezier(.6,0,.25,1) infinite;
}

body.cs-skin .sr-climb .sr-n { visibility: hidden; }

body.cs-skin .sr-climb .sr-b {
  transform: scaleX(1); background-color: #C9F73B;
  display: flex; align-items: center; padding: 0 4cqh;
  animation: sr-pulse 1.6s ease-in-out infinite;
}

body.cs-skin .sr-you {
  font-size: 5cqh; font-weight: 600; color: #2A3A10; white-space: nowrap;
  position: relative; z-index: 1;
}

body.cs-skin .sr-n.n5 { animation: sr-lit-n5 9s linear infinite; }
body.cs-skin .sr-n.n4 { animation: sr-lit-n4 9s linear infinite; }
body.cs-skin .sr-n.n3 { animation: sr-lit-n3 9s linear infinite; }
body.cs-skin .sr-n.n2 { animation: sr-lit-n2 9s linear infinite; }
body.cs-skin .sr-n.n1 { animation: sr-lit-n1 9s linear infinite; }

body.cs-skin .sr-move {
  display: flex; align-items: center; gap: 4cqh;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
  font-size: 6.5cqh;
  animation: sr-move-in 9s ease infinite;
}

body.cs-skin .sr-was { color: #A8B2C4; }
body.cs-skin .sr-now { color: #5C7A18; }
body.cs-skin .sr-move svg { width: 6.5cqh; height: 6.5cqh; color: #5C7A18; }

body.cs-skin .sr-when {
  margin-left: auto; font-size: 5cqh; letter-spacing: .08em; text-transform: uppercase;
  color: #5C7A18; background: #EEF9C6; padding: 1.5cqh 4cqh; border-radius: 8cqh;
}

/* --- AI card --------------------------------------------------------------*/
body.cs-skin .ai-ans {
  background: #EEF2FF; border-radius: 7cqh; padding: 2cqh 6.5cqh;
  display: flex; flex-direction: column; gap: 4.5cqh;
}

/* The AI card has one fewer block than the Google one. Its own top and bottom
   padding comes down so the contents sit tighter, and the whole card moves down
   on a margin rather than padding, so the two changes stay independent: last
   time I used padding-top for the nudge, which pushed it down but also made the
   padding worse, which was the opposite of what was asked. */
body.cs-skin .cs-lc--ai {
  padding-top: 8px;
  padding-bottom: 8px;
  margin-top: 30px;
}

body.cs-skin .ai-ty {
  display: block; height: 6cqh; border-radius: 3cqh;
  position: relative; overflow: hidden;
  transform-origin: left center; transform: scaleX(0);
  background-color: #D6E0F7;
  animation: sr-in .55s cubic-bezier(.7,0,.3,1) both;
}

body.cs-skin .ai-row { display: flex; align-items: center; gap: 4.5cqh; }

body.cs-skin .ai-chip {
  font-style: normal; font-size: 6cqh; font-weight: 600;
  background: #C9F73B; color: #2A3A10; border-radius: 2.5cqh;
  padding: 1cqh 4cqh; white-space: nowrap;
  animation: sr-breathe 1.7s ease-in-out 1s infinite;
}

body.cs-skin .ai-src { display: flex; align-items: center; gap: 5cqh; }
body.cs-skin .ai-srcs { display: flex; gap: 3.5cqh; flex: 1; }

body.cs-skin .ai-srcs span {
  height: 8cqh; border-radius: 3.5cqh; flex: 1;
  transform-origin: left center; transform: scaleX(0);
  background-color: #EEF1F6;
  animation: sr-in .45s cubic-bezier(.7,0,.3,1) both, ai-cite 3.6s ease-in-out infinite;
}

body.cs-skin .ai-srcs span.is-lit { flex: 1.4; }
body.cs-skin .ai-srcs span:nth-child(1) { animation-delay: .62s, .70s; }
body.cs-skin .ai-srcs span:nth-child(2) { animation-delay: .72s, 1.60s; }
body.cs-skin .ai-srcs span:nth-child(3) { animation-delay: .68s, 2.50s; }
body.cs-skin .ai-srcs span:nth-child(4) { animation-delay: .78s, 3.40s; }

/* --- keyframes ------------------------------------------------------------*/

/* One 9s loop for the whole card. The row enters at position 9, steps up
   through 5, 4, 3, 2 and holds at 1, then fades and starts again, so the climb
   is visible whenever someone happens to scroll past rather than only in the
   first three seconds of the page's life. */
@keyframes sr-climb {
  0%       { transform: translateY(44cqh); opacity: 0; }
  4%, 12%  { transform: translateY(44cqh); opacity: 1; }
  18%, 26% { transform: translateY(33cqh); }
  32%, 40% { transform: translateY(22cqh); }
  46%, 54% { transform: translateY(11cqh); }
  60%, 92% { transform: translateY(0); opacity: 1; }
  98%,100% { transform: translateY(0); opacity: 0; }
}

@keyframes sr-lit-n5 { 0%,3% { color:#A8B2C4; } 5%,12% { color:#5C7A18; } 15%,100% { color:#A8B2C4; } }
@keyframes sr-lit-n4 { 0%,17% { color:#A8B2C4; } 19%,26% { color:#5C7A18; } 29%,100% { color:#A8B2C4; } }
@keyframes sr-lit-n3 { 0%,31% { color:#A8B2C4; } 33%,40% { color:#5C7A18; } 43%,100% { color:#A8B2C4; } }
@keyframes sr-lit-n2 { 0%,45% { color:#A8B2C4; } 47%,54% { color:#5C7A18; } 57%,100% { color:#A8B2C4; } }
@keyframes sr-lit-n1 { 0%,59% { color:#A8B2C4; } 62%,94% { color:#5C7A18; } 98%,100% { color:#A8B2C4; } }

@keyframes sr-move-in {
  0%, 58%   { opacity: 0; transform: translateY(2.5cqh); }
  64%, 92%  { opacity: 1; transform: none; }
  97%, 100% { opacity: 0; transform: translateY(2.5cqh); }
}

@keyframes sr-in      { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes sr-sweep   { from { transform: translateX(-160%); } to { transform: translateX(340%); } }
@keyframes sr-breathe { 0%,100% { transform: scale(1); } 50% { transform: scale(1.05); } }
@keyframes sr-pulse   { 0%,100% { filter: brightness(1); } 50% { filter: brightness(1.15); } }
@keyframes ai-cite    { 0%,6% { background-color:#EEF1F6; } 12%,26% { background-color:#C9F73B; } 32%,100% { background-color:#EEF1F6; } }

/* (Removed: an orphaned 4-step keyframe body, the remains of an older, shorter
   sr-climb. Its "@keyframes sr-climb {" opening line had been deleted when the
   7-step version above replaced it, leaving three percentage rules and a stray
   closer at the top level of the stylesheet. Browsers discarded them, so
   nothing rendered differently, but the file no longer parses clean.) */

@media (prefers-reduced-motion: reduce) {
  body.cs-skin .cs-find * { animation: none !important; }
  body.cs-skin .cs-find .sr-b,
  body.cs-skin .cs-find .ai-ty,
  body.cs-skin .cs-find .ai-srcs span { transform: scaleX(1); }
  body.cs-skin .cs-find .sr-move { opacity: 1; transform: none; }
  body.cs-skin .cs-find .sr-climb { transform: translateY(0); }
}

/* --- Punctuation ------------------------------------------------------------
   Same device as the About section: small, bright, in the margins. */

/* cs-pun--s1 retired: the spark now hangs off the badge itself rather than off
   the section, so it holds the corner at every width. See .cs-kicker__spark. */
body.cs-skin .cs-pun--s2 { position: absolute; top: 46%; left: 1vw;   transform: rotate(-12deg); line-height: 0; pointer-events: none; z-index: 1; }
body.cs-skin .cs-pun--s3 { position: absolute; bottom: 8%; right: 4vw; transform: rotate(26deg); line-height: 0; pointer-events: none; z-index: 1; }

@media screen and (max-width: 1023px) {
  body.cs-skin .cs-pun--s1,
  body.cs-skin .cs-pun--s2,
  body.cs-skin .cs-pun--s3 { display: none; }
}


/* The SERP result highlight, the CRO variant badge and the email flow arrows
   all carried the old accent. One rule catches the fills, one the strokes. */
body.cs-skin .sv6 [fill="#00E9E4"],
body.cs-skin .sv6 [fill="#A04FF4"],
body.cs-skin .sv6 [fill="#7B61FF"] { fill: var(--lime) !important; }

body.cs-skin .sv6 [stroke="#00E9E4"],
body.cs-skin .sv6 [stroke="#A04FF4"],
body.cs-skin .sv6 [stroke="#7B61FF"] { stroke: var(--lime) !important; }

body.cs-skin .sv6__cta { color: var(--lime); }

/*------------------------------------------------------------------------------
  6. Video band
  Kept, as agreed. It sits on ink rather than black and gets a lime hairline so
  it reads as deliberate rather than as a hole in the page.
------------------------------------------------------------------------------*/

/* --- Hero gallery video -----------------------------------------------------
   The big video under the logo bar is .hero-gallery__main-image from
   includes/hero.php, not .charle-video further down the page.

   It was never full bleed. hero.css sizes its first frame as
       width:  calc(100vw - (2 * var(--gutter)))
       height: calc(100vh - (2 * var(--gutter)))
   with --gutter: 2rem, and .hero-gallery adds another 2rem of side padding on
   top of that. So it arrived inset on all four sides by design.

   Gutter and padding go to zero, and the keyframes are re-declared under new
   names carrying border-radius, so the video starts square and edge to edge and
   rounds off as it shrinks into the grid. New names because @keyframes resolve
   by source order, not specificity: reusing scale-x would only work while this
   sheet loads after hero.css. */

body.cs-skin .hero-gallery {
  --gutter: 0px;
  padding: 0;
}

body.cs-skin .hero-gallery__main-image { margin: 0 auto; }

/* hero.css puts 30px of padding on top of the grid, which is the last gap
   between the logo bar's hairline and the top of the video. */
body.cs-skin .hero-gallery__grid { padding-top: 0; }

/* --- CSignal shapes behind the gallery --------------------------------------
   Six brand shapes, large and cropped off the edges, drifting behind the grid.
   Full brand colour rather than tinted, so the section still reads as CSignal
   once the video has shrunk and the ink ground is showing through.

   The layer is inert: pointer-events none, aria-hidden, and pinned under the
   grid, so it can never sit between someone and a case study link. */

body.cs-skin .cs-gal-deco {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

/* THE SEAM ABOVE THE VIDEO.
   .hero-gallery__inner is sticky at top: 0, so while the video is full bleed
   its top edge and the top of this box are the same line, and the logo bar
   sits directly above it. Any sub-pixel the video does not cover shows the
   shape layer, which reads as a thin coral or blue sliver cutting across the
   join rather than as brand furniture.

   The curtain is a child of the deco layer rather than of the gallery, which
   matters: the deco is z-index 0 and clipped, so this can only ever cover
   shapes. Put the same rule on .hero-gallery__inner and it would paint over
   the case study thumbnails, which are unpositioned and therefore below a
   z-index of 1. */
body.cs-skin .cs-gal-deco::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 16px;
  background: var(--ink);
}

/* animation-direction is NOT alternate. The keyframes run 0 -> up -> 0 on
   their own, so the inline duration is one complete round trip, the same as the
   hero's cs-float. With alternate the duration bought only half a cycle and
   every shape took twice as long to do the same thing. */
body.cs-skin .cs-gal-deco__s {
  position: absolute;
  display: block;
  line-height: 0;
  opacity: 0.9;
  animation-name: cs-gal-float;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}

body.cs-skin .cs-gal-deco__s svg { display: block; height: auto; }

/* Depth: biggest is faintest and furthest back, smallest is brightest and
   nearest. All four bleed off an edge so they read as brand furniture running
   past the frame rather than stickers placed inside it. */

/* xl — the ground plane. Very large, right aligned, bleeding off the edge, in a
       green one step up from the ink so the grid has something behind it.
       Sits under the other six. */
/* Centring moved off `translate` and into `transform`. The float keyframe
   animates `translate`, so anything the element sets there is overwritten the
   moment the animation starts, and this slab lost its -50% centring. */
body.cs-skin .cs-gal-deco__s--xl {
  top: 50%;
  right: -18vw;
  transform: translateY(-50%) rotate(-6deg);
  opacity: 1;
  z-index: 0;
}

body.cs-skin .cs-gal-deco__s--xl svg {
  height: clamp(620px, 96vh, 1180px);
  width: auto;
}

/* The six brand shapes sit above the ground plane. */
body.cs-skin .cs-gal-deco__s--tl,
body.cs-skin .cs-gal-deco__s--tr,
body.cs-skin .cs-gal-deco__s--tr2,
body.cs-skin .cs-gal-deco__s--bl,
body.cs-skin .cs-gal-deco__s--br,
body.cs-skin .cs-gal-deco__s--ml,
body.cs-skin .cs-gal-deco__s--mr { z-index: 1; }

body.cs-skin .cs-gal-deco__s--tl { top: -7vh;    left: -6vw;  transform: rotate(-12deg); }
body.cs-skin .cs-gal-deco__s--tr { top: -4vh;    right: -7vw; transform: rotate(14deg); }

/* Small lime spark, tucked off the bottom-left corner of the blue block so it
   reads as something firing off that shape rather than floating on its own.
   Punctuation, so it stays small and fully lit. */
body.cs-skin .cs-gal-deco__s--tr2 { top: 21vh; right: 20vw; transform: rotate(-24deg); }
body.cs-skin .cs-gal-deco__s--bl { bottom: -8vh; left: -5vw;  transform: rotate(8deg); }
body.cs-skin .cs-gal-deco__s--br { bottom: -6vh; right: -4vw; transform: rotate(-18deg); }
body.cs-skin .cs-gal-deco__s--ml { top: 42%;     left: 4vw;   transform: rotate(-8deg); }
body.cs-skin .cs-gal-deco__s--mr { top: 30%;     right: -12vw; transform: rotate(10deg); opacity: 1; }

/* Amplitudes, scaled to each shape. The two small marks get a wider swing and
   more turn because at that size it reads as character; the slab gets the
   largest travel in pixels and the least rotation, because a 1180px shape
   turning three degrees sweeps a very long way at its corners. */
body.cs-skin .cs-gal-deco__s--xl  { --amp: 54px; --rotamp: 1.2deg; }
body.cs-skin .cs-gal-deco__s--tl  { --amp: 40px; --rotamp: 3deg; }
body.cs-skin .cs-gal-deco__s--tr  { --amp: 38px; --rotamp: 3.4deg; }
body.cs-skin .cs-gal-deco__s--bl  { --amp: 36px; --rotamp: 3.2deg; }
body.cs-skin .cs-gal-deco__s--br  { --amp: 34px; --rotamp: 3.6deg; }
body.cs-skin .cs-gal-deco__s--tr2 { --amp: 26px; --rotamp: 9deg; }
body.cs-skin .cs-gal-deco__s--ml  { --amp: 28px; --rotamp: 8deg; }

/* The hero's motion, borrowed. csignal-hero.css floats its shapes on cs-float:
   a short 9px lift paired with a 1.4deg turn, which is what stops it reading as
   a lift and starts it reading as drift. This was a bare 26px vertical slide,
   which at that distance looks like a slider rather than a floating object.

   Rotation has to be the individual `rotate` property, not `transform`. Each
   shape already carries its resting angle in `transform: rotate(...)`, and the
   two do compose: translate, then rotate, then transform. Animating `transform`
   here would overwrite the resting angle and every shape would snap square the
   moment the animation started. */
/* Amplitude is a per-shape variable rather than one figure for all of them.
   A 1180px slab and a 66px spark moving the same 12px is the same distance but
   nothing like the same amount of movement: the big one barely registers while
   the small one is the only thing you notice. Each shape sets its own. */
@keyframes cs-gal-float {
  0%, 100% {
    translate: 0 0;
    rotate: 0deg;
  }
  50% {
    translate: calc(var(--amp, 26px) * 0.22) calc(var(--amp, 26px) * -1);
    rotate: var(--rotamp, 3deg);
  }
}

/* NOTE: do not give .hero-gallery__grid position/z-index to lift it above the
   shapes. It opens a new stacking context and re-composites the gallery's own
   layers, which detaches the main video from its cell. The shapes sit behind on
   their own, because .hero-gallery__main-image already carries z-index 2 and
   the layers are positioned above this layer's 0. */

/* Below 1024 the gallery is tight enough that the shapes only crowd it. */
@media screen and (max-width: 1023px) {
  /* Only the roadmap and the cursor survive at phone width. Four shapes around
     a gallery this tight stops being depth and starts being clutter. */
  body.cs-skin .cs-gal-deco__s--ml,
  body.cs-skin .cs-gal-deco__s--tr2,
  body.cs-skin .cs-gal-deco__s--br,
  body.cs-skin .cs-gal-deco__s--xl { display: none; }

  body.cs-skin .cs-gal-deco__s { opacity: 0.7; }
}

@media (prefers-reduced-motion: reduce) {
  body.cs-skin .cs-gal-deco__s { animation: none; }
}

@keyframes cs-hero-w {
  0%, 10% { width: 100vw; border-radius: 0; }
}

@keyframes cs-hero-h-desktop {
  0%, 10% { height: 100vh; }
}

@keyframes cs-hero-h-mobile {
  0%, 10% { height: 100vh; }
}

@media (prefers-reduced-motion: no-preference) {
  body.cs-skin .hero-gallery__main-image img,
  body.cs-skin .hero-gallery__main-image video {
    animation-name: cs-hero-w, cs-hero-h-mobile;
  }

  @media (min-width: 1024px) {
    body.cs-skin .hero-gallery__main-image img,
    body.cs-skin .hero-gallery__main-image video {
      animation-name: cs-hero-w, cs-hero-h-desktop;
    }
  }
}

/* The stock behaviour is the reverse of what we want: it starts at scale(0.75)
   with a 50px radius and grows to full bleed as you scroll. Here it arrives
   full bleed, hard against the logo bar above it, and pulls in as it moves up
   the viewport.

   The keyframes are renamed rather than redefined, because @keyframes do not
   cascade by specificity: redeclaring video-scale would depend on source order
   against new-home.css and would silently break if the load order ever moved. */

body.cs-skin .charle-video {
  background: var(--ink);
  padding: 0;
  margin-top: 0;
}

/* Full width, square, no border at rest. */
body.cs-skin .charle-video__video {
  transform: scale(1);
  border-radius: 0;
  border: 0;
  overflow: hidden;
}

@supports (animation-timeline: scroll()) and (animation-range: 0 100%) {
  body.cs-skin .charle-video__video {
    animation-name: cs-video-inset;
    animation-fill-mode: both;
    animation-timeline: --video-scroll;
    /* Begins once the band is fully in view, finishes as it starts to leave. */
    animation-range: entry 100% exit 0%;
  }
}

@keyframes cs-video-inset {
  0% {
    transform: scale(1);
    border-radius: 0;
  }
  100% {
    transform: scale(0.8);
    border-radius: 40px;
  }
}

/*------------------------------------------------------------------------------
  7. Projects carousel
------------------------------------------------------------------------------*/

body.cs-skin .projects { background-color: var(--paper); }

body.cs-skin .project__title { color: var(--on-paper); }
body.cs-skin .project__type { color: var(--on-paper-muted); }

/* Outline, not a filled disc, and the CSignal cursor rather than a chevron.
   The chevron stays a chevron. The cursor mark is CSignal's own logo form, so
   on a control whose only job is left and right it reads as a brand mark rather
   than as a direction. Drawn at 2.6 rather than the stock 2 so its weight sits
   with the 2px ring around it. */
body.cs-skin .projects__carousel__arrow {
  background: transparent;
  color: #fff;
  border: 2px solid #fff;
  transition: background 0.18s ease-out, color 0.18s ease-out, border-color 0.18s ease-out;
}

body.cs-skin .projects__carousel__arrow svg { display: block; }

body.cs-skin .projects__carousel__arrow:hover {
  background: var(--lime);
  color: var(--ink);
  border-color: var(--lime);
}

/*------------------------------------------------------------------------------
  8. Feature blocks
  The alternating dark service blocks. Ten of them, all on the same classes.
------------------------------------------------------------------------------*/

body.cs-skin .feature { background-color: var(--ink); }

/* The first feature band arrives straight under the paper projects band, so it
   gets the same stepped join the services section has. Third step run on the
   page, deliberately unlike the other two: repeat the same teeth and the page
   reads as a pattern rather than as torn edges. */
body.cs-skin .feature-1 {
  position: relative;
  /* Above .projects, which carries z-index 1 for its own backdrop slab. Left at
     auto this band paints under it and the ink teeth vanish behind the paper. */
  z-index: 2;
  overflow: clip;
  overflow-clip-margin: 60px;
}

body.cs-skin .feature__subheading { color: var(--lime); }
body.cs-skin .feature__heading { color: var(--paper); }
body.cs-skin .feature__description { color: var(--on-ink-muted); }

/* No panel and no hairline. This is a caption sitting under an image on the
   ink ground, not a card, and the ink-2 fill plus the border drew a box around
   the two lines of text. */
body.cs-skin .feature__image_content {
  background: transparent;
  border: 0;
}

body.cs-skin .feature__image_content_heading { color: var(--paper); }
body.cs-skin .feature__image_content_description { color: var(--on-ink-muted); }

body.cs-skin .feature__images img,
body.cs-skin .feature__image img { border-radius: 14px; }

/* style.css fills these #151515 with a 4px radius and no border at all, which
   is why the skin's border-colour rule did nothing: there was no border to
   colour. CSignal has no filled grey chips, so they become what /csignal/ uses
   for a secondary action: a clear pill with a hairline in the text colour. */
body.cs-skin .link-badges a {
  background-color: transparent;
  border: 1px solid rgba(243, 245, 238, 0.32);
  border-radius: 999px;
  padding: 7px 15px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  color: rgba(243, 245, 238, 0.82);
  transition: border-color 0.18s ease-out, color 0.18s ease-out, background 0.18s ease-out;
}
body.cs-skin .link-badges a:hover {
  background-color: transparent;
  border-color: var(--lime);
  color: var(--lime);
}

/*------------------------------------------------------------------------------
  9. People and Partners
------------------------------------------------------------------------------*/

body.cs-skin .people,
/* Paper band. It sits between the ink people band and the paper faqs band, so
   it takes a stepped join at the top only: partners and faqs run together as
   one paper block and a divider between them would be a line drawn across a
   single colour. */
body.cs-skin .partners {
  position: relative;
  z-index: 1;
  background-color: var(--paper);
  overflow: clip;
  overflow-clip-margin: 60px;
}

body.cs-skin .people__subtitle,
body.cs-skin .partners__subtitle {
  color: var(--on-paper);
  font-family: var(--cs-display) !important;
  font-size: clamp(30px, 4vw, 52px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.025em;
  text-transform: none;
}

body.cs-skin .people__title,
body.cs-skin .partners__title { color: rgba(14, 28, 22, 0.5); }

body.cs-skin .people__description,
body.cs-skin .partners__description { color: var(--on-paper-muted); }

/* The partner marks are light artwork, tuned to sit on ink. brightness(1.6)
   pushed them whiter still, which on paper is invisible. brightness(0) knocks
   them to solid ink instead, and hover returns each to its real colour. */
body.cs-skin .partners__logo {
  filter: grayscale(1) brightness(0);
  opacity: 0.62;
  transition: opacity 0.2s ease, filter 0.2s ease;
}

body.cs-skin .partners__logo:hover {
  opacity: 1;
  filter: grayscale(0) brightness(1);
}

body.cs-skin .read-more-btn { color: var(--lime); }

/*------------------------------------------------------------------------------
  10. FAQs and accordion
------------------------------------------------------------------------------*/

body.cs-skin .accordion { border-color: var(--line-on-paper); }

body.cs-skin .accordion__title {
  color: var(--on-paper);
  font-family: var(--cs-display);
}

body.cs-skin .accordion__title:hover { color: var(--lime-dim); }

body.cs-skin .accordion__content__inner { color: var(--on-paper-muted); }

/*------------------------------------------------------------------------------
  11. Buttons
  The stock page uses btn-white on dark and btn-black on light. Under the skin
  the primary action is always lime on ink, which is the CSignal convention.
------------------------------------------------------------------------------*/

body.cs-skin .btn {
  font-family: var(--cs-body);
  font-weight: 700;
  border-radius: 999px;
}

body.cs-skin .btn-white {
  background: var(--lime);
  color: var(--ink);
}

body.cs-skin .btn-white:hover { background: #E2FF3A; }

/* "Explore Our Work" is effectively .cs-btn--ink on /csignal/. Same values. */
body.cs-skin .btn-black {
  display: inline-block;
  width: auto;
  background: var(--ink);
  color: var(--paper);
  font-weight: 700;
  font-size: 15px;
  line-height: normal;
  padding: 13px 24px;
  border-radius: 999px;
}

body.cs-skin .btn-black:hover { background: var(--ink-3); opacity: 1; }

body.cs-skin .btn-arrow svg { transition: transform 0.2s ease; }
body.cs-skin .btn-arrow:hover svg { transform: translate(2px, -2px); }

/*------------------------------------------------------------------------------
  12. Footer
------------------------------------------------------------------------------*/

body.cs-skin .new-footer,
body.cs-skin footer { background-color: var(--ink); }

body.cs-skin .new-footer__nav-link:hover { color: var(--lime); }

/*------------------------------------------------------------------------------
  13. Decoration
  Flat shapes only. No gradients, no blurs, no glows anywhere in this skin:
  CSignal shapes are solid forms with hard edges, and a soft radial glow reads
  as the old brand however it is coloured.

  Both shapes are pointer-events:none so they can never sit between a user and
  a link, and both are hidden on mobile where there is no room for them.
------------------------------------------------------------------------------*/

body.cs-skin .about-charle,
body.cs-skin .people {
  position: relative;
  overflow: hidden;
}

/* Ring, cropped off the right edge. */
/* Solid quarter-round, cropped off the bottom left. */
/* Was a 260px lime circle at opacity 0.07, hung off the bottom at -120px. On
   ink that reads as a murky dark-green dome, and the section clips, so it was
   sliced flat along the bottom. A real brand shape at full strength replaces
   it, sitting entirely inside the section so nothing crops it. See
   .cs-pdeco in the markup. */

@media screen and (max-width: 1024px) {
  body.cs-skin .people::before { display: none; }
}

/*------------------------------------------------------------------------------
  14. Selection and focus
------------------------------------------------------------------------------*/

body.cs-skin ::selection {
  background: var(--lime);
  color: var(--ink);
}

body.cs-skin a:focus-visible,
body.cs-skin button:focus-visible {
  outline: 2px solid var(--lime);
  outline-offset: 3px;
}


/*------------------------------------------------------------------------------
  20. Legal pages: terms and privacy
  ----------------------------------------------------------------------------
  /terms/ and /privacy/ are the same page twice: identical body class
  (terms-page), identical stylesheets (style.css + terms.css), identical
  four-element skeleton. One H1, one <p>. So everything here is written once and
  serves both, and nothing below is keyed to which of the two it is.

  Scoped to .terms-page as well as .cs-skin. terms.css loads on these two pages
  only, so its selectors could not reach anything else anyway, but the extra
  class keeps the intent legible and stops .terms-content ever colliding with a
  future page that reuses the name.

  The seam below is the third on the site and reuses section 19's construction
  exactly: ::before on the LOWER section, filled with the colour of the section
  ABOVE, 34px, clip-path. Only the cut itself is new, because two identical
  cuts would read as a repeat rather than as two tears.
------------------------------------------------------------------------------*/

/* --- Hero -------------------------------------------------------------------
   terms.css paints this pure black and floats two blurred teal-to-purple orbs
   over it at blur(100px). That is the old brand's glassmorphism, the same thing
   switched off on the homepage hero in section 3, and section 13 rules it out
   outright: no gradients, no blurs, no glows. Both orbs are pseudo-elements, so
   they are switched off rather than recoloured and the revert is still just
   removing this stylesheet. */

body.cs-skin.terms-page .terms-hero { background: var(--ink); }

body.cs-skin.terms-page .terms-hero::before,
body.cs-skin.terms-page .terms-hero::after { display: none; }

/* Lifted above the shape layer, as .about-charle > .container is in section 4. */
body.cs-skin.terms-page .terms-hero > .container {
  position: relative;
  z-index: 1;
}

/* Display L in the guidelines' own numbers: Bricolage 800, 0.94, -0.03em. The
   clamp is left alone because it is the page's existing type size and this file
   does not move layout; only weight, leading and tracking come onto the scale.
   800 is not a divergence from the rest of the skin: .cs-h1, the homepage
   display line, is already 800. */
body.cs-skin.terms-page .terms-hero__heading {
  font-family: var(--cs-display);
  font-weight: 800;
  line-height: 0.94;
  letter-spacing: -0.03em;
  color: var(--paper);
}

/* --- Hero decoration --------------------------------------------------------
   Reuses .cs-hero__deco / .cs-deco / .cs-deco__in from csignal-hero.css rather
   than inventing a second parallax layer. Only placement is retuned: the
   positions in that file are measured against the homepage hero, which is
   several times taller than this one.

   The set is the homepage hero's, at legal-page scale: leak in Electric Blue,
   spike in Pulse Coral, ask in Deep Violet, and the signal mark in lime. Four
   shapes, four depths. Lime on the signal mark is the one place the guidelines
   actually ask for #D3F502: it is the logo lime, reserved for the logo, and
   signal is the logo. Sky is the surround colour and never an accent, which is
   what it was doing there.  Coral is the one the frame crops, off the left edge; blue sits clear
   of every edge, because at this size a clipped leak reads as a rendering
   fault rather than as a shape running past the frame.

   No dark ground shape here. On the homepage a #173023 store anchors a hero
   over 800px tall; at a third of that height it just reads as a smudge, which
   is why it is gone rather than shrunk.

   The H1 is centred on this page, so everything sits in the outer thirds and
   nothing crosses the text column. */

body.cs-skin.terms-page .terms-hero .cs-hero__deco {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}

body.cs-skin.terms-page .cs-deco--leak   { top: 34px;   right: 5vw; }
body.cs-skin.terms-page .cs-deco--spike  { bottom: 6px;  left: -46px; }
body.cs-skin.terms-page .cs-deco--ask    { top: 10px;    left: 13vw; }
body.cs-skin.terms-page .cs-deco--signal { top: 46%;     right: 15vw; }

/* csignal-hero.css hides leak, spike and signal below 900px and re-pegs ask to
   the top right, because on the homepage the deck takes that space over. Here
   there is no deck, so the rule is restated rather than inherited: one shape,
   cropped, and nothing else. display has to be set back explicitly, since the
   upstream rule is a display:none this file only outranks by specificity. */
@media screen and (max-width: 1023px) {
  body.cs-skin.terms-page .cs-deco--spike,
  body.cs-skin.terms-page .cs-deco--ask,
  body.cs-skin.terms-page .cs-deco--signal { display: none; }

  body.cs-skin.terms-page .cs-deco--leak { display: block; top: 16px; right: 14px; }
  body.cs-skin.terms-page .cs-deco--leak svg { height: 84px; }
}

/* --- The seam ---------------------------------------------------------------
   terms.css joins the ink hero to the light content block with a 30px lip
   (50px at desktop) pulled up over the hero by a negative margin. That lip is
   the exact default the guidelines name as the thing to resist: "Every layout
   wants to be a stack of 24px rounded cards... The stepped edge is the one
   deliberate act of resistance in the system."

   So the radius goes and the seam takes its place. A legal page has exactly one
   section transition, which is a comfortable budget for a device the guidelines
   cap at twice per screen.

   Steps are 11% to 17% wide across five depths, per section 19. The cut is a
   different one from either seam on the work page. */

body.cs-skin.terms-page .terms-content {
  background: var(--paper);
  border-radius: 0;
  margin-top: 0;
  position: relative;
}

body.cs-skin.terms-page .terms-content::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 34px;
  pointer-events: none;
  z-index: 1;
  background: var(--ink);
  clip-path: polygon(
    0 0, 100% 0,
    100% 37%, 84% 37%, 84% 91%, 73% 91%, 73% 24%,
    57% 24%, 57% 70%, 45% 70%, 45% 37%, 28% 37%,
    28% 91%, 15% 91%, 15% 58%, 0 58%
  );
}

/* --- Long-form copy ---------------------------------------------------------
   Body on the guidelines' scale: Hanken 400, 1.55. terms.css sets pure black on
   pure white, which is the one contrast pairing the palette does not contain.
   Ink on paper instead. */

body.cs-skin.terms-page .terms-content__inner p {
  color: var(--on-paper);
  line-height: 1.55;
}

body.cs-skin.terms-page .terms-content__inner strong {
  font-weight: 700;
  color: var(--ink);
}

/* Links. Lime as a text colour on paper is close to invisible, which section 4
   already found. The link stays ink and the lime does the work underneath it,
   then fills on hover: the same figure-ground flip as .cs-hl, at inline scale. */
body.cs-skin.terms-page .terms-content__inner a {
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
  box-shadow: inset 0 -2px 0 var(--lime);
  transition: background 0.12s ease-out, box-shadow 0.12s ease-out;
}

body.cs-skin.terms-page .terms-content__inner a:hover {
  background: var(--lime);
  box-shadow: inset 0 -0.35em 0 var(--lime), 0 0 0 3px var(--lime);
}

/* The two ink cards want the artwork as it ships: white, at full strength.
   At 0.75 it read as grey against the dark green rather than white. */
body.cs-skin .sv6__cell--2 .sv6__cell-badge img,
body.cs-skin .sv6__cell--5 .sv6__cell-badge img,
body.cs-skin .sv6__cell--6 .sv6__cell-badge img { filter: none; opacity: 1; }

/* --- Graphic position ------------------------------------------------------
   .sv6__cell is a flex column with justify-content: flex-end, so every card
   anchors its contents to the bottom and all the spare height collects above
   the first child. On the two cards with a graphic that put roughly 60px of
   dead space over the panel against 19px under it.

   Auto margins were the wrong tool: they fight flex-end rather than remove it.
   Switching just those two cards to flex-start drops the graphic to the top of
   the padding box, so the gap above it is the card's own 1.8rem padding and the
   gap below is the graphic's 1.2rem bottom margin. Near enough equal, and the
   slack moves to the foot of the card where it is not read as a gap. */

body.cs-skin .sv6__cell--1,
body.cs-skin .sv6__cell--7,
body.cs-skin .sv6__cell--4 { justify-content: flex-start; }

body.cs-skin .sv6__cell--1 .sv6__cell-number,
body.cs-skin .sv6__cell--7 .sv6__cell-number,
body.cs-skin .sv6__cell--4 .sv6__cell-number { margin-bottom: 0; }

/* The text block follows the graphic rather than being pushed to the foot of
   the card. margin-top:auto was holding it down there, which reopened under the
   graphic the same gap flex-start had just closed above it. The slack now
   collects at the bottom of the card instead, where there is nothing to read
   it against. */
body.cs-skin .sv6__cell--1 .sv6__cell-badge,
body.cs-skin .sv6__cell--7 .sv6__cell-badge,
body.cs-skin .sv6__cell--4 .sv6__cell-badge { margin-top: 0; }


/* ---------------------------------------------------------------------------
   CSIGNAL HINT BADGES
   ---------------------------------------------------------------------------
   Same lockup as the About kicker, in a second colourway, so the page carries
   a family of small CSignal hints rather than one badge saying everything.
   One beat per section: About takes the promise, Services takes the method.

   Built as a modifier on .cs-kicker rather than a new component, so the two
   stay in step if the lockup is ever retuned.
------------------------------------------------------------------------------*/
body.cs-skin .cs-kicker-row {
  display: flex;
  flex: 0 0 auto;
  justify-content: flex-end;
  margin: 0;
  padding-bottom: 0.35rem;
}

/* Pivots off its own right edge, so the tilt never pushes it past the grid. */
body.cs-skin .cs-kicker-hit--sv6 { position: relative; }

/* Bursting off the badge's top-left corner. Anchored to the anchor rather than
   to the section, so it stays on the corner however the row reflows. It is a
   sibling of the rotated .cs-kicker, so the badge tilt does not carry into it. */
body.cs-skin .cs-kicker__spark {
  position: absolute;
  top: -50px;
  left: -44px;
  line-height: 0;
  pointer-events: none;
  transform: rotate(-18deg);
  z-index: 1;
}

body.cs-skin .cs-kicker-hit--sv6 .cs-kicker {
  transform: rotate(2.6deg);
  transform-origin: 100% 50%;
  margin: 0;
  text-align: right;
}

body.cs-skin .cs-kicker-hit--sv6:hover .cs-kicker { transform: rotate(2.6deg); }

/* Blue colourway. The white ring is what makes the lockup read as one family,
   so it stays; only the ground, the text and the mark change. */
body.cs-skin .cs-kicker--blue {
  background: var(--blue, #2F6BFF);
  color: #fff;
}

body.cs-skin .cs-kicker--blue em { color: var(--lime, #D3F502); }

@media screen and (max-width: 900px) {
  /* Still flex, not block: the badge moves ABOVE the heading here, and order is
     the only way to do that without a second copy of it in the markup. Column
     direction so the two stack. */
  body.cs-skin .sv6__mobile-heading {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  body.cs-skin .cs-kicker-row {
    order: -1;
    justify-content: flex-end;
    margin: 0 0 1.5rem;
    padding-bottom: 0;
  }

  /* Tilted the other way from desktop, and still pivoting off the edge it is
     aligned to so the tilt cannot push it past the gutter. */
  body.cs-skin .cs-kicker-hit--sv6 .cs-kicker {
    transform: rotate(-2.6deg);
    transform-origin: 100% 50%;
    text-align: right;
  }
  body.cs-skin .cs-kicker-hit--sv6:hover .cs-kicker { transform: rotate(-2.6deg); }
}


/*==============================================================================
  UI / UX DESIGN graphic: an artboard out for review
  ----------------------------------------------------------------------------
  The stock graphic was a browser window full of grey bars, which is the one
  picture every agency site already has and the one an image generator reaches
  for first. This is deliberately not that: no chrome, no page, just a cropped
  frame from a design file with the review happening on top of it.

  It borrows the card language from the SEO & GEO pair (white, 12px radius, soft
  shadow) so the two read as the same family, and the comment / avatar / chip
  furniture from "Delivery, out in the open" on /csignal/.

  One 12s loop, four beats: the frame sits at v2, a comment lands on the CTA,
  the CTA answers it and the version ticks to v3, Approved drops in.

  Everything is sized in px rather than container units. The SEO cards needed
  container-type: size and paid for it with a zero-height failure; nothing here
  queries its own box, so there is no reason to take that on.
==============================================================================*/

body.cs-skin .sv6__graphic.cs-dsn {
  display: block;
  width: 100%;
  opacity: 1;
}

body.cs-skin .cs-dsn__card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: clamp(150px, 17vw, 215px);
  padding: 14px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 6px 18px rgba(14, 28, 22, 0.08);
}

body.cs-skin .cs-dsn__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex: 0 0 auto;
}

body.cs-skin .cs-dsn__file {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: rgba(14, 28, 22, 0.45);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The two version labels are stacked in the same box and cross-faded, so the
   chip never changes width mid-loop. */
body.cs-skin .cs-dsn__ver {
  position: relative;
  flex: 0 0 auto;
  width: 26px;
  height: 16px;
}

body.cs-skin .cs-dsn__ver em {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  background: rgba(14, 28, 22, 0.06);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace !important;
  font-size: 9px;
  font-style: normal;
  font-weight: 600;
  color: rgba(14, 28, 22, 0.55);
}

body.cs-skin .cs-dsn__v2 { animation: cs-dsn-v2 12s ease-in-out infinite; }

body.cs-skin .cs-dsn__v3 {
  background: var(--lime);
  color: var(--ink);
  animation: cs-dsn-v3 12s ease-in-out infinite;
}

/* The artboard. Flat blocks, not wireframe outlines: a design file shows solid
   shapes, and hairline strokes are what make a graphic read as a wireframe. */
body.cs-skin .cs-dsn__art {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: stretch;
  gap: 12px;
  padding: 12px;
  border-radius: 8px;
  background: rgba(14, 28, 22, 0.035);
}

body.cs-skin .cs-dsn__col {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 7px;
}

body.cs-skin .cs-dsn__h {
  height: 9px;
  width: 76%;
  border-radius: 3px;
  background: rgba(14, 28, 22, 0.78);
}

body.cs-skin .cs-dsn__t {
  height: 5px;
  width: 88%;
  border-radius: 3px;
  background: rgba(14, 28, 22, 0.2);
}

body.cs-skin .cs-dsn__t--s { width: 60%; }

body.cs-skin .cs-dsn__btn {
  height: 16px;
  width: 52px;
  margin-top: 3px;
  border-radius: 999px;
  background: rgba(14, 28, 22, 0.18);
  animation: cs-dsn-btn 12s cubic-bezier(.2,.9,.2,1) infinite;
}

body.cs-skin .cs-dsn__img {
  flex: 0 0 34%;
  border-radius: 6px;
  background: rgba(14, 28, 22, 0.1);
}

/* The comment, pinned to the thing it is about. */
body.cs-skin .cs-dsn__pin {
  position: absolute;
  left: 58px;
  bottom: 14px;
  width: 17px;
  height: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px 999px 999px 2px;
  background: var(--coral, #FF5A2C);
  box-shadow: 0 0 0 2px #fff;
  font-size: 9px;
  font-weight: 700;
  color: #fff;
  animation: cs-dsn-pin 12s cubic-bezier(.2,.9,.2,1) infinite;
}

body.cs-skin .cs-dsn__note {
  position: absolute;
  left: 12px;
  bottom: 36px;
  right: 38%;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 8px 5px 5px;
  border-radius: 7px;
  background: #fff;
  box-shadow: 0 4px 14px rgba(14, 28, 22, 0.14);
  animation: cs-dsn-note 12s cubic-bezier(.2,.9,.2,1) infinite;
}

body.cs-skin .cs-dsn__who {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--ink);
  font-size: 8px;
  font-weight: 700;
  color: var(--lime);
}

body.cs-skin .cs-dsn__note i {
  font-style: normal;
  font-size: 9.5px;
  font-weight: 500;
  line-height: 1.1;
  color: rgba(14, 28, 22, 0.72);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

body.cs-skin .cs-dsn__chip {
  position: absolute;
  top: 10px;
  right: 10px;
  padding: 4px 9px;
  border-radius: 999px;
  background: var(--lime);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--ink);
  white-space: nowrap;
  animation: cs-dsn-chip 12s cubic-bezier(.2,.9,.2,1) infinite;
}

@keyframes cs-dsn-pin {
  0%, 6%    { opacity: 0; transform: scale(0.4); }
  12%, 46%  { opacity: 1; transform: scale(1); }
  54%, 100% { opacity: 0; transform: scale(0.4); }
}

@keyframes cs-dsn-note {
  0%, 10%   { opacity: 0; transform: translateY(6px); }
  19%, 44%  { opacity: 1; transform: none; }
  52%, 100% { opacity: 0; transform: translateY(6px); }
}

@keyframes cs-dsn-btn {
  0%, 34%   { width: 52px; background: rgba(14, 28, 22, 0.18); }
  43%, 86%  { width: 72px; background: var(--lime); }
  94%, 100% { width: 52px; background: rgba(14, 28, 22, 0.18); }
}

@keyframes cs-dsn-v2 {
  0%, 34%   { opacity: 1; }
  41%, 90%  { opacity: 0; }
  96%, 100% { opacity: 1; }
}

@keyframes cs-dsn-v3 {
  0%, 34%   { opacity: 0; }
  41%, 90%  { opacity: 1; }
  96%, 100% { opacity: 0; }
}

@keyframes cs-dsn-chip {
  0%, 56%   { opacity: 0; transform: translateY(5px) scale(0.9); }
  64%, 86%  { opacity: 1; transform: none; }
  93%, 100% { opacity: 0; transform: translateY(5px) scale(0.9); }
}

/* Reduced motion gets the end of the story rather than the middle of it. */
@media (prefers-reduced-motion: reduce) {
  body.cs-skin .cs-dsn__pin,
  body.cs-skin .cs-dsn__note,
  body.cs-skin .cs-dsn__btn,
  body.cs-skin .cs-dsn__v2,
  body.cs-skin .cs-dsn__v3,
  body.cs-skin .cs-dsn__chip { animation: none; }

  body.cs-skin .cs-dsn__pin,
  body.cs-skin .cs-dsn__note,
  body.cs-skin .cs-dsn__v2 { opacity: 0; }

  body.cs-skin .cs-dsn__btn { width: 72px; background: var(--lime); }
}

@media screen and (max-width: 760px) {
  body.cs-skin .cs-dsn__note { right: 24%; }
  body.cs-skin .cs-dsn__note i { font-size: 9px; }
}


/*==============================================================================
  EMAIL & SMS graphic: the lifecycle flow, and what it returned
  ----------------------------------------------------------------------------
  The stock graphic was four dark email mockups in muted pastels, which is the
  old palette and says only "we send emails". This keeps the four stages, which
  are the actual product, and adds the half that is Charle's argument: the
  revenue the flow is attributing, stepping as each stage fires.

  Same white card as the SEO and Design graphics, so all three read as one
  family. One 12s loop, 3s per stage, driven entirely by the inline
  animation-delay on each step, so adding a fifth stage is a markup change.
==============================================================================*/

/* No width here on purpose. Cell 8 is a two-column card and its own rule sets
   flex: 0 0 55% on the graphic; a width from this sheet outranks that. */
body.cs-skin .sv6__graphic.cs-flow {
  display: block;
  opacity: 1;
}

body.cs-skin .cs-flow__card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: clamp(150px, 14vw, 190px);
  padding: 14px;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 6px 18px rgba(14, 28, 22, 0.08);
}

body.cs-skin .cs-flow__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex: 0 0 auto;
}

body.cs-skin .cs-flow__lbl {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: rgba(14, 28, 22, 0.45);
  white-space: nowrap;
}

body.cs-skin .cs-flow__rev {
  display: flex;
  align-items: baseline;
  gap: 7px;
  flex: 0 0 auto;
}

body.cs-skin .cs-flow__rev em {
  font-style: normal;
  font-size: 9px;
  font-weight: 500;
  color: rgba(14, 28, 22, 0.4);
  white-space: nowrap;
}

/* The four figures are stacked in one box and cross-faded, so the row never
   reflows as the number grows. Width is fixed to the widest of them. */
body.cs-skin .cs-flow__fig {
  position: relative;
  display: block;
  width: 54px;
  height: 14px;
}

body.cs-skin .cs-flow__fig b {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  font-family: var(--cs-mono) !important;
  font-size: 12px;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
  animation: cs-flow-fig 12s ease-in-out infinite;
}

body.cs-skin .cs-flow__row {
  display: flex;
  align-items: stretch;
  gap: 10px;
  flex: 1 1 auto;
  min-height: 0;
}

body.cs-skin .cs-flow__step {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  padding: 9px;
  border-radius: 8px;
  background: rgba(14, 28, 22, 0.035);
  animation: cs-flow-step 12s cubic-bezier(.2,.9,.2,1) infinite;
}

/* The connector lives in the gap rather than as its own element. */
body.cs-skin .cs-flow__step + .cs-flow__step::before {
  content: "";
  position: absolute;
  right: 100%;
  top: 50%;
  width: 10px;
  height: 1px;
  background: rgba(14, 28, 22, 0.16);
}

body.cs-skin .cs-flow__chip {
  align-self: flex-start;
  max-width: 100%;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.01em;
  line-height: 1.4;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Lime is the one stage colour dark enough text has to sit on it. */
body.cs-skin .cs-flow__chip--dark { color: var(--ink); }

body.cs-skin .cs-flow__h {
  height: 6px;
  width: 78%;
  border-radius: 3px;
  background: rgba(14, 28, 22, 0.72);
}

body.cs-skin .cs-flow__t {
  height: 4px;
  width: 92%;
  border-radius: 3px;
  background: rgba(14, 28, 22, 0.18);
}

body.cs-skin .cs-flow__t--s { width: 62%; }

body.cs-skin .cs-flow__btn {
  height: 11px;
  width: 36px;
  margin-top: 2px;
  border-radius: 999px;
  background: rgba(14, 28, 22, 0.22);
}

/* 19% of 12s is 2.3s lit, then it sits back. The delays (0, -9, -6, -3) put the
   four windows 3s apart, left to right. */
@keyframes cs-flow-step {
  0%, 19%   {
    opacity: 1;
    transform: translateY(-3px);
    background: #fff;
    box-shadow: 0 0 0 2px var(--lime), 0 8px 18px rgba(14, 28, 22, 0.14);
  }
  27%, 100% {
    opacity: 0.5;
    transform: none;
    background: rgba(14, 28, 22, 0.035);
    box-shadow: 0 0 0 1px rgba(14, 28, 22, 0.07);
  }
}

@keyframes cs-flow-fig {
  0%, 22%   { opacity: 1; }
  30%, 100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  body.cs-skin .cs-flow__step,
  body.cs-skin .cs-flow__fig b { animation: none; }
  body.cs-skin .cs-flow__fig b { opacity: 0; }
  body.cs-skin .cs-flow__fig b:last-child { opacity: 1; }
}

@media screen and (max-width: 900px) {
  body.cs-skin .cs-flow__rev em { display: none; }
  body.cs-skin .cs-flow__chip { font-size: 8px; padding: 2px 5px; }
  body.cs-skin .cs-flow__step { padding: 7px; }
}


/*==============================================================================
  SHAPES IN THE SERVICE CARDS
  ----------------------------------------------------------------------------
  Four brand shapes cropped by the cards that hold them, so each reads as a
  shape passing behind the card rather than an icon placed on it. The cards
  already carry overflow:hidden, which is what does the cropping; nothing here
  needs a mask.

  Placed on the four text-only cards only. The four that carry a graphic have
  enough going on, and a shape behind a white card would just be a stripe.

  Colour is chosen against the ground, not the service: blue and purple on the
  ink cards, ink and coral on the lime ones. Full strength, no opacity, because
  a faded brand colour is a different colour.
==============================================================================*/

body.cs-skin .cs-cshape {
  position: absolute;
  z-index: 0;
  line-height: 0;
  pointer-events: none;
}

body.cs-skin .cs-cshape svg { display: block; }

/* 02 New Stores, ink. Store shape leaving the bottom right corner. */
body.cs-skin .cs-cshape--2 {
  right: -58px;
  bottom: -70px;
  transform: rotate(14deg);
}

/* 03 Shopify Migrations, lime. A route running off the top right. */
body.cs-skin .cs-cshape--3 {
  right: -52px;
  top: -58px;
  transform: rotate(-10deg);
}

/* 05 Theme Development, ink. Staircase climbing out of the top right. */
body.cs-skin .cs-cshape--5 {
  right: -46px;
  top: -62px;
  transform: rotate(8deg);
}

/* 06 Support & Maintenance, lime. Tick leaving the right edge. Blue, not
   coral: coral and lime sit too close in value and the shape goes muddy.
   Blue is the only accent that holds its edge against lime. */
body.cs-skin .cs-cshape--6 {
  right: -44px;
  bottom: -48px;
  transform: rotate(16deg);
}

/* 07 UI / UX Design, paper. Rising out of the bottom edge, right of centre, so
   it clears the copy on the left and the graphic card above it. */
body.cs-skin .cs-cshape--7 {
  left: 52%;
  bottom: -62px;
  transform: rotate(-12deg);
}

/* The text has to win. .sv6__cell-name and friends already carry z-index 1, but
   the badge image and the number are worth stating so a future shape cannot
   drift over them. */
body.cs-skin .sv6__cell-badge,
body.cs-skin .sv6__cell-number,
body.cs-skin .sv6__cell-name,
body.cs-skin .sv6__cell-desc { position: relative; z-index: 1; }

/* Kept on at narrow widths, scaled back. The cards go full width when the grid
   stacks, so there is more room for a shape than the desktop layout has, not
   less; what does not survive is the size, which is why they are scaled from
   the corner they hang off rather than hidden. */
@media screen and (max-width: 900px) {
  body.cs-skin .cs-cshape { transform-origin: center; }
  body.cs-skin .cs-cshape--2 { transform: rotate(14deg)  scale(0.62); }
  body.cs-skin .cs-cshape--3 { transform: rotate(-10deg) scale(0.62); }
  body.cs-skin .cs-cshape--5 { transform: rotate(8deg)   scale(0.62); }
  body.cs-skin .cs-cshape--6 { transform: rotate(16deg)  scale(0.62); }
  body.cs-skin .cs-cshape--7 { transform: rotate(-12deg) scale(0.62); }
}


/* A small purple ask beside the Services heading. Inside the h2 so it tracks
   the word rather than a fixed offset, aria-hidden so it adds nothing to the
   heading text, and the heading string is untouched. */
body.cs-skin .cs-hshape {
  display: inline-block;
  line-height: 0;
  margin-left: 0.32em;
  vertical-align: 0.12em;
  transform: rotate(-9deg);
}

body.cs-skin .cs-hshape svg {
  display: block;
  height: clamp(20px, 2.2vw, 32px);
  width: auto;
}


/* A shape that pokes out ABOVE a card cannot live inside it: the cards carry
   overflow:hidden, which is exactly what crops the .cs-cshape set. So this one
   is its own grid item, placed on the same track as the card it belongs to and
   painted underneath it.

   z-index 0 rather than -1. The cards are position:relative with z-index auto,
   so they and this sit in the same paint group, ordered by z-index and then by
   DOM order; first in the grid at z-index 0 puts it under every card. A
   negative z-index would drop it behind .sv6's own background instead. */
body.cs-skin .cs-gshape {
  position: relative;
  z-index: 0;
  pointer-events: none;
  line-height: 0;
}

body.cs-skin .cs-gshape svg {
  position: absolute;
  display: block;
}

/* 02 New Stores. */
body.cs-skin .cs-gshape--2 {
  grid-column: 6 / 10;
  grid-row: 1 / 2;
}

body.cs-skin .cs-gshape--2 svg {
  top: -44px;
  left: 24%;
  transform: rotate(-14deg);
}

@media screen and (max-width: 900px) {
  body.cs-skin .cs-gshape { display: none; }
}


/* Two small marks in the empty run to the left of the product logo row. The row
   is justify-content:center and position:relative already, so they are pinned
   to its left edge rather than added as flex children, which would have pushed
   the five logos off centre. */
body.cs-skin .cs-pshape {
  position: absolute;
  line-height: 0;
  pointer-events: none;
}

body.cs-skin .cs-pshape svg { display: block; }

/* Scattered rather than paired: different sizes, different angles, and offset
   on both axes, so they read as two marks that happen to be near each other. */
body.cs-skin .cs-pshape--a {
  left: 0;
  top: 50%;
  transform: translateY(-88%) rotate(-27deg);
}

body.cs-skin .cs-pshape--b {
  left: 74px;
  top: 50%;
  transform: translateY(14px) rotate(41deg);
}

/* Below the point where the logos start wrapping there is no empty run left to
   put them in. */
@media screen and (max-width: 1100px) {
  body.cs-skin .cs-pshape { display: none; }
}


/* One coral spark among the projects heading. Inside the h2 so it travels with
   the text block at every width rather than being pinned to the container,
   which on a centred heading would drift away from the words as the line
   length changes. */
body.cs-skin .projects__heading { position: relative; }

body.cs-skin .cs-hdeco {
  position: absolute;
  top: -0.42em;
  right: 7%;
  line-height: 0;
  pointer-events: none;
  transform: rotate(52deg);
}

body.cs-skin .cs-hdeco svg { display: block; }

@media screen and (max-width: 900px) {
  body.cs-skin .cs-hdeco { right: 2%; top: -0.6em; }
  body.cs-skin .cs-hdeco svg { height: 32px; width: auto; }
}


/*==============================================================================
  SHAPES ACROSS THE FEATURE BANDS
  ----------------------------------------------------------------------------
  One shape per band, sitting BEHIND the image stack and the copy column, so
  where a shape meets an image it disappears under it and only the part past the
  edge shows. That is what makes them read as scattered rather than placed.

  Positions, shapes, colours and sizes are all deliberately unpatterned: no
  shape or colour repeats back to back, sides alternate irregularly rather than
  strictly, and half sit against the images while half sit by a heading. A
  regular rhythm here would read as a border treatment.
==============================================================================*/

body.cs-skin .feature__inner { position: relative; }

/* The content has to sit over them, or a shape lands on top of a paragraph. */
/* The copy column sits above everything. The image column does NOT: at z-index
   1 with the shapes at 0, any shape whose position happened to land over an
   image was hidden completely rather than poking out of it, which is why only
   the two on open ground were showing. The shapes now sit over the images and
   under the text. */
body.cs-skin .feature__images { position: relative; z-index: 1; }

body.cs-skin .feature__content { position: relative; z-index: 3; }

body.cs-skin .cs-fdeco {
  position: absolute;
  z-index: 2;
  line-height: 0;
  pointer-events: none;
}

body.cs-skin .cs-fdeco svg { display: block; }

body.cs-skin .cs-fdeco--1  { left: -22px;  top: 16%;    transform: rotate(-18deg); }
body.cs-skin .cs-fdeco--2  { right: 3%;    top: -20px;  transform: rotate(24deg); }
body.cs-skin .cs-fdeco--3  { left: 44%;    bottom: -14px; transform: rotate(-8deg); }
body.cs-skin .cs-fdeco--4  { right: -26px; top: 34%;    transform: rotate(12deg); }
body.cs-skin .cs-fdeco--5  { left: 6%;     top: -24px;  transform: rotate(-32deg); }
body.cs-skin .cs-fdeco--6  { right: 38%;   bottom: 4%;  transform: rotate(16deg); }
body.cs-skin .cs-fdeco--7  { left: -20px;  bottom: 20%; transform: rotate(-46deg); }
body.cs-skin .cs-fdeco--8  { right: 7%;    top: 9%;     transform: rotate(28deg); }
body.cs-skin .cs-fdeco--9  { left: 36%;    top: -18px;  transform: rotate(-14deg); }
body.cs-skin .cs-fdeco--10 { right: -18px; bottom: 12%; transform: rotate(20deg); }

/* Second shape on six of the ten, so the scatter is uneven down the page
   rather than one-per-band all the way. */
body.cs-skin .cs-fdeco--11 { right: 18%;   bottom: -16px; transform: rotate(34deg); }
body.cs-skin .cs-fdeco--12 { left: 2%;     bottom: 14%;   transform: rotate(-26deg); }
body.cs-skin .cs-fdeco--13 { left: 30%;    top: -14px;    transform: rotate(18deg); }
body.cs-skin .cs-fdeco--14 { right: -14px; top: 8%;       transform: rotate(-38deg); }
body.cs-skin .cs-fdeco--15 { left: 12%;    bottom: -12px; transform: rotate(22deg); }
body.cs-skin .cs-fdeco--16 { right: 26%;   top: -16px;    transform: rotate(-20deg); }

/* Stacked, the two columns fill the width and there is no margin for a shape to
   sit in; it just lands on the copy. */
@media screen and (max-width: 1023px) {
  body.cs-skin .cs-fdeco { display: none; }
}


/* Large blue leak in the left margin of the people band. Behind the container,
   at full strength, and positioned off the bottom edge rather than through it
   so the section's clipping never touches it. */
body.cs-skin .people { position: relative; }

body.cs-skin .people > .container { position: relative; z-index: 1; }

/* Stated outright. This band is ink and must stay ink whatever the sections
   either side of it are painted. */
body.cs-skin .people { background-color: var(--ink); }

/* The eyebrow lands ON the photograph, where the stock ink colour disappeared
   into the dark half of the image. White. The heading below it is untouched. */
body.cs-skin .people__subtitle {
  color: var(--paper) !important;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

body.cs-skin .people__description { color: var(--paper); }

body.cs-skin .cs-pdeco {
  position: absolute;
  left: -8px;
  bottom: -22px;
  z-index: 0;
  line-height: 0;
  pointer-events: none;
  transform: rotate(-10deg);
}

body.cs-skin .cs-pdeco svg { display: block; }

/* Under this width the container fills the band and there is no margin to sit
   in, so it would land behind the copy. */
@media screen and (max-width: 1279px) {
  body.cs-skin .cs-pdeco { display: none; }
}


/*==============================================================================
  PAGE BUTTONS
  ----------------------------------------------------------------------------
  CSIGNAL BUTTON SPEC. Every .btn on the page is set to the same figures
  /csignal/ uses for .cs-btn, so the CTAs stop varying in size and padding from
  section to section: 15px/700, 13px 24px, fully rounded.

  The arrow icons are gone from the markup, and .btn-arrow with them, or
  style.css keeps reserving 3rem of right padding for an arrow that is no longer
  there and every button sits visibly off-centre in its own pill.

  Colours are deliberately untouched. Each modifier keeps whatever ground it
  already had.
==============================================================================*/

body.cs-skin .btn {
  display: inline-block;
  width: auto;
  font-family: var(--cs-body) !important;
  font-size: 15px;
  font-weight: 700;
  /* /csignal/ .cs-btn declares no line-height and inherits the browser normal.
     style.css pins 1.2, which makes the pill a few px shorter than the landing
     page's. */
  line-height: normal;
  padding: 13px 24px;
  border-radius: 999px;
  white-space: nowrap;
  text-align: center;
  transition: background 0.12s ease-out, border-color 0.12s ease-out, color 0.12s ease-out;
}

/* .btn:hover fades the whole button to 0.8 opacity. CSignal shifts the colour
   instead and never dims. */
body.cs-skin .btn:hover { opacity: 1; }


/* People-first agency: paper heading with the first half on the lime highlight
   block. Heading text is never set in lime; lime is a ground the ink sits on,
   which is how every accented heading on /csignal/ is built. */
body.cs-skin .people__title { color: var(--paper); }


/*==============================================================================
  EXPERTS: the shape field
  ----------------------------------------------------------------------------
  Twelve brand shapes scattered through the band the four photographs sit in,
  each drifting on its own clock so the field never pulses in unison, which is
  what makes a float loop read as an animation rather than as movement.

  Rotation is held in --r and applied INSIDE the keyframes. A transform on the
  element and a transform in its animation do not compose; the animation wins
  outright and every shape would snap square the moment it started.

  The shapes sit over the photographs and under the copy: over, so the field
  reads as one layer across the whole band rather than as two; under, because
  nothing may land on the heading.
==============================================================================*/

body.cs-skin .experts { position: relative; }

body.cs-skin .experts > .container { position: relative; z-index: 3; }

body.cs-skin .experts__media { z-index: 1; }

body.cs-skin .cs-xp {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

body.cs-skin .cs-xp__s {
  position: absolute;
  line-height: 0;
  transform: rotate(var(--r, 0deg));
  animation: cs-xp-float var(--dur, 9s) ease-in-out infinite;
  animation-delay: var(--del, 0s);
}

body.cs-skin .cs-xp__s svg { display: block; }

@keyframes cs-xp-float {
  0%, 100% { transform: translateY(0)     rotate(var(--r, 0deg)); }
  50%      { transform: translateY(-19px) rotate(calc(var(--r, 0deg) + 5deg)); }
}

/* The heading is the point of the section; at narrow widths the shapes have
   nowhere to go but on top of it. */
@media screen and (max-width: 1023px) {
  body.cs-skin .cs-xp__s { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  body.cs-skin .cs-xp__s { animation: none; }
}

/* The eyebrow takes the lime block, not lime type: lime is a ground the ink
   sits on. It also gives the label something to sit on, which it needed anyway
   since it lands over the top photograph. inline-block so the block hugs the
   words rather than running the width of the centred column. */
body.cs-skin .experts__subtitle {
  position: relative;
  z-index: 1;
  display: inline-block;
  padding: 0.3em 14px 0.36em;
  border-radius: 10px;
  background: var(--lime);
  color: var(--ink);
  font-weight: 700;
  line-height: 1.1;
}


/* The read-more control is a bare <button>, so it inherits nothing useful. */
body.cs-skin .partners .read-more-btn {
  color: var(--on-paper);
  text-decoration-color: rgba(14, 28, 22, 0.4);
}

body.cs-skin .partners .read-more-btn:hover { color: var(--ink); }

/* Taupe slab, mirroring the one behind the About band. Right-hand side here, so
   it sits under the logo grid rather than under the copy, and flush at top:0
   for the same reason as the projects one: .cs-secdeco clips at inset:0 and a
   negative top would show as a cut. */
/* .cs-secdeco is z-index 0 inside the section; the content has to clear it. */
body.cs-skin .partners > .container { position: relative; z-index: 1; }

body.cs-skin .cs-sdeco--slab-p {
  top: 0;
  right: -170px;
  transform: scaleX(-1);
}


/*==============================================================================
  CHARLE OBSERVATORY sign-up
  ----------------------------------------------------------------------------
  podcast.php ships its own stylesheet inline, built on the old brand: #080808,
  two radial green glows, Season Serif italic at 55% opacity, a frosted
  translucent card and a white button. Every one of those is a thing the CSignal
  palette rules out, so this is a full repaint rather than a few overrides.

  The include is untouched: it is shared, and everything here is reachable from
  its existing classes.
==============================================================================*/

body.cs-skin .obs-cta {
  position: relative;
  z-index: 1;
  background: var(--paper);
  /* Both stepped joins sit outside this section's box, and .section clips. */
  overflow: clip;
  overflow-clip-margin: 60px;
}

body.cs-skin .obs-cta__inner { position: relative; z-index: 2; }

/* No glows. Flat colour only. */
body.cs-skin .obs-cta::before,
body.cs-skin .obs-cta::after,
body.cs-skin .obs-cta__card::before { display: none; }

body.cs-skin .obs-cta__eyebrow {
  font-family: var(--cs-mono) !important;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  color: rgba(14, 28, 22, 0.5);
}

body.cs-skin .obs-cta__h2 {
  font-family: var(--cs-display) !important;
  font-weight: 800;
  font-size: clamp(32px, 4vw, 56px);
  line-height: 1.04;
  letter-spacing: -0.03em;
  color: var(--on-paper);
}

/* "Observatory." was Season Serif italic at 55% opacity, which on this ground
   read as the heading fading out. It takes the lime block instead: the accent
   is a ground the ink sits on, never a type colour. */
body.cs-skin .obs-cta__h2 em {
  font-family: var(--cs-display) !important;
  font-style: normal;
  font-weight: 800;
  opacity: 1;
  display: inline-block;
  padding: 0.06em 12px 0.12em;
  border-radius: 10px;
  background: var(--lime);
  color: var(--ink);
}

body.cs-skin .obs-cta__desc {
  font-family: var(--cs-body) !important;
  font-size: clamp(14px, 1.3vw, 16px);
  color: var(--on-paper-muted);
}

body.cs-skin .obs-cta__stats,
body.cs-skin .obs-cta__stat { border-color: var(--line-on-paper); }

body.cs-skin .obs-cta__stat-num {
  font-family: var(--cs-display) !important;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--on-paper);
}

body.cs-skin .obs-cta__stat-lbl {
  font-family: var(--cs-mono) !important;
  font-size: 10px;
  letter-spacing: 0.12em;
  color: rgba(14, 28, 22, 0.45);
}

/* The card stays ink on the paper band rather than becoming a second shade of
   paper. A form is the one thing in this section you are meant to act on, and
   an ink block on paper is the strongest way /csignal/ says so. */
body.cs-skin .obs-cta__card {
  background: var(--ink);
  border: 0;
  border-radius: 18px;
}

body.cs-skin .obs-cta__card-label {
  font-family: var(--cs-mono) !important;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--on-ink-muted);
}

/* Pill field and pill button, so the form speaks the same shape language as
   every other control on the page. */
body.cs-skin .obs-cta__input {
  background: var(--ink-2);
  border: 1px solid var(--line-on-ink);
  border-radius: 999px;
  padding: 14px 20px;
  font-family: var(--cs-body) !important;
  font-size: 15px;
  color: var(--paper);
}

body.cs-skin .obs-cta__input::placeholder { color: rgba(243, 245, 238, 0.45); }

body.cs-skin .obs-cta__input:focus {
  background: var(--ink);
  border-color: var(--lime);
}

body.cs-skin .obs-cta__btn {
  background: var(--lime);
  color: var(--ink);
  border-radius: 999px;
  padding: 14px 22px;
  font-family: var(--cs-body) !important;
  font-size: 15px;
  font-weight: 700;
}

/* The old hover dimmed the whole button and lifted it. CSignal shifts the lime
   and never dims or moves. */
body.cs-skin .obs-cta__btn:hover {
  background: #E2FF3A;
  opacity: 1;
  transform: none;
}

body.cs-skin .obs-cta__btn:disabled { background: var(--lime-dim); opacity: 1; }

/* Same reason the page CTAs lost theirs. */
body.cs-skin .obs-cta__btn svg { display: none; }

body.cs-skin .obs-cta__fine {
  font-family: var(--cs-body) !important;
  font-size: 11px;
  color: rgba(243, 245, 238, 0.42);
}

body.cs-skin .obs-cta__success {
  font-family: var(--cs-body) !important;
  color: var(--lime);
  background: rgba(211, 245, 2, 0.1);
  border: 1px solid rgba(211, 245, 2, 0.28);
  border-radius: 12px;
}

body.cs-skin .obs-cta__error {
  font-family: var(--cs-body) !important;
  color: var(--coral);
}


/* Ink rising into the paper at the FOOT of a section, for a join whose lower
   half belongs to something this stylesheet should not reach into, the footer
   being the case here. Same geometry as .cs-edge, sitting inside the section at
   its bottom rather than outside it at its top. */
body.cs-skin .cs-edge--btm {
  top: auto;
  bottom: -1px;
  z-index: 3;
}

body.cs-skin .cs-edge--btm path { fill: var(--ink); }

/* The Observatory shape field reuses the experts float: same class on the
   items, so there is one keyframe and one set of custom properties for both. */
body.cs-skin .cs-xp--ob {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}


/*==============================================================================
  FOOTER
  ----------------------------------------------------------------------------
  includes/footer.php ships its own inline stylesheet on the old brand: #0a0a0a
  under three purple and teal radial blobs, Season Serif for the sign-off,
  Season Sans Light at 30-70% white for everything else, and a white button.
  Repainted here rather than edited, because the include is shared: this lands
  on /v2.php and /work/v2.php together, and on every page that adopts the skin
  afterwards, with no per-page work.
==============================================================================*/

body.cs-skin .new-footer { background: var(--ink); }

/* The blobs go. Same rule as the hero and the Observatory: no gradients, no
   blurs, no glows. */
body.cs-skin .new-footer__bg { display: none; }

body.cs-skin .new-footer__hero,
body.cs-skin .new-footer__nav,
body.cs-skin .new-footer__nav-group { border-color: var(--line-on-ink); }

/* Sign-off. Built exactly like "The Charle Observatory." directly above it, so
   the page's two closing statements rhyme rather than each inventing a way of
   accenting its last word. */
body.cs-skin .new-footer__heading {
  font-family: var(--cs-display) !important;
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--paper);
}

body.cs-skin .new-footer__heading em {
  font-family: var(--cs-display) !important;
  font-style: normal;
  font-weight: 800;
  opacity: 1;
  display: inline-block;
  margin-top: 0.12em;
  padding: 0.04em 0.14em 0.1em;
  border-radius: 16px;
  background: var(--lime);
  color: var(--ink);
}

/* Same figures as every other button on the page. */
body.cs-skin .new-footer__cta {
  font-family: var(--cs-body) !important;
  font-size: 15px;
  font-weight: 700;
  line-height: normal;
  padding: 13px 24px;
  border-radius: 999px;
}

body.cs-skin .new-footer__cta--primary {
  background: var(--lime);
  color: var(--ink);
}

body.cs-skin .new-footer__cta--primary:hover { background: #E2FF3A; opacity: 1; }

/* The arrow, as everywhere else. */
body.cs-skin .new-footer__cta svg { display: none; }

body.cs-skin .new-footer__newsletter-label {
  font-family: var(--cs-body) !important;
  font-size: 15px;
  font-weight: 400;
  color: var(--on-ink-muted);
}

body.cs-skin .new-footer__newsletter-input {
  background: var(--ink-2);
  border-color: var(--line-on-ink);
  font-family: var(--cs-body) !important;
  font-size: 15px;
  font-weight: 400;
  color: var(--paper);
}

body.cs-skin .new-footer__newsletter-input::placeholder { color: rgba(243, 245, 238, 0.45); }

body.cs-skin .new-footer__newsletter-input:focus { border-color: var(--lime); }

body.cs-skin .new-footer__newsletter-btn {
  background: var(--lime);
  border-color: var(--lime);
  color: var(--ink);
  font-family: var(--cs-body) !important;
  font-size: 15px;
  font-weight: 700;
}

body.cs-skin .new-footer__newsletter-btn:hover { background: #E2FF3A; border-color: #E2FF3A; }

/* Column headings take the metric role. */
body.cs-skin .new-footer__nav-title,
body.cs-skin .new-footer__location-name {
  font-family: var(--cs-mono) !important;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.13em;
  color: rgba(243, 245, 238, 0.4);
}

/* Season Sans Light at 70% white is what made this block read washed out. */
body.cs-skin .new-footer__nav-link,
body.cs-skin .new-footer__nav-text,
body.cs-skin .new-footer__follow-text {
  font-family: var(--cs-body) !important;
  font-size: 15px;
  font-weight: 500;
  color: rgba(243, 245, 238, 0.72);
}

body.cs-skin .new-footer__nav-link:hover { color: var(--lime); }

/* The ring language used by the service-card arrows and the carousel controls:
   2px, currentColor, lime on hover. */
body.cs-skin .new-footer__follow-social a {
  border: 2px solid rgba(243, 245, 238, 0.22);
  color: rgba(243, 245, 238, 0.7);
}

body.cs-skin .new-footer__follow-social a:hover {
  background: transparent;
  border-color: var(--lime);
  color: var(--lime);
}

body.cs-skin .new-footer__bottom-social a { color: rgba(243, 245, 238, 0.5); }

body.cs-skin .new-footer__bottom-social a:hover { color: var(--lime); }

body.cs-skin .new-footer__copyright,
body.cs-skin .new-footer__bottom-link {
  font-family: var(--cs-body) !important;
  font-size: 13px;
  color: rgba(243, 245, 238, 0.42);
}

body.cs-skin .new-footer__bottom-link:hover { color: var(--lime); }

body.cs-skin .new-footer__logo { color: var(--paper); }

/* Shape field in the empty half of the sign-off row. Reuses the experts float,
   so there is one keyframe for all three fields on the page. */
body.cs-skin .new-footer__hero { position: relative; }

body.cs-skin .cs-xp--ft {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

body.cs-skin .new-footer__hero-left,
body.cs-skin .new-footer__hero-right { position: relative; z-index: 1; }

@media screen and (max-width: 1023px) {
  body.cs-skin .cs-xp--ft { display: none; }
}




/* Cell 8 turns column below 1023 but its graphic keeps the 55% basis the
   two-column layout gave it, so the flow sat in a narrow strip down the left of
   a full-width card. */
@media screen and (max-width: 1023px) {
  body.cs-skin .sv6__cell--8 .sv6__graphic {
    flex: 0 0 auto;
    width: 100%;
  }
}


/* The stat row is a flex strip divided by right-hand rules, which podcast.php
   wraps at 560 with flex: 1 1 45% and a border-bottom added on. Wrapped, the
   right-hand rules end up in the middle of a row and the bottom rules stop
   halfway across: that is the broken lines. On one column the divider only ever
   needs to run horizontally, so the vertical rules come off entirely. */
@media screen and (max-width: 640px) {
  body.cs-skin .obs-cta__stats {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0;
  }

  body.cs-skin .obs-cta__stat {
    flex: none;
    width: auto;
    padding: 12px 0;
    margin: 0;
    border-right: 0;
    border-bottom: 1px solid var(--line-on-paper);
  }

  body.cs-skin .obs-cta__stat:last-child { border-bottom: 0; padding-bottom: 0; }
}

/* Five of the twelve on mobile. Two was too quiet against the twelve the desktop
   band carries, and the reason the other ten were cut was that they were still
   on their DESKTOP anchors, where they landed on the heading.

   Measured at 375: the copy occupies 21% to 68% of the section, so the clear
   pockets are the top fifth and the bottom quarter. Everything below is placed
   inside those two bands and nothing is left on a desktop anchor. */
@media screen and (max-width: 1023px) {
  body.cs-skin .experts .cs-xp__s:nth-child(7),
  body.cs-skin .experts .cs-xp__s:nth-child(4) { display: block; }

  body.cs-skin .experts .cs-xp__s:nth-child(7) {
    top: 7%;
    right: 7%;
    bottom: auto;
    left: auto;
  }

  body.cs-skin .experts .cs-xp__s:nth-child(4) {
    bottom: 11%;
    left: 6%;
    top: auto;
    right: auto;
  }

  body.cs-skin .experts .cs-xp__s:nth-child(7) svg,
  body.cs-skin .experts .cs-xp__s:nth-child(4) svg {
    height: 42px;
    width: auto;
  }

  /* The other four, smaller so the original pair still leads. */
  /* Three added, not four. Child 2 is the one shape whose float wrapper is tall
     enough to reach the heading from the top band, wherever its own 30px sits,
     so it stays out rather than being nudged around a box that is not the size
     it looks. */
  body.cs-skin .experts .cs-xp__s:nth-child(1),
  body.cs-skin .experts .cs-xp__s:nth-child(9),
  body.cs-skin .experts .cs-xp__s:nth-child(10) { display: block; }

  body.cs-skin .experts .cs-xp__s:nth-child(1)  { top: 3%;  left: 6%;   right: auto; bottom: auto; }
  body.cs-skin .experts .cs-xp__s:nth-child(9)  { bottom: 21%; left: 4%;  top: auto; right: auto; }
  body.cs-skin .experts .cs-xp__s:nth-child(10) { bottom: 4%;  right: 7%; top: auto; left: auto; }

  body.cs-skin .experts .cs-xp__s:nth-child(1) svg,
  body.cs-skin .experts .cs-xp__s:nth-child(9) svg,
  body.cs-skin .experts .cs-xp__s:nth-child(10) svg {
    height: 30px;
    width: auto;
  }
}

/* The experts band uses the same component on every page that renders it: the
   cs-xp scatter injected in v2.php and copied verbatim into /work/ and the
   case studies. An earlier three-shape version that lived here has gone, so
   there is one definition rather than two that drift. */

body.cs-skin .experts__title { color: var(--on-ink); }
body.cs-skin .experts__description { color: var(--on-ink-muted); }
body.cs-skin .experts .btn-arrow svg { display: none; }
body.cs-skin .experts .btn-arrow { padding-right: 1.5rem; }



/*==============================================================================
  HERO SPACING AT NARROW WIDTHS
  ----------------------------------------------------------------------------
  MUST STAY BELOW .cs-eyebrow's base rule. That rule sets the margin with the
  shorthand, and a media query adds no specificity, so written above it the
  shorthand simply resets margin-bottom to -16px again and nothing appears to
  change. This is exactly what happened the first time these were written.

  The -16px pull is measured against the desktop display size. At mobile heading
  sizes the same 16px bites proportionally much deeper, which is what stuck the
  label to the headline. Both gaps move toward each other rather than one being
  fixed: the pull goes positive, and the lede's 34px comes down to meet it.
==============================================================================*/

@media screen and (max-width: 767px) {
  body.cs-skin .cs-eyebrow {
    margin-bottom: 14px;
    font-size: 11px;
    letter-spacing: 0.12em;
  }

  body.cs-skin .cs-lede { margin-top: 20px; }
}

@media screen and (min-width: 768px) and (max-width: 1023px) {
  body.cs-skin .cs-eyebrow { margin-bottom: 10px; }

  body.cs-skin .cs-lede { margin-top: 24px; }
}


/* SEO & GEO on mobile. Two things were opening that gap above the AI card: the
   card's own 1.8rem padding, and the .cs-lc height clamp leaving the content
   floating in the middle of a box taller than it needs, since .cs-lc centres
   what is inside it. Both come down. */
@media screen and (max-width: 760px) {
  body.cs-skin .sv6__cell--1 { padding-top: 0.6rem; }

  body.cs-skin .cs-lc { height: clamp(150px, 38vw, 190px); }

  /* The card's remaining top padding is the gap; the graphic is the first thing
     in the cell, so pulling it up is the only lever left short of unpadding the
     card on every side. */
  body.cs-skin .sv6__cell--1 .cs-find { margin-top: -4px; }

  /* ---------------------------------------------------------------------
     SEO & GEO goes to the ink ground at this width.

     The graphic is a white card, and on a paper card that is near-white on
     near-white. On desktop the pair of cards, the neighbouring cells and the
     grid around them carry the contrast; stacked on a phone this cell is the
     only thing on screen and there is nothing to give it an edge, so it reads
     as one flat white block.

     Ink is what cells 2 and 5 already use, so this is the existing card
     treatment applied at a breakpoint rather than a new one. Every rule the
     ink cards carry has to come with it: the marks stop being filtered black,
     and the name, number, arrow and description all invert.
     --------------------------------------------------------------------- */
  body.cs-skin .sv6__cell--1,
  body.cs-skin .sv6__cell--1:hover {
    background: var(--ink-2);
    border-color: var(--line-on-ink) !important;
  }

  body.cs-skin .sv6__cell--1 .sv6__cell-name,
  body.cs-skin .sv6__cell--1 .sv6__cell-number,
  body.cs-skin .sv6__cell--1 .sv6__cell-arrow,
  body.cs-skin .sv6__cell--1:hover .sv6__cell-name,
  body.cs-skin .sv6__cell--1:hover .sv6__cell-number,
  body.cs-skin .sv6__cell--1:hover .sv6__cell-arrow { color: var(--paper); }

  body.cs-skin .sv6__cell--1 .sv6__cell-desc,
  body.cs-skin .sv6__cell--1:hover .sv6__cell-desc { color: var(--on-ink-muted); }

  /* The marks are white artwork; the paper cards filter them black. On ink they
     go back to being used as drawn. */
  body.cs-skin .sv6__cell--1 .sv6__cell-badge img,
  body.cs-skin .sv6__cell--1:hover .sv6__cell-badge img {
    filter: none;
    opacity: 1;
  }
}


/*==============================================================================
  MEGA MENU CTA PANEL
  ----------------------------------------------------------------------------
  The photograph of the team becomes a CSignal panel. Same box as the image it
  replaces, so style.css's flex-basis and aspect-ratio still size it and nothing
  about the dropdown's layout changes.
==============================================================================*/

body.cs-skin .cs-navcta {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  /* Extra room at the foot. The wordmark and lockup are centred in the panel
     while Learn more is pinned to the bottom right, so without it the two
     centre into each other's space. */
  padding: 22px 22px 58px;
  border-radius: 14px;
  background: var(--ink-3);
  overflow: hidden;
}

body.cs-skin .cs-navcta__deco {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

body.cs-skin .cs-navcta__s {
  position: absolute;
  line-height: 0;
}

body.cs-skin .cs-navcta__s svg { display: block; }

body.cs-skin .cs-navcta__mark {
  position: relative;
  display: block;
  line-height: 0;
}

body.cs-skin .cs-navcta__mark svg { display: block; }

/* The lockup, in the same two-line form the page badge uses: the Charle line
   muted, the CSignal line lime. */
body.cs-skin .cs-navcta__lockup {
  position: relative;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 0 5px;
  font-family: var(--cs-body) !important;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
  line-height: 1.35;
  text-align: center;
  color: rgba(243, 245, 238, 0.62);
}

body.cs-skin .cs-navcta__lockup em {
  font-style: normal;
  font-weight: 700;
  color: var(--lime);
}

/* Bottom right, inside the panel. */
body.cs-skin .cs-navcta__cta {
  position: absolute;
  right: 14px;
  bottom: 14px;
  padding: 7px 14px;
  border: 1px solid rgba(243, 245, 238, 0.28);
  border-radius: 999px;
  font-family: var(--cs-body) !important;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--paper);
  text-decoration: none;
  white-space: nowrap;
  transition: border-color 0.18s ease-out, color 0.18s ease-out, background 0.18s ease-out;
}

body.cs-skin .cs-navcta__cta:hover {
  background: var(--lime);
  border-color: var(--lime);
  color: var(--ink);
}

/* Mobile drawer panel only. The mobile CTA slot is a short, wide box
   (aspect-ratio 35/13) with overflow:hidden, so the full wordmark + lockup +
   Learn more stack is taller than the box and the wordmark's top gets clipped.
   Drop the lockup line here and tighten the padding so the wordmark sits clear.
   The desktop dropdown panel (.new-nav-dropdown__cta-image) is untouched. */
body.cs-skin .new-mobile-navigation__cta-image.cs-navcta {
  padding: 16px 18px 40px;
  gap: 8px;
}
body.cs-skin .new-mobile-navigation__cta-image.cs-navcta .cs-navcta__lockup {
  display: none;
}


/* HERO LEDE SIZE. csignal-hero.css sets clamp(15px, 2.4vw, 21px), sized for the
   single sentence the hero carried before the CSignal line was added to it. Two
   sentences at that size push the block down onto the CTAs, so it steps down a
   notch. Scoped with body.cs-skin, so it outranks the plain .cs-lede in
   csignal-hero.css whichever order the two sheets load in. */
body.cs-skin .cs-lede { font-size: clamp(14px, 2.05vw, 18px); }


/* ============================================================================
   POSITIONING BAND  (homepage v2, below the About Charle intro)

   The loop is lifted from /csignal/ .cs-how rather than invented: the rail with
   its advancing lime track, the dots, the steps sitting at opacity .34 until
   they are the live one. The only change is that the rail runs horizontally,
   because the homepage is already long and a vertical rail plus a 320px stage
   would have cost three times the height.

   Net new markup. Nothing existing was moved or rewritten to fit it, so the
   page's headings, copy and links are unchanged and the band is additive.
   ========================================================================= */
body.cs-skin .cs-pos {
  position: relative;
  overflow-x: clip;
  /* #0A140F, the announcement bar's ink -- a shade below the page ground, so
     the band separates from the sections either side without a rule or a gap. */
  background-color: #0A140F;
  padding: 58px 0 62px;
}

body.cs-skin .cs-pos__deco { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
body.cs-skin .cs-pos__s { position: absolute; display: block; line-height: 0; }
body.cs-skin .cs-pos__s svg { display: block; }
body.cs-skin .cs-pos__s--a { top: -52px; left: -70px; transform: rotate(-10deg); }
/* Cropped by the right edge only. At bottom:-44px it was cut top-and-bottom as
   well, which left a rounded blob rather than a cursor -- the tip is what makes
   the shape readable, so that has to stay on the page. */
body.cs-skin .cs-pos__s--b { bottom: 26px; right: -44px; transform: rotate(12deg); }

body.cs-skin .cs-pos > .container-fluid,
body.cs-skin .cs-pos > .container { position: relative; z-index: 1; }

body.cs-skin .cs-pos__inner {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: 60px;
  align-items: center;
}

body.cs-skin .cs-pos__title {
  font-family: var(--cs-display) !important;
  font-weight: 800; letter-spacing: -0.032em;
  /* 1.02 was set for plain text. The .cs-hl highlight adds a padded box around
     the word, so on a wrapped line that box collides with the line above. */
  line-height: 1.22;
  font-size: clamp(30px, 3.1vw, 46px); color: var(--on-ink); margin: 0 0 18px;
}

body.cs-skin .cs-pos__lede {
  font-size: 15.5px; line-height: 1.55;
  color: rgba(243, 245, 238, 0.6); margin: 0; max-width: 58ch;
}

body.cs-skin .cs-pos__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 24px;
}

/* Outline, the same treatment the offer pills and the CSignal buttons use:
   transparent, one hairline, lime on hover. */
body.cs-skin .cs-pos__cta {
  margin-top: 0;
  background-color: transparent !important;
  border: 1px solid rgba(255, 255, 255, 0.25) !important;
  color: var(--on-ink) !important;
  transition: border-color 0.12s ease-out, color 0.12s ease-out;
}

body.cs-skin .cs-pos__cta:hover {
  background-color: transparent !important;
  border-color: var(--lime) !important;
  color: var(--lime) !important;
}

/* The primary of the pair: CSignal is the thing this band is arguing for, so it
   takes the solid lime and About Charle stays the outline behind it. */
body.cs-skin .cs-pos__cta--lime,
body.cs-skin .cs-pos__cta--lime:hover {
  background-color: var(--lime) !important;
  border-color: var(--lime) !important;
  color: var(--ink) !important;
}

body.cs-skin .cs-pos__cta--lime:hover { filter: brightness(0.94); }

/* --- The rail --------------------------------------------------------------- */
body.cs-skin .cs-pos__loop { position: relative; }

body.cs-skin .cs-pos__track {
  position: absolute; left: 0; right: 0; top: 13px; height: 2px;
  background: rgba(255, 255, 255, 0.12); border-radius: 2px; overflow: hidden;
}
body.cs-skin .cs-pos__track i {
  position: absolute; left: 0; top: 0; height: 2px; width: 0;
  background: var(--lime); transition: width 0.55s cubic-bezier(0.7, 0, 0.3, 1);
}

body.cs-skin .cs-pos__steps {
  position: relative; display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px;
}

body.cs-skin .cs-pos__step {
  position: relative; text-align: left; background: none; border: 0; padding: 0;
  font: inherit; color: inherit; cursor: pointer; opacity: 0.34;
  transition: opacity 0.35s ease;
}
body.cs-skin .cs-pos__step:hover { opacity: 0.7; }
body.cs-skin .cs-pos__step.is-on,
body.cs-skin .cs-pos__step.is-on:hover { opacity: 1; }
body.cs-skin .cs-pos__step:focus-visible { outline: 2px solid var(--lime); outline-offset: 6px; border-radius: 6px; }

/* The dot carries an ink border so the track passes behind it cleanly. */
body.cs-skin .cs-pos__step em {
  position: absolute; left: 0; top: 7px; width: 14px; height: 14px; border-radius: 50%;
  background: #3A4A42; border: 3px solid #0A140F;
  transition: background 0.35s ease, transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
body.cs-skin .cs-pos__step.is-on em { background: var(--lime); transform: scale(1.25); }

body.cs-skin .cs-pos__step b {
  display: block; font-family: var(--cs-mono) !important; font-size: 10px;
  letter-spacing: 0.13em; color: rgba(255, 255, 255, 0.42); padding-top: 34px; margin-bottom: 5px;
}
body.cs-skin .cs-pos__step h3 {
  font-family: var(--cs-display) !important; font-weight: 800; font-size: 19px;
  letter-spacing: -0.02em; margin: 0 0 5px; color: #fff;
}
body.cs-skin .cs-pos__step p {
  margin: 0; font-size: 12.5px; line-height: 1.45; color: rgba(243, 245, 238, 0.55);
}

/* --- The read-out ------------------------------------------------------------
   Panels are stacked in a fixed-height box so nothing below the band moves when
   the loop advances -- the same reason /csignal/ stacks .cs-how__pan. */
/* Capped, not full width. Across the whole right column the card stretched to
   well over a comfortable measure and the single line of text floated in it. */
body.cs-skin .cs-pos__stage {
  position: relative;
  height: 74px;
  margin-top: 26px;
  max-width: 520px;
}

body.cs-skin .cs-pos__pan {
  position: absolute; inset: 0; opacity: 0; transform: translateY(10px);
  transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
  display: flex; align-items: center; gap: 14px;
  background: #fff; border-radius: 14px; padding: 0 20px; color: var(--ink);
}
body.cs-skin .cs-pos__pan.is-on { opacity: 1; transform: none; }

/* The card is a CSignal read-out, not a generic notification -- without the
   source on it, the recommendation reads as something Charle wrote by hand,
   which is exactly the opposite of the point. */
body.cs-skin .cs-pos__src {
  position: absolute;
  top: 9px;
  right: 14px;
  font-family: var(--cs-mono) !important;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #9AA8A0;
}

body.cs-skin .cs-pos__mark {
  width: 26px; height: 26px; border-radius: 7px; display: flex; align-items: center;
  justify-content: center; flex: none; font-family: var(--cs-mono) !important;
  font-size: 11px; font-weight: 600;
}
/* Same source colours the CSignal page uses for goal, ask and measured. */
body.cs-skin .cs-pos__mark--goal  { background: #EEF9C6; color: #5C7A18; }
body.cs-skin .cs-pos__mark--ask   { background: #EFEBFE; color: #6C4CF1; }
body.cs-skin .cs-pos__mark--meas  { background: #EAF0FF; color: #2F6BFF; }
body.cs-skin .cs-pos__mark--build { background: #E8EFEA; color: #2C5C42; }

body.cs-skin .cs-pos__t {
  display: block; font-size: 14px; font-weight: 600; line-height: 1.3; color: #12211A;
}
body.cs-skin .cs-pos__sub {
  display: block; font-family: var(--cs-mono) !important; font-size: 10.5px;
  letter-spacing: 0.06em; text-transform: uppercase; color: #7C8B83; margin-top: 3px;
}
body.cs-skin .cs-pos__live {
  margin-left: auto; font-family: var(--cs-mono) !important; font-size: 11px;
  color: #7C8B83; white-space: nowrap;
}

body.cs-skin .cs-pos__bar {
  width: 78px; height: 8px; border-radius: 6px; background: #EEF1F6;
  overflow: hidden; flex: none; margin-left: auto;
}
body.cs-skin .cs-pos__bar i {
  display: block; height: 100%; width: 0; background: var(--blue); border-radius: 6px;
  transition: width 0.8s cubic-bezier(0.7, 0, 0.3, 1) 0.25s;
}
body.cs-skin .cs-pos__pan.is-on .cs-pos__bar i { width: var(--w, 70%); }

@media screen and (max-width: 1023px) {
  body.cs-skin .cs-pos { padding: 46px 0 50px; }
  body.cs-skin .cs-pos__inner { grid-template-columns: 1fr; gap: 34px; }
  body.cs-skin .cs-pos__steps { grid-template-columns: repeat(2, 1fr); gap: 22px 14px; }
  /* The track cannot follow a wrapped grid, so it goes and each dot sits above
     its own step instead. */
  body.cs-skin .cs-pos__track { display: none; }
  body.cs-skin .cs-pos__step em { position: static; display: block; margin-bottom: 10px; }
  body.cs-skin .cs-pos__step b { padding-top: 0; }
  body.cs-skin .cs-pos__stage { height: 92px; }
  body.cs-skin .cs-pos__s--a { transform: rotate(-10deg) scale(0.7); left: -84px; }
  body.cs-skin .cs-pos__s--b { display: none; }
}

/* No single-column fallback. Four steps read as a cycle, and a cycle has to be
   seen as a shape: stacked one under the other it becomes a list of four
   unrelated paragraphs and the numbering is the only thing holding it together.
   The 2x2 from the rule above therefore holds all the way down. */

@media (prefers-reduced-motion: reduce) {
  body.cs-skin .cs-pos__step,
  body.cs-skin .cs-pos__pan,
  body.cs-skin .cs-pos__track i,
  body.cs-skin .cs-pos__bar i { transition: none; }
}


/* ============================================================================
   COOKIE CONSENT, CSIGNAL SKIN
   includes/tracking.php styles the modal in an inline <style> in the head:
   #111 on #222, Season Sans, Season Serif title, a white pill for accept. That
   is the old brand, and it is the first thing a first-time visitor sees.

   Overridden here rather than edited there, because tracking.php is shared with
   every non-v2 page and must keep working untouched. Every selector is scoped
   to body.cs-skin, so this reaches the v2 pages only -- and, after they replace
   index.php, the whole site.

   Specificity does the work: the page's own rules are single classes (0,1,0),
   these are (0,2,0) plus an element, so load order never matters.
   ========================================================================= */
body.cs-skin .cc-modal {
  background: var(--ink-2) !important;
  border: 0 !important;
  border-radius: 16px !important;
  font-family: var(--cs-body) !important;
  padding: 1.75rem 1.75rem 1.5rem !important;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
  overflow: hidden;
}

/* The Spike mark in the top-right corner, clipped by the modal's own radius.
   Drawn as a background rather than markup because the modal is injected by
   tracking.php's inline JS, which is shared with every non-v2 page and must
   stay untouched. Note there is deliberately NO position on .cc-modal here:
   tracking.php sets position:fixed;bottom:1.5rem, and overriding that is what
   pulled the whole modal to the top of the viewport. fixed is already a
   containing block, so the absolute corner piece anchors to it correctly.
   The copy sits above it via the z-index below. */
body.cs-skin .cc-modal::before {
  content: "";
  position: absolute;
  top: -30px;
  right: -34px;
  width: 158px;
  height: 158px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-10 -10 140 140' fill='none'%3E%3Cpath d='M0 120 V96 H24 V72 H48 V44 H72 V22 H96 V6 H120 V120 Z' fill='%23FF5A2C' stroke='%23FF5A2C' stroke-width='12' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / contain;
  transform: rotate(180deg);
  pointer-events: none;
}

body.cs-skin .cc-logo,
body.cs-skin .cc-title,
body.cs-skin .cc-text,
body.cs-skin .cc-actions { position: relative; z-index: 1; }

body.cs-skin .cc-logo { color: var(--paper) !important; margin-bottom: 1.1rem !important; }

/* The kit's display face, tight, replacing Season Serif. */
body.cs-skin .cc-title {
  font-family: var(--cs-display) !important;
  font-size: 21px !important;
  font-weight: 800 !important;
  letter-spacing: -0.02em;
  line-height: 1.15 !important;
  color: var(--on-ink) !important;
  margin-bottom: 0.6rem !important;
}

body.cs-skin .cc-text {
  font-family: var(--cs-body) !important;
  font-size: 14px !important;
  line-height: 1.6 !important;
  color: var(--on-ink-muted) !important;
  margin-bottom: 1.35rem !important;
}

body.cs-skin .cc-text a {
  color: var(--lime) !important;
  text-decoration: none !important;
  border-bottom: 1px solid rgba(211, 245, 2, 0.4);
}
body.cs-skin .cc-text a:hover { border-bottom-color: var(--lime); opacity: 1 !important; }

body.cs-skin .cc-actions { gap: 0.55rem !important; }

body.cs-skin .cc-btn {
  font-family: var(--cs-body) !important;
  font-size: 14px !important;
  font-weight: 600 !important;
  letter-spacing: 0 !important;
  padding: 0.8rem 1.6rem !important;
  border-radius: 999px !important;
  transition: background-color 0.14s ease-out, border-color 0.14s ease-out, color 0.14s ease-out !important;
}

/* Lime is the affirmative, the same as every other primary on the skin. */
body.cs-skin .cc-btn--accept {
  background: var(--lime) !important;
  color: var(--ink) !important;
  border: 1px solid var(--lime) !important;
}
body.cs-skin .cc-btn--accept:hover { filter: brightness(0.94); opacity: 1 !important; }

/* Decline stays a real, readable option rather than near-invisible grey: #555
   on #111 was about 2:1, which fails contrast and reads as a dark pattern. */
body.cs-skin .cc-btn--reject {
  background: transparent !important;
  color: var(--on-ink-muted) !important;
  border: 1px solid rgba(243, 245, 238, 0.22) !important;
  padding: 0.8rem 1.6rem !important;
}
body.cs-skin .cc-btn--reject:hover {
  color: var(--on-ink) !important;
  border-color: rgba(243, 245, 238, 0.45) !important;
}

body.cs-skin .cc-overlay { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }

@media screen and (max-width: 560px) {
  body.cs-skin .cc-modal { border-radius: 14px !important; padding: 1.4rem 1.35rem 1.25rem !important; }
  body.cs-skin .cc-title { font-size: 19px !important; }
}

/*==============================================================================
  MOBILE PASS, 13 Sep 2026
  ----------------------------------------------------------------------------
  Everything here is phone-only and additive. Kept in one block at the end so
  the mobile corrections are findable, rather than scattered through the file.
==============================================================================*/

@media screen and (max-width: 767px) {

  /* --- Gallery shapes ------------------------------------------------------
     They were rendering at their desktop intrinsic sizes: Store at 451px and
     Leak at 401px on a 435px-wide screen, so a single shape was wider than the
     phone and the band read as two coloured slabs rather than as depth behind
     the grid. Driven from the viewport here, so they stay punctuation. The xl
     ground plane keeps its own rule and stays out on mobile. */
  body.cs-skin .cs-gal-deco__s:not(.cs-gal-deco__s--xl) svg {
    height: clamp(78px, 22vw, 140px);
    width: auto;
  }
  /* The offsets were tuned against desktop shape sizes, so at a sixth of the
     size they left the shapes stranded mid-canvas instead of cropped by an
     edge. Pulled back onto the edges. */
  body.cs-skin .cs-gal-deco__s--tl { top: 2%;  left: -7vw;  }
  body.cs-skin .cs-gal-deco__s--tr { top: 6%;  right: -6vw; }
  body.cs-skin .cs-gal-deco__s--bl { bottom: 4%; left: -6vw; }
  body.cs-skin .cs-gal-deco__s--br { bottom: 2%; right: -7vw; }
  body.cs-skin .cs-gal-deco__s--ml,
  body.cs-skin .cs-gal-deco__s--mr,
  body.cs-skin .cs-gal-deco__s--tr2 { display: none; }

  /* --- Footer -------------------------------------------------------------
     .new-footer__hero ends with 64px of padding and .new-footer__nav opens
     with 48px, so 112px of dead ground stacked up above SERVICES. Halved on
     both sides: the hairline is already doing the separating. */
  body.cs-skin .new-footer__hero { padding-bottom: 28px; }
  body.cs-skin .new-footer__nav  { padding-top: 24px; }

  /* Every nav group carried a bottom border including the last, which drew a
     rule under Get in touch with nothing beneath it. */
  body.cs-skin .new-footer__nav-group:last-child { border-bottom: 0; }
}

@media screen and (max-width: 1023px) {

  /* --- Feature shapes ------------------------------------------------------
     These were switched off wholesale below 1023 because, stacked, the two
     columns fill the width and a shape sized for the desktop margin simply
     landed on the copy. The shapes were not the problem, the sizes and the
     anchors were: at 30px and pinned to the corners of the image block they
     sit on the artwork, which is where .cs-fdeco's own z-index already puts
     them (over .feature__images at 1, under .feature__content at 3). */
  body.cs-skin .cs-fdeco { display: block; }
  body.cs-skin .cs-fdeco svg { height: 30px; width: auto; }

  /* Every desktop anchor is overridden, so nothing inherits a position tuned
     for a two-column layout. Odd numbers left, even numbers right, staggered
     down the image block so no two sit level. */
  body.cs-skin .cs-fdeco--1,
  body.cs-skin .cs-fdeco--5,
  body.cs-skin .cs-fdeco--9,
  body.cs-skin .cs-fdeco--13  { left: -10px; right: auto; top: 4%;  bottom: auto; }
  body.cs-skin .cs-fdeco--3,
  body.cs-skin .cs-fdeco--7,
  body.cs-skin .cs-fdeco--11,
  body.cs-skin .cs-fdeco--15  { left: -8px;  right: auto; top: 26%; bottom: auto; }
  body.cs-skin .cs-fdeco--2,
  body.cs-skin .cs-fdeco--6,
  body.cs-skin .cs-fdeco--10,
  body.cs-skin .cs-fdeco--14  { right: -10px; left: auto; top: 9%;  bottom: auto; }
  body.cs-skin .cs-fdeco--4,
  body.cs-skin .cs-fdeco--8,
  body.cs-skin .cs-fdeco--12,
  body.cs-skin .cs-fdeco--16  { right: -8px;  left: auto; top: 31%; bottom: auto; }
}

/*------------------------------------------------------------------------------
  MOBILE MENU
  ----------------------------------------------------------------------------
  The panel was never skinned. It kept the stock Charle grey (#1A1B1E, which is
  not the CSignal ink), white-on-black badges, and submenu anchors with no colour
  rule at all, so they were resolving to the browser's DEFAULT LINK BLUE
  (rgb(0,0,238)) with a white child element sitting on top of them. That last one
  is only invisible because .new-mobile-submenu__link-title repaints the text.
------------------------------------------------------------------------------*/

body.cs-skin .new-mobile-navigation,
body.cs-skin .new-mobile-navigation__inner { background-color: var(--ink); }

body.cs-skin .new-mobile-navigation__submenu,
body.cs-skin .new-mobile-submenu__inner { background-color: var(--ink); }

/* Top-level items take the display face. They are the largest type in the
   panel, so leaving them in the body face was the one thing that made the menu
   read as a different site to the page behind it. */
body.cs-skin .new-mobile-navigation__link,
body.cs-skin .new-mobile-submenu__title,
body.cs-skin .new-mobile-submenu__title-text {
  font-family: var(--cs-display) !important;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--paper);
}

/* The anchor itself, not just its title child. */
body.cs-skin .new-mobile-submenu__link { color: var(--paper); text-decoration: none; }
body.cs-skin .new-mobile-submenu__link-title { color: var(--paper); }
body.cs-skin .new-mobile-submenu__link-description { color: var(--on-ink-muted); }
body.cs-skin .new-mobile-submenu__link:hover .new-mobile-submenu__link-title,
body.cs-skin .new-mobile-submenu__link:active .new-mobile-submenu__link-title { color: var(--lime); }

/* Section headers are the little outlined labels (Search, Launch). Mono, the
   way every other eyebrow on the skin is set. */
body.cs-skin .new-mobile-submenu__section-header {
  font-family: var(--cs-mono, ui-monospace, monospace) !important;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--on-ink-faint, rgba(243, 245, 238, 0.38));
  border-color: var(--line-on-ink);
}

/* Badges were white on black, which is the only pure white surface in the
   whole skin. Lime on ink, matching the nav badge on desktop. */
body.cs-skin .new-mobile-navigation__badge,
body.cs-skin .new-mobile-submenu__title-badge {
  background: var(--lime) !important;
  color: var(--ink) !important;
  font-family: var(--cs-body) !important;
  font-weight: 700;
  border: 0;
}

body.cs-skin .new-mobile-navigation__item { border-color: var(--line-on-ink); }

/* The promo card at the foot of the panel. */
body.cs-skin .new-mobile-navigation__cta { background: var(--ink-2); border: 1px solid var(--line-on-ink); }

/* Centring it, which it was not.

   Two things were pulling it off-axis. It is a flex child, and one of its
   parents is align-items: flex-start, so it never stretched and sized itself
   to its content instead. And it has no horizontal margin, while every block
   above it (__list and __section) is inset by 1.5rem, so even stretched it sat
   full-bleed against inset content.

   align-self overrides the parent's align-items whatever that parent is, which
   matters because this CTA appears in three different containers. The margin
   then matches the inset the rest of the drawer already uses, and equal margins
   on a stretched box are what actually centres it.

   All four corners, because with the skin's border this reads as a card. The
   0 0 20px 20px it ships with is for a panel flush to the foot of the drawer,
   which is no longer what it is. */
body.cs-skin .new-mobile-navigation__cta {
  align-self: stretch;
  width: auto;
  margin: 0 1.5rem 1.5rem;
  border-radius: 16px;
}
body.cs-skin .new-mobile-navigation__cta-title { color: var(--paper); font-family: var(--cs-display) !important; font-weight: 700; }
body.cs-skin .new-mobile-navigation__cta-description { color: var(--on-ink-muted); }

/* --- Stat cards at laptop widths ---------------------------------------------
   The four cards size to their content on one row, so in a 659px column at
   1280 they came out at 129, 172, 156 and 166px with every label wrapping to
   three lines. Two by two from here down: each card gets about 320px, the
   labels sit on one or two lines, and the row stops looking squeezed. Above
   1440 there is room for four across and they stay as they were.
---------------------------------------------------------------------------- */
@media screen and (min-width: 768px) and (max-width: 1440px) {
  body.cs-skin .about-charle__stats {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
  }
}


/* ============================================================================
   NEWSLETTER POPUP, CSIGNAL SKIN
   includes/header.php styles "The Charle Observatory" in an inline <style> in
   the body: #111 with a mint-green eyebrow, a blurred radial glow behind the
   corner, Season Sans throughout and a Season Serif italic for the second half
   of the title. That is the old brand, and it is the largest single thing a
   visitor sees on the site.

   Overridden here rather than edited there, for the same reason as the cookie
   modal above: header.php is shared with every non-v2 page and must keep
   working untouched. Every selector is scoped to body.cs-skin, so this reaches
   the v2 pages only -- and, once they replace index.php, the whole site.

   Specificity does the work: the page's own rules are single classes (0,1,0),
   these are (0,2,0) plus an element, so load order never matters. The two
   exceptions are the title's <em> and the input's ::placeholder, both flagged
   at their rules.
   ========================================================================= */
body.cs-skin .nl-popup {
  background: var(--ink-2) !important;
  border: 0 !important;
  border-radius: 20px !important;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
}

/* The glow becomes a shape. .nl-popup::before was a 50px-blurred mint radial,
   and CSignal has no gradients, no blurs and no glows anywhere in the kit.
   Reusing the same pseudo-element rather than adding markup, because the popup
   is printed by header.php. Bottom-right, not top: the close button owns the
   top-right corner, and the privacy line is short so the bottom corner is the
   one piece of open ground in the card.

   Path in Electric Blue. Path is the kit's only STROKED mark, so it reads as a
   route rather than a block and stays distinct from the cookie modal's solid
   coral Spike, which crops the opposite corner of a card the same size. Its
   climb runs up to the right, so a bottom-right crop takes the flat start and
   leaves the ascent showing, which is the half worth seeing. */
body.cs-skin .nl-popup::before {
  top: auto !important;
  bottom: -52px !important;
  right: -46px !important;
  width: 186px !important;
  height: 186px !important;
  aspect-ratio: auto !important;
  border-radius: 0 !important;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-24 -24 168 168' fill='none'%3E%3Cpath d='M10 106 V82 H42 V58 H74 V34 H110' stroke='%232F6BFF' stroke-width='34' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / contain !important;
  filter: none !important;
  transform: rotate(-8deg);
  opacity: 1;
}

body.cs-skin .nl-backdrop { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }

/* Mono eyebrow, lime, the same label treatment as every other eyebrow on the
   skin. Was 10px mint at 0.16em, which at that size read as a smudge. */
body.cs-skin .nl-popup__sub {
  font-family: var(--cs-mono) !important;
  font-size: 11px !important;
  font-weight: 500 !important;
  letter-spacing: 0.08em !important;
  color: var(--lime) !important;
  margin-bottom: 0.85rem !important;
}

body.cs-skin .nl-popup__heading {
  font-family: var(--cs-display) !important;
  font-size: clamp(24px, 3vw, 30px) !important;
  font-weight: 800 !important;
  letter-spacing: -0.02em !important;
  line-height: 1.12 !important;
  color: var(--on-ink) !important;
  margin-bottom: 0.7rem !important;
}

/* "Observatory." carries inline style on the <em> itself: Season Serif,
   italic, opacity 0.65. Inline beats any selector, so !important is the only
   way to reach it without editing the shared markup. Lime and upright instead:
   the kit sets the second half apart by colour, never by a serif italic. */
body.cs-skin .nl-popup__heading em {
  font-family: var(--cs-display) !important;
  font-style: normal !important;
  font-weight: 800 !important;
  opacity: 1 !important;
  color: var(--lime) !important;
}

body.cs-skin .nl-popup__desc {
  font-family: var(--cs-body) !important;
  font-size: 14px !important;
  line-height: 1.6 !important;
  color: var(--on-ink-muted) !important;
  margin-bottom: 1.4rem !important;
}

/* --- The form ---------------------------------------------------------------
   Kept as one joined pill, which is the shape the markup is built for: the
   input and the button carry opposite half-radii and the button has no left
   border. Only the colours change. */
body.cs-skin .nl-form__input {
  background: var(--ink-3) !important;
  border: 1px solid rgba(243, 245, 238, 0.14) !important;
  border-right: 0 !important;
  color: var(--on-ink) !important;
  font-family: var(--cs-body) !important;
  padding: 0.85rem 1.25rem !important;
}
/* ::placeholder is not inherited from the input's own colour, so it needs its
   own rule or it keeps the old 0.3 white. */
body.cs-skin .nl-form__input::placeholder { color: rgba(243, 245, 238, 0.38) !important; }
body.cs-skin .nl-form__input:focus {
  border-color: var(--lime) !important;
  background: var(--ink-3) !important;
}

/* Lime is the affirmative everywhere on the skin, the same as Accept on the
   cookie modal and every primary button on the site. */
body.cs-skin .nl-form__btn {
  background: var(--lime) !important;
  color: var(--ink) !important;
  border: 1px solid var(--lime) !important;
  border-left: 0 !important;
  font-family: var(--cs-body) !important;
  font-weight: 600 !important;
  padding: 0.85rem 1.6rem !important;
}
body.cs-skin .nl-form__btn:hover { background: var(--lime) !important; filter: brightness(0.94); }

body.cs-skin .nl-close {
  background: rgba(243, 245, 238, 0.08) !important;
  border: 1px solid rgba(243, 245, 238, 0.16) !important;
  color: var(--on-ink) !important;
}
body.cs-skin .nl-close:hover { background: rgba(243, 245, 238, 0.16) !important; }
body.cs-skin .nl-close svg { stroke: var(--on-ink) !important; }

/* Mono, like the source line under the work stats: it is a footnote, and the
   kit sets footnotes in the label face. */
body.cs-skin .nl-popup__privacy {
  font-family: var(--cs-mono) !important;
  font-size: 10px !important;
  letter-spacing: 0.04em !important;
  color: rgba(243, 245, 238, 0.38) !important;
  margin-top: 1.1rem !important;
}
body.cs-skin .nl-popup__privacy a { color: rgba(243, 245, 238, 0.6) !important; text-decoration-color: rgba(243, 245, 238, 0.3); }
body.cs-skin .nl-popup__privacy a:hover { color: var(--lime) !important; }

body.cs-skin .nl-status { font-family: var(--cs-body) !important; }
body.cs-skin .nl-status--success { color: var(--lime) !important; }
body.cs-skin .nl-status--error { color: var(--coral) !important; }

/* --- Success state --------------------------------------------------------- */
body.cs-skin .nl-success-msg__icon {
  background: rgba(211, 245, 2, 0.12) !important;
  border: 1px solid rgba(211, 245, 2, 0.3) !important;
}
body.cs-skin .nl-success-msg__icon svg { stroke: var(--lime) !important; }
body.cs-skin .nl-success-msg__text {
  font-family: var(--cs-display) !important;
  font-weight: 800 !important;
  letter-spacing: -0.02em !important;
  font-size: 20px !important;
  color: var(--on-ink) !important;
}
body.cs-skin .nl-success-msg__sub {
  font-family: var(--cs-body) !important;
  color: var(--on-ink-muted) !important;
}

@media screen and (max-width: 520px) {
  body.cs-skin .nl-popup { border-radius: 20px 20px 0 0 !important; }
  /* The card is edge to edge and bottom-anchored on phones, so the corner the
     shape hung off is now the screen's own bottom-right. Pulled in and up so
     it still crops against the card rather than against the viewport. */
  body.cs-skin .nl-popup::before {
    bottom: -36px !important;
    right: -30px !important;
    width: 142px !important;
    height: 142px !important;
  }
}

/* ==========================================================================
   Horizontal-overflow guard.
   The logo marquee ticker (.cs-lg__item / .cs-lg__track) lays its items out in
   a very wide row and leaks a few dozen px past the viewport on narrow screens.
   That makes the page wider than the device, so mobile browsers load slightly
   zoomed in and leave a dead margin on the right when you zoom out.
   overflow-x: clip on the root clips that stray horizontal content without
   creating a scroll container, so position: sticky keeps working (unlike
   overflow: hidden). Vertical scrolling is untouched.
   ========================================================================== */
html:has(body.cs-skin) { overflow-x: clip; }
body.cs-skin { overflow-x: clip; }
