/* ═══════════════════════════════════════════════════════════════════════
   New Bloom — newbloom.world, rebuilt

   Measured off the live site rather than eyeballed: the palette, the type
   sizes and the two hover transitions are the numbers the browser actually
   reported, not approximations of them.

   The real site is Framer, which means every value below is a fixed pixel
   number baked in at one breakpoint. Rebuilding gives the chance to make the
   display type fluid instead, so the wordmark fills the frame at any width
   rather than at three chosen ones.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* Sampled from the live page. The green is the whole identity and it is
     used exactly twice at size: the wordmark and the buttons. */
  --green: #9bde64;
  --green-deep: #8ad14f;
  --ink: #090909;
  --ink-80: rgba(9, 9, 9, 0.8);
  --ink-55: rgba(9, 9, 9, 0.55);
  --ink-40: rgba(9, 9, 9, 0.4);
  --cream: #f5f4f3;
  --line: #eaeaea;
  --paper: #ffffff;

  /* One curve for everything, which is what makes a page feel like one
     object rather than a set of independently animated parts. */
  --ease: cubic-bezier(0.23, 1, 0.32, 1);
  --fast: 220ms;
  --slow: 620ms;

  --gutter: clamp(20px, 5vw, 80px);
  --measure: 1160px;
}

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: inherit; }

.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;
}

/* The little green square that prefixes a label. Three of them on the page,
   and it is the quietest possible way to carry the brand colour. */
.sq {
  width: 8px; height: 8px; background: var(--green);
  display: inline-block; margin-right: 9px; flex: none;
}

/* ───────────────────────────────────────────────────────────── header ──── */

/*
  A green strip across the very top.

  Present on the live site at every scroll position and full width at rest,
  so it is a brand edge rather than a reading-progress bar. Missed entirely
  on the first pass because it is eight pixels tall and sits above the
  header, where nothing else draws attention to it.
*/
.topbar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 70;
  height: 8px;
  background: var(--green);
}

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  display: flex;
  align-items: center;
  /* The links stand well clear of the button on the live header — about 65px
     — which is what stops the last link reading as part of it. */
  gap: clamp(20px, 4vw, 58px);
  /* Cleared below the green strip.
     A tighter gutter than the page uses. The header sits at about 34px from
     the left edge on the live site while the content column sits at 80, and
     matching the content gutter pushed the wordmark visibly inboard of where
     it belongs. */
  padding: calc(18px + 8px) clamp(18px, 2.4vw, 34px) 18px;
  color: #fff;
  transition: background var(--slow) var(--ease), color var(--slow) var(--ease);
}

/* Over the photograph the mark is white; past it the page is white, so the
   mark has to become ink or it disappears. The only state this header keeps. */
.nav.is-past {
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  color: var(--ink);
  border-bottom: 1px solid var(--line);
}
.nav.is-past .nav__mark img { filter: none; }

.nav__mark img {
  /* 230px, which is what the live header renders. The supplied PNG carries
     transparent padding, so the visible word is nearer 180 — measuring the
     glyphs rather than the box is what made the first pass half the size it
     should have been. */
  width: 230px; height: auto;
  /* The supplied mark is dark, and the hero behind it is not. */
  filter: brightness(0) invert(1);
  transition: filter var(--slow) var(--ease);
}

/*
  The links, as they actually measure.

  18px and 600, not 13px and 500 — the first pass read them as small print
  when they are nearly the size of body copy.

  And they are ink at 40%, not white. Over a pale sky that resolves to a soft
  grey, which is what the live header shows; setting them white made the
  header louder than the photograph behind it.
*/
.nav__links {
  margin-left: auto;
  display: flex;
  gap: clamp(20px, 4.6vw, 66px);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.1px;
}
.nav__links a {
  text-decoration: none;
  color: var(--ink-40);
  transition: color var(--fast) var(--ease);
}
.nav__links a:hover { color: var(--ink-80); }
.nav__links sup {
  font-size: 10px;
  font-weight: 700;
  margin-left: 4px;
  vertical-align: super;
  color: inherit;
}

/* Past the photograph the page is white, so 40% ink on white is too faint to
   read. The links firm up along with everything else. */
.nav.is-past .nav__links a { color: var(--ink-55); }
.nav.is-past .nav__links a:hover { color: var(--ink); }

/*
  The pill, and the one transition worth copying exactly.

  At rest it is a cream capsule with a small green disc at its left end. On
  hover the disc does not light up or change colour: it grows until it is the
  whole capsule. Measured on the live site as a background swap from #F5F4F3
  to #9BDE64, but a scaling disc is what it looks like, and a disc is what it
  actually is.
*/
.pill {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  /* Measured off the live header: about 182 by 44, which is a good deal
     larger than the first pass drew it. */
  padding: 6px 28px 6px 6px;
  border-radius: 999px;
  background: var(--cream);
  color: var(--ink);
  text-decoration: none;
  font-size: 15px;
  font-weight: 600;
  overflow: hidden;
  isolation: isolate;
  flex: none;
}

/* The disc that becomes the button. Sized to cover the widest pill when
   scaled, and scaled rather than resized so it stays perfectly round the
   whole way. */
.pill::before {
  content: "";
  position: absolute;
  left: 6px; top: 50%;
  width: 32px; height: 32px;
  margin-top: -16px;
  border-radius: 999px;
  background: var(--green);
  transform: scale(1);
  transform-origin: center;
  transition: transform var(--slow) var(--ease);
  z-index: -1;
}
.pill:hover::before { transform: scale(18); }

.pill__dot {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: 999px;
  color: var(--ink);
  flex: none;
}
.pill__dot svg { width: 17px; height: 17px; }
.pill__label { white-space: nowrap; }

/*
  The pill, as a form control.

  A square green block sitting beside a capsule in the header read as two
  different systems on one page. Same capsule, same disc, same arrow — the
  only additions are the resets a <button> needs and the states a form puts
  it through.
*/
.pill--submit {
  appearance: none;
  border: 0;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.pill--submit:disabled { cursor: default; }
/* While submitting the disc has already covered the capsule, so the label
   needs to read against green rather than cream. */
.pill--submit:disabled .pill__label { opacity: 0.75; }

/*
  Ink, not cream.

  The page now has two shop routes and they are not the same promise: "See
  collection" takes an email first, this one goes straight through. Drawing
  them identically would make that difference invisible, so this one is solid
  ink with the disc in green — the inverse of the header pill.
*/
.pill--ink {
  /* Above the garment row, which is pulled up underneath it. The row and the
     button deliberately share a band — the same overlap the live page has
     between its form and the garments — so the one that must stay legible
     needs to say so. */
  position: relative;
  z-index: 2;
  background: var(--ink);
  color: #fff;
  padding: 7px 26px 7px 7px;
  font-size: 15px;
}
.pill--ink::before { background: var(--green); }
.pill--ink .pill__dot { color: var(--ink); }
/* Once the disc has covered the capsule the label sits on green, so it has
   to become ink or it disappears at the end of the hover. */
.pill--ink:hover { color: var(--ink); }

/* The consultancy button starts green and stays green: it is the page's
   single call to action, not a navigation control. */
.pill--solid { background: var(--green); padding: 6px 22px 6px 6px; font-size: 14px; }
.pill--solid::before { background: var(--green-deep); }

/* ─────────────────────────────────────────────────────────────── hero ──── */

.hero {
  position: relative;
  /* A blending context of its own, so the wordmark differences against the
     photograph and nothing else. */
  isolation: isolate;
  min-height: 100svh;
  padding: var(--gutter);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  color: #fff;
}

.hero__bg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 40%;
  z-index: -2;
}

/* A wash along the bottom only. The photograph is bright at the top, where
   the header sits, and the wordmark needs the ground under it darkened just
   enough to hold an edge without greying the hillside. */
.hero::after {
  content: "";
  position: absolute; inset: auto 0 0 0; height: 62%;
  /* Lighter than before. The wash existed to give flat type an edge to sit
     on; the blend now does that, and a heavy scrim only greys the hillside
     the mark is reacting to. */
  background: linear-gradient(to top, rgba(0,0,0,0.22), transparent);
  z-index: -1;
  pointer-events: none;
}

.hero__tag {
  /* Larger than the first pass. It names the category the whole page is
     about, and at 15px it read as a caption on the photograph. */
  font-size: clamp(18px, 2vw, 26px);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 4px;
}

/*
  The wordmark.

  Framer ships this at a fixed 250px, which means it is the right size at one
  window width and wrong at every other. Set fluid here: it takes the frame at
  any width, which is what the design is actually saying.
*/
.hero__mark {
  margin: 0;
  font-size: clamp(56px, 15.5vw, 250px);
  line-height: 0.82;
  letter-spacing: -0.045em;
  font-weight: 700;
  color: var(--green);

  /*
    The overlay, which is the thing that makes this hero.

    The type does not sit on the photograph, it reacts to it: the hillside's
    own texture runs through the letters, and the word is lit by the same
    light as the scene behind it. A flat fill with a drop shadow, which is
    what was here first, is the same colour everywhere and reads as a
    sticker laid on top.

    screen, not difference. The live page does carry a differenced layer, but
    differencing green against a green hill drives the letters to a dark
    navy, and the real wordmark is lighter than the hillside everywhere it
    crosses it — including over the brightest parts, which rules out plain
    transparency too. screen is the mode that can only lighten, which is why
    it holds the mark up against every part of the picture. Checked against
    the live hero alongside difference, overlay, soft-light, hard-light,
    exclusion and luminosity.

    isolation on the hero confines the blend to the photograph. Without it
    the mark would blend against whatever the browser had composited
    underneath, which on a scrolled page is not the video.
  */
  mix-blend-mode: screen;
  /* No shadow. A shadow under a difference blend is differenced too, and
     comes out as a grey halo. */
  text-shadow: none;
}
.hero__mark span { display: block; }
.hero__mark em { font-style: normal; }

.hero__note {
  position: absolute;
  right: var(--gutter);
  bottom: calc(var(--gutter) + 96px);
  max-width: 270px;
  font-size: 13px;
  line-height: 1.45;
  font-weight: 500;
  text-align: right;
  margin: 0;
}

.hero__scroll {
  position: absolute;
  right: var(--gutter);
  bottom: var(--gutter);
  color: #fff;
  opacity: 0.9;
  transition: transform var(--fast) var(--ease);
}
.hero__scroll svg { width: 15px; height: 21px; }
.hero__scroll:hover { transform: translateY(4px); }

/* ──────────────────────────────────────────────────────── statement ──── */

.future {
  position: relative;
  padding: clamp(80px, 11vw, 150px) var(--gutter) clamp(60px, 8vw, 110px);
  overflow: hidden;
}

/* The two soft shapes. They are what stops this section reading as a plain
   white box, and they are deliberately almost invisible. */
.blob {
  position: absolute;
  background: var(--cream);
  z-index: 0;
  pointer-events: none;
}
.blob--left {
  left: -14%; top: 2%;
  width: 46%; height: 78%;
  border-radius: 0 56% 60% 0 / 0 46% 54% 0;
}
.blob--right {
  right: -20%; top: 22%;
  width: 40%; height: 62%;
  border-radius: 58% 0 0 62% / 48% 0 0 52%;
}

.future__inner {
  position: relative;
  z-index: 1;
  max-width: var(--measure);
  margin: 0 auto;
}

.eyebrow {
  display: flex;
  align-items: center;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-80);
  margin: 0 0 46px;
}

.statement {
  margin: 0 0 32px;
  max-width: 660px;
  font-size: clamp(25px, 3.6vw, 35px);
  line-height: 1.28;
  letter-spacing: -0.022em;
  font-weight: 600;
}
.green { color: var(--green); }

.lede {
  margin: 0 0 20px;
  font-size: 15px;
  font-weight: 600;
}

/* The waitlist form. A bordered field and a green button, sitting on one
   line, the way it does on the live site. */
/* What joining actually gets you, said where the decision is made rather
   than after it. */
.lede__note {
  margin: -12px 0 18px;
  max-width: 430px;
  font-size: 12px;
  line-height: 1.55;
  color: var(--ink-55);
}
.dress__note { color: var(--ink-80); }

.waitlist {
  display: flex;
  gap: 10px;
  align-items: stretch;
  max-width: 430px;
  margin: 0 0 clamp(48px, 7vw, 86px);
}
.waitlist input {
  flex: 1;
  min-width: 0;
  padding: 11px 15px;
  font: inherit;
  font-size: 13px;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 8px;
  transition: border-color var(--fast) var(--ease);
}
.waitlist input::placeholder { color: var(--ink-40); }
.waitlist input:focus { outline: none; border-color: var(--ink); }
/* The submit button is .pill--submit and carries its own shape. All this
   adds is the press, which every control on the site has. */
.waitlist button { flex: none; transition: transform var(--fast) var(--ease); }
.waitlist button:active { transform: scale(0.97); }

.waitlist--tight { margin-inline: auto; margin-bottom: clamp(40px, 6vw, 72px); }

/*
  The services.

  Set at body weight rather than as small print: this is the answer to "what
  does this company do", and on most pages that answer is the one thing a
  visitor is actually looking for.
*/
.services {
  max-width: 760px;
  margin: 0 0 clamp(36px, 5vw, 56px);
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
.services__head {
  margin: 0 0 14px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.services__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}
@media (min-width: 760px) {
  .services__list { grid-template-columns: repeat(3, 1fr); gap: clamp(20px, 3vw, 40px); }
}
.services__list li {
  font-size: 12px;
  line-height: 1.6;
  color: var(--ink-55);
}
.services__list strong {
  display: block;
  margin-bottom: 3px;
  color: var(--ink);
  font-weight: 600;
}

/* Two columns, divided by a rule above each rather than between them. */
.cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 6vw, 80px);
  max-width: 760px;
}
.col { border-top: 1px solid var(--line); padding-top: 16px; }
.col__head {
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.col p {
  margin: 0 0 11px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--ink-55);
}
.col a { color: var(--ink-80); }

/* ───────────────────────────────────────────────────────────── cards ──── */

.pillars {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 2.2vw, 28px);
  max-width: var(--measure);
  margin: 0 auto;
  padding: clamp(20px, 3vw, 40px) var(--gutter) clamp(80px, 10vw, 130px);
}

/*
  A card lifts on hover and its photograph grows inside a frame that does not.
  Both measured on the live site; the frame holding still is the part that
  makes it read as a photograph rather than as a whole card inflating.
*/
.card {
  background: var(--paper);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(9, 9, 9, 0.05), 0 12px 28px rgba(9, 9, 9, 0.06);
  transition: transform var(--slow) var(--ease), box-shadow var(--slow) var(--ease);
}
.card:hover {
  transform: translateY(-6px);
  box-shadow: 0 2px 4px rgba(9, 9, 9, 0.06), 0 22px 46px rgba(9, 9, 9, 0.11);
}
.card__shot { overflow: hidden; aspect-ratio: 4 / 3.1; background: var(--cream); }
.card__shot img,
.card__shot video {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.001);
  transition: transform 900ms var(--ease);
}
.card:hover .card__shot img,
.card:hover .card__shot video { transform: scale(1.06); }

.card__body { padding: 22px 24px 26px; }
.card__body h3 {
  margin: 0 0 7px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.012em;
}
.card__body p {
  margin: 0 0 18px;
  font-size: 12.5px;
  color: var(--ink-55);
}

.chip {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--green);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
}

/* ────────────────────────────────────────────────────────── meta rule ──── */

.meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 16px var(--gutter);
  border-top: 1px solid var(--line);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-80);
}
.meta span { display: inline-flex; align-items: center; }

/* ──────────────────────────────────────────────── a new way to dress ──── */

.dress {
  text-align: center;
  /*
    Was 150px above and 160px below, for a row 335px tall: more than half the
    section's height was empty padding, and on a wide screen it read as two
    unexplained holes rather than as breathing room. The house rhythm
    separates sections by roughly 40 to 56px; this is a little over that
    because the row bleeds, and no more.
  */
  padding: clamp(52px, 5.2vw, 84px) 0 clamp(44px, 4.4vw, 72px);
  overflow: hidden;
}

/* A pale capsule with the green square in it, centred above the heading. */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 16px;
  border-radius: 999px;
  background: var(--cream);
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-80);
  margin-bottom: 26px;
}
.tag__icon { width: 13px; height: 13px; color: var(--green); flex: none; }

/* This section's tag is green throughout, cube and label alike, where the
   consultancy tag is ink with a green mark. */
.tag--green { color: var(--green); }
.tag__cube { width: 14px; height: 14px; flex: none; }

.display {
  margin: 0 0 20px;
  font-size: clamp(38px, 7.2vw, 110px);
  line-height: 1.0;
  letter-spacing: -0.04em;
  font-weight: 600;
}
.display--left { text-align: left; }

.dress__sub {
  margin: 0 auto clamp(26px, 3vw, 38px);
  /* Wide enough that each sentence holds one line, which is how the live
     page sets it. 460 broke it into four; 600 still broke the first sentence
     after "chemical-free" on a wide screen. Measured against the longer of
     the two sentences rather than picked. */
  max-width: 680px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-55);
  padding-inline: var(--gutter);
}

/*
  The garment rail.

  Previously an arc: large at the ends, small in the middle, each piece
  turned and lifted by hand. That composes well as a still, where size
  encodes position. It falls apart the moment the row scrolls, because every
  garment then passes through every position and the sizing means nothing —
  ten source images at ten aspect ratios, sliding past at ten sizes.

  A row you can move needs a repeating unit. One frame, one rhythm, and the
  variety carried by the clothes rather than by the container.

  The one authored moment here is the dissolve at each end. A hard-cut row
  stops; a row that fades out continues. It is a mask rather than a pair of
  gradient overlays because the page behind it is not a flat colour — an
  overlay would need to know the background and would show its seam the
  moment anything sat underneath.
*/
.rail {
  display: flex;
  align-items: stretch;
  gap: clamp(10px, 1.1vw, 18px);

  /*
    Clear of the button above it.

    The row used to be pulled up under a form, which is how the original
    composed it. A single pill is a smaller object and reads as sitting on
    top of the row rather than in front of it, so each gets its own space.
  */
  margin-top: clamp(30px, 3vw, 52px);

  /* Full bleed. The gutter is applied as scroll padding instead, so the
     first and last pieces can sit under the dissolve rather than being
     held away from it. */
  padding: 0 var(--gutter) clamp(28px, 3.5vw, 44px);
  scroll-padding-inline: var(--gutter);

  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;

  /* Comes to rest on a garment rather than halfway across one. proximity,
     not mandatory: a deliberate flick past several pieces should not be
     dragged back. */
  scroll-snap-type: x proximity;

  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;

  /* The dissolve. Opaque across the middle, transparent at both edges. */
  -webkit-mask-image: linear-gradient(
    to right, transparent 0, #000 7%, #000 93%, transparent 100%);
  mask-image: linear-gradient(
    to right, transparent 0, #000 7%, #000 93%, transparent 100%);
}
.rail::-webkit-scrollbar { display: none; }
.rail:active { cursor: grabbing; }

/*
  One frame, repeated.

  A fixed portrait panel with the garment inside it rather than filling it.
  The photographs come from different sources on different grounds at
  different crops, so the frame supplies the consistency they do not have:
  contain, not cover, because cover would crop a coat's shoulders to match a
  shoe's proportions.
*/
.piece {
  flex: none;
  width: clamp(150px, 15vw, 218px);
  margin: 0;
  padding: 0;
  scroll-snap-align: start;

  aspect-ratio: 3 / 4;
  display: grid;
  place-items: center;

  /*
    White, not cream.

    These photographs are cut out on their own near-white grounds, so a cream
    frame put a pale card inside a pale card: ten visible boxes-within-boxes
    down the row. Matching the frame to the photography's own ground makes
    the seam disappear and leaves one clean panel per garment.
  */
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
}

.piece img {
  width: 100%;
  height: 100%;
  object-fit: contain;

  /*
    Per photograph, because the photography is not consistent with itself.
    Measured rather than eyeballed: each frame was captured and the garment's
    real extent found by pixel bounds. The card-backed shots fill their frame
    edge to edge; the cut-outs carry so much baked-in margin that they arrive
    at 72 to 88 percent of the same frame and read as smaller garments rather
    than as differently photographed ones.

    Only the outliers are corrected, and only upward. Scaling the already
    full ones would crop them for no gain.
  */
  transform: scale(var(--fit, 1));
  transition: transform 620ms var(--ease);
  -webkit-user-drag: none;
  user-drag: none;
  pointer-events: none;
}

/* The garment leans in; the frame holds still. The frame holding still is
   what keeps the row's rhythm intact while a single piece responds. */
.rail:not(.is-dragging) .piece:hover img { transform: scale(calc(var(--fit, 1) * 1.06)); }

@media (prefers-reduced-motion: reduce) {
  .rail { scroll-behavior: auto; }
  .piece img { transition: none; }
  .rail:not(.is-dragging) .piece:hover img { transform: scale(var(--fit, 1)); }
}

@media (max-width: 860px) {
  /* Narrower frames and a softer dissolve: at this width a 7% fade eats a
     meaningful part of the first garment. */
  .piece { width: clamp(132px, 42vw, 168px); }
  .rail {
    -webkit-mask-image: linear-gradient(
      to right, transparent 0, #000 4%, #000 96%, transparent 100%);
    mask-image: linear-gradient(
      to right, transparent 0, #000 4%, #000 96%, transparent 100%);
  }
}

/* ──────────────────────────────────────────────────────── consultancy ──── */

.consult {
  max-width: var(--measure);
  margin: 0 auto;
  padding: clamp(60px, 8vw, 100px) var(--gutter) clamp(70px, 9vw, 110px);
}
.consult .display { margin-bottom: 26px; }

.consult__body { max-width: 430px; }
.consult__hook {
  margin: 0 0 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-80);
}
.consult__body > p {
  margin: 0 0 14px;
  font-size: 12px;
  line-height: 1.65;
  color: var(--ink-55);
}
.consult__who {
  margin: 30px 0 12px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-80);
}

.who { list-style: none; margin: 0 0 26px; padding: 0; }
.who li {
  display: flex;
  align-items: center;
  gap: 11px;
  font-size: 12px;
  color: var(--ink-80);
  padding: 5px 0;
}
.dot {
  width: 17px; height: 17px;
  border-radius: 999px;
  background: var(--cream);
  flex: none;
}

/* ───────────────────────────────────────────────────────────── footer ──── */

.foot { background: var(--cream); margin-top: clamp(40px, 6vw, 70px); }

.foot__inner {
  max-width: var(--measure);
  margin: 0 auto;
  padding: clamp(46px, 6vw, 72px) var(--gutter) clamp(30px, 4vw, 46px);
}
.foot__label {
  margin: 0 0 6px;
  font-size: clamp(19px, 2.4vw, 27px);
  font-weight: 500;
  color: var(--ink-55);
  letter-spacing: -0.02em;
}
.foot__mail {
  display: inline-block;
  font-size: clamp(22px, 3.6vw, 40px);
  font-weight: 600;
  letter-spacing: -0.032em;
  text-decoration: underline;
  text-underline-offset: 6px;
  text-decoration-thickness: 2px;
  transition: color var(--fast) var(--ease);
}
.foot__mail:hover { color: var(--green-deep); }

/* One line, in every footer. Whatever page somebody landed on, the answer to
   "what is this company" is a scroll away rather than a search. */
.foot__what {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--gutter) 18px;
}
.foot__what p {
  margin: 0;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-80);
}

.foot__bar {
  display: flex;
  justify-content: space-between;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 16px var(--gutter) 26px;
  border-top: 1px solid #e3e2e1;
  font-size: 11px;
  color: var(--ink-55);
}
.foot__bar a { text-decoration: none; }
.foot__bar a:hover { color: var(--ink); }

/* ───────────────────────────────────────────── scroll-in reveal ──── */

/*
  Content rises a little as it arrives, once, and never animates again.

  data-delay staggers siblings so a row of three cards arrives as a row
  rather than as three simultaneous events.
*/
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 760ms var(--ease), transform 760ms var(--ease);
  transition-delay: var(--d, 0ms);
}
.reveal.is-in { opacity: 1; transform: none; }

/* Anything already on screen at load is not an arrival, so it just appears.
   Without this the hero animates in on every reload, which reads as slow. */
.no-motion .reveal { opacity: 1; transform: none; transition: none; }

/* ─────────────────────────────────────────────────────────── phones ──── */

@media (max-width: 860px) {
  .nav { padding: 14px var(--gutter); gap: 14px; }
  .nav__links { display: none; }
  .nav__mark img { width: 150px; }
  .pill { font-size: 13px; padding: 5px 16px 5px 5px; gap: 9px; }
  .pill::before { width: 26px; height: 26px; margin-top: -13px; left: 5px; }
  .pill__dot { width: 26px; height: 26px; }
  .pill__dot svg { width: 15px; height: 15px; }

  .hero { min-height: 92svh; }
  .hero__note {
    position: static;
    text-align: left;
    max-width: none;
    margin-top: 20px;
    font-size: 12px;
  }
  .hero__scroll { display: none; }

  .cols { grid-template-columns: 1fr; }
  .pillars { grid-template-columns: 1fr; }
  .rail { justify-content: flex-start; }
  .consult__body { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .pill::before,
  .card, .card__shot img, .piece { transition: none; }
}
