/* Offstone — site.css
   One stylesheet, no framework. Tokens, base, then page sections top to bottom,
   then the scroll choreography at the end. */

@font-face {
  font-family: "Cormorant Garamond";
  src: url("/assets/fonts/cormorant-garamond-latin-300-normal.woff2") format("woff2");
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: "Cormorant Garamond";
  src: url("/assets/fonts/cormorant-garamond-latin-400-normal.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

/* Inter — the interface typeface for everything outside the hero. Self-hosted. */
@font-face {
  font-family: "Inter";
  src: url("/assets/fonts/inter-latin-400-normal.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("/assets/fonts/inter-latin-500-normal.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("/assets/fonts/inter-latin-600-normal.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
}

/* Scroll progress through the first screen: 0 at the top, 1 once the hero has
   lifted away. Driven by CSS scroll timelines where supported, JS otherwise. */
@property --p {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

:root {
  --paper: #fff;
  --ink: #1d1d1f;
  --ink-soft: #424245;
  --ink-muted: #6e6e73;
  --line: #d2d2d7;
  --accent: #a88d6a;
  --error: #9b3a2c;

  --serif: "Cormorant Garamond", "Cormorant", Garamond, "Times New Roman", serif;
  --ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --gutter: clamp(1.5rem, 6.5vw, 7.5rem);
  --masthead-h: clamp(5.5rem, 10vw, 8rem);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --p: 0;
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--paper);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--ui);
  font-size: 1.0625rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

img { display: block; max-width: 100%; height: auto; }
h1, h2, h3, p { margin: 0; }
a { color: inherit; }

::selection { background: #e6dccb; color: var(--ink); }

:focus-visible {
  outline: 1px solid var(--ink);
  outline-offset: 4px;
}

/* ---------- Masthead: fixed, no background, logo only ---------- */

.masthead {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 10;
  padding: clamp(1.75rem, 4.5vw, 3.25rem) var(--gutter) 0;
  padding-top: max(clamp(1.75rem, 4.5vw, 3.25rem), env(safe-area-inset-top));
  pointer-events: none; /* only the logo itself is interactive */
}

.masthead__home {
  display: inline-block;
  pointer-events: auto;
}

.logo {
  width: clamp(7.5rem, 10.5vw, 10.5rem);
  height: auto;
  /* The SVG carries ~2% internal left padding; pull it back so the
     wordmark aligns optically with the text below it. */
  margin-left: calc(clamp(7.5rem, 10.5vw, 10.5rem) * -0.021);
}

/* ---------- Hero: full screen ---------- */

.hero {
  position: relative;
  z-index: 2;
  isolation: isolate;
  height: 100vh;
  height: 100svh;
  min-height: 34rem;
  /* Not clipped: the photo may extend below the box (see .hero__media). */
  padding: 0 var(--gutter);
  background: #e9e6e1;
}

.hero__media {
  position: absolute;
  inset: 0;
  /* Mobile browsers whose toolbar floats over the page (Safari on iOS 26+) show
     content behind it. The hero is one *small* viewport tall (the scroll effect
     relies on that), so the photo extends by the toolbar's height to fill the
     screen. On desktop 100lvh = 100svh and this is 0. */
  bottom: calc(100svh - 100lvh);
  z-index: -1;
  overflow: hidden;
  background: #e9e6e1;
}

.hero__media picture,
.hero__media img {
  width: 100%;
  height: 100%;
}

.hero__media img {
  object-fit: cover;
  object-position: 60% 100%;
  transform-origin: 50% 100%;
}

/* A faint, local lift of the sky behind the words so they read on any crop. */
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 60% 55% at 16% 38%, rgba(247, 244, 238, 0.55), rgba(247, 244, 238, 0) 70%);
  pointer-events: none;
}

.hero__copy {
  position: relative;
  padding-top: clamp(8.5rem, 23vh, 15rem);
}

.hero h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2.5rem, 1.05rem + 4.1vw, 5.25rem);
  line-height: 1.06;
  letter-spacing: -0.012em;
  color: var(--ink);
  font-kerning: normal;
}

.hero h1 span { display: block; text-wrap: balance; }

.lede {
  position: relative;
  font-family: var(--serif);
  margin-top: clamp(2rem, 3.6vw, 3rem);
  padding-top: clamp(1.75rem, 3vw, 2.5rem);
  max-width: 30rem;
  font-size: clamp(1.1875rem, 1rem + 0.5vw, 1.5rem);
  line-height: 1.55;
  color: var(--ink-soft);
  text-wrap: pretty;
}

/* The short rule between headline and body copy. */
.lede::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 3rem;
  height: 1px;
  background: var(--accent);
}

/* A hairline at the foot of the first screen hinting there is more below. */
.hero__cue {
  position: absolute;
  left: var(--gutter);
  bottom: max(2rem, env(safe-area-inset-bottom));
  width: 1px;
  height: clamp(2.5rem, 7vh, 4rem);
  background: rgba(29, 27, 24, 0.45);
  transform-origin: 50% 0;
}

/* ---------- Contact: the layer beneath ---------- */

.under {
  position: relative;
  z-index: 1;
}

/* Contact + footer together fill exactly one screen, so the page ends the moment
   the hero has fully lifted and nothing slides beneath the fixed logo.
   --footer-h is measured by site.js; the fallback covers the no-JS case. */
.contact {
  min-height: calc(100vh - var(--footer-h, 7rem));
  min-height: calc(100svh - var(--footer-h, 7rem));
  display: grid;
  align-content: center;
  padding: calc(var(--masthead-h) + clamp(2.5rem, 6vh, 5rem)) var(--gutter) clamp(4rem, 10vh, 7rem);
}

.contact__inner {
  display: grid;
  gap: clamp(2.5rem, 5vh, 3.5rem);
  width: 100%;
  max-width: 32rem;
  margin-inline: auto;   /* one centred column; title, labels and fields share a left edge */
}

.contact h2 {
  font-family: var(--ui);
  font-weight: 500;
  font-size: clamp(2rem, 1.5rem + 1.6vw, 2.75rem);
  line-height: 1.1;
  letter-spacing: -0.025em;
}

.form {
  display: grid;
  gap: clamp(1.75rem, 3.5vh, 2.5rem);
}

.field { display: grid; gap: 0.5rem; }

.field label,
.button,
.form__status,
.field__error,
.footer {
  font-family: var(--ui);
}

.field label {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.field input,
.field textarea {
  width: 100%;
  margin: 0;
  padding: 0.625rem 0 0.75rem;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--ui);
  font-size: 1.0625rem;   /* ≥16px keeps iOS from zooming on focus */
  line-height: 1.45;
  min-height: 3rem;
  -webkit-appearance: none;
          appearance: none;
  transition: border-color 0.4s var(--ease), box-shadow 0.4s var(--ease);
}

.field textarea {
  resize: vertical;
  min-height: 7rem;
  max-height: 24rem;
  field-sizing: content;
}
@supports (field-sizing: content) {
  .field textarea { resize: none; }
}

.field input:hover,
.field textarea:hover { border-bottom-color: #a1a1a6; }

.field input:focus,
.field textarea:focus {
  outline: none;
  border-bottom-color: var(--ink);
  box-shadow: 0 1px 0 0 var(--ink);
}

.field [aria-invalid="true"] { border-bottom-color: var(--error); }
.field [aria-invalid="true"]:focus { box-shadow: 0 1px 0 0 var(--error); }

.field__error {
  font-size: 0.875rem;
  letter-spacing: 0.01em;
  color: var(--error);
}

/* Honeypot: off-screen, not display:none, so naive bots still fill it. */
.hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.25rem 2rem;
  margin-top: 0.5rem;
}

.button {
  min-height: 3.25rem;
  min-width: 9rem;
  padding: 0 2.25rem;
  border: 1px solid var(--ink);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 0.45s var(--ease), color 0.45s var(--ease);
}

.button:hover { background: var(--ink); color: var(--paper); }
.button:active { transform: translateY(1px); }
.button[disabled] { cursor: progress; opacity: 0.55; }
.button[disabled]:hover { background: transparent; color: var(--ink); }

.form__status {
  font-size: 0.9375rem;
  color: var(--ink-soft);
}
.form__status:empty { display: none; }
.form__status:focus { outline: none; }
.form__status[data-state="error"] { color: var(--error); }

/* After a successful send the fields step aside and the message remains. */
.form.is-sent .field,
.form.is-sent .button { display: none; }
.form.is-sent .form__status {
  font-family: var(--ui);
  font-size: 1.25rem;
  color: var(--ink);
}

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

.footer {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: flex-end;
  gap: 1.5rem 3rem;
  margin: 0 var(--gutter);
  padding: 2.25rem 0 max(2.25rem, env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.footer__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 2.5rem;
}

.footer small { font-size: inherit; }

.footer a {
  display: inline-block;
  padding: 0.75rem 0;       /* comfortable touch target without visual bulk */
  margin: -0.75rem 0;
  color: var(--ink);
  text-decoration: none;
  background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
  background-position: 0 calc(100% - 0.6rem);
  transition: background-size 0.5s var(--ease);
}
.footer a:hover,
.footer a:focus-visible { background-size: 100% 1px; }

/* ---------- Phones ---------- */

@media (max-width: 767px) {
  .hero__copy { padding-top: clamp(7.5rem, 20svh, 10rem); }
  .contact { padding-top: calc(var(--masthead-h) + 1.5rem); padding-bottom: 3rem; }
  .contact__inner { gap: 2rem; }
  .form { gap: 1.5rem; }
  .field textarea { min-height: 5.5rem; }
  .hero__media::after {
    background: radial-gradient(ellipse 110% 50% at 20% 30%, rgba(247, 244, 238, 0.5), rgba(247, 244, 238, 0) 70%);
  }
  .lede { font-size: 1.1875rem; }
}

@media (orientation: portrait) and (max-width: 1100px) {
  .hero__media img { object-position: 64% 100%; }
}

/* ---------- Scroll choreography ----------
   The hero is a sheet lying over the contact section. As you scroll it slides
   up; the landscape inside it drifts at a slower rate (parallax) while the words
   lift away faster. The contact layer rises more slowly than the page, so it
   reads as having been underneath all along, and comes out of shadow as the
   sheet clears. All of it turns off for people who prefer reduced motion. */

@media (prefers-reduced-motion: no-preference) {
  /* Where supported, the browser drives --p from scroll position off the main thread. */
  @supports (animation-timeline: scroll()) {
    :root {
      animation: scroll-progress linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 100svh;
    }
  }

  .hero {
    box-shadow: 0 1.5rem 4rem rgba(29, 27, 24, calc(0.18 * (1 - var(--p))));
  }

  /* The photo's extension below the hero retracts as the sheet lifts, so it never
     covers the contact section. */
  .hero__media {
    clip-path: inset(0 0 calc((100lvh - 100svh) * var(--p)) 0);
  }

  .hero__media img {
    transform:
      translate3d(0, calc(var(--p) * 32%), 0)
      scale(calc(1 + var(--p) * 0.08));
    will-change: transform;
  }

  .hero__copy {
    transform: translate3d(0, calc(var(--p) * -8svh), 0);
    opacity: calc(1 - var(--p) * 2.6);
  }

  .hero__cue {
    opacity: calc(1 - var(--p) * 5);
    animation: cue 3.2s var(--ease) 1.6s infinite;
  }

  .under {
    transform: translate3d(0, calc((1 - var(--p)) * -42svh), 0);
    will-change: transform;
  }

  /* Shade over the contact layer that clears as the sheet lifts off it. */
  .contact::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--ink);
    opacity: calc((1 - var(--p)) * 0.2);
    pointer-events: none;
  }

  /* Staggered entrance for the contact content (enabled by JS; see site.js). */
  .js .reveal {
    opacity: 0;
    translate: 0 1.25rem;
    transition: opacity 1.1s var(--ease), translate 1.1s var(--ease);
    transition-delay: calc(var(--i, 0) * 90ms);
  }
  .js .reveal.is-in {
    opacity: 1;
    translate: 0 0;
  }

  /* First-load entrance. */
  .hero__media picture { animation: settle 6s var(--ease) both; }
  .masthead { animation: appear 1.8s var(--ease) both; }
  .hero h1 { animation: rise 1.4s var(--ease) 0.15s both; }
  .lede { animation: rise 1.4s var(--ease) 0.45s both; }
}

/* Without the scroll effect the page scrolls normally: make the hero itself fill
   the large viewport instead of extending the photo over the contact section. */
@media (prefers-reduced-motion: reduce) {
  .hero { height: 100lvh; }
  .hero__media { bottom: 0; }
}

@keyframes scroll-progress {
  from { --p: 0; }
  to   { --p: 1; }
}
@keyframes settle {
  from { scale: 1.035; }
  to   { scale: 1; }
}
/* Starts at 1% rather than 0 so browsers still count the headline as the
   page's main paint (Largest Contentful Paint). Visually identical. */
@keyframes rise {
  from { opacity: 0.01; translate: 0 0.75rem; }
  to   { opacity: 1; translate: 0 0; }
}
@keyframes appear {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes cue {
  0%   { scale: 1 0; transform-origin: 50% 0; }
  45%  { scale: 1 1; transform-origin: 50% 0; }
  55%  { scale: 1 1; transform-origin: 50% 100%; }
  100% { scale: 1 0; transform-origin: 50% 100%; }
}

/* ---------- Inner pages (Privacy & Terms, 404) ----------
   Full width, black on white, in the interface sans-serif. */

.page {
  padding: calc(var(--masthead-h) + clamp(3rem, 10vh, 6rem)) var(--gutter) clamp(5rem, 12vh, 8rem);
  color: #000;
}

.page h1 {
  font-family: var(--ui);
  font-weight: 600;
  font-size: clamp(2.25rem, 1.6rem + 2.2vw, 3.5rem);
  line-height: 1.1;
  letter-spacing: -0.03em;
}

.page .meta {
  margin-top: 0.75rem;
  font-size: 0.9375rem;
  color: var(--ink-muted);
}

.page h2 {
  margin-top: clamp(3rem, 7vh, 4.5rem);
  padding-top: 2rem;
  border-top: 1px solid var(--line);
  font-family: var(--ui);
  font-weight: 600;
  font-size: clamp(1.625rem, 1.3rem + 1vw, 2.125rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.page h3 {
  margin-top: 2rem;
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.4;
}

.page p,
.page li {
  font-size: 1.0625rem;
  line-height: 1.65;
  color: #000;
}

.page p { margin-top: 0.75rem; }
.page ul { margin: 0.75rem 0 0; padding-left: 1.25rem; }
.page li + li { margin-top: 0.375rem; }
.page strong { font-weight: 600; }

.page a {
  color: #000;
  text-decoration: underline;
  text-decoration-color: #86868b;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: text-decoration-color 0.3s var(--ease);
}
.page a:hover { text-decoration-color: #000; }

.page .intro {
  margin-top: 2rem;
  font-size: clamp(1.1875rem, 1rem + 0.4vw, 1.375rem);
  line-height: 1.5;
}


/* Long inner pages scroll beneath the fixed logo; a white backing (invisible
   against the white page) keeps text from running under it. */
.inner .masthead {
  background: var(--paper);
  padding-bottom: clamp(1rem, 2.5vw, 1.75rem);
}

.page code {
  font-family: var(--ui);
  font-size: 0.95em;
  padding: 0.1em 0.35em;
  border-radius: 4px;
  background: #f5f5f7;
}
