/* ============================================================================
   custom-dev.css — the arch system, loaded only by index_dev.html.
   Layered on top of css/custom.css, never instead of it: every accessibility
   decision documented there (contrast tokens, reduced-motion gates, the
   blocked-CDN fallbacks) still applies. This file only changes shape, and it
   changes it in one direction.

   THE RULE THIS FILE EXISTS TO ENFORCE
   The page had three unrelated shape families: an arch on 6 photos, circles on
   the countdown and timeline nodes, and hard rectangles on every card — plus
   one stray 2px radius on the travel photo that matched nothing. Here there is
   one curve, at four scales:

     nave    full-width, between sections   — you walk under it
     arch    portrait photos                — 4/5, so the ellipse is identical
     cap     cards and landscape photos     — the same curve, flattened
     tick    the RSVP stepper               — the same curve, 28px wide

   WHY THE ASPECT RATIO MATTERS
   border-radius resolves its horizontal radius against width and its vertical
   radius against height. `50% / 32%` therefore draws a DIFFERENT ellipse on a
   4/5 portrait (245x196, aspect 1.25) than on a square story image (220x141,
   aspect 1.56) — two different arches on one page. Size is irrelevant, only
   aspect is: any two elements sharing an aspect ratio share the curve exactly.
   That is why every .arch image in index_dev.html is 4/5, and why changing one
   of them silently breaks the motif.
   ========================================================================== */

:root {
  /* The arch, flattened. Cards and landscape photos are too wide for the full
     32% rise — at 3/2 it would read as a dome, not a springline. */
  --arch-cap: 44px 44px 3px 3px / 24px 24px 3px 3px;

  /* The champagne hairline held off the content by a ring of cream. Lifted
     verbatim from .arch in custom.css so a medallion, a card and a portrait
     are framed by the same three lines. */
  --ring:
    0 0 0 1px var(--champagne),
    0 0 0 6px var(--cream),
    0 0 0 7px rgba(200, 169, 106, 0.3);

  /* One easing pair for every CSS transition in this file. The page had four. */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --dur: 0.5s;
}

/* --------------------------------------------------------------------------
   THE NAVE — the section transition
   Replaces .band-curve, which was 52px of #f0dcd8 at 0.4 alpha over cream:
   rgb(248,237,235) against rgb(253,249,248), a delta of 5/12/13. Six SVGs of
   markup for a transition that was, measurably, invisible.

   The fill still carries the incoming section's colour (that is what turns a
   hard horizontal edge into a curve), but the rib is what you actually see —
   a champagne hairline on the same curve as the photo frames, at architectural
   scale. Scrolling the page becomes walking down a nave.
   -------------------------------------------------------------------------- */
.nave {
  display: block;
  width: 100%;
  height: clamp(48px, 6vw, 104px);
  /* Pulled up by its own height so it overlaps the section above. Capped at
     104px against a 96px (py-24) / 128px (sm:py-32) bottom padding, so it never
     reaches the last line of the preceding section. */
  margin-top: calc(-1 * clamp(48px, 6vw, 104px));
  position: relative;
  z-index: 1;
  pointer-events: none;
}

.nave-rib {
  fill: none;
  stroke: var(--champagne);
  stroke-width: 1;
  /* Required. preserveAspectRatio="none" stretches the viewBox horizontally by
     ~13x at 1440px, which would stretch the stroke with it into an invisible
     smear at the shoulders and a fat band at the crown. This opts the stroke
     out of the transform so the rib is one hairline all the way across. */
  vector-effect: non-scaling-stroke;
  opacity: 0.55;
  stroke-linecap: round;
}

.nave--blush .nave-fill { fill: #f0dcd8; fill-opacity: 0.4; }  /* matches bg-blush/40 */
.nave--cream .nave-fill { fill: var(--cream); }

/* --------------------------------------------------------------------------
   THE HERO — an arch-framed portrait rather than a scrimmed backdrop
   The photo used to run full-bleed under `bg-cream/55`, which washed it out
   and still left the nav links fighting whatever was behind them. Here nothing
   overlays the photo at all, so the image keeps its colour and every piece of
   type sits on cream at full contrast.

   Sized from vh, not vw, on purpose: the hero's problem is vertical. Height
   drives the frame and aspect-ratio derives the width, so the whole stack —
   arch, names, medallions, buttons — still lands inside a 900px viewport.
   -------------------------------------------------------------------------- */
/* Top padding clears the 80px fixed header; both ends shrink on short screens
   so the stack keeps its proportions instead of clipping the buttons. */
.hero-pad {
  padding-top: clamp(88px, 12vh, 132px);
  padding-bottom: clamp(40px, 6vh, 72px);
}

.hero-arch {
  display: flex;
  justify-content: center;
  margin: 1rem 0 1.25rem;
}

.hero-arch-frame {
  position: relative;
  height: clamp(170px, 38vh, 380px);
  aspect-ratio: 4 / 5;
  border-radius: 50% 50% 6px 6px / 32% 32% 3px 3px;  /* the .arch curve, at 4/5 */
  box-shadow: var(--ring);
  overflow: hidden;
  background: var(--blush);
}

.hero-arch-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A single soft wash so the cream field behind the arch is not flat. This is
   the only atmospheric element in the hero; the photo is the subject. */
.hero-veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 70% 55% at 50% 42%,
    rgba(240, 220, 216, 0.55) 0%,
    rgba(240, 220, 216, 0.18) 45%,
    rgba(253, 249, 248, 0) 72%);
}

/* Smaller than the section headings: at 88px the names dwarfed a 300px arch.
   Bounded by 7vh as well as 6vw, because on a wide-but-short window (1440x768
   is the common laptop) width alone would size the names off the bottom of the
   screen along with everything under them. */
.hero-names {
  font-size: clamp(1.9rem, min(6vw, 7vh), 4.25rem);
  line-height: 1.04;
}

/* The whole hero stack has to survive 1440x768 and 360x740, so every vertical
   gap in it is vh-bounded rather than fixed. Measured, not estimated: see the
   viewport sweep in the review. */
#inicio .rule { margin-top: 0.9rem; margin-bottom: 0.9rem; }

.hero-meta {
  font-size: 0.72rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
}

.hero-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  margin-top: clamp(1rem, 2.5vh, 2rem);
}

/* --------------------------------------------------------------------------
   THE MEDALLIONS
   Re-cut so a countdown unit is visibly a sibling of a portrait: the blush-deep
   inner ring becomes the same champagne hairline, and the disc gains the cream
   ring from .arch. Shrunk too — at clamp(112px, 30vw, 132px) four discs could
   not sit on one line under 375px, which forced the 2x2 grid that pushed the
   hero's buttons off a phone screen.

   Widths are checked against the narrowest case, 360px minus the hero's px-6:
   4 x 68 + 3 x 6.5 = 291.5 inside 312. Colours are untouched — --ink-deep on
   --blush still measures 7.0:1, as custom.css documents.
   -------------------------------------------------------------------------- */
.countdown-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(0.45rem, 2.2vw, 1.5rem);
  margin-top: clamp(1rem, 2.5vh, 2rem);
}

/* No --ring here, deliberately. It was tried and removed: the champagne hairline
   plus a 6px cream ring plus a second faint hairline turned a 100px disc into a
   coin with a triple border, and four of them into a row of buttons. At photo
   scale the ring reads as a mount; at medallion scale it reads as clutter. The
   single inner hairline is enough to make a medallion a sibling of an arch. */
.count-unit {
  width: clamp(68px, min(18vw, 13vh), 104px);
  height: clamp(68px, min(18vw, 13vh), 104px);
}

.count-unit::after {
  inset: 7px;
  border-color: var(--champagne);
  opacity: 0.7;
}

.count-card { font-size: clamp(1.3rem, 4.4vw, 2.1rem); }

.count-label {
  font-size: clamp(0.625rem, 1.9vw, 0.72rem);
  letter-spacing: 0.06em;
  margin-top: 0.3rem;
}

/* --------------------------------------------------------------------------
   CARDS JOIN THE FAMILY
   day-block, gift-card and hotel-card were the only hard rectangles left. The
   flattened cap gives them the arch's springline without pretending a 2-column
   information card is a chapel window.
   -------------------------------------------------------------------------- */
.day-block,
.gift-card,
.hotel-card,
.rsvp-choice { border-radius: var(--arch-cap); }

/* Buttons stay square, on purpose. Rounding them too would leave the page one
   undifferentiated blur of soft corners; keeping the arch for things you read
   and the rectangle for things you press is what makes either one legible. */

/* At the full column width the two portraits came out 490x612 and pushed both
   names and both paragraphs below the fold — the arch stopped being a frame and
   became the section. Capped, they still lead, and the copy sits with them. */
#nosotros img.arch {
  max-width: 380px;
  margin-inline: auto;
}

/* The travel photo was the page's one `rounded-sm` — a 2px radius matching
   nothing else on the page. It is landscape, so it takes the cap rather than
   the arch, and the same ring as every other framed photo. */
.arch-cap {
  border-radius: var(--arch-cap);
  box-shadow: var(--ring);
}

/* --------------------------------------------------------------------------
   THE GALLERY
   `column-count` was costing two things at once.

   1. It flows top-to-bottom DOWN each column, so the visual reading order was
      0,3,6,1,4,7,2,5 while the lightbox's next/prev walked 0,1,2. Clicking the
      top-left photo and pressing next jumped to the photo underneath it.
   2. Its tiles were the only images on the page with no reserved space — no
      width/height attributes and computed `aspect-ratio: auto`, next to
      `loading="lazy"`. Every other photo here carries a Tailwind aspect class.
      Measured: the grid stood at 43px before the files arrived and 1355px after,
      growing 1312px under the reader, for a cumulative layout shift of 0.557 —
      more than double the 0.25 that counts as poor, and effectively all of the
      page's shift.

   CSS Grid fixes both: it flows left-to-right, and a declared aspect-ratio holds
   each tile's space from first paint.

   The tiles are uniformly 4/5 rather than the mixed heights the masonry gave.
   That is a deliberate trade and worth knowing about: varied ratios in CSS Grid
   need either `align-items: start`, which leaves ragged holes along each row, or
   fixed row units and row spans, which stop tracking the column width once the
   breakpoint changes. Uniform tiles pack flush at every width, and 4/5 is the
   same ratio as every arch on the page, so the gallery finally belongs to the
   motif instead of being its one square-cornered exception. The rhythm the mixed
   heights used to supply now comes from the arrival wave in js/gallery-dev.js.
   -------------------------------------------------------------------------- */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

@media (min-width: 768px) {
  .gallery-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.gallery-item {
  aspect-ratio: 4 / 5;
  margin-bottom: 0;   /* the multi-column gutter; `gap` owns spacing now */
}

.gallery-item img { height: 100%; object-fit: cover; }

/* Hover did three things at once — scale, a champagne glow, and a dip to
   opacity 0.9. The dip only made the photo look dulled as the pointer arrived,
   which is the opposite of an invitation. Scale and glow stay. */
.gallery-item:hover img { opacity: 1; }

.lightbox-count {
  position: absolute;
  bottom: 1.5rem;
  left: 0;
  right: 0;
  text-align: center;
  font-family: 'Jost', sans-serif;
  font-size: 0.75rem;
  letter-spacing: 0.22em;
  color: var(--cream);
  opacity: 0.75;
}

/* --------------------------------------------------------------------------
   THE RSVP STEPPER
   #rsvp-progress had no rule anywhere in custom.css. js/rsvp.js:147 does mark
   the live step with .is-current, but computed styles came back identical for
   every item — 16px, weight 300, rgb(95,63,67) — so the stepper rendered as
   four plain lines of body copy and told the guest nothing.

   Each step is capped by the motif at its smallest scale: a 28px arch tick,
   filled champagne on the step you are standing in.
   -------------------------------------------------------------------------- */
#rsvp-progress {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.75rem;
  margin: 0 0 2.75rem;
  padding: 0;
  list-style: none;
}

#rsvp-progress li {
  position: relative;
  padding-top: 1rem;
  font-family: 'Jost', sans-serif;
  font-size: 0.6875rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sage-deep);
  opacity: 0.45;
  transition: opacity var(--dur) var(--ease), color var(--dur) var(--ease);
}

#rsvp-progress li::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 28px;
  height: 9px;
  border: 1px solid currentColor;
  border-bottom: 0;
  border-radius: 14px 14px 0 0 / 9px 9px 0 0;
  transition: background var(--dur) var(--ease);
}

#rsvp-progress li.is-current {
  opacity: 1;
  color: var(--ink-deep);
}

#rsvp-progress li.is-current::before {
  background: var(--champagne);
  border-color: var(--champagne);
}

@media (prefers-reduced-motion: reduce) {
  #rsvp-progress li,
  #rsvp-progress li::before { transition: none; }
}

/* --------------------------------------------------------------------------
   THE TIMELINE
   Each card was 559px tall and 440px wide inside a 1024px container, leaving
   ~580px of empty gutter beside every entry, with the heart node floating at
   the card's top edge aligned to nothing. The node now sits on the date line it
   belongs to and a hairline reaches from the spine to the card, so the gutter
   reads as a connection rather than a hole.
   -------------------------------------------------------------------------- */
.timeline-item + .timeline-item { margin-top: 3rem; }

.timeline-spine { background: var(--champagne); opacity: 0.35; }

/* The centred spine with cards alternating either side is the reason for the
   gutter: a 440px card in a 1024px container leaves ~580px of nothing beside
   every entry, and the taller 4/5 arches only widened the hole. So the spine
   moves to the left — where the mobile layout already had it — every card takes
   the full width, and the alternation moves inside the card, flipping which side
   the photograph sits on. The rhythm survives; the emptiness does not. It also
   reads as one procession down the page rather than a zigzag, which is the same
   idea the nave arches are carrying. */
@media (min-width: 768px) {
  .timeline-spine { left: 0.4rem; }

  .timeline-item,
  .timeline-item.is-right {
    width: 100%;
    margin-left: 0;
    padding-left: 3.75rem;
    padding-right: 0;
  }

  .timeline-node,
  .timeline-item.is-right .timeline-node { left: -0.8rem; right: auto; top: 0.3rem; }

  /* Tie-line from spine to card, level with the node's centre (node top 0.3rem
     + half of its 2.4rem height = 1.5rem). */
  .timeline-item::before,
  .timeline-item.is-right::before {
    content: '';
    position: absolute;
    top: 1.5rem;
    left: 1.6rem;
    right: auto;
    width: 1.9rem;
    height: 1px;
    background: var(--champagne);
    opacity: 0.35;
  }

  /* A hard cap rather than a fraction: at 4/5 a fractional column makes the arch
     grow taller as the container widens, and a 370x462 photo beside three lines
     of copy is a photo with a caption, not a milestone. */
  /* Both tracks are capped, and the pair is packed toward one edge rather than
     stretched across the card. A `1fr` text column looked fine with the photo on
     the left and fell apart with it on the right: the copy pinned itself to the
     far left, the photo to the far right, and the two stopped reading as one
     milestone. Packing start/end keeps them shoulder to shoulder and still swings
     the card left and right down the page. */
  .timeline-card {
    display: grid;
    grid-template-columns: minmax(0, 300px) minmax(0, 26rem);
    gap: 2.75rem;
    align-items: center;
    justify-content: start;
  }

  .timeline-item.is-right .timeline-card {
    grid-template-columns: minmax(0, 26rem) minmax(0, 300px);
    justify-content: end;
  }
  .timeline-item.is-right .story-image { order: 2; }
  .timeline-item.is-right .timeline-text { order: 1; }

  /* mt-6 spaced the date below the photo when they were stacked; side by side
     it would push the copy off centre. */
  .timeline-text > .eyebrow { margin-top: 0; }
}

/* --------------------------------------------------------------------------
   MOTION GRAMMAR
   One rule for the whole page: things rise and settle. Nothing slides sideways,
   nothing scales but a photograph under the pointer. The magnetic cursor-follow
   is gone from the markup — it was the only motion on the page that responded
   to the pointer rather than to the content.
   -------------------------------------------------------------------------- */

/* The rib is drawn by the inline script in index_dev.html, and only in the
   `full` tier. Left undashed here on purpose: under reduced motion, a blocked
   CDN or no JS at all, every rib is simply present. */
.nave-rib { transition: none; }

.gallery-item,
.gallery-item img,
.story-image img,
.rsvp-choice,
.lang-btn { transition-timing-function: var(--ease); }

/* --------------------------------------------------------------------------
   HEADER
   At 360px the wordmark cleared the language switch by 1px. Trimming the
   tracking below md buys ~18px and takes it out of collision range.
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
  #site-nav a[href="#inicio"] {
    font-size: 0.95rem;
    letter-spacing: 0.1em;
  }
}
