/* ==========================================================================
   ANUPANA — site.css
   --------------------------------------------------------------------------
   Consumes assets/css/tokens.css. Contains no colour, length, duration or
   easing literal of its own, with exactly two declared exceptions, both
   forced by CSS itself and both marked EXCEPTION below:

     1. @font-face descriptors — file paths, formats and weight RANGES
        describe the binaries, not the design. There is nothing to tokenise.
     2. Media query conditions — custom properties are not valid inside a
        media query condition. `@media (min-width: var(--bp))` does not work
        in any browser. The two breakpoints are therefore literal, declared
        once, here, and used nowhere else.

   Authored entirely in logical properties. The strings "left" and "right"
   do not appear in this file.
   ========================================================================== */


/* ==========================================================================
   EXCEPTION 1 — FONT BINARIES
   Latin subset, self-hosted, zero cross-origin requests.
   IBM Plex Sans is a single variable file spanning 400–600.
   ========================================================================== */

@font-face {
  font-family: "Instrument Serif";
  src: url("../fonts/instrument-serif-normal.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Instrument Serif";
  src: url("../fonts/instrument-serif-italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/ibm-plex-sans-normal.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/ibm-plex-sans-italic.woff2") format("woff2");
  font-weight: 400 600;
  font-style: italic;
  font-display: swap;
}


/* ==========================================================================
   RESET AND BASE
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  color-scheme: light;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  background-color: var(--c-page);
  color: var(--c-ink);
  font-family: var(--ff-body);
  font-size: var(--fs-300);
  font-weight: var(--fw-regular);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4 {
  font-family: var(--ff-display);
  font-weight: var(--fw-display);
  margin: 0;
  text-wrap: balance;
}

p, ul, ol, dl, figure, blockquote { margin: 0; }

ul, ol { padding-inline-start: 0; list-style: none; }

a { color: inherit; }

::selection {
  background-color: var(--c-accent);
  color: var(--c-on-accent);
}

:focus-visible {
  outline: var(--focus-width) solid var(--c-focus);
  outline-offset: var(--focus-offset);
}

/* Dark grounds flip the ring rather than losing it. */
.band :focus-visible,
.site-footer :focus-visible {
  outline-color: var(--c-focus-inverse);
}


/* ==========================================================================
   TYPE ROLES
   ========================================================================== */

.t-display {
  font-family: var(--ff-display);
  font-size: var(--fs-1000);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
}

.t-title {
  font-family: var(--ff-display);
  font-size: var(--fs-800);
  line-height: var(--lh-title);
  letter-spacing: var(--ls-title);
}

.t-heading {
  font-family: var(--ff-display);
  font-size: var(--fs-600);
  line-height: var(--lh-heading);
  letter-spacing: var(--ls-heading);
}

.t-lede {
  font-size: var(--fs-400);
  line-height: var(--lh-snug);
  max-inline-size: var(--measure-lede);
}

.t-body {
  max-inline-size: var(--measure);
}

.t-label {
  font-size: var(--fs-100);
  line-height: var(--lh-loose);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-ink-secondary);
}

.t-meta {
  font-size: var(--fs-100);
  line-height: var(--lh-loose);
  color: var(--c-ink-muted);
}

.flow > * + * { margin-block-start: var(--space-flow); }
.flow-lg > * + * { margin-block-start: var(--space-flow-lg); }


/* ==========================================================================
   LAYOUT PRIMITIVES
   ========================================================================== */

.wrap {
  max-inline-size: var(--container);
  margin-inline: auto;
  padding-inline: var(--page-inline);
}

.grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
  gap: var(--gutter);
}

.section { padding-block: var(--space-section); }
.section--sm { padding-block: var(--space-section-sm); }
.section--lg { padding-block: var(--space-section-lg); }

.ground-sunk { background-color: var(--c-surface-sunk); }
.ground-tint { background-color: var(--c-surface-tint); }
.ground-deep {
  background-color: var(--c-surface-deep);
  color: var(--c-ink-inverse);
}

/* Muted text tokens are tuned for light grounds. On a deep ground
   --c-ink-muted would land at 3.35:1 and fail AA, so dark sections
   re-point the muted roles at the inverse token (8.65:1). */
.ground-deep .t-meta,
.ground-deep .t-label,
.site-footer .t-meta,
.site-footer .t-label {
  color: var(--c-ink-inverse-muted);
}


/* ==========================================================================
   CHROME — SKIP LINK, DEMO MARKER, HEADER
   ========================================================================== */

.skip-link {
  position: absolute;
  inset-block-start: var(--sp-2);
  inset-inline-start: var(--sp-2);
  z-index: var(--z-marker);
  padding: var(--sp-3) var(--sp-5);
  background-color: var(--c-accent);
  color: var(--c-on-accent);
  font-size: var(--fs-200);
  text-decoration: none;
  translate: 0 -200%;
}

.skip-link:focus { translate: 0 0; }

/* The demo marker. Sticky, so it is on screen at every scroll position,
   on every page, and cannot be dismissed. 14px floor, 7.83:1 contrast. */
.demo-marker {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-marker);
  background-color: var(--c-marker-bg);
  color: var(--c-marker-ink);
  font-size: var(--fs-100);
  line-height: var(--lh-loose);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  text-align: center;
  padding-block: var(--sp-2);
  padding-inline: var(--page-inline);
}

.site-header {
  padding-block: var(--sp-6);
  border-block-end: var(--hairline) solid var(--c-rule);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-5) var(--sp-7);
}

.wordmark {
  font-family: var(--ff-display);
  font-size: var(--fs-500);
  line-height: var(--lh-heading);
  letter-spacing: var(--ls-heading);
  text-decoration: none;
  margin-inline-end: auto;
}

.nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5) var(--sp-6);
  align-items: baseline;
}

.nav__link {
  font-size: var(--fs-200);
  text-decoration: none;
  padding-block: var(--sp-2);
  border-block-end: var(--underline-weight) solid transparent;
  transition: border-color var(--dur-micro) var(--ease-out-slow),
              color var(--dur-micro) var(--ease-out-slow);
}

.nav__link:hover,
.nav__link[aria-current] {
  border-block-end-color: var(--c-accent);
  color: var(--c-accent);
}


/* ==========================================================================
   ACTION — the single WhatsApp link
   ========================================================================== */

.action {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  min-block-size: var(--target-min);
  padding-block: var(--sp-3);
  padding-inline: var(--sp-6);
  background-color: var(--c-accent);
  color: var(--c-on-accent);
  font-size: var(--fs-200);
  font-weight: var(--fw-medium);
  text-decoration: none;
  border-radius: var(--radius-1);
  transition: background-color var(--dur-micro) var(--ease-out-slow);
}

.action:hover { background-color: var(--c-accent-strong); }

.action__icon {
  inline-size: var(--fs-400);
  block-size: var(--fs-400);
  flex: none;
  fill: currentColor;
}


/* ==========================================================================
   SECTION 1 — HERO   (split pair · lg · page)
   ========================================================================== */

.hero { padding-block-start: var(--space-section); }

.hero__text { grid-column: 1 / -1; }
.hero__figure { grid-column: 1 / -1; }

.hero__title { margin-block-end: var(--sp-7); }

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-5);
  margin-block-start: var(--sp-7);
}


/* ==========================================================================
   PLATE — imagery placeholder
   Tone block at a real aspect ratio, with the intended photograph
   described in the caption beneath it.
   ========================================================================== */

.plate {
  position: relative;
  overflow: hidden;
  aspect-ratio: var(--ar-portrait);
  background-color: var(--tone-linen);
}

.plate--landscape { aspect-ratio: var(--ar-landscape); }

/* Oversized by twice the maximum parallax displacement, so the layer can
   travel its full range without ever exposing an edge. Under reduced
   motion the displacement token is zero and this resolves to inset: 0. */
.plate__inner {
  position: absolute;
  inset: calc(var(--parallax-near) * -2);
}

.plate--room .plate__inner { background-image: var(--tone-grad-room); }
.plate--vessel .plate__inner { background-image: var(--tone-grad-vessel); }
.plate--cloth .plate__inner { background-image: var(--tone-grad-cloth); }

.plate__caption {
  margin-block-start: var(--sp-3);
  font-size: var(--fs-100);
  line-height: var(--lh-loose);
  color: var(--c-ink-muted);
  max-inline-size: var(--measure-narrow);
}


/* ==========================================================================
   SECTION 2 — STATEMENT   (offset label + text · default · sunk)
   ========================================================================== */

.statement__label { grid-column: 1 / -1; }
.statement__body { grid-column: 1 / -1; }


/* ==========================================================================
   SECTION 3 — THERAPY INDEX   (asymmetric index · default · page)
   ========================================================================== */

.therapies__intro { grid-column: 1 / -1; }
.therapies__list { grid-column: 1 / -1; }

.index { border-block-start: var(--hairline) solid var(--c-rule); }

.index__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-2) var(--gutter);
  padding-block: var(--sp-6);
  border-block-end: var(--hairline) solid var(--c-rule);
}

.index__num {
  font-size: var(--fs-100);
  letter-spacing: var(--ls-caps);
  color: var(--c-ink-secondary);
  font-variant-numeric: tabular-nums;
}

.index__name {
  font-family: var(--ff-display);
  font-size: var(--fs-600);
  line-height: var(--lh-heading);
  letter-spacing: var(--ls-heading);
  font-weight: var(--fw-display);
}

.index__desc {
  color: var(--c-ink-muted);
  max-inline-size: var(--measure);
}


/* ==========================================================================
   SECTION 4 — BAND   (full-bleed narrow · sm · deep)
   The one place symmetry is permitted, and it is permitted because it is
   the exception that makes the asymmetry elsewhere read as intentional.
   ========================================================================== */

.band__inner {
  max-inline-size: var(--measure-wide);
  margin-inline: auto;
  text-align: center;
}

.band__quote {
  font-family: var(--ff-display);
  font-style: italic;
  font-size: var(--fs-800);
  line-height: var(--lh-title);
  letter-spacing: var(--ls-title);
  text-wrap: balance;
}

.band__attrib {
  margin-block-start: var(--sp-6);
  font-size: var(--fs-100);
  line-height: var(--lh-loose);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--c-ink-inverse-muted);
}


/* ==========================================================================
   SECTION 5 — ROOMS   (split pair, reversed · lg · page)
   ========================================================================== */

.rooms__figure { grid-column: 1 / -1; }
.rooms__text { grid-column: 1 / -1; }


/* ==========================================================================
   SECTION 6 — VISIT   (three-part · default · tint)
   ========================================================================== */

.visit__col { grid-column: 1 / -1; }

.visit__address { font-style: normal; }

.visit__fiction {
  margin-block-start: var(--sp-3);
  font-size: var(--fs-100);
  line-height: var(--lh-loose);
  color: var(--c-ink-secondary);
}

.visit__hours { font-variant-numeric: tabular-nums; }

.visit__hours div + div { margin-block-start: var(--sp-2); }


/* ==========================================================================
   FOOTER
   ========================================================================== */

.site-footer {
  background-color: var(--c-surface-deep);
  color: var(--c-ink-inverse);
  padding-block: var(--space-section-sm);
}

.site-footer__grid { row-gap: var(--sp-8); }

.site-footer__col { grid-column: 1 / -1; }

.site-footer__wordmark {
  font-family: var(--ff-display);
  font-size: var(--fs-600);
  line-height: var(--lh-heading);
}

.footer-nav { display: grid; gap: var(--sp-3); }

.footer-nav a {
  font-size: var(--fs-200);
  text-decoration-line: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: var(--underline-weight);
  text-underline-offset: var(--underline-offset);
  transition: text-decoration-color var(--dur-micro) var(--ease-out-slow);
}

.footer-nav a:hover { text-decoration-color: currentColor; }

.site-footer__marker {
  font-size: var(--fs-200);
  color: var(--c-ink-inverse);
}

.site-footer__legal {
  margin-block-start: var(--sp-8);
  padding-block-start: var(--sp-6);
  border-block-start: var(--hairline) solid var(--c-rule-strong);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-7);
  font-size: var(--fs-100);
  line-height: var(--lh-loose);
  color: var(--c-ink-inverse-muted);
}

.site-footer__legal a {
  text-decoration-line: underline;
  text-decoration-thickness: var(--underline-weight);
  text-underline-offset: var(--underline-offset);
}


/* ==========================================================================
   MOTION
   Reveal targets are VISIBLE BY DEFAULT. The hidden state below is scoped
   to .js-motion, a class added by motion.js only when motion is permitted.
   No JS, no motion preference, or a crawler — all get the finished page.
   ========================================================================== */

.js-motion .reveal {
  opacity: 0;
  translate: 0 var(--reveal-shift);
  transition: opacity var(--dur-1) var(--ease-out-slow),
              translate var(--dur-1) var(--ease-out-slow);
  transition-delay: var(--reveal-delay);
}

.js-motion .reveal--slow {
  transition-duration: var(--dur-2);
}

.js-motion .reveal.is-in {
  opacity: 1;
  translate: 0 0;
}

/* Pointer parallax. Exactly two elements on this page and nowhere else.
   JS writes --px-x / --px-y; absent JS they resolve to zero. */
.parallax {
  translate: var(--px-x, 0) var(--px-y, 0);
  will-change: translate;
}


/* ==========================================================================
   EXCEPTION 2 — BREAKPOINTS
   Custom properties cannot be used in media query conditions. These are
   the only two literals below, and the only two breakpoints in the project.
     48rem = 768px   ·   64rem = 1024px
   ========================================================================== */

@media (min-width: 48rem) {

  .demo-marker { text-align: start; }

  .hero__text { grid-column: 1 / 8; }
  .hero__figure { grid-column: 9 / -1; }

  .statement__label { grid-column: 1 / 3; }
  .statement__body { grid-column: 4 / 11; }

  .therapies__intro { grid-column: 1 / 4; }
  .therapies__list { grid-column: 5 / -1; }

  .index__row {
    grid-template-columns: min-content minmax(0, 1fr) minmax(0, 1.4fr);
    align-items: baseline;
  }

  .rooms__figure { grid-column: 1 / 6; }
  .rooms__text { grid-column: 7 / -1; }

  .visit__col { grid-column: span 4; }

  .site-footer__col { grid-column: span 4; }
}

@media (min-width: 64rem) {

  .hero { padding-block-start: var(--space-section-lg); }

  /* The deliberate break: the hero figure drops below the text baseline
     so the two halves do not align, and the grid is visibly disobeyed. */
  .hero__figure { margin-block-start: var(--sp-10); }

  .rooms__text { padding-block-start: var(--sp-9); }

  .visit__col { grid-column: span 3; }
  .visit__col--action { grid-column: 10 / -1; }

  .site-footer__col--brand { grid-column: 1 / 5; }
  .site-footer__col--nav { grid-column: 6 / 9; }
  .site-footer__col--note { grid-column: 10 / -1; }
}
