/* ============================================================
   SECTIONS — one block per section of the page, in page order.
   ============================================================ */

/* ------------------------------------------------------------
   PAGE EFFECT

   Every section is a screen. Content sits in the middle of it,
   so moving on reads as turning a page rather than as sliding
   down a column — the reader is never looking at the foot of
   one argument and the head of the next at once.

   Sections still grow when their content needs more than a
   screen: min-height, not height. What overflows keeps its own
   resting positions further down this stack, so nothing is
   locked out of reach.

   #method is out of it, deliberately. It is the one section
   that is taller than a screen by design — three phases do not
   fit in one — and squeezing it into a single page would either
   hide a phase or crush all three. It scrolls, as it always did.
   ------------------------------------------------------------ */
#main > section:not(#method) {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* The block padding was what separated one section from the next down a
   column. A screen each separates them now, and it was the only thing
   pushing three of these sections past the screen they are meant to be.

   What replaces it is edge room that can give way. As fixed padding it
   cannot: 'contact' carries enough content to come within fifty
   pixels of the screen, so any fixed value tips it over and the page
   effect clips its last line. As two flex spacers it yields —
   they take their full size whenever the section has room and give it
   back, proportionally, when it does not. The section lands on exactly
   one screen either way, and nothing is ever cut.

   The rule below is what makes that safe: only the spacers may shrink.
   Left to the default the content would be squeezed with them, which is
   the one thing worse than a section running long.

   The hero keeps its own padding — it was authored against this same
   full screen and already fits. */
#main > section:not(#method):not(.hero) {
  padding-block: 0;
}

#main > section:not(#method):not(.hero) > * { flex: 0 0 auto; }

#main > section:not(#method):not(.hero)::before {
  content: "";
  flex: 0 1 clamp(4rem, 7vh, 5.5rem);   /* clears the bar */
}

#main > section:not(#method):not(.hero)::after {
  content: "";
  flex: 0 1 clamp(1.5rem, 3vh, 3rem);
}

.menu[hidden] { display: none; }

/* ------------------------------------------------------------
   01 — HERO
   ------------------------------------------------------------ */
.hero {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  padding-block: clamp(4rem, 11vh, 8rem) clamp(1.5rem, 4vh, 3rem);
}

.hero__inner {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  margin-block: auto;
  padding-inline: var(--gutter);
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1rem, 3.5vw, 3rem);
}

.hero__title {
  /* Not --t-display: that size was cut for the 17-character wordmark.
     A sentence needs room to sit on two lines without shrinking to nothing. */
  font-size: clamp(1.9rem, 7.4vw, 7rem);
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  font-variation-settings: 'wdth' 106, 'wght' 600;
  margin-top: clamp(1rem, 3vw, 2.5rem);
}

.hero__slogan {
  display: flex;
  flex-wrap: wrap;
  gap: 0 clamp(0.6rem, 1.6vw, 1.4rem);
  font-size: clamp(1.25rem, 3.1vw, 2.5rem);
  line-height: 1.1;
  letter-spacing: -0.03em;
  font-variation-settings: 'wdth' 100, 'wght' 500;
  padding-bottom: clamp(1.75rem, 4vw, 3rem);
  border-bottom: 1px solid var(--rule);
}
/* THE LIT WORD

   The word that is lit changes voice as well as colour: sans into serif
   italic, the same move the headings make on the word they arrive at. The
   slogan is the method, so each of its three words gets to be the arrival
   in turn.

   Both versions live in the same grid cell, stacked and cross-faded. A
   plain font-family swap would resize the word — the serif italic does not
   set to the same width as the sans — and all three would shift sideways
   every 1.7 seconds. The cell is as wide as the wider of the two, always,
   so nothing moves. */
.slogan__w {
  display: inline-grid;
  vertical-align: baseline;
}

.slogan__a,
.slogan__b {
  grid-area: 1 / 1;
  transition: opacity 0.55s var(--ease-in);
}

.slogan__b {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--reagent);
  opacity: 0;
}

.slogan__w.is-on .slogan__a { opacity: 0; }
.slogan__w.is-on .slogan__b { opacity: 1; }

/* The blink. Hard on and off — a fade would read as a dimmer, not as a
   signal. It runs on the serif layer, and because the sans layer under it
   is already out, the words genuinely disappear rather than swapping face. */
@keyframes slogan-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0; }
}

.hero__slogan.is-blinking .slogan__b {
  animation: slogan-blink 0.42s steps(1, end) 2;
}

/* Settled: it keeps the serif italic and gives the accent back. */
.hero__slogan.is-settled .slogan__b { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .slogan__a, .slogan__b { transition: none; }
}

.hero__lead {
  font-size: var(--t-lead);
  line-height: 1.3;
  letter-spacing: -0.02em;
  /* Each .line is a written line and must not wrap inside its own clip —
     the reveal slides one line at a time. Wide enough for the longer of
     the two, in either language. */
  max-width: 52ch;
  color: var(--ink);
}

.hero__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }

/* The figure sits with the headline rather than under it: three shapes
   that mean nothing resolving into T-M-L is the headline performed, so
   the claim and its demonstration share one screen. */
.hero__morph { grid-column: 1 / -1; margin: 0; cursor: pointer; }
.hero__morph .morph__stage { max-width: clamp(9.5rem, 38vw, 17rem); }

/* On a phone the figure has the row to itself, and centred it reads as a
   logo dropped in the middle of the page rather than as the headline
   being performed. Pulled to the left edge it lines up with the eyebrow,
   the headline and the lead — everything on this screen starts on the
   same rule — and a size down so it does not outweigh the line it is
   there to illustrate. Ends at 1000px, where the figure moves into its
   own column beside the headline and is right-aligned there. */
@media (max-width: 999.98px) {
  .hero__morph .morph__stage {
    max-width: clamp(6.5rem, 26vw, 11rem);
    margin-left: 0;
    margin-right: auto;
  }
}

@media (min-width: 860px) {
  .hero__inner { grid-template-columns: minmax(0, 1fr) auto; }
  .hero__title,
  .hero__slogan { grid-column: 1 / -1; }
  .hero__lead { grid-column: 1; align-self: end; }
  .hero__actions { grid-column: 2; align-self: end; justify-self: end; }

}

@media (min-width: 1000px) {
  .hero__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 0.44fr); }
  /* Capped below the full-width size: the headline now shares its row
     with the figure, and the two written lines have to stay two. */
  .hero__title   { grid-column: 1; grid-row: 1; font-size: clamp(2.5rem, 5.6vw, 6rem); }
  .hero__morph   { grid-column: 2; grid-row: 1; align-self: center; justify-self: end; }
  .hero__slogan  { grid-column: 1 / -1; grid-row: 2; }
  .hero__lead    { grid-column: 1; grid-row: 3; align-self: end; }
  .hero__actions { grid-column: 2; grid-row: 3; align-self: end; justify-self: end; }
  .hero__morph .morph__stage { max-width: min(100%, 27rem); }

}

/* The figure arrives with the type it illustrates. */
.js .hero__morph { opacity: 0; transition: opacity 0.9s var(--ease-in); }
.js.is-loaded .hero__morph { opacity: 1; transition-delay: 0.3s; }

/* Hero load sequence — orchestrated once, on first paint. */
.js .hero .line__in { transform: translate3d(0, 110%, 0); }
.js.is-loaded .hero .line__in { transform: none; }
.js .hero__title .line:nth-child(1) .line__in { transition-delay: 0.15s; }
.js .hero__title .line:nth-child(2) .line__in { transition-delay: 0.25s; }
.js .hero__lead .line:nth-child(1) .line__in { transition-delay: 0.6s; }
.js .hero__lead .line:nth-child(2) .line__in { transition-delay: 0.68s; }

.js .hero__slogan,
.js .hero__actions {
  opacity: 0;
  transition: opacity 0.9s var(--ease-in);
}
.js.is-loaded .hero__slogan  { opacity: 1; transition-delay: 0.35s; }
.js.is-loaded .hero__actions { opacity: 1; transition-delay: 0.7s; }

/* ------------------------------------------------------------
   02 — WHAT IS TML
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   02 — WHAT IS TML

   Two beats. The claim and what a lab is; then the three positions
   that prove it. One column at every width — the previous version
   ran a two-column grid, then a second two-column grid, then a
   full-width block, and three topologies in one section is three
   different things to go wrong at 390px. There is nothing here to
   reflow, so there is nothing to break.

   The rhythm is deliberate rather than even: 0.5–0.8rem inside a
   thought, 2–3.5rem between thoughts, 5–8rem between the two beats.
   The old section used one spacing value almost everywhere, which
   is what made everything read at the same weight.
   ------------------------------------------------------------ */
/* Smaller than the other section headings on the page, on purpose. This
   one is two negations, and a negation is the setup — it should not be the
   loudest thing in the section. The line it sets up is below, and that one
   grew. --t-h2 is clamp(2.4rem, 6.4vw, 6rem); this sits a step under it. */
.what__title {
  font-size: clamp(2rem, 4.6vw, 4.2rem);
  margin-block: clamp(1.25rem, 2.5vw, 2rem) clamp(1.1rem, 2vw, 1.6rem);
}

/* THE ARRIVAL

   The headline is two negations, and a negation has no word to arrive on
   — so it is set plain. The sentence arrives underneath, on "lab", and
   that is where the typography plays: sans into serif italic, and the
   period in reagent. Same move as the deck cover, and the same rule that
   governs the accent everywhere on this page — it lands on the thing that
   changed, never on the whole sentence.

   Set apart to the right and below the subtitle rather than in line with
   it: a conclusion that sits in the same column as its premise reads as
   one more sentence instead of as the answer. */
.what__is {
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
  text-align: right;
  font-size: clamp(1.85rem, 3.6vw, 3.2rem);
  line-height: 1.05;
  letter-spacing: -0.04em;
  font-variation-settings: 'wdth' 104, 'wght' 500;
  color: var(--ink);
}

.what__is em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.015em;
}

/* THE WORD ARRIVES

   This line is the answer the section builds to, so it lands rather than
   simply being there: "lab" changes voice on arrival, sans into serif
   italic, and the mark follows a beat later. It is the slogan's move, for
   the same reason, and it is built the same way -- two layers in one grid
   cell -- so the swap cannot shift the line sideways when the serif sets
   narrower than the sans. */
.what__is .lab {
  display: inline-grid;
  vertical-align: baseline;
}

.what__is .lab__a,
.what__is .lab__b {
  grid-area: 1 / 1;
  transition: opacity 0.55s var(--ease-in) 0.45s;
}

.what__is .lab__b { opacity: 0; }

.what__is.is-visible .lab__a { opacity: 0; }
.what__is.is-visible .lab__b { opacity: 1; }

/* The mark lands last, once the word has settled into its serif. It grows
   from the baseline, which is where a full stop belongs. */
.what__is .dot {
  color: var(--reagent);
  transform: scale(0);
  transform-origin: 50% 100%;
  transition: transform 0.4s var(--ease) 0.95s;
}

.what__is.is-visible .dot { transform: scale(1); }

@media (prefers-reduced-motion: reduce) {
  .what__is .lab__a,
  .what__is .lab__b,
  .what__is .dot { transition: none; }
  .what__is .lab__a { opacity: 0; }
  .what__is .lab__b { opacity: 1; }
  .what__is .dot { transform: none; }
}

/* One grid, one breakpoint. The argument on the left, the three positions
   it proves on the right — which is also the reading order, so nothing has
   to be reordered when it stacks.

   A single column at every width was the previous attempt at making this
   adaptive, and it made the wide case worse than the narrow one: at 1920
   the whole section sat in the left third and read as a phone layout that
   had been stretched. Adaptive means one model that changes shape, not one
   shape held everywhere. */
.what__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2.5rem, 5vw, 4rem);
  align-items: start;
}

@media (min-width: 900px) {
  .what__grid {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    gap: clamp(3rem, 6vw, 7rem);
  }
}

/* The claim and the definition are one sentence because they are one
   thought. Set as two blocks, with the word large and serif in its own
   column, "lab" became a second protagonist competing with the headline
   for the same job. */
.what__when {
  /* Nothing above it any more: this margin separated it from a line that
     was removed, and it was doing two things wrong at once — adding to the
     gap under the headline, and pushing the whole left column below the
     first position on the right. */
  margin-top: 0;
  /* Optically flush with the headline, not mechanically flush. Both boxes
     start at the same x, but a left side bearing is a fraction of the em:
     the headline's N hangs 4.2px inside its box at 67px, the subtitle's E
     only 1.6px at 20px, so the headline read as indented by the 2.6px
     difference. The headline is the anchor -- it lines up with every other
     section title on the page -- so the subtitle moves to meet it. */
  margin-left: 0.13em;
  font-size: clamp(1.05rem, 1.45vw, 1.25rem);
  line-height: 1.55;
  color: var(--ink-2);
  /* Measured, not guessed. At 44ch it broke after "ideas," and left
     "negocios y proyectos." as a stub two fifths the length of the line
     above; balance did worse, cutting after the conjunction. At 36ch the
     break lands between the verbs and the objects, which is where the
     sentence wants to fold anyway. */
  max-width: 36ch;
  text-wrap: pretty;
}

/* ------------------------------------------------------------
   THREE POSITIONS

   The only rule in the section sits above TML, and it is graduated
   the way the instruments on this page are graduated. One line,
   where the previous version had six and read as a very well made
   corporate slide.
   ------------------------------------------------------------ */
.stance {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 2.6vw, 2.15rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.stance__who {
  font-size: clamp(0.95rem, 1.2vw, 1.05rem);
  line-height: 1;
  letter-spacing: 0.01em;
  font-variation-settings: 'wdth' 102, 'wght' 500;
  color: var(--ink-3);
}

.stance__verb {
  margin-top: 0.5rem;
  font-size: clamp(1.2rem, 2vw, 1.65rem);
  line-height: 1.05;
  letter-spacing: -0.035em;
  font-variation-settings: 'wdth' 104, 'wght' 500;
  color: var(--ink-2);
}

.stance__line {
  margin-top: 0.6rem;
  font-size: clamp(0.95rem, 1.2vw, 1.05rem);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 46ch;
  text-wrap: pretty;
}

/* ---- The arrival ----
   Agencia and Consultora are identical because they are peers. This one
   is not better; it is the one the section is about, and it arrives by
   scale and by a rule. The reagent marks position, which is the only
   thing the accent is allowed to do on this page. */
.stance__pos--us {
  position: relative;
  margin-top: clamp(0.4rem, 1vw, 0.7rem);
  padding-top: clamp(1.4rem, 2.4vw, 1.9rem);
  background-repeat: no-repeat;
  background-image:
    linear-gradient(var(--ink), var(--ink)),
    repeating-linear-gradient(90deg, var(--ink-3) 0 1px, transparent 1px 60px),
    repeating-linear-gradient(90deg, var(--rule) 0 1px, transparent 1px 12px);
  background-size: 100% 1px, 100% 7px, 100% 4px;
  background-position: 0 0, 0 1px, 0 1px;
}

/* The mark rests as a short tick — this is the one of the three the page
   is about, and that is position, which the accent is allowed to say. Under
   the pointer it runs the whole scale, exactly as the two doors do: same
   reagent, same 0.9s, same reason. */
.stance__pos--us::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  /* Full width, revealed by a clip rather than grown by one. Animating
     the width relays out the box on every frame of the nine hundred
     milliseconds; the clip never touches layout, and the resting tick is
     still exactly 2.5rem because the inset is measured from this
     element's own edge. */
  width: 100%;
  height: 2px;
  background: var(--reagent);
  clip-path: inset(0 calc(100% - 2.5rem) 0 0);
  transition: clip-path 0.9s var(--ease);
}

.stance__pos--us .stance__who,
.stance__pos--us .stance__verb { transition: color 0.35s var(--ease); }

/* The name and the verb take the accent together — they are the heading
   here, the way the question is the heading of a door. The line underneath
   stays as it is, which is what the doors do with their own line too. */
@media (pointer: fine) {
  .stance__pos--us:hover::before { clip-path: inset(0); }
  .stance__pos--us:hover .stance__who,
  .stance__pos--us:hover .stance__verb { color: var(--reagent); }
}

/* The same reaction, reached by a finger. A phone has no hover, and the
   reader who only ever sees this page on one was being shown a still
   version of a page that reacts. Pressing is the touch spelling of
   looking, so it lights the same way and stays lit until the finger goes
   somewhere else. Class rather than :active, which lasts only as long as
   the press and would flash a nine-hundred-millisecond move in and out. */
.stance__pos--us.is-live::before { clip-path: inset(0); }
.stance__pos--us.is-live .stance__who,
.stance__pos--us.is-live .stance__verb { color: var(--reagent); }

@media (prefers-reduced-motion: reduce) {
  .stance__pos--us::before,
  .stance__pos--us .stance__who,
  .stance__pos--us .stance__verb { transition: none; }
}

.stance__pos--us .stance__who { color: var(--ink-2); }

.stance__pos--us .stance__verb {
  margin-top: 0.7rem;
  /* Still just under twice the peers above it. The arrival is a ratio,
     not a size: drop this to their scale and it stops arriving. */
  font-size: clamp(1.9rem, 4vw, 3.1rem);
  line-height: 0.95;
  letter-spacing: -0.045em;
  font-variation-settings: 'wdth' 104, 'wght' 600;
  color: var(--ink);
}

.stance__pos--us .stance__line {
  margin-top: clamp(0.7rem, 1.4vw, 1.1rem);
  font-size: clamp(1rem, 1.5vw, 1.3rem);
  line-height: 1.4;
  letter-spacing: -0.02em;
  color: var(--ink);
  /* One line, like the two above it. The three rows are a comparison, and
     a comparison only reads as one while its terms are the same shape:
     name, verb, a single line. The block states a position; the method is
     explained elsewhere on the page and does not need explaining twice.
     Seventeen characters, so no cap -- but left wrappable rather than
     forced, since a second line is a better failure than a clipped one. */
  max-width: none;
  text-wrap: balance;
}

/* ------------------------------------------------------------
   03 — THE TML METHOD
   ------------------------------------------------------------ */
.method__title {
  margin-block: clamp(1.5rem, 3vw, 2.5rem) clamp(1.25rem, 2.5vw, 2rem);
  font-size: clamp(2.6rem, 7vw, 6.5rem);
  line-height: 0.92;
  letter-spacing: var(--tr-display);
  font-variation-settings: 'wdth' 104, 'wght' 500;
}
.method__lead {
  color: var(--void-ink-2);
  font-size: var(--t-lead);
  line-height: 1.45;
  max-width: 64ch;
}

.phases { margin-top: clamp(4rem, 9vw, 8rem); }

.phase {
  display: grid;
  grid-template-columns: 2px minmax(0, 1fr);
  column-gap: clamp(1.5rem, 4vw, 3.5rem);
  row-gap: clamp(1.5rem, 3vw, 2.5rem);
  padding-block: clamp(2.5rem, 6vw, 5rem);
  border-top: 1px solid var(--void-rule);
}
.phase:last-child { border-bottom: 1px solid var(--void-rule); }

.phase__rail {
  position: relative;
  grid-column: 1;
  grid-row: 1 / span 2;  /* head sits in row 1, body in row 2 — the rail spans both */
  align-self: stretch;   /* the ≥1000px rule sets align-items:start, which would collapse it to 0 */
  background: var(--void-rule);
}
.phase__rail i {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background: var(--reagent);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 1.4s var(--ease);
}
.phase.is-active .phase__rail i { transform: scaleY(1); }

.phase__head { grid-column: 2; display: flex; align-items: flex-start; gap: 1.25rem; }
.phase__body { grid-column: 2; }

.phase__num {
  font-family: var(--mono);
  font-size: var(--t-mono);
  font-weight: 500;
  letter-spacing: var(--tr-mono);
  color: var(--void-ink-2);
  padding-top: 0.9em;
  transition: color var(--mid) var(--ease-in);
}
.phase.is-active .phase__num { color: var(--reagent); }

.phase__name {
  font-size: clamp(3.25rem, 11vw, 9.5rem);
  line-height: 0.84;
  letter-spacing: -0.05em;
  font-variation-settings: 'wdth' 108, 'wght' 600;
  transition: color 1.1s var(--ease-in), -webkit-text-stroke-color 1.1s var(--ease-in);
}
@supports (-webkit-text-stroke: 1px #000) {
  .js .phase__name {
    color: transparent;
    -webkit-text-stroke: 1px var(--void-ink-2);
  }
  .js .phase.is-active .phase__name {
    color: var(--void-ink);
    -webkit-text-stroke-color: transparent;
  }

}

.phase__line {
  font-size: var(--t-lead);
  line-height: 1.4;
  letter-spacing: -0.015em;
  max-width: 34ch;
  /* The gap that used to sit here now belongs under .phase__how: the line
     and the how are one thought and must not be separated by the same
     space that separates the thought from the examples. */
  margin-bottom: 0.7rem;
  text-wrap: balance;
}

/* How the phase is actually done. Secondary in weight, not in importance:
   it is the only place on the page that says plainly what the work is,
   and someone deciding whether to write reads this before anything else. */
.phase__how {
  font-size: clamp(0.95rem, 1.25vw, 1.08rem);
  line-height: 1.55;
  max-width: 46ch;
  color: var(--void-ink-2);
  margin-bottom: clamp(1.75rem, 3vw, 2.5rem);
  /* balance, not pretty: these are two-line statements, and pretty only
     rescues a one-word orphan. Make and Launch were ending on stubs a
     quarter the length of the line above. Think was already even and
     balance leaves it alone. */
  text-wrap: balance;
}

@media (min-width: 1000px) {
  .phase { grid-template-columns: 2px minmax(0, 1.05fr) minmax(0, 1fr); align-items: start; }
  .phase__rail { grid-row: 1 / span 1; }   /* head and body share one row here */
  .phase__head { grid-column: 2; }
  .phase__body { grid-column: 3; padding-top: 0.6rem; }

}

/* ------------------------------------------------------------
   TAGS
   One shared row of labels, used by the method phases, the scope
   table, the capabilities and the work list. Deliberately the
   quietest type on the page: everything in these rows is an example
   of something, never a thing being sold on its own. Colour comes
   from currentColor's neighbours rather than a fixed grey, because
   the method sits on the dark ground.
   ------------------------------------------------------------ */
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  line-height: 1.5;
}
.tags li::after { content: ' ·'; color: var(--rule); }
.tags li:last-child::after { content: ''; }
/* In the method these rows run to ten and thirteen terms, and at the label
   size they were a grey strip the eye skips rather than a list it reads.
   Up a step, with the tracking eased so a long row does not sprawl, and
   with room between the wrapped lines. */
#method .tags {
  font-size: clamp(0.72rem, 0.85vw, 0.8rem);
  letter-spacing: 0.1em;
  gap: 0.55rem 0.7rem;
  line-height: 1.7;
  margin-top: clamp(1.4rem, 2.6vw, 2rem);
}

.section--dark .tags { color: var(--void-ink-2); }
.section--dark .tags li::after { color: var(--void-ink-3, var(--void-ink-2)); }

/* ------------------------------------------------------------
   04 — WHAT WE DO
   Three groupings, set as rows: name on the left, what it covers on
   the right. Rows and not cards, because three cards in a two-column
   grid leave a hole, and because a card implies a package you can
   buy on its own. These are not that.
   ------------------------------------------------------------ */
.do__title { margin-bottom: clamp(2.5rem, 6vw, 4.5rem); }

.do__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}

.area {
  border-top: 1px solid var(--rule);
  padding-block: clamp(1.75rem, 3.5vw, 2.5rem);
}
.area:last-child { border-bottom: 1px solid var(--rule); }
.area__name {
  font-size: var(--t-h3);
  line-height: 1;
  letter-spacing: -0.04em;
  font-variation-settings: 'wdth' 104, 'wght' 500;
}
.area .tags { margin-top: 1rem; }

@media (min-width: 780px) {
  .area {
    display: grid;
    grid-template-columns: minmax(0, 0.34fr) minmax(0, 1fr);
    column-gap: clamp(2rem, 5vw, 5rem);
    align-items: start;
  }
  .area .tags { margin-top: 0.2rem; }
}

/* The one line the section is allowed after the lists. It exists to
   stop the three names reading as three departments. */
.do__note {
  margin-top: clamp(2rem, 4vw, 3rem);
  font-size: clamp(1.15rem, 2.2vw, 1.75rem);
  line-height: 1.2;
  letter-spacing: -0.03em;
  font-variation-settings: 'wdth' 104, 'wght' 500;
}

/* ------------------------------------------------------------
   05 — WHAT COMES INTO THE LAB
   Five kinds of thing and what usually gets worked on in each. Same
   row instrument as the capabilities above, one step quieter: the
   left column is a label here, not a heading.
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   07 — WORK
   A list, not a portfolio grid. No images, no logos, no numbers:
   the name, the industry and the kind of work, and that is the
   whole of what can honestly be shown.
   ------------------------------------------------------------ */
.work__title { margin-bottom: clamp(1rem, 2vw, 1.5rem); }
.work__lead {
  color: var(--ink-2);
  max-width: 52ch;
  text-wrap: pretty;
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

.work__list { border-top: 1px solid var(--rule); }
.job {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.45rem;
  padding-block: clamp(1.4rem, 2.8vw, 2rem);
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 820px) {
  .job {
    grid-template-columns: minmax(0, 0.42fr) minmax(0, 0.2fr) minmax(0, 1fr);
    column-gap: clamp(1.5rem, 3.5vw, 3rem);
    align-items: baseline;
    gap: 0;
  }
}
.job__name {
  font-size: clamp(1.2rem, 2.1vw, 1.7rem);
  line-height: 1.15;
  letter-spacing: -0.03em;
  font-variation-settings: 'wdth' 102, 'wght' 500;
}
.job__field {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: var(--tr-mono);
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ------------------------------------------------------------
   08 — ABOUT
   ------------------------------------------------------------ */
/* The two-column grid and the single lettered portrait are gone with the
   founder block: there are three portraits now and they sit in one row,
   which is the whole point of a firm that is three people and says so. */
.about__title { margin-block: 0 clamp(0.75rem, 1.5vw, 1.25rem); }
#about > .wrap > p:not(.lead) { color: var(--ink-2); max-width: 60ch; }
.note a {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  gap: clamp(1rem, 3vw, 2.5rem);
  align-items: baseline;
  padding-block: clamp(1.25rem, 3vw, 2rem);
  border-bottom: 1px solid var(--rule);
  transition: color var(--fast) var(--ease-in);
}
.note a:hover { color: var(--reagent-deep); }
.note a:hover .arrow { transform: translateX(0.35rem); }
.subscribe__btn:hover .arrow { transform: translateX(0.35rem); }
.subscribe__msg.is-ok { color: var(--ink); }
.subscribe__msg.is-bad { color: var(--reagent-deep); }

/* ------------------------------------------------------------
   10 — FINAL CTA
   ------------------------------------------------------------ */
.close__title {
  margin-block: clamp(1.5rem, 3vw, 2.5rem) clamp(1.5rem, 3vw, 2.5rem);
  /* One line where it fits, evenly split where it does not. It used to be
     broken by hand into "¿Qué estás" and "haciendo?", and the second line
     was short enough to read as something left behind. */
  font-size: clamp(2.75rem, 8vw, 7.5rem);
  text-wrap: balance;
  line-height: 0.88;
  letter-spacing: var(--tr-display);
  font-variation-settings: 'wdth' 106, 'wght' 500;
}
.close__slogan {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: var(--tr-mono);
  text-transform: uppercase;
  color: var(--void-ink-2);
}
.close__grid {
  margin-top: clamp(3rem, 7vw, 5.5rem);
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(3rem, 6vw, 6rem);
  align-items: start;
}
@media (min-width: 900px) {
  .close__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); }

}

.close__left { display: flex; flex-direction: column; align-items: flex-start; gap: clamp(1.5rem, 3vw, 2.25rem); }

/* The answer to the headline, stacked. One noun per line, because the
   point is the range and a comma-separated sentence flattens it. */
.close__kinds {
  font-size: clamp(1.25rem, 2.4vw, 1.9rem);
  line-height: 1.3;
  letter-spacing: -0.03em;
  font-variation-settings: 'wdth' 102, 'wght' 400;
  color: var(--void-ink);
}
.close__note {
  color: var(--void-ink);
  font-size: clamp(1.25rem, 2.4vw, 1.9rem);
  line-height: 1.3;
  letter-spacing: -0.03em;
  font-variation-settings: 'wdth' 102, 'wght' 500;
  margin-top: -0.75rem;
}

.close__note em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.01em;
}

/* What to tell us. Under the invitation and quieter than it: the line
   above asks, this one says what an answer looks like. */
.close__ask {
  margin-top: 0.7rem;
  color: var(--void-ink-2);
  font-size: clamp(1rem, 1.35vw, 1.15rem);
  line-height: 1.5;
  max-width: 40ch;
  text-wrap: pretty;
}

.close__direct {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: auto;
  padding-top: clamp(1.25rem, 3vw, 2rem);
  border-top: 1px solid var(--void-rule);
  width: 100%;
  transition: color var(--fast) var(--ease-in);
}
.close__direct-k {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: var(--tr-mono);
  text-transform: uppercase;
  color: var(--void-ink-2);
}
.close__direct-v {
  font-size: clamp(1.05rem, 2vw, 1.5rem);
  letter-spacing: -0.025em;
}
.close__direct:hover { color: var(--reagent); }
.close__direct:hover .arrow { transform: translateX(0.35rem); }

/* --- enquiry form ---------------------------------------- */
.field {
  border-bottom: 1px solid var(--void-rule);
  padding-block: 0.85rem 0.5rem;
  transition: border-color var(--fast) var(--ease-in);
}
.field:focus-within { border-bottom-width: 2px; border-color: var(--reagent); padding-bottom: calc(0.5rem - 1px); }

.field__label {
  display: block;
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: var(--tr-mono);
  text-transform: uppercase;
  color: var(--void-ink-2);
  margin-bottom: 0.5rem;
}

.field__input {
  width: 100%;
  background: none;
  border: 0;
  padding: 0.2rem 0;
  color: var(--void-ink);
  font-size: clamp(1rem, 1.3vw, 1.1875rem);
  letter-spacing: -0.015em;
  line-height: 1.4;
}
.field__input:focus { outline: none; }
.field__input--area { resize: vertical; min-height: 4.5rem; }

/* THE FIELDS, UNDER A THUMB

   A text input twenty-nine pixels tall is a fine target for a cursor and
   a poor one for a finger, and this is the form the whole page walks
   toward. Fifteen pixels of padding brings each one to forty-five.

   The room comes back out of the field's own frame rather than being
   added to the section: it already runs past a phone screen, and paying
   for the targets in section height would have made that worse. The
   trade is measured — at 390 the fields go 29 to 45 and the section
   grows by fourteen pixels, not by forty-eight. */
@media (pointer: coarse) {
  .field { padding-block: 0.5rem 0.35rem; }
  .field:focus-within { padding-bottom: calc(0.35rem - 1px); }
  .field__label { margin-bottom: 0.3rem; }
  .field__input { padding: 0.7rem 0; }
}

.enquiry__btn {
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  display: inline-flex;
  align-items: center;
  gap: 0.9rem;
  background: var(--paper);
  color: var(--ink);
  border: 0;
  cursor: pointer;
  padding: 1.05rem 1.6rem;
  font-family: var(--mono);
  font-size: var(--t-mono);
  font-weight: 500;
  letter-spacing: var(--tr-mono);
  text-transform: uppercase;
  line-height: 1;
  transition: background var(--fast) var(--ease-in), color var(--fast) var(--ease-in);
}
.enquiry__btn:hover { background: var(--reagent); color: var(--on-reagent); }
.enquiry__btn:hover .arrow { transform: translateX(0.35rem); }
.enquiry__btn[disabled] { opacity: 0.5; cursor: wait; }

.enquiry__msg {
  margin-top: 1.1rem;
  min-height: 1.25rem;
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: var(--tr-mono);
  text-transform: uppercase;
  color: var(--void-ink-2);
}
.enquiry__msg.is-ok { color: var(--void-ink); }
/* The one line a person has to read when the form refuses them, at the
   label size on the void. In plain reagent it sat at 4.30:1 -- under AA
   for anything below 24px, which is exactly what an error message must
   never be. */
.enquiry__msg.is-bad { color: var(--reagent-lift); }
.enquiry__msg a { text-decoration: underline; text-underline-offset: 3px; }

/* ------------------------------------------------------------
   SHAPE → LETTER
   ------------------------------------------------------------ */
.morph {
  margin: clamp(4rem, 9vw, 7rem) 0 0;
}
.morph__stage {
  max-width: 44rem;
  margin-left: auto;   /* centred inside its own column; the hero right-aligns it */
  margin-right: auto;
}
.morph__svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
}
.morph__shape {
  fill: var(--reagent);
}

/* ============================================================
   THE FORK — two starting points, one method
   Both sides carry exactly the same rule, rhythm and type scale:
   the moment one of them gets its own treatment, the page has two
   subjects and the first one loses.
   ============================================================ */
.fork__title { margin-bottom: clamp(2.5rem, 6vw, 4.5rem); }

/* ------------------------------------------------------------
   THE TWO DOORS

   This section asks the reader a question — which of these two is
   you — and it used to present two paragraphs and wait. Now the
   page behaves like something that asked.

   Each door gets its own graduated scale instead of the two of
   them sharing one rule: they are alternatives, not a pair, and a
   single line across both reads as one table with a divider.

   Considering a door runs the reagent along its scale, and the
   question mark of that door — and only that one — takes the
   accent. That is the site's own rule, made literal: magenta
   appears where something reacted, and the reader's attention is
   the reaction. The question gets an answer because they looked.

   Nothing dims and nothing moves out of the way. Both doors stay
   fully readable at rest and while the other is being read; a
   passing pointer must never cost the reader half the section.
   ------------------------------------------------------------ */
.fork__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2.25rem, 4vw, 3rem);
}
@media (min-width: 780px) {
  .fork__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(2rem, 6vw, 5rem); }
}

.fork__door {
  position: relative;
  padding-top: clamp(1.5rem, 3vw, 2.25rem);
  background-repeat: no-repeat;
  background-image:
    linear-gradient(var(--ink), var(--ink)),
    repeating-linear-gradient(90deg, var(--ink-3) 0 1px, transparent 1px 60px),
    repeating-linear-gradient(90deg, var(--rule) 0 1px, transparent 1px 12px);
  background-size: 100% 1px, 100% 7px, 100% 4px;
  background-position: 0 0, 0 1px, 0 1px;
}

.fork__door::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  /* Same reason as the mark under TML: scaled, not widened, so the run
     down the scale costs no layout. */
  height: 1px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left;
  background: var(--reagent);
  transition: transform 0.9s var(--ease);
}

.fork__name {
  font-size: clamp(1.5rem, 2.8vw, 2.25rem);
  line-height: 1;
  letter-spacing: -0.04em;
  font-variation-settings: 'wdth' 104, 'wght' 600;
}

.fork__name { transition: color 0.35s var(--ease); }

/* Only where there is a pointer to consider with. On a touchscreen there
   is no hovering and nothing is missing: both doors read in full.

   The whole question takes the accent, not only its marks: at this size a
   pair of magenta signs around black type reads as two stray dots rather
   than as the door answering. */
@media (pointer: fine) {
  .fork__door:hover::after { transform: scaleX(1); }
  .fork__door:hover .fork__name { color: var(--reagent); }
}

/* Pressed, on a screen with no pointer to hover with. Considering a door
   is the reaction this section is built around — losing it on the phone
   left the reader with two paragraphs and no answer. */
.fork__door.is-live::after { transform: scaleX(1); }
.fork__door.is-live .fork__name { color: var(--reagent); }

/* The mark still lands, it just does not travel to get there. */
@media (prefers-reduced-motion: reduce) {
  .fork__door::after { transition: none; }
  .fork__name { transition: none; }
}
.fork__line {
  margin-top: 0.7rem;
  color: var(--ink-2);
  max-width: 38ch;
  text-wrap: pretty;
}

/* ------------------------------------------------------------
   THE TEAM

   Three panels in a row. The one under the pointer takes room
   from the other two and gives it back when the pointer leaves —
   ported from a React component, which this site is not. Nothing
   was lost in the port: the effect is flex-grow and a transition.

   What did change is what the effect is allowed to carry. The
   original hides every name until hover. Three names on a page
   about who we are cannot be behind a gesture that a phone does
   not have and a keyboard does not do — so the names, the roles
   and the credentials are always there, and widening only reveals
   more of the portrait. On a phone the row becomes a column and
   nothing widens at all, which is the honest version of an effect
   that needs a pointer.
   ------------------------------------------------------------ */
.crew {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  padding-top: clamp(1.25rem, 2.5vw, 1.75rem);
  margin-top: clamp(1.5rem, 3.5vw, 3rem);
  border-top: 1px solid var(--rule);
  width: 100%;
  list-style: none;
}

.crew__member { min-width: 0; }

/* The portrait's place. Neutral until the photographs arrive: put the
   image inside .crew__plate and it fills the frame with no other change.
   The border is structural — it is the edge of a frame, not a shadow. */
.crew__plate {
  position: relative;
  /* Height, not ratio. A ratio would derive the width from the height and
     the frame would stop filling its panel — which kills the whole effect,
     because widening a panel has to widen the portrait in it. So the width
     comes from the panel, the height from the screen, and the photograph
     crops to fill. The cap is also what keeps this section to one page:
     three plates at a full 3:4 run two hundred pixels past the fold. */
  width: 100%;
  height: clamp(11rem, 38vh, 24rem);
  overflow: hidden;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  display: grid;
  place-items: center;
  margin-bottom: clamp(0.9rem, 1.8vw, 1.4rem);
}

.crew__plate > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.crew__initials {
  font-family: var(--serif);
  font-size: clamp(2.5rem, 5vw, 4.5rem);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--rule);
}

.crew__name {
  font-size: clamp(1.05rem, 1.5vw, 1.25rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-variation-settings: 'wdth' 102, 'wght' 500;
  text-wrap: balance;
}

.crew__does {
  margin-top: 0.4rem;
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: var(--tr-mono);
  text-transform: uppercase;
  color: var(--ink-3);
}

.crew__cred {
  margin-top: 0.6rem;
  font-size: clamp(0.85rem, 1.1vw, 0.95rem);
  line-height: 1.5;
  color: var(--ink-2);
  text-wrap: pretty;
}

.crew__cred .dot { color: var(--rule); margin: 0 0.4rem; }

/* On a phone the portrait turns sideways. Three tall plates stacked run
   the section to nearly two screens, and a team of three should be one
   look, not a scroll. A square beside the name says the same thing in a
   fifth of the height. */
@media (max-width: 640px) {
  .crew__member {
    display: grid;
    grid-template-columns: 5.5rem minmax(0, 1fr);
    column-gap: clamp(1rem, 4vw, 1.5rem);
    align-items: start;
  }

  .crew__plate {
    grid-row: 1 / span 3;
    height: auto;
    aspect-ratio: 1;
    margin-bottom: 0;
  }

  .crew__initials { font-size: 1.9rem; }
}

/* The accordion, and only where there is a pointer to drive it. Below
   this the row is a column and every panel is its full self. */
@media (min-width: 860px) and (pointer: fine) {
  .crew {
    display: flex;
    gap: clamp(0.6rem, 1.2vw, 1rem);
  }

  .crew__member {
    flex: 1 1 0;
    /* flex-grow and not width: the three panels stay one row that always
       adds up, so nothing reflows and nothing can fall off the end. */
    transition: flex-grow 0.5s var(--ease);
  }

  /* The two that are not under the pointer give room to the one that is.
     Stated on the list, so leaving the row returns all three at once
     rather than one at a time.

     The second selector repeats .crew:hover on purpose. Without it the
     two rules are three classes against two, the shrink wins over the
     grow, and the panel under the pointer shrinks along with the others
     — the effect looks broken in exactly the way that reads as nothing
     happening at all. */
  .crew:hover .crew__member { flex-grow: 0.78; }
  .crew:hover .crew__member:hover { flex-grow: 1.9; }
}

@media (prefers-reduced-motion: reduce) {
  .crew__member { transition: none; }
}

/* ------------------------------------------------------------
   ADDED WITH THE EDITORIAL PASS
   ------------------------------------------------------------ */

/* Brand line above the headline. The nav carries the mark too, so this
   stays quiet: it anchors the top of the composition, nothing more. */
.hero__eyebrow {
  font-family: var(--mono);
  font-size: var(--t-mono);
  font-weight: 500;
  letter-spacing: var(--tr-mono);
  text-transform: uppercase;
  color: var(--ink-3);
  line-height: 1;
}
.js .hero__eyebrow { opacity: 0; transition: opacity 0.9s var(--ease-in); }
.js.is-loaded .hero__eyebrow { opacity: 1; transition-delay: 0.1s; }
@media (min-width: 1000px) { .hero__eyebrow { grid-column: 1; grid-row: 1; align-self: start; } 
}

/* The one sentence in About: it should split evenly or not at all. */
#about .lead { max-width: 56ch; text-wrap: pretty; }

/* ------------------------------------------------------------
   WORK, SMALLER

   The list steps back a size. It is no longer the only thing in its
   section — the images carry the weight now — and at the old scale
   five rows and a heading fill the screen on their own, which leaves
   the images nowhere to go.

   Sizes only. The grid, the rules and the column proportions are
   untouched, so nothing about how the section is read changes.
   ------------------------------------------------------------ */
#work .work__title { font-size: clamp(1.5rem, 3.2vw, 2.8rem); }

#work .work__lead {
  font-size: clamp(0.95rem, 1.35vw, 1.1rem);
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}

/* .work__list and .job keep their rules: section 08, commented out in the
   markup for now, is built on them. What went are the size overrides for
   this section's list, which no longer has one. */

/* ------------------------------------------------------------
   THE CORRIDOR

   A strip under the list, not a background. It sits in the flow
   and takes the room the list gave back when it stepped down a
   size — nothing floats behind the type.

   container-type is what makes it resolution-independent: every
   length in the animation is cqw, a percentage of THIS box, so
   the corridor keeps its proportions instead of being tuned to
   one screen.
   ------------------------------------------------------------ */
.stream {
  position: relative;
  container-type: inline-size;
  /* It owns the section now, so it takes the room the list gave back
     rather than sitting in a band at the foot of it. */
  height: clamp(13rem, 44vh, 30rem);
  /* Every length in the corridor is cqw — a share of this box WIDTH — so
     on a narrow screen the whole figure shrinks with the width while a
     height in vh does not, and the corridor ends up a thin ribbon adrift
     in an empty frame. Below this the frame is measured in width too. */
  margin-top: clamp(1.5rem, 3.5vw, 3rem);
  overflow: hidden;
}

@media (max-width: 860px) {
  .stream { height: clamp(5.5rem, 34vw, 11rem); margin-top: clamp(1rem, 4vw, 2rem); }
}

.stream__stage {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
}

.stream__plate {
  position: absolute;
  left: 50%;
  overflow: hidden;
  /* Composited on its own layer, and its back never drawn: nine plates
     per rail turning in 3D is a lot of work to hand the compositor
     twice. */
  backface-visibility: hidden;
  border: 1px solid var(--rule);
}

.stream__plate > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Neutral until the artwork lands. Three tones off the page's own
   palette, far enough apart that the corridor has depth and close
   enough that it does not read as a colour statement. */
.stream__plate--a { background: var(--paper-2); }
.stream__plate--b { background: var(--rule); }
.stream__plate--c { background: var(--paper); }

/* Pausing, not disabling. Every plate is already dropped mid-flight by
   its negative delay, so it freezes as a finished still instead of
   collapsing back onto the axis in a heap. */
@media (prefers-reduced-motion: reduce) {
  .stream__plate { animation-play-state: paused !important; }
}
