/* ==========================================================================
   HOTEL SOLO SUKHUMVIT 2 — "Bangkok After Dark"
   Design system, 2026 redesign.
   Single source of truth for the whole site.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* Palette — 5 values, nothing more. Restraint is the point. */
  --ink:        #0C0C0E;   /* page base                      */
  --charcoal:   #16171A;   /* raised surfaces, cards         */
  --charcoal-2: #1E2024;   /* hover surface, inputs          */
  --brass:      #C8A25A;   /* the one accent                 */
  --brass-lo:   #A5833F;   /* brass, pressed                 */
  --ember:      #8A5A2B;   /* warm secondary, gradients only */
  --bone:       #E8E4DC;   /* primary text                   */
  --bone-dim:   #A9A49B;   /* secondary text                 */
  --bone-faint: #6E6A63;   /* tertiary text, meta            */

  /* ---- Accent system -----------------------------------------------------
     --accent is the themeable slot. Brass is the house default; individual
     sections re-point it with a .theme-* class so the site gains colour
     variety without ever showing two accents at once. */
  --accent:     #C8A25A;
  --accent-lo:  #A5833F;
  --accent-rgb: 200, 162, 90;

  /* Section accents, each drawn from a real photograph on the site */
  --violet:   #A98BC9;   /* Lavender laundromat — from the sub-brand name  */
  --violet-lo:#8B6BB0;
  --neon:     #E0508F;   /* Cloud 9 — the rooftop bar's actual pink neon   */
  --neon-lo:  #C13A75;
  --teal:     #4FA8A0;   /* Pool & facilities — water                     */
  --teal-lo:  #3B8880;

  /* Hairlines */
  --rule:        rgba(232, 228, 220, 0.11);
  --rule-brass:  rgba(var(--accent-rgb), 0.32);

  /* Type */
  --display: "Cormorant Garamond", "Times New Roman", serif;
  --body:    "Jost", "Helvetica Neue", Arial, sans-serif;
  /* Numerals get their own stack. Cormorant ships old-style (text) figures
     that sit below the baseline at display sizes and read as a mistake in
     stat blocks and prices — Jost's lining figures are even and modern. */
  --numeric: "Jost", "Helvetica Neue", Arial, sans-serif;

  /* Fluid type scale — clamp keeps hierarchy intact on every screen */
  --t-hero:  clamp(2.9rem, 7.2vw, 7.5rem);
  --t-h1:    clamp(2.4rem, 5.2vw, 4.75rem);
  --t-h2:    clamp(1.95rem, 3.6vw, 3.25rem);
  --t-h3:    clamp(1.35rem, 2vw, 1.85rem);
  --t-lead:  clamp(1.02rem, 1.35vw, 1.24rem);
  --t-body:  clamp(0.94rem, 1.02vw, 1.03rem);
  --t-small: 0.82rem;
  --t-eyebrow: 0.72rem;

  /* Space */
  --gap:       clamp(1.25rem, 2.5vw, 2rem);
  --section:   clamp(4.5rem, 10vw, 9.5rem);
  --shell:     min(92vw, 1280px);
  --shell-narrow: min(92vw, 940px);
  --shell-text: min(92vw, 680px);

  /* Motion — one curve, used everywhere. Consistency reads as considered. */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --slow: 900ms;
  --med:  480ms;
  --fast: 240ms;

  --nav-h: 84px;
}

/* ---- Section themes -----------------------------------------------------
   Drop one of these on a <section> and every accent inside it retunes:
   eyebrow, rules, buttons, badges, checkmarks, hover glow. One accent at a
   time, so the site gains range without turning into a rainbow.
   --rule-brass is restated because custom properties resolve where they are
   declared, so a :root definition would not pick up the local --accent-rgb. */
.theme-brass  { --accent: #C8A25A; --accent-lo: #A5833F; --accent-rgb: 200,162,90;  --rule-brass: rgba(200,162,90,0.32); }
.theme-violet { --accent: #A98BC9; --accent-lo: #8B6BB0; --accent-rgb: 169,139,201; --rule-brass: rgba(169,139,201,0.32); }
.theme-neon   { --accent: #E0508F; --accent-lo: #C13A75; --accent-rgb: 224,80,143;  --rule-brass: rgba(224,80,143,0.32); }
.theme-teal   { --accent: #4FA8A0; --accent-lo: #3B8880; --accent-rgb: 79,168,160;  --rule-brass: rgba(79,168,160,0.32); }

/* --------------------------------------------------------------------------
   2. RESET
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--nav-h);
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--body);
  font-size: var(--t-body);
  font-weight: 300;
  line-height: 1.72;
  letter-spacing: 0.012em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, video { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { margin: 0; padding: 0; list-style: none; }

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

/* Focus — visible, on-brand, never removed. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Scrollbar */
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-track { background: var(--ink); }
::-webkit-scrollbar-thumb {
  background: #2A2C31;
  border-radius: 99px;
  border: 3px solid var(--ink);
}
::-webkit-scrollbar-thumb:hover { background: var(--accent-lo); }

/* --------------------------------------------------------------------------
   3. TYPOGRAPHY
   -------------------------------------------------------------------------- */
h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 300;
  line-height: 1.06;
  letter-spacing: -0.015em;
  margin: 0;
  color: var(--bone);
}

h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); letter-spacing: -0.005em; line-height: 1.22; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

.lead {
  font-size: var(--t-lead);
  line-height: 1.68;
  color: var(--bone-dim);
  font-weight: 300;
}

/* Eyebrow — the small brass label above every section heading.
   This one component does most of the hierarchy work on the site. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  font-family: var(--body);
  font-size: var(--t-eyebrow);
  font-weight: 400;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 1.35rem;
}
.eyebrow::before {
  content: "";
  width: 34px;
  height: 1px;
  background: var(--accent);
  opacity: 0.65;
}
.eyebrow--center::before { display: none; }

/* Italic serif accent, used sparingly inside display headings */
.accent { font-style: italic; color: var(--accent); }

.muted { color: var(--bone-dim); }
.faint { color: var(--bone-faint); }

/* --------------------------------------------------------------------------
   4. LAYOUT
   -------------------------------------------------------------------------- */
.shell        { width: var(--shell); margin-inline: auto; }
.shell-narrow { width: var(--shell-narrow); margin-inline: auto; }
.shell-text   { width: var(--shell-text); margin-inline: auto; }

.section { padding-block: var(--section); position: relative; }
.section--tight { padding-block: calc(var(--section) * 0.62); }
.section--raised { background: var(--charcoal); }

.section-head { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.section-head--center { text-align: center; }
.section-head--center .eyebrow { justify-content: center; }
.section-head--center p { margin-inline: auto; max-width: 60ch; }
.section-head p { margin-top: 1.35rem; max-width: 58ch; }

/* Split head: heading left, supporting copy right. Creates asymmetry,
   which reads more designed than a centred stack every time. */
.section-head--split {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: end;
}
.section-head--split p { margin-top: 0; }

.grid { display: grid; gap: var(--gap); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

/* Hairline divider — animates open on reveal. */
.rule {
  height: 1px;
  background: var(--rule);
  border: 0;
  margin: 0;
  transform-origin: left center;
}
.rule--brass { background: var(--rule-brass); }

/* --------------------------------------------------------------------------
   5. BUTTONS
   -------------------------------------------------------------------------- */
.btn {
  --btn-bg: var(--accent);
  --btn-fg: var(--ink);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.75em;
  padding: 1.05em 2.3em;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--body);
  font-size: var(--t-small);
  font-weight: 500;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  border-radius: 2px;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--med) var(--ease), background var(--med) var(--ease),
              border-color var(--med) var(--ease), transform var(--fast) var(--ease);
}
/* Wipe fill on hover — subtle, not flashy. */
.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--bone);
  transform: translateY(101%);
  transition: transform var(--med) var(--ease);
}
.btn:hover::after { transform: translateY(0); }
.btn:hover { color: var(--ink); }
.btn:active { transform: translateY(1px); }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--bone);
  border: 1px solid var(--rule-brass);
}
.btn--ghost:hover { color: var(--ink); border-color: var(--bone); }

.btn--block { display: flex; width: 100%; }
.btn--sm { padding: 0.85em 1.6em; font-size: 0.74rem; }

/* Text link with an underline that draws in from the left */
.link {
  position: relative;
  display: inline-block;
  font-size: var(--t-small);
  font-weight: 400;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--accent);
  padding-bottom: 4px;
}
.link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform var(--med) var(--ease);
}
.link:hover::after { transform: scaleX(1); transform-origin: left center; }

/* --------------------------------------------------------------------------
   6. NAV
   -------------------------------------------------------------------------- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  transition: background var(--med) var(--ease), height var(--med) var(--ease),
              border-color var(--med) var(--ease), backdrop-filter var(--med) var(--ease);
  border-bottom: 1px solid transparent;
}
/* Glass only after scroll — over the hero it stays fully transparent. */
.nav.is-stuck {
  height: 68px;
  background: rgba(12, 12, 14, 0.82);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border-bottom-color: var(--rule);
}

.nav__inner {
  width: var(--shell);
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
}

.nav__brand { display: flex; align-items: center; gap: 0.9rem; flex-shrink: 0; }
.nav__brand img { height: 42px; width: auto; transition: height var(--med) var(--ease); }
.nav.is-stuck .nav__brand img { height: 34px; }

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.1vw, 2.1rem);
}
.nav__link {
  position: relative;
  font-size: 0.76rem;
  font-weight: 400;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--bone);
  padding: 0.4rem 0;
  white-space: nowrap;
  transition: color var(--fast) var(--ease);
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform var(--med) var(--ease);
}
.nav__link:hover { color: var(--accent); }
.nav__link:hover::after { transform: scaleX(1); transform-origin: left center; }
.nav__link.is-active { color: var(--accent); }
.nav__link.is-active::after { transform: scaleX(1); }

.nav__cta { flex-shrink: 0; }

/* Burger */
.nav__burger {
  display: none;
  width: 44px; height: 44px;
  flex-direction: column;
  justify-content: center;
  align-items: flex-end;
  gap: 6px;
}
.nav__burger span {
  display: block;
  height: 1px;
  background: var(--bone);
  transition: transform var(--med) var(--ease), opacity var(--fast) var(--ease),
              width var(--med) var(--ease);
}
.nav__burger span:nth-child(1) { width: 26px; }
.nav__burger span:nth-child(2) { width: 18px; }
.nav__burger span:nth-child(3) { width: 26px; }
.nav__burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav__burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__burger[aria-expanded="true"] span:nth-child(3) { width: 26px; transform: translateY(-7px) rotate(-45deg); }

/* Mobile drawer */
.nav__drawer {
  position: fixed;
  inset: 0;
  z-index: 99;
  background: var(--ink);
  padding: calc(var(--nav-h) + 2rem) 7vw 3rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.35rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px);
  transition: opacity var(--med) var(--ease), transform var(--med) var(--ease),
              visibility var(--med);
}
.nav__drawer.is-open { opacity: 1; visibility: visible; transform: none; }
.nav__drawer a {
  font-family: var(--display);
  font-size: clamp(1.8rem, 8vw, 2.6rem);
  font-weight: 300;
  line-height: 1.5;
  border-bottom: 1px solid var(--rule);
  padding: 0.28em 0;
}
.nav__drawer a:last-of-type { border-bottom: 0; }
.nav__drawer .btn { margin-top: 1.8rem; }
body.nav-open { overflow: hidden; }

/* --------------------------------------------------------------------------
   7. HERO
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--ink);
}
.hero--page { min-height: 68svh; }

.hero__media { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.hero__media > img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  animation: drift 24s var(--ease) infinite alternate;
}
@keyframes drift {
  from { transform: scale(1.02); }
  to   { transform: scale(1.11); }
}

/* ---- Cinematic hero -----------------------------------------------------
   There is no video anywhere on this server, so the ambient-video feel is
   built from the 1600px stills instead: long crossfades over a slow Ken
   Burns push. Only the active slide animates, so it costs one compositor
   layer, not a decoded video stream — and it works on every phone. */
.hero__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 2s linear;
  will-change: opacity;
}
.hero__slide.is-active { opacity: 1; }
/* Without JS nothing ever gets .is-active, which would leave the hero — the
   largest element on the page — as an empty black box. Show the first slide. */
html:not(.js) .hero__slide:first-child { opacity: 1; }
.hero__slide img {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.06);
}
/* Alternate the push direction so consecutive slides never feel identical */
.hero__slide.is-active img            { animation: kb-in  11s ease-out forwards; }
.hero__slide.is-active:nth-child(even) img { animation: kb-out 11s ease-out forwards; }

@keyframes kb-in {
  from { transform: scale(1.02) translate3d(0, 0, 0); }
  to   { transform: scale(1.14) translate3d(-1.2%, -1%, 0); }
}
@keyframes kb-out {
  from { transform: scale(1.14) translate3d(1.2%, 0, 0); }
  to   { transform: scale(1.02) translate3d(0, -1.4%, 0); }
}

/* Slide progress dots */
.hero__dots {
  position: absolute;
  right: max(4vw, 2rem); bottom: 2.4rem;
  z-index: 3;
  display: flex;
  gap: 0.6rem;
}
.hero__dot {
  width: 30px; height: 2px;
  background: rgba(232,228,220,0.24);
  border-radius: 2px;
  overflow: hidden;
  cursor: pointer;
  padding: 0;
}
.hero__dot span { display: block; height: 100%; width: 0; background: var(--accent); }
.hero__dot.is-active span { width: 100%; transition: width 7s linear; }

/* ---- Parallax -----------------------------------------------------------
   Driven from one rAF-throttled scroll handler in JS. Transform only, so it
   never triggers layout. Disabled under prefers-reduced-motion and on
   touch-width screens, where it costs more than it gives. */
[data-parallax] { will-change: transform; }
.parallax-wrap { position: relative; overflow: hidden; }
.parallax-wrap > [data-parallax] {
  position: absolute;
  inset: -12% 0;
  width: 100%; height: 124%;
  object-fit: cover;
  /* No transition: JS writes transform every frame, and a 1.1s ease here
     would make the parallax lag a full second behind the scroll. */
  transition: filter var(--slow) var(--ease);
}
/* The hover zoom would fight the inline transform the parallax writes. */
.feature__media.parallax-wrap:hover > [data-parallax] { transform: none; }

/* ---- Draft-rate markers -------------------------------------------------
   Visible while inc/offers.php has RATES_ARE_PLACEHOLDER = true. Setting it
   to false removes both of these from the page entirely. */
.rate-draft {
  display: inline-block;
  margin-left: 0.5em;
  padding: 0.25em 0.6em;
  border: 1px solid var(--rule-brass);
  border-radius: 2px;
  font-size: 0.58rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  vertical-align: middle;
  cursor: help;
}
.draft-banner {
  margin: 0 0 var(--gap);
  padding: 1em 1.35em;
  border: 1px dashed var(--rule-brass);
  border-radius: 3px;
  background: rgba(var(--accent-rgb), 0.055);
  font-size: 0.86rem;
  color: var(--bone-dim);
}
.draft-banner strong { color: var(--accent); font-weight: 500; }

/* Price sitting in a card foot */
.card__price {
  font-family: var(--numeric);
  font-variant-numeric: lining-nums tabular-nums;
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

/* Two-layer scrim: vertical for text legibility, radial for vignette. */
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, var(--ink) 2%, rgba(12,12,14,0.78) 26%, rgba(12,12,14,0.28) 58%, rgba(12,12,14,0.52) 100%),
    radial-gradient(120% 78% at 50% 42%, transparent 38%, rgba(12,12,14,0.62) 100%);
}

.hero__inner {
  position: relative;
  z-index: 2;
  width: var(--shell);
  margin-inline: auto;
  padding-bottom: clamp(4.5rem, 9vh, 8rem);
  padding-top: calc(var(--nav-h) + 3rem);
}

.hero__title {
  font-size: var(--t-hero);
  line-height: 0.98;
  letter-spacing: -0.028em;
  max-width: 15ch;
}
.hero__sub {
  margin-top: 1.9rem;
  max-width: 46ch;
  font-size: var(--t-lead);
  color: var(--bone-dim);
}
.hero__actions {
  margin-top: 2.6rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
}

/* Scroll cue */
.hero__cue {
  position: absolute;
  left: 50%; bottom: 2rem;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.62rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--bone-faint);
}
.hero__cue i {
  display: block;
  width: 1px; height: 52px;
  background: linear-gradient(to bottom, var(--accent), transparent);
  animation: cue 2.4s var(--ease) infinite;
}
@keyframes cue {
  0%, 100% { opacity: 0.25; transform: scaleY(0.55); transform-origin: top; }
  50%      { opacity: 1;    transform: scaleY(1);    transform-origin: top; }
}

/* --------------------------------------------------------------------------
   8. CARDS — offers, rooms, dining, facilities
   -------------------------------------------------------------------------- */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--charcoal);
  border: 1px solid var(--rule);
  border-radius: 3px;
  overflow: hidden;
  transition: border-color var(--med) var(--ease), transform var(--med) var(--ease),
              background var(--med) var(--ease);
}
.card:hover {
  border-color: var(--rule-brass);
  transform: translateY(-5px);
  background: var(--charcoal-2);
}

.card__media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--charcoal-2);
}
.card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--slow) var(--ease), filter var(--slow) var(--ease);
  filter: saturate(0.92) brightness(0.94);
}
.card:hover .card__media img {
  transform: scale(1.055);
  filter: saturate(1) brightness(1);
}

.card__body {
  padding: clamp(1.5rem, 2.4vw, 2.1rem);
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 0.85rem;
}
.card__title { font-size: var(--t-h3); }
.card__text { color: var(--bone-dim); font-size: 0.95rem; line-height: 1.68; }
.card__foot {
  margin-top: auto;
  padding-top: 1.35rem;
  border-top: 1px solid var(--rule);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

/* Meta row — sqm / beds / guests, or hours / floor */
.card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.35rem;
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bone-faint);
}
.card__meta span { display: inline-flex; align-items: center; gap: 0.45em; }

/* Corner ribbon for featured items */
.card__flag {
  position: absolute;
  top: 1rem; left: 1rem;
  z-index: 2;
  padding: 0.5em 1em;
  background: var(--accent);
  color: var(--ink);
  font-size: 0.64rem;
  font-weight: 500;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  border-radius: 2px;
}

/* ---- Offer card: the money component -------------------------------------
   Dark card, brass edge glow on hover, price laid out as a real offer. */
.offer {
  position: relative;
  display: flex;
  flex-direction: column;
  background: linear-gradient(168deg, var(--charcoal) 0%, #121316 100%);
  border: 1px solid var(--rule);
  border-radius: 3px;
  overflow: hidden;
  transition: transform var(--med) var(--ease), border-color var(--med) var(--ease),
              box-shadow var(--med) var(--ease);
}
.offer::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px transparent, 0 0 0 0 rgba(200,162,90,0);
  transition: box-shadow var(--slow) var(--ease);
}
.offer:hover {
  transform: translateY(-6px);
  border-color: var(--rule-brass);
  box-shadow: 0 26px 60px -28px rgba(0,0,0,0.9);
}
.offer:hover::before {
  box-shadow: inset 0 0 0 1px rgba(200,162,90,0.36), 0 0 44px -12px rgba(200,162,90,0.22);
}

.offer--featured { border-color: var(--rule-brass); }
.offer--featured::before { box-shadow: inset 0 0 0 1px rgba(200,162,90,0.28); }

.offer__media { position: relative; aspect-ratio: 16 / 10; overflow: hidden; }
.offer__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(0.9) brightness(0.82);
  transition: transform var(--slow) var(--ease), filter var(--slow) var(--ease);
}
.offer:hover .offer__media img { transform: scale(1.06); filter: saturate(1) brightness(0.95); }
.offer__media::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to top, var(--charcoal) 1%, rgba(22,23,26,0.15) 62%);
}

.offer__save {
  position: absolute;
  top: 1rem; right: 1rem;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 72px; height: 72px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--ink);
  font-family: var(--body);
  line-height: 1;
}
.offer__save b { font-size: 1.32rem; font-weight: 600; letter-spacing: -0.02em; }
.offer__save small { font-size: 0.55rem; letter-spacing: 0.16em; text-transform: uppercase; margin-top: 3px; }

.offer__body {
  padding: clamp(1.6rem, 2.4vw, 2.2rem);
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 1rem;
}
.offer__title { font-size: clamp(1.45rem, 2.1vw, 1.95rem); }

.offer__includes {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin: 0.35rem 0 0;
}
.offer__includes li {
  position: relative;
  padding-left: 1.6rem;
  font-size: 0.9rem;
  color: var(--bone-dim);
  line-height: 1.55;
}
/* Brass check, drawn in CSS — no icon font needed */
.offer__includes li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.44em;
  width: 9px; height: 5px;
  border-left: 1.5px solid var(--accent);
  border-bottom: 1.5px solid var(--accent);
  transform: rotate(-45deg);
}

.offer__price {
  margin-top: auto;
  padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.offer__from { font-size: 0.68rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--bone-faint); }
.offer__amount {
  font-family: var(--numeric);
  font-variant-numeric: lining-nums tabular-nums;
  font-size: clamp(2rem, 3.2vw, 2.7rem);
  font-weight: 300;
  line-height: 1;
  color: var(--bone);
  letter-spacing: -0.035em;
}
.offer__amount sup {
  font-family: var(--body);
  font-size: 0.36em;
  font-weight: 400;
  letter-spacing: 0.14em;
  vertical-align: super;
  color: var(--bone-faint);
  margin-right: 0.25em;
}
.offer__was {
  font-family: var(--numeric);
  font-variant-numeric: lining-nums tabular-nums;
  font-size: 0.9rem;
  font-weight: 300;
  color: var(--bone-faint);
  text-decoration: line-through;
  margin-left: 0.6rem;
  letter-spacing: 0;
}

/* Any numeral rendered in the display serif gets lining figures, so a "42"
   inside a headline sits on the baseline like the letters around it. */
h1, h2, h3, h4, .hero__title { font-variant-numeric: lining-nums; }
.offer__terms { font-size: 0.72rem; color: var(--bone-faint); line-height: 1.5; }

/* --------------------------------------------------------------------------
   9. FEATURE ROW — alternating image / text (rooms, dining, laundry)
   -------------------------------------------------------------------------- */
.feature {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 5.5rem);
  align-items: center;
}
.feature + .feature { margin-top: clamp(4rem, 8vw, 7.5rem); }
.feature--flip .feature__media { order: 2; }

.feature__media {
  position: relative;
  overflow: hidden;
  border-radius: 3px;
  aspect-ratio: 4 / 3;
}
.feature__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--ease);
}
.feature__media:hover img { transform: scale(1.045); }

/* Small brass frame offset behind the image — cheap trick, expensive look */
.feature__media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  border: 1px solid rgba(200,162,90,0.18);
  margin: 12px;
  border-radius: 2px;
}

.feature__body h2 { margin-bottom: 1.4rem; }
.feature__list {
  margin-top: 1.9rem;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.75rem 1.5rem;
}
.feature__list li {
  font-size: 0.86rem;
  color: var(--bone-dim);
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--rule);
}
.feature__actions { margin-top: 2.1rem; display: flex; gap: 0.9rem; flex-wrap: wrap; }

/* --------------------------------------------------------------------------
   10. STATS / TRUST STRIP
   -------------------------------------------------------------------------- */
.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.stats__item {
  padding: clamp(1.8rem, 3vw, 2.8rem) clamp(1rem, 2vw, 2rem);
  text-align: center;
  border-right: 1px solid var(--rule);
}
.stats__item:last-child { border-right: 0; }
.stats__n {
  font-family: var(--numeric);
  font-variant-numeric: lining-nums tabular-nums;
  font-size: clamp(2.4rem, 4vw, 3.5rem);
  font-weight: 300;
  line-height: 1;
  color: var(--accent);
  letter-spacing: -0.03em;
}
/* The unit that trails a stat ("min", "th", "h") — sans, small, muted, so
   the numeral keeps all the weight. */
.stats__u {
  font-size: 0.36em;
  font-weight: 400;
  letter-spacing: 0.06em;
  color: var(--bone-dim);
  margin-left: 0.12em;
}
.stats__l {
  margin-top: 0.7rem;
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--bone-faint);
}

/* --------------------------------------------------------------------------
   11. GALLERY
   -------------------------------------------------------------------------- */
.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: clamp(150px, 17vw, 230px);
  gap: 10px;
}
.gallery__item {
  position: relative;
  overflow: hidden;
  border-radius: 2px;
  background: var(--charcoal);
}
.gallery__item img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(0.9) brightness(0.88);
  transition: transform var(--slow) var(--ease), filter var(--slow) var(--ease);
}
.gallery__item:hover img { transform: scale(1.07); filter: saturate(1) brightness(1); }
.gallery__item--wide { grid-column: span 2; }
.gallery__item--tall { grid-row: span 2; }
.gallery__cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 1.5rem 1.2rem 1rem;
  background: linear-gradient(to top, rgba(12,12,14,0.9), transparent);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--bone);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--med) var(--ease), transform var(--med) var(--ease);
}
.gallery__item:hover .gallery__cap { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   12. FORMS
   -------------------------------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: 0.55rem; }
.field label {
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--bone-faint);
}
.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.95em 1.1em;
  background: var(--charcoal);
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--bone);
  font-family: var(--body);
  font-size: 0.95rem;
  font-weight: 300;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.field textarea { resize: vertical; min-height: 140px; }
.field input::placeholder, .field textarea::placeholder { color: var(--bone-faint); }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--charcoal-2);
}
/* Native date/select controls are light by default on dark backgrounds */
.field select { appearance: none; background-image: none; cursor: pointer; }
.field select option { background: var(--charcoal); color: var(--bone); }
.field input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(0.8); cursor: pointer; }

.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.4rem; }
.form-grid .full { grid-column: 1 / -1; }

/* Booking bar — the sticky conversion strip under the hero */
.bookbar {
  position: relative;
  z-index: 5;
  margin-top: -46px;
  background: var(--charcoal);
  border: 1px solid var(--rule-brass);
  border-radius: 3px;
  padding: clamp(1.2rem, 2vw, 1.6rem);
  display: grid;
  grid-template-columns: repeat(3, 1fr) auto;
  gap: 1rem;
  align-items: end;
  box-shadow: 0 30px 70px -34px rgba(0,0,0,0.95);
}
.bookbar .field label { font-size: 0.62rem; }
.bookbar .btn { height: 47px; }

/* Newsletter — input and arrow button share one bordered shell */
.enews {
  display: flex;
  align-items: stretch;
  border: 1px solid var(--rule);
  border-radius: 2px;
  overflow: hidden;
  background: var(--charcoal);
  transition: border-color var(--fast) var(--ease);
}
.enews:focus-within { border-color: var(--accent); }
.enews input {
  flex: 1;
  min-width: 0;
  padding: 0.95em 1.1em;
  background: transparent;
  border: 0;
  color: var(--bone);
  font-family: var(--body);
  font-size: 0.92rem;
  font-weight: 300;
}
.enews input:focus { outline: none; }
.enews input::placeholder { color: var(--bone-faint); }
.enews button {
  padding: 0 1.25em;
  background: var(--accent);
  color: var(--ink);
  font-size: 1.05rem;
  line-height: 1;
  transition: background var(--fast) var(--ease);
}
.enews button:hover { background: var(--bone); }

/* Accessibility utilities */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.skip {
  position: absolute;
  top: -100px; left: 1rem;
  z-index: 200;
  padding: 0.9em 1.5em;
  background: var(--accent);
  color: var(--ink);
  font-size: 0.76rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border-radius: 0 0 3px 3px;
  transition: top var(--med) var(--ease);
}
.skip:focus { top: 0; }

/* --------------------------------------------------------------------------
   13. FOOTER
   -------------------------------------------------------------------------- */
.footer {
  background: #08080A;
  border-top: 1px solid var(--rule);
  padding-block: clamp(3.5rem, 7vw, 6rem) 2rem;
}
.footer__grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1.3fr;
  gap: clamp(2rem, 4vw, 4rem);
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}
.footer h4 {
  font-family: var(--body);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1.5rem;
}
.footer__links { display: flex; flex-direction: column; gap: 0.85rem; }
.footer__links a {
  font-size: 0.9rem;
  color: var(--bone-dim);
  transition: color var(--fast) var(--ease), transform var(--fast) var(--ease);
  width: fit-content;
}
.footer__links a:hover { color: var(--accent); transform: translateX(4px); }
.footer__logo { height: 52px; width: auto; margin-bottom: 1.5rem; }
.footer__addr { font-size: 0.9rem; color: var(--bone-dim); line-height: 1.85; }
.footer__addr a:hover { color: var(--accent); }

/* Social — the one piece of real personality in the old design was its
   45°-rotated diamond icons that straighten to squares on hover. Kept,
   because it is genuinely theirs. */
.social { display: flex; gap: 1.15rem; margin-top: 1.9rem; }
.social a {
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid var(--rule);
  transform: rotate(45deg);
  transition: border-color var(--med) var(--ease), background var(--med) var(--ease),
              transform var(--med) var(--ease);
}
.social a:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.12);
  transform: rotate(0deg);
}
.social img {
  width: 16px; height: 16px;
  opacity: 0.65;
  transform: rotate(-45deg);
  transition: transform var(--med) var(--ease), opacity var(--med) var(--ease);
}
.social a:hover img { opacity: 1; transform: rotate(0deg); }

.footer__bottom {
  border-top: 1px solid var(--rule);
  padding-top: 2rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  font-size: 0.78rem;
  color: var(--bone-faint);
}
.footer__bottom nav { display: flex; gap: 1.6rem; flex-wrap: wrap; }
.footer__bottom a:hover { color: var(--accent); }

/* ---- Featured offer, laid out wide -------------------------------------- */
.offer--wide { display: grid; grid-template-columns: 1.05fr 0.95fr; }
.offer--wide .offer__media { aspect-ratio: auto; height: 100%; min-height: 420px; }
.offer--wide .offer__media::after {
  background: linear-gradient(to right, transparent 55%, rgba(22,23,26,0.55) 100%);
}
.offer--wide .offer__body { padding: clamp(2rem, 3.4vw, 3.2rem); }
.offer--wide .offer__title { font-size: clamp(1.9rem, 3vw, 2.7rem); }

/* Note under the booking bar */
.bookbar__note {
  margin: 1.1rem 0 0;
  text-align: center;
  font-size: 0.8rem;
  color: var(--bone-faint);
}
.bookbar__note .link { font-size: 0.74rem; }

/* ---- Ledger: a dense list that still reads as designed -------------------
   Used for facility lists. Hairlines do the work; no icons, no bullets. */
.ledger {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0 clamp(1.5rem, 3vw, 3rem);
  border-top: 1px solid var(--rule);
}
.ledger__item {
  padding: 1.05rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 0.88rem;
  color: var(--bone-dim);
  display: flex;
  align-items: center;
  gap: 0.75rem;
  transition: color var(--fast) var(--ease);
}
.ledger__item::before {
  content: "";
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  opacity: 0.7;
}
.ledger__item:hover { color: var(--bone); }

/* ---- Closing CTA band --------------------------------------------------- */
.cta {
  position: relative;
  padding-block: clamp(5rem, 11vw, 9rem);
  overflow: hidden;
  text-align: center;
}
.cta__media { position: absolute; inset: 0; z-index: 0; }
.cta__media img { width: 100%; height: 100%; object-fit: cover; }
.cta__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(12,12,14,0.90), rgba(12,12,14,0.94)),
    radial-gradient(90% 70% at 50% 50%, transparent 20%, rgba(12,12,14,0.7) 100%);
}
.cta__inner { position: relative; z-index: 1; }
.cta__inner .lead { margin: 1.5rem auto 2.4rem; max-width: 52ch; }

/* ---- Image treatment ----------------------------------------------------
   The property photography spans magenta neon, orange cushions and green
   curtains. Pulling saturation down and warming the shadows makes a set of
   inconsistent images read as one deliberate palette. Hover restores it. */
.card__media img,
.offer__media img,
.gallery__item img,
.feature__media img { filter: saturate(0.78) contrast(1.04) brightness(0.9); }

.card:hover .card__media img,
.offer:hover .offer__media img,
.gallery__item:hover img,
.feature__media:hover img { filter: saturate(0.98) contrast(1.02) brightness(1); }

.hero__media img { filter: saturate(0.85) contrast(1.05); }

/* --------------------------------------------------------------------------
   14. MOTION — restrained. Fade-and-rise on reveal, nothing more.
   -------------------------------------------------------------------------- */
/* Everything below is scoped to .js (set by an inline script in inc/head.php).
   These rules hide content until JavaScript reveals it, so if the script is
   blocked, fails to load, or throws, the unscoped default must stay VISIBLE —
   otherwise a single JS error blanks every page below the nav. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
  will-change: opacity, transform;
}
[data-reveal].is-in { opacity: 1; transform: none; }

/* Stagger children of a revealed group */
.js [data-reveal-group] > * {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
}
[data-reveal-group].is-in > * { opacity: 1; transform: none; }
[data-reveal-group].is-in > *:nth-child(1) { transition-delay: 0ms; }
[data-reveal-group].is-in > *:nth-child(2) { transition-delay: 90ms; }
[data-reveal-group].is-in > *:nth-child(3) { transition-delay: 180ms; }
[data-reveal-group].is-in > *:nth-child(4) { transition-delay: 270ms; }
[data-reveal-group].is-in > *:nth-child(5) { transition-delay: 360ms; }
[data-reveal-group].is-in > *:nth-child(6) { transition-delay: 450ms; }

/* Hairline that draws open */
.js [data-rule] { transform: scaleX(0); transition: transform 1.2s var(--ease); }
[data-rule].is-in { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal], [data-reveal-group] > * { opacity: 1; transform: none; }
  [data-rule] { transform: scaleX(1); }
}

/* --------------------------------------------------------------------------
   15. RESPONSIVE — designed for phones, not squished from desktop
   -------------------------------------------------------------------------- */
@media (max-width: 1080px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .bookbar { grid-template-columns: repeat(2, 1fr); }
  .bookbar .btn { grid-column: 1 / -1; }
}

@media (max-width: 900px) {
  :root { --nav-h: 68px; }

  .nav__links, .nav__cta { display: none; }
  .nav__burger { display: flex; }
  .nav { background: rgba(12,12,14,0.82); backdrop-filter: blur(16px); border-bottom-color: var(--rule); }

  .grid-3, .grid-2 { grid-template-columns: 1fr; }
  .section-head--split { grid-template-columns: 1fr; gap: 1.5rem; align-items: start; }

  .feature { grid-template-columns: 1fr; gap: 2rem; }
  .feature--flip .feature__media { order: 0; }
  .feature__media { aspect-ratio: 3 / 2; }

  .stats { grid-template-columns: repeat(2, 1fr); }
  .stats__item:nth-child(2) { border-right: 0; }
  .stats__item:nth-child(1), .stats__item:nth-child(2) { border-bottom: 1px solid var(--rule); }

  .gallery { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 40vw; }
  .gallery__item--wide { grid-column: span 2; }
  .gallery__item--tall { grid-row: span 1; }

  .hero { min-height: 92svh; }
  .hero__title { max-width: 100%; }
  /* Ken Burns is expensive on mobile GPUs and barely visible at this size.
     Drop the zoom but keep the crossfade — that is where the feel lives. */
  .hero__media > img,
  .hero__slide.is-active img,
  .hero__slide.is-active:nth-child(even) img { animation: none; transform: scale(1.04); }
  .hero__dots { right: 50%; transform: translateX(50%); bottom: 1.4rem; }
  .hero__cue { display: none; }

  .offer--wide { grid-template-columns: 1fr; }
  .offer--wide .offer__media { min-height: 0; aspect-ratio: 16 / 10; height: auto; }
  .offer--wide .offer__media::after {
    background: linear-gradient(to top, var(--charcoal) 1%, rgba(22,23,26,0.15) 62%);
  }

  .ledger { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 620px) {
  :root { --gap: 1.1rem; }

  .grid-4 { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
  .bookbar { grid-template-columns: 1fr; margin-top: -20px; }
  .footer__grid { grid-template-columns: 1fr; }
  .feature__list { grid-template-columns: 1fr; }

  .gallery { grid-template-columns: 1fr; grid-auto-rows: 62vw; }
  .gallery__item--wide { grid-column: span 1; }

  .btn { width: 100%; padding: 1.05em 1.5em; }
  .hero__actions .btn { width: 100%; }
  .offer__save { width: 62px; height: 62px; }
  .offer__save b { font-size: 1.1rem; }

  .footer__bottom { flex-direction: column; align-items: flex-start; gap: 1rem; }

  .ledger { grid-template-columns: 1fr; }
  .offer__price { flex-direction: column; align-items: stretch; gap: 1.2rem; }
  .offer__price .btn { width: 100%; }
  .card__foot { flex-direction: column; align-items: stretch; gap: 1rem; }
  .card__foot .btn { width: 100%; }
  .section-head--split { gap: 1.2rem; }
}

/* --------------------------------------------------------------------------
   16. RATE TABLE — the hotel's seasonal rate master
   -------------------------------------------------------------------------- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.rates {
  width: 100%;
  min-width: 560px;              /* below this it scrolls rather than crushes */
  border-collapse: collapse;
  font-size: 0.95rem;
}
.rates th, .rates td {
  padding: 1.1rem 1.2rem;
  text-align: left;
  border-bottom: 1px solid var(--rule);
}
.rates thead th {
  font-family: var(--body);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  border-bottom-color: var(--rule-brass);
  white-space: nowrap;
}
.rates tbody th {
  font-family: var(--body);
  font-size: 0.92rem;
  font-weight: 400;
  color: var(--bone);
}
.rates td {
  font-family: var(--numeric);
  font-variant-numeric: lining-nums tabular-nums;   /* digits line up */
  font-size: 1.12rem;
  font-weight: 300;
  color: var(--bone);
  white-space: nowrap;
}
.rates__cur {
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  color: var(--bone-faint);
  margin-right: 0.2em;
}
.rates tbody tr:last-child th,
.rates tbody tr:last-child td { border-bottom: 0; }

/* The season the visitor is actually in */
.rates tr.is-now { background: rgba(var(--accent-rgb), 0.06); }
.rates tr.is-now td { color: var(--accent); }
.rates__now {
  display: inline-block;
  margin-left: 0.7em;
  padding: 0.24em 0.6em;
  background: var(--accent);
  color: var(--ink);
  font-size: 0.56rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border-radius: 2px;
  vertical-align: middle;
}

.rates__note {
  margin-top: 1.4rem;
  font-size: 0.78rem;
  color: var(--bone-faint);
}

@media (max-width: 620px) {
  .rates th, .rates td { padding: 0.9rem; }
  .rates td { font-size: 1rem; }
}

/* --------------------------------------------------------------------------
   17. LAVENDER SOLO WASH & DRY
   Sub-brand page. Runs on .theme-violet, so every accent below retunes
   automatically from the shared token set.
   -------------------------------------------------------------------------- */

/* Thai text sits alongside English throughout. Give it its own treatment so
   the two languages read as a pair rather than a mistake. */
.lav-th {
  font-family: "Noto Sans Thai", "Leelawadee UI", "Tahoma", var(--body);
  font-size: 0.88rem;
  line-height: 1.85;
  color: var(--bone-dim);
  margin: 0.15rem 0 0;
}
.steps__body .lav-th { display: block; margin-top: 0.2rem; font-size: 0.82rem; }
.rates thead .lav-th { font-size: 0.7rem; letter-spacing: 0; text-transform: none; }

/* ---- "Open now" badge ---------------------------------------------------- */
.lav-open {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem 0.8rem;
  margin: 1.9rem 0 0;
  padding: 0.75em 1.2em;
  border: 1px solid var(--rule-brass);
  border-radius: 99px;
  background: rgba(var(--accent-rgb), 0.09);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.lav-open__dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.6);
  animation: pulse 2.6s ease-out infinite;
  flex-shrink: 0;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.55); }
  70%  { box-shadow: 0 0 0 11px rgba(var(--accent-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0); }
}
.lav-open__label {
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
}
.lav-open__time {
  font-family: var(--numeric);
  font-variant-numeric: tabular-nums;
  font-size: 0.8rem;
  color: var(--bone);
}
.lav-open__sub { font-size: 0.76rem; color: var(--bone-dim); }

/* ---- Price cards --------------------------------------------------------- */
.price-card {
  background: var(--charcoal);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: clamp(1.5rem, 2.6vw, 2.2rem);
  transition: border-color var(--med) var(--ease);
}
.price-card:hover { border-color: var(--rule-brass); }
.price-card__title {
  font-size: var(--t-h3);
  margin-bottom: 0.1rem;
}
.price-card .table-wrap { margin-top: 1.5rem; }
.price-card .rates { min-width: 0; }
.price-card .rates td { font-size: 1.2rem; }

/* ---- Cost calculator ----------------------------------------------------- */
.calc {
  margin-top: var(--gap);
  padding: clamp(1.7rem, 3vw, 2.6rem);
  border: 1px solid var(--rule-brass);
  border-radius: 3px;
  background: linear-gradient(160deg, var(--charcoal) 0%, #121316 100%);
  display: grid;
  gap: clamp(1.4rem, 2.5vw, 2.2rem);
}
.calc__head h3 { font-size: clamp(1.5rem, 2.4vw, 2.1rem); margin-bottom: 0.6rem; }
.calc__controls {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.1rem;
}
.calc__out {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}
.calc__break {
  font-size: 0.84rem;
  color: var(--bone-dim);
  text-transform: capitalize;
}
.calc__total {
  font-family: var(--numeric);
  font-variant-numeric: lining-nums tabular-nums;
  font-size: clamp(2.2rem, 4vw, 3.2rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.035em;
  color: var(--accent);
}
.calc__cur {
  font-size: 0.3em;
  font-weight: 400;
  letter-spacing: 0.16em;
  color: var(--bone-faint);
  vertical-align: super;
  margin-right: 0.25em;
}

/* ---- How-to steps -------------------------------------------------------- */
.steps {
  background: var(--charcoal);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: clamp(1.5rem, 2.6vw, 2.2rem);
}
.steps__title { font-size: var(--t-h3); margin-bottom: 0.1rem; }
.steps__list {
  margin-top: 1.6rem;
  display: flex;
  flex-direction: column;
  gap: 1.15rem;
  counter-reset: step;
}
.steps__list li {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  padding-bottom: 1.15rem;
  border-bottom: 1px solid var(--rule);
}
.steps__list li:last-child { border-bottom: 0; padding-bottom: 0; }
.steps__n {
  flex-shrink: 0;
  width: 28px; height: 28px;
  display: grid;
  place-items: center;
  border: 1px solid var(--rule-brass);
  border-radius: 50%;
  font-family: var(--numeric);
  font-variant-numeric: lining-nums;
  font-size: 0.78rem;
  color: var(--accent);
}
.steps__body { font-size: 0.94rem; line-height: 1.6; color: var(--bone); }

/* ---- Machine rack -------------------------------------------------------- */
.machines {
  margin-top: 1.9rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.6rem;
}
.machine {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  padding: 0.95rem 0.5rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--ink);
  text-align: center;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.machine:hover { border-color: var(--rule-brass); background: var(--charcoal-2); }
.machine__n {
  font-size: 0.58rem;
  letter-spacing: 0.16em;
  color: var(--bone-faint);
}
.machine__kg {
  font-family: var(--numeric);
  font-variant-numeric: lining-nums;
  font-size: 1.5rem;
  font-weight: 300;
  line-height: 1;
  color: var(--accent);
}
.machine__kg small { font-size: 0.42em; margin-left: 0.1em; color: var(--bone-dim); }
.machine__type {
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--bone-dim);
}
/* Dryers sit on top of the washers in the shop; mirror that here. */
.machine--dryer { border-top: 2px solid var(--rule-brass); }

/* ---- Booking form -------------------------------------------------------- */
.lav-form {
  background: var(--charcoal);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: clamp(1.6rem, 3vw, 2.6rem);
  display: grid;
  gap: 1.6rem;
}
.lav-time { display: flex; align-items: center; gap: 0.6rem; }
.lav-time select { flex: 1; }
.lav-time__sep { color: var(--bone-faint); }

/* Flat card variant — no image, so no media box */
.card--flat .card__body { padding-top: clamp(1.6rem, 2.6vw, 2.2rem); }

.social--center { justify-content: center; margin-top: 2.2rem; }
.social__txt {
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--bone-dim);
  transform: rotate(-45deg);
  transition: color var(--med) var(--ease), transform var(--med) var(--ease);
}
.social a:hover .social__txt { color: var(--accent); transform: rotate(0deg); }

@media (max-width: 900px) {
  .calc__controls { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  .lav-open { border-radius: 14px; }
  .machines { grid-template-columns: repeat(3, 1fr); gap: 0.4rem; }
  .machine { padding: 0.7rem 0.3rem; }
  .machine__kg { font-size: 1.2rem; }
  .calc__out { flex-direction: column; align-items: flex-start; }
}

/* ==========================================================================
   18. LAVENDER — "FRESH CYCLE"
   --------------------------------------------------------------------------
   The hotel is Bangkok After Dark. The laundromat is not: it sells "Fresh &
   Clean Every Time", it gets used at 7am with wet hair, and its customers are
   locals and long-stayers, not cocktail drinkers. A dark palette fought that
   message and gave the weakest text contrast on the whole site.

   So this page inverts the token set rather than forking the stylesheet.
   Every component already reads from tokens, so one block flips the page from
   bone-on-black to deep-violet-on-white and each component follows.

   The nav and footer stay dark deliberately. They bookend the page, and the
   fixed nav has to stay legible over the hero photograph.
   ========================================================================== */

body.lav {
  /* Surfaces, inverted */
  --ink:        #FBF7FF;   /* page ground — white with a lilac cast */
  --charcoal:   #FFFFFF;   /* raised cards                          */
  --charcoal-2: #F4ECFF;   /* hover / inputs                        */

  /* Text is deep violet rather than black, so it belongs to the palette.
     #2A1F3D on #FBF7FF measures about 13:1 — far past the 4.5:1 minimum. */
  --bone:       #2A1F3D;
  --bone-dim:   #574372;
  /* Darkened from #7B6B96: the small print measured 4.79:1, which passes AA
     but is the weakest text on the page. This takes it comfortably clear. */
  --bone-faint: #635180;

  --rule:       rgba(42, 31, 61, 0.14);

  --accent:     #7C3AED;
  --accent-lo:  #5B21B6;
  --accent-rgb: 124, 58, 237;
  --rule-brass: rgba(124, 58, 237, 0.30);

  /* The colour set. Used as whole blocks, never as sprinkled decoration. */
  --pop-violet: #7C3AED;
  --pop-cyan:   #0891B2;
  --pop-amber:  #D97706;
  --pop-pink:   #DB2777;
  --pop-green:  #059669;
}

/* Buttons need a light-ground wipe, not the dark-ground one. */
body.lav .btn { --btn-fg: #fff; }
body.lav .btn::after { background: var(--accent-lo); }
body.lav .btn:hover { color: #fff; }
body.lav .btn--ghost { --btn-fg: var(--bone); border-color: var(--accent); }
body.lav .btn--ghost:hover { color: #fff; }

/* On a light ground, cards need a real edge and a shadow to lift. */
body.lav .card,
body.lav .price-card,
body.lav .steps,
body.lav .lav-form,
body.lav .machine {
  border-color: rgba(42, 31, 61, 0.12);
  box-shadow: 0 2px 0 rgba(42, 31, 61, 0.05);
}
body.lav .card:hover { box-shadow: 0 14px 34px -18px rgba(42, 31, 61, 0.4); }

body.lav ::selection { background: var(--accent); color: #fff; }

/* ---- Colour-blocked service cards ---------------------------------------
   Each service owns a colour. The colour is the top edge and the heading;
   the card body stays white so the copy keeps full contrast. */
body.lav .card--flat {
  border-top: 4px solid var(--c, var(--accent));
  border-radius: 0 0 3px 3px;
}
body.lav .card--flat:nth-child(1) { --c: var(--pop-violet); }
body.lav .card--flat:nth-child(2) { --c: var(--pop-cyan); }
body.lav .card--flat:nth-child(3) { --c: var(--pop-pink); }
body.lav .card--flat .card__title { color: var(--c); }

/* ---- Price cards --------------------------------------------------------- */
body.lav .price-card {
  border-top: 4px solid var(--c, var(--accent));
  background: #fff;
}
body.lav .price-card:nth-child(1) { --c: var(--pop-cyan); }
body.lav .price-card:nth-child(2) { --c: var(--pop-amber); }
body.lav .price-card__title { color: var(--c); }
body.lav .price-card .rates thead th { color: var(--c); border-bottom-color: var(--c); }
body.lav .price-card .rates td { color: var(--bone); font-weight: 400; }
body.lav .price-card .rates tbody tr:hover { background: rgba(42, 31, 61, 0.035); }

/* ---- Calculator — the one fully saturated block on the page -------------- */
body.lav .calc {
  background: linear-gradient(135deg, #7C3AED 0%, #A855F7 48%, #DB2777 100%);
  border: 0;
  border-radius: 6px;
  color: #fff;
  box-shadow: 0 24px 50px -26px rgba(124, 58, 237, 0.75);
}
body.lav .calc .eyebrow,
body.lav .calc h3,
body.lav .calc .card__text,
body.lav .calc .field label,
body.lav .calc .calc__break { color: #fff; }
body.lav .calc .eyebrow::before { background: #fff; }
body.lav .calc .card__text,
body.lav .calc .calc__break { opacity: 0.88; }
body.lav .calc .field select {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.45);
  color: #fff;
  font-weight: 400;
}
body.lav .calc .field select option { background: #5B21B6; color: #fff; }
body.lav .calc .field select:focus { border-color: #fff; background: rgba(255, 255, 255, 0.24); }
body.lav .calc__out { border-top-color: rgba(255, 255, 255, 0.32); }
body.lav .calc__total { color: #fff; }
body.lav .calc__cur { color: rgba(255, 255, 255, 0.75); }

/* ---- How-to steps -------------------------------------------------------- */
body.lav .steps { border-top: 4px solid var(--c, var(--accent)); }
body.lav .steps:nth-child(1) { --c: var(--pop-violet); }
body.lav .steps:nth-child(2) { --c: var(--pop-green); }
body.lav .steps__title { color: var(--c); }
body.lav .steps__n {
  background: var(--c, var(--accent));
  border-color: transparent;
  color: #fff;
  font-weight: 500;
}

/* ---- Machine rack — washers and dryers read as two families ------------- */
body.lav .machine { background: #fff; border-top: 3px solid var(--c); }
body.lav .machine--dryer  { --c: var(--pop-amber); }
body.lav .machine--washer { --c: var(--pop-cyan); }
body.lav .machine__kg   { color: var(--c); }
body.lav .machine__type { color: var(--bone-dim); }
body.lav .machine:hover { background: var(--charcoal-2); }

/* ---- Open now — green reads as open in every country -------------------- */
body.lav .lav-open {
  background: rgba(5, 150, 105, 0.14);
  border-color: rgba(5, 150, 105, 0.45);
}
body.lav .lav-open__dot { background: var(--pop-green); }
body.lav .lav-open__label { color: var(--pop-green); }
body.lav .lav-open__time,
body.lav .lav-open__sub { color: var(--bone-dim); }

/* ---- Ledger — rotate the dot colour so the list has rhythm --------------- */
body.lav .ledger__item::before { opacity: 1; width: 7px; height: 7px; }
body.lav .ledger__item:nth-child(5n+1)::before { background: var(--pop-violet); }
body.lav .ledger__item:nth-child(5n+2)::before { background: var(--pop-cyan); }
body.lav .ledger__item:nth-child(5n+3)::before { background: var(--pop-amber); }
body.lav .ledger__item:nth-child(5n+4)::before { background: var(--pop-pink); }
body.lav .ledger__item:nth-child(5n+5)::before { background: var(--pop-green); }

/* ---- Soap bubbles -------------------------------------------------------
   The one decorative motif on the page, and it is on-subject. Pure CSS, sits
   behind the content, and never overlaps text. */
body.lav .bubbles {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
body.lav .bubbles span {
  position: absolute;
  bottom: -160px;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 30%,
              rgba(255, 255, 255, 0.95),
              rgba(124, 58, 237, 0.16) 60%,
              rgba(124, 58, 237, 0.06));
  border: 1px solid rgba(124, 58, 237, 0.16);
  animation: rise linear infinite;
}
@keyframes rise {
  from { transform: translateY(0) scale(0.85); opacity: 0; }
  15%  { opacity: 0.9; }
  85%  { opacity: 0.5; }
  to   { transform: translateY(-120vh) scale(1.12); opacity: 0; }
}
/* Keep real content above the bubbles. */
body.lav .section > .shell,
body.lav .section > .shell-narrow { position: relative; z-index: 1; }

/* ---- Forms on a light ground -------------------------------------------- */
body.lav .field input,
body.lav .field select,
body.lav .field textarea {
  background: #fff;
  border-color: rgba(42, 31, 61, 0.22);
  color: var(--bone);
}
body.lav .field input::placeholder { color: var(--bone-faint); }
body.lav .field input[type="date"]::-webkit-calendar-picker-indicator { filter: none; }

/* The closing band keeps its dark photograph, so the light page lands back
   on the dark footer without a hard seam. */
body.lav .cta__inner h2,
body.lav .cta__inner .lead { color: #F5F0FF; }
body.lav .cta__inner .eyebrow { color: #C4B5FD; }
body.lav .cta__inner .eyebrow::before { background: #C4B5FD; }
body.lav .cta .btn--ghost { --btn-fg: #F5F0FF; border-color: rgba(255, 255, 255, 0.5); }

@media (prefers-reduced-motion: reduce) {
  body.lav .bubbles { display: none; }
}

/* ==========================================================================
   18b. LAVENDER — CORRECTIONS AND DEPTH
   --------------------------------------------------------------------------
   Three real faults in 18, all reported as "it looks so light, the text is
   not visible":

   1. THE HERO INVERTED WITH THE PAGE. Its scrim is built from var(--ink),
      which 18 flipped to near-white — so the photograph faded to white while
      the heading stayed dark violet, and the fixed nav links went dark over
      a photograph too. The hero has to stay dark; it sits under a dark nav
      and over photography.

   2. WEIGHT, NOT RATIO. Body copy was still font-weight 300. Light text on a
      dark ground blooms optically and reads heavier than it is; the same
      weight on a light ground reads thin and faint at any contrast ratio.
      Measured contrast was 14:1 and it still looked washed out, because the
      problem was never the ratio. 300 -> 400, and headings gain weight too.

   3. NOT ENOUGH COLOUR. Near-white sections on a near-white ground gave the
      page no structure. Sections are now washed with real tint, alternating
      against white, so the page reads as blocks rather than one pale sheet.
   ========================================================================== */

/* ---- 1. The hero stays dark --------------------------------------------- */
body.lav .hero__media::after {
  /* Fixed dark values, not var(--ink) — this sits over a photograph and under
     a dark nav, so it must not follow the light page palette. */
  background:
    linear-gradient(to top, #17102A 2%, rgba(23, 16, 42, 0.82) 26%, rgba(23, 16, 42, 0.34) 58%, rgba(23, 16, 42, 0.58) 100%),
    radial-gradient(120% 78% at 50% 42%, transparent 38%, rgba(23, 16, 42, 0.66) 100%);
}
body.lav .hero__title       { color: #FFFFFF; }
body.lav .hero__title .accent { color: #D8B4FE; }
body.lav .hero__sub         { color: #E7DCFF; font-weight: 400; }
body.lav .hero .eyebrow     { color: #C4B5FD; }
body.lav .hero .eyebrow::before { background: #C4B5FD; }
body.lav .hero .btn--ghost  { --btn-fg: #FFFFFF; border-color: rgba(255, 255, 255, 0.55); }
body.lav .hero .btn--ghost:hover { color: #2A1F3D; }
body.lav .hero .btn--ghost::after { background: #FFFFFF; }

/* Open-now badge sits in the dark hero, so it needs the dark-ground variant */
body.lav .lav-open {
  background: rgba(16, 185, 129, 0.20);
  border-color: rgba(52, 211, 153, 0.65);
}
body.lav .lav-open__dot   { background: #34D399; }
body.lav .lav-open__label { color: #6EE7B7; }
body.lav .lav-open__time  { color: #FFFFFF; }
body.lav .lav-open__sub   { color: #E7DCFF; }

/* Nav links ride over the hero photograph before the bar goes solid */
body.lav .nav__link,
body.lav .nav__drawer a { color: #FFFFFF; }
body.lav .nav__link:hover,
body.lav .nav__link.is-active { color: #D8B4FE; }
body.lav .nav__link::after,
body.lav .nav__link.is-active::after { background: #D8B4FE; }
body.lav .nav__burger span { background: #FFFFFF; }

/* ---- 2. Weight — the actual reason it read as faint --------------------- */
body.lav { font-weight: 400; }
body.lav .lead        { font-weight: 400; color: #46356B; }
body.lav .card__text  { font-weight: 400; }
body.lav .steps__body { font-weight: 400; }
body.lav .ledger__item{ font-weight: 400; }
body.lav .lav-th      { font-weight: 400; color: #55447A; }
body.lav .rates__note { font-weight: 400; }
body.lav h2, body.lav h3 { font-weight: 400; }
body.lav .rates tbody th { font-weight: 500; }
body.lav .rates td       { font-weight: 500; }
body.lav .eyebrow        { font-weight: 500; }
body.lav .field label    { font-weight: 500; color: #46356B; }

/* ---- 3. Colour-washed sections ------------------------------------------
   Alternating tint and white so the page has blocks instead of one flat
   sheet. Each tint is a heavy dilution of one of the five accent colours. */
body.lav main > section:nth-of-type(2) { background: #F1E7FF; }  /* services  — violet */
body.lav main > section:nth-of-type(3) { background: #FFFFFF; }  /* prices              */
body.lav main > section:nth-of-type(4) { background: #E3F7F4; }  /* how to    — green   */
body.lav main > section:nth-of-type(5) { background: #FFFFFF; }  /* machines            */
body.lav main > section:nth-of-type(6) { background: #FFF3E0; }  /* why here  — amber   */
body.lav main > section:nth-of-type(7) { background: #FFFFFF; }  /* location            */
body.lav main > section:nth-of-type(8) { background: #E6F4FB; }  /* booking   — cyan    */

/* Hairlines need more presence against a tinted ground */
body.lav { --rule: rgba(42, 31, 61, 0.20); }

/* Cards sit on tinted grounds now, so give them a real lift */
body.lav .card,
body.lav .price-card,
body.lav .steps,
body.lav .lav-form {
  box-shadow: 0 4px 14px -6px rgba(42, 31, 61, 0.18);
}

/* Section headings carry their own colour, matched to the block they sit in */
body.lav main > section:nth-of-type(2) .accent { color: #6D28D9; }
body.lav main > section:nth-of-type(4) .accent { color: #047857; }
body.lav main > section:nth-of-type(6) .accent { color: #B45309; }
body.lav main > section:nth-of-type(8) .accent { color: #0369A1; }
body.lav main > section:nth-of-type(2) .eyebrow { color: #6D28D9; }
body.lav main > section:nth-of-type(4) .eyebrow { color: #047857; }
body.lav main > section:nth-of-type(6) .eyebrow { color: #B45309; }
body.lav main > section:nth-of-type(8) .eyebrow { color: #0369A1; }
body.lav main > section:nth-of-type(2) .eyebrow::before { background: #6D28D9; }
body.lav main > section:nth-of-type(4) .eyebrow::before { background: #047857; }
body.lav main > section:nth-of-type(6) .eyebrow::before { background: #B45309; }
body.lav main > section:nth-of-type(8) .eyebrow::before { background: #0369A1; }

/* Bubbles read as white soap against a tint rather than vanishing on white */
body.lav .bubbles span {
  background: radial-gradient(circle at 32% 30%,
              rgba(255, 255, 255, 0.98),
              rgba(255, 255, 255, 0.55) 58%,
              rgba(124, 58, 237, 0.10));
  border-color: rgba(255, 255, 255, 0.9);
}

/* ==========================================================================
   18c. LAVENDER — THE SHOP'S OWN COLOURS
   --------------------------------------------------------------------------
   18 and 18b invented a palette. The shop photographs show the real one: the
   storefront is navy blue and vivid orange, the interior wall is orange, and
   the Lavender mark is purple with a green leaf. Those four colours are the
   brand, they already appear on every sign and machine, and they are far more
   vivid than what was invented for them.

   The section washes are also taken up several steps. Pale tints on a pale
   ground read as "no colour at all", which is what came back from review.
   ========================================================================== */

body.lav {
  /* Straight off the storefront and the interior wall */
  --pop-violet: #6D28D9;   /* the Lavender mark            */
  --pop-cyan:   #1E4A8F;   /* storefront navy              */
  --pop-amber:  #B23A08;   /* interior orange, darkened
                              enough to hold text on white */
  --pop-pink:   #BE185D;
  --pop-green:  #3F7D20;   /* the leaf in the logo         */

  --accent:     #6D28D9;
  --accent-lo:  #4C1D95;
  --accent-rgb: 109, 40, 217;
  --rule-brass: rgba(109, 40, 217, 0.32);

  /* A ground with some actual colour in it, not near-white */
  --ink:        #F2E9FF;
}

/* ---- Section washes, several steps stronger ----------------------------- */
body.lav main > section:nth-of-type(2) { background: #E7D8FF; }  /* services — lavender */
body.lav main > section:nth-of-type(3) { background: #FFFFFF; }  /* prices              */
body.lav main > section:nth-of-type(4) { background: #D9EDD4; }  /* how to   — green    */
body.lav main > section:nth-of-type(5) { background: #FFFFFF; }  /* machines            */
body.lav main > section:nth-of-type(6) { background: #FFE0CC; }  /* why here — orange   */
body.lav main > section:nth-of-type(7) { background: #FFFFFF; }  /* location            */
body.lav main > section:nth-of-type(8) { background: #D9E7F7; }  /* booking  — navy     */

/* Section accents follow the block they sit in */
body.lav main > section:nth-of-type(2) .accent,
body.lav main > section:nth-of-type(2) .eyebrow { color: #5B21B6; }
body.lav main > section:nth-of-type(4) .accent,
body.lav main > section:nth-of-type(4) .eyebrow { color: #2F5F18; }
body.lav main > section:nth-of-type(6) .accent,
body.lav main > section:nth-of-type(6) .eyebrow { color: #B23A08; }
body.lav main > section:nth-of-type(8) .accent,
body.lav main > section:nth-of-type(8) .eyebrow { color: #1B3F73; }
body.lav main > section:nth-of-type(2) .eyebrow::before { background: #5B21B6; }
body.lav main > section:nth-of-type(4) .eyebrow::before { background: #2F5F18; }
body.lav main > section:nth-of-type(6) .eyebrow::before { background: #B23A08; }
body.lav main > section:nth-of-type(8) .eyebrow::before { background: #1B3F73; }

/* ---- Price cards: navy for washing, orange for drying ------------------- */
body.lav .price-card:nth-child(1) { --c: #1E4A8F; }
body.lav .price-card:nth-child(2) { --c: #B23A08; }
body.lav .price-card { border-top-width: 6px; }

/* Table headers carry the card colour as a solid band, not a hairline —
   far more visible than coloured text on white. */
body.lav .price-card .rates thead th {
  background: var(--c);
  color: #FFFFFF;
  padding-top: 0.9rem;
  padding-bottom: 0.9rem;
  border-bottom: 0;
}
body.lav .price-card .rates thead th:first-child { border-radius: 3px 0 0 0; }
body.lav .price-card .rates thead th:last-child  { border-radius: 0 3px 0 0; }
body.lav .price-card .rates tbody th { color: #2A1F3D; }
body.lav .price-card .rates td { color: var(--c); font-weight: 600; font-size: 1.3rem; }
body.lav .price-card .rates tbody tr:nth-child(even) { background: rgba(42, 31, 61, 0.04); }

/* ---- Service cards: the three brand colours ---------------------------- */
body.lav .card--flat:nth-child(1) { --c: #6D28D9; }
body.lav .card--flat:nth-child(2) { --c: #1E4A8F; }
body.lav .card--flat:nth-child(3) { --c: #B23A08; }
body.lav .card--flat { border-top-width: 6px; }

/* ---- Steps ------------------------------------------------------------- */
body.lav .steps:nth-child(1) { --c: #1E4A8F; }
body.lav .steps:nth-child(2) { --c: #B23A08; }
body.lav .steps { border-top-width: 6px; }

/* ---- Machines: dryers orange, washers navy, matching their own labels --- */
body.lav .machine--dryer  { --c: #B23A08; }
body.lav .machine--washer { --c: #1E4A8F; }
body.lav .machine { border-top-width: 4px; }
body.lav .machine__kg { font-weight: 500; }

/* ---- Calculator: the shop's orange-to-purple, not a generic gradient ---- */
body.lav .calc {
  background: linear-gradient(135deg, #4C1D95 0%, #6D28D9 42%, #B23A08 100%);
  box-shadow: 0 24px 50px -24px rgba(76, 29, 149, 0.7);
}

/* ---- Ledger dots cycle the four brand colours -------------------------- */
body.lav .ledger__item:nth-child(4n+1)::before { background: #6D28D9; }
body.lav .ledger__item:nth-child(4n+2)::before { background: #1E4A8F; }
body.lav .ledger__item:nth-child(4n+3)::before { background: #B23A08; }
body.lav .ledger__item:nth-child(4n+4)::before { background: #3F7D20; }
body.lav .ledger__item::before { width: 9px; height: 9px; }
body.lav .ledger__item { border-bottom-color: rgba(42, 31, 61, 0.18); }

/* Cards need a firmer edge now that they sit on saturated grounds */
body.lav .card,
body.lav .price-card,
body.lav .steps,
body.lav .lav-form,
body.lav .machine {
  border-color: rgba(42, 31, 61, 0.16);
  box-shadow: 0 6px 18px -8px rgba(42, 31, 61, 0.28);
}

/* --------------------------------------------------------------------------
   19. LEDGER LINKS + INLINE SOCIAL ICONS
   -------------------------------------------------------------------------- */

/* A ledger entry that links somewhere. Matches the plain entries exactly so
   the list stays even, and only reveals itself as a link on hover/focus. */
.ledger__item--link {
  color: var(--bone);
  text-decoration: none;
  transition: color var(--fast) var(--ease), gap var(--fast) var(--ease);
}
.ledger__item--link:hover,
.ledger__item--link:focus-visible { color: var(--accent); }
.ledger__item--link::after {
  content: "\2192";                 /* arrow, revealed on hover */
  margin-left: auto;
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease);
  color: var(--accent);
}
.ledger__item--link:hover::after,
.ledger__item--link:focus-visible::after { opacity: 1; transform: none; }

/* Some social channels have no PNG in images/social/, so their mark is drawn
   inline instead. Match the sizing and the diamond rotation of the images. */
.social a svg {
  width: 16px;
  height: 16px;
  opacity: 0.65;
  transform: rotate(-45deg);
  transition: transform var(--med) var(--ease), opacity var(--med) var(--ease);
}
.social a:hover svg { opacity: 1; transform: rotate(0deg); }

/* ==========================================================================
   20. LAVENDER SPLIT HERO
   --------------------------------------------------------------------------
   The client's own footage is vertical 1080p. Filling the old full-width
   banner with it meant upscaling a 1080px-wide frame to 1440px or more, which
   goes visibly soft - and image quality was the complaint that started this.
   So the photo gets its own column at 4:5, never shown larger than it is.

   The ground stays dark: the photo is a dusk shot of neon signage, and the
   fixed nav above it is white. The page turns light below, as before.
   ========================================================================== */

body.lav .lav-hero {
  min-height: 0;
  align-items: stretch;
  background:
    radial-gradient(60% 80% at 85% 35%, rgba(124, 58, 237, 0.32), transparent 62%),
    radial-gradient(40% 50% at 8% 92%, rgba(217, 72, 15, 0.16), transparent 70%),
    #17102A;
}
body.lav .lav-hero .hero__inner {
  width: var(--shell);
  padding-top: calc(var(--nav-h) + clamp(2rem, 5vh, 3.5rem));
  padding-bottom: clamp(3rem, 8vh, 6rem);
}

.lav-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2rem, 5vw, 5.5rem);
  align-items: center;
}
.lav-hero__text { min-width: 0; }
body.lav .lav-hero .hero__title { max-width: 12ch; }

.lav-hero__photo {
  position: relative;
  margin: 0;
  justify-self: end;
  width: 100%;
  max-width: 500px;               /* 1080px source stays at or above 2x */
  aspect-ratio: 4 / 5;
  border-radius: 8px;
  overflow: hidden;
  box-shadow:
    0 50px 90px -40px rgba(0, 0, 0, 0.9),
    0 0 0 1px rgba(216, 180, 254, 0.22);
}
.lav-hero__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Thin inner frame, echoing the framed feature images on the hotel pages */
.lav-hero__photo::after {
  content: "";
  position: absolute;
  inset: 12px;
  border: 1px solid rgba(216, 180, 254, 0.28);
  border-radius: 4px;
  pointer-events: none;
}

@media (max-width: 900px) {
  .lav-hero__grid { grid-template-columns: 1fr; gap: 2rem; }
  /* Photo first on phones: vertical footage is native to a phone screen */
  .lav-hero__photo { order: -1; justify-self: stretch; max-width: none; }
  body.lav .lav-hero .hero__title { max-width: none; }
}

/* --------------------------------------------------------------------------
   21. LAVENDER PHOTOS — keep the client's footage vivid
   --------------------------------------------------------------------------
   Sitewide, photos are desaturated and darkened (section 13 image treatment)
   so the hotel's inconsistent stock photography reads as one palette on a
   dark ground. The Lavender page is light, its brand colours are orange,
   navy and purple, and these stills are the client's own new footage - so
   that treatment would dull exactly what the client asked to show off.
   Specificity is set to beat the sitewide :hover rules as well. */
body.lav .card__media img,
body.lav .card:hover .card__media img,
body.lav .feature__media img,
body.lav .feature__media:hover img,
body.lav .offer__media img,
body.lav .offer:hover .offer__media img,
body.lav .lav-hero__photo img {
  filter: none;
}
