/* Venezuela Invest
   ---------------------------------------------------------------------------
   White page, black type, photographs. The flag colours appear only as hairlines
   and hover states: remove all three and the design still stands, which is the
   test the brief sets.

   The recurring device is the place stamp. Every photograph carries where it was
   taken, set in mono in the margin. Photographs we took ourselves carry a
   verification mark as well. As real photography replaces the reference images,
   the marks appear one by one, which is the trust claim made visible instead of
   asserted.
   --------------------------------------------------------------------------- */

/* 1. Reset ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; }
img, picture, video { display: block; max-width: 100%; }
button, input, textarea, select { font: inherit; color: inherit; }
a { color: inherit; }

/* 2. Tokens --------------------------------------------------------------- */
:root {
  --paper:   #ffffff;
  --wash:    #f7f7f5;
  --ink:     #0e0e0e;
  --ink-2:   #6b6b6b;
  --ink-3:   #9a9a97;
  --rule:    #e3e3e1;
  --aspect:  21 / 9;

  /* The flag, softened. Pastel rather than the true yellow, blue and red, so the
     colour can appear in more places without ever shouting. Tuned to stay visible
     as a 2px hairline on white. */
  --pa-yellow: #e9ce84;
  --pa-blue:   #9db2d8;
  --pa-red:    #dda6a0;
  /* globe.js reads these off the page, so the globe follows the palette. The
     land is a near-ink dot matrix, dark enough that the continents read at a
     glance; the visitor LEDs take the three flag pastels above, a darker core
     of the same hue with a soft halo of it behind. No green anywhere. */
  --accent:    #0e0e0e;
  --globe-dot: #1c1c1a;

  --pa-yellow-wash: #faf3e2;
  --pa-blue-wash:   #eef1f8;
  --pa-red-wash:    #f9eeed;

  --serif: "Newsreader", "Iowan Old Style", Georgia, serif;
  /* The aside voice, carried over from whatsvibecode.com: one italic serif line
     that says the thing the headline cannot. Used sparingly, never for body copy. */
  --voice: Georgia, "Iowan Old Style", "Times New Roman", serif;
  --sans:  "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --mono:  "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --gutter: clamp(1.25rem, 4vw, 4.5rem);
  --rail: 9.5rem;
  --measure: 34rem;

  --step: clamp(3.5rem, 9vw, 8rem);   /* vertical rhythm between sections */
  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* 3. Base ----------------------------------------------------------------- */
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.55;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--serif); font-weight: 300; line-height: 1.02; letter-spacing: -.02em; }

.display  { font-size: clamp(2.7rem, 6.4vw, 5.6rem); }
.title    { font-size: clamp(2rem, 3.9vw, 3.3rem); }
.subtitle { font-size: clamp(1.35rem, 2.1vw, 1.9rem); line-height: 1.15; }

.lede { font-size: clamp(1.05rem, 1.35vw, 1.3rem); line-height: 1.5; color: var(--ink); max-width: var(--measure); }
.body-copy { color: var(--ink-2); max-width: var(--measure); }
.body-copy + .body-copy { margin-top: 1rem; }

/* Mono is the utility voice: labels, metadata, prices, times, coordinates. */
.meta {
  font-family: var(--mono);
  font-size: .69rem;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 500;
}
.meta--ink { color: var(--ink); }

/* 4. Layout --------------------------------------------------------------- */
.wrap { width: 100%; max-width: 96rem; margin-inline: auto; padding-inline: var(--gutter); }

/* The margin rail carries metadata beside the content. It collapses below 1100px,
   where the stamp moves under its photograph instead. */
.railed { display: grid; grid-template-columns: var(--rail) minmax(0, 1fr); gap: clamp(1.5rem, 3vw, 3rem); }
.railed > .rail { padding-top: .45rem; }
@media (max-width: 1100px) { .railed { grid-template-columns: minmax(0, 1fr); } .railed > .rail { display: none; } }

.section { padding-block: var(--step); }
.section--wash { background: var(--wash); }
.section--tight { padding-block: calc(var(--step) * .62); }
hr.rule { border: 0; border-top: 1px solid var(--rule); }

/* 5. Signature: the place stamp ------------------------------------------- */
.stamp { font-family: var(--mono); font-size: .66rem; letter-spacing: .15em; text-transform: uppercase; color: var(--ink-3); }
.stamp::before { content: ""; display: block; width: 1.6rem; border-top: 1px solid var(--ink); margin-bottom: .55rem; }
.stamp b { font-weight: 500; color: var(--ink-2); display: block; }
.stamp .verified { color: var(--ink); }
.stamp .verified::before { content: "◆ "; color: var(--pa-yellow); }
.figure-stamp { margin-top: .85rem; }
@media (min-width: 1101px) { .figure-stamp { display: none; } }

/* 6. Wordmark ------------------------------------------------------------- */
.wordmark { display: inline-block; text-decoration: none; }
.wordmark span {
  font-family: var(--sans); font-weight: 600; font-size: .78rem;
  letter-spacing: .26em; text-transform: uppercase; display: block;
}
.wordmark::after {
  content: ""; display: block; height: 2px; margin-top: .45rem;
  background: linear-gradient(to right,
    var(--pa-yellow) 0 33.33%, var(--pa-blue) 33.33% 66.66%, var(--pa-red) 66.66% 100%);
  transform: scaleX(1); transform-origin: left; transition: transform .5s var(--ease);
}
.wordmark:hover::after { transform: scaleX(1.18); }

/* 7. Navigation ----------------------------------------------------------- */
.nav { position: sticky; top: 0; z-index: 40; background: var(--paper); border-bottom: 1px solid var(--rule); }
.nav__in { display: flex; align-items: center; justify-content: space-between; gap: 2rem; padding-block: 1.05rem; }
.nav__links { display: flex; align-items: center; gap: clamp(1.1rem, 2.2vw, 2.2rem); }
.nav__links a { text-decoration: none; font-size: .89rem; }
.nav__local { color: var(--ink-3); }
@media (max-width: 860px) { .nav__links .hide-sm { display: none; } }

/* Link underline wipes in on hover, in the section's accent colour. */
.ul { position: relative; text-decoration: none; }
.ul::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: right;
  transition: transform .38s var(--ease);
}
.ul:hover::after, .ul:focus-visible::after { transform: scaleX(1); transform-origin: left; }

/* 8. Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: baseline; gap: .7rem;
  background: var(--ink); color: var(--paper);
  padding: .95rem 1.5rem; border: 1px solid var(--ink); border-radius: 0;
  text-decoration: none; font-size: .95rem; cursor: pointer;
  transition: background .3s var(--ease), color .3s var(--ease);
}
.btn:hover { background: var(--paper); color: var(--ink); }
.btn__price { font-family: var(--mono); font-size: .85rem; letter-spacing: .04em; opacity: .75; }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--paper); }
.btn--sm { padding: .62rem 1rem; font-size: .85rem; }

.arrow { display: inline-block; transition: transform .35s var(--ease); }
a:hover .arrow, .btn:hover .arrow { transform: translateX(.32rem); }

/* 9. Hero ----------------------------------------------------------------- */
.hero { padding-top: clamp(3rem, 7vw, 6.5rem); padding-bottom: 0; }
.hero__grid { display: grid; grid-template-columns: var(--rail) minmax(0, 1.02fr) minmax(0, 1fr); gap: clamp(1.5rem, 3vw, 3rem); align-items: start; }
.hero__copy { padding-bottom: clamp(2rem, 5vw, 4rem); }
.hero .display { margin-top: 1.6rem; }
.hero__standfirst { margin-top: 1.5rem; font-size: clamp(1.05rem, 1.3vw, 1.22rem); color: var(--ink-2); max-width: 26rem; line-height: 1.5; }
.hero__cta { margin-top: 2.4rem; display: flex; flex-wrap: wrap; align-items: center; gap: 1.6rem; }
.hero__note { margin-top: 1.1rem; color: var(--ink-3); font-size: .87rem; max-width: 24rem; }

/* The photograph breaks the right edge of the grid and continues past the fold. */
.hero__figure { position: relative; margin-right: calc(var(--gutter) * -1); }
.hero__figure img { width: 100%; aspect-ratio: var(--aspect); object-fit: cover; }
@media (max-width: 1100px) {
  .hero__grid { grid-template-columns: minmax(0, 1fr); }
  .hero__figure { margin-inline: calc(var(--gutter) * -1); }
  .hero__figure img { aspect-ratio: 16 / 10; }
}

/* 10. Two doors ----------------------------------------------------------- */
.doors { display: grid; grid-template-columns: repeat(2, 1fr); border-top: 1px solid var(--rule); }
.door {
  position: relative; display: block; text-decoration: none; overflow: hidden;
  padding: clamp(1.6rem, 3vw, 2.6rem) 0 clamp(2rem, 4vw, 3.2rem);
}
.door + .door { border-left: 1px solid var(--rule); padding-left: clamp(1.6rem, 3vw, 2.6rem); }
.door + .door .door__media { margin-left: 0; }
.door__media { overflow: hidden; margin-bottom: 1.6rem; }
.door__media img { width: 100%; aspect-ratio: var(--aspect); object-fit: cover; transition: transform 1.1s var(--ease); }
.door:hover .door__media img { transform: scale(1.035); }
.door__sub { color: var(--ink-2); margin-top: .55rem; font-size: .95rem; }
.door__go { margin-top: 1.5rem; display: inline-flex; gap: .55rem; font-size: .9rem; }
.door__bar { position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: var(--rule); }
.door__bar::after { content: ""; position: absolute; inset: 0; transform: scaleX(0); transform-origin: left; transition: transform .6s var(--ease); }
.door:hover .door__bar::after { transform: scaleX(1); }
.door--yellow .door__bar::after { background: var(--pa-yellow); }
.door--blue   .door__bar::after { background: var(--pa-blue); }
@media (max-width: 800px) {
  .doors { grid-template-columns: 1fr; }
  .door + .door { border-left: 0; border-top: 1px solid var(--rule); padding-left: 0; }
}

/* 11. The half hour ------------------------------------------------------- */
/* Timestamps, not 01/02/03. The order is real and the reader is buying a
   specific thirty minutes, so the marker says when rather than how many. */
.session { border-top: 1px solid var(--ink); margin-top: 2.6rem; }
.session__row { display: grid; grid-template-columns: 5.5rem minmax(0, 15rem) minmax(0, 1fr); gap: clamp(1rem, 2.5vw, 2.5rem); padding-block: 1.5rem; border-bottom: 1px solid var(--rule); align-items: baseline; }
.session__at { font-family: var(--mono); font-size: .8rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.session__t { font-family: var(--serif); font-size: 1.28rem; line-height: 1.2; }
.session__b { color: var(--ink-2); font-size: .95rem; }
@media (max-width: 760px) {
  .session__row { grid-template-columns: 4rem minmax(0, 1fr); row-gap: .4rem; }
  .session__b { grid-column: 2; }
}

/* 12. People -------------------------------------------------------------- */
.people { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1.5rem, 4vw, 4rem); }
.person img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.person__name { font-family: var(--serif); font-size: 1.7rem; margin-top: 1.1rem; }
.person__role { margin-top: .35rem; }
.person__line { margin-top: .8rem; color: var(--ink-2); font-size: .95rem; }
@media (max-width: 700px) { .people { grid-template-columns: 1fr; } }

/* 13. Cards (properties, guide) ------------------------------------------- */
.cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1.25rem, 2.5vw, 2.5rem); }
.card { text-decoration: none; display: block; }
.card__media { overflow: hidden; margin-bottom: 1rem; background: var(--wash); }
.card__media img { width: 100%; aspect-ratio: var(--aspect); object-fit: cover; transition: transform 1s var(--ease); }
.card:hover .card__media img { transform: scale(1.04); }
.card__t { font-family: var(--serif); font-size: 1.32rem; line-height: 1.2; margin-top: .5rem; }
.card__sub { color: var(--ink-2); font-size: .92rem; margin-top: .5rem; }
.card__price { font-family: var(--mono); font-size: .92rem; margin-top: .7rem; }
@media (max-width: 900px) { .cards { grid-template-columns: 1fr; } }

/* 14. Consultation block -------------------------------------------------- */
.consult { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(2rem, 5vw, 5rem); align-items: end; }
.consult__price { font-family: var(--mono); font-size: 1rem; letter-spacing: .05em; }
@media (max-width: 860px) { .consult { grid-template-columns: 1fr; align-items: start; } }

/* 15. Booking calendar ---------------------------------------------------- */
.tzbar { display: flex; flex-wrap: wrap; align-items: center; gap: .8rem; padding-block: 1rem; border-bottom: 1px solid var(--rule); }
.tzbar select { border: 1px solid var(--rule); background: var(--paper); padding: .45rem .6rem; font-size: .85rem; border-radius: 0; }
.day { display: grid; grid-template-columns: 11rem minmax(0, 1fr); gap: clamp(1rem, 3vw, 2.5rem); padding-block: 1.6rem; border-bottom: 1px solid var(--rule); }
.day__wd { font-family: var(--serif); font-size: 1.45rem; }
.day__date { margin-top: .3rem; }
.day__slots { display: flex; flex-wrap: wrap; gap: .6rem; }
.slot {
  font-family: var(--mono); font-size: .85rem; letter-spacing: .02em;
  border: 1px solid var(--rule); background: var(--paper); color: var(--ink);
  padding: .6rem .85rem; text-decoration: none; cursor: pointer;
  transition: border-color .25s var(--ease), background .25s var(--ease), color .25s var(--ease);
}
.slot:hover, .slot:focus-visible { border-color: var(--ink); background: var(--ink); color: var(--paper); }
.day__none { color: var(--ink-3); font-size: .9rem; }
@media (max-width: 700px) { .day { grid-template-columns: 1fr; row-gap: .9rem; } }

/* 16. Footer -------------------------------------------------------------- */
.footer { border-top: 1px solid var(--ink); padding-block: clamp(2.5rem, 5vw, 4rem) 2.5rem; }
.footer__grid { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: clamp(1.5rem, 3vw, 3rem); }
.footer__grid > * { min-width: 0; overflow-wrap: anywhere; }
.footer h4 { font-family: var(--sans); font-weight: 600; font-size: .74rem; letter-spacing: .17em; text-transform: uppercase; color: var(--ink-3); margin: 0; }
/* One heading row across all four columns. The box is as tall as the tallest
   heading (the wordmark, which carries a 2px rule under it), so every column
   starts its first line of content on the same baseline. */
.footer__head { display: flex; align-items: flex-start; min-height: 1.75rem; margin-bottom: 1rem; }
.footer__col ul { margin: 0; padding: 0; }
.footer__col > p:first-of-type { margin-top: 0; }
.footer li { list-style: none; margin-bottom: .5rem; }
.footer a { text-decoration: none; font-size: .92rem; }
.footer__legal { margin-top: clamp(2.5rem, 5vw, 4rem); padding-top: 1.5rem; border-top: 1px solid var(--rule); color: var(--ink-3); font-size: .8rem; max-width: 44rem; }
.footer__legal p + p { margin-top: .6rem; }
@media (max-width: 800px) { .footer__grid { grid-template-columns: repeat(2, 1fr); } }

/* 17. Motion -------------------------------------------------------------- */
/* One orchestrated entrance on the hero, quiet reveals after it.
   Every hidden starting state is gated behind html.js (set by one inline line
   in the head), so a visitor with JavaScript blocked sees the whole page. */
.js .reveal { opacity: 0; transform: translateY(1.1rem); transition: opacity .85s var(--ease), transform .85s var(--ease); }
.reveal.in { opacity: 1; transform: none; }
.reveal[data-d="1"] { transition-delay: .09s; }
.reveal[data-d="2"] { transition-delay: .18s; }
.reveal[data-d="3"] { transition-delay: .27s; }
.reveal[data-d="4"] { transition-delay: .36s; }

/* Headline reveals line by line behind a clipping mask. */
.lines span { display: block; overflow: hidden; }
.lines i { display: block; font-style: inherit; }
.js .lines i { transform: translateY(105%); transition: transform 1s var(--ease); }
.lines.in i { transform: none; }
.lines.in span:nth-child(2) i { transition-delay: .1s; }

.parallax { will-change: transform; }

/* 18. Accessibility ------------------------------------------------------- */
:where(a, button, select, input, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--ink); outline-offset: 3px;
}
.skip { position: absolute; left: -9999px; }
.skip:focus { left: var(--gutter); top: .6rem; z-index: 100; background: var(--ink); color: var(--paper); padding: .6rem 1rem; }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

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

/* =========================================================================
   19. The aside voice
   One italic serif line per section, carried over from whatsvibecode.com.
   It says the thing the headline is too formal to say. Never body copy.
   ========================================================================= */
.aside {
  font-family: var(--voice); font-style: italic;
  font-size: clamp(1.05rem, 1.55vw, 1.35rem); line-height: 1.45;
  color: var(--ink-2); max-width: 40ch; margin-top: .9rem;
}

/* 20. Real Estate lead block ---------------------------------------------
   Promoted above Business & Investment: it is the section people come for. */
.lead-door { display: block; text-decoration: none; position: relative; }
.lead-door__media { overflow: hidden; position: relative; }
.lead-door__media img { width: 100%; aspect-ratio: var(--aspect); object-fit: cover; transition: transform 1.3s var(--ease); }
.lead-door:hover .lead-door__media img { transform: scale(1.03); }
/* the image uncovers itself from the left as it arrives, easing home from a
   breath larger, so the uncover reads as a settle rather than a wipe */
.js .mask { clip-path: inset(0 100% 0 0); transition: clip-path 1.1s var(--ease); }
/* the wipe must never be able to strand an image: after its own duration plus a
   margin, the clip opens whatever happened with the observer */
.js .mask { animation: mask-failsafe 0s linear 4s forwards; }
@keyframes mask-failsafe { to { clip-path: inset(0 0 0 0); } }
.js .mask img { transform: scale(1.055); transition: transform 1.45s var(--ease); }
.mask.in img { transform: scale(1); }
.mask.in { clip-path: inset(0 0 0 0); }
.lead-door__foot { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 1rem; margin-top: 1.5rem; padding-top: 1.1rem; border-top: 1px solid var(--ink); }
.lead-door__go { display: inline-flex; gap: .55rem; font-size: 1rem; }

/* 21. Business & Investment, deliberately smaller -------------------------- */
.mini { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 clamp(1rem, 2.5vw, 2.5rem); border-top: 1px solid var(--rule); }
.mini a { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; padding: .95rem 0; border-bottom: 1px solid var(--rule); text-decoration: none; font-size: .95rem; }
.mini a span:last-child { color: var(--ink-3); transition: transform .3s var(--ease), color .3s var(--ease); }
.mini a:hover span:last-child { transform: translateX(.3rem); color: var(--ink); }
@media (max-width: 820px) { .mini { grid-template-columns: 1fr; } }

/* 22. Globe --------------------------------------------------------------- */
.globe { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: clamp(2rem, 5vw, 5rem); align-items: center; }
.globe canvas { width: 100%; height: auto; display: block; }
.globe__stat { font-family: var(--mono); font-size: 2.1rem; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.globe__row { display: flex; gap: clamp(1.5rem, 4vw, 3.5rem); margin-top: 1.8rem; }
.globe__feed { margin-top: 2rem; border-top: 1px solid var(--rule); }
.globe__feed li { list-style: none; display: flex; justify-content: space-between; gap: 1rem; padding: .6rem 0; border-bottom: 1px solid var(--rule); font-size: .9rem; }
.globe__feed .ago { font-family: var(--mono); font-size: .74rem; color: var(--ink-3); white-space: nowrap; }
.globe__empty { color: var(--ink-3); }
@media (max-width: 900px) { .globe { grid-template-columns: 1fr; } }

/* 23. Vetted network ------------------------------------------------------ */
.criteria { margin-top: 2.2rem; border-top: 1px solid var(--ink); }
.criteria li { list-style: none; display: grid; grid-template-columns: 2.2rem 1fr; gap: 1rem; padding: 1.05rem 0; border-bottom: 1px solid var(--rule); font-size: 1rem; }
.criteria i { font-style: normal; font-family: var(--mono); font-size: .72rem; color: var(--ink-3); padding-top: .28rem; }
/* the roster reads as a row of small faces, not two hero portraits */
.roster { display: flex; flex-wrap: wrap; gap: clamp(1rem, 2.5vw, 2.2rem); margin-top: 2.4rem; align-items: flex-start; }
.roster__p { width: 8.5rem; }
.roster__p img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; display: block; }
.roster__n { font-family: var(--serif); font-size: 1.12rem; margin-top: .6rem; }
.roster__more { width: 8.5rem; aspect-ratio: 1 / 1; border: 1px dashed var(--rule); display: grid; place-items: center; text-align: center; color: var(--ink-3); font-size: .78rem; padding: .5rem; }

/* =========================================================================
   24. Micro-interactions
   Many small ones rather than a few large ones. Every effect here is
   transform or opacity only, so nothing shifts layout under a thumb, and
   every one turns itself off under prefers-reduced-motion.
   ========================================================================= */

/* a) a hairline reading-progress bar in the softened flag colours */
.progress { position: fixed; top: 0; left: 0; height: 2px; width: 100%; z-index: 60; transform: scaleX(0); transform-origin: left;
  background: linear-gradient(to right, var(--pa-yellow), var(--pa-blue), var(--pa-red)); }

/* b) the nav condenses once the visitor leaves the hero */
.nav { transition: padding .4s var(--ease), border-color .4s var(--ease); }
.nav.shrunk .nav__in { padding-block: .7rem; }
.nav.shrunk { border-bottom-color: var(--ink); }

/* c) buttons lean very slightly toward the cursor */
.btn { will-change: transform; }
.btn.mag { transition: background .3s var(--ease), color .3s var(--ease), transform .18s var(--ease); }

/* d) the button fills from the left rather than swapping colour */
.btn--wipe { position: relative; overflow: hidden; z-index: 0; }
.btn--wipe::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--paper);
  transform: scaleX(0); transform-origin: right; transition: transform .45s var(--ease); }
.btn--wipe:hover::before { transform: scaleX(1); transform-origin: left; }

/* e) numbers count up when they scroll into view */
.odo { font-variant-numeric: tabular-nums; }

/* f) each section's rail label carries a running count */
.rail__idx { display: block; margin-top: .5rem; color: var(--rule); font-size: 2.4rem; font-family: var(--serif); line-height: 1; }

/* g) children of a group arrive one after another */
.js .stagger > * { opacity: 0; transform: translateY(.9rem); transition: opacity .7s var(--ease), transform .7s var(--ease); }
.stagger.in > * { opacity: 1; transform: none; }

/* h) a soft pastel wash follows the cursor across a door */
.door, .lead-door { --mx: 50%; --my: 50%; }
.door::before, .lead-door::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  transition: opacity .5s var(--ease);
  background: radial-gradient(18rem circle at var(--mx) var(--my), var(--tint, var(--pa-yellow-wash)), transparent 70%);
}
.door:hover::before, .lead-door:hover::before { opacity: 1; }
.door > *, .lead-door > * { position: relative; }
.door--yellow { --tint: var(--pa-yellow-wash); }
.door--blue { --tint: var(--pa-blue-wash); }

/* i) a rule that draws itself in when its section arrives */
.draw { position: relative; }
.draw::after { content: ""; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%; background: var(--ink); }
.js .draw::after { transform: scaleX(0); transform-origin: left; transition: transform 1s var(--ease); }
.draw.in::after { transform: scaleX(1); }

/* j) the local clock ticks over rather than cutting */
.tick { display: inline-block; transition: opacity .25s var(--ease), transform .25s var(--ease); }
.tick.beat { opacity: .35; transform: translateY(-.12em); }

/* k) slots settle in one after another, and lift on hover */
.slot { transition: border-color .25s var(--ease), background .25s var(--ease), color .25s var(--ease), transform .25s var(--ease); }
.slot:hover { transform: translateY(-2px); }

/* l) each session row wipes a pastel tint behind itself on hover, cycling the
   three washes down the list the way the asking rows do */
.session__row { transition: background .4s var(--ease); }
.session__row:hover { background: var(--pa-yellow-wash); }
.session__row:nth-child(3n+2):hover { background: var(--pa-blue-wash); }
.session__row:nth-child(3n):hover   { background: var(--pa-red-wash); }

/* m) the stamp's rule extends when its photograph is hovered */
.stamp::before { transition: width .5s var(--ease); }
figure:hover .stamp::before, .lead-door:hover .stamp::before { width: 3.2rem; }

/* n) footer links shift a hair on hover */
.footer a { display: inline-block; transition: transform .3s var(--ease); }
.footer a:hover { transform: translateX(.2rem); }

@media (prefers-reduced-motion: reduce) {
  .js .stagger > * { opacity: 1; transform: none; }
  .js .mask { clip-path: none; }
  .js .mask img { transform: none; }
  .js .draw::after { transform: scaleX(1); }
  .progress { display: none; }
  .door::before, .lead-door::before { display: none; }
}

/* 25. What people bring to a call ----------------------------------------
   Two tracks, one conversation: the paperwork and the family. Shown side by
   side so nobody assumes this is only for investors. */
.brings { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1.5rem, 3vw, 3rem); margin-top: 3rem; }
.brings h3 { font-family: var(--sans); font-weight: 600; font-size: .74rem; letter-spacing: .17em; text-transform: uppercase; color: var(--ink-3); padding-bottom: .8rem; border-bottom: 1px solid var(--ink); }
.brings li { list-style: none; padding: .8rem 0; border-bottom: 1px solid var(--rule); font-size: .95rem; color: var(--ink-2); }
.brings li::before { content: ""; display: inline-block; width: .42rem; height: .42rem; margin-right: .6rem; vertical-align: middle; background: var(--dot, var(--pa-yellow)); }
.brings > div:nth-child(2) li::before { background: var(--pa-blue); }
.brings > div:nth-child(3) li::before { background: var(--pa-red); }
@media (max-width: 860px) { .brings { grid-template-columns: 1fr; } }

/* 26. Who is asking -------------------------------------------------------
   A self-identification router. The visitor should find their own sentence
   before they read anything about us. Each row picks up a different pastel
   as the cursor crosses it, so the four read as four separate doors. */
.asking { margin-top: 2.8rem; border-top: 1px solid var(--ink); }
.asking__row {
  display: grid; grid-template-columns: minmax(0, 20rem) minmax(0, 1fr) 2rem;
  gap: clamp(1rem, 3vw, 3rem); align-items: baseline;
  padding: 1.6rem 1rem 1.6rem 0; border-bottom: 1px solid var(--rule);
  text-decoration: none; transition: background .4s var(--ease), padding-left .4s var(--ease);
}
/* Each row carries a colour tab, cycling yellow, blue, red down the list, so
   scanning the section reassembles the three bands under the wordmark. The tab
   is always there; the wash only arrives on hover. */
.asking__row { position: relative; padding-left: 1.4rem; }
.asking__row::before {
  content: ""; position: absolute; left: 0; top: 1.6rem; bottom: 1.6rem; width: 3px;
  background: var(--band); transform: scaleY(.34); transform-origin: top;
  transition: transform .5s var(--ease);
}
.asking__row:hover::before { transform: scaleY(1); }
.asking__row:hover { background: var(--tint); padding-left: 2rem; }
.asking__row:nth-child(3n+1) { --band: var(--pa-yellow); --tint: var(--pa-yellow-wash); }
.asking__row:nth-child(3n+2) { --band: var(--pa-blue);   --tint: var(--pa-blue-wash); }
.asking__row:nth-child(3n+3) { --band: var(--pa-red);    --tint: var(--pa-red-wash); }
.asking__t { font-family: var(--serif); font-size: clamp(1.35rem, 2vw, 1.75rem); line-height: 1.15; }
.asking__b { color: var(--ink-2); font-size: .97rem; }
.asking__go { color: var(--ink-3); transition: transform .35s var(--ease), color .35s var(--ease); text-align: right; }
.asking__row:hover .asking__go { transform: translateX(.35rem); color: var(--ink); }
.asking__close { margin-top: 2.2rem; font-size: 1.02rem; max-width: 44rem; }
@media (max-width: 820px) {
  .asking__row { grid-template-columns: minmax(0, 1fr) 2rem; row-gap: .5rem; }
  .asking__row::before { top: 1.2rem; bottom: 1.2rem; }
  .asking__b { grid-column: 1; }
}

/* 28. Notice --------------------------------------------------------------
   Used where the honest caveat is the point rather than the small print, so
   it gets a full rule above and below rather than being tucked into a corner. */
.notice {
  margin-top: 3rem; padding: 1.6rem 0; max-width: 44rem;
  border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink);
  color: var(--ink-2); font-size: .97rem;
}

/* 29. Categories still being written --------------------------------------
   Shown, but not linked. An empty category page reads as a dead site, and a
   link that goes nowhere reads worse. */
.is-pending { color: var(--ink-3); }
.is-pending .session__t { color: var(--ink-3); }
.pending-tag {
  font-family: var(--mono); font-size: .6rem; letter-spacing: .15em; text-transform: uppercase;
  color: var(--ink-3); border: 1px solid var(--rule); padding: .15rem .4rem; margin-left: .7rem;
  white-space: nowrap;
}
.mini__soon { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding: .95rem 0; border-bottom: 1px solid var(--rule); font-size: .95rem; color: var(--ink-3); }

/* 30. Booking steps 2 and 3 ----------------------------------------------- */
.held { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
  margin-top: 2rem; padding: 1.2rem 0; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--rule); }
.held__when { font-family: var(--serif); font-size: 1.5rem; margin-top: .35rem; }
.held__timer { font-family: var(--mono); font-size: 1.05rem; font-variant-numeric: tabular-nums; color: var(--ink-2); }
.held__timer.low { color: var(--ve-red, #b3403a); }

.form { margin-top: 2.4rem; }
.field { display: block; margin-bottom: 1.6rem; }
.field input, .field textarea {
  display: block; width: 100%; margin-top: .55rem; padding: .8rem .9rem;
  border: 1px solid var(--rule); border-radius: 0; background: var(--paper);
  font-size: 1rem; font-family: var(--sans); transition: border-color .25s var(--ease);
}
.field input:focus, .field textarea:focus { border-color: var(--ink); outline: none; }
.field textarea { resize: vertical; }
.field__hint { display: block; margin-top: .45rem; font-size: .82rem; color: var(--ink-3); }

.checkout { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .8fr); gap: clamp(2rem, 5vw, 4.5rem); }
@media (max-width: 880px) { .checkout { grid-template-columns: 1fr; } }
.summary { margin-top: 2rem; border-top: 1px solid var(--ink); }
.summary > div { display: flex; justify-content: space-between; gap: 1.5rem; padding: .9rem 0; border-bottom: 1px solid var(--rule); }
.summary dd { margin: 0; font-size: .98rem; text-align: right; }
.brings__list { margin-top: .6rem; }
.brings__list li { list-style: none; padding: .7rem 0; border-bottom: 1px solid var(--rule); color: var(--ink-2); font-size: .95rem; }
.brings__list li::before { content: ""; display: inline-block; width: .42rem; height: .42rem; margin-right: .6rem; vertical-align: middle; background: var(--pa-yellow); }
.brings__list li:nth-child(2)::before { background: var(--pa-blue); }
.brings__list li:nth-child(3)::before { background: var(--pa-red); }

.pay { border: 1px solid var(--ink); padding: clamp(1.4rem, 2.5vw, 2rem); }
.pay__amount { font-family: var(--mono); font-size: 2.9rem; letter-spacing: -.03em; margin-top: .5rem; }
.pay__option { display: flex; align-items: center; justify-content: space-between; gap: 1rem; width: 100%;
  margin-top: .7rem; padding: .9rem 1rem; border: 1px solid var(--rule); background: var(--paper);
  text-align: left; font-size: .97rem; cursor: pointer; transition: border-color .25s var(--ease); }
.pay__option:hover:not(.is-off) { border-color: var(--ink); }
.pay__option.is-off { color: var(--ink-3); cursor: not-allowed; }
.pay__note { font-family: var(--mono); font-size: .68rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.pay__timer { font-family: var(--mono); font-size: .72rem; letter-spacing: .06em; color: var(--ink-3); margin-top: 1.1rem; text-align: center; }

/* 31. Language marks ------------------------------------------------------
   Dots in the flag's colours rather than a drawn flag. At this size a flag
   needs detail it cannot legibly carry, and dots scale, recolour, and sit with
   the rest of the site's marks. Labelled, because a flag names a country and
   we mean a language. */
.flags { display: flex; flex-wrap: wrap; gap: .6rem 1.4rem; margin-top: 1.1rem; }
.lang { display: inline-flex; align-items: center; gap: .6rem; }
.lang__ball {
  width: 1.3rem; height: 1.3rem; display: block; flex: none;
  transition: transform .4s var(--ease), filter .4s var(--ease);
  filter: saturate(.82);
}
.lang:hover .lang__ball { transform: translateY(-3px) scale(1.06); filter: saturate(1); }
.lang__name { font-family: var(--mono); font-size: .68rem; letter-spacing: .11em; text-transform: uppercase; color: var(--ink-2); }

/* 32. About ---------------------------------------------------------------- */
.about__not { margin-top: 2.4rem; border-top: 1px solid var(--ink); max-width: 44rem; }
.about__not li { list-style: none; padding: .95rem 0; border-bottom: 1px solid var(--rule);
  color: var(--ink-2); font-size: .97rem; display: grid; grid-template-columns: 1.4rem 1fr; gap: .8rem; }
.about__not i { font-style: normal; color: var(--ink-3); }
.bio { display: grid; grid-template-columns: 11rem minmax(0, 1fr); align-items: start; gap: clamp(1.2rem, 2.5vw, 2.2rem);
  padding: 1.8rem 0; border-bottom: 1px solid var(--rule); align-items: start; }
.bio > picture { display: block; width: 100%; aspect-ratio: 1 / 1; }
.bio > picture img { width: 100%; height: 100%; object-fit: contain; display: block; }
.bio__n { font-family: var(--serif); font-size: 1.6rem; }
.bio__r { margin-top: .35rem; }
.bio__f { font-family: var(--voice); font-style: italic; color: var(--ink-2); font-size: .95rem; margin-top: .25rem; }
.bio__l { margin-top: .9rem; color: var(--ink-2); font-size: .97rem; max-width: 40rem; }
@media (max-width: 640px) { .bio { grid-template-columns: 1fr; } .bio picture { max-width: 11rem; } }

/* 33. Questions -----------------------------------------------------------
   Native <details>, so it opens with JavaScript blocked and is keyboard
   operable without any code of ours. The marker is drawn rather than a glyph,
   so it can animate and never renders as a stray arrow in a strange font. */
.faq { margin-top: 2.4rem; }
.faq__list { margin-top: 1.6rem; border-top: 1px solid var(--ink); }
.faq__item { border-bottom: 1px solid var(--rule); }
.faq__item summary {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1.5rem;
  padding: 1.15rem 0; cursor: pointer; list-style: none;
  transition: padding-left .35s var(--ease), color .35s var(--ease);
}
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary:hover { padding-left: .5rem; }
.faq__q { font-family: var(--serif); font-size: clamp(1.08rem, 1.5vw, 1.28rem); line-height: 1.25; }
.faq__mark { position: relative; flex: none; width: .8rem; height: .8rem; }
.faq__mark::before, .faq__mark::after {
  content: ""; position: absolute; background: var(--ink-3); transition: transform .35s var(--ease), background .35s var(--ease);
}
.faq__mark::before { left: 0; right: 0; top: 50%; height: 1px; }
.faq__mark::after { top: 0; bottom: 0; left: 50%; width: 1px; }
.faq__item[open] .faq__mark::after { transform: scaleY(0); }
.faq__item[open] .faq__mark::before { background: var(--ink); }
.faq__item summary:hover .faq__mark::before,
.faq__item summary:hover .faq__mark::after { background: var(--ink); }
.faq__a { padding: 0 0 1.35rem; color: var(--ink-2); max-width: 46rem; font-size: .99rem; }
.faq__item[open] .faq__a { animation: faq-in .45s var(--ease); }
@keyframes faq-in { from { opacity: 0; transform: translateY(-.4rem); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .faq__item[open] .faq__a { animation: none; } }

/* the questions index groups the sets as columns of links */
.qindex { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1.5rem, 3vw, 3rem); margin-top: 2.4rem; }
@media (max-width: 760px) { .qindex { grid-template-columns: 1fr; } }

/* 34. Payment note --------------------------------------------------------
   Longer than small print and doing more work: it explains why the payment
   rail is what it is, so it reads as body copy rather than a legal footer. */
.paynote { margin-top: 1.3rem; font-size: .84rem; line-height: 1.55; color: var(--ink-3); }
.paynote p + p { margin-top: .7rem; }
.paynote p:first-child { color: var(--ink-2); }

/* =========================================================================
   35. Movement between pages, and this pass's micro-interactions
   The one bold moment on the site: routes hand over to each other instead of
   cutting. The nav holds still while the page beneath it drifts in, and in
   the booking flow the thirty minutes you chose physically travels with you,
   from the slot you pressed, to "Held for you", to the confirmation summary.
   View transitions where the browser has them; everywhere else the site
   navigates exactly as before. Reduced motion switches all of it off.
   ========================================================================= */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
.nav { view-transition-name: site-nav; }
::view-transition-old(root) { animation: vt-out .28s var(--ease) both; }
::view-transition-new(root) { animation: vt-in .5s var(--ease) both; }
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in { from { opacity: 0; transform: translateY(.55rem); } }

/* the chosen half hour: .taking is set the moment a slot is pressed, and the
   same name sits on step 2's held time and step 3's "When" line */
.slot.taking { background: var(--ink); color: var(--paper); border-color: var(--ink); view-transition-name: held-when; }
.held__when { view-transition-name: held-when; }
.vt-when { view-transition-name: held-when; }
::view-transition-group(held-when) { animation-duration: .5s; animation-timing-function: var(--ease); }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-image-pair(*),
  ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

/* o) the margin rail tracks the reading. Each section a visitor has passed
   keeps a short pastel band above its label, cycling yellow, blue, red, so a
   read page reassembles the flag down its own margin; the section under the
   eye darkens its number. JS adds .seen and .live; without it, nothing shows. */
.rail[data-count] > .meta::before {
  content: ""; display: block; width: 1.6rem; height: 2px; margin-bottom: .55rem;
  background: var(--band-c, var(--pa-yellow));
  transform: scaleX(0); transform-origin: left; transition: transform .7s var(--ease);
}
.rail.seen > .meta::before { transform: scaleX(1); }
.rail[data-count] > .meta { transition: color .5s var(--ease); }
.rail.live > .meta { color: var(--ink); }
.rail__idx { transition: color .6s var(--ease); }
.rail.live .rail__idx { color: var(--ink-3); }

/* p) a pressed slot acknowledges the finger before the page moves */
.slot:active { transform: translateY(0) scale(.97); }

/* p2) the calendar arrives: slots settle in one after another, each day a
   beat behind the one before. An animation rather than a transition, so the
   slot's own hover and press transitions stay at their .25s. JS hands each
   slot its delay in --d. */
@keyframes slot-in { from { opacity: 0; translate: 0 .5rem; } }
.js .day__slots > .slot { animation: slot-in .55s var(--ease) var(--d, 0s) backwards; }

/* q) the hold visibly drains: a hairline under the countdown empties with it */
.held__timer, .pay__timer { position: relative; }
.held__timer::after, .pay__timer::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -.35rem; height: 1px;
  background: currentColor; opacity: .45;
  transform: scaleX(var(--drain, 1)); transform-origin: left;
  transition: transform .95s linear;
}

/* r) form fields answer the visitor: the hint brightens while its field has
   focus, and the placeholder steps back to make room */
.field__hint { transition: color .3s var(--ease); }
.field:focus-within .field__hint { color: var(--ink-2); }
.field input::placeholder, .field textarea::placeholder { transition: opacity .3s var(--ease); opacity: .85; }
.field input:focus::placeholder, .field textarea:focus::placeholder { opacity: .4; }

/* s) the FAQ plus turns as it collapses into a minus */
.faq__mark { transition: transform .45s var(--ease); }
.faq__item[open] .faq__mark { transform: rotate(90deg); }

/* t) the tricolour band under the wordmark draws itself on arrival */
@keyframes band-in { from { transform: scaleX(0); } }
.js .wordmark::after { animation: band-in .7s var(--ease) .1s backwards; }

@media (prefers-reduced-motion: reduce) {
  .rail[data-count] > .meta::before { display: none; }
  .held__timer::after, .pay__timer::after { display: none; }
  .slot:active { transform: none; }
  .js .day__slots > .slot { animation: none; }
  .js .wordmark::after { animation: none; }
}

/* =========================================================================
   35. Listings
   The photographs are portrait phone shots, so the media box is 4:5 and the
   picture keeps its own shape. A 21:9 crop would cut the subject out of most
   of them.
   ========================================================================= */
.plots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1.5rem, 3vw, 3rem); margin-top: 2.6rem; }
.plots > * { display: flex; flex-direction: column; }
@media (max-width: 900px) { .plots { grid-template-columns: 1fr; } }

.plot { display: block; text-decoration: none; }
.plot__media { position: relative; overflow: hidden; background: var(--wash); margin-bottom: 1rem; }
.plot__media img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; display: block;
  transition: transform 1s var(--ease); }
.plot:hover .plot__media img { transform: scale(1.035); }
.plot__draft {
  position: absolute; top: .7rem; left: .7rem; background: var(--paper); color: var(--ink);
  font-family: var(--mono); font-size: .6rem; letter-spacing: .16em; text-transform: uppercase;
  padding: .25rem .5rem; border: 1px solid var(--ink);
}
.plot__t { font-family: var(--serif); font-weight: 300; font-size: 1.35rem; line-height: 1.2; margin-top: .5rem; }
.plot__price { font-family: var(--mono); font-size: 1.02rem; margin-top: .7rem; }
.plot__facts { font-size: .78rem; color: var(--ink-2); margin-top: .35rem; letter-spacing: .02em; }
.plot__go { display: inline-flex; gap: .5rem; font-size: .88rem; margin-top: .9rem; }

/* The listings area on Real Estate: one block per area, each opening on a full
   hairline with the area set in serif and its count in mono on the far side.
   The areas come from the listings, so this styles however many there turn out
   to be without anything here knowing their names. */
.listings { margin-top: 3.5rem; }
.area { margin-top: clamp(2.6rem, 5vw, 4rem); }
.area__head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: .4rem 1.5rem; padding-top: 1.1rem; border-top: 1px solid var(--ink);
}
.area__t { font-family: var(--serif); font-weight: 300; line-height: 1.15; margin-top: .4rem;
  font-size: clamp(1.6rem, 2.6vw, 2.1rem); }
.area__count { font-family: var(--mono); font-size: .78rem; letter-spacing: .04em; color: var(--ink-2);
  font-variant-numeric: tabular-nums; }
.area .plots { margin-top: 2rem; }
.listings + .faq { margin-top: clamp(3.2rem, 6vw, 4.6rem); }

/* the gallery leads with one large frame, the rest in pairs */
.gallery { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .75rem; }
.gallery__f { margin: 0; overflow: hidden; background: var(--wash); }
.gallery__f img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 1.1s var(--ease); }
.gallery__f:hover img { transform: scale(1.03); }
.gallery__f.is-lead { grid-column: 1 / -1; }
.gallery__f.is-lead img { aspect-ratio: 3 / 2; }
.gallery__f:not(.is-lead) img { aspect-ratio: 4 / 5; }
@media (max-width: 620px) { .gallery { grid-template-columns: 1fr; } }

.pfacts { display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); gap: 1.2rem;
  margin-top: 2.6rem; padding: 1.4rem 0; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--rule); }
.pfacts > div { display: flex; flex-direction: column; gap: .4rem; }
.pfacts__v { font-family: var(--mono); font-size: 1.15rem; }

.pcols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1.5rem, 3vw, 3rem); margin-top: 2.6rem; }
@media (max-width: 760px) { .pcols { grid-template-columns: 1fr; } }

.pcta { display: flex; flex-wrap: wrap; align-items: end; justify-content: space-between;
  gap: 1.5rem; margin-top: 3rem; padding-top: 1.6rem; border-top: 1px solid var(--ink); }

/* =========================================================================
   36. The ladder, checkout only
   Quiet by construction: smaller type than the page above it, estimates set in
   mono at the far edge rather than in the headline. Someone reading this has
   already decided; it is information, not a second thing being sold.
   ========================================================================= */
.after { border-top: 1px solid var(--rule); }
.after .subtitle { font-size: clamp(1.2rem, 1.7vw, 1.5rem); }
.ladder { margin-top: 2rem; border-top: 1px solid var(--ink); }
.rung {
  display: grid; grid-template-columns: 2.6rem minmax(0, 9rem) minmax(0, 1fr) minmax(0, 9rem);
  gap: clamp(.9rem, 2vw, 2rem); padding: 1.4rem 0; border-bottom: 1px solid var(--rule);
  align-items: start; transition: background .4s var(--ease);
}
.rung:hover { background: var(--wash); }
.rung__n { font-size: .74rem; color: var(--ink-3); padding-top: .25rem; }
.rung__name { font-family: var(--serif); font-size: 1.18rem; line-height: 1.2; }
.rung__b { color: var(--ink-2); font-size: .92rem; }
.rung__items { margin-top: .7rem; }
.rung__items li { list-style: none; font-size: .84rem; color: var(--ink-3); padding: .18rem 0; }
.rung__items li::before { content: ""; display: inline-block; width: .3rem; height: .3rem;
  margin-right: .55rem; vertical-align: middle; background: var(--rule); }
.rung__p { font-size: .76rem; color: var(--ink-3); text-align: right; padding-top: .3rem; letter-spacing: .04em; }
.rung.is-now .rung__n, .rung.is-now .rung__p { color: var(--ink); }
.rung.is-now { background: var(--pa-yellow-wash); }
.rung:nth-child(2):hover { background: var(--pa-blue-wash); }
.rung:nth-child(3):hover { background: var(--pa-red-wash); }
.rung--aside { border-bottom: 1px solid var(--ink); }
.rung--aside .rung__n { color: var(--ink-3); }
.after__single { margin-top: 1.3rem; font-size: .88rem; color: var(--ink-2); max-width: 44rem; }
.after__foot { margin-top: .9rem; font-size: .8rem; color: var(--ink-3); max-width: 44rem; }
@media (max-width: 820px) {
  .rung { grid-template-columns: 2.2rem minmax(0, 1fr); row-gap: .5rem; }
  .rung__b, .rung__p { grid-column: 2; }
  .rung__p { text-align: left; }
}

/* 37. Language switcher ---------------------------------------------------
   Only rendered once a second language exists. Two-letter codes rather than
   flags: a flag names a country and we mean a language. */
.langsw { display: inline-flex; align-items: baseline; gap: .3rem; font-family: var(--mono);
  font-size: .68rem; letter-spacing: .12em; }
.langsw__l { text-decoration: none; color: var(--ink-3); transition: color .3s var(--ease); }
.langsw__l:hover { color: var(--ink); }
.langsw__l.is-on { color: var(--ink); }
.langsw__s { color: var(--rule); }

/* =========================================================================
   38. The free door
   A property question does not need a paid consultation. This sits beside the
   listing and beside the paid call, quieter than either, so nobody assumes the
   only way to ask anything is to pay first.
   ========================================================================= */
.ask { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 1.2rem; margin-top: 1.6rem; padding: 1.2rem 0;
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
.ask__h { font-family: var(--serif); font-size: 1.15rem; }
.ask__b { color: var(--ink-2); font-size: .92rem; margin-top: .4rem; max-width: 32rem; }
.ask__cta { display: inline-flex; align-items: center; gap: .6rem; text-decoration: none;
  border: 1px solid var(--ink); padding: .7rem 1rem; font-size: .92rem; white-space: nowrap;
  transition: background .3s var(--ease), color .3s var(--ease); }
.ask__cta:hover { background: var(--ink); color: var(--paper); }
.ask__ic { display: inline-flex; transition: transform .35s var(--ease); }
.ask__cta:hover .ask__ic { transform: translateX(2px) translateY(-1px); }
.ask__free { font-family: var(--mono); font-size: .6rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-3); border: 1px solid var(--rule);
  padding: .1rem .35rem; }
.ask__cta:hover .ask__free { color: var(--paper); border-color: var(--paper); }
.ask__note { margin-top: .7rem; font-size: .8rem; color: var(--ink-3); }

/* on a listing card the same idea shrinks to one line under the price */
.ask--compact { margin-top: .9rem; padding: .7rem 0 0; border-bottom: 0; }
.ask--compact .ask__h { font-size: .88rem; font-family: var(--sans); color: var(--ink-2); }
.ask--compact .ask__cta { padding: .5rem .75rem; font-size: .82rem; }

/* =========================================================================
   41. Payment
   The calendar chip became a button inside a form when holding a slot moved
   from GET to POST, so the form has to disappear from the layout and the
   button has to shed the styling a button brings with it. Everything else
   here is the payment page: an address a person has to be able to read
   character by character, and the queue the operator works from.
   ========================================================================= */

.slot-form { display: contents; }
.slot { border-radius: 0; line-height: 1.2; font: inherit; font-family: var(--mono);
  font-size: .85rem; letter-spacing: .02em; }
.js .day__slots .slot { animation: slot-in .55s var(--ease) var(--d, 0s) backwards; }

/* The terms checkbox. The label is the operator's own sentence and has to read
   as a sentence, not as fine print, so it sits at body size with the box
   aligned to its first line. */
.terms { display: grid; grid-template-columns: 1.1rem minmax(0, 1fr); gap: .7rem;
  align-items: start; margin-top: 1.6rem; padding-top: 1.2rem;
  border-top: 1px solid var(--rule); font-size: .86rem; line-height: 1.5;
  color: var(--ink-2); cursor: pointer; }
.terms input { margin: .2rem 0 0; accent-color: var(--ink); }
.terms b { font-weight: 600; color: var(--ink); display: block; }
.field__hint--warn { color: var(--ve-red, #b3403a); }

/* The address. Monospace, broken into readable runs, and selectable as one
   piece: a mistyped character here loses somebody's money. */
.payaddr { font-family: var(--mono); font-size: .82rem; line-height: 1.5;
  word-break: break-all; margin-top: .9rem; padding: .7rem .8rem;
  border: 1px solid var(--rule); background: var(--wash); user-select: all; }
.payaddr--sm { font-size: .74rem; padding: .35rem .5rem; text-align: left; }

.qr { margin-top: 1.1rem; background: var(--paper); }
/* The copy and share row under the address. Wraps rather than squeezing: on a
   phone these are the two things the buyer actually presses. */
.payacts { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .9rem; }
.payacts .btn { flex: 0 0 auto; }
.qr svg { display: block; width: 100%; max-width: 15rem; height: auto;
  margin-inline: auto; image-rendering: pixelated; }

/* What the page knows so far. Quiet while it waits, and marked once the
   transfer is on the chain, because that is the moment a buyer stops worrying. */
.paystate { margin-top: 1.8rem; padding: .9rem 1rem; border: 1px solid var(--rule);
  background: var(--wash); font-size: .9rem; color: var(--ink-2); }
.paystate.is-seen { border-color: var(--ink); background: var(--pa-yellow-wash); color: var(--ink); }
.paystate p + p { margin-top: .6rem; }
/* A transfer that arrived short. Marked, because it is the one thing on the
   page the buyer has to read, and not shouted, because he has not done anything
   wrong that a person cannot sort out. */
.paystate--short { border-color: var(--ve-red, #b3403a); }

/* The network step, as a modal in front of the pay page. Server rendered and
   posted as a form: there is no JavaScript here, and nothing to open or close.
   The page behind is the frame of where he is going, dimmed and set back; the
   address is not blurred out of it, it is not in the document at all until the
   box is ticked.

   One paragraph, one box, one button. Anything longer stops being read. */
.gate-under { filter: blur(3px); opacity: .45; pointer-events: none; user-select: none; }
.gate-veil {
  position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center;
  padding: 1.5rem 1.1rem; overflow-y: auto;
  background: rgba(255, 255, 255, .74); backdrop-filter: blur(5px);
}
.gate-modal {
  width: 100%; max-width: 28rem; margin: auto;
  background: var(--paper); border: 1px solid var(--ink);
  padding: clamp(1.5rem, 4vw, 2.1rem);
  box-shadow: 0 1.5rem 3.5rem rgba(14, 14, 14, .1);
}
.gate-modal__title { font-size: clamp(1.5rem, 3.2vw, 1.9rem); margin-top: .5rem; }
.gate-modal__body { margin-top: .9rem; font-size: .95rem; line-height: 1.65; color: var(--ink-2); }
.gate-modal form { margin-top: 1.5rem; }
.gate-modal .terms { font-size: .88rem; }
/* The one action, sized like every other button on the site rather than
   stretched across the card: this is a decision, not an app. */
.gate-modal__go { margin-top: 1.3rem; }
/* The freeze is running while he reads, so it is shown running: same markup and
   same timer the address page uses. A hairline separates it from the decision. */
.gate-modal__foot {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  margin-top: 1.5rem; padding-top: .9rem; border-top: 1px solid var(--rule);
}
.gate-modal__foot .meta { max-width: 16rem; }
.gate-modal__foot .held__timer { font-size: .95rem; }
@media (max-width: 420px) {
  .gate-veil { padding: 1rem .8rem; }
  .gate-modal__foot { flex-direction: column; align-items: flex-start; gap: .45rem; }
}

.summary--tight { margin-top: 1.2rem; }
.summary--tight > div { padding: .55rem 0; font-size: .9rem; }
.form--tight { margin-top: 1.4rem; }

/* The review queue. One card per payment a person has to decide about. */
.review { margin-top: 1.8rem; padding: 1.2rem 0; border-top: 1px solid var(--ink); }
.review__who { font-family: var(--serif); font-size: 1.25rem; }
.review__acts { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: 1.2rem; }
/* A figure meant to be read digit by digit. Deliberately a new class: `mono`
   appears in older templates without ever having had a rule, and giving it one
   now would silently restyle pages this phase was not asked to touch. */
.paynum { font-family: var(--mono); font-variant-numeric: tabular-nums; }
/* A transaction hash is sixty-six characters and has to fit inside its own
   column on the operator's page rather than running off the end of the row. */
.summary--tight dd { word-break: break-all; }

/* A stranded payment is money we hold against a slot somebody else now has.
   It reads differently from a payment waiting on a decision, because the
   operator has to do something outside this machine about it. */
.review--stranded { border-top-color: var(--ve-red, #b3403a); }
.review__flag { font-family: var(--mono); font-size: .68rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ve-red, #b3403a); margin-top: .5rem; }
.review__note { margin-top: 1rem; font-size: .88rem; color: var(--ink-2); max-width: 42rem; }
.review__acts .field--inline { margin-bottom: 0; flex: 1 1 16rem; }
.review__acts .field--inline input { margin-top: .35rem; padding: .5rem .6rem; font-size: .9rem; }
.review__acts { align-items: end; }

/* =========================================================================
   42. Booking step one: the month
   The first thing a paying visitor touches, so it is set like the rest of the
   page rather than like a widget. A hairline month rule, weekday initials in
   the mono utility voice, and a day that is nothing but its own number.

   Availability is a dot, never a count: "3 times free" on a Tuesday and
   "1 time free" on a Wednesday reads as a diary nobody is using, which is the
   impression the month grid exists to correct. A day you can book is a link
   and carries the mark; every other day is muted and inert, so the difference
   survives without colour and without JavaScript.
   ========================================================================= */
/* One rule across both columns rather than one per column: the month and the
   chosen day start on the same line, the way the rest of the page starts its
   sections. Stacked, each block takes its own rule back. */
.book1 {
  display: grid; grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  gap: clamp(1.8rem, 4vw, 4rem); align-items: start;
  margin-top: 2.8rem; padding-top: 1.35rem; border-top: 1px solid var(--ink);
}
@media (max-width: 900px) {
  .book1 { grid-template-columns: minmax(0, 1fr); gap: 2.4rem; }
  .cal { max-width: 26rem; }
}

.cal__head { display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; padding-bottom: .5rem; }
.cal__nav { display: flex; flex-wrap: wrap; gap: 1.1rem; }
.cal__step { font-family: var(--mono); font-size: .62rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-3); text-decoration: none;
  white-space: nowrap; transition: color .3s var(--ease); }
.cal__step:hover, .cal__step:focus-visible { color: var(--ink); }

.cal__grid { width: 100%; table-layout: fixed; border-collapse: collapse; }
.cal__grid th {
  font-family: var(--mono); font-weight: 500; font-size: .58rem; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-3); text-align: center;
  padding: .95rem 0 .5rem; border-bottom: 1px solid var(--rule);
}
.cal__grid td { padding: 1px; }

/* One cell: the number, and under it the room the mark occupies whether or not
   the day has one, so no row ever shifts against the row above it. */
.cal__d {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .32rem; min-height: 3.1rem; padding: .4rem 0; text-decoration: none;
  color: var(--ink-2);
}
.cal__n { font-family: var(--mono); font-size: .82rem; letter-spacing: .01em;
  font-variant-numeric: tabular-nums; line-height: 1; }
.cal__dot { display: block; width: .3rem; height: .3rem; flex: none;
  background: var(--pa-yellow); transition: background .3s var(--ease); }

/* Days you cannot book: outside the window, or with nothing left on them. Days
   belonging to the month either side fade further, so the month reads as one
   shape rather than six weeks of numbers. */
.cal__d.is-off { cursor: default; color: var(--ink-3); }
.cal__d.is-off .cal__dot { visibility: hidden; }
.cal__d.is-out { color: var(--rule); }
.cal__d.is-today .cal__n { box-shadow: 0 .32rem 0 -.28rem currentColor; }
/* A day you are looking at but cannot book is outlined, not filled: the filled
   square is the site's "this is chosen and live" mark and must not promise a
   time that is not there. */
.cal__d.is-off.is-on { box-shadow: inset 0 0 0 1px var(--ink); color: var(--ink); }

a.cal__d { color: var(--ink); transition: background .3s var(--ease), color .3s var(--ease); }
a.cal__d:hover:not(.is-on), a.cal__d:focus-visible:not(.is-on) { background: var(--pa-yellow-wash); }
a.cal__d:hover:not(.is-on) .cal__dot { background: var(--ink); }
a.cal__d.is-on { background: var(--ink); color: var(--paper); }
a.cal__d.is-on .cal__dot { background: var(--paper); }

.cal__legend { display: flex; align-items: center; gap: .55rem; font-size: .6rem;
  margin-top: 1.1rem; padding-top: .9rem; border-top: 1px solid var(--rule); }

/* The chosen day. Same .day and .day__slots the list version used, so the chips,
   their entrance stagger and the view transition that carries the chosen half
   hour to step 2 all behave exactly as before. */
.day--one { grid-template-columns: minmax(0, 1fr); row-gap: 1.2rem;
  padding-block: 0 1.9rem; border-top: 0; border-bottom: 0; }
.day--one .day__when { display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem .9rem; }
.day--one .day__wd { font-size: clamp(1.7rem, 2.8vw, 2.2rem); }
.day--one .day__date { margin-top: 0; }

/* The nearest free day on either side. Quiet, and always there: it costs one
   hairline row and saves a visitor a second guess at the grid. */
.near { display: flex; flex-wrap: wrap; align-items: flex-start;
  justify-content: space-between; gap: 1.1rem 2rem;
  padding-top: 1.15rem; border-top: 1px solid var(--rule); }
.near__l { display: block; text-decoration: none; max-width: 16rem; }
.near__l--r { margin-left: auto; text-align: right; }
.near__d { display: block; margin-top: .4rem; font-size: .93rem; color: var(--ink-2);
  transition: color .3s var(--ease); }
.near__l:hover .near__d, .near__l:focus-visible .near__d { color: var(--ink); }

/* Stacked, the two blocks are no longer under one rule, so the day takes its
   own back. After the base rule above, not inside the earlier media block:
   equal specificity, and the last one written wins. */
@media (max-width: 900px) {
  .day--one { padding-top: 1.35rem; border-top: 1px solid var(--ink); }
}
@media (max-width: 420px) {
  .cal__d { min-height: 2.8rem; }
  .cal__head { flex-wrap: wrap; }
  .near__l { max-width: 100%; }
}
