/*
 * Aperro site styles.
 *
 * Built from the Figma frames "Aperro / Desktop" (1440 wide) and
 * "Aperro / Mobile" (390 wide). Desktop values are the defaults; the single
 * breakpoint at 860px switches to the mobile layout. Large headings use
 * clamp() so widths between the two frames scale smoothly instead of jumping.
 */

/* ---------- Fonts (self-hosted latin subsets from Google Fonts) ---------- */

@font-face {
  font-family: "Barlow Condensed";
  src: url("/fonts/barlow-condensed-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* DM Sans is variable in weight and optical size; the design fixes opsz at 14. */
@font-face {
  font-family: "DM Sans";
  src: url("/fonts/dm-sans.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* Google's latin subset of DM Sans leaves out the arrows, so they come from a
   second tiny file covering only → and ↓. */
@font-face {
  font-family: "DM Sans";
  src: url("/fonts/dm-sans-arrows.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+2192, U+2193;
}

/* The italic face, for the emphasised phrases that come from Figma as <em>. */
@font-face {
  font-family: "DM Sans";
  src: url("/fonts/dm-sans-italic.woff2") format("woff2");
  font-weight: 400 700;
  font-style: italic;
  font-display: swap;
}

/* Fraunces SemiBold with SOFT 0 and WONK 1 baked in; only opsz stays variable. */
@font-face {
  font-family: "Fraunces";
  src: url("/fonts/fraunces.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */

:root {
  --color-ink: #27312b;
  --color-ochre: #e6b368;
  --color-paper: #ece5d8;
  --color-white: #f9f5ec;
  --color-sand: #e1dacd;
  /* Dark enough for body text on the sand sections (4.8:1). */
  --color-muted: #575e51;
  --color-line: #b9bbaa;

  --font-display: "Barlow Condensed", "Arial Narrow", sans-serif;
  --font-body: "DM Sans", system-ui, sans-serif;
  --font-wordmark: "Fraunces", Georgia, serif;

  /* Horizontal page padding: 80px on the desktop frame, 24px on mobile. */
  --gutter: 80px;
  --content: 1280px;
}

/* ---------- Base ---------- */

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

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

body {
  margin: 0;
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: 18px;
  line-height: 28px;
  font-variation-settings: "opsz" 14;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, figure, ol {
  margin: 0;
}

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

/* Every text link is underlined; the line thickens on hover. Buttons and the
   brand lockup opt out below. */
a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1px;
}

a:hover {
  text-decoration-thickness: 2px;
}

hr {
  border: 0;
  margin: 0;
}

/* The Aperro wordmark face. Fraunces picks its optical size from the font size,
   so the body's fixed opsz must not be inherited here. */
.wordmark {
  font-family: var(--font-wordmark);
  font-weight: 600;
  font-variation-settings: normal;
  font-optical-sizing: auto;
}

.mobile-only {
  display: none;
}

/* The short ochre bar above every section heading. */
.mark {
  display: block;
  width: 40px;
  height: 4px;
  background: var(--color-ochre);
}

.mark--ink {
  background: var(--color-ink);
}

.eyebrow {
  font-size: 11px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.heading {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(42px, 4.03vw, 58px);
  line-height: 1.07;
  letter-spacing: -0.01em;
}

.heading--sub {
  font-size: clamp(38px, 3.2vw, 46px);
  line-height: 1.09;
}

.heading--ochre {
  color: var(--color-ochre);
}

.section-heading {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Small uppercase label chips used on photos. */
.chip {
  display: inline-block;
  background: var(--color-white);
  color: var(--color-ink);
  padding: 8px 12px;
  font-size: 11px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.button {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  /* Figma draws button strokes inside the box: every tone carries a 1px
     border (transparent when filled), so all buttons are 56px tall. */
  padding: 15px 23px;
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 24px;
  font-weight: 700;
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
}

.button .arrow {
  width: 22px;
}

/* Buttons are links, but never carry the text-link underline. */
.button,
.button:hover {
  text-decoration: none;
}

/* Call and text actions: a 20px line icon before the label, in the label's
   colour, 10px from it. */
.button--icon {
  gap: 10px;
}

.button__icon {
  flex: none;
  width: 20px;
  height: 20px;
}

/* Outline button for dark bands: light stroke and text, with a light wash on
   hover. */
.button--paper-outline {
  border-color: var(--color-white);
  color: var(--color-white);
}

.button--paper-outline:hover {
  background: rgba(255, 255, 255, 0.12);
}

.button--pine {
  background: var(--color-ink);
  color: var(--color-white);
}

.button--outline {
  border-color: var(--color-ink);
  color: var(--color-ink);
}

.button--ochre {
  background: var(--color-ochre);
  color: var(--color-ink);
}

/* ---------- Navigation ---------- */

.nav {
  display: flex;
  align-items: center;
  gap: 48px;
  padding: 24px 64px;
  background: var(--color-paper);
}

.nav__brand {
  flex: 1;
  display: flex;
  align-items: center;
  min-width: 0;
  color: var(--color-ink);
}

.nav__brand,
.nav__brand:hover {
  text-decoration: none;
}

.nav__lockup {
  display: block;
  flex: none;
}

/* Horizontal lockup at header size: 44px wordmark, about 392 x 44. */
.nav__lockup--horizontal {
  width: 391.56px;
  height: 44px;
}

/* Compact lockup for phones: 34px wordmark over small tracked caps. */
.nav__lockup--compact {
  display: none;
  width: 142px;
  height: 50.5px;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 48px;
}

.nav__link {
  font-size: 18px;
  line-height: 28px;
  font-weight: 500;
}

/* ---------- Hero ---------- */

.hero {
  display: grid;
  /* 744 / 696 split from the desktop frame. */
  grid-template-columns: 744fr 696fr;
  background: var(--color-ochre);
}

.hero__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding: 58px 64px 52px;
  max-width: 744px;
}

.hero__title {
  padding: 24px 0;
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(66px, 7.78vw, 112px);
  line-height: 0.964;
  letter-spacing: -0.01em;
}

/* Rotating last word (hero-words.js). The stage is exactly one line tall
   whatever it shows, so the page never moves while words change, and it clips
   letters that roll up out of the line or in from below. The hair of padding
   keeps glyph edges clear of the clip and is taken back by the margins, so
   the line is exactly as wide as the word. */
.hero__word-stage {
  display: inline-block;
  position: relative;
  height: 1lh;
  vertical-align: top;
  overflow: hidden;
  padding: 0 0.06em;
  margin: 0 -0.06em;
  white-space: nowrap;
  /* Copying the heading gives its real text, not the word on show. */
  user-select: none;
}

/* The word at rest. An inline-block so it can be held at the wider of two
   words while both are in play. */
.hero__word {
  display: inline-block;
}

/* Moving parts sit over the word at rest, which is hidden while they run.
   The layer covers the stage, so a letter's own height is one line: a letter
   moved by 100% of its height has left the line entirely. */
.hero__word-motion {
  position: absolute;
  inset: 0;
}

.hero__letter {
  position: absolute;
  top: 0;
  height: 100%;
  will-change: transform;
}

.hero__lead {
  font-size: 21px;
  line-height: 32px;
  max-width: 616px;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  padding: 28px 0 16px;
}

/* The phone number beside the call and text buttons, in the hero, the second
   homes band and the contact section: plain, selectable text. */
.phone-line {
  align-self: center;
  font-size: 18px;
  line-height: 28px;
  font-weight: 500;
  letter-spacing: 0.02em;
  user-select: text;
  -webkit-user-select: text;
}

/* The link to the form sits beside the buttons as plain text. */
.hero__details {
  align-self: center;
  font-size: 18px;
  line-height: 28px;
  font-weight: 500;
}

/* A hairline that closes the introduction, 40px under the details link. */
.hero__rule {
  width: 100%;
  max-width: 616px;
  margin-top: 28px;
  height: 1px;
  background: var(--color-ink);
}

.hero__photo {
  position: relative;
  min-height: 757px;
  overflow: hidden;
}

.hero__photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The owner's name sits bottom-right of the hero photo on wide screens and
   bottom-left on phones, where the photo is a short landscape. */
.chip--caption {
  position: absolute;
  right: 16px;
  bottom: 16px;
  background: var(--color-ink);
  color: var(--color-sand);
  padding: 8px 14px;
  font-size: 14px;
  line-height: 20px;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: none;
}

/* ---------- Service area strip ---------- */

.area-strip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 32px;
  padding: 20px var(--gutter);
  background: var(--color-ink);
  color: var(--color-paper);
  text-align: center;
  font-size: 13px;
  line-height: 22px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.area-strip__regions {
  flex: none;
  order: 1;
  white-space: nowrap;
}

/* On wide screens the group is invisible to layout: its two lists sit either
   side of the regions. */
.area-strip__towns-group {
  display: contents;
}

/* A region name never breaks across lines; lines break only at the dots. */
.area-strip__regions span {
  white-space: nowrap;
}

.area-strip__dot {
  margin: 0 14px;
}

/* The towns flank the regions in smaller, dimmer type, two lines a side. */
.area-strip__towns {
  flex: 0 1 300px;
  font-size: 10px;
  line-height: 16px;
  color: var(--color-sand);
  opacity: 0.7;
}

.area-strip__towns--left {
  order: 0;
  text-align: right;
}

.area-strip__towns--right {
  order: 2;
  text-align: left;
}

/* ---------- Services ---------- */

.services {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 72px var(--gutter);
  background: var(--color-white);
}

.services .section-heading {
  max-width: 780px;
}

.services__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 40px;
  row-gap: 32px;
  width: 100%;
  max-width: var(--content);
}

.service {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-bottom: 16px;
}

/* Each card ends with a hairline divider one gap below its text. */
.service::after {
  content: "";
  height: 1px;
  background: var(--color-line);
}

.gallery {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* A little more air between the strip and the card title than the card's
     own 12px gap gives. */
  padding-bottom: 8px;
}

.gallery img {
  width: 100%;
  object-fit: cover;
  border: 1px solid var(--color-line);
  background: var(--color-sand);
}

.gallery__item--main img {
  aspect-ratio: 400 / 260;
}

/* A lead photo the slot would crop too hard is matted instead: the whole
   photo, centred on the sand behind it. The sync decides per photo and per
   lead shape (data-fit for this slot, data-fit-phone for the square phone
   slot); see the README. */
@media (min-width: 861px) {
  .gallery__item--main img[data-fit="matte"] {
    object-fit: contain;
  }
}

/* Every gallery photo is a button that opens the lightbox. */
/* A "Photo to come" tile opens nothing. */
.gallery__item--inert {
  cursor: default;
}

.gallery__item {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}

.gallery__item:focus-visible {
  outline: 3px solid var(--color-ochre);
  outline-offset: 2px;
}

/* Six small thumbnails in one row under the main photo, filling the card's
   width: the main photo carries the card and the strip says there is more. */
.gallery__thumbs {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 8px;
}

.gallery__thumbs img {
  aspect-ratio: 1;
}

.service__title {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 30px;
  line-height: 34px;
  letter-spacing: -0.01em;
}

.service__text {
  color: var(--color-muted);
}

/* ---------- AI mockup ---------- */

/* On sand, so the dark base of the lake photo above meets a light block. */
.ai {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: 72px var(--gutter);
  background: var(--color-sand);
}

.ai__intro {
  display: flex;
  gap: 80px;
  max-width: var(--content);
}

.ai__heading {
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 0 0 600px;
}

.ai__heading .heading {
  line-height: 1.03;
}

.ai__text {
  flex: 1;
  font-size: 20px;
  line-height: 30px;
  color: var(--color-muted);
}

.ai__examples {
  display: flex;
  gap: 24px;
  max-width: var(--content);
  height: 520px;
}

/* The slider and the mockup share the row equally on wide screens. */
.ai__mockup {
  position: relative;
  flex: 1 1 0;
  border: 1px solid var(--color-line);
  overflow: hidden;
}

.ai__mockup img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 25% 50%;
}

.ai__mockup-label {
  position: absolute;
  top: 16px;
  left: 16px;
}

/* The phone-only stack of three photos. */
.ai__stack {
  display: none;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* On the sand section the photo labels are ink on the photo, not white. */
.ai .chip {
  background: var(--color-ink);
  color: var(--color-white);
}

.ai__note {
  font-size: 13px;
  line-height: 20px;
  font-weight: 500;
  color: var(--color-muted);
}

/* Before / after slider. --position is the share of the width showing the
   before photo. main.js sets it while the visitor drags anywhere on the photo,
   and from the range input when it is moved with the keyboard. */
.compare {
  position: relative;
  flex: 1;
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
  cursor: ew-resize;
  /* Horizontal drags move the slider; vertical swipes still scroll the page. */
  touch-action: pan-y;
}

.compare img {
  pointer-events: none;
}

.compare__after,
.compare__before img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Both photos share one framing; the crop sits left of centre so the
     tree on the left of the garden stays in view. */
  object-position: 25% 50%;
}

/* Clip the full-size before photo instead of resizing it, so both photos stay
   perfectly aligned as the handle moves. */
.compare__before {
  position: absolute;
  inset: 0;
  clip-path: inset(0 calc(100% - var(--position)) 0 0);
}

/* The mockup's label is clipped to the right of the divider the same way. */
.compare__after-side {
  position: absolute;
  inset: 0;
  clip-path: inset(0 0 0 var(--position));
}

.compare__divider {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--position);
  width: 2px;
  transform: translateX(-50%);
  background: var(--color-white);
}

.compare__handle {
  position: absolute;
  top: 50%;
  left: var(--position);
  width: 64px;
  height: 64px;
  /* The SVG includes 8px of shadow room around the 48px circle. */
  transform: translate(-50%, calc(-50% + 2px));
}

.compare__label {
  position: absolute;
  top: 16px;
}

.compare__label--before { left: 16px; }
.compare__label--after { right: 16px; }

/* The native range input stays for keyboard and screen reader use only.
   Pointer input goes to the photo itself, because a hidden range input on iOS
   only moves when the finger lands exactly on its invisible thumb. */
.compare__range {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}

.compare:has(.compare__range:focus-visible) {
  outline: 3px solid var(--color-ochre);
  outline-offset: 4px;
}

/* ---------- Second homes ---------- */

/* A photo-led section: the lake fills a tall panel, a pine gradient darkens
   its lower part, and the copy sits as one stack bottom-left over it. The
   contact band runs flush beneath. */
.second-homes {
  display: flex;
  flex-direction: column;
  background: var(--color-ink);
}

.second-homes__scene {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 720px;
  padding: 96px var(--gutter) 72px;
  isolation: isolate;
  overflow: hidden;
}

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

.second-homes__scene::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to bottom,
    rgba(39, 49, 43, 0) 30%,
    rgba(39, 49, 43, 0.6) 65%,
    rgba(39, 49, 43, 0.88) 100%
  );
}

.second-homes__copy {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 640px;
}

.second-homes__copy .mark {
  background: var(--color-white);
}

.second-homes__copy .heading {
  color: var(--color-white);
}

.second-homes__lead {
  font-size: 22px;
  line-height: 32px;
  font-weight: 500;
  color: var(--color-white);
}

.second-homes__text {
  color: var(--color-sand);
}


/* ---------- How we work ---------- */

/* A ruled list of three numbered steps takes two thirds of the width; the
   pricing card, the one solid object in the section, takes the last third. */
.how-we-work {
  display: flex;
  flex-direction: column;
  gap: 48px;
  padding: 96px var(--gutter);
  background: var(--color-ink);
  color: var(--color-sand);
}

.how-we-work__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 420px;
  gap: 80px;
  align-items: start;
  max-width: var(--content);
}

.steps {
  list-style: none;
  margin: 0;
  padding: 0;
}

.step {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  column-gap: 24px;
  padding: 28px 0;
  border-top: 1px solid rgba(236, 229, 216, 0.25);
}

.step:last-child {
  border-bottom: 1px solid rgba(236, 229, 216, 0.25);
}

.step__number {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 44px;
  line-height: 44px;
  color: var(--color-ochre);
}

.step__text {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.step__title,
.pricing__title {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 30px;
  line-height: 34px;
  letter-spacing: -0.01em;
}

.step__title {
  color: var(--color-white);
}

.pricing__title {
  color: var(--color-white);
}

/* The rate card: each term on its own ruled row, the label left and the
   term right, in the same ruled language as the steps. */
.terms {
  margin: 0;
}

.term {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
  padding: 14px 0;
  border-top: 1px solid rgba(236, 229, 216, 0.25);
}

.term:last-child {
  border-bottom: 1px solid rgba(236, 229, 216, 0.25);
}

.term dt {
  color: var(--color-sand);
}

.term dd {
  margin: 0;
  font-weight: 500;
  text-align: right;
  white-space: nowrap;
  color: var(--color-ochre);
}

/* The text and call buttons close the rate card, centred under it. */
.pricing__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 16px;
  padding-top: 16px;
}

.step p {
  color: var(--color-sand);
}

.pricing {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* ---------- Questions ---------- */

.faq {
  display: flex;
  flex-direction: column;
  gap: 32px;
  padding: 72px var(--gutter);
  background: var(--color-white);
}

.faq__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: 48px;
  row-gap: 32px;
  max-width: var(--content);
}

.faq__item {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.faq__item h3 {
  font-size: 20px;
  line-height: 28px;
  font-weight: 700;
}

.faq__item p {
  color: var(--color-muted);
}

/* ---------- Contact ---------- */

.contact {
  display: flex;
  gap: 96px;
  padding: 96px var(--gutter);
  background: var(--color-ink);
  color: var(--color-paper);
}

.contact__invite,
.form {
  flex: 0 1 592px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.contact__invite {
  gap: 24px;
}

.contact__title {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  color: var(--color-ochre);
  font-size: clamp(64px, 5.83vw, 84px);
  line-height: 1.048;
  letter-spacing: -0.01em;
}

/* The intro's two sentences are two paragraphs with a little air between. */
.contact__copy {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 500px;
}

.contact__text {
  font-size: 20px;
  line-height: 32px;
}

/* Text now and Call now, with room above and below; wraps on narrow screens. */
.contact__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin: 16px 0;
  max-width: 500px;
}


/* The number sits beside the buttons, as in the hero. */
.contact__phone {
  align-self: center;
  margin-left: 8px;
  font-size: 18px;
  line-height: 28px;
  font-weight: 500;
  letter-spacing: 0.02em;
}

.form {
  gap: 20px;
}

.form__title {
  font-size: 24px;
  line-height: 32px;
  font-weight: 500;
  letter-spacing: -0.03em;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}

.field__label {
  font-size: 13px;
  line-height: 20px;
  font-weight: 500;
  color: var(--color-paper);
}

.field__input {
  width: 100%;
  padding: 16px;
  font: inherit;
  font-size: 18px;
  line-height: 28px;
  color: var(--color-ink);
  background: var(--color-white);
  border: 1px solid var(--color-line);
  border-radius: 0;
}

.field__input::placeholder {
  color: var(--color-muted);
  opacity: 1;
}

.field__input:focus,
.dropzone:focus-within {
  outline: 3px solid var(--color-ochre);
  outline-offset: 0;
}

.field__input--message {
  height: 140px;
  resize: vertical;
}

.dropzone {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 22px 16px;
  background: var(--color-white);
  border: 1px dashed var(--color-line);
  cursor: pointer;
  text-align: center;
}

.dropzone__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.dropzone__title {
  font-size: 18px;
  line-height: 28px;
  font-weight: 500;
  color: var(--color-ink);
}

.dropzone__hint {
  font-size: 15px;
  line-height: 22px;
  color: var(--color-muted);
}

/* The honeypot field is off screen for people and tab order; bots still see it. */
.form__extra {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Turnstile stays empty unless it needs a visitor to click; when it does,
   the challenge sits above the button with a little room. */
.cf-turnstile:not(:empty) {
  margin-bottom: 8px;
}

.form__status {
  font-size: 15px;
  line-height: 22px;
  font-weight: 500;
  color: var(--color-ochre);
}

.form__note {
  font-size: 13px;
  line-height: 20px;
  font-weight: 500;
}

/* ---------- Footer ---------- */

.footer {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: 72px var(--gutter) 48px;
  background: var(--color-paper);
  font-size: 13px;
  line-height: 20px;
  font-weight: 500;
}

.footer__rule {
  height: 1px;
  background: var(--color-line);
  max-width: var(--content);
}

/* The name, set as a dictionary entry: the wordmark and its pronunciation
   beside the two senses. */

.name {
  display: flex;
  gap: 80px;
  max-width: var(--content);
  font-size: 18px;
  line-height: 28px;
  font-weight: 400;
}

.name__entry {
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 0 0 520px;
}

.name__word {
  font-size: 128px;
  line-height: 128px;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.name__pronunciation {
  margin-top: 24px;
  font-size: 22px;
  line-height: 30px;
  letter-spacing: 0.04em;
  color: var(--color-muted);
}

.name__senses {
  list-style: none;
  margin: 0;
  padding: 28px 0 0;
  display: flex;
  flex-direction: column;
  gap: 40px;
  flex: 1;
  max-width: 680px;
}

.sense {
  display: flex;
  gap: 24px;
}

.sense > div {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sense__number {
  flex: 0 0 30px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 44px;
  line-height: 44px;
  color: var(--color-ochre);
}

.sense__label {
  font-size: 11px;
  line-height: 16px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.sense__text {
  font-size: 26px;
  line-height: 36px;
}


/* ---------- Gallery lightbox ---------- */

/* Fraunces Italic for the lightbox quote, with SOFT 0 and WONK 0 baked in:
   the plain italic, not the wonky one. Only opsz stays variable. */
@font-face {
  font-family: "Fraunces";
  src: url("/fonts/fraunces-italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* Scroll is locked on the root while the lightbox is open. lightbox.js sets
   --lightbox-scrollbar to the width the page scrollbar took up, and the padding
   gives that width back so the page does not shift sideways. */
html.lightbox-open {
  overflow: hidden;
  padding-right: var(--lightbox-scrollbar, 0px);
}

/* The dialog element is the paper panel; its backdrop is the pine scrim. */
.lightbox {
  /* The panel takes the photo's shape. The media box is as tall as fits
     (600px, or less on a short screen: 360px leaves 32px above and below
     plus a four-line quote block) and as wide as the photo's ratio makes it,
     capped at the design width. lightbox.js sets --photo-aspect and
     data-orientation from the photo. */
  --lightbox-media-height: min(600px, calc(100dvh - 360px));
  width: min(calc(var(--lightbox-media-height) * var(--photo-aspect, 1.7333)), 1040px, calc(100vw - 64px));
  max-width: calc(100vw - 32px);
  max-height: calc(100dvh - 32px);
  padding: 0;
  border: 0;
  overflow: hidden auto;
  background: var(--color-white);
  color: var(--color-ink);
  overscroll-behavior: contain;
}

/* A portrait photo sits beside its quote instead of above it, so the panel
   stays wide and the photo keeps its full height. */
.lightbox[data-orientation="portrait"] {
  display: grid;
  grid-template-columns: auto minmax(320px, 1fr);
  align-items: center;
  width: min(1040px, calc(100vw - 64px));
}

.lightbox[data-orientation="portrait"] .lightbox__media {
  width: calc(var(--lightbox-media-height) * var(--photo-aspect, 0.75));
}

/* The dialog itself takes focus when it opens, so no control shows a ring
   until the keyboard is used. */
.lightbox:focus {
  outline: none;
}

/* --lightbox-veil is set on the dialog while a phone drags the sheet away, so
   the scrim thins with it in browsers where ::backdrop reads the dialog's
   custom properties. */
.lightbox::backdrop {
  background: rgba(39, 49, 43, calc(0.85 * var(--lightbox-veil, 1)));
}

.lightbox[open],
.lightbox[open]::backdrop {
  animation: lightbox-fade 200ms ease-out;
}

@keyframes lightbox-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

.lightbox__media {
  position: relative;
  width: 100%;
  aspect-ratio: var(--photo-aspect, 1040 / 600);
  overflow: hidden;
  background: var(--color-ink);
  /* lightbox.js handles every touch gesture on the photo itself. */
  touch-action: none;
}

.lightbox__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* The lightbox always shows the whole photo; the ink behind it fills the rest. */
  object-fit: contain;
  transition: opacity 180ms ease;
}

/* Set for a moment while the next photo loads, giving a short dissolve. */
.lightbox__image.is-switching {
  opacity: 0;
}

/* Hidden by attribute and by class, so the single photo can never show
   through behind the before/after slider. */
.lightbox__image[hidden],
.lightbox__media.is-compare .lightbox__image {
  display: none;
}

/* The before/after slider fills the media box the way the single photo does.
   Its two photos are whole photos of one view at one aspect ratio, so they
   show whole on the ink and sit centred rather than left of centre like the
   AI section's pair. */
.lightbox__compare {
  position: absolute;
  inset: 0;
  flex: none;
  transition: opacity 180ms ease;
  /* The AI section's slider lets the page pan vertically; here every touch
     gesture belongs to the lightbox, so a vertical drag on a pair is never
     taken by the browser as a scroll. */
  touch-action: none;
}

.lightbox__compare[hidden] {
  display: none;
}

.lightbox__compare.is-switching {
  opacity: 0;
}

.lightbox__compare .compare__after,
.lightbox__compare .compare__before img {
  object-fit: contain;
  object-position: 50% 50%;
}

/* The counter and the close button own the top corners of the media box, so
   the slider's labels sit one row below them. */
/* The labels sit in the bottom corners, clear of the close button, and each
   one jumps the divider to its own end. */
.lightbox__compare .compare__label {
  top: auto;
  bottom: 16px;
  cursor: pointer;
}

/* Close is a bare cross with the same soft shadow as the chevrons; the
   slider handle is the only round control on the photo. */
.lightbox__close {
  position: absolute;
  top: 8px;
  right: 8px;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--color-white);
  font-family: var(--font-body);
  font-size: 36px;
  font-weight: 400;
  line-height: 1;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.5);
  cursor: pointer;
}

/* Previous and next are bare chevrons with a soft shadow, so they read apart
   from the before/after slider's round handle. The art keeps the 64px canvas
   the circles had, offset over the 48px hit area. */
.lightbox__nav {
  position: absolute;
  top: 50%;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  cursor: pointer;
  transform: translateY(-50%);
}

.lightbox__nav img {
  position: absolute;
  top: -6px;
  left: -8px;
  width: 64px;
  height: 64px;
  max-width: none;
}

.lightbox__nav--prev { left: 16px; }
.lightbox__nav--next { right: 16px; }

.lightbox__nav .nav-art--small {
  display: none;
}

.lightbox__close:focus-visible,
.lightbox__nav:focus-visible {
  outline: 3px solid var(--color-ochre);
  outline-offset: 2px;
}

/* The card name and dots stay a left-and-right header row; the quote below
   it is a centred column under an ochre quotation mark. */
.lightbox__quote-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 32px 36px 36px;
  text-align: center;
}

.lightbox__header {
  display: flex;
  align-items: center;
  align-self: stretch;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 8px;
  text-align: left;
}

.lightbox__mark {
  font-family: var(--font-wordmark);
  font-weight: 600;
  font-size: 56px;
  line-height: 32px;
  color: var(--color-ochre);
}

.lightbox__byline {
  margin: 0;
  font-size: 13px;
  line-height: 20px;
  font-weight: 500;
  color: var(--color-muted);
}

.lightbox__dots {
  display: flex;
  gap: 6px;
}

.lightbox__dots span {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-line);
}

.lightbox__dots span.is-active {
  background: var(--color-ochre);
}

.lightbox__quote {
  margin: 0;
  font-family: var(--font-wordmark);
  font-style: italic;
  font-weight: 400;
  /* A text-size optical cut reads better than the display one at 28px. */
  font-variation-settings: "opsz" 14;
  font-size: 22px;
  line-height: 32px;
  max-width: 640px;
  letter-spacing: 0;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .lightbox[open],
  .lightbox[open]::backdrop {
    animation: none;
  }

  .lightbox__image {
    transition: none;
  }
}

/* ---------- Mid widths: keep two-column bands from overflowing ---------- */

@media (max-width: 1200px) {
  :root {
    --gutter: 48px;
  }

  .nav {
    padding: 24px 48px;
    gap: 32px;
  }

  .nav__links {
    gap: 32px;
  }

  .hero__intro {
    padding: 48px;
  }

  .ai__heading {
    flex-basis: 45%;
  }


  .name__entry {
    flex-basis: auto;
  }

  .name__word {
    font-size: 96px;
    line-height: 100px;
  }
}

/* ---------- Mobile (the 390 frame) ---------- */

@media (max-width: 860px) {
  :root {
    --gutter: 24px;
  }

  .desktop-only {
    display: none;
  }

  .mobile-only {
    display: inline;
  }

  .heading {
    font-size: 42px;
    line-height: 46px;
  }

  .heading--sub {
    font-size: 38px;
    line-height: 42px;
  }

  .nav {
    padding: 20px 24px;
    gap: 16px;
  }

  .nav__lockup--horizontal {
    display: none;
  }

  .nav__lockup--compact {
    display: block;
  }

  .hero {
    grid-template-columns: 1fr;
  }

  .hero__intro {
    max-width: none;
    padding: 36px 24px 40px;
  }

  .hero__title {
    padding: 20px 0;
    font-size: 66px;
    line-height: 63px;
  }

  .hero__lead {
    font-size: 18px;
    line-height: 28px;
  }

  .hero__actions {
    align-self: stretch;
  }

  /* The number stays beside the buttons wherever it fits and wraps under
     them only when the row runs out of room. */
  /* The form link is its own line under the buttons, 28px below them, centred. */
  .hero__details {
    flex-basis: 100%;
    margin-top: 12px;
    text-align: center;
  }

  .hero__actions {
    padding-bottom: 0;
  }

  .hero__actions .button {
    flex: 1 1 0;
    justify-content: center;
  }

  /* The mobile frame closes the hero with the photo, not a rule. */
  .hero__rule {
    display: none;
  }

  .hero__photo {
    min-height: 0;
    height: 350px;
  }

  .chip--caption {
    right: auto;
    left: 24px;
    bottom: 24px;
    font-size: 13px;
    line-height: 18px;
  }

  /* Regions on two lines, the towns under them. */
  .area-strip {
    flex-direction: column;
    gap: 8px;
    padding: 20px 24px;
    font-size: 11px;
  }

  .area-strip__regions {
    white-space: normal;
    max-width: 280px;
  }

  .area-strip__dot {
    margin: 0 8px;
  }

  /* Two lines of two regions; the middle dot gives way to the line break. */
  .area-strip__dot--middle {
    display: none;
  }

  /* One run of small type under the regions, the two lists joined by a dot. */
  .area-strip__towns-group {
    display: block;
    order: 2;
    max-width: 342px;
    font-size: 10px;
    line-height: 16px;
    text-align: center;
  }

  .area-strip__towns {
    display: inline;
  }

  .area-strip__towns--right::before {
    content: " \00b7 ";
  }

  .services {
    gap: 24px;
    padding: 56px 24px;
  }

  .services__grid {
    grid-template-columns: repeat(2, 1fr);
    column-gap: 16px;
    row-gap: 24px;
  }

  .gallery__item--main img {
    aspect-ratio: 1;
  }

  .gallery__item--main img[data-fit-phone="matte"] {
    object-fit: contain;
  }

  /* On phones the six thumbnails run as two rows of three. */
  .gallery__thumbs {
    grid-template-columns: repeat(3, 1fr);
  }

  .service__title {
    font-size: 22px;
    line-height: 25px;
  }

  .service__text {
    font-size: 14px;
    line-height: 22px;
  }

  .ai {
    gap: 24px;
    padding: 56px 24px;
  }

  .ai__intro {
    flex-direction: column;
    gap: 16px;
  }

  .ai__heading {
    flex-basis: auto;
  }

  .ai__heading .heading {
    line-height: 44px;
  }

  .ai__text {
    font-size: 18px;
    line-height: 28px;
  }

  .ai__examples {
    flex-direction: column;
    gap: 16px;
    height: auto;
  }

  /* Phones scroll through the three photos instead of dragging a slider:
     each card sticks near the top until the next one slides over it. */
  .compare,
  .ai__mockup {
    display: none;
  }
  /* The lightbox's slider still shows on phones; only the AI section
     swaps its slider for the stacked photos. */
  .lightbox__compare:not([hidden]) {
    display: block;
  }

  .ai__stack {
    display: block;
  }

  .ai__card {
    position: sticky;
    top: 16px;
    aspect-ratio: 1;
    margin-bottom: 16px;
    overflow: hidden;
    box-shadow: 0 -12px 32px rgba(39, 49, 43, 0.3);
  }

  .ai__card:last-child {
    margin-bottom: 0;
  }

  .ai__card img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 25% 50%;
  }

  .ai__card .chip {
    position: absolute;
    top: 12px;
    left: 12px;
    padding: 6px 10px;
    font-size: 10px;
    line-height: 14px;
  }

  .second-homes__scene {
    min-height: 600px;
    padding: 64px 24px 48px;
  }

  .second-homes__lead {
    font-size: 20px;
  }

  .pricing__actions .button {
    flex: 1 1 0;
    justify-content: center;
  }

  .how-we-work {
    padding: 64px 24px;
  }

  .how-we-work__body {
    grid-template-columns: 1fr;
    gap: 40px;
  }

  .step {
    grid-template-columns: 44px minmax(0, 1fr);
    column-gap: 16px;
  }

  .step__number {
    font-size: 34px;
    line-height: 34px;
  }


  .faq {
    gap: 24px;
    padding: 56px 24px;
  }

  .faq__grid {
    grid-template-columns: 1fr;
    row-gap: 24px;
  }

  .contact {
    flex-direction: column;
    gap: 48px;
    padding: 64px 24px;
  }

  .contact__invite,
  .form {
    flex-basis: auto;
  }

  .contact__title {
    font-size: 64px;
    line-height: 68px;
  }

  .contact__text {
    font-size: 18px;
  }


  .footer {
    gap: 32px;
    padding: 56px 24px 48px;
  }

  .name {
    flex-direction: column;
    gap: 32px;
  }

  .name__entry {
    gap: 12px;
  }

  .name__word {
    font-size: 80px;
    line-height: 84px;
  }

  .name__pronunciation {
    margin-top: 20px;
    font-size: 18px;
    line-height: 26px;
  }

  .name__senses {
    padding-top: 0;
    gap: 28px;
  }

  .sense {
    gap: 16px;
  }

  .sense > div {
    gap: 8px;
  }

  .sense__number {
    flex-basis: 22px;
    font-size: 34px;
    line-height: 34px;
  }

  .sense__text {
    font-size: 20px;
    line-height: 29px;
  }

  .lightbox {
    width: 100%;
    max-width: 100%;
    max-height: 100dvh;
    margin: auto 0 0;
  }

  /* The desktop portrait rule outranks .lightbox here, so it is repeated with
     the phone width: the sheet is always the full screen wide. */
  /* The sheet is a column no taller than the screen: the photo shrinks
     before the quote block ever hides, and nothing scrolls inside it. */
  .lightbox,
  .lightbox[data-orientation="portrait"] {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 100%;
    max-height: 100dvh;
    overflow: hidden;
  }

  /* The box is the photo's shape held between 3:4 and 4:3, so a wide or a
     tall photo is never a strip across the screen. lightbox.js sets the box
     and, by the three-fifths rule, whether the photo fills it (cropped from
     the centre) or shows whole on the ink. */
  .lightbox__media,
  .lightbox[data-orientation="portrait"] .lightbox__media {
    flex: 0 1 auto;
    width: 100%;
    min-height: 0;
    aspect-ratio: var(--phone-box-aspect, 1);
  }

  .lightbox__image,
  .lightbox__compare .compare__after,
  .lightbox__compare .compare__before img {
    object-fit: var(--phone-fit, contain);
  }

  .lightbox__quote-block {
    flex: none;
  }

  /* Every touch gesture on the sheet belongs to lightbox.js: a vertical drag
     anywhere on it, the quote included, carries it away. */
  .lightbox {
    touch-action: none;
  }

  /* A short dark fade at the top of the photo keeps the close cross and the
     chevrons readable on a bright photo; the controls sit above it. */
  .lightbox__media::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    z-index: 1;
    height: 112px;
    background: linear-gradient(rgba(39, 49, 43, 0.6), rgba(39, 49, 43, 0));
    pointer-events: none;
  }

  .lightbox__close,
  .lightbox__nav {
    z-index: 2;
  }

  .lightbox__close {
    top: 6px;
    right: 6px;
    width: 52px;
    height: 52px;
    font-size: 44px;
    font-weight: 500;
    text-shadow: 0 1px 8px rgba(0, 0, 0, 0.6);
  }

  .lightbox__nav {
    width: 44px;
    height: 44px;
  }

  .lightbox__nav img {
    width: 60px;
    height: 60px;
  }

  .lightbox__nav .nav-art--large {
    display: none;
  }

  .lightbox__nav .nav-art--small {
    display: block;
  }

  .lightbox__quote-block {
    padding: 24px;
  }

  .lightbox__quote {
    font-size: 18px;
    line-height: 26px;
  }

  .lightbox__mark {
    font-size: 44px;
    line-height: 24px;
  }
}

/* The rules above set a display on the dialog for its layouts; a closed
   dialog must still be gone, or it renders inline at the foot of the page. */
.lightbox:not([open]) {
  display: none;
}
