/* La Moda — quiet-luxury editorial. Her mood, not her brand: warm paper, espresso
   ink, one rose-clay accent, no logo and no photography (SPEC §3). */

:root {
  --paper: #f6f1ea;
  --paper-deep: #ece2d6;
  --paper-card: #fffdfa;
  --ink: #241e1b;
  --ink-soft: #6e625a;
  --ink-faint: #a3958a;
  --clay: #ac6c5c;
  --clay-deep: #8d5548;
  --clay-wash: #f0ded6;
  --sage: #4f6157;
  --line: rgba(36, 30, 27, 0.12);
  --line-soft: rgba(36, 30, 27, 0.06);

  --display: "Cormorant Garamond", "Iowan Old Style", Georgia, serif;
  --body: "Golos Text", "Helvetica Neue", Helvetica, sans-serif;

  --shell: min(1220px, 92vw);
  --radius: 18px;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: 5rem;
  -webkit-text-size-adjust: 100%;
  /* The hero bloom bleeds past the right edge by design. `clip` stops that overflow
     from widening the document, which on a real phone rendered the whole page ~9%
     wider than the screen and clipped the right edge (found at P8.2 QA). `hidden` on
     body is not enough: the document still reports the wider scrollWidth. */
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.62;
  font-feature-settings: "kern" 1;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Paper grain — the whole page sits under it. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  opacity: 0.5;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.16'/%3E%3C/svg%3E");
}

a {
  color: inherit;
}
img {
  max-width: 100%;
}

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

/* ── Top bar ───────────────────────────────────────────────────────────────── */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  width: var(--shell);
  margin-inline: auto;
  padding: 1.1rem 0 0.9rem;
  background: linear-gradient(var(--paper) 72%, rgba(246, 241, 234, 0));
}

.wordmark {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  text-decoration: none;
}
.wordmark__name {
  font-family: var(--display);
  font-size: 1.6rem;
  letter-spacing: 0.03em;
  line-height: 1;
  white-space: nowrap;
}
.wordmark__sub {
  font-size: 0.6rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.topnav {
  display: flex;
  align-items: center;
  gap: 1.6rem;
  font-size: 0.82rem;
  letter-spacing: 0.04em;
}
.topnav a {
  text-decoration: none;
  color: var(--ink-soft);
  transition: color 0.25s var(--ease);
}
.topnav a:hover {
  color: var(--clay);
}
.topnav__lang {
  padding-left: 1.6rem;
  border-left: 1px solid var(--line);
  font-variant: small-caps;
  letter-spacing: 0.1em;
}
.topnav__wa {
  padding: 0.42rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--ink) !important;
  transition: border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.topnav__wa:hover {
  border-color: var(--clay);
  background: var(--clay-wash);
}

@media (max-width: 720px) {
  .topnav a:not(.topnav__wa):not(.topnav__lang) {
    display: none;
  }
  .topnav {
    gap: 1rem;
  }
  .topnav__lang {
    padding-left: 0;
    border-left: 0;
  }
}

@media (max-width: 440px) {
  /* The strapline is the first thing to go — the name must never wrap. */
  .wordmark__sub {
    display: none;
  }
  .topbar {
    padding-top: 0.8rem;
  }
}

/* ── Hero ──────────────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  width: var(--shell);
  margin: clamp(1.5rem, 4vw, 3.5rem) auto clamp(4rem, 9vw, 7rem);
  display: grid;
  grid-template-columns: minmax(0, 0.86fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  /* `start`, not `center`: a centred text column re-flows every time the chat card
     changes height, so the headline would drift while the visitor is typing. */
  align-items: start;
}

.hero__bloom {
  position: absolute;
  z-index: -1;
  right: -14%;
  top: -28%;
  width: 68%;
  aspect-ratio: 1;
  background:
    radial-gradient(circle at 38% 42%, rgba(172, 108, 92, 0.19), transparent 62%),
    radial-gradient(circle at 68% 66%, rgba(79, 97, 87, 0.14), transparent 58%);
  filter: blur(28px);
  border-radius: 50%;
}

.eyebrow {
  margin: 0 0 1.4rem;
  font-size: 0.7rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.hero__title {
  margin: 0 0 1.5rem;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(3rem, 6.4vw, 5.4rem);
  line-height: 0.98;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.hero__title em {
  display: block;
  font-style: italic;
  color: var(--clay);
}

.hero__lede {
  margin: 0 0 1.1rem;
  max-width: 34ch;
  font-size: 1.05rem;
  color: var(--ink-soft);
}

.hero__note {
  margin: 0 0 2rem;
  max-width: 34ch;
  padding-left: 1rem;
  border-left: 2px solid var(--clay-wash);
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--ink-faint);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.78rem 1.5rem;
  border-radius: 999px;
  font-size: 0.86rem;
  letter-spacing: 0.05em;
  text-decoration: none;
  border: 1px solid transparent;
  transition: transform 0.25s var(--ease), background 0.25s var(--ease),
    border-color 0.25s var(--ease);
}
.btn:hover {
  transform: translateY(-1px);
}
.btn--wa {
  background: var(--sage);
  color: var(--paper);
}
.btn--wa:hover {
  background: #3f5147;
}
.btn--ghost {
  border-color: var(--line);
  color: var(--ink);
}
.btn--ghost:hover {
  border-color: var(--clay);
  background: var(--clay-wash);
}

/* ── Chat ──────────────────────────────────────────────────────────────────── */

.chat {
  display: flex;
  flex-direction: column;
  min-height: 27rem;
  background: var(--paper-card);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  box-shadow:
    0 1px 2px rgba(36, 30, 27, 0.04),
    0 18px 44px -22px rgba(36, 30, 27, 0.34);
  overflow: hidden;
}

.chat__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.95rem 1.2rem;
  border-bottom: 1px solid var(--line-soft);
}
.chat__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--sage);
  box-shadow: 0 0 0 3px rgba(79, 97, 87, 0.14);
}
.chat__title {
  font-family: var(--display);
  font-size: 1.15rem;
  letter-spacing: 0.01em;
}
.chat__badge {
  margin-left: auto;
  padding: 0.22rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}

.chat__log {
  flex: 1;
  min-height: 0;
  max-height: 22rem;
  overflow-y: auto;
  padding: 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  scrollbar-width: thin;
}

.chat__disclosure {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--ink-faint);
  text-wrap: pretty;
}

.msg {
  max-width: 84%;
  padding: 0.72rem 0.95rem;
  border-radius: 14px;
  font-size: 0.92rem;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  animation: rise 0.4s var(--ease) both;
}
.msg--bot {
  align-self: flex-start;
  background: var(--paper-deep);
  border-bottom-left-radius: 5px;
}
.msg--user {
  align-self: flex-end;
  background: var(--clay);
  color: #fff9f6;
  border-bottom-right-radius: 5px;
}
/* /lab only since P11.2: one input serves three columns there, so a single status line
   above it cannot represent three different waits and the rotation stays in the column's
   own bubble. The production pages use .chat__waiting instead. */
.msg--pending {
  color: var(--ink-faint);
  font-family: var(--display);
  font-style: italic;
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

/* `display: flex` beats the [hidden] attribute's display:none — without this the
   starter chips stay on screen for the whole conversation. */
.chat__chips[hidden] {
  display: none;
}

.chat__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  padding: 0 1.2rem 0.9rem;
}
.chip {
  padding: 0.42rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-soft);
  font-family: inherit;
  font-size: 0.78rem;
  cursor: pointer;
  transition: border-color 0.22s var(--ease), background 0.22s var(--ease),
    color 0.22s var(--ease);
}
.chip:hover {
  border-color: var(--clay);
  background: var(--clay-wash);
  color: var(--clay-deep);
}

/* Turnstile renders here only when it actually needs a human — appearance is
   "interaction-only", so the usual case is an empty, zero-height box. */
.chat__turnstile:not(:empty) {
  padding: 0 1.2rem 0.9rem;
}

/* The wait (P11.2). It used to be a grey bubble inside the log; it is now a status
   line of its own between the chips and the input. Left-aligned on the input's own
   1.2rem inset, so the line, the placeholder and Ama's bubbles share one left edge —
   her messages sit left and the visitor's sit right, and a line in her voice belongs
   on her side. `nowrap` is a guarantee, not a style: every approved line is 20
   characters or fewer, and a wrapped one would change the row's height mid-wait. */
.chat__waiting {
  margin: 0;
  padding: 0 1.2rem 0.3rem;
  font-family: var(--display);
  font-style: italic;
  /* An optical call, not a number. The target is one notch smaller than a message
     (0.92rem Golos). Cormorant has a small x-height, so 0.95rem measured the same but
     read two notches down and went papery next to the placeholder; 1.02rem sits one
     notch below the bubbles and stays comfortably readable at phone metrics, with
     --ink-faint and the italic doing the quietening instead of the size. */
  font-size: 1.02rem;
  line-height: 1.4;
  color: var(--ink-faint);
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  /* A fixed box, not a min-height: an empty row and a filled one must be the same
     height or the input steps down 5px the moment a line appears. `nowrap` above is
     the other half of that guarantee (border-box, so the padding is inside). */
  height: calc(1.4em + 0.3rem);
}
/* No height before the first send. `/` in Russian on a 360px phone has 25px of fold
   clearance and this row costs 21 of them, so the invite state cannot afford it — and
   an empty row reserved under a folded card buys nothing. From the first send onward
   the row is permanent and never collapses, so the input never twitches mid-conversation;
   the 21px arrives during the unfold, which is a far larger intentional transition.
   /salon has no invite state, so it reserves the row from the start. */
.chat--invite .chat__waiting {
  display: none;
}

.chat__form {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 0.8rem 0.8rem 1.2rem;
  border-top: 1px solid var(--line-soft);
}
.chat__form input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: 0.92rem;
  color: var(--ink);
  padding: 0.45rem 0;
}
.chat__form input:focus {
  outline: none;
}
.chat__form input::placeholder {
  color: var(--ink-faint);
}
.chat__send {
  display: grid;
  place-items: center;
  width: 2.3rem;
  height: 2.3rem;
  flex: none;
  border: 0;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  cursor: pointer;
  transition: background 0.25s var(--ease), transform 0.25s var(--ease);
}
.chat__send:hover {
  background: var(--clay);
  transform: translateX(1px);
}
.chat__send:disabled {
  opacity: 0.4;
  cursor: default;
  transform: none;
}

/* The graceful down state (SPEC §2). Hidden until the chat actually fails. */
.chat__down {
  display: none;
  padding: 1.4rem 1.2rem 1.5rem;
  border-top: 1px solid var(--line-soft);
  background: linear-gradient(var(--paper-card), var(--paper-deep));
}
.chat--down .chat__down {
  display: block;
}
.chat--down .chat__live {
  display: none;
}
/* Nothing more is coming, so stop reserving room for it. */
.chat--down .chat__log {
  flex: 0 1 auto;
}
.chat--down {
  min-height: 0;
}
.chat__down-title {
  margin: 0 0 0.4rem;
  font-family: var(--display);
  font-size: 1.25rem;
}
.chat__down-body {
  margin: 0 0 1.1rem;
  font-size: 0.88rem;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.chat__down--noscript {
  display: block;
}
noscript .chat__down {
  border-top: 1px solid var(--line-soft);
}

/* The booking slate card (SPEC §6) — the confirm step. */
.slate {
  align-self: stretch;
  max-width: 100%;
  margin-top: 0.2rem;
  padding: 1rem 1.1rem 1.1rem;
  border: 1px solid var(--clay-wash);
  border-radius: 14px;
  background: linear-gradient(var(--paper-card), var(--clay-wash));
  animation: rise 0.45s var(--ease) both;
}
.slate__title {
  margin: 0 0 0.6rem;
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--clay-deep);
}
.slate__lines {
  margin: 0 0 0.9rem;
  padding: 0;
  list-style: none;
  font-size: 0.92rem;
  line-height: 1.7;
}
.slate__lines li + li {
  border-top: 1px dotted var(--line);
}
.slate__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}
.slate__edit {
  border: 0;
  background: none;
  padding: 0.4rem 0.2rem;
  font-family: inherit;
  font-size: 0.8rem;
  color: var(--ink-faint);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* Post-tap closing state (SPEC §6) — no dead end. */
.closing {
  padding: 1.1rem;
  border-radius: 14px;
  background: var(--paper-deep);
  animation: rise 0.45s var(--ease) both;
}
.closing__title {
  margin: 0 0 0.3rem;
  font-family: var(--display);
  font-size: 1.2rem;
}
.closing__body {
  margin: 0 0 0.8rem;
  font-size: 0.86rem;
  color: var(--ink-soft);
}
.closing__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.1rem;
  font-size: 0.82rem;
}
.closing__links a {
  color: var(--clay-deep);
  text-underline-offset: 3px;
}

@media (max-width: 900px) {
  .hero {
    grid-template-columns: 1fr;
    gap: 2.4rem;
  }
  .hero__lede,
  .hero__note {
    max-width: none;
  }
  .chat {
    min-height: 24rem;
  }
}

@media (max-width: 560px) {
  /* This is the demo: a QR code scanned on a phone in the salon. If the chat card is
     entirely below the fold, the page reads as a brochure rather than as a receptionist.
     Tighten the hero until the top of the card peeks above it. */
  .hero {
    margin-top: 0.5rem;
    gap: 1.6rem;
  }
  .hero__title {
    font-size: clamp(2.5rem, 11vw, 3.2rem);
    margin-bottom: 1rem;
  }
  .eyebrow {
    margin-bottom: 1rem;
  }
  .hero__lede {
    font-size: 0.98rem;
    margin-bottom: 0.9rem;
  }
  .hero__note {
    margin-bottom: 1.4rem;
    font-size: 0.84rem;
  }
  .hero__actions .btn {
    padding: 0.7rem 1.25rem;
  }

  /* The head wraps at this width; keep the badge on its own line rather than letting it
     shoulder the title out of alignment. */
  .chat__head {
    flex-wrap: wrap;
    row-gap: 0.35rem;
  }
  .chat__title {
    font-size: 1.05rem;
  }
  /* A flex item with a 100% basis stretches, so the pill would run the full width of
     the card. Drop the pill chrome here and let it read as a caption line instead. */
  .chat__badge {
    margin-left: 0;
    order: 3;
    flex-basis: 100%;
    padding: 0;
    border: 0;
  }
  .chat__log {
    padding: 1rem;
    max-height: 18rem;
  }
}

/* ── Price list ────────────────────────────────────────────────────────────── */

.section-title {
  margin: 0 0 0.5rem;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(2rem, 3.6vw, 2.9rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
}
.section-lede {
  margin: 0;
  max-width: 44ch;
  color: var(--ink-soft);
  font-size: 0.98rem;
}

.prices {
  width: var(--shell);
  margin: 0 auto clamp(4rem, 8vw, 6.5rem);
  padding-top: clamp(2rem, 5vw, 3.5rem);
  border-top: 1px solid var(--line);
}

.prices__intro {
  max-width: 46rem;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

.prices__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 1.5rem;
}
.prices__nav a {
  padding: 0.36rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.76rem;
  letter-spacing: 0.04em;
  text-decoration: none;
  color: var(--ink-soft);
  transition: border-color 0.22s var(--ease), color 0.22s var(--ease);
}
.prices__nav a:hover {
  border-color: var(--clay);
  color: var(--clay-deep);
}

.prices__grid {
  columns: 2;
  column-gap: clamp(2rem, 5vw, 4.5rem);
}
@media (max-width: 860px) {
  .prices__grid {
    columns: 1;
  }
}

.cat {
  break-inside: avoid;
  margin-bottom: 2.8rem;
}
.cat__title {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin: 0 0 0.9rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--line);
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.5rem;
  scroll-margin-top: 5.5rem;
}
.cat__count {
  font-family: var(--body);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  color: var(--ink-faint);
}

.cat__list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.svc {
  padding: 0.62rem 0;
  border-bottom: 1px solid var(--line-soft);
}
.svc__head {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
}
.svc__name {
  font-size: 0.93rem;
}
.svc__dots {
  flex: 1;
  min-width: 1.5rem;
  height: 0;
  border-bottom: 1px dotted var(--ink-faint);
  opacity: 0.55;
  transform: translateY(-0.28em);
}
.svc__price {
  flex: none;
  font-size: 0.88rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  color: var(--clay-deep);
  white-space: nowrap;
}
.svc__tag {
  display: inline-block;
  margin-left: 0.35rem;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: var(--clay-wash);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  color: var(--clay-deep);
  vertical-align: 0.12em;
}
.svc__meta {
  display: flex;
  gap: 0.9rem;
  font-size: 0.72rem;
  color: var(--ink-faint);
}

.tiers {
  margin: 0.5rem 0 0.15rem;
  padding: 0.5rem 0.75rem;
  list-style: none;
  border-left: 2px solid var(--clay-wash);
  background: rgba(236, 226, 214, 0.4);
  border-radius: 0 8px 8px 0;
}
.tiers li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.78rem;
  color: var(--ink-soft);
}
.tiers__price {
  font-variant-numeric: tabular-nums;
  color: var(--clay-deep);
}

.prices__stamp {
  margin: 0;
  padding-top: 1.4rem;
  border-top: 1px solid var(--line);
  font-size: 0.74rem;
  color: var(--ink-faint);
}

/* ── Visit ─────────────────────────────────────────────────────────────────── */

.visit {
  width: var(--shell);
  margin: 0 auto clamp(4rem, 8vw, 6rem);
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  padding-top: clamp(2rem, 5vw, 3.5rem);
  border-top: 1px solid var(--line);
}
@media (max-width: 780px) {
  .visit {
    grid-template-columns: 1fr;
    gap: 2.5rem;
  }
}

.visit__facts {
  margin: 1.4rem 0 1.2rem;
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.45rem 1.6rem;
  font-size: 0.9rem;
}
.visit__facts dt {
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-top: 0.2rem;
}
.visit__facts dd {
  margin: 0;
}

.link-arrow {
  font-size: 0.84rem;
  color: var(--clay-deep);
  text-underline-offset: 4px;
}
.link-arrow::after {
  content: " →";
}

.team {
  margin: 1.4rem 0 0;
  padding: 0;
  list-style: none;
}
.team li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--line-soft);
}
.team__name {
  font-family: var(--display);
  font-size: 1.2rem;
}
.team__role {
  font-size: 0.76rem;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
  text-align: right;
}

/* ── Footer ────────────────────────────────────────────────────────────────── */

.footer {
  width: var(--shell);
  margin: 0 auto;
  padding: 2rem 0 3rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 2rem;
  justify-content: space-between;
  font-size: 0.76rem;
  color: var(--ink-faint);
}
.footer p {
  margin: 0;
}
.footer__privacy {
  max-width: 46ch;
}

/* ── Entrance ──────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: no-preference) {
  .hero__text > *,
  .hero__chat {
    animation: rise 0.75s var(--ease) both;
  }
  .hero__text > :nth-child(1) { animation-delay: 0.05s; }
  .hero__text > :nth-child(2) { animation-delay: 0.12s; }
  .hero__text > :nth-child(3) { animation-delay: 0.2s; }
  .hero__text > :nth-child(4) { animation-delay: 0.27s; }
  .hero__text > :nth-child(5) { animation-delay: 0.34s; }
  .hero__chat { animation-delay: 0.18s; }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
  html {
    scroll-behavior: auto;
  }
}

:focus-visible {
  outline: 2px solid var(--clay);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ── Pitch page (BUILD-PLAN P8.2) — the owner-facing argument, in her mood ────── */

.chat__online {
  font-size: 0.64rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sage);
}

.chat__caption {
  margin: 0;
  padding: 0.85rem 1.2rem;
  border-bottom: 1px solid var(--line-soft);
  font-size: 0.8rem;
  line-height: 1.55;
  color: var(--ink-faint);
  text-wrap: pretty;
}

/* Ama's concierge card: the chat arrives folded to an invitation and becomes the full
   receptionist on the first send (chat.js removes the class). The height animates once
   per visit, so transitioning max-height is an acceptable trade for zero extra markup. */
.chat--invite {
  min-height: 0;
}
.chat__log {
  transition: max-height 0.3s var(--ease), opacity 0.3s var(--ease),
    padding 0.3s var(--ease);
}
.chat--invite .chat__log {
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  opacity: 0;
  overflow: hidden;
}
/* Once open, the log is a fixed-height window that scrolls inside itself. If it grew
   with every message the whole page below the card would shift on each reply. */
.chat:not(.chat--invite):not(.chat--down) .chat__log {
  height: 22rem;
}
@media (max-width: 560px) {
  .chat:not(.chat--invite):not(.chat--down) .chat__log {
    height: 18rem;
  }
}
.chat--invite .chat__title {
  font-size: 1.45rem;
  font-style: italic;
  letter-spacing: 0.02em;
}
@media (prefers-reduced-motion: no-preference) {
  .chat--invite .chat__dot {
    animation: breathe 2.8s var(--ease) infinite;
  }
}
@keyframes breathe {
  50% {
    box-shadow: 0 0 0 6px rgba(79, 97, 87, 0.07);
  }
}

/* The five reasons — an editorial numbered list, not feature cards. */
.reasons {
  width: var(--shell);
  margin: 0 auto clamp(4rem, 8vw, 6rem);
  padding-top: clamp(2rem, 5vw, 3.5rem);
  border-top: 1px solid var(--line);
}
.reasons__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.8rem, 4vw, 3rem) clamp(2rem, 5vw, 4.5rem);
  margin: clamp(1.8rem, 4vw, 2.6rem) 0 0;
  padding: 0;
  list-style: none;
}
.reason {
  position: relative;
  padding-left: 2.6rem;
}
.reason__num {
  position: absolute;
  left: 0;
  top: 0.15rem;
  font-family: var(--display);
  font-style: italic;
  font-size: 1.15rem;
  color: var(--clay);
}
.reason__title {
  margin: 0 0 0.35rem;
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.45rem;
  line-height: 1.15;
}
.reason__body {
  margin: 0;
  max-width: 44ch;
  font-size: 0.92rem;
  color: var(--ink-soft);
}
@media (max-width: 780px) {
  .reasons__grid {
    grid-template-columns: 1fr;
  }
}

/* Everything after the hero hides behind the "where she earns her keep" button —
   pure CSS via :target, so it works with zero JS and inherits smooth scrolling. */
.pitch-more {
  display: none;
}
.pitch-more:target {
  display: block;
  animation: rise 0.6s var(--ease) both;
}

/* The reveal button: the hero's one loud element. Once the content is open (:target),
   it flips to a quiet "done" state so the click visibly changed something. */
.btn--reveal {
  background: var(--clay);
  border-color: transparent;
  color: #fff9f6;
}
.btn--reveal::after {
  content: " ↓";
}
.btn--reveal:hover {
  background: var(--clay-deep);
}
.btn:active {
  transform: scale(0.97);
}
body:has(.pitch-more:target) .btn--reveal {
  background: var(--clay-wash);
  border: 1px solid var(--clay);
  color: var(--clay-deep);
}
body:has(.pitch-more:target) .btn--reveal::after {
  content: " ✓";
}

/* The trust block: her hard rules as owner-facing promises. */
.trust {
  width: var(--shell);
  margin: 0 auto clamp(4rem, 8vw, 6rem);
  padding-top: clamp(2rem, 5vw, 3.5rem);
  border-top: 1px solid var(--line);
}
.trust__list {
  margin: clamp(1.6rem, 3.5vw, 2.2rem) 0 0;
  padding: 0;
  list-style: none;
  max-width: 58ch;
}
.trust__list li {
  position: relative;
  padding: 0.7rem 0 0.7rem 2rem;
  border-bottom: 1px solid var(--line-soft);
  font-size: 0.94rem;
  color: var(--ink-soft);
}
.trust__list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0.7rem;
  font-family: var(--display);
  font-size: 1.05rem;
  color: var(--clay);
}

/* ── The Ama monogram (/v2 variant) ─────────────────────────────────────────
   One asset does all of this: public/ama-mark.png is an ALPHA MASK derived from
   assets/public/Ama.svg by tools/make-ama-mark.py — the baked drop shadow stripped and
   the gowned figure turned into a real knockout. Because it is a mask and not a
   picture, `background-color` tints it, so the same 20 KB file is clay at 420px behind
   the headline and ink at 22px in the card head. The glyph is wider than it is tall;
   every box sizes by width and lets `aspect-ratio` find the height.

   Two optical sizes, not one scaled file: the knocked-out figure that carries the mark
   at 420px turns into a ragged notch at 22px, so the signet drops it and keeps only the
   letterform. Same discipline as a type family changing shape across sizes.

   Nothing here applies to `/` — every rule is scoped to an element or a class that
   only the variant renders. */

:root {
  --ama-mark: url("/ama-mark.png") no-repeat center / contain;
  --ama-ratio: 542 / 419;
  --ama-signet: url("/ama-signet.png") no-repeat center / contain;
  --ama-signet-ratio: 220 / 171;
}

/* The hero watermark: the letterform at a size where its detail actually survives,
   cropped by the left edge. It is texture, not a logo — if it reads as a logo, it is
   too strong, and `opacity` is the one number to turn. */
.hero__watermark {
  position: absolute;
  z-index: -1;
  /* As tall as the hero's left section (the operator, 2026-09-10): anchored to the
     hero's top and bottom with breathing room, the width follows the glyph's own
     ratio. The hero's height IS the left column's height (the card column is
     shorter), so the glyph spans exactly the argument it sits behind.
     `overflow-x: clip` on html makes any horizontal bleed safe. */
  top: 0.75rem;
  bottom: 0.75rem;
  left: -5%;
  width: auto;
  aspect-ratio: var(--ama-ratio);
  background-color: var(--clay);
  -webkit-mask: var(--ama-mark);
  mask: var(--ama-mark);
  opacity: 0.07;
  pointer-events: none;
}

/* Below 900px the hero is one column and the watermark would sit under body copy,
   fighting the paper grain, so it is dropped. The mark is not re-introduced anywhere
   else on the page: it now lives large inside the card, and one mark per screen is the
   point. */
@media (max-width: 900px) {
  .hero__watermark {
    display: none;
  }
}

/* The reveal on the variant is a TEXT line at every width (the operator,
   2026-09-10, extending the phone decision to desktop): the screen's one loud
   element is Ama's card, and talking to her is the primary action — so the reveal
   borrows the title's accent voice (display italic, clay, hairline underline)
   instead of competing as chrome. Desktop sits flush with the text's left edge;
   the phone block re-centres it. Text visually, button physically: the padding
   keeps a finger-sized target, and .btn:active's press response survives. */
.hero--mark .hero__actions .btn--reveal {
  width: auto;
  background: transparent;
  border: 0;
  padding: 0.45rem 0.6rem 0.45rem 0;
  color: var(--clay-deep);
  font-family: var(--display);
  font-style: italic;
  font-size: 1.15rem;
  letter-spacing: 0.01em;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: rgba(172, 108, 92, 0.45);
  text-underline-offset: 6px;
}
.hero--mark .hero__actions .btn--reveal:hover {
  background: transparent;
  color: var(--clay);
}
/* The done state stays text too — it quiets instead of filling; the ✓ from the
   base rule still lands, and the colour change survives reduced motion. */
body:has(.pitch-more:target) .hero--mark .hero__actions .btn--reveal {
  background: transparent;
  border: 0;
  color: var(--ink-faint);
  text-decoration-color: var(--line);
}

@media (max-width: 900px) {
  /* One-column order per the operator (2026-09-10): centred title, centred lede, then
     the reveal as a quiet TEXT line, not a button — the screen's one loud element is
     Ama's card, and talking to her is the primary action. The link borrows the
     title's own accent voice (display italic, clay), so it reads as the last line of
     the argument rather than as competing chrome. Reordering in CSS keeps one DOM
     for both pages, so `/` and /v2 can never drift apart in content. */
  .hero--mark .hero__text {
    display: flex;
    flex-direction: column;
  }
  .hero--mark .hero__title {
    order: 1;
    text-align: center;
  }
  .hero--mark .hero__lede {
    order: 2;
    margin-bottom: 0.9rem;
    text-align: center;
  }
  .hero--mark .hero__actions {
    order: 3;
    margin-bottom: 0;
    justify-content: center;
  }
  /* The text treatment itself is the base rule now; the phone only re-centres it. */
  .hero--mark .hero__actions .btn--reveal {
    padding: 0.45rem 0.6rem;
  }
}

/* ── The variant's card format, both widths (the operator, 2026-09-10) ─────────
   Service shortcuts: the two SPEC §3 chips cover the crowd favourites, the
   .chip--svc names surface services a guest would not think to ask for. They are
   exact catalog names resolved at render time (pitch.ts), and a tap sends the name
   as the message. Desktop keeps the caption too — space exists there; the phone
   trades it away, where the AI RECEPTIONIST badge alone still carries the P1.7
   disclosure. */
.chip--svc {
  display: none;
}
.chat--mark .chip--svc {
  display: inline-flex;
  background: var(--clay-wash);
  border-color: transparent;
  color: var(--clay-deep);
}
.chat--mark .chat__chips {
  padding-top: 0.95rem;
}

/* The input stops hiding in the furniture: a framed pill, a readable placeholder,
   and the send button in clay so the two read as one gesture. */
.chat--mark .chat__form {
  padding: 0.8rem 0.9rem 0.95rem;
}
.chat--mark .chat__form input {
  border: 1px solid var(--clay);
  border-radius: 999px;
  background: var(--paper);
  padding: 0.62rem 1.05rem;
  font-size: 0.95rem;
}
.chat--mark .chat__form input::placeholder {
  color: var(--ink-soft);
}
.chat--mark .chat__form input:focus {
  border-color: var(--clay-deep);
  box-shadow: 0 0 0 4px rgba(172, 108, 92, 0.12);
}
.chat--mark .chat__send {
  background: var(--clay);
}
.chat--mark .chat__send:hover {
  background: var(--clay-deep);
}
@media (max-width: 900px) {
  .chat--mark .chat__caption {
    display: none;
  }
}
/* The halo beckons only while the card is still an invitation — once the visitor has
   sent something, a pulsing input would be a state claim, not a welcome. */
@media (prefers-reduced-motion: no-preference) {
  .chat--mark.chat--invite .chat__form input {
    animation: ama-beckon 3.4s var(--ease) infinite;
  }
}
@keyframes ama-beckon {
  50% {
    border-color: var(--clay-deep);
    box-shadow: 0 0 0 6px rgba(172, 108, 92, 0.09);
  }
}

/* RU runs longer than EN in the headline, the lede and the chip names, and at the EN
   sizes the input row lands below a phone's fold (measured at 390px: input bottom
   772 vs EN's 692). One notch smaller for RU only, until the full card clears the
   same fold as EN. */
@media (max-width: 900px) {
  [lang="ru"] .hero--mark .hero__title {
    font-size: clamp(2rem, 9vw, 2.7rem);
  }
  [lang="ru"] .hero--mark .hero__lede {
    font-size: 0.92rem;
  }
  [lang="ru"] .chat--mark .chip {
    font-size: 0.74rem;
    padding: 0.4rem 0.68rem;
  }
}

/* ── The card head on the variant ──────────────────────────────────────────────
   Left: the mark at a size where the figure inside the counter actually reads, in
   clay — the knockout lets the card's paper through her, which is the whole reason
   the shape was worth keeping. Right: the badge stacked over the live status. */
.chat--mark .chat__head {
  gap: 0.75rem;
  padding: 1.05rem 1.2rem;
}
.chat--mark .chat__ident {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.chat--mark .chat__signet {
  position: relative;
  display: block;
  flex: none;
  width: 46px;
  aspect-ratio: var(--ama-ratio);
  background-color: var(--clay);
  -webkit-mask: var(--ama-mark);
  mask: var(--ama-mark);
  transition: background-color 0.2s var(--ease), transform 0.2s var(--ease);
}

/* ── Ink & sheen ───────────────────────────────────────────────────────────────
   A light passes over the glyph and nothing moves. That is the point: the head
   already carries a 2.8s pulse on the status dot 100px away, and a second thing
   changing POSITION next to it would read as two clocks ticking out of step.

   Both bands are clipped by the signet's own mask, so the light only ever falls on
   the letterform — never on the knockout, never on the card. Composited transform
   only. The watermark deliberately gets none of this: at 7% opacity a glint there
   would be invisible work. */
.chat--mark .chat__signet::before,
.chat--mark .chat__signet::after {
  content: "";
  position: absolute;
  top: -30%;
  bottom: -30%;
  left: 0;
  /* Narrow and soft. A wide, bright band washes half the glyph and reads as a loading
     shimmer; a tight one reads as light catching an edge. */
  width: 36%;
  transform: translateX(-120%);
  background: linear-gradient(
    105deg,
    rgba(255, 253, 250, 0) 18%,
    rgba(255, 253, 250, 0.44) 50%,
    rgba(255, 253, 250, 0) 82%
  );
  pointer-events: none;
}

/* The idle pass: ~1.1s of travel, then 7.9s of complete stillness. The dwell is the
   whole trick — a sheen that cycles continuously is the vocabulary of a loading
   skeleton, and the pause is what makes this read as a material instead. */
@keyframes ama-sheen {
  0% {
    transform: translateX(-120%);
  }
  12% {
    transform: translateX(300%);
  }
  100% {
    transform: translateX(300%);
  }
}
/* The hover pass lives on its own pseudo-element so it can replay on every hover:
   the rule is applied fresh each time the pointer arrives, which restarts it. Sharing
   one element with the idle loop would mean fighting it for `animation`. */
@keyframes ama-sheen-once {
  from {
    transform: translateX(-120%);
  }
  to {
    transform: translateX(300%);
  }
}

.chat--mark .chat__signet::after {
  animation: ama-sheen 9s cubic-bezier(0.55, 0, 0.35, 1) infinite;
}

@media (hover: hover) and (pointer: fine) {
  .chat--mark .chat__ident:hover .chat__signet {
    background-color: var(--clay-deep);
    transform: scale(1.04);
  }
  .chat--mark .chat__ident:hover .chat__signet::before {
    animation: ama-sheen-once 0.55s cubic-bezier(0.55, 0, 0.35, 1) both;
  }
  .chat--mark .chat__ident:active .chat__signet {
    transform: scale(0.98);
  }
}

/* Reduced motion keeps the colour change — it aids comprehension and does not move —
   and drops every travelling highlight and the lift. */
@media (prefers-reduced-motion: reduce) {
  .chat--mark .chat__signet::before,
  .chat--mark .chat__signet::after {
    animation: none;
    opacity: 0;
  }
  .chat--mark .chat__ident:hover .chat__signet,
  .chat--mark .chat__ident:active .chat__signet {
    transform: none;
  }
}
.chat--mark .chat__status {
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.45rem;
}
.chat--mark .chat__badge {
  margin-left: 0;
}
/* The dot travels with the words it qualifies. `breathe` still owns box-shadow on the
   invite state, so the pulse is untouched by anything here. */
.chat--mark .chat__online {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

@media (max-width: 560px) {
  /* `/` drops the badge to its own full-width line at this width. The variant already
     has a column for it, so every part of that rule is undone rather than inherited. */
  .chat--mark .chat__head {
    flex-wrap: nowrap;
  }
  .chat--mark .chat__badge {
    order: 0;
    flex-basis: auto;
    padding: 0.22rem 0.6rem;
    border: 1px solid var(--line);
  }
  .chat--mark .chat__signet {
    width: 42px;
  }
}

/* A mark carried entirely by a translucent wash is the first thing to disappear when
   the reader has asked for less of exactly that. Make it a legible mark instead. */
@media (prefers-reduced-transparency: reduce) {
  .hero__watermark {
    display: none;
  }
}

.footer__compare {
  margin-left: 1rem;
  font-size: 0.8rem;
  color: var(--ink-faint);
}

/* ── /lab — the model comparison bench. Local only, never linked from a real page. ── */

.lab {
  width: var(--shell);
  margin: 1.5rem auto 3rem;
}
.lab__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.6rem 1.5rem;
  margin-bottom: 1rem;
}
.lab__head h1 {
  margin: 0;
  font-family: var(--display);
  font-weight: 300;
  font-size: 2rem;
}
.lab__head p {
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink-faint);
}
.lab__lang {
  margin-left: auto;
  font-size: 0.8rem;
  color: var(--ink-soft);
}
.lab__cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
}
@media (max-width: 900px) {
  .lab__cols {
    grid-template-columns: 1fr;
  }
}
.lab__col {
  display: flex;
  flex-direction: column;
  background: var(--paper-card);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  overflow: hidden;
}
.lab__model {
  margin: 0.8rem 0.9rem 0.4rem;
  padding: 0.45rem 0.6rem;
  font: inherit;
  font-size: 0.82rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
  color: var(--ink);
  max-width: 100%;
}
.lab__lang .lab__model {
  margin: 0 0 0 0.4rem;
}
.lab__meta {
  min-height: 1.2rem;
  padding: 0 0.9rem 0.6rem;
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
}
.lab__log {
  flex: 1;
  height: 56vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: 0.9rem;
  border-top: 1px solid var(--line-soft);
}
.lab__form {
  display: flex;
  gap: 0.6rem;
  margin-top: 1rem;
}
.lab__form input {
  flex: 1;
  min-width: 0;
  padding: 0.75rem 1rem;
  font: inherit;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper-card);
  color: var(--ink);
}
.lab__form button,
.lab__reset {
  padding: 0.7rem 1.2rem;
  font: inherit;
  font-size: 0.86rem;
  border-radius: 999px;
  border: 1px solid transparent;
  background: var(--ink);
  color: var(--paper);
  cursor: pointer;
}
.lab__reset {
  margin-top: 0.8rem;
  background: transparent;
  border-color: var(--line);
  color: var(--ink-soft);
}

/* The counted-bookings close. */
.proof {
  width: var(--shell);
  margin: 0 auto clamp(4rem, 8vw, 6rem);
  padding-top: clamp(2rem, 5vw, 3.5rem);
  border-top: 1px solid var(--line);
}
.proof__title {
  margin: 0 0 1rem;
  max-width: 24ch;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(1.9rem, 3.4vw, 2.7rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
}
.proof__body {
  margin: 0 0 1.2rem;
  max-width: 62ch;
  font-size: 0.98rem;
  color: var(--ink-soft);
}
.proof__note {
  margin: 0;
  max-width: 52ch;
  padding-left: 1rem;
  border-left: 2px solid var(--clay-wash);
  font-family: var(--display);
  font-style: italic;
  font-size: 1.2rem;
  color: var(--clay-deep);
}
