/* ==========================================================================
   Belmont Group — belmontgroup.llc
   Tokens and the .bp corner-mark motif come from the "Industry" design system
   shipped with the Claude Design source (design-source/.../_ds/styles.css).
   Plain CSS, no build step — drops straight into the Apache DocumentRoot.
   ========================================================================== */

/* --- tokens ------------------------------------------------------------- */
:root {
  --color-bg:      #f2f2f3;
  --color-surface: #e9e9ea;
  --color-text:    #1d1f20;
  --color-accent:  #5980a6;
  --color-divider: rgba(29, 31, 32, .16);
  --color-muted:   rgba(29, 31, 32, .55);

  --color-accent-600: #597ea3;
  --color-accent-700: #416180;
  --color-accent-900: #1d2d3d;
  --color-danger:     #a04040;

  --font-heading: "Barlow Condensed", "Barlow", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body:    "Barlow", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --wrap:  1160px;
  --gutter: 24px;

  /* Single source of truth for the sticky header — JS keeps it in sync with
     the real measured height so scroll-margin can never drift out of step. */
  --header-h: 66px;

  --ease: cubic-bezier(.16, 1, .3, 1);
  --dur:  .6s;

  --mark-color: var(--color-muted);
}

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

html {
  scroll-behavior: smooth;
  /* Anchors land clear of the sticky header instead of under it. */
  scroll-padding-top: calc(var(--header-h) + 24px);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }
img { height: auto; }

/* A class that sets `display` outdranks the UA's [hidden] rule on
   specificity, which would leave hidden panels (and the submitted form)
   on screen. Make the attribute win wherever it is used. */
[hidden] { display: none !important; }

h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -.015em;
  margin: 0;
  text-wrap: balance;
}

h1 { font-size: clamp(32px, 5.2vw, 44px); letter-spacing: -.02em; }
h2 { font-size: clamp(25px, 3.4vw, 28px); margin-bottom: 20px; }
h2.tight { margin-bottom: 8px; }

p { margin: 0; text-wrap: pretty; }

a { color: var(--color-accent); text-decoration: none; }
a:hover { color: var(--color-accent-700); }

::selection { background: rgba(89, 128, 166, .3); }

:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 100;
  background: var(--color-accent); color: var(--color-bg);
  padding: 10px 16px; font-family: var(--font-heading);
  font-weight: 600; font-size: 14px;
  transition: top .2s var(--ease);
}
.skip-link:focus-visible { top: 12px; color: var(--color-bg); }

/* --- layout ------------------------------------------------------------- */
.wrap {
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section  { padding-block: clamp(64px, 9vw, 96px); }
/* The design tucks "How I Work" up under the hero (24px top, 96px bottom)
   rather than giving it the full section rhythm. */
#how-i-work { padding-top: 24px; }
/* Four cards, not three. At the 1112px content width a plain auto-fit would
   land exactly four 260px columns — cramped, and a pixel from reflowing.
   A 380px floor forces a deliberate 2x2 on desktop and degrades to 1-up. */
#how-i-work .grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); }
.band     { background: var(--color-surface); }
.band-inner { padding-block: clamp(64px, 9vw, 96px); }

.band-dark {
  background: var(--color-accent-900);
  color: var(--color-bg);
  --mark-color: rgba(242, 242, 243, .55);
  --color-divider: rgba(242, 242, 243, .22);
}
.band-dark .band-inner { padding-block: clamp(56px, 7vw, 72px); }
.band-dark .eyebrow { border-color: rgba(242, 242, 243, .6); color: rgba(242, 242, 243, .85); }
.band-lede {
  font-size: clamp(18px, 2.4vw, 22px);
  line-height: 1.55;
  max-width: 760px;
}

.grid { display: grid; gap: 24px; }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

.section-lede {
  font-size: 17px; line-height: 1.6;
  max-width: 720px; opacity: .85;
  margin-bottom: 40px;
}
.section-note { font-size: 14px; color: var(--color-muted); margin-bottom: 40px; }

/* --- blueprint corner marks --------------------------------------------
   The design draws four crosshairs just outside each hairline box. The
   source markup used four nested <span> pairs per box (eight elements);
   one pseudo-element with eight gradient layers gives the identical result
   with zero extra DOM, and inherits --mark-color per context.
   ----------------------------------------------------------------------- */
.bp { position: relative; border: 1px solid var(--color-divider); }

.bp::after {
  content: "";
  position: absolute; inset: -6px;
  pointer-events: none;
  background-repeat: no-repeat;
  background-image:
    linear-gradient(var(--mark-color) 0 0), linear-gradient(var(--mark-color) 0 0),
    linear-gradient(var(--mark-color) 0 0), linear-gradient(var(--mark-color) 0 0),
    linear-gradient(var(--mark-color) 0 0), linear-gradient(var(--mark-color) 0 0),
    linear-gradient(var(--mark-color) 0 0), linear-gradient(var(--mark-color) 0 0);
  background-size: 1px 11px, 11px 1px, 1px 11px, 11px 1px,
                   1px 11px, 11px 1px, 1px 11px, 11px 1px;
  background-position:
    left 5px top 0,     left 0 top 5px,
    right 5px top 0,    right 0 top 5px,
    left 5px bottom 0,  left 0 bottom 5px,
    right 5px bottom 0, right 0 bottom 5px;
  transition: opacity .3s var(--ease);
}

/* --- header ------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--color-bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--color-divider);
  transition: box-shadow .3s var(--ease), background .3s var(--ease);
}
@supports not (backdrop-filter: blur(1px)) {
  .site-header { background: var(--color-bg); }
}
.site-header.is-scrolled { box-shadow: 0 1px 16px rgba(29, 31, 32, .09); }

.nav {
  display: flex; align-items: center; gap: 32px;
  padding-block: 18px;
  transition: padding-block .3s var(--ease);
}
.site-header.is-scrolled .nav { padding-block: 11px; }

.nav-brand {
  display: inline-flex; align-items: center; gap: 10px;
  margin-right: auto; color: var(--color-text);
  font-family: var(--font-heading); font-weight: 600;
  font-size: 19px; letter-spacing: .02em;
}
.nav-brand:hover { color: var(--color-text); }
.brand-mark {
  width: 9px; height: 9px; flex-shrink: 0;
  background: var(--color-accent);
  transition: transform .4s var(--ease);
}
.nav-brand:hover .brand-mark { transform: rotate(45deg); }

.nav-menu { display: flex; }
.nav-menu-inner { display: flex; align-items: center; gap: 24px; }
.nav-menu a:not(.btn) {
  position: relative;
  font-size: 14px; color: var(--color-text);
  padding-block: 4px;
}
/* Underline grows from the left on hover and stays put for the section
   the reader is currently inside. */
.nav-menu a:not(.btn)::after {
  content: "";
  position: absolute; left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--color-accent);
  transform: scaleX(0); transform-origin: left;
  transition: transform .3s var(--ease);
}
.nav-menu a:not(.btn):hover,
.nav-menu a:not(.btn)[aria-current="true"] { color: var(--color-accent); }
.nav-menu a:not(.btn):hover::after,
.nav-menu a:not(.btn)[aria-current="true"]::after { transform: scaleX(1); }

.nav-toggle {
  display: none;
  background: none; border: 1px solid var(--color-divider);
  padding: 9px 10px; cursor: pointer; color: inherit;
}
.nav-toggle-bars { display: block; width: 18px; }
.nav-toggle-bars span {
  display: block; height: 1px; background: currentColor;
  transition: transform .3s var(--ease), opacity .2s var(--ease);
}
.nav-toggle-bars span + span { margin-top: 5px; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:first-child { transform: translateY(3px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars span:last-child  { transform: translateY(-3px) rotate(-45deg); }

/* --- buttons ------------------------------------------------------------ */
.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-heading); font-weight: 600; font-size: 14px;
  line-height: 1.2; cursor: pointer;
  padding: 9px 18px;
  border: 1px solid transparent; border-radius: 0;
  background: transparent; color: var(--color-text);
  transition: background .2s var(--ease), color .2s var(--ease),
              transform .2s var(--ease), border-color .2s var(--ease);
}
.btn-lg { padding: 13px 24px; font-size: 15px; }

.btn-primary {
  --mark-color: rgba(242, 242, 243, .7);
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-bg);
}
.btn-primary::after {
  content: "";
  position: absolute; inset: -6px;
  pointer-events: none;
  background-repeat: no-repeat;
  background-image:
    linear-gradient(var(--mark-color) 0 0), linear-gradient(var(--mark-color) 0 0),
    linear-gradient(var(--mark-color) 0 0), linear-gradient(var(--mark-color) 0 0),
    linear-gradient(var(--mark-color) 0 0), linear-gradient(var(--mark-color) 0 0),
    linear-gradient(var(--mark-color) 0 0), linear-gradient(var(--mark-color) 0 0);
  background-size: 1px 11px, 11px 1px, 1px 11px, 11px 1px,
                   1px 11px, 11px 1px, 1px 11px, 11px 1px;
  background-position:
    left 5px top 0,     left 0 top 5px,
    right 5px top 0,    right 0 top 5px,
    left 5px bottom 0,  left 0 bottom 5px,
    right 5px bottom 0, right 0 bottom 5px;
}
/* Hairline, no corner marks — the marks stay a primary-action signal. */
.btn-secondary {
  border-color: var(--color-divider);
  color: var(--color-text);
}
.btn-secondary:hover {
  background: rgba(29, 31, 32, .06);
  border-color: rgba(29, 31, 32, .38);
  color: var(--color-text);
  transform: translateY(-1px);
}
.btn-secondary:active { background: rgba(29, 31, 32, .12); transform: translateY(0); }
.btn-secondary svg { transition: transform .3s var(--ease); }
.btn-secondary:hover svg { transform: translateX(3px); }

.btn-primary:hover {
  background: var(--color-accent-600);
  border-color: var(--color-accent-600);
  color: var(--color-bg);
  transform: translateY(-1px);
}
.btn-primary:active { background: var(--color-accent-700); transform: translateY(0); }
.btn-primary svg { transition: transform .3s var(--ease); }
.btn-primary:hover svg { transform: translateX(3px); }

.link-quiet {
  font-size: 14px; color: var(--color-accent);
  padding: 8px 0;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px; background-position: 0 88%;
  background-repeat: no-repeat;
  transition: background-size .3s var(--ease);
}
.link-quiet:hover { background-size: 100% 1px; }

/* --- splash --------------------------------------------------------------
   The summary that stands in for the page until the visitor asks for the rest.

   It covers the page rather than replacing it: the real page stays in the
   document, laid out and measurable, and only html.splash-on — set by the
   inline script before first paint — puts this over the top of it. Hiding
   main behind display:none would have been simpler and would have meant
   handing a crawler a page whose entire content is hidden, which is not a
   trade a marketing site should make. Focus is kept out with inert instead,
   which costs a crawler nothing.

   Hidden outright by default, so with JavaScript off it never appears.
   ------------------------------------------------------------------------ */
.splash { display: none; }

html.splash-on .splash {
  display: flex;
  position: fixed; inset: 0; z-index: 60;
  background: var(--color-bg);
  padding-block: clamp(32px, 6vh, 72px);
  /* Small screens: the summary is allowed to scroll inside its own cover. */
  overflow-y: auto;
  /* Not align-items: center. On a phone the summary is taller than the
     viewport, and centring overflow puts the wordmark and half the heading
     above the top of the scroll range, where nothing can bring them back.
     An auto margin centres exactly the same way when there is room to spare,
     and collapses to zero when there is not. */
  align-items: flex-start;
}
html.splash-on .splash-inner { margin-block: auto; }

/* The page behind must not scroll under the cover. */
html.splash-on body { overflow: hidden; }

.splash-inner {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: clamp(32px, 5vw, 64px);
  width: 100%;
  animation: splash-in .5s var(--ease) both;
}
@keyframes splash-in {
  from { opacity: 0; transform: translateY(12px); }
}

.splash-copy { flex: 1 1 460px; min-width: 0; }

/* flex, not inline-flex: the eyebrow below is itself inline-flex and would
   otherwise sit on the same line as the wordmark. */
.splash-brand {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 30px;
  font-family: var(--font-heading); font-weight: 600;
  font-size: 19px; letter-spacing: .02em;
}

.splash .lede {
  font-size: 17px; line-height: 1.6; max-width: 620px;
  opacity: .85; margin-block: 20px 30px;
}

/* Tighter than a section list: this is a scan, not a read. Qualified with
   .splash because .ticklist sets the same properties further down the file
   and would otherwise win on equal specificity. */
.splash .splash-points { gap: 14px; max-width: 660px; }
.splash .splash-points li { font-size: 15px; }
.splash .splash-points strong {
  font-family: var(--font-heading); font-weight: 600;
  font-size: 16px; color: var(--color-accent);
}

.splash-actions { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 34px; }
/* The chevron points down the page, where the button is about to take you —
   whichever weight the button is wearing. */
.splash-actions .splash-cta-all:hover svg { transform: translateY(2px); }
/* The second pair is a phone affordance; on a wider screen one pair is the
   whole story and a repeat would just be clutter above the fold. */
.splash-actions-repeat { display: none; }

.splash-note {
  margin-top: 26px; max-width: 580px;
  font-size: 13px; color: var(--color-muted);
}

.splash-figure { flex: 0 0 280px; margin: 0; max-width: 100%; }
.splash-figure figcaption { font-size: 11px; margin-top: 8px; color: var(--color-muted); }

@media (max-width: 860px) {
  /* Below the width where the portrait and the copy stop fitting side by
     side, the summary takes a different composition rather than a narrower
     one: the portrait becomes a thumbnail beside the opening paragraph, one
     button stands above the fold, and the pair repeats under the four points.
     It widens from here down to the smallest phone without changing shape —
     the alternative, stacking a full-size portrait under everything, put the
     face last on exactly the screens where it arrives first.

     A grid, because the portrait has to sit beside the paragraph and the two
     are not siblings — the paragraph lives inside .splash-copy. display:
     contents dissolves that box so its children take part in this grid
     directly, alongside the portrait. It carries no semantics to lose. */
  .splash-inner {
    display: grid;
    /* Grows with the viewport, within reason: a thumbnail on a phone, a
       small portrait on a tablet. */
    grid-template-columns: clamp(112px, 20vw, 148px) minmax(0, 1fr);
    gap: 0 18px;
    align-items: start;
  }
  .splash-copy { display: contents; }

  /* Placement order, since the portrait comes last in the markup and belongs
     fourth here. Everything but the portrait and the paragraph spans both
     columns. */
  .splash-brand          { order: 1; grid-column: 1 / -1; margin-bottom: 22px; }
  .splash .eyebrow       { order: 2; grid-column: 1 / -1; }
  .splash h1             { order: 3; grid-column: 1 / -1; margin-bottom: 24px; }
  .splash-figure         { order: 4; grid-column: 1; }
  .splash .lede          { order: 5; grid-column: 2; margin-block: 0; }
  .splash-actions        { order: 6; grid-column: 1 / -1; margin-top: 28px; }
  .splash .splash-points { order: 7; grid-column: 1 / -1; margin-top: 30px; }
  .splash-actions-repeat { order: 8; grid-column: 1 / -1; display: flex; margin-top: 30px; }
  .splash-note           { order: 9; grid-column: 1 / -1; margin-top: 24px; }

  /* One decision above the fold, and it is the one that opens the page.
     Get in Touch is two taps away in the pair below the points, and one tap
     away on the page this button opens. */
  .splash-actions:not(.splash-actions-repeat) .splash-cta-contact { display: none; }

  /* Centred in its row rather than pinned to the top: the paragraph beside it
     is usually the taller of the two, and a portrait floating at the top of a
     column of empty space looks like a mistake rather than a decision. */
  .splash-figure { max-width: none; align-self: center; }

  /* Capped narrower than the column it sits in, so the caption always breaks
     after the name instead of taking "Mark Laurent, Principal" on the first
     line and leaving "Consultant" on its own. Two lines, on purpose. */
  .splash-figure figcaption {
    /* Two lines, breaking after the name. Both halves of that: balance picks
       the evener of the two possible breaks — 13 characters against 20, not
       23 against 10 — and the cap makes the same choice for a browser that
       does not know the property, by leaving "Mark Laurent, Principal" no
       room to fit on one line. */
    max-width: 104px;
    text-wrap: balance;
    margin-top: 10px;
    line-height: 1.35;
  }
}

@media (max-width: 560px) {
  /* Phone-only trims. Everything structural is in the block above. */
  .splash .lede { font-size: 15px; }
  .splash .splash-points li { font-size: 14px; }
}

/* --- hero --------------------------------------------------------------- */
.hero {
  display: flex; gap: 56px; flex-wrap: wrap; align-items: center;
  padding-block: clamp(56px, 8vw, 80px) clamp(64px, 9vw, 96px);
}
.hero-copy { flex: 1 1 420px; min-width: 0; }
.hero .lede {
  font-size: 17px; line-height: 1.6; max-width: 560px;
  opacity: .85; margin-block: 20px 24px;
}
.hero h1 { max-width: 560px; }

/* The AI note is a second lede, not a third paragraph: the accent rule and the
   accent lead-in are what stop it reading as more of the same prose. */
.hero-ai {
  font-size: 15px; line-height: 1.6; max-width: 560px;
  border-left: 2px solid var(--color-accent);
  padding-left: 16px; margin-block: 0 32px;
}
.hero-ai strong {
  font-family: var(--font-heading); font-weight: 600;
  font-size: 16px; color: var(--color-accent);
}
.hero-actions { display: flex; gap: 16px; flex-wrap: wrap; align-items: center; }

.eyebrow {
  display: inline-flex;
  border: 1px solid var(--color-accent);
  color: var(--color-accent);
  font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  padding: 4px 10px; margin-bottom: 20px;
}

.hero-figure { flex: 0 0 300px; margin: 0; max-width: 100%; }
.portrait-inner { position: relative; overflow: hidden; aspect-ratio: 4 / 5; }
.portrait-inner img { width: 100%; height: 100%; object-fit: cover; }
/* The design toned the portrait to the accent blue and an earlier pass tried
   a light sepia. Both are gone: the photograph shows as shot. */
.hero-figure figcaption { font-size: 11px; margin-top: 8px; color: var(--color-muted); }

/* --- cards -------------------------------------------------------------- */
.card {
  display: flex; flex-direction: column; gap: 12px;
  padding: 28px; background: transparent;
  transition: transform .35s var(--ease), border-color .35s var(--ease);
}
.card-lg { padding: 32px; }
.card:hover { transform: translateY(-3px); border-color: rgba(89, 128, 166, .55); }
.card:hover::after { opacity: .75; }

.card-icon { color: var(--color-accent); }
.card-kicker { font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: var(--color-accent); }
.card-title {
  font-family: var(--font-heading); font-weight: 600;
  font-size: 19px; line-height: 1.25; letter-spacing: 0;
}
.card-title-lg { font-size: 22px; }
.card-meta { font-size: 12px; color: var(--color-muted); }
.card-body { font-size: 14px; opacity: .8; }

/* --- accordion ---------------------------------------------------------- */
.accordion { border-top: 1px solid var(--color-divider); }

.acc-item {
  position: relative;
  border-bottom: 1px solid var(--color-divider);
  transition: background .35s var(--ease);
}

/* The open item is tinted, and the tint bleeds 12px past the text column on
   both sides so it reads as a highlighted row rather than as a box drawn
   tightly around the words. Offset shadows rather than padding or margin:
   nothing here may move the text, which is aligned with the section heading
   above it. */
.acc-item.is-open {
  background: rgba(89, 128, 166, .06);
  box-shadow: -12px 0 0 rgba(89, 128, 166, .06), 12px 0 0 rgba(89, 128, 166, .06);
}
/* An accent edge that grows down the left as the item opens, drawn in the
   bleed so it never indents the content. */
.acc-item::before {
  content: "";
  position: absolute; left: -12px; top: 0; bottom: 0; width: 2px;
  background: var(--color-accent);
  transform: scaleY(0); transform-origin: top;
  transition: transform .35s var(--ease);
}
.acc-item.is-open::before { transform: scaleY(1); }

.acc-h { margin: 0; font: inherit; }

.acc-trigger {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; width: 100%;
  padding: 20px 4px; cursor: pointer; text-align: left;
  background: none; border: 0; color: var(--color-text);
  font-family: var(--font-heading); font-weight: 600; font-size: 18px;
  transition: color .2s var(--ease);
}
.acc-trigger:hover,
.acc-item.is-open > .acc-h > .acc-trigger { color: var(--color-accent); }
.acc-chev {
  flex-shrink: 0; color: var(--color-accent);
  transition: transform .3s var(--ease);
}
.acc-trigger[aria-expanded="true"] .acc-chev { transform: rotate(180deg); }

/* 0fr -> 1fr animates cleanly without measuring heights in JS. */
.acc-panel {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .35s var(--ease);
}
.acc-panel > .acc-inner { overflow: hidden; }
.acc-item.is-open > .acc-panel { grid-template-rows: 1fr; }

/* Room between the answer and the rule under it — on the last child, not on
   .acc-inner, because padding on the element the grid is holding at zero
   height is not held at zero with it: border-box keeps it and every closed
   item carries the gap. That is exactly what used to happen, via the 24px
   .ticklist reserved for this. */
.acc-inner > :last-child { padding-bottom: 26px; }

.ticklist {
  list-style: none; margin: 0;
  padding: 0 4px;
  display: flex; flex-direction: column; gap: 10px;
}
.ticklist li {
  display: flex; gap: 10px; align-items: flex-start;
  font-size: 15px; line-height: 1.5;
}
/* The stagger belongs to the accordion, where items arrive as a panel opens.
   Scoped to .acc-panel because a list anywhere else — a wiki section, the
   lightbox, the splash — has nothing to open it, and an unscoped opacity: 0
   left those permanently invisible. */
.acc-panel .ticklist li {
  opacity: 0; transform: translateY(6px);
  transition: opacity .4s var(--ease), transform .4s var(--ease);
}
.acc-item.is-open .ticklist li { opacity: 1; transform: none; }
.acc-item.is-open .ticklist li:nth-child(2) { transition-delay: .06s; }
.acc-item.is-open .ticklist li:nth-child(3) { transition-delay: .12s; }
.ticklist li::before {
  content: ""; flex-shrink: 0;
  width: 6px; height: 6px; margin-top: 8px;
  background: var(--color-accent);
}

/* --- contact ------------------------------------------------------------ */
.contact { display: flex; gap: 56px; flex-wrap: wrap; padding-block: clamp(64px, 9vw, 96px); }
.contact-intro { flex: 1 1 320px; }
.contact-intro .section-lede { max-width: 420px; margin-bottom: 24px; }
.contact-form-wrap { flex: 2 1 420px; min-width: 0; }

.contact-form { display: flex; flex-direction: column; gap: 18px; }
.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 18px; }
.field > label {
  display: block; font-size: 12px; margin-bottom: 5px;
  color: rgba(29, 31, 32, .7);
}
.input {
  width: 100%; min-height: 38px;
  padding: 8px 10px; font: inherit; font-size: 14px;
  color: var(--color-text); caret-color: var(--color-accent);
  background: var(--color-bg);
  border: 1px solid var(--color-divider); border-radius: 0;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.input:hover { border-color: rgba(29, 31, 32, .45); }
.input:focus-visible {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(89, 128, 166, .18);
}
.input[aria-invalid="true"] { border-color: var(--color-danger); }
textarea.input { resize: vertical; min-height: 100px; }

/* Off-screen rather than display:none — see the note in index.html. */
.hp-field {
  position: absolute !important;
  left: -9999px; top: auto;
  width: 1px; height: 1px; overflow: hidden;
}

.field-error, .form-error { font-size: 12px; color: var(--color-danger); margin-top: 4px; }

.contact-form .btn-primary { align-self: flex-start; }
.btn[aria-busy="true"] { opacity: .7; pointer-events: none; }

.sent-panel {
  display: flex; flex-direction: column; gap: 16px; align-items: flex-start;
  padding: 40px; color: var(--color-accent);
}
.sent-panel > :not(svg) { color: var(--color-text); }
.sent-panel .btn-primary { color: var(--color-bg); }
.sent-title { font-family: var(--font-heading); font-weight: 600; font-size: 20px; }

/* --- footer ------------------------------------------------------------- */
.site-footer { border-top: 1px solid var(--color-divider); }
.footer-inner {
  display: flex; justify-content: space-between; flex-wrap: wrap;
  gap: 12px; padding-block: 24px;
  font-size: 12px; color: var(--color-muted);
}
.footer-inner a { color: var(--color-muted); }
.footer-inner a:hover { color: var(--color-accent); }

/* The referral ask takes its own row above the colophon rather than joining
   the space-between run, so it reads as a sentence and not a third column. */
.footer-referral { flex-basis: 100%; margin-bottom: 4px; }
.footer-referral a { color: var(--color-accent); }
.footer-referral a:hover { color: var(--color-accent-700); }

/* --- portfolio examples -------------------------------------------------
   Alternating copy/media rows. The media column is wider than the copy one
   because these are screenshots being read, not decoration beside a headline.
   ------------------------------------------------------------------------ */
.folio-section { border-top: 1px solid var(--color-divider); }

.folio {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 6fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
  padding-block: clamp(40px, 5vw, 64px);
  border-bottom: 1px solid var(--color-divider);
}
.folio:last-child { border-bottom: 0; padding-bottom: 0; }

/* Mirror every other row so the page does not read as a single column of
   screenshots with captions hanging off the same edge. nth-of-type, not
   nth-child: the section's heading and note are children too, so nth-child
   would flip the whole sequence if either were ever removed. */
.folio:nth-of-type(even) > .folio-copy { order: 2; }

.folio-copy .card-title-lg { margin-block: 6px 12px; }
.folio-copy .card-body { font-size: 15px; }

.folio-media { display: grid; gap: 16px; min-width: 0; }
/* The CRM row carries three shots: a lead image, then two beneath it. */
.folio-media-stack { grid-template-columns: 1fr 1fr; }
.folio-shot-lead { grid-column: 1 / -1; }

.folio-shot { margin: 0; overflow: hidden; background: var(--color-surface); }
.folio-shot img { width: 100%; height: auto; display: block; }

.folio-pending {
  display: grid; place-items: center;
  min-height: 200px; padding: 24px;
  background: var(--color-surface);
}
.folio-pending span {
  font-family: var(--font-heading); font-size: 12px;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--color-muted);
}

@media (max-width: 760px) {
  .folio { grid-template-columns: 1fr; }
  /* Copy first on every row once stacked — alternating order only makes
     sense side by side. */
  .folio:nth-of-type(even) > .folio-copy { order: 0; }
}

/* --- wiki-rendered sections ---------------------------------------------
   The body sections are authored in the markup lib/wiki.js parses, so these
   rules dress its output. Everything reuses the existing card, grid and
   ticklist vocabulary — the wiki chooses which blocks appear, never how they
   look.
   ------------------------------------------------------------------------ */
.wiki-body > * + * { margin-top: 24px; }
.wiki-body > .grid + .grid { margin-top: 24px; }

.wiki-p {
  font-size: 17px; line-height: 1.6; max-width: 720px; opacity: .85;
}
.band-dark .wiki-p { font-size: clamp(18px, 2.4vw, 22px); line-height: 1.55; max-width: 760px; opacity: 1; }

.wiki-h {
  font-family: var(--font-heading); font-weight: 600; line-height: 1.15;
  letter-spacing: -.015em; font-size: 22px;
}
.wiki-body h3.wiki-h { font-size: 22px; }
.wiki-body h4.wiki-h { font-size: 18px; }

.wiki-rule { border: 0; border-top: 1px solid var(--color-divider); margin-block: 8px; }

.wiki-space.is-sm { height: 8px; }
.wiki-space.is-md { height: 24px; }
.wiki-space.is-lg { height: 48px; }
.wiki-space.is-xl { height: 80px; }

/* The author picked a column count, so honour it and step down at breakpoints
   rather than letting auto-fit quietly choose a different one — a two-column
   grid reflowing to three is a layout the editor did not ask for. */
.grid-w2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-w3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-w4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 980px) {
  .grid-w3, .grid-w4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .grid-w2, .grid-w3, .grid-w4 { grid-template-columns: minmax(0, 1fr); }
}

.card > .card-body > .wiki-p { font-size: 14px; opacity: 1; max-width: none; }
.card > .card-body > * + * { margin-top: 10px; }
.card-lg > .card-body > .wiki-p { font-size: 15px; }

.wiki-list { margin-top: 14px; }
.acc-panel .wiki-list { margin-top: 0; }
.wiki-section h2 { margin-bottom: 20px; }
.wiki-body .accordion { margin-top: 8px; }

/* Rows: the alternating copy/media layout, now authored rather than hardcoded.
   is-flipped puts the picture first instead of relying on nth-of-type, so
   adding or removing a row cannot silently reverse every one below it. */
.wiki-row { border-bottom: 0; padding-block: clamp(24px, 3vw, 40px); }
.wiki-row + .wiki-row { border-top: 1px solid var(--color-divider); }
.wiki-row.is-flipped > .folio-copy { order: 2; }
.wiki-row.is-copy-only { grid-template-columns: minmax(0, 1fr); }
.wiki-row .folio-copy > * + * { margin-top: 10px; }
.wiki-row .folio-copy .wiki-p { font-size: 15px; }

.wiki-image { margin: 0; }
.wiki-image.is-half { max-width: 50%; }
.wiki-image.is-inline { max-width: 320px; }
.wiki-caption { font-size: 12px; color: var(--color-muted); margin-top: 8px; }

/* A slug that no longer resolves shows as an explicit gap. Silently dropping
   it would hide a broken reference until someone happened to look. */
.wiki-image-missing {
  display: grid; place-items: center; min-height: 140px; padding: 20px;
  background: var(--color-surface); color: var(--color-muted); font-size: 13px;
}

/* Full-bleed band inside a wrapped section. */
.wiki-band {
  width: 100vw; margin-inline: calc(50% - 50vw);
  background: var(--color-surface);
}
.wiki-band.is-dark {
  background: var(--color-accent-900); color: var(--color-bg);
  --mark-color: rgba(242, 242, 243, .55);
  --color-divider: rgba(242, 242, 243, .22);
}
.wiki-band-inner {
  max-width: var(--wrap); margin-inline: auto;
  padding: clamp(40px, 6vw, 64px) var(--gutter);
}
.wiki-band-inner > * + * { margin-top: 20px; }

@media (max-width: 760px) {
  .wiki-row.is-flipped > .folio-copy { order: 0; }
  .wiki-image.is-half { max-width: 100%; }
}

/* --- testimonial carousel ------------------------------------------------
   Authored as {carousel} / {quote} in a section body. The slides are stacked
   in one grid cell so the block is as tall as its tallest quote and never
   jumps as it advances — but only once .js is set, because with JavaScript
   off there is nothing to advance them and they have to read as a plain list.
   ------------------------------------------------------------------------ */
.tcar { position: relative; }
.tcar-stage { display: grid; gap: 32px; }
.js .tcar-stage > .tcar-slide { grid-area: 1 / 1; }

.tcar-slide { margin: 0; max-width: 900px; }

.js .tcar-stage > .tcar-slide {
  opacity: 0; visibility: hidden;
  transform: translateY(10px);
  transition: opacity .55s var(--ease), transform .55s var(--ease),
              visibility 0s linear .55s;
}
.js .tcar-stage > .tcar-slide.is-current {
  opacity: 1; visibility: visible;
  transform: none;
  transition-delay: 0s;
}

.tcar-quote { margin: 0; }
.tcar-quote .wiki-p {
  font-size: clamp(19px, 2.4vw, 24px);
  line-height: 1.5;
  max-width: none;
  opacity: 1;
}
/* The opening mark hangs into the gutter so the quotation still reads as one
   from the left edge, without an oversized decorative glyph. */
.tcar-quote > .wiki-p:first-child::before { content: "\201C"; margin-left: -.44em; }
.tcar-quote > .wiki-p:last-child::after { content: "\201D"; }

.tcar-by {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  margin-top: 20px;
  font-family: var(--font-heading);
  font-size: 13px; letter-spacing: .08em; text-transform: uppercase;
}
.tcar-name { color: var(--color-accent); font-weight: 600; }
.tcar-name::before { content: "\2014\00a0"; color: var(--color-muted); }
.tcar-role { color: var(--color-muted); }

.tcar-nav { display: flex; align-items: center; gap: 16px; margin-top: 32px; }

.tcar-arrow {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; cursor: pointer;
  background: none; color: var(--color-text);
  border: 1px solid var(--color-divider); border-radius: 0;
  transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.tcar-arrow:hover {
  background: rgba(29, 31, 32, .06);
  border-color: rgba(29, 31, 32, .38);
  color: var(--color-accent);
}

.tcar-dots { display: flex; align-items: center; gap: 9px; }
.tcar-dot {
  width: 9px; height: 9px; padding: 0; cursor: pointer;
  background: none; border: 1px solid var(--color-divider); border-radius: 0;
  transition: background .25s var(--ease), border-color .25s var(--ease),
              transform .25s var(--ease);
}
.tcar-dot:hover { border-color: var(--color-accent); }
.tcar-dot.is-current {
  background: var(--color-accent);
  border-color: var(--color-accent);
  transform: rotate(45deg);
}

/* Dots and arrows are JavaScript controls; with none running they would be
   three inert boxes under a list of quotes. */
html:not(.js) .tcar-nav { display: none; }

/* --- lightbox modal -----------------------------------------------------
   Authored as {modal} inside whichever section owns the button, so the panel
   copy is edited in the same textarea as everything around it. <dialog> owns
   the backdrop, the focus trap and Escape; main.js only opens and closes it.
   ------------------------------------------------------------------------ */
.modal {
  width: min(760px, calc(100vw - 32px));
  max-width: none; padding: 0; margin: auto;
  background: transparent; border: 0; color: var(--color-text);
}
/* The page is blurred rather than merely dimmed, so the panel reads as being
   in front of the site instead of on top of a grey sheet. The colour layer
   stays: a blur alone leaves light text unreadable over light content, and a
   browser without backdrop-filter still needs the contrast. */
.modal::backdrop {
  background: rgba(29, 31, 32, .42);
  backdrop-filter: blur(7px) saturate(115%);
  -webkit-backdrop-filter: blur(7px) saturate(115%);
}

.modal-inner {
  position: relative;
  background: var(--color-bg);
  /* The accent edge gives the panel a top the corner marks alone do not. */
  border-top: 2px solid var(--color-accent);
  box-shadow: 0 30px 70px rgba(29, 31, 32, .3);
  padding: clamp(28px, 4vw, 44px);
  max-height: min(84vh, 900px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Arriving, rather than appearing. The motion guard flattens both. */
.modal[open] { animation: modal-in .3s var(--ease) both; }
.modal[open]::backdrop { animation: modal-backdrop-in .35s var(--ease) both; }
@keyframes modal-in {
  from { opacity: 0; transform: translateY(16px) scale(.985); }
}
@keyframes modal-backdrop-in {
  from { opacity: 0; }
}

.modal-close {
  position: absolute; top: 10px; right: 10px;
  display: inline-flex; padding: 6px; cursor: pointer;
  background: none; border: 0; color: var(--color-muted);
  transition: color .2s var(--ease);
}
.modal-close:hover { color: var(--color-accent); }

.modal-title {
  font-size: clamp(23px, 3vw, 27px);
  margin-bottom: 24px; padding-right: 32px;
}
/* A short accent rule under the title, the same mark the eyebrow uses
   elsewhere, so the panel belongs to the same page. */
.modal-title::after {
  content: "";
  display: block; width: 46px; height: 2px;
  margin-top: 16px;
  background: var(--color-accent);
}

.modal-body > * + * { margin-top: 18px; }
.modal-body .wiki-p { font-size: 15px; max-width: none; }

/* Each heading opens a new part of the panel, so give it a rule and the
   accent — a long lightbox needs somewhere for the eye to land. */
.modal-body .wiki-h {
  font-size: 13px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--color-accent);
}
.modal-body .wiki-h + * { margin-top: 12px; }
.modal-body .wiki-h:not(:first-child) {
  margin-top: 28px; padding-top: 24px;
  border-top: 1px solid var(--color-divider);
}
.modal-body .wiki-list { margin-top: 0; }
.modal-body .ticklist li { font-size: 14px; }

/* The opener carries the accent rather than the hairline every other
   secondary button wears: inside a card of body copy it has to read as the
   one thing on offer, without being promoted to a primary button and
   competing with the page's own call to action. It fills in on hover, which
   is the promotion — at the moment of intent. */
.btn.modal-open {
  border-color: var(--color-accent);
  color: var(--color-accent);
  background: rgba(89, 128, 166, .07);
}
.btn.modal-open:hover {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-bg);
  transform: translateY(-1px);
}
.btn.modal-open:active { background: var(--color-accent-700); transform: translateY(0); }
.btn.modal-open svg { transition: transform .3s var(--ease); }
.btn.modal-open:hover svg { transform: translateX(3px); }

/* A button inside a card needs to sit apart from the copy above it. */
.card-body > .modal-open { margin-top: 10px; align-self: flex-start; }

/* With no JavaScript the button cannot open anything, so the panel is shown
   in place instead — unstyled as a lightbox, but readable. */
html:not(.js) .modal-open { display: none; }
html:not(.js) dialog.modal {
  display: block; position: static;
  width: auto; margin: 20px 0 0;
}
html:not(.js) .modal-close { display: none; }

/* --- reveal on scroll ---------------------------------------------------
   Gated behind .js so the page is fully readable with JavaScript disabled.
   ------------------------------------------------------------------------ */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
  transition-delay: calc(var(--i, 0) * 70ms);
  will-change: opacity, transform;
}
.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* --- responsive --------------------------------------------------------- */
@media (max-width: 860px) {
  .nav { gap: 16px; flex-wrap: wrap; }
  .nav-toggle { display: inline-flex; }

  .nav-menu {
    flex-basis: 100%;
    display: grid; grid-template-rows: 0fr;
    transition: grid-template-rows .35s var(--ease);
  }
  .nav-menu.is-open { grid-template-rows: 1fr; }
  .nav-menu-inner {
    overflow: hidden;
    flex-direction: column; align-items: stretch; gap: 0;
    min-width: 0;
  }

  /* :not(.btn) matters — this rule used to hit the Contact button too, and
     2px of horizontal padding jammed its label against its own border. */
  .nav-menu a:not(.btn) {
    padding: 13px 2px;
    border-top: 1px solid var(--color-divider);
  }
  .nav-menu a:not(.btn)::after { display: none; }

  .nav-menu a.btn {
    align-self: flex-start;
    margin: 18px 0 20px;
    padding: 13px 26px;
  }
}

@media (max-width: 560px) {
  :root { --gutter: 20px; }
  .hero, .contact { gap: 40px; }
  .hero-figure { flex-basis: 100%; max-width: 280px; }
  .card { padding: 24px; }
  .sent-panel { padding: 28px; }
}

/* --- motion guard ------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
  .js [data-reveal] { opacity: 1; transform: none; }
  .ticklist li { opacity: 1; transform: none; }
}
