/*! Monantalia — public site
 *  Designed & built by TESLA CREATIVE AGENCY · teslakafa.com
 *
 *  DIRECTION — "Mediterranean Modernism".
 *  Not a clinic, not a hotel brochure: the restraint of an architecture
 *  monograph about a limestone house on the Antalya coast. Warm stone ground,
 *  deep sea accent, brass hairlines, and a great deal of air.
 *
 *  The typography carries the positioning. Cormorant Garamond (classical,
 *  Mediterranean, hospitable) against IBM Plex Sans (engineered, precise,
 *  medical). Hospitality wrapper, clinical core — the two faces are the brief.
 *
 *  Deliberately NO medical blue, no rounded pill buttons, no card-grid sameness.
 */

/* ==========================================================================
   1. Tokens
   ========================================================================== */
:root {
  /* Sampled from the brand mark: a gold gradient running #A37213 -> #D9AA34,
     a near-black wordmark, on an almost-white ground. The palette is the logo's
     own, so the site and the mark read as one thing rather than two. */
  --bone:       #fbf9f5;
  --bone-2:     #f4f0e7;
  --bone-3:     #e9e3d6;
  --ink:        #121210;
  --ink-soft:   #57534b;
  --ink-faint:  #8a857b;

  /* The page ground. These two were REFERENCED by `body` but never declared,
     so every light surface fell back to browser white and every word to pure
     #000 — the warm stone palette described above had never actually
     rendered. An undefined custom property fails silently: no console error,
     no invalid rule, just the initial value. Declared here, once. */
  --bg:         var(--bone);
  --fg:         var(--ink);

  /* Dark surfaces are warm espresso rather than flat black: the mark's gold is
     a METALLIC gradient, and metal needs a warm ground to read as metal
     instead of yellow paint. */
  --dark:       #14120d;
  --dark-2:     #1e1b14;

  --gold:        #a37213;   /* the ramp's dark end — safe for text on light */
  --gold-mid:    #c08f24;
  --gold-bright: #d9aa34;   /* the ramp's midpoint — the mark's dominant tone */
  --gold-glow:   #e8c978;   /* for gold on dark, where the dark end disappears */

  /* Gold TEXT on a light ground. The mid golds measure under 4:1 on cream, so
     small gold type needs the deep end of the ramp — which also happens to be
     the richer, more engraved-looking colour. Antique gold, not highlighter. */
  --gold-deep:   #8f6110;   /* 5.1:1 on bone — safe for small text */

  --line:       #e2dbcc;

  --display: 'Cormorant Garamond', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  --sans:    'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* Fluid scale. min is the mobile size, max the desktop one. */
  --t-xs:   clamp(.72rem, .70rem + .10vw, .78rem);
  --t-sm:   clamp(.82rem, .79rem + .15vw, .90rem);
  --t-base: clamp(1rem, .96rem + .20vw, 1.09rem);
  --t-lg:   clamp(1.15rem, 1.05rem + .45vw, 1.4rem);
  --t-xl:   clamp(1.5rem, 1.25rem + 1.2vw, 2.1rem);
  --t-2xl:  clamp(2rem, 1.45rem + 2.6vw, 3.4rem);
  --t-3xl:  clamp(2.3rem, 1.6rem + 3.2vw, 4rem);
  --t-4xl:  clamp(2.6rem, 1.5rem + 4.6vw, 5rem);

  --s-1: .5rem;  --s-2: .875rem; --s-3: 1.25rem; --s-4: 2rem;
  --s-5: 3rem;   --s-6: 4.5rem;  --s-7: 6.5rem;  --s-8: 9rem;

  --measure: 62ch;
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --maxw: 78rem;

  --ease: cubic-bezier(.16, .84, .44, 1);
  --slow: .9s;
}

/* ==========================================================================
   2. Reset and base
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: var(--t-base);
  line-height: 1.65;
  font-feature-settings: 'kern' 1, 'liga' 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, picture, svg, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: .22em; }
button, input, select, textarea { font: inherit; color: inherit; }

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

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

/* A very fine paper grain. Barely perceptible, but it stops large flat areas
   reading as flat screen colour and gives the stone palette some tooth. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: .035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ==========================================================================
   3. Typography
   ========================================================================== */
h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -.014em;
  text-wrap: balance;
}

h1 { font-size: var(--t-3xl); }
h2 { font-size: var(--t-2xl); }
h3 { font-size: var(--t-xl); }
h4 { font-size: var(--t-lg); }

p, li { text-wrap: pretty; }
p { max-width: var(--measure); }

.lede {
  font-size: var(--t-lg);
  line-height: 1.5;
  color: var(--ink-soft);
  max-width: 46ch;
}

/* The small letter-spaced label that opens each section. */
.eyebrow {
  font-family: var(--sans);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--gold-deep);
  display: flex;
  align-items: center;
  gap: .75rem;
}
.eyebrow::before {
  content: '';
  width: 1.75rem;
  height: 1px;
  background: currentColor;
  flex: none;
}

/* Figures line up in tables and the fact rail. */
.tnum { font-variant-numeric: tabular-nums; }

/* ==========================================================================
   4. Layout
   ========================================================================== */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap-narrow { max-width: 54rem; }

.section { padding-block: clamp(var(--s-6), 10vw, var(--s-8)); }
.section--tight { padding-block: clamp(var(--s-5), 7vw, var(--s-6)); }
/* A very shallow vertical gradient and hairline edges. Flat fills read as
   "a coloured div"; a band that is fractionally lighter at the top reads as a
   surface with light falling on it. */
.section--sand {
  background: linear-gradient(180deg, var(--bone) 0%, var(--bone-2) 38%, var(--bone-2) 100%);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.section--dark  { background: var(--dark); color: var(--bone); }
.section--dark .eyebrow { color: var(--gold-glow); }
.section--dark .lede { color: #cfc9bd; }

.stack > * + * { margin-top: var(--s-3); }
.stack-lg > * + * { margin-top: var(--s-4); }

/* minmax(0,...) not 1fr: a bare 1fr inherits its items' min-content floor and
   is a classic source of mobile horizontal overflow. */
.grid { display: grid; gap: clamp(1.5rem, 4vw, 3.5rem); }
.grid-2 { grid-template-columns: minmax(0, 1fr); }
.grid-3 { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 48rem) {
  .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* Asymmetric editorial split — deliberately not 50/50. */
@media (min-width: 62rem) {
  .grid-editorial { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: start; }
  .grid-editorial--flip { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
}

.rule { border: 0; border-top: 1px solid var(--line); margin-block: var(--s-5); }
.section--dark .rule { border-color: rgba(247, 243, 234, .18); }

/* ==========================================================================
   5. Header
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--bone) 88%, transparent);
  backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.site-header[data-scrolled] { border-bottom-color: var(--line); }

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 4.5rem;
}

.brand { display: flex; align-items: center; gap: .625rem; min-height: 44px; text-decoration: none; color: var(--ink); flex: none; }
.brand img, .brand svg { height: 2.35rem; width: auto; }
/* The name is set as written, not uppercased: CSS uppercasing is language-blind,
   so "Hüseyin" would become "HÜSEYIN" (the Turkish capital is "HÜSEYİN").
   A long practice name wraps to two lines instead of pushing the nav off-screen. */
.brand__name {
  font-family: var(--sans);
  font-weight: 500;
  font-size: clamp(.9rem, .82rem + .3vw, 1.05rem);
  letter-spacing: .03em;
  line-height: 1.15;
  color: var(--ink);
  max-width: 11.5em;
}
@media (max-width: 26rem) { .brand__name { display: none; } }

/* Below 62rem the nav is a panel the toggle opens, not a hidden element.
   It used to be display:none with no toggle anywhere, which left every phone
   visitor with no route to Treatments, Our approach, Your visit, The dentist
   or The practice except by scrolling to the footer — on a site whose traffic
   is overwhelmingly phones. */
.nav {
  position: absolute;
  inset-inline: 0;
  top: 100%;
  display: grid;
  gap: var(--s-1);
  padding: var(--s-3) var(--s-4) var(--s-4);
  background: var(--bone);
  border-block-start: 1px solid var(--line);
  box-shadow: 0 18px 40px -24px rgba(14, 14, 12, .45);
  /* Collapsed by default, and collapsed WITHOUT display:none so the panel can
     animate and so its links stay reachable to a screen reader only when open. */
  visibility: hidden;
  opacity: 0;
  transform: translateY(-0.35rem);
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease, visibility 0s linear .18s;
}

.site-header[data-nav-open] .nav {
  visibility: visible;
  opacity: 1;
  transform: none;
  pointer-events: auto;
  transition: opacity .18s ease, transform .18s ease, visibility 0s;
}

.nav a {
  padding-block: var(--s-2);
  font-size: var(--t-md);
}

.nav a.nav__cta {
  margin-block-start: var(--s-2);
  padding: .8rem 1rem;
  justify-content: center;
  background: var(--ink);
  color: var(--bone);
  border-radius: 2rem;
}

.nav a.nav__cta::after { content: none; }

.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  margin-inline-start: auto;
  padding: .5rem .25rem;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: var(--t-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
}

.nav-toggle__bars {
  position: relative;
  display: block;
  width: 1.15rem;
  height: .6rem;
}

.nav-toggle__bars span {
  position: absolute;
  inset-inline: 0;
  height: 1px;
  background: currentColor;
  transition: transform .18s ease, opacity .18s ease;
}

.nav-toggle__bars span:first-child { top: 0; }
.nav-toggle__bars span:last-child  { bottom: 0; }

.site-header[data-nav-open] .nav-toggle__bars span:first-child { transform: translateY(.295rem) rotate(45deg); }
.site-header[data-nav-open] .nav-toggle__bars span:last-child  { transform: translateY(-.295rem) rotate(-45deg); }

@media (prefers-reduced-motion: reduce) {
  .nav, .nav-toggle__bars span { transition: none; }
}

/* The header CTA duplicates the one inside the panel on small screens, and at
   375px it wraps to two lines and squeezes the logo and language switcher.
   One CTA per viewport: the panel owns it below the breakpoint. */
.header-actions .header-cta { display: none; }

@media (min-width: 62rem) {
  .nav-toggle { display: none; }
  .nav a.nav__cta { display: none; }
  .header-actions .header-cta { display: inline-flex; }
  .nav {
    position: static;
    display: flex;
    align-items: center;
    gap: clamp(1rem, 2.2vw, 2.25rem);
    margin-inline-start: auto;
    padding: 0;
    background: none;
    border: 0;
    box-shadow: none;
    visibility: visible;
    opacity: 1;
    transform: none;
    pointer-events: auto;
  }
  .nav a { padding-block: 0; font-size: inherit; }
}

.nav a {
  font-size: var(--t-sm);
  text-decoration: none;
  color: var(--ink-soft);
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding-block: .4rem;
  transition: color .2s var(--ease);
}
.nav a::after {
  content: '';
  position: absolute;
  left: 0; right: 100%; bottom: .1rem;
  height: 1px;
  background: var(--gold);
  transition: right .35s var(--ease);
}
.nav a:hover, .nav a[aria-current] { color: var(--ink); }
@media (hover: hover) and (pointer: fine) {
  .nav a:hover::after { right: 0; }
}
.nav a[aria-current]::after { right: 0; }

.header-actions { display: flex; align-items: center; gap: var(--s-2); margin-inline-start: auto; }
@media (min-width: 62rem) { .header-actions { margin-inline-start: var(--s-3); } }

/* ==========================================================================
   6. Buttons — square, not pills. Pills read as consumer app, not as a practice.
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  padding: .85rem 1.5rem;
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: .02em;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 2px;
  cursor: pointer;
  min-height: 44px;
  transition: background .25s var(--ease), color .25s var(--ease),
              border-color .25s var(--ease), transform .25s var(--ease);
}
/* Solid antique gold, cream lettering — an engraved brass plate, not a shiny
   web button. A multi-stop gradient with a coloured glow is the single fastest
   way to make a luxury brand look cheap: real metal in print is one flat ink,
   and restraint is what reads as expensive. Depth comes from the colour and
   the type, not from a sheen. */
.btn--primary {
  background: var(--gold-deep);
  color: var(--bone);
  border-color: var(--gold-deep);
}
.btn--ghost   { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--light   { background: var(--bone); color: var(--dark); }

@media (hover: hover) and (pointer: fine) {
  /* Deepens rather than glows. */
  .btn--primary:hover {
    background: #7a520c;
    border-color: #7a520c;
    transform: translateY(-1px);
  }
  .btn--ghost:hover   { border-color: var(--gold); color: var(--gold-deep); }
  .btn--light:hover   { transform: translateY(-1px); }
}
.btn--sm { padding: .55rem 1rem; font-size: var(--t-xs); min-height: 40px; }

/* ==========================================================================
   7. Hero
   ========================================================================== */
.hero {
  position: relative;
  min-height: min(86svh, 46rem);
  display: grid;
  align-items: end;
  overflow: hidden;
  /* Reserve the overlaying header so long translations grow downward instead of
     riding up behind the nav — a full-height centred hero is otherwise the
     classic multilingual overlap bug. */
  padding-top: 4.5rem;
}
.hero__media { position: absolute; inset: 0; z-index: 0; }
/* The coastal frames are shot flat and cool. A touch of saturation and warmth
   gives back the Mediterranean light the compression took out — the scene
   should look like late afternoon in Antalya, not an overcast morning. */
.hero__media img { width: 100%; height: 100%; object-fit: cover; filter: saturate(1.14) contrast(1.05); }

/* Slideshow. Frames are stacked and crossfaded; the single-image hero uses the
   identical markup with one frame, so there is no separate code path to rot.
   Only the stacking is done here — WHICH frame is active is a class the script
   moves, so with JS off the first frame simply stays visible. */
.hero__media--show .hero__frame {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1.1s var(--ease);
}
.hero__media--show .hero__frame.is-active { opacity: 1; }

/* A crossfading photograph behind a headline is decoration, and decoration
   that moves is exactly what this media query exists to stop. The first frame
   is shown and the rest are never faded in. */
@media (prefers-reduced-motion: reduce) {
  .hero__media--show .hero__frame { transition: none; }
}
.hero__media::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Warm espresso rather than neutral black, and lighter at the top so the
     photograph is still a photograph. The third layer is a low gold wash —
     sunlight, and the mark's colour, over the whole frame. */
  background:
    linear-gradient(to top, rgba(20,18,13,.88) 0%, rgba(20,18,13,.46) 46%, rgba(20,18,13,.14) 100%),
    linear-gradient(to right, rgba(20,18,13,.56), transparent 62%),
    linear-gradient(200deg, rgba(184,134,38,.20) 0%, transparent 58%);
}
.hero__inner { position: relative; z-index: 1; color: var(--bone); padding-block: clamp(2.5rem, 5vw, 4rem); }
.hero h1 { font-size: var(--t-4xl); max-width: 17ch; line-height: 1.02; }
/* Was a cool blue-grey — the one cold value in a warm palette, and it read as
   grey plastic against the stone. */
.hero .lede { color: #e4ddd0; margin-top: var(--s-3); }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }

/* ==========================================================================
   8. Fact rail — verifiable credentials directly beneath the aspirational image.
      Luxury without proof reads as expensive-therefore-suspicious; this is the
      antidote, and it sits deliberately adjacent to the hero.
   ========================================================================== */
/* Light, not black. The credentials are the reassuring part of the page, and a
   black slab immediately under a dark hero stacked two heavy bands with no air
   between them. Ivory ground, gold numerals, hairline dividers — the proof now
   reads as an engraved plate rather than a warning panel. */
.factrail {
  background: linear-gradient(180deg, var(--bone) 0%, var(--bone-2) 100%);
  color: var(--ink);
  border-bottom: 1px solid var(--line);
}
.factrail__inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr));
  gap: 1px;
  background: var(--line);
}
/* Centred: the four figures are a set of equal credentials, and a centred
   column reads as an engraved plate rather than a left-aligned data table.
   The flex column keeps each cell's value and label centred as a pair even
   when one label wraps to three lines and its neighbours use one. */
.fact {
  background: linear-gradient(180deg, var(--bone) 0%, var(--bone-2) 100%);
  padding: clamp(1.25rem, 3vw, 2rem) clamp(1rem, 2.5vw, 1.75rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.fact__value {
  font-family: var(--display);
  font-size: var(--t-xl);
  line-height: 1;
  color: var(--gold-deep);
  /* Cormorant defaults to OLD-STYLE figures, where a lone "1" is a short
     stroke sitting on the baseline — "1 dentist, start to finish", the page's
     central claim, was rendering as "I". Lining figures make a one a one. */
  font-variant-numeric: lining-nums;
  font-feature-settings: 'lnum' 1;
}
.fact__label { font-size: var(--t-xs); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-faint); margin-top: .5rem; }

/* ==========================================================================
   9. Treatment cards — the index number set large behind the title.
   ========================================================================== */
.card-treatment {
  position: relative;
  display: block;
  padding: var(--s-4) var(--s-3) var(--s-3);
  border-top: 1px solid var(--line);
  text-decoration: none;
  color: inherit;
  overflow: hidden;
  transition: background .3s var(--ease);
}
.card-treatment__n {
  position: absolute;
  top: .25rem; right: .5rem;
  font-family: var(--display);
  font-size: clamp(3.5rem, 8vw, 6rem);
  line-height: 1;
  color: var(--gold);
  opacity: .14;
  pointer-events: none;
  transition: opacity .4s var(--ease), transform .5s var(--ease);
}
.card-treatment h3 { margin-bottom: .5rem; }
.card-treatment p { color: var(--ink-soft); font-size: var(--t-sm); }
.card-treatment__meta {
  display: flex; flex-wrap: wrap; gap: .4rem 1.1rem;
  margin-top: var(--s-2);
  font-size: var(--t-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
@media (hover: hover) and (pointer: fine) {
  .card-treatment:hover { background: var(--bone-2); }
  .card-treatment:hover .card-treatment__n { opacity: .3; transform: translateY(-.15rem); }
}

/* ==========================================================================
   10. Statement — the honesty block. Deliberately the loudest thing on the page.
   ========================================================================== */
.statement { text-align: center; }
.statement blockquote {
  font-family: var(--display);
  font-size: var(--t-2xl);
  line-height: 1.16;
  letter-spacing: -.015em;
  max-width: 22ch;
  margin-inline: auto;
  text-wrap: balance;
}
.statement__cite { display: block; margin-top: var(--s-3); font-size: var(--t-xs); letter-spacing: .16em; text-transform: uppercase; color: var(--gold-glow); }

/* A short list of things we refuse to do. Plain, unadorned, no icons — the
   restraint is the point. */
.refusals { list-style: none; padding: 0; max-width: 44rem; margin-inline: auto; text-align: left; }
.refusals li { padding-block: var(--s-2); border-top: 1px solid rgba(247,243,234,.16); display: flex; gap: var(--s-2); }
.refusals li::before { content: '—'; color: var(--gold-glow); flex: none; }

/* ==========================================================================
   11. Itinerary — a resort programme, not a flowchart.
   ========================================================================== */
.itinerary { list-style: none; padding: 0; display: grid; gap: 0; }
.itin {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr);
  gap: var(--s-3);
  padding-block: var(--s-3);
  border-top: 1px solid var(--line);
}
.itin__day { font-family: var(--display); font-size: var(--t-lg); color: var(--gold); line-height: 1.2; }
.itin__body h4 { margin-bottom: .3rem; }
.itin__body p { color: var(--ink-soft); font-size: var(--t-sm); }

/* ==========================================================================
   12. Figures and media
   ========================================================================== */
.figure { position: relative; }
.figure img { width: 100%; object-fit: cover; border-radius: 2px; }
.figure--tall img { aspect-ratio: 4 / 5; }
.figure--wide img { aspect-ratio: 16 / 10; }
.figure figcaption { margin-top: .75rem; font-size: var(--t-xs); color: var(--ink-faint); letter-spacing: .04em; }
/* A thin brass rule that sits under an image and shifts it off the grid — a
   small asymmetry that stops the page reading as a stack of boxes. */
.figure--offset { margin-inline-start: clamp(0rem, 3vw, 2.5rem); }

/* ==========================================================================
   12b. Forms
   ==========================================================================
   Square, generous, and high-contrast. A medical enquiry form should feel like
   a document you are filling in, not a signup widget.
   ========================================================================== */
.form-label {
  display: block;
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: .5rem;
}

input[type="text"], input[type="email"], input[type="tel"], input[type="date"],
input[type="number"], select, textarea {
  width: 100%;
  font-family: var(--sans);
  font-size: var(--t-base);
  color: var(--ink);
  background: var(--bone);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: .8rem .9rem;
  min-height: 48px;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
textarea { min-height: 9rem; resize: vertical; line-height: 1.6; }

input:hover, select:hover, textarea:hover { border-color: var(--ink-faint); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(168, 114, 19, .14);
}

/* Never rely on colour alone to signal an error. */
small.err {
  display: block;
  margin-top: .4rem;
  font-size: var(--t-xs);
  color: #8c2f1f;
}
small.err::before { content: '! '; font-weight: 700; }

input[type="checkbox"] { width: 1.1rem; height: 1.1rem; min-height: 0; accent-color: var(--gold); }

select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%235f584c' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  padding-right: 2.5rem;
}

/* ==========================================================================
   13. Footer
   ========================================================================== */
.site-footer { background: var(--dark); color: var(--bone); padding-block: var(--s-6) var(--s-4); }
.site-footer a { color: #cfc9bd; text-decoration: none; }
@media (hover: hover) and (pointer: fine) { .site-footer a:hover { color: var(--bone); text-decoration: underline; } }
.site-footer h4 { font-family: var(--sans); font-size: var(--t-xs); font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--gold-glow); margin-bottom: var(--s-2); }
/* The practice name under the mark. Compound selector: it must outrank the h4 rule above. */
.site-footer h4.footer-brand { font-size: var(--t-base, 1rem); font-weight: 500; letter-spacing: .03em; text-transform: none; color: var(--bone); margin-bottom: var(--s-3); }
.footer-grid { display: grid; gap: var(--s-4); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 48rem) { .footer-grid { grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)); } }
.footer-list { list-style: none; padding: 0; font-size: var(--t-sm); }
.footer-list li + li { margin-top: .25rem; }
/* 24px is the WCAG 2.2 AA minimum target; footer links are the main touch
   targets on a phone, where the desktop nav is not rendered at all. */
.footer-list a { display: inline-flex; align-items: center; min-height: 28px; }
.footer-bottom { margin-top: var(--s-5); padding-top: var(--s-3); border-top: 1px solid rgba(247,243,234,.16); display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); justify-content: space-between; font-size: var(--t-xs); color: #a6a094; }

/* ==========================================================================
   14. Language switcher
   ========================================================================== */
.langs { position: relative; }
.langs__btn { display: inline-flex; align-items: center; gap: .4rem; min-height: 40px; background: none; border: 1px solid var(--line); border-radius: 2px; padding: .45rem .7rem; font-size: var(--t-xs); letter-spacing: .1em; text-transform: uppercase; cursor: pointer; }
.langs__menu { position: absolute; right: 0; top: calc(100% + .5rem); min-width: 10rem; background: var(--bone); border: 1px solid var(--line); border-radius: 2px; padding: .35rem; box-shadow: 0 18px 40px -22px rgba(25,23,19,.4); }
.langs__menu[hidden] { display: none; }
.langs__menu a { display: block; min-height: 40px; display: flex; align-items: center; padding: .5rem .7rem; font-size: var(--t-sm); text-decoration: none; border-radius: 1px; }
.langs__menu a[aria-current] { background: var(--bone-2); font-weight: 600; }
@media (hover: hover) and (pointer: fine) { .langs__menu a:hover { background: var(--bone-2); } }

/* ==========================================================================
   15. Utility
   ========================================================================== */
.skip { position: absolute; left: -9999px; }
.skip:focus { left: var(--gutter); top: .75rem; z-index: 200; background: var(--ink); color: var(--bone); padding: .7rem 1rem; border-radius: 2px; }
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.placeholder-img { background: var(--bone-3); }

/* ==========================================================================
   15b. Motion pieces
   ==========================================================================
   Four moments, not forty. The brief for this palette is "expensive", and
   expensive motion is slow, few, and confident. Everything here is opt-out via
   prefers-reduced-motion and every one of them degrades to plain visible text.
   ========================================================================== */

/* --- a) Masked word reveal ------------------------------------------------
   Words rise out from behind a mask rather than fading in. The mask is what
   makes it read as typesetting rather than as a web animation. JS splits the
   words; with JS off the heading is simply a heading. */
.split { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: .08em; }
.split > i { display: inline-block; font-style: inherit; }
@keyframes wordRise { from { transform: translateY(105%); opacity: 0; } to { transform: none; opacity: 1; } }
/* Fail open: the mask only hides once script has armed it AND confirmed the
   heading is below the fold. No script, no hiding. */
.split > i { transform: none; opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .split.is-armed > i { transform: translateY(105%); opacity: 0; }
  .split.is-armed.is-in > i {
    animation: wordRise .9s cubic-bezier(.16,.9,.3,1) forwards;
    animation-delay: calc(var(--i, 0) * 55ms);
  }
}

/* --- b) Ken Burns on the hero --------------------------------------------
   A still photograph of a building is inert. A very slow push gives the hero
   the feeling of a held shot without anyone noticing a "slideshow". */
@media (prefers-reduced-motion: no-preference) {
  .hero__media img { animation: kenburns 26s ease-out both; transform-origin: 58% 45%; }
}
@keyframes kenburns { from { transform: scale(1.075); } to { transform: scale(1); } }

/* --- c) The gold rule draws itself ---------------------------------------
   The eyebrow's hairline is the smallest piece of the brand. Drawing it makes
   the section header feel authored rather than placed. */
.eyebrow::before { transform-origin: left center; }
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .eyebrow::before {
      animation: drawRule linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 22%;
    }
  }
  .is-in .eyebrow::before, .eyebrow.is-in::before { animation: drawRule .8s var(--ease) both; }
}
@keyframes drawRule { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* --- d) Staggered groups --------------------------------------------------
   Used on the fact rail and the refusals: the eye should travel down the list
   rather than have the whole block appear at once. */
/*
 * CONTENT IS VISIBLE BY DEFAULT. The hiding is applied by script, and only to
 * groups that are genuinely below the fold — see site.js.
 *
 * The obvious way to write this is `.stagger > * { opacity: 0 }` with a class
 * to reveal, and it is wrong: anything the observer never reports is then
 * invisible permanently, with a healthy-looking page and nothing in the
 * console. Making the hidden state opt-IN means the worst case is a missing
 * animation rather than missing text.
 */
@media (prefers-reduced-motion: no-preference) {
  .stagger.is-armed > * { opacity: 0; transform: translateY(.9rem); }
  .stagger.is-armed.is-in > * {
    animation: rise .75s var(--ease) both;
    animation-delay: calc(var(--d, 0ms) + (var(--i, 0) * 90ms));
  }
}

/* --- e) Scroll progress ---------------------------------------------------
   A one-pixel gold thread under the header. It is the only persistent motion
   on the page, and it earns its place by telling a long page how long it is. */
.progress {
  position: fixed; inset: 0 0 auto 0; height: 2px; z-index: 70;
  background: linear-gradient(90deg, var(--gold), var(--gold-bright));
  transform-origin: 0 50%;
  transform: scaleX(0);
  pointer-events: none;
}
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .progress { animation: grow linear both; animation-timeline: scroll(root block); }
  }
}
@keyframes grow { to { transform: scaleX(1); } }

/* --- f) The treatment number drifts --------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .card-treatment__n {
      animation: drift linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
  }
}
@keyframes drift { from { transform: translateY(.9rem); } to { transform: translateY(-.9rem); } }

/* ==========================================================================
   16. Motion — one orchestrated reveal, not scattered fidgeting.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .reveal {
      animation: reveal linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 26%;
    }
    @keyframes reveal {
      from { opacity: 0; transform: translateY(1.25rem); }
      to   { opacity: 1; transform: none; }
    }
  }

  /* The hero is above the fold, so it animates on load rather than on scroll,
     staggered so the eye lands on the headline first. */
  .hero__inner > * { animation: rise var(--slow) var(--ease) both; }
  .hero__inner > :nth-child(1) { animation-delay: .05s; }
  .hero__inner > :nth-child(2) { animation-delay: .18s; }
  .hero__inner > :nth-child(3) { animation-delay: .30s; }
  .hero__inner > :nth-child(4) { animation-delay: .42s; }
  @keyframes rise { from { opacity: 0; transform: translateY(1.5rem); } to { opacity: 1; transform: none; } }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* ==========================================================================
   17. Print — a patient printing a quote or the guarantee should get something
       legible, not a dark section with white text.
   ========================================================================== */
@media print {
  body::after, .site-header, .langs, .hero__media { display: none !important; }
  .section--dark, .factrail, .site-footer { background: #fff !important; color: #000 !important; }
  a[href^="http"]::after { content: ' (' attr(href) ')'; font-size: .8em; }
}

/* ==========================================================================
   Long-form CMS content
   --------------------------------------------------------------------------
   `.prose` was applied in every body-rendering view but had no rules at all,
   and the global `* { margin: 0 }` reset meant every paragraph, heading and
   list in the CMS ran together with zero separation — on every content page,
   in every language. The only visual break came from line-height.

   The scale below is set in em so it tracks each element's own size, and the
   vertical rhythm is asymmetric on purpose: a heading belongs to the text that
   follows it, so its space-above is large and its space-below is small.
   ========================================================================== */
.prose > * + * { margin-block-start: 1.15em; }

.prose p {
  line-height: 1.65;
  color: var(--ink-soft);
}

.prose h2,
.prose h3 {
  color: var(--ink);
  text-wrap: balance;
}

.prose h2 { font-size: var(--t-xl); }
.prose h3 { font-size: var(--t-lg); }

.prose > h2 + *,
.prose > h3 + * { margin-block-start: .7em; }

.prose > * + h2 { margin-block-start: 2.1em; }
.prose > * + h3 { margin-block-start: 1.7em; }

.prose > :first-child { margin-block-start: 0; }

.prose ul,
.prose ol {
  padding-inline-start: 1.35em;
  max-width: var(--measure);
  color: var(--ink-soft);
}

.prose ul { list-style: none; }

/* A gold rule instead of a bullet: the lists here carry published figures, and
   a marker that reads as part of the type is calmer than a disc. */
.prose ul > li { position: relative; }

.prose ul > li::before {
  content: "";
  position: absolute;
  inset-inline-start: -1.1em;
  top: .72em;
  width: .5em;
  height: 1px;
  background: var(--gold);
}

.prose ol { list-style: decimal; }

.prose li {
  line-height: 1.65;
  margin-block-start: .5em;
}

.prose li:first-child { margin-block-start: 0; }

.prose strong { color: var(--ink); font-weight: 600; }

.prose em { font-style: italic; }

.prose a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: .18em;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--gold);
}

@media (hover: hover) and (pointer: fine) {
  .prose a:hover { text-decoration-color: var(--ink); }
}

.prose blockquote {
  padding-inline-start: 1.1em;
  border-inline-start: 2px solid var(--gold);
  color: var(--ink);
  font-family: var(--display);
  font-size: var(--t-lg);
  line-height: 1.35;
}

/* ==========================================================================
   Parallax scenery
   --------------------------------------------------------------------------
   Not `background-attachment: fixed` — it is unsupported on iOS, forces a
   full-surface repaint on every scroll frame elsewhere, and is the usual
   reason parallax feels broken on a phone. This is a transform on a composited
   layer instead, driven by one rAF-gated scroll listener that only runs while
   the section is actually on screen.

   The image is oversized vertically so the translation never exposes an edge:
   at 0.16 travel over a viewport the layer moves at most ~16% of the section
   height, and 124% covers that with room to spare.
   ========================================================================== */
.has-parallax { position: relative; overflow: hidden; }
.has-parallax > .wrap { position: relative; z-index: 2; }

.parallax {
  position: absolute;
  inset: -12% 0;
  z-index: 0;
  pointer-events: none;
}

.parallax__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Promote once, up front, so the first scroll frame is not the one that
     pays for layer creation. */
  will-change: transform;
  transform: translate3d(0, 0, 0);
}

/* A scrim keeps body copy at full contrast over any frame. The section already
   carries --dark, so this only has to deepen it. */
.has-parallax::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Was .86/.78 of neutral black, which buried the photograph and made two
     near-identical black bands on one page. Warmer, lighter, with a gold wash
     across the top so the image is present instead of merely implied. */
  background:
    linear-gradient(to bottom, rgba(20,18,13,.80), rgba(20,18,13,.68)),
    linear-gradient(160deg, rgba(184,134,38,.16) 0%, transparent 62%);
}


@media (prefers-reduced-motion: reduce) {
  .parallax__img { transform: none !important; will-change: auto; }
}

/* ==========================================================================
   Consent banner
   --------------------------------------------------------------------------
   Fixed to the bottom, so it must be measured per-element rather than by any
   document-level overflow probe: a fixed box contributes nothing to document
   scrollWidth, and this exact component has shipped 45px off-screen on a phone
   before. Actions wrap, and refusing is the same size and weight as accepting.
   ========================================================================== */
.consent {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 90;
  background: var(--dark);
  color: var(--bone);
  border-top: 1px solid rgba(247, 243, 234, .16);
}

.consent[hidden] { display: none; }

.consent__inner {
  max-width: var(--maxw);
  margin-inline: auto;
  padding: var(--s-3) var(--gutter);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2) var(--s-4);
  /* Without this the text column inherits a min-content floor and pushes the
     bar wider than the viewport. */
  min-width: 0;
}

.consent__text {
  flex: 1 1 22rem;
  min-width: 0;
  margin: 0;
  font-size: var(--t-sm);
  line-height: 1.5;
  color: #cfc9bd;
  max-width: 68ch;
}

.consent__text a { color: var(--bone); text-decoration: underline; text-underline-offset: .16em; }

.consent__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  flex: 0 0 auto;
  margin-inline-start: auto;
}

.consent .btn--ghost { color: var(--bone); border-color: rgba(247, 243, 234, .4); }

@media (max-width: 32rem) {
  .consent__actions { width: 100%; margin-inline-start: 0; }
  .consent__actions .btn { flex: 1 1 0; }
}

/* Tables inside CMS prose — currently the cookie table on the privacy page.
   Wrapped in its own scroll container so a narrow phone scrolls the TABLE
   rather than the page: a table is the classic source of a document-level
   horizontal overflow, and that overflow then expands the mobile layout
   viewport and drags every fixed element off-screen with it. */
.prose table {
  display: block;
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: var(--t-sm);
  white-space: nowrap;
}

.prose table thead th {
  text-align: start;
  font-family: var(--sans);
  font-size: var(--t-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 600;
  padding: 0 var(--s-3) var(--s-2) 0;
  border-bottom: 1px solid var(--line);
}

.prose table td {
  padding: var(--s-2) var(--s-3) var(--s-2) 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  color: var(--ink-soft);
}

.prose table td:first-child {
  font-family: var(--sans);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* The purpose column carries real sentences, so it alone is allowed to wrap. */
.prose table td:nth-child(2) { white-space: normal; min-width: 20rem; }

/* ————— Patient reviews carousel (belge-gated; absent from informational locales) ————— */

.preview-flag {
  display: inline-block;
  margin-bottom: var(--s-3);
  padding: .35rem .8rem;
  border: 1px dashed var(--gold);
  border-radius: 2px;
  font-family: var(--sans);
  font-size: var(--t-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: var(--bone);
}

.reviews__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-3);
}

.reviews__nav { display: flex; gap: .5rem; flex: none; }

.reviews__btn {
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .reviews__btn:hover { border-color: var(--gold); background: var(--bone); }
}

.reviews__track {
  display: grid;
  grid-auto-flow: column;
  /* Snap-scrolled row: each card a column, width clamped for phone → desktop. */
  grid-auto-columns: min(26rem, 85%);
  gap: var(--s-3);
  margin-top: var(--s-5);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-bottom: var(--s-2);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.reviews__track::-webkit-scrollbar { display: none; }
.reviews__track:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }

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

.review-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin: 0;
  padding: var(--s-4) var(--s-3);
  border-top: 1px solid var(--line);
  background: var(--bone);
  border-radius: 2px;
  scroll-snap-align: start;
}

.review-card__stars {
  color: var(--gold);
  letter-spacing: .15em;
  font-size: var(--t-sm);
}

.review-card__body {
  margin: 0;
  color: var(--ink-soft);
  font-size: var(--t-sm);
  line-height: 1.65;
}

.review-card__meta {
  margin-top: auto;
  display: grid;
  gap: .15rem;
  font-family: var(--sans);
  font-size: var(--t-xs);
}

.review-card__meta strong { color: var(--ink); font-weight: 600; }
.review-card__meta span { color: var(--ink-faint); }
.review-card__meta a { color: inherit; }

/* ————— Content-page hero band (Media::slotOrScene — real photo wins the slot) ————— */

.page-hero { padding-block: 0 var(--s-4); }

/* The frame is what the parallax layer is measured against, so it needs its own
   height, position and clip. The layer inside it (.parallax / .parallax__img,
   shared with the dark bands) is 124% tall and drifts on scroll, which means
   the visible crop is the MIDDLE of the photograph at rest — a 3.2:1 letterbox
   slice was showing a band across the subject rather than the subject. Taller
   and explicitly centre-cropped fixes the framing; the parallax gives the same
   motion the refuse and CTA bands have. */
.page-hero__frame {
  position: relative;
  overflow: hidden;
  /* Full-bleed: no border-radius, no max-width, no gutter. A contained image
     with rounded corners reads as an illustration OF the room; edge to edge it
     reads as the room. That is the whole difference in effect. */
  /* The viewport-width cap is what keeps the band LANDSCAPE on a phone. A pure
     vh height is 390px against a 335px column at 375x812 — a portrait crop of a
     wide room photograph, which is the worst possible framing of it, on the
     viewport 80% of these patients actually use. Desktop is untouched by the
     cap: at 1024 it is 573px against a 369px height. */
  height: min(clamp(20rem, 62vh, 42rem), 56vw);
}

/* Stated rather than left to the initial value: this is the whole point of the
   band, and a future object-position on a shared .parallax__img would silently
   re-crop five templates. */
.page-hero__frame .parallax__img { object-position: 50% 50%; }

/* Deeper travel than the dark bands, because here the photograph IS the content
   rather than a backdrop for type — scrolling past should reveal the top and
   bottom of the frame, not just breathe.
   Travel and slack are one decision, not two: the layer can only move as far as
   it overhangs. data-parallax="0.24" in partials/page_hero.php moves at most 24%
   of the frame height, so the overhang has to exceed that — 30% here against 24%.
   Raise one and you MUST raise the other, or the crop shows a hard edge at the
   moment the band is entering the viewport, which is exactly when a visitor is
   looking at it. Scoped to this frame so the refuse (0.16) and CTA (0.12) bands
   keep the shared -12%.

   30% and not more, because slack is not free on a PHONE. `object-fit: cover`
   scales by whichever axis binds. On desktop the frame is far wider than it is
   tall, so WIDTH binds and the extra slack is nearly free — it buys travel. At
   375x210 the LAYER is taller than the frame is wide relative to the source, so
   HEIGHT binds, and every point of slack zooms in and throws the sides of the
   room away. Measured at 375 full-bleed against the 16:9 file the srcset serves
   there (NOT the 3:2 original — deriving it from the source file understates it
   badly): -12% loses 19.0% of the width, -20% loses 28.2%, -30% loses 37.2%.
   The -30% figure is browser-measured; the other two come from the same formula
   that reproduced it exactly (crop = 1 - 1/scale, scale = layerHeight/sourceH).
   Do not raise either number without re-measuring on a phone viewport — and note
   these figures are for a FULL-BLEED band; the contained version this replaced
   cropped less at the same slack simply because its frame was shorter. */
.page-hero__frame .parallax { inset: -30% 0; }

.review-card__mark { vertical-align: -2px; margin-inline-end: .25rem; }

/* ————— Pre-footer CTA band (partials/cta.php) ————— */

.cta-band__inner {
  display: grid;
  justify-items: center;
  text-align: center;
}

.cta-band__inner h2 { max-width: 20ch; }
.cta-band__inner .lede { margin-top: var(--s-3); }
.cta-band__inner p:last-child { margin-top: var(--s-4); }

/* ————— Floating contact buttons (partials/contact_float.php) ————— */

.contact-float {
  position: fixed;
  inset-inline-end: max(1rem, env(safe-area-inset-right));
  bottom: max(1rem, env(safe-area-inset-bottom));
  z-index: 60;
  display: grid;
  gap: .6rem;
  transition: opacity .25s var(--ease), visibility .25s;
}

/* While the consent dialog owns the bottom edge, the float steps aside —
   a chat button covering the Decline button is a dark pattern by accident. */
.consent-open .contact-float { opacity: 0; visibility: hidden; }

.contact-float__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.1rem;
  height: 3.1rem;
  border-radius: 50%;
  color: #fff;
  box-shadow: 0 6px 20px rgba(14, 14, 12, .28);
}

.contact-float__btn--wa { background: #25d366; }
.contact-float__btn--tg { background: #229ed9; }

@media (hover: hover) and (pointer: fine) {
  .contact-float__btn:hover { filter: brightness(1.07); }
}

/* ————— Blog index (site/blog/index.php) ————— */

.post-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(20rem, 100%), 1fr));
  gap: var(--s-4) var(--s-3);
}

.post-card {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: inherit;
  border-top: 1px solid var(--line);
}

.post-card__media {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 2px;
  margin-top: var(--s-3);
}

.post-card__media img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform .5s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .post-card:hover .post-card__media img { transform: scale(1.03); }
}

.post-card__draft {
  position: absolute;
  top: .6rem;
  inset-inline-start: .6rem;
  padding: .2rem .55rem;
  border-radius: 2px;
  background: var(--bone);
  border: 1px dashed var(--gold);
  font-family: var(--sans);
  font-size: var(--t-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.post-card__body { display: grid; gap: .5rem; padding-block: var(--s-3); }
.post-card__date { font-family: var(--sans); font-size: var(--t-xs); color: var(--ink-faint); }
.post-card__title { font-size: var(--t-xl); line-height: 1.15; }
.post-card__excerpt { color: var(--ink-soft); font-size: var(--t-sm); }
.post-card__more { font-family: var(--sans); font-size: var(--t-sm); color: var(--ink); }

.post-byline {
  margin-top: var(--s-3);
  font-family: var(--sans);
  font-size: var(--t-sm);
  color: var(--ink-faint);
}
.post-byline strong { color: var(--ink); font-weight: 600; }

/* ————— Reviews page grid (site/reviews.php) ————— */

.review-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(20rem, 100%), 1fr));
  gap: var(--s-3);
  align-items: start;
}

/* ————— Price table (site/prices.php) ————— */

.price-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-sm);
}

.price-table th {
  font-family: var(--sans);
  font-size: var(--t-xs);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  text-align: start;
  padding: 0 var(--s-3) var(--s-2) 0;
  border-bottom: 1px solid var(--ink);
}

.price-table td {
  padding: var(--s-2) var(--s-3) var(--s-2) 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

/* ————— Opening hours (site/contact.php) ————— */

.hours-list { display: grid; gap: .3rem; margin-top: var(--s-2); max-width: 20rem; }
.hours-list > div { display: flex; justify-content: space-between; gap: var(--s-3); font-size: var(--t-sm); }
.hours-list dt { color: var(--ink-soft); }
.hours-list dd { margin: 0; color: var(--ink); }

/* ————— Horizontally scrollable tables —————
   A table wider than a phone was already contained by `overflow-x:auto`, so
   nothing overflowed the page and every document-level probe read clean — but
   the clipping had NO affordance: no scrollbar on iOS, no fade, no hint. A
   patient simply never learned the "Before flying" column existed. Measured
   2026-09-24: 174px hidden on the journey table in all five languages, 258px
   and 270px on the nl/ru cookie tables.

   The fade is painted with two background layers: an opaque "cover" pinned to
   each edge that scrolls with the box, and a shadow that does not — so the
   shadow only shows on the side where content is actually hidden, and
   disappears on its own once scrolled to the end. No JS, no scroll listener. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  background:
    linear-gradient(to right, var(--bone) 30%, transparent) left center / 3rem 100% no-repeat local,
    linear-gradient(to left,  var(--bone) 30%, transparent) right center / 3rem 100% no-repeat local,
    radial-gradient(farthest-side at 0, rgba(20,18,13,.20), transparent) left center / 1.1rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100%, rgba(20,18,13,.20), transparent) right center / 1.1rem 100% no-repeat scroll;
}

/* The box is keyboard-scrollable (tabindex on the element), so it must show a
   focus ring like any other focusable thing. */
.table-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* On a --sand section the cover must match THAT surface or the fade paints a
   pale stripe over a darker background. */
.section--sand .table-scroll {
  background:
    linear-gradient(to right, var(--bone-2) 30%, transparent) left center / 3rem 100% no-repeat local,
    linear-gradient(to left,  var(--bone-2) 30%, transparent) right center / 3rem 100% no-repeat local,
    radial-gradient(farthest-side at 0, rgba(20,18,13,.20), transparent) left center / 1.1rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100%, rgba(20,18,13,.20), transparent) right center / 1.1rem 100% no-repeat scroll;
}

/* CMS tables come from rich text and cannot be wrapped in the markup, so
   site.js wraps them at runtime. This keeps them sane if JS never runs. */
.prose table { width: 100%; border-collapse: collapse; }
