/*
 * Haus of Contour — shared foundation.
 *
 * Design tokens, base typography, and the chrome (header, footer, buttons)
 * that every page repeats. Page-specific layout lives in its own stylesheet
 * alongside this one.
 */

/* ---------------------------------------------------------------- tokens */

:root {
  --shell:  #EFEBE4;  /* page ground                                        */
  --raised: #FBF9F6;  /* alternating sections, and text on a dark ground     */
  --ink:    #24211E;  /* headings, body copy, the dark button                */
  --muted:  #6F6862;  /* eyebrows, secondary copy                            */
  --accent: #A97460;  /* terracotta: links, hover states, the bullet square  */
  --rule:   #DCD5CA;  /* every hairline on the page                          */

  --serif: "Instrument Serif", Georgia, "Times New Roman", serif;
  --sans:  "Instrument Sans", -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --shift: 400ms var(--ease);

  --gutter: 32px;
  --measure: 1320px;
}

/* ------------------------------------------------------------------ base */

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

html {
  -webkit-font-smoothing: antialiased;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--shell);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 400;
  overflow-x: hidden;
}

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--ink); }

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

ul { margin: 0; padding: 0; list-style: none; }

figure { margin: 0; }

::selection { background: var(--rule); }

/* A visible focus ring on the sober palette. Browsers vary on whether they
   show :focus-visible for mouse clicks; this keeps keyboard users covered
   without ringing every click. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* --------------------------------------------------------------- helpers */

.shell {
  max-width: var(--measure);
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

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

/* Skip link — parked off-screen until focused. */
.skip-link {
  position: absolute;
  top: 0; left: 0;
  z-index: 60;
  transform: translateY(-110%);
  background: var(--ink);
  color: var(--raised);
  padding: 14px 22px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.skip-link:focus { transform: translateY(0); color: var(--raised); }

/* ------------------------------------------------------------ typography */

/* The small uppercase label used for every section and field heading. */
.eyebrow {
  display: block;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.display {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -0.018em;
  color: var(--ink);
  font-size: clamp(30px, 3.2vw, 44px);
}

.display--hero {
  font-size: clamp(44px, 6vw, 80px);
  line-height: 0.97;
}

.display--sm { font-size: 30px; line-height: 1.1; }

/* The one italic flourish the brand allows itself. */
.accent { font-style: italic; color: var(--accent); }

.lede {
  margin: 0;
  font-size: 17px;
  line-height: 1.62;
  color: var(--muted);
  max-width: 56ch;
}

.prose {
  margin: 0;
  font-size: 15px;
  line-height: 1.7;
  color: var(--ink);
}

.numeral { font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------- page intro */

/* Eyebrow, oversized serif headline, lede — how every page but the home page
   opens. */
.intro { padding-top: 96px; }

.intro__title { margin-top: 24px; max-width: 20ch; }

.intro__lede { margin-top: 30px; max-width: 52ch; }

@media (max-width: 719px) {
  .intro { padding-top: 64px; }
}

/* ----------------------------------------------------------- question row */

/* A question and its answer, side by side above the fold-in point. Used by
   the home page's short list and by the questions page in full. */
.qa {
  border-top: 1px solid var(--rule);
  padding: 32px 0;
  display: grid;
  grid-template-columns: minmax(min(220px, 100%), 0.7fr) minmax(min(280px, 100%), 1fr);
  gap: 48px;
}

.qa__q {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: 23px;
  line-height: 1.15;
  letter-spacing: -0.018em;
  color: var(--ink);
}

.qa__a {
  margin: 0;
  font-size: 15px;
  line-height: 1.7;
  color: var(--muted);
  max-width: 64ch;
  text-wrap: pretty;
}

@media (max-width: 720px) {
  .qa { grid-template-columns: 1fr; gap: 16px; }
}

/* --------------------------------------------------------------- buttons */

.btn {
  display: inline-block;
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--raised);
  background: var(--ink);
  border: 0;
  padding: 18px 30px;
  cursor: pointer;
  /* These labels are two or three words; wrapping one turns the button into
     a block and drags the header height with it. */
  white-space: nowrap;
  transition: background var(--shift);
}
.btn:hover { background: var(--accent); color: var(--raised); }

.btn--compact { padding: 14px 22px; }

/* The secondary action: the same shape, drawn rather than filled, so it
   never competes with the booking button beside it. */
.btn--ghost {
  color: var(--ink);
  background: none;
  border: 1px solid var(--ink);
  transition: color var(--shift), border-color var(--shift);
}
.btn--ghost:hover {
  color: var(--accent);
  background: none;
  border-color: var(--accent);
}

/* Text link that carries its own underline rule. */
.link-rule {
  display: inline-block;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  border-bottom: 1px solid var(--accent);
  padding-bottom: 3px;
  transition: color var(--shift), border-color var(--shift);
}
.link-rule:hover { color: var(--ink); border-bottom-color: var(--ink); }

/* ---------------------------------------------------------------- header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(239, 235, 228, 0.92);
  border-bottom: 1px solid var(--rule);
}

@supports (backdrop-filter: blur(8px)) or (-webkit-backdrop-filter: blur(8px)) {
  .site-header {
    background: rgba(239, 235, 228, 0.82);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
  }
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 34px;
  height: 78px;
}

/* The wordmark: a hairline rule above small, widely-tracked caps. */
.wordmark {
  display: block;
  border-top: 1px solid var(--accent);
  padding-top: 9px;
  font-size: 12px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}
.wordmark:hover { color: var(--accent); }

.site-nav {
  display: flex;
  align-items: center;
  gap: 34px;
  /* Pushes the links and the booking button together against the right
     edge, leaving the wordmark alone on the left. */
  margin-left: auto;
}

.nav-link {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 4px 0;
  border-bottom: 1px solid transparent;
  white-space: nowrap;
  transition: color var(--shift), border-color var(--shift);
}
.nav-link:hover { color: var(--ink); border-bottom-color: var(--accent); }

.nav-link[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--accent);
}

/* Below the point where the links and the button stop fitting on one line,
   the header stacks: wordmark and booking button, then the links on their own
   full-width row. It wraps rather than using fixed rows, so on a very narrow
   phone the button drops to a line of its own instead of forcing a minimum
   page width and clipping every section below it. */
@media (max-width: 900px) {
  .site-header__inner {
    flex-wrap: wrap;
    gap: 14px 16px;
    height: auto;
    padding-top: 16px;
    padding-bottom: 12px;
  }
  .wordmark { order: 1; margin-right: auto; }
  .site-header__cta { order: 2; padding: 12px 16px; }
  .site-nav {
    order: 3;
    flex: 1 0 100%;
    margin-left: 0;
    gap: 20px;
    /* Bleeds to the gutter edges and scrolls, so the narrowest phones push
       the last link along rather than losing it. */
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
    margin-inline: calc(var(--gutter) * -1);
    padding: 0 var(--gutter) 2px;
  }
  .site-nav::-webkit-scrollbar { display: none; }
}

/* 32px gutters are a lot of a 390px screen. */
@media (max-width: 720px) {
  :root { --gutter: 24px; }
}

/* ---------------------------------------------------------------- footer */

.site-footer { border-top: 1px solid var(--rule); }

.site-footer__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  padding-top: 44px;
  padding-bottom: 44px;
}

.footer-links {
  display: flex;
  align-items: center;
  gap: 28px;
  flex-wrap: wrap;
}

.footer-links a,
.footer-links span {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color var(--shift);
}
.footer-links a:hover { color: var(--accent); }

/* ---------------------------------------------------- image frame + hover */

/* A fixed-ratio window with a rule that lights up and a slow push-in on
   hover. Pointer-only: there is no hover state to reward on a touch screen,
   and the transform would only cost a repaint. */
.frame {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid transparent;
  transition: border-color 500ms var(--ease);
}

.frame__inner {
  position: absolute;
  inset: 0;
  transition: transform 700ms var(--ease);
  /* A woven greige plate behind every image. It is what shows if a file is
     missing, still uploading, or fails to decode — a deliberate-looking empty
     frame rather than a broken-image icon in the middle of the layout. */
  background: repeating-linear-gradient(
    107deg,
    #E7E1D7 0px, #E7E1D7 9px,
    #DED7CB 9px, #DED7CB 18px
  );
}

.frame__inner > img,
.frame__inner > video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .frame:hover { border-bottom-color: var(--accent); }
  .frame:hover .frame__inner { transform: scale(1.03); }
}

/* --------------------------------------------------- scroll-in animation */

/*
 * `js-motion` is set by the inline head script only when scripting is on and
 * the visitor has not asked for reduced motion, so copy is never hidden from
 * someone who would not get it back. motion.js clears the class if it fails
 * to take over within a few seconds.
 */
.js-motion [data-reveal] {
  clip-path: inset(0 0 100% 0);
  opacity: 0;
}

/* ------------------------------------------------- anchored scrolling */

/* The header is sticky, so a jump to #buccal would otherwise park the
   section title underneath it. */
main [id] { scroll-margin-top: 96px; }

@media (max-width: 900px) {
  main [id] { scroll-margin-top: 132px; }
}

/* ---------------------------------------------------------- parallax bands */

/* A full-bleed photograph that drifts against the scroll. motion.js drives
   the transform from [data-parallax]; without it the band is simply a
   cropped image, which is why the layer is overscanned rather than offset. */
.band {
  position: relative;
  height: 74vh;
  min-height: 480px;
  overflow: hidden;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.band--short { height: 70vh; min-height: 440px; }

/* Overscanned top and bottom so the parallax shift never exposes an edge. */
.band__layer {
  position: absolute;
  inset: -7% 0;
  will-change: transform;
  /* Same plate as .frame__inner, at the band's coarser scale. */
  background: repeating-linear-gradient(
    97deg,
    #E7E1D7 0px, #E7E1D7 11px,
    #DED7CB 11px, #DED7CB 22px
  );
}

.band__layer > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 767px) {
  .band { height: 52vh; min-height: 320px; }
  .band--short { height: 50vh; min-height: 300px; }
}

/* ------------------------------------------------------------- "best for" */

/* A small terracotta square in place of a bullet. */
.fit-list {
  margin-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.fit-list li {
  font-size: 15px;
  line-height: 1.7;
  color: var(--ink);
  padding-left: 20px;
  position: relative;
}

.fit-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 11px;
  width: 5px;
  height: 5px;
  background: var(--accent);
}

/* ------------------------------------------------------------ detail grid */

/* Ruled columns of short prose under an eyebrow — protocol, aftercare,
   contraindications, studio facts. Used by several pages. */
.details {
  margin-top: 64px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 40px 44px;
}

.details__item {
  border-top: 1px solid var(--rule);
  padding-top: 22px;
}

.details__item .prose { margin-top: 14px; }

/* --------------------------------------------------------- horizontal rail */

.studio {
  border-top: 1px solid var(--rule);
  background: var(--raised);
  padding-top: 96px;
  padding-bottom: 96px;
}

.studio__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  padding-bottom: 40px;
}

/* Two buttons sharing a single hairline between them. */
.rail-nav {
  display: flex;
  gap: 1px;
  background: var(--rule);
}

.rail-nav button {
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--shell);
  border: 1px solid var(--rule);
  cursor: pointer;
  padding: 12px 18px;
  transition: background var(--shift), color var(--shift);
}
.rail-nav button:hover { background: var(--ink); color: var(--raised); }

.rail {
  display: flex;
  gap: 24px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-bottom: 4px;
}
.rail::-webkit-scrollbar { display: none; }

@media (prefers-reduced-motion: reduce) {
  .rail { scroll-behavior: auto; }
}

.rail__item {
  flex: 0 0 calc((100% - 48px) / 3);
  min-width: 200px;
  scroll-snap-align: start;
  aspect-ratio: 9 / 16;
  background: var(--shell);
}

/* Two up, then a hair over one, as the viewport narrows. */
@media (max-width: 900px) {
  .rail__item { flex-basis: calc((100% - 24px) / 2); }
}
@media (max-width: 600px) {
  .rail__item { flex-basis: 78%; }
}

/* The caption sits over the foot of the clip on a soft scrim. */
.rail__label {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 18px 18px 16px;
  background: linear-gradient(to top, rgba(36, 33, 30, 0.6), rgba(36, 33, 30, 0));
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--raised);
}

/* -------------------------------------------------------- onward + closing */

/* The two-card "before you book" block that closes most pages. */
.onward {
  border-top: 1px solid var(--rule);
  padding-top: 96px;
  padding-bottom: 96px;
}

.onward__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 56px;
}

.onward__card {
  border-top: 1px solid var(--rule);
  padding-top: 24px;
}

.onward__card .prose { margin: 16px 0 24px; max-width: 44ch; }

/* The closing address-and-book band. */
.closing { border-top: 1px solid var(--rule); }

.closing__inner {
  padding-top: 96px;
  padding-bottom: 96px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 48px;
  flex-wrap: wrap;
}

.closing__title {
  max-width: 26ch;
  font-size: clamp(30px, 3.4vw, 46px);
  line-height: 1.06;
}

.closing__hours {
  margin-top: 24px;
  font-size: 15px;
  line-height: 1.7;
  color: var(--muted);
  max-width: 44ch;
}

@media (max-width: 719px) {
  .studio, .onward { padding-top: 64px; padding-bottom: 64px; }
  .closing__inner { padding-top: 64px; padding-bottom: 64px; }
  .details { margin-top: 48px; }
}
