/*
 * 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;
}

.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);
}

/* ---------- 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 item is a button that opens the lightbox. The badges and the
   counted cell's veil sit over its image, so it is their positioning box. */
.gallery__item {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}

/* gallery.js hides the items and the strip the card does not draw; the
   display rule above would otherwise override the hidden attribute. */
.gallery__item[hidden],
.gallery__thumbs[hidden] {
  display: none;
}

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

/* One row of six cells under the lead, the cell size fixed by the Service
   component: a gallery with fewer items ends the row early, and one with more
   draws a counted cell last (gallery.js decides which items are drawn). */
.gallery__thumbs {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 8px;
}

.gallery__thumbs img {
  aspect-ratio: 1;
}

/* Kind badges: a square white chip bottom left of a pair's or a clip's cell or
   lead, holding the slider handle's two chevrons or a play triangle drawn in
   the same line (the Gallery cell component 381:286). The glyph is a mask
   filled with the ink, so its colour stays the palette's. A photo has none,
   and neither has the counted cell. */
.gallery__item:is([data-kind="pair"], [data-kind="clip"]):not(.gallery__item--more)::before,
.gallery__item:is([data-kind="pair"], [data-kind="clip"]):not(.gallery__item--more)::after {
  content: "";
  position: absolute;
  left: var(--badge-inset, 4px);
  bottom: var(--badge-inset, 4px);
  width: var(--badge-size, 16px);
  height: var(--badge-size, 16px);
  pointer-events: none;
}

.gallery__item:is([data-kind="pair"], [data-kind="clip"]):not(.gallery__item--more)::before {
  background: var(--color-white);
}

.gallery__item:is([data-kind="pair"], [data-kind="clip"]):not(.gallery__item--more)::after {
  background: var(--color-ink);
  -webkit-mask: var(--badge-glyph) center / 62.5% no-repeat;
  mask: var(--badge-glyph) center / 62.5% no-repeat;
}

.gallery__item[data-kind="pair"] {
  --badge-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 6 3 12l6 6M15 6l6 6-6 6'/%3E%3C/svg%3E");
}

.gallery__item[data-kind="clip"] {
  --badge-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 4.5v15L19.5 12z'/%3E%3C/svg%3E");
}

/* The lead's badge is larger and sits further in. */
.gallery__item--main {
  --badge-size: 24px;
  --badge-inset: 12px;
}

/* The counted cell keeps its item's still under an ink veil (opacity of the
   cell component's Count veil 386:282) with the count in the phone card
   title's setting, centred. It opens the lightbox on its own item. */
.gallery__item--more::after {
  content: attr(data-more-count);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgb(39 49 43 / 0.55);
  color: var(--color-white);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 22px;
  line-height: 25px;
  letter-spacing: -0.01em;
  pointer-events: none;
}

.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 a stable paper panel; its backdrop is the pine scrim. */
.lightbox {
  width: min(1040px, calc(100vw - 192px));
  height: min(800px, calc(100dvh - 48px));
  margin: auto;
  display: flex;
  flex-direction: column;
  padding: 0;
  border: 0;
  overflow: visible;
  background: var(--color-white);
  color: var(--color-ink);
  overscroll-behavior: contain;
}

/* 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;
  flex: 1 1 0;
  min-height: 0;
  width: 100%;
  aspect-ratio: auto;
  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;
}

/* A clip plays in the box where its poster still sits, at the same size and
   fit. lightbox.js shows it only once it has a frame of its own. */
.lightbox__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--color-ink);
}

.lightbox__video[hidden] {
  display: none;
}

/* The clip's play and pause control covers the whole media box beneath close,
   previous and next, so a tap anywhere on the clip plays or pauses it. Its
   chip is square, the size of the slider's handle with the handle's shadow
   (the clip rest frames 386:689 and 386:714). */
.lightbox__play {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.lightbox__play[hidden] {
  display: none;
}

.lightbox__play-chip {
  position: relative;
  width: 48px;
  height: 48px;
  background: var(--color-white);
  box-shadow: 0 2px 8px rgb(0 0 0 / 0.25);
}

.lightbox__play-chip::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--color-ink);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 15.5v17L32.5 24z'/%3E%3C/svg%3E") center / 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 15.5v17L32.5 24z'/%3E%3C/svg%3E") center / 100% no-repeat;
}

/* While the clip loads the chip dims to the counted cell's veil opacity; while
   it plays the chip is gone and the control's name reads Pause. */
.lightbox__media[data-clip-state="loading"] .lightbox__play-chip {
  opacity: 0.55;
}

.lightbox__media[data-clip-state="playing"] .lightbox__play-chip {
  visibility: hidden;
}

/* The box clips whatever lies outside it, so the focus outline is drawn inside. */
.lightbox__play:focus-visible {
  outline: 3px solid var(--color-ochre);
  outline-offset: -3px;
}

/* Close, previous and next stay above the clip control at every width. */
.lightbox__close,
.lightbox__nav {
  z-index: 2;
}

/* A comparison can retain its after photo while loading or offer a retry. */
.lightbox__comparison-status {
  position: absolute;
  left: 16px;
  bottom: 16px;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 8px;
  max-width: calc(100% - 32px);
}

.lightbox__notice {
  margin: 0;
}

.lightbox__notice[hidden] {
  display: none;
}

.lightbox__retry {
  color: var(--color-white);
  background: var(--color-ink);
  border: 0;
  cursor: pointer;
}

.lightbox__retry:hover {
  background: var(--color-muted);
}

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

.lightbox__retry[hidden] {
  display: none;
}

/* On wide screens the comparison is exactly the contained image rectangle,
   centred inside the fixed stage. lightbox.js supplies its source-shaped size
   so the labels, range, and drag area never occupy letterbox matte. */
.lightbox__compare {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  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 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;
  /* A pair's own side names can be longer than Before and After; each stays
     within its half of the image and wraps, so the two never meet. */
  max-width: calc(50% - 24px);
  white-space: normal;
}

.lightbox__compare .compare__label--after {
  text-align: right;
}

/* 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 64px artwork is centred
   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;
}

/* On desktop the same buttons sit 24px outside the complete photo-and-quote
   panel. Their 64px artwork and focus ring remain clear of both panel and
   viewport because the dialog reserves the matching horizontal gutter. */
.lightbox__nav--prev { left: -72px; }
.lightbox__nav--next { right: -72px; }

.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 above a compact,
   centred quote. */
.lightbox__quote-block {
  min-width: 0;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 24px;
  text-align: center;
}

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

.lightbox__mark {
  display: none;
}

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

.lightbox__dots {
  display: flex;
  align-items: center;
  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);
}

/* A window end with more items beyond it is drawn at half size. */
.lightbox__dots span.is-small {
  width: 4px;
  height: 4px;
}

.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 here. */
  font-variation-settings: "opsz" 14;
  font-size: 20px;
  line-height: 28px;
  max-width: 840px;
  letter-spacing: 0;
}

/* A shallow desktop stage still reserves useful room for the photo before
   the quote becomes denser. */
@media (min-width: 701px) and (max-height: 600px) {
  .lightbox__quote-block {
    padding: 16px;
  }

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

.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;
  }

  .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;
  }

  /* 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 strip has three cells. */
  .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;
  }

}

/* The gallery card and hero switch at 860px, but the lightbox keeps its
   stable wide viewer through tablet widths. Only a true phone gets the tuned
   bottom sheet and its direct-on-photo controls. */
@media (max-width: 700px) {
  /* 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 {
    width: 100%;
    max-width: 100%;
    /* Keep the sheet intrinsic so the modal backdrop remains a draggable scrim. */
    height: fit-content;
    max-height: 100dvh;
    margin: auto 0 0;
    overflow: hidden;
    touch-action: none;
  }

  /* 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 {
    flex: 0 1 auto;
    width: 100%;
    min-height: 0;
    aspect-ratio: var(--phone-box-aspect, 1);
  }

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

  /* Phone comparisons retain the existing full photo-box interaction area. */
  .lightbox__compare {
    inset: 0;
    width: auto !important;
    height: auto !important;
    transform: 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--prev { left: 16px; }
  .lightbox__nav--next { right: 16px; }

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

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

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

  .lightbox__quote-block {
    gap: 12px;
    padding: 24px;
  }

  .lightbox__header {
    margin-bottom: 8px;
  }

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

  .lightbox__mark {
    display: inline;
    font-family: var(--font-wordmark);
    font-weight: 600;
    font-size: 44px;
    line-height: 24px;
    color: var(--color-ochre);
  }
}

/* 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;
}
