@import url('fonts.css');

/* =========================================================================
   Método Cristina Castro — landing stylesheet.

   Implements the Claude Design source in design/. That file carries its
   layout in inline styles; here the same design lives in classes so the
   markup stays readable and the responsive behaviour can be reviewed in one
   place. Palette, type scale and radii are unchanged from the design.
   ========================================================================= */

:root {
  /* Palette, straight from the design source. */
  /* Greens, not browns. The client asked for the palette of her reference
     boards: a warm bone page, olive ink, near-black forest for the dark
     blocks. The terracotta accent went too, on a second pass: the boards keep
     it, but the brief was every tone green, so the whole page is now one
     family. --brown was renamed --ink rather than left holding a green. */
  /* Bone, but sitting on the green side of neutral (60-65° rather than the
     45-47° beige it was), so the light surfaces belong to the same family as
     everything on them instead of reading as a warm background under it. */
  --cream: #f4f4ea;   /* page background      */
  --sand: #e5e6d9;    /* secondary surface    */
  --ink: #35402f;     /* ink and dark blocks  */
  --deep: #1f2a1c;    /* footer, phone shells */
  --deep-2: #2b3626;  /* raised on --deep     */
  /* Three greens with three jobs, because one cannot do all of them: a green
     dark enough to carry cream button text is also too close to the ink to
     read as an accent beside it.
       --accent       fills on light, links, icons  (4.97:1 both ways on cream)
       --accent-text  small caps at 11-13px         (5.2 on cream, 4.7 on sand)
       --sage         display italics, and anything on a dark ground
                      (3.3 on cream, 4.1 on the darkest green, 3.0 vs the ink,
                       so the two-tone headline still separates) */
  --accent: #567048;
  --accent-dark: #3f5636;
  --accent-text: #4a6340;
  --sage: #6f8f63;    /* also the affirmative tick */
  /* Sage measures only 2.9:1 against the veil on the reel tiles, and those
     labels are 12px. Same hue, lifted until it clears 4.5. */
  --sage-light: #a3c096;
  --red: #c4574e;     /* negative             */
  --white: #fff;

  --shell: 1200px;
  --pad: 24px;
  --radius: 24px;
  --section-y: clamp(56px, 9vw, 96px);
  --section-y-lg: clamp(64px, 10vw, 112px);

  --serif: 'Playfair Display', 'Iowan Old Style', Georgia, serif;
  --sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  /* The marquee is wider than the viewport by design; nothing else may be. */
  overflow-x: hidden;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

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

a { color: var(--accent); text-decoration: none; transition: color .2s; }
a:hover { color: var(--ink); }

h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 400;
  text-wrap: pretty;
  margin: 0;
}

p { margin: 0; }

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: 50;
  background: var(--ink);
  color: var(--cream);
  padding: 12px 20px;
  border-radius: 0 0 12px 12px;
  font-size: 14px;
  font-weight: 600;
  transition: top .2s;
}
.skip:focus { top: 0; color: var(--cream); }

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

/* --- Brand ---------------------------------------------------------------
   The client's wordmark already says her name, so it is the whole lockup: no
   type beside it. Two files, same artwork recoloured — cream over the hero
   photo and the footers, ink on the light error and legal pages. Regenerate
   both with tools/build-brand.py. */

.site-header {
  position: absolute;
  inset: 0 0 auto;
  z-index: 20;
  padding: clamp(18px, 2.4vw, 30px) var(--pad);
  /* Only the lockup should swallow clicks; the rest of the hero stays free. */
  pointer-events: none;
}
.site-header .brand { pointer-events: auto; }

.brand { display: inline-block; }
.brand:hover { opacity: .8; }
.brand img {
  width: clamp(168px, 19vw, 232px);
  height: auto;
}
/* One lockup per hero, and they are in different places: the phone's sits at
   the foot of the hero over the photograph, so up here the header only exists
   from 900px. */
.site-header { display: none; }
.brand--hero { display: block; margin-bottom: 20px; }
.brand--hero img { width: clamp(160px, 44vw, 200px); }
@media (min-width: 900px) {
  .site-header { display: block; }
  .brand--hero { display: none; }
}

/* Error and legal pages: same wordmark, in ink, on the page background. */
.site-header--plain {
  position: static;
  padding: clamp(24px, 4vw, 40px) var(--pad) 0;
  width: min(800px, 100%);
  margin-inline: auto;
}

/* --- Shared layout ------------------------------------------------------ */

.shell {
  width: min(var(--shell), 100%);
  margin-inline: auto;
  padding-inline: var(--pad);
}
.shell--narrow { --shell: 1100px; }
.shell--tight { --shell: 800px; }

.section { padding-block: var(--section-y); }
.section--lg { padding-block: var(--section-y-lg); }
.section--sand { background: var(--sand); }
.section--white { background: var(--white); }
.section--ink { background: var(--ink); color: var(--cream); }

.section__title {
  font-size: clamp(28px, 3.4vw, 42px);
  line-height: 1.2;
}
.section__lede {
  max-width: 620px;
  margin: 0 auto 56px;
  text-align: center;
  font-size: 17px;
  line-height: 1.7;
  opacity: .7;
}
/* A small line under a title. The page's other small-caps labels sit above
   their heading, but this one qualifies the stories rather than announcing
   them, so it reads after. */
.section__sub {
  margin: 10px 0 48px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent-text);
}

.section__title--centered {
  text-align: center;
  max-width: 820px;
  margin-inline: auto;
}

/* Two-column blocks that stack below ~900px of available width. */
.split {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(40px, 6vw, 64px);
  align-items: center;
  justify-content: center;
}
.split__copy {
  flex: 1 1 380px;
  min-width: 0; /* the design's 300px floor overflows a 320px viewport */
  max-width: 520px;
}

/* --- Buttons ------------------------------------------------------------ */

.btn {
  display: inline-block;
  border: none;
  border-radius: 999px;
  padding: 18px 40px;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .12em;
  text-align: center;
  cursor: pointer;
  transition: background .2s, color .2s, transform .2s;
}
.btn--accent { background: var(--accent); color: var(--cream); }
.btn--accent:hover { background: var(--ink); color: var(--cream); }
.btn--brown { background: var(--ink); color: var(--cream); }
.btn--brown:hover { background: var(--accent); color: var(--cream); }
.btn--light { background: var(--accent); color: var(--cream); }
.btn--light:hover { background: var(--cream); color: var(--ink); }
.btn--block { display: block; width: 100%; padding-inline: 20px; }

/* WhatsApp is the only conversion path on the page, so its button carries the
   channel's own mark — people click what they recognise. */
.btn--wa {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* This one only ever sits on a dark photo band, where any green fill sinks
     into the scrim — so it inverts: bone fill, ink label. */
  background: var(--cream);
  color: var(--ink);
  letter-spacing: .06em;
  font-size: 15px;
  padding: 17px 32px;
}
.btn--wa:hover { background: var(--sage); color: var(--deep); }
.btn--wa svg { width: 22px; height: 22px; flex: none; }

/* The reference boards set every call to action as a black rectangle with an
   arrow, not the rounded pill the design shipped with. The WhatsApp mark
   stays on it: the boards were drawn for a generic "descubrir" link, but every
   button here opens a chat, and hiding that is worse than matching the board
   exactly. */
.btn--ink {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  background: var(--deep);
  color: var(--cream);
  border-radius: 3px;
  padding: 18px 26px;
  font-size: 13px;
  letter-spacing: .13em;
  text-transform: uppercase;
}
.btn--ink:hover { background: var(--accent); color: var(--cream); }
.btn--ink svg { width: 19px; height: 19px; flex: none; }
.btn__arrow { font-size: 15px; letter-spacing: 0; }

.btn--outline {
  background: transparent;
  color: var(--cream);
  border: 1.5px solid rgba(244, 244, 234, .6);
  letter-spacing: .06em;
  font-size: 15px;
  padding: 16px 30px;
}
.btn--outline:hover { background: rgba(244, 244, 234, .14); color: var(--cream); border-color: var(--cream); }

/* --- Photos -------------------------------------------------------------
   Every photo sits in a wrapper the layout has already sized, so the image
   itself just fills it. Listed together because the alternative is repeating
   the same three declarations in nine places. */

.hero__media img,
.marquee__item img,
.phone > img,
.plan360__media img,
.category__disc img,
.portrait img,
.testimonial__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* <picture> only picks the file; the img is what the layout sizes. */
.hero__media picture { display: contents; }

/* She stands on the right of the hero frame; keep her there as the crop
   narrows so the headline keeps the empty dune to itself. Below 700px the
   phone crop is already composed that way, so it is centred. */
.hero__media img { object-position: 68% 50%; }
@media (max-width: 700px) {
  /* Her photograph is 9:16 and the viewport is taller than that, so covering
     it trims the sides. Trimming from the left slides her clear of the
     headline instead of leaving her face behind the type. */
  .hero__media img { object-position: 22% 50%; }
}

/* --- Image placeholders -------------------------------------------------
   Every photo in the design is still pending from the client. Rather than
   ship broken <img> tags, each slot renders as a framed block in the palette
   that names the photo that belongs there. Replacing one means swapping the
   <div class="slot"> for an <img> with the same wrapper — nothing else moves.
   ------------------------------------------------------------------------ */

.slot {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 120px;
  display: grid;
  place-items: center;
  padding: 16px;
  background:
    repeating-linear-gradient(135deg,
      rgba(53, 64, 47, .035) 0 12px,
      transparent 12px 24px),
    linear-gradient(160deg, var(--sand), #dccfb8);
  color: rgba(53, 64, 47, .58);
  overflow: hidden;
}
.slot::after {
  content: '';
  position: absolute;
  inset: 10px;
  border: 1px solid rgba(53, 64, 47, .16);
  border-radius: inherit;
  pointer-events: none;
}
.slot__label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.5;
  max-width: 220px;
}
/* Dark variant: used where the slot sits under light text (hero, cards with
   a gradient scrim) so the composition still reads as intended. */
.slot--dark {
  background:
    repeating-linear-gradient(135deg,
      rgba(244, 244, 234, .04) 0 12px,
      transparent 12px 24px),
    linear-gradient(150deg, #5c3a2e, var(--deep));
  color: rgba(244, 244, 234, .5);
}
.slot--dark::after { border-color: rgba(244, 244, 234, .16); }

/* --- Scroll reveal ------------------------------------------------------ */

.rv {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity .8s ease, transform .8s ease;
}
.rv.is-on { opacity: 1; transform: none; }

/* =========================================================================
   1 · Hero
   ========================================================================= */

/* Two heroes in one, and the phone gets the loud one.

   On a phone the photograph is the hero: it fills the device screen, the copy
   sits over its bottom half on a scrim, and her face keeps the top of the
   frame to itself. From 900px it becomes the light two-column board the client
   sent — copy on cream at the left, photograph bleeding off the right edge.

   Both fill the viewport (100svh, so a phone's collapsing toolbar cannot push
   the button out of reach; 100vh stays as the fallback for older browsers). */

.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: stretch;
  overflow: hidden;
  background: var(--deep);
  color: var(--cream);
}
.hero__media { position: absolute; inset: 0; }
/* The photograph runs at its own size — no enlargement. It was scaled up for
   a while to push her below a block of copy that sat across the whole top of
   the frame; now that the copy splits to the two ends, she falls in the clear
   middle on her own. At a phone's ratio the 9:16 file fits the box
   vertically, so what shows is the whole frame, trimmed at the sides. */
/* Words at both ends of the frame now, so the scrim darkens both and leaves
   the middle — where she is — alone. */
.hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(31, 42, 28, .90) 0%,
    rgba(31, 42, 28, .66) 24%,
    rgba(31, 42, 28, .12) 46%,
    rgba(31, 42, 28, .58) 74%,
    rgba(31, 42, 28, .92) 100%);
  pointer-events: none;
}
/* The copy splits: title at the head of the frame under the lockup, the line
   and the button at its foot, and the photograph between them. */
.hero__copy {
  position: relative;
  /* The copy comes first in the source but the photograph and its scrim are
     positioned too, so without this they paint over it. */
  z-index: 1;
  width: min(var(--shell), 100%);
  margin-inline: auto;
  /* 92px used to clear the lockup floating up here; it moved to the foot, so
     the headline starts near the top of the frame instead. */
  padding: 34px var(--pad) 40px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 32px;
}
/* Over the photograph both of these have to be light: the sage that carries
   them on the desktop hero measures 1.97:1 against the frame behind them. */
.hero__kicker {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .16em;
  color: var(--cream);
  opacity: .9;
}
/* Two sentences, and the second is the turn: it drops to its own line in
   italic sage, which is the one typographic move the whole board is built on
   — the boards set that line in terracotta; here it is the light green. */
.hero h1 {
  font-size: clamp(31px, 8.6vw, 52px);
  line-height: 1.06;
  letter-spacing: -.015em;
  margin: 16px 0 0;
  /* Wide enough that the italic sentence breaks in two lines rather than
     three; on desktop the column itself is the measure. */
  max-width: 19ch;
}
/* The second sentence is the turn: bold, no italic at all. It ran fully
   italic first, which at this size read as a caption rather than as the other
   half of the headline, and then italic on three words, which the client also
   did not want. */
.hero__turn {
  display: block;
  font-weight: 600;
  color: var(--sand);
}
.hero__rule {
  display: none;
  width: 54px;
  height: 1px;
  background: var(--sage);
  opacity: .6;
  margin: 22px 0;
}
.hero__lede {
  font-size: clamp(15px, 4.1vw, 17px);
  line-height: 1.6;
  max-width: 40ch;
  opacity: .85;
}
.hero__note {
  margin-top: 16px;
  font-size: 13px;
  letter-spacing: .02em;
  opacity: .7;
}
.hero .btn { margin-top: 26px; }
/* Near-black on a dark photograph is a hole, so over the phone hero the
   button inverts — same call as the one on the closing bands. */
.hero .btn--ink { background: var(--cream); color: var(--ink); }
.hero .btn--ink:hover { background: var(--sage); color: var(--deep); }

@media (min-width: 900px) {
  .hero {
    display: grid;
    grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr);
    /* One row, filling the section, so the height comes from the viewport and
       not from the photograph: left to itself a 900x1600 file in a 590px
       column is 1049px tall and drags the hero past the screen. */
    grid-template-rows: 1fr;
    background: var(--cream);
    color: var(--ink);
  }
  .hero__copy { align-self: center; }
  /* The photograph stops being the background and becomes the right column,
     with the image absolute inside it so the cell decides the size. */
  .hero__media { position: relative; align-self: stretch; overflow: hidden; }
  .hero__media img {
    position: absolute;
    inset: 0;
    transform: none;
    /* Tuned to the olive frame, which is shot closer than the one before it:
       at 50% she ended up against the right edge of the column. */
    object-position: 34% 44%;
  }
  .hero__scrim { display: none; }
  /* Left edge lines up with every other section's shell; the photograph runs
     off the right edge of the window, as on the boards. */
  .hero__copy {
    /* One block again: splitting head from foot is what the phone frame needs,
       and on a column this tall it would just leave a hole in the middle. */
    display: block;
    margin: 0;
    width: auto;
    padding: clamp(64px, 7vw, 104px) 48px clamp(64px, 7vw, 104px)
             max(var(--pad), calc((100vw - var(--shell)) / 2 + var(--pad)));
  }
  .hero__kicker { color: var(--accent-text); opacity: 1; }
  .hero__turn { color: var(--sage); }
  .hero__rule { display: block; background: var(--accent); opacity: .55; }
  .hero__lede { opacity: .78; }
  .hero__note { opacity: .6; }
  .hero .btn--ink { background: var(--deep); color: var(--cream); }
  .hero .btn--ink:hover { background: var(--accent); color: var(--cream); }
  /* The column is the measure here, so the italic breaks in two rather than
     three lines without a character count guessing at it. */
  .hero h1 { max-width: none; }
}

[hidden] { display: none !important; }

/* =========================================================================
   1b · Before/after strip

   Same mechanics as the marquee: two identical groups and a shift of exactly
   one group plus the gap, so the loop has no seam. The collages keep the
   aspect ratio the client gave them — each one is two panels she paired
   herself, and cropping them to a common card would cut a panel off.
   ========================================================================= */

.changes {
  position: relative;
  overflow: hidden;
  background: var(--sand);
  padding-block: clamp(28px, 4vw, 44px);
}
.changes__kicker {
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .18em;
  color: rgba(53, 64, 47, .55);
  margin-bottom: 22px;
}

/* The kicker is a sentence now, and at 320px it broke leaving "AQUÍ" alone on
   a second line. Tightened just below 380 so it holds one line there; wider
   phones keep the full tracking. */
@media (max-width: 380px) {
  .changes__kicker { font-size: 11px; letter-spacing: .06em; }
}
.changes::before,
.changes::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 8%;
  z-index: 2;
  pointer-events: none;
}
.changes::before { left: 0; background: linear-gradient(90deg, var(--sand), transparent); }
.changes::after { right: 0; background: linear-gradient(270deg, var(--sand), transparent); }

/* One row, seventeen collages. This ran as three rows at two sizes for a while
   — a big middle one between two thin ones, each at its own speed — and it was
   too much motion directly under the hero: three tracks sliding at once read as
   busy rather than as proof. One row, bigger than any of those three, shows the
   same photographs and lets each one be looked at.

   Two identical groups shifted by exactly one group plus half the gap: that is
   what makes the loop seamless. The track does not clip its own overflow — the
   section already does, and clipping here would cut the shadow off the tiles. */
.changes__track {
  display: flex;
  gap: 18px;
  width: max-content;
  animation: changes 84s linear infinite;
}
.changes__group { display: flex; gap: 18px; }
.changes__item {
  height: clamp(190px, 21vw, 310px);
  width: auto;
  border-radius: 18px;
  box-shadow: 0 16px 40px rgba(53, 64, 47, .2);
  background: var(--sand);
}

/* The tiles shrink with the viewport, so a single duration would make the strip
   crawl on a narrow screen — the group it has to travel is that much shorter.
   These steps hold it between roughly 55 and 62 px/s all the way down, which is
   the speed at which a collage is readable as it passes. */
@media (max-width: 1100px) { .changes__track { animation-duration: 72s; } }
@media (max-width: 905px)  { .changes__track { animation-duration: 64s; } }
@media (max-width: 700px)  { .changes__track { animation-duration: 58s; } }

.changes:hover .changes__track,
.changes:focus-within .changes__track { animation-play-state: paused; }

@keyframes changes { to { transform: translateX(calc(-50% - 9px)); } }

@media (prefers-reduced-motion: reduce) {
  .changes__track { animation: none; }
}

/* =========================================================================
   3 · Marquee
   ========================================================================= */

/* The strip now sits between two padded sections (the pillars above, the
   training block below), so those provide its breathing room; adding its own
   padding on top of theirs left a hole. */
/* Sand, like the two blocks above it. The strip declared no background at
   all, which was fine when it sat between cream sections — after it moved
   under the pillars and the video and the figures landed on top of it in
   sand, inheriting the page's cream turned it into a white gap between two
   darker bands. */
.marquee {
  position: relative;
  overflow: hidden;
  background: var(--sand);
  /* Air under the tiles before the next section starts. Above them the strip
     borrows the figures' own bottom padding, so only this side needs it, and
     it is set to the same figure so the band looks evenly packed. */
  padding-bottom: clamp(32px, 6vw, 48px);
}
/* The strip runs off both edges and is faded out so it reads as continuous.
   This was a mask-image, which iOS Safari composites badly on a layer this
   wide and animated: tiles scrolling in from outside the original layer came
   in blank. Two gradient overlays look identical and touch no compositing. */
.marquee::before,
.marquee::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 7%;
  z-index: 2;
  pointer-events: none;
}
.marquee::before { left: 0; background: linear-gradient(90deg, var(--sand), transparent); }
.marquee::after { right: 0; background: linear-gradient(270deg, var(--sand), transparent); }
.marquee__track {
  display: flex;
  gap: 24px;
  width: max-content;
  animation: marquee var(--marquee-duration, 32s) linear infinite;
}
.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track { animation-play-state: paused; }
.marquee__group { display: flex; gap: 24px; align-items: center; }
.marquee__item {
  flex: none;
  width: 280px;
  height: 200px;
  border-radius: var(--radius);
  overflow: hidden;
  /* A tile whose photo has not arrived should still read as a tile rather
     than as a hole in the strip — which now means a shade off the band it
     sits on, not the band's own colour. */
  background: rgba(31, 42, 28, .09);
}
.marquee__item .slot { border-radius: var(--radius); }
.marquee__cta {
  flex: none;
  width: 280px;
  height: 200px;
  border-radius: var(--radius);
  background: linear-gradient(135deg, var(--accent), var(--accent-dark));
  color: var(--cream);
  display: grid;
  place-items: center;
  text-align: center;
  padding-inline: 24px;
  font-family: var(--serif);
  font-size: 24px;
  transition: transform .25s;
}
.marquee__cta:hover { transform: scale(1.03); color: var(--cream); }

@keyframes marquee { to { transform: translateX(calc(-50% - 12px)); } }

/* =========================================================================
   4 · Programa
   ========================================================================= */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: 20px;
  text-align: left;
}
.card {
  background: var(--white);
  border-radius: var(--radius);
  padding: 32px 28px;
  box-shadow: 0 10px 30px rgba(53, 64, 47, .07);
  transition: transform .25s;
}
.card:hover { transform: translateY(-6px); }
/* The icons went with the rewrite: each pillar is numbered now, and a number
   plus a glyph plus a title is one thing too many at this size. */
/* The number sits on its own line above the title. Inline it orphaned itself
   on the fourth card: "Acompañamiento" does not fit beside a number in a
   quarter of the shell, so the line broke after the middot. */
.card__n {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .18em;
  color: var(--accent);
}
/* Sentence case: the four pillars are the answer to the heading above them,
   not four labels, and in caps they read as a menu. The tracking went with
   the capitals — it was there to open them up, and lowercase does not want
   it. */
.card__title {
  font-family: var(--serif);
  font-size: 17px;
  margin: 8px 0 10px;
}
.card__text { font-size: 14px; line-height: 1.6; opacity: .75; }


/* =========================================================================
   4b · Training: her corrections, marked over the client's own video
   ========================================================================= */

.eyebrow {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .18em;
  color: var(--accent-text);
  margin-bottom: 14px;
}
/* Under the heading rather than over it, because this one is a sentence and
   not a category label — and tracked less, since eight words in caps at
   .18em stop being readable. */
.eyebrow--deck {
  margin: 12px 0 24px;
  max-width: 44ch;
  letter-spacing: .1em;
  line-height: 1.5;
}
.lede {
  font-size: 16px;
  line-height: 1.7;
  opacity: .78;
  margin-top: 18px;
  text-wrap: pretty;
}
/* A stand-first: two short sentences that answer the headline before the
   explanation starts, so they sit at full strength rather than at the .78 the
   body copy runs at. */
.lede--strong {
  font-size: clamp(17px, 2vw, 19px);
  line-height: 1.5;
  opacity: 1;
  margin-top: 20px;
}
.corr {
  position: relative;
  flex: 0 0 auto;
  width: min(440px, 100%);
  height: min(560px, 128vw);
}
.corr img {
  position: absolute;
  width: min(238px, 54%);
  height: auto;
  border-radius: 18px;
  box-shadow: 0 24px 50px rgba(53, 64, 47, .22);
}
.corr__a { left: 0; top: 0; z-index: 2; }
.corr__b { right: 0; top: 92px; z-index: 1; }

/* =========================================================================
   5 · Testimonios
   ========================================================================= */

.testimonials {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: 20px;
}
.testimonial {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  height: 420px;
  background: var(--ink);
  box-shadow: 0 12px 32px rgba(53, 64, 47, .15);
}
.testimonial__media { position: absolute; inset: 0; }
.testimonial__scrim {
  position: absolute;
  inset: 0;
  /* Some posters are lit rooms, some are dark: the scrim has to hold white
     text over both. */
  background: linear-gradient(180deg, transparent 26%, rgba(31, 42, 28, .55) 58%, rgba(31, 42, 28, .92) 100%);
  pointer-events: none;
}
.testimonial__body {
  position: absolute;
  left: 20px;
  right: 20px;
  bottom: 20px;
  color: var(--cream);
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: flex-start;
}
.testimonial__quote {
  font-family: var(--serif);
  font-style: italic;
  font-size: 18px;
  line-height: 1.4;
}
.testimonial__name {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .06em;
}
.testimonial__play {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: none;
  background: rgba(244, 244, 234, .92);
  color: var(--accent);
  font-size: 18px;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: transform .2s;
}
.testimonial__play:hover { transform: scale(1.1); }
.btn-ghost {
  background: transparent;
  border: 1.5px solid var(--cream);
  color: var(--cream);
  border-radius: 999px;
  padding: 10px 22px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .12em;
  cursor: pointer;
  transition: background .2s, color .2s;
}
.btn-ghost:hover { background: var(--cream); color: var(--ink); }

/* "Ver más": twelve cards at once is a wall, and on a phone the grid is one
   column, so it is a very long one. Eight show and the rest unfold on demand.
   The fold is applied by JS and so is the button, which means a browser with
   JavaScript off gets all twelve and never sees a control that does nothing. */
.testimonial.is-folded { display: none; }
.testimonial.is-unfolded { animation: testimonial-unfold .5s ease both; }
@keyframes testimonial-unfold {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
.testimonials__more {
  display: block;
  margin: 36px auto 0;
  background: transparent;
  /* The section is sand, so the cream outline of .btn--outline would vanish. */
  border: 1.5px solid rgba(53, 64, 47, .45);
  color: var(--ink);
  border-radius: 999px;
  padding: 16px 34px;
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .12em;
  cursor: pointer;
  transition: background .2s, color .2s, border-color .2s;
}
.testimonials__more:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream);
}
@media (prefers-reduced-motion: reduce) {
  .testimonial.is-unfolded { animation: none; }
}


/* Video lightbox (only wired for testimonials that carry a data-video). */
.lightbox {
  /* The testimonials were filmed on a phone: 9:16. Sizing the dialog off the
     viewport height is what keeps a portrait video on screen whole. */
  border: none;
  padding: 0;
  background: transparent;
  width: min(calc(86vh * 9 / 16), 92vw);
  max-width: 460px;
}
.lightbox::backdrop { background: rgba(31, 42, 28, .82); }
.lightbox__frame {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: #000;
}
.lightbox video {
  width: 100%;
  max-height: 86vh;
  aspect-ratio: 9 / 16;   /* hold the box before metadata loads */
  object-fit: contain;
  background: #000;
  display: block;
}
.lightbox__close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: rgba(244, 244, 234, .9);
  color: var(--ink);
  font-size: 20px;
  cursor: pointer;
}

/* =========================================================================
   6 · App mockups
   ========================================================================= */

/* The two phones are one object: the front one, holding the app's home screen,
   sitting over the one behind it, which holds the recipe book.

   Both are real screenshots run to the edge of the frame, which changes what
   the overlap costs. It used to be free: the phone behind was a drawn card with
   an empty lower third, and the front one was parked on that emptiness. A
   screenshot has no empty third — everything the front phone covers is content.
   So the overlap is derived from what has to stay readable behind it:

       visible band = 62% of the phone
       overlap      = the remaining 38%
       frame height = dark + photo − overlap

   A fraction rather than a pixel count, because the phones scale with the
   viewport and the old 226px band was measured off a card that no longer
   exists. 62% clears the recipe book's header, its tabs and its search field at
   every width; the cut lands inside the first recipe photograph, where a cut
   reads as the phone continuing rather than as a slice.

   Sideways is free by comparison: the shared region is the same at any height,
   so the frame can be as narrow as it likes. It is set so the phone behind
   still shows ~60px of itself down the right, which is what keeps it reading as
   a second handset instead of a shadow.

   Both phones are the same height. A shorter front one buys the same overlap
   in a shorter block, and that was tried, but two matching handsets is what
   reads as a pair.

   tools/check-phones.py measures all of this in a browser at nine widths and
   fails if the overlap disappears or if the band gets too thin to read. */
.phones {
  --back-h: min(500px, 116vw);
  --front-h: var(--back-h);
  --overlap-y: calc(var(--back-h) * .38);   /* leaves 62% of the phone behind readable */
  position: relative;
  flex: 0 0 auto;
  width: min(310px, 100%);    /* narrower than two phones: that is the overlap */
  /* The frame is narrower than the column it sits in, so without this the
     whole stack hangs off the left edge with the slack piled on the right. */
  margin-inline: auto;
  height: calc(var(--back-h) + var(--front-h) - var(--overlap-y));
}
/* No padding and no drawn chrome — no notch, no caption, no cards. The
   screenshot is the screen, edge to edge, which is the only way it reads as a
   handset instead of as a picture of one pasted inside a card. The hairline
   and the radius are the whole frame. */
.phone {
  position: absolute;
  width: min(250px, 58vw);
  border-radius: 36px;
  overflow: hidden;
  border: 1px solid var(--sand);
  background: var(--cream);   /* stands in while the screenshot loads */
}
/* Sizing comes from the shared photo rule up top. Both sources are cropped to
   1:2 — the frame's own ratio — so its cover has nothing left to crop and the
   interface is never stretched. */
.phone > img { display: block; }
.phone--back { height: var(--back-h); }
.phone--front { height: var(--front-h); }
/* Behind the front phone and above it in the frame. Only its top band is ever
   read, so it carries the screen whose own header explains it. */
.phone--back {
  right: 0;
  top: 0;
  z-index: 1;
  box-shadow: 0 30px 60px rgba(53, 64, 47, .35);
}
/* The home screen leads the stack: it is the one that answers the section —
   the training of the day, and the Chat and Nutrición tabs under it. Anchored
   to the bottom rather than offset from the top so the overlap survives the
   phone and container heights shrinking at different rates on small screens. */
.phone--front {
  left: 0;
  bottom: 0;
  z-index: 2;
  box-shadow: 0 30px 60px rgba(53, 64, 47, .26);
}
/* The caption goes under the whole mockup, not under the photograph: inside
   the stack the front phone sits on top of it. */
.phones-wrap { flex: 0 0 auto; width: min(480px, 100%); }
/* The line that closes the section: it answers the objection the rest of the
   copy raises, so it is ruled off rather than run on as another paragraph. */
.app__close {
  margin-top: 20px;
  padding-left: 16px;
  border-left: 2px solid var(--accent);
  font-size: 15px;
  line-height: 1.65;
  opacity: .8;
  text-wrap: pretty;
}

.phones__cap {
  margin-top: 14px;
  font-size: 12px;
  line-height: 1.5;
  opacity: .6;
  text-align: center;
}

/* =========================================================================
   7 · Plan 360
   ========================================================================= */

/* The copy carries the section, so it is typeset here rather than in inline
   styles on the markup, which is what it had before.

   Lower case, like every other heading she has been through: capitals turned a
   sentence written as a concession into a slogan being shouted. Two points
   larger than it was, because dropping the capitals costs a line its presence
   and this one has to hold a column of its own against the photograph. */
.plan360__title {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(28px, 3.7vw, 44px);
  line-height: 1.16;
  letter-spacing: .01em;
}
/* The second sentence is the answer to the first, so it drops to its own line
   in sage — the same two-part shape the hero uses. */
.plan360__title span {
  display: block;
  color: var(--sage);
}
.plan360__list {
  margin-top: 22px;
  font-size: clamp(16px, 1.7vw, 18px);
  line-height: 1.6;
  color: var(--sand);
}
.plan360__text {
  margin-top: 16px;
  font-size: 16px;
  line-height: 1.7;
  color: rgba(244, 244, 234, .75);
}
.plan360__ask {
  margin-top: 24px;
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(19px, 2.2vw, 24px);
  line-height: 1.35;
  color: var(--sage);
}

.plan360 {
  position: relative;
  flex: 0 0 auto;
  width: min(420px, 90vw);
  height: 520px;
}
.plan360__media {
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
  overflow: hidden;
}
.plan360__media .slot { border-radius: var(--radius); }
.chip {
  position: absolute;
  background: var(--cream);
  color: var(--ink);
  border-radius: 16px;
  padding: 12px 18px;
  font-size: 13px;
  font-weight: 600;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .25);
  white-space: nowrap;
}
.chip--1 { top: 28px; left: -8px; }
.chip--2 { top: 120px; right: -8px; }
.chip--3 { top: 230px; left: -10px; }
.chip--4 { bottom: 130px; right: -8px; }
.chip--5 { bottom: 32px; left: -6px; }

/* =========================================================================
   8 · Categorías
   ========================================================================= */

.lead-line {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(22px, 2.6vw, 30px);
  margin-bottom: 56px;
  text-align: center;
}
.lead-line__sub {
  max-width: 560px;
  margin: -34px auto 48px;
  text-align: center;
  font-size: 16px;
  line-height: 1.7;
  opacity: .78;
}
.lead-line__sub a { font-weight: 600; white-space: nowrap; }
.categories {
  display: flex;
  flex-wrap: wrap;
  gap: 32px;
  justify-content: center;
}
.category {
  color: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.category__disc {
  width: 150px;
  height: 150px;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 12px 28px rgba(53, 64, 47, .12);
  transition: transform .25s;
}
.category:hover .category__disc { transform: scale(1.05); }
.category__disc .slot { border-radius: 50%; min-height: 0; }
.category__disc .slot__label { font-size: 10px; letter-spacing: .1em; }
.category__name { font-size: 14px; font-weight: 600; letter-spacing: .1em; }
.category:hover .category__name { color: var(--accent); }
.category__disc { display: block; }

/* =========================================================================
   8b · Community: what the group sounds like from inside
   ========================================================================= */

.community {
  flex: 1 1 380px;
  min-width: 0;
  max-width: 520px;
  columns: 2 200px;
  column-gap: 16px;
}
.community__item {
  width: 100%;
  height: auto;
  margin-bottom: 16px;
  border-radius: 14px;
  break-inside: avoid;
  box-shadow: 0 10px 26px rgba(53, 64, 47, .10);
}

@media (max-width: 560px) {
  .community { columns: 1; }
}

/* =========================================================================
   9 · Comparativa · 10 · Filtro
   ========================================================================= */

.duo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 24px;
  text-align: left;
}
.panel {
  border-radius: var(--radius);
  padding: 36px 32px;
}
.panel--pro { background: var(--cream); border: 1.5px solid var(--sage); }
.panel--con { background: var(--cream); border: 1.5px solid var(--sand); }
.panel--white { background: var(--white); box-shadow: 0 12px 32px rgba(53, 64, 47, .08); padding: 40px 36px; }
.panel--ink { background: var(--ink); color: var(--cream); padding: 40px 36px; }
.panel__title {
  font-family: var(--serif);
  font-size: 22px;
  margin-bottom: 24px;
}
.panel__title--lg { font-size: 26px; }
.panel--con .panel__title { opacity: .7; }

.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  font-size: 15px;
  line-height: 1.5;
}
.checklist li { display: flex; gap: 12px; }
.checklist li::before {
  content: '✓';
  flex: none;
  color: var(--sage);
  font-weight: 700;
}
.checklist--no li::before { content: '✗'; color: var(--red); }

/* The line that closes each column of the "es / no es para ti" pair: her own
   words, aimed at the reader rather than another bullet. */
.panel__foot {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid rgba(53, 64, 47, .14);
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  line-height: 1.5;
}
.panel--ink .panel__foot { border-top-color: rgba(244, 244, 234, .22); }
.panel--con .checklist { opacity: .85; }

/* =========================================================================
   9b · Comidas de las clientas

   A mosaic of square tiles: the photographs arrive from phones, in every
   aspect ratio there is, so a fixed square with object-fit is what keeps the
   grid from turning into a ragged wall.
   ========================================================================= */

.meals__kicker {
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .18em;
  color: var(--accent-text);
  margin-bottom: 14px;
}
.meals__lede {
  text-align: center;
  max-width: 620px;
  margin: 18px auto 0;
  font-size: 16px;
  line-height: 1.7;
  opacity: .75;
  text-wrap: pretty;
}
.meals {
  /* Fixed counts rather than auto-fit: eight tiles need to land as 2×4 or
     4×2, never as a 5 + 3 with a hole in the second row. */
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
  margin-top: 44px;
}
@media (min-width: 640px) {
  .meals { grid-template-columns: repeat(4, 1fr); }
}
.meals__item {
  aspect-ratio: 1;
  border-radius: 18px;
  overflow: hidden;
  box-shadow: 0 8px 22px rgba(53, 64, 47, .10);
}
.meals__item img { width: 100%; height: 100%; object-fit: cover; }
.meals__item .slot { min-height: 0; border-radius: 18px; }

/* --- Segunda tanda: fuera de casa -----------------------------------------
   Same tiles, three across instead of four, because here the background is
   half the argument — the bar's placemat, the office desk, the café table —
   and at a quarter of the width it disappears.

   It had a heading and a lede of its own; both came out on her say-so, so the
   rule is now the only thing separating the two mosaics, which is all it ever
   needed to be — and with nothing to introduce, it wants equal air on both
   sides rather than the deep well a heading needed. 72px above; 28px here plus
   the 44px every .meals grid carries makes 72px below. The tiles also dropped
   the 36px margin that used to clear the lede, which stacked on top of all of
   this and left the rule hugging the paragraph above. */
.meals-out {
  margin-top: 72px;
  padding-top: 28px;
  border-top: 1px solid rgba(53, 64, 47, .14);
}
.meals--out { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 640px) {
  .meals--out { grid-template-columns: repeat(3, 1fr); }
}
.meals__item .slot__label { font-size: 10px; letter-spacing: .12em; }

/* =========================================================================
   11 · Sobre Cristina
   ========================================================================= */

.portrait {
  flex: 0 0 auto;
  width: min(380px, 90vw);
  height: 460px;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 24px 50px rgba(53, 64, 47, .18);
}
.portrait .slot { border-radius: var(--radius); }
/* Her story runs long, so the portrait grows with it instead of leaving a
   column of sand next to five paragraphs. */
.portrait--tall { height: 620px; }
.about { align-items: flex-start; }
.about__copy { max-width: 600px; }
@media (max-width: 900px) {
  .portrait--tall { height: 480px; }
}
.prose {
  font-size: 17px;
  line-height: 1.8;
  text-wrap: pretty;
}
.prose em { font-family: var(--serif); font-style: italic; }
.prose + .prose { margin-top: 18px; }
/* "No lo es. Y se sale. Yo soy la prueba." — the turn in her story. */
.prose--lead {
  font-family: var(--serif);
  font-size: clamp(20px, 2.2vw, 24px);
  line-height: 1.4;
}

/* =========================================================================
   12 · 6 pasos
   ========================================================================= */

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 20px;
  text-align: left;
  list-style: none;
  margin: 0;
  padding: 0;
}
.step {
  background: var(--white);
  border-radius: var(--radius);
  padding: 32px 28px;
  box-shadow: 0 10px 30px rgba(53, 64, 47, .07);
  display: flex;
  gap: 20px;
  align-items: flex-start;
  transition: transform .25s;
}
.step:hover { transform: translateY(-6px); }
.step__n {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--cream);
  display: grid;
  place-items: center;
  font-family: var(--serif);
  font-size: 20px;
}
.step__title { font-family: var(--serif); font-size: 20px; margin-bottom: 6px; }
.step__text { font-size: 14px; line-height: 1.6; opacity: .7; }

/* =========================================================================
   12b · Messages from clients

   Screenshots, published as they arrived. A masonry column keeps each one at
   its own height, which is what makes the wall read as a phone full of
   messages rather than as a grid of cards someone designed.
   ========================================================================= */

/* Lower case here, unlike the band after the hero: the line is a quiet
   observation, and capitals made it read as another claim being shouted. The
   weight on one word carries the emphasis instead. */
.msgs__title strong { font-weight: 700; }
/* Five things a scale cannot weigh, one per line. No markers: it is a litany,
   not a list of features. */
.msgs__list {
  list-style: none;
  margin: 22px auto 0;
  padding: 0;
  max-width: 40ch;
  text-align: center;
  font-size: clamp(16px, 4.2vw, 19px);
  line-height: 1.85;
  opacity: .85;
}
.msgs__lede {
  max-width: 620px;
  margin: 18px auto 0;
  text-align: center;
  font-size: 16px;
  line-height: 1.7;
  opacity: .75;
  text-wrap: pretty;
}
/* The one fact that used to sit in the intro: these are unedited. It reads
   better as a footnote to the wall than as a claim before it. */
.msgs__note {
  margin-top: 22px;
  text-align: center;
  font-size: 13px;
  opacity: .6;
}
.msgs {
  columns: 3 260px;
  column-gap: 18px;
  margin-top: 44px;
}
.msgs__item {
  width: 100%;
  height: auto;
  margin-bottom: 18px;
  border-radius: 14px;
  break-inside: avoid;
  box-shadow: 0 10px 26px rgba(53, 64, 47, .10);
}

@media (max-width: 560px) {
  .msgs { columns: 1; }
}

/* =========================================================================
   13 · FAQ — native <details>, exclusive via the name attribute.
   ========================================================================= */

.faq {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.faq__item {
  background: var(--white);
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 6px 20px rgba(53, 64, 47, .05);
}
.faq__q {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 22px 26px;
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after {
  content: '+';
  flex: none;
  font-size: 22px;
  color: var(--accent);
  transition: transform .3s;
}
.faq__item[open] .faq__q::after { transform: rotate(45deg); }
.faq__a {
  /* 0fr → 1fr animates without hard-coding a max-height. */
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .35s ease;
}
.faq__item[open] .faq__a { grid-template-rows: 1fr; }
.faq__a > div { overflow: hidden; }
.faq__a p {
  padding: 0 26px 22px;
  font-size: 15px;
  line-height: 1.7;
  opacity: .75;
}

/* =========================================================================
   14 · CTA bands — the mid-page one and the closing one

   The mid-page one: a photograph of her out in the desert, a scrim that
   darkens the side the copy sits on, and one WhatsApp button. The scrim runs
   left-to-right on wide screens (copy on the dune, her on the right, like the
   hero) and top-to-bottom on a phone, where there is no room to keep them
   apart. The closing one was the same component until 24 Aug; it is now a
   portrait beside the copy and keeps only this block's type — see .close.
   ========================================================================= */

.band {
  position: relative;
  display: grid;
  align-items: center;
  min-height: 480px;
  padding-block: clamp(64px, 9vw, 104px);
  overflow: hidden;
  background: var(--ink);
  color: var(--cream);
}

.band__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 62% 50%;
}
.band__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg,
    rgba(31, 42, 28, .92) 0%,
    rgba(31, 42, 28, .72) 42%,
    rgba(31, 42, 28, .25) 78%,
    rgba(31, 42, 28, .10) 100%);
}
.band__inner {
  position: relative;
  max-width: 640px;
  margin-inline: 0;
  padding-inline: var(--pad);
}
/* Keep the copy on the shell's left edge instead of the viewport's. */
@media (min-width: 1248px) {
  .band__inner { margin-left: max(var(--pad), calc((100vw - 1200px) / 2)); }
}
.band__kicker {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .18em;
  color: rgba(244, 244, 234, .72);
  margin-bottom: 18px;
}
.band__title {
  font-size: clamp(30px, 4vw, 50px);
  line-height: 1.12;
  margin-bottom: 20px;
}
.band__text {
  font-size: clamp(16px, 1.5vw, 18px);
  line-height: 1.7;
  color: rgba(244, 244, 234, .82);
  margin-bottom: 34px;
  text-wrap: pretty;
}
/* The closing band is deliberately sparse: kicker, headline, one line, button.
   It used to carry a lede and two long paragraphs of hers as well, and by the
   time a visitor reached the button she had read six blocks of text on top of
   the whole page above. The one line that stayed is the last beat before the
   button, which is the only place that argument still earns its space. */

/* The closing argument: three paragraphs of hers between the headline and the
   button, set quieter than the headline and wider than the note. */
.band__aside {
  max-width: 56ch;
  margin: 26px auto 0;
  text-align: center;
}
.band__aside p {
  font-size: clamp(15px, 4vw, 16px);
  line-height: 1.75;
  color: rgba(244, 244, 234, .82);
}
.band__aside p + p { margin-top: 14px; }

/* Same reassurance the hero gives, repeated where she has to decide. */
.band__note {
  margin-top: 18px;
  font-size: 13px;
  letter-spacing: .02em;
  color: rgba(244, 244, 234, .72);
}
/* The closing button carries the page: it is the last thing asked. This rule
   went missing when the flat closing section became a photo band. */
.btn--wa-lg { font-size: 16px; padding: 20px 40px; }

@media (max-width: 860px) {
  .band { min-height: 0; }
  /* No room for copy and photograph side by side: she goes behind, and the
     scrim turns vertical so the text keeps its contrast. */
  .band__bg { object-position: 66% 40%; }
  .band__scrim {
    background: linear-gradient(180deg,
      rgba(31, 42, 28, .42) 0%,
      rgba(31, 42, 28, .74) 42%,
      rgba(31, 42, 28, .90) 100%);
  }
  .band__inner { max-width: none; }
}

/* --- The closing section ------------------------------------------------
   The mid band is still a full-bleed photograph. This one stopped being one.
   Every picture Cristina chose to end the page on is a portrait phone shot,
   and a 2:1 strip cut out of a portrait leaves an arm and a chin — all four
   candidates were rendered in the band and all four lost her. So the close
   keeps the band's ink ground and its type, and stands her beside the copy at
   the shape the photograph actually is. Below 860px the split wraps on its
   own: she comes first, then the argument, then the button. */
.close { align-items: center; }
.portrait--close {
  width: min(420px, 90vw);
  height: 560px;
  box-shadow: 0 30px 60px rgba(15, 20, 13, .45);
}
.close__copy { max-width: 560px; }
/* Beside a photograph the copy is a column, not a centred block. */
.close .band__aside {
  max-width: none;
  margin-inline: 0;
  text-align: left;
}
/* 50px in a 560px column wrapped the headline to four lines. */
.close .band__title {
  font-size: clamp(28px, 3.4vw, 42px);
  margin-bottom: 18px;
}

@media (max-width: 900px) {
  .portrait--close { height: 460px; }
}

/* =========================================================================
   15 · Footer
   ========================================================================= */

.footer {
  background: var(--deep);
  color: rgba(244, 244, 234, .6);
  text-align: center;
  padding: 40px 24px;
  font-size: 13px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: center;
}
.footer a { color: rgba(244, 244, 234, .8); }
.footer a:hover { color: var(--cream); }
.footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  justify-content: center;
}
.footer__mark { width: 190px; height: auto; margin-bottom: 8px; opacity: .85; }
.footer__credit { font-size: 12px; opacity: .75; }

/* =========================================================================
   Consent
   -------------------------------------------------------------------------
   Only index.html has a tracker, so only index.html has this. It sits on the
   deep green the footer uses, so it reads as part of the site rather than as
   a browser chrome bolted on top, and both answers are the same size — a
   "Rechazar" styled as a whisper next to a filled "Aceptar" is a dark pattern
   and would also make the consent worthless.
   ========================================================================= */

.consent {
  position: fixed;
  z-index: 60;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  width: min(680px, calc(100vw - 32px));
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 20px;
  padding: 16px 20px;
  border-radius: 18px;
  background: var(--deep);
  color: rgba(244, 244, 234, .88);
  box-shadow: 0 20px 50px rgba(15, 20, 13, .45);
}
.consent__text {
  flex: 1 1 300px;
  min-width: 0;
  font-size: 13px;
  line-height: 1.6;
}
.consent__text a { color: var(--sage-light); text-decoration: underline; }
.consent__actions {
  display: flex;
  gap: 10px;
  flex: 0 0 auto;
}
.consent__btn {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  padding: 11px 20px;
  border-radius: 999px;
  border: 1px solid rgba(244, 244, 234, .35);
  background: transparent;
  color: var(--cream);
  cursor: pointer;
}
.consent__btn:hover { border-color: var(--cream); }
.consent__btn--yes {
  background: var(--sage);
  border-color: var(--sage);
  color: var(--deep);
}
.consent__btn--yes:hover { background: var(--sage-light); border-color: var(--sage-light); }

/* Shown on privacidad.html beside the withdraw button. */
.consent-state { font-size: 14px; opacity: .75; }

@media (max-width: 520px) {
  .consent { gap: 12px; }
  .consent__actions { flex: 1 1 100%; }
  .consent__btn { flex: 1 1 0; }
}

/* =========================================================================
   Error page
   ========================================================================= */

.error {
  min-height: 100vh;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 48px 24px;
}
.error__code {
  font-family: var(--serif);
  font-size: clamp(72px, 18vw, 140px);
  line-height: 1;
  color: var(--accent);
}
.error h1 { font-size: clamp(26px, 4vw, 38px); margin: 16px 0 12px; }
.error p { max-width: 460px; margin: 0 auto 32px; opacity: .75; line-height: 1.7; }

/* =========================================================================
   Legal pages
   ========================================================================= */

.legal { padding-block: clamp(48px, 8vw, 80px); }
.legal h1 { font-size: clamp(30px, 4vw, 44px); margin-bottom: 8px; }
.legal__meta { font-size: 13px; opacity: .6; margin-bottom: 40px; }
.legal h2 {
  font-size: clamp(20px, 2.4vw, 26px);
  margin: 40px 0 12px;
}
.legal p, .legal li { font-size: 16px; line-height: 1.8; }
.legal ul { padding-left: 20px; }
.legal li { margin-bottom: 8px; }
.legal .todo {
  background: var(--sand);
  border-left: 3px solid var(--accent);
  padding: 2px 8px;
  border-radius: 4px;
  font-weight: 600;
}
.legal__back { display: inline-block; margin-top: 48px; font-weight: 600; }

/* =========================================================================
   Vídeo del método
   ========================================================================= */

.vsl { padding-block: var(--section-y); background: var(--sand); }
.vsl__head { text-align: center; }
.vsl__kicker {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .16em;
  color: var(--accent-text);
}
.vsl__title {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(26px, 7vw, 40px);
  line-height: 1.14;
  margin: 14px 0 0;
}
/* The invitation, between the title and the video it is inviting you into. */
.vsl__lede {
  margin: 18px auto 28px;
  max-width: 54ch;
  font-size: clamp(15px, 4vw, 17px);
  line-height: 1.7;
  opacity: .78;
}
/* Full bleed, and the same 16:9 the file is, so nothing crops: the subtitles
   are burned into the bottom of the frame and any crop that eats them leaves
   the video mute for anyone watching without sound. Capped in viewport height
   so a wide screen does not hand over a 720px-tall block. */
.vsl__stage {
  position: relative;
  aspect-ratio: 16 / 9;
  max-height: 78vh;
  background: var(--deep);
  overflow: hidden;
}
.vsl__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--deep);
}

@media (min-width: 900px) {
  /* Inset from the edges once there is room, so it reads as a framed piece of
     the page rather than a full-width interruption. */
  .vsl__stage {
    width: min(var(--shell), calc(100% - var(--pad) * 2));
    margin-inline: auto;
    border-radius: var(--radius);
    box-shadow: 0 30px 60px rgba(31, 42, 28, .22);
  }
}

/* The closing statement under the six steps: the point of the whole section,
   so it gets its own weight rather than reading as a seventh step. */
.steps__close {
  max-width: 60ch;
  margin: clamp(40px, 7vw, 64px) auto 0;
  text-align: center;
}
.steps__close-lead {
  font-family: var(--serif);
  font-size: clamp(24px, 6vw, 38px);
  line-height: 1.2;
}
.steps__close-text {
  margin-top: 16px;
  font-size: clamp(15px, 4vw, 17px);
  line-height: 1.7;
  opacity: .75;
}

/* =========================================================================
   Directos de Instagram
   ========================================================================= */

/* Cards, not embeds. Nothing on this page calls a third party, which is the
   whole reason it ships without a cookie banner, and an Instagram embed would
   end that for a thumbnail. */
.reels__kicker {
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .16em;
  color: var(--accent-text);
  margin-bottom: 14px;
}
.reels__lede {
  max-width: 52ch;
  margin: 16px auto 0;
  text-align: center;
  font-size: 16px;
  line-height: 1.7;
  opacity: .75;
}
.reels {
  display: grid;
  gap: 14px;
  margin-top: 28px;
}
/* Photo tiles. The covers come off Instagram with whatever framing the reel
   had — some are letterboxed, all carry its play badge — so they run behind a
   heavy veil rather than as crisp thumbnails: the bars disappear, the badge
   reads as texture, and nineteen cards of wildly different origin end up
   looking like one set. */
.reel {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 230px;
  padding: 22px;
  border-radius: 18px;
  overflow: hidden;
  isolation: isolate;
  background: var(--ink);
  color: var(--cream);
  transition: transform .25s;
}
.reel__bg,
.reel__veil {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
}
/* Blurred, not just darkened. Several covers carry their own burned-in
   headline — "DIRECTO CON LOURDES", "¿Te dijeron que después de ser mamá…" —
   and behind a plain veil that type fights the card's own words. Out of focus
   it stops competing and reads as colour. Scaled slightly so the blur has
   pixels to bleed into instead of showing a soft edge. */
.reel__bg {
  object-fit: cover;
  filter: blur(7px) saturate(.85);
  transform: scale(1.08);
}
.reel__veil {
  background: linear-gradient(180deg,
    rgba(31, 42, 28, .62) 0%,
    rgba(31, 42, 28, .74) 46%,
    rgba(31, 42, 28, .94) 100%);
}
.reel:hover { color: var(--cream); transform: translateY(-3px); }
.reel:hover .reel__bg { opacity: .9; }
.reel__who {
  font-family: var(--serif);
  font-size: 21px;
  line-height: 1.2;
}
.reel__line {
  margin-top: 8px;
  font-size: 15px;
  line-height: 1.6;
  opacity: .88;
}
.reel__go {
  display: inline-block;
  margin-top: 14px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--sage-light);
}
.reel--wide {
  margin-top: 28px;
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream);
}
.reel--wide .reel__who { font-size: 24px; }
.reel--wide .reel__line { opacity: .82; }
.reel--wide .reel__go { color: var(--sage); }
.reel--wide:hover { color: var(--cream); border-color: var(--sage); }
/* Hers carry a title and no story, so they need no room for one. */
.reels--mine { margin-top: 24px; }
.reel--mine { background: var(--white); }
.reel--mine .reel__who { font-size: 19px; }

@media (min-width: 700px) {
  .reels { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1040px) {
  .reels { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .reels--mine { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* =========================================================================
   Cifras y cita
   ========================================================================= */

/* Two columns on a phone, four once there is room. The dividers are drawn with
   borders on the grid items rather than separate elements, so they reflow with
   the grid instead of needing their own breakpoint. */
.stats { background: var(--sand); padding-block: clamp(32px, 6vw, 48px); }
.stats__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(24px, 5vw, 36px) 0;
}
.stat { text-align: center; padding-inline: 12px; }
.stat:nth-child(even) { border-left: 1px solid rgba(53, 64, 47, .16); }
.stat__n {
  font-family: var(--serif);
  font-size: clamp(30px, 8vw, 42px);
  line-height: 1;
  color: var(--accent);
}
/* "1 objetivo" is ten characters where the others are four to six, and at two
   columns on a phone it runs past its cell. It shrinks there and comes back to
   full size once there is room, so the row stays even on a wide screen. */
.stat__n--long { font-size: clamp(21px, 5.4vw, 42px); }
.stat__k {
  margin-top: 8px;
  font-size: clamp(11px, 3vw, 12px);
  letter-spacing: .1em;
  text-transform: uppercase;
  line-height: 1.4;
  opacity: .65;
}

@media (min-width: 760px) {
  .stats__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .stat:nth-child(n + 2) { border-left: 1px solid rgba(53, 64, 47, .16); }
}

/* The turn, dark, with nothing else on the screen to argue with it. It was a
   pull quote of hers and is now the argument itself: display serif for the
   line she wants read first, the text face for the three that explain it. */
.turn {
  background: var(--deep);
  color: var(--cream);
  padding-block: clamp(52px, 10vw, 96px);
  text-align: center;
}
/* Lower case, and the one word the sentence turns on in bold. She asked for
   this the same way she asked for it on the pillars and on the scale heading:
   in capitals the line reads as a claim being announced, and it is meant to be
   the thing the reader already knows said back to her, quietly.
   It also has to hold one line — "adelgazar" dropping alone underneath was the
   specific thing she pointed at.

   So the size is derived from the line rather than picked. The heading is
   15.74x its own font-size wide, and the shell it sits in is the viewport less
   48px of padding up to an 800px cap, so 6.3vw − 3.2px is the largest size that
   still fits across. That holds one line down to 480px, where the 27px floor
   takes over and it has to wrap; balance splits it "Probablemente ya / sabes
   adelgazar" rather than leaving the word alone on the second line, which is
   the shape she objected to. Re-measure if the wording changes. */
.turn__title {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(27px, calc(6.3vw - 3.2px), 46px);
  line-height: 1.14;
  letter-spacing: .01em;
  text-wrap: balance;
}
.turn__title strong { font-weight: 700; }
.turn__lead {
  margin: 22px auto 0;
  max-width: 34ch;
  font-size: clamp(17px, 4.6vw, 21px);
  line-height: 1.5;
  color: var(--sand);
}
.turn__text {
  margin: 18px auto 0;
  max-width: 46ch;
  font-size: clamp(15px, 4vw, 17px);
  line-height: 1.75;
  opacity: .8;
}
/* The last line stands on its own — it is the hinge into the rest. */
.turn__close {
  margin-top: 30px;
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(19px, 5vw, 26px);
  line-height: 1.3;
  color: var(--sage);
}

/* Its closing headline carries the same two-part shape as the hero, so it now
   carries the same treatment too: the turn drops to its own line in bold, with
   no italic anywhere. It ran italic here after the hero had already dropped it,
   which left the page making its two most important lines two different ways —
   and at this size the italic read as a caption under the headline rather than
   as the half of it that closes the argument. */
.band__title em {
  display: block;
  font-style: normal;
  font-weight: 600;
  color: var(--sand);
}

/* The filter now announces itself before the two columns; this is the second
   half of that opening line. */
.filtro__sub {
  max-width: 40ch;
  margin: 14px auto 48px;
  text-align: center;
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 4.6vw, 24px);
  line-height: 1.35;
  color: var(--accent);
}

/* =========================================================================
   Responsive
   ========================================================================= */

@media (max-width: 900px) {
  /* The two phones keep overlapping down to the smallest screen — one behind
     the other is the whole point of the mockup, and stacking them read as two
     unrelated screenshots. They shrink instead: two of them are wider than the
     column, which is exactly what produces the overlap.

     Only the sizes change here. The overlap is a fraction of the phone now, so
     it needs no second value at this breakpoint: it followed the pixel band the
     drawn chart ended at, and there is no chart any more. */
  .phones {
    --back-h: min(460px, 124vw);
    --front-h: var(--back-h);
    width: min(300px, 100%);
  }
  .phone { width: min(240px, 62vw); }

  /* The chips stay pinned to the photograph. Stacking them underneath turned
     the five inputs the plan is built from into a loose row of pills with
     nothing to point at. They move inside the frame instead of hanging off
     its edges, which is what would overflow a phone. */
  .plan360 { width: min(420px, 100%); height: auto; }
  .plan360__media { position: relative; height: min(460px, 118vw); }
  .plan360__chips { position: absolute; inset: 0; pointer-events: none; }
  .chip {
    font-size: 11.5px;
    padding: 8px 12px;
    border-radius: 12px;
    box-shadow: 0 8px 20px rgba(0, 0, 0, .28);
  }
  .chip--1 { top: 12px; left: 10px; }
  .chip--2 { top: 74px; right: 10px; left: auto; }
  .chip--3 { top: auto; bottom: 128px; left: 10px; }
  .chip--4 { bottom: 68px; right: 10px; }
  .chip--5 { bottom: 12px; left: 10px; }
}

@media (max-width: 560px) {
  :root { --pad: 20px; --radius: 20px; }
  /* The kicker is a sentence, not two words: it has to fit 320px. The rest is
     what buys the last 26px on a 568px-tall screen, where the copy was
     pushing the hero past the viewport. */
  .hero__kicker { font-size: 11px; letter-spacing: .12em; }
  .hero__rule { margin: 14px 0; }
  /* The split costs a gap between the two blocks, which is what pushed a
     568px-tall screen 24px past itself. */
  .hero__copy { padding: 26px var(--pad) 28px; gap: 14px; }
  .hero .btn { margin-top: 20px; }
  .hero__note { margin-top: 12px; }
  .panel, .panel--white, .panel--ink { padding: 32px 24px; }
  .marquee__item, .marquee__cta { width: 220px; height: 160px; }
  .marquee__cta { font-size: 20px; }
  .category__disc { width: 124px; height: 124px; }
  .testimonial { height: 380px; }
  .btn { padding: 16px 28px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .marquee__track { animation: none; }
  .rv { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
