/* =========================================================================
   ALCHEMY DETAILING — styles
   Palette: deep charcoal base · warm gold accent · off-white neutrals
   Mobile-first, tested down to ~360px.
   ========================================================================= */

:root {
  --ink: #17140f;          /* near-black charcoal */
  --ink-soft: #24201a;
  --ink-2: #2e2922;
  --ink-raised: #38322a;   /* one tonal step above --ink-2: hover on dark panels */
  --gold: #c9a24b;
  --gold-bright: #e0bc66;
  /* The on-light gold. Every use of this token sits on --paper or #fff, so it
     is struck down until it clears 4.5:1 on both (5.13:1 and 5.63:1). The old
     #a5823c measured 3.27:1 on paper — it looked like gold and read as haze.
     Same hue family, same warmth; assayed rather than raw. */
  --gold-deep: #806326;
  --paper: #f7f4ee;        /* off-white */
  --text-on-paper: #2b261f;
  --muted-on-paper: #6b6357;
  --text-on-ink: #f1ece1;
  --muted-on-ink: #b3aa99;
  /* Validation. An oxidized red rather than a signal red: warm enough to sit
     inside this palette (red channel above blue, like every other neutral
     here), dark enough to clear 4.5:1 on both #fff and --paper. */
  --danger: #a3341f;
  --danger-wash: #fbf0ec;
  /* The text colour on every gold fill. Never white (fails contrast, reads
     cheap), never pure black (reads cold against a warm accent). */
  --on-gold: #201a10;
  --radius: 14px;
  --shadow: 0 10px 30px rgba(23, 20, 15, 0.12);
  --header-h: 72px;
  --font-head: "Fraunces", Georgia, "Times New Roman", serif;
  --font-body: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;

  /* ----------------------------------------------------------------
     Type scale — six fixed steps and two fluid ones.
     This replaced 27 declared sizes, eighteen of them crowded between
     0.68rem and 1.15rem where consecutive steps differed by as little as
     0.16px. Steps that small are invisible: they cost the reader nothing
     and cost the system its hierarchy. Where two roles now share a size,
     family and weight separate them instead — a Fraunces 600 heading and
     an Inter 400 paragraph at the same size are never confused.
     ---------------------------------------------------------------- */
  --t-micro: 0.75rem;   /* 12px · uppercase labels, tags, badges, eyebrows */
  --t-sm: 0.875rem;     /* 14px · dense secondary: captions, nav, footer, forms */
  --t-base: 1rem;       /* 16px · body, and the floor for anything read at length */
  --t-lead: 1.125rem;   /* 18px · section intros, hero subtitle, prices */
  --t-title: 1.25rem;   /* 20px · card headings */
  --t-numeral: 2rem;    /* 32px · the Fraunces step counters */
  --t-headline: clamp(1.7rem, 4.5vw, 2.5rem);
  --t-display: clamp(2.1rem, 6vw, 3.6rem);
  /* The wordmark is a lockup, not UI text. These two sizes exist so its two
     lines optically match in width; they are exceptions, not scale steps. */
  --t-wordmark: 1.45rem;
  --t-wordmark-sub: 0.62rem;
}

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 12px);
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: 1.65;
  color: var(--text-on-paper);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

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

h1, h2, h3 {
  font-family: var(--font-head);
  font-weight: 600;
  line-height: 1.15;
  margin: 0 0 0.5em;
  letter-spacing: 0.01em;
}

h1 { font-size: var(--t-display); }
h2 { font-size: var(--t-headline); }
h3 { font-size: var(--t-title); }

p { margin: 0 0 1em; }

a { color: var(--gold-deep); }

.container {
  width: min(1120px, 100% - 2.5rem);
  margin-inline: auto;
}

section { padding: clamp(3.5rem, 8vw, 6rem) 0; }

.section-intro {
  max-width: 46rem;
  color: var(--muted-on-paper);
  font-size: var(--t-lead);
  margin-bottom: 2.2rem;
}

.eyebrow {
  display: inline-block;
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-deep);
  margin-bottom: 0.8rem;
}

/* Dark sections */
.section-dark {
  background: linear-gradient(180deg, var(--ink) 0%, var(--ink-soft) 100%);
  color: var(--text-on-ink);
}
.section-dark .section-intro { color: var(--muted-on-ink); }
.section-dark .eyebrow { color: var(--gold); }

/* Uppercase micro-labels are single-line by construction — body's 1.65 leading
   only padded their boxes and pushed the pills off-centre. */
.eyebrow,
.ba-label,
.card-badge,
.gallery-tag,
.ch-label {
  line-height: 1.2;
}

/* Light text on a dark ground blooms: at 15.9:1 the strokes thicken optically
   and the letters crowd, so the same metrics that read well on paper read
   tighter here. A little tracking and a little more leading give the dark
   sections the same rhythm as the light ones. */
.section-dark p,
.hero-subtitle,
.site-footer p {
  letter-spacing: 0.006em;
  line-height: 1.72;
}

/* ------------------------------------------------------------------
   Buttons
------------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.85rem 1.7rem;
  border-radius: 999px;
  border: 1.5px solid transparent;
  font-family: var(--font-body);
  font-size: var(--t-base);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
  min-height: 48px; /* tap-friendly */
}
.btn:active { transform: translateY(1px); }

.btn-gold {
  background: linear-gradient(135deg, var(--gold-bright), var(--gold));
  color: var(--on-gold);
  box-shadow: 0 6px 18px rgba(201, 162, 75, 0.35);
}
.btn-gold:hover { box-shadow: 0 8px 24px rgba(201, 162, 75, 0.5); }

.btn-ghost {
  background: transparent;
  color: var(--text-on-ink);
  border-color: rgba(241, 236, 225, 0.35);
}
.btn-ghost:hover { border-color: var(--gold); color: var(--gold-bright); }

.btn-ghost-dark {
  background: transparent;
  color: var(--ink);
  border-color: rgba(23, 20, 15, 0.3);
}
.btn-ghost-dark:hover { border-color: var(--gold-deep); color: var(--gold-deep); }

/* ------------------------------------------------------------------
   Header
------------------------------------------------------------------ */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: rgba(23, 20, 15, 0.92);
  backdrop-filter: blur(10px);
  transition: box-shadow 0.2s ease;
}
.site-header.is-scrolled { box-shadow: 0 4px 24px rgba(23, 20, 15, 0.4); }

.header-inner {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  width: min(1120px, 100% - 2.5rem);
  margin-inline: auto;
}

/* ------------------------------------------------------------------
   Logo lockup
   Mark + name, used by the header and the footer. The mark is a <use> of the
   #logo-mark symbol declared once in index.html; its letterform and the back
   half of its ribbon are currentColor, so the lockup takes its colour from
   whatever surface it lands on and the gold ribbon stays gold on both.
------------------------------------------------------------------ */
/* The symbol lives in a zero-size <svg> at the top of <body>. Out of flow so
   it cannot occupy a grid row or push the skip link around. */
.svg-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  line-height: 1;
  text-decoration: none;
  margin-right: auto;
  color: var(--text-on-ink);
}
.wordmark-mark {
  height: 2.15rem;
  width: auto;
  flex: none;
}
.wordmark-text {
  display: flex;
  flex-direction: column;
}
.wordmark-main {
  font-family: var(--font-head);
  font-size: var(--t-wordmark);
  font-weight: 600;
  /* The reference lockup sets the name solid, not tracked out — the letter
     spacing lives in the DETAILING line underneath it, where it does the
     work of matching the two lines' widths. */
  letter-spacing: 0.005em;
  color: inherit;
}
.wordmark-sub {
  font-size: var(--t-wordmark-sub);
  font-weight: 600;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--muted-on-ink);
  margin-top: 0.34rem;
  /* Tracking adds a trailing space after the last letter; pulling it back
     keeps the two lines optically flush on the left and right. */
  margin-right: -0.42em;
}

/* The footer lockup is the brand block of the page rather than a nav element,
   so it runs one step larger and keeps its name at every width. */
.wordmark-lg .wordmark-mark { height: 2.7rem; }
.wordmark-lg .wordmark-main { font-size: calc(var(--t-wordmark) * 1.25); }
.wordmark-lg .wordmark-sub { font-size: calc(var(--t-wordmark-sub) * 1.25); }

.site-nav { display: flex; align-items: center; gap: 1.4rem; }
.site-nav a {
  color: var(--text-on-ink);
  text-decoration: none;
  font-size: var(--t-sm);
  font-weight: 500;
}
.site-nav a:hover { color: var(--gold-bright); }
.site-nav .btn { padding: 0.55rem 1.25rem; min-height: 42px; font-size: var(--t-sm); }

/* Language toggle */
.lang-toggle {
  display: inline-flex;
  border: 1px solid rgba(241, 236, 225, 0.25);
  border-radius: 999px;
  overflow: hidden;
}
.lang-toggle button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--muted-on-ink);
  font: 600 var(--t-micro)/1.2 var(--font-body);
  letter-spacing: 0.06em;
  padding: 0.45rem 0.8rem;
  cursor: pointer;
  min-height: 36px;
}
.lang-toggle button.is-active {
  background: var(--gold);
  color: var(--on-gold);
}

/* Mobile nav */
.nav-toggle {
  display: none;
  appearance: none;
  background: transparent;
  border: 0;
  width: 44px;
  height: 44px;
  flex-shrink: 0; /* without this it collapsed to 36px at 320px — a flex item, not a fixed one */
  cursor: pointer;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
}
.nav-toggle span {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--text-on-ink);
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.nav-toggle.is-open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle.is-open span:nth-child(2) { opacity: 0; }
.nav-toggle.is-open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 860px) {
  .nav-toggle { display: flex; }
  .site-nav {
    position: fixed;
    top: var(--header-h);
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--ink);
    padding: 0.6rem 1.25rem 1.2rem;
    box-shadow: 0 20px 30px rgba(23, 20, 15, 0.4);
    display: none;
  }
  .site-nav.is-open { display: flex; }
  .site-nav a {
    padding: 0.85rem 0.25rem;
    border-bottom: 1px solid rgba(241, 236, 225, 0.08);
    font-size: var(--t-base);
  }
  .site-nav .btn { margin-top: 1rem; border-bottom: 0; }
}

/* Phone: the header drops to the mark alone.
   640px rather than the 860px the nav uses, because the two are solving
   different problems — the nav collapses when it runs out of room for six
   links, the name collapses only when the mark, the language switch and the
   menu button start competing, which is a phone-portrait width. Tablets keep
   the full lockup. */
@media (max-width: 640px) {
  /* .site-header .wordmark-text { display: none; } */
  .site-header .wordmark-mark { height: 2.35rem; }
}

/* ------------------------------------------------------------------
   Hero
------------------------------------------------------------------ */
.hero {
  position: relative;
  overflow: hidden;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
  /* Self-hosted fallback surface. The video sits ON TOP of this, so the hero
     is never a bare rectangle: this shows while the video loads, if the CDN
     fails or is blocked, and when prefers-reduced-motion removes the video.
     Swap hero-fallback.svg for a real photo when one exists. */
  background: var(--ink) url("../assets/hero-fallback.svg") center / cover no-repeat;
  color: var(--text-on-ink);
  padding-top: calc(var(--header-h) + clamp(2.5rem, 7vw, 5rem));
  padding-bottom: clamp(3rem, 8vw, 5.5rem);
}
.hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(23, 20, 15, 0.72) 0%,
    rgba(23, 20, 15, 0.45) 45%,
    rgba(23, 20, 15, 0.88) 100%);
}
.hero-content {
  position: relative;
  z-index: 1;
  max-width: 44rem;
}
/* No `.gold` span rule here: the headline is written by applyLang() via
   textContent, which erases child elements on every language switch. Any
   per-word colouring would need the i18n layer to carry markup — a different
   decision, not a style one. */
.hero h1 { color: #fff; }
.hero-subtitle {
  font-size: var(--t-lead);
  color: var(--muted-on-ink);
  max-width: 34rem;
  margin-bottom: 1.8rem;
}
.hero-ctas { display: flex; flex-wrap: wrap; gap: 0.9rem; }

/* Landscape phones.
   The hero sized itself from the wide axis: padding-top is
   calc(header + 7vw), which at 740px wide reserves 124px — inside a viewport
   only 360px tall. The hero rendered 454px against a 360px screen and both
   CTAs ended up behind the fixed action bar, so the primary conversion button
   was invisible on load. Here height is the scarce axis, so the display size
   is driven by vh and the padding collapses to what the header actually needs. */
@media (orientation: landscape) and (max-height: 520px) {
  .hero {
    min-height: auto;
    padding-top: calc(var(--header-h) + 1.25rem);
    padding-bottom: 1.5rem;
  }
  /* Built from existing steps rather than new numbers: the title step is the
     floor, the numeral step the ceiling, and 7vh moves between them. A landscape
     hero is a different size, not a different scale. */
  .hero h1 {
    font-size: clamp(var(--t-title), 7vh, var(--t-numeral));
    margin-bottom: 0.35em;
  }
  .hero-subtitle {
    font-size: var(--t-base);
    margin-bottom: 1rem;
  }
}

/* ------------------------------------------------------------------
   Before/After reveal slider
------------------------------------------------------------------ */
.ba-slider {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  aspect-ratio: 4 / 3;
  user-select: none;
  touch-action: pan-y; /* vertical page scroll still works on touch */
  cursor: ew-resize;
  box-shadow: var(--shadow);
  background: var(--ink-2);
}
.ba-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.ba-after-wrap {
  position: absolute;
  inset: 0;
  clip-path: inset(0 50% 0 0);
}
.ba-after-wrap .ba-img { position: absolute; }

.ba-label {
  position: absolute;
  top: 0.8rem;
  z-index: 3;
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.32rem 0.7rem;
  border-radius: 999px;
  pointer-events: none;
}
.ba-label-before {
  right: 0.8rem;
  background: rgba(23, 20, 15, 0.72);
  color: #d8d2c6;
}
.ba-label-after {
  left: 0.8rem;
  background: rgba(201, 162, 75, 0.92);
  color: var(--on-gold);
}

.ba-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 0;
  z-index: 4;
  outline-offset: 4px;
}
.ba-handle-line {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -1.5px;
  width: 3px;
  background: #fff;
  box-shadow: 0 0 12px rgba(23, 20, 15, 0.45);
}
.ba-handle-knob {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translate(-50%, -50%);
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--gold);
  color: var(--on-gold);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 14px rgba(23, 20, 15, 0.4);
  transition: transform 0.12s ease;
}
.ba-slider.is-dragging .ba-handle-knob,
.ba-handle:focus-visible .ba-handle-knob {
  transform: translate(-50%, -50%) scale(1.08);
}
.ba-handle:focus-visible .ba-handle-line { background: var(--gold-bright); }

/* ------------------------------------------------------------------
   How it works
------------------------------------------------------------------ */
.steps {
  display: grid;
  gap: 1.2rem;
  counter-reset: step;
}
@media (min-width: 760px) { .steps { grid-template-columns: repeat(3, 1fr); gap: 1.6rem; } }

.step {
  background: #fff;
  border-radius: var(--radius);
  padding: 1.8rem 1.5rem;
  box-shadow: var(--shadow);
  counter-increment: step;
}
.step::before {
  content: counter(step, decimal-leading-zero);
  display: block;
  font-family: var(--font-head);
  font-size: var(--t-numeral);
  font-weight: 500; /* Fraunces ships 500 and 600 here; 400 only exists in the fallback */
  color: var(--gold);
  margin-bottom: 0.6rem;
}
.step h3 { margin-bottom: 0.35rem; }
.step p { color: var(--muted-on-paper); margin: 0; }

/* ------------------------------------------------------------------
   Service cards
------------------------------------------------------------------ */
.cards {
  display: grid;
  gap: 1.2rem;
}
@media (min-width: 760px) { .cards-3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 760px) { .cards-4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .cards-4 { grid-template-columns: repeat(4, 1fr); } }

.service-card {
  position: relative;
  background: #fff;
  border-radius: var(--radius);
  padding: 1.8rem 1.5rem 1.5rem;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  border-top: 3px solid var(--gold);
}
.section-dark .service-card {
  background: var(--ink-2);
  color: var(--text-on-ink);
}
.section-dark .service-card p { color: var(--muted-on-ink); }
.service-card h3 { margin-bottom: 0.4rem; }
.service-card p { color: var(--muted-on-paper); flex-grow: 1; }
/* Fraunces is loaded at 500 and 600 only. Leaving these at the inherited 400
   made the browser clamp to 500 anyway on the variable font — but the moment
   Fraunces fails to load, Georgia renders at a genuine 400 and the price
   suddenly reads lighter than it was designed to. Declare what we mean. */
.service-price {
  font-family: var(--font-head);
  font-size: var(--t-lead);
  font-weight: 500;
  color: var(--gold-deep);
  margin-top: 0.6rem;
}
.section-dark .service-price { color: var(--gold-bright); }

.card-badge {
  position: absolute;
  top: -0.85rem;
  right: 1rem;
  background: var(--gold);
  color: var(--on-gold);
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
}

/* The aside that lists add-ons. This used to carry a 3px gold left-rule —
   the side-tab callout, which is one of the most recognisable tells of a
   generated interface. The aside still needs to read as subordinate to the
   cards above it, so the job now falls to a hairline plus indent: quieter,
   and the gold stays a hairline rather than a slab. */
.addons-note {
  margin-top: 1.6rem;
  /* Measured at 117 characters across before this cap — nearly double a
     comfortable line. The eye loses its place returning to the left edge. */
  max-width: 46rem;
  font-size: var(--t-base);
  color: var(--muted-on-paper);
  border-left: 1px solid var(--gold-deep);
  padding-left: 1.1rem;
}
.section-dark .addons-note {
  color: var(--muted-on-ink);
  border-left-color: var(--gold);
}

.after-block-cta { margin-top: 2rem; }

/* ------------------------------------------------------------------
   Gallery
------------------------------------------------------------------ */
.gallery-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 1.8rem;
}
.gallery-filters button {
  appearance: none;
  border: 1.5px solid rgba(241, 236, 225, 0.3);
  background: transparent;
  color: var(--text-on-ink);
  font: 600 var(--t-sm)/1.2 var(--font-body);
  padding: 0.5rem 1.2rem;
  border-radius: 999px;
  cursor: pointer;
  min-height: 42px;
}
.gallery-filters button.is-active {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--on-gold);
}

.gallery-featured {
  display: grid;
  gap: 1.4rem;
  margin-bottom: 1.4rem;
}
@media (min-width: 860px) {
  .gallery-featured { grid-template-columns: repeat(3, 1fr); }
  .gallery-featured .gallery-card:first-child { grid-column: 1 / -1; }
  .gallery-featured .gallery-card:first-child .ba-slider { aspect-ratio: 21 / 9; }
}

.gallery-grid {
  display: grid;
  gap: 1.4rem;
}
@media (min-width: 640px) { .gallery-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .gallery-grid { grid-template-columns: repeat(3, 1fr); } }

.gallery-card { margin: 0; }
.gallery-caption {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.7rem;
  font-size: var(--t-sm);
  color: var(--muted-on-ink);
}
.gallery-caption > span:last-child { min-width: 0; overflow-wrap: break-word; }
.gallery-tag {
  flex-shrink: 0;
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold);
  border: 1px solid rgba(201, 162, 75, 0.5);
  border-radius: 999px;
  padding: 0.18rem 0.6rem;
}

/* ------------------------------------------------------------------
   Why Alchemy
------------------------------------------------------------------ */
.why-grid { display: grid; gap: 1.2rem; }
@media (min-width: 640px) { .why-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .why-grid { grid-template-columns: repeat(4, 1fr); } }

.why-item {
  background: #fff;
  border-radius: var(--radius);
  padding: 1.6rem 1.4rem;
  box-shadow: var(--shadow);
}
.why-item h3 { font-size: var(--t-base); margin-bottom: 0.35rem; }
.why-item p { color: var(--muted-on-paper); margin: 0; font-size: var(--t-base); }
.why-icon {
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: rgba(201, 162, 75, 0.15);
  color: var(--gold-deep);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.9rem;
}

/* ------------------------------------------------------------------
   Pricing
------------------------------------------------------------------ */
.pricing-grid { display: grid; gap: 2rem; }
@media (min-width: 900px) { .pricing-grid { grid-template-columns: 1fr 1fr; } }

.pricing-table {
  background: var(--ink-2);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}
.pricing-table h3 {
  margin: 0;
  padding: 1.1rem 1.4rem;
  background: rgba(201, 162, 75, 0.12);
  color: var(--gold-bright);
  font-size: var(--t-lead);
  letter-spacing: 0.04em;
}
.pricing-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.95rem 1.4rem;
  border-top: 1px solid rgba(241, 236, 225, 0.07);
}
/* min-width: 0 lets the name wrap instead of forcing the row wider than the
   panel. Romanian service names already run long, and EN/RO swaps change
   their length under the visitor's feet. */
.pricing-row .name { font-weight: 500; min-width: 0; overflow-wrap: break-word; }
/* The price outranks its row label, so it takes the lead step while the name
   stays at body. They share a baseline, so the size difference reads as
   emphasis rather than misalignment. */
.pricing-row .price {
  font-family: var(--font-head);
  font-size: var(--t-lead);
  font-weight: 500;
  color: var(--gold-bright);
  white-space: nowrap;
  flex-shrink: 0;
}
.pricing-cta-wrap { text-align: center; margin-top: 2.4rem; }

/* ------------------------------------------------------------------
   Service area
------------------------------------------------------------------ */
.area-grid { display: grid; gap: 1.2rem; margin-top: 1.6rem; }
@media (min-width: 700px) { .area-grid { grid-template-columns: 1fr 1fr; } }
.area-card {
  background: #fff;
  border-radius: var(--radius);
  padding: 1.6rem 1.4rem;
  box-shadow: var(--shadow);
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}
.area-card h3 { font-size: var(--t-base); margin-bottom: 0.3rem; }
.area-card p { margin: 0; color: var(--muted-on-paper); font-size: var(--t-base); }
.area-icon {
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: rgba(201, 162, 75, 0.15);
  color: var(--gold-deep);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Reviews: intentionally absent. See the note in index.html — there are no
   real customers to quote yet, and invented testimonials are both unlawful
   in the EU and corrosive to the one claim this page can actually prove. */

/* ------------------------------------------------------------------
   FAQ
------------------------------------------------------------------ */
.faq-list { max-width: 46rem; }
.faq-item {
  background: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 0.8rem;
  overflow: hidden;
}
.faq-item summary {
  list-style: none;
  cursor: pointer;
  padding: 1.1rem 3rem 1.1rem 1.4rem;
  font-weight: 600;
  position: relative;
  min-height: 48px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+";
  position: absolute;
  right: 1.3rem;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-head);
  font-size: var(--t-title);
  color: var(--gold-deep);
  transition: transform 0.2s ease;
}
.faq-item[open] summary::after { transform: translateY(-50%) rotate(45deg); }
.faq-item .faq-answer {
  padding: 0 1.4rem 1.2rem;
  color: var(--muted-on-paper);
}

/* ------------------------------------------------------------------
   Contact
------------------------------------------------------------------ */
.contact-grid { display: grid; gap: 2.5rem; }
@media (min-width: 900px) { .contact-grid { grid-template-columns: 1fr 1.15fr; } }

.contact-channels { display: flex; flex-direction: column; gap: 0.9rem; margin: 1.6rem 0; }
.contact-channel {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  background: var(--ink-2);
  border-radius: var(--radius);
  padding: 1rem 1.2rem;
  color: var(--text-on-ink);
  text-decoration: none;
  font-weight: 500;
  transition: background 0.15s ease;
}
.contact-channel:hover { background: var(--ink-raised); }
/* The email address is one long unbreakable token at 360px. Let it break
   rather than push the card past the viewport. */
.contact-channel > span:last-child { min-width: 0; overflow-wrap: anywhere; }
.contact-channel .ch-icon {
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: rgba(201, 162, 75, 0.16);
  color: var(--gold-bright);
  display: flex;
  align-items: center;
  justify-content: center;
}
.contact-channel .ch-label {
  display: block;
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-on-ink);
}

.availability-note {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--gold-bright);
  font-size: var(--t-base);
}

/* Form */
.contact-form {
  background: #fff;
  color: var(--text-on-paper);
  border-radius: var(--radius);
  padding: 1.8rem 1.5rem;
  box-shadow: var(--shadow);
}
.form-note {
  font-size: var(--t-sm);
  color: var(--muted-on-paper);
  margin: 0 0 1.2rem;
}
.form-field { margin-bottom: 1.1rem; }
.form-field label {
  display: block;
  font-size: var(--t-sm);
  font-weight: 600;
  margin-bottom: 0.35rem;
}
.form-field .req {
  color: var(--gold-deep);
  margin-left: 0.15em;
}
.form-field input,
.form-field select,
.form-field textarea {
  width: 100%;
  padding: 0.75rem 0.9rem;
  border: 1.5px solid #d8d1c4;
  border-radius: 10px;
  font: 400 var(--t-base)/1.5 var(--font-body);
  color: var(--text-on-paper);
  background: var(--paper);
}
/* Struck Gold, not Transmuted: the field sits on white, where --gold measures
   2.40:1 and misses the 3:1 an indicator needs. Same Two Grounds Rule as text. */
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  outline: 2px solid var(--gold-deep);
  outline-offset: 1px;
  border-color: var(--gold-deep);
}
.form-field textarea { resize: vertical; min-height: 110px; }
.form-field input[type="file"] { padding: 0.6rem; background: #fff; }
.contact-form .btn { width: 100%; }

/* Field help + validation.
   Errors are red-brown rather than pure red: warm enough to sit inside this
   palette, dark enough to clear 4.5:1 on both white and paper. */
.form-hint {
  font-size: var(--t-sm);
  color: var(--muted-on-paper);
  margin: 0.35rem 0 0;
}
.form-error {
  display: flex;
  align-items: flex-start;
  gap: 0.4rem;
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--danger);
  margin: 0.4rem 0 0;
}
.form-error::before {
  content: "!";
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.05rem;
  height: 1.05rem;
  margin-top: 0.12rem;
  border-radius: 50%;
  background: var(--danger);
  color: #fff;
  font-size: var(--t-micro);
  font-weight: 700;
}
.form-field [aria-invalid="true"] {
  border-color: var(--danger);
  background: var(--danger-wash);
}
.form-field [aria-invalid="true"]:focus {
  outline-color: var(--danger);
  border-color: var(--danger);
}
/* Submit lock: the request is in flight, the button says so and cannot fire twice. */
.contact-form .btn[aria-busy="true"] {
  pointer-events: none;
  opacity: 0.72;
}

/* ------------------------------------------------------------------
   Footer
------------------------------------------------------------------ */
.site-footer {
  background: #100d09;
  color: var(--muted-on-ink);
  padding: 3rem 0 2rem;
  font-size: var(--t-sm);
}
.footer-grid {
  display: grid;
  gap: 1.8rem;
  margin-bottom: 2rem;
}
@media (min-width: 760px) { .footer-grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.footer-heading {
  color: var(--text-on-ink);
  font: 600 var(--t-micro)/1.2 var(--font-body);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin: 0 0 0.8rem;
}
.site-footer a { color: var(--muted-on-ink); text-decoration: none; }
.site-footer a:hover { color: var(--gold-bright); }
/* The lockup is a logo, not a footer link: it keeps its own colour, and its
   hover must not repaint the letterform gold on top of the gold ribbon. */
.site-footer a.wordmark,
.site-footer a.wordmark:hover { color: var(--text-on-ink); }
.footer-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.2rem; }
/* These links measured 18px tall, under the 24x24 minimum, because an inline
   anchor reports its font box rather than its line box. Making the anchor a
   block gives it the full line, and the padding gives it room to be hit. */
.footer-list a { display: block; padding-block: 0.35rem; }
.footer-bottom {
  border-top: 1px solid rgba(241, 236, 225, 0.08);
  padding-top: 1.4rem;
  text-align: center;
  font-size: var(--t-sm);
}

/* ------------------------------------------------------------------
   Sticky mobile action bar
------------------------------------------------------------------ */
.mobile-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: none;
  grid-template-columns: 1fr 1fr 1.3fr;
  gap: 1px;
  background: rgba(241, 236, 225, 0.12);
  border-top: 1px solid rgba(241, 236, 225, 0.12);
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.mobile-bar a {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  min-height: 56px;
  background: var(--ink);
  color: var(--text-on-ink);
  text-decoration: none;
  font-size: var(--t-sm);
  font-weight: 600;
}
.mobile-bar a.bar-quote { background: var(--gold); color: var(--on-gold); }
/* 860px, not 760px — the same number the desktop nav appears at.
   They used to disagree, which left 761–860px with no persistent contact
   affordance at all: the thumb bar had gone but the nav had not arrived, so
   the header held only a wordmark, a language switch and a hamburger. That
   band is iPad-mini portrait and most Android tablets. The bar now hands over
   to the nav on exactly the pixel the nav takes the job. */
@media (max-width: 860px) {
  .mobile-bar { display: grid; }
  body { padding-bottom: 60px; }
}

/* ------------------------------------------------------------------
   Utilities / a11y
------------------------------------------------------------------ */
/* ------------------------------------------------------------------
   Coarse pointers
   Screen width does not tell you how the page is being touched: a laptop can
   have a touchscreen and a tablet can have a trackpad. These sizes are keyed
   to the input device instead. Everything here already cleared WCAG's 24px
   minimum; this lifts the remaining controls to the 44px that thumbs actually
   want, and only for the people using thumbs.
------------------------------------------------------------------ */
@media (pointer: coarse) {
  .lang-toggle button { min-height: 44px; padding-inline: 1rem; }
  .gallery-filters button { min-height: 44px; }
  .footer-list a { padding-block: 0.6rem; }
  .faq-item summary { padding-block: 1.3rem; }
}

/* ------------------------------------------------------------------
   Focus
   One ring for the whole site, obeying The Two Grounds Rule: Struck Gold
   on light (5.13:1 on paper), Kindled Gold on dark (10.11:1 on ink). Before
   this, only the slider had a designed focus state and everything else fell
   back to the browser's ring — which is a different colour in every browser
   and can vanish against gold. `:where()` keeps specificity at zero so any
   component can still override it.
------------------------------------------------------------------ */
:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--gold-deep);
  outline-offset: 3px;
}
:where(.section-dark, .hero, .site-header, .site-footer, .mobile-bar, .noscript-note)
  :where(a, button, summary, [tabindex]):focus-visible {
  outline-color: var(--gold-bright);
}
/* The ground is the nearest surface, not the nearest section. The contact form
   is a white card inside a dark section, so everything in it flips back to the
   light ring — Kindled Gold on white measures 1.82:1. This is the system's only
   light island on a dark ground; a second one would need the same line. */
.contact-form :where(a, button, summary, [tabindex]):focus-visible {
  outline-color: var(--gold-deep);
}

/* Three controls live inside an `overflow: hidden` parent (the pill that makes
   the language toggle seamless, the panel that rounds the FAQ item, the frame
   that clips the slider). An outset ring on those is drawn and then cut off,
   which is worse than no ring at all — so theirs is drawn inside instead. */
.lang-toggle button:focus-visible,
.faq-item summary:focus-visible {
  outline-offset: -3px;
}
/* The mobile bar's cells butt against each other and against the bottom of the
   viewport, so an outset ring is drawn over its neighbours and over whatever
   page content happens to be scrolling behind. Inset keeps it on its own cell. */
.mobile-bar a:focus-visible { outline-offset: -3px; }

/* An inset ring is painted on the element's own fill, not on the ground behind
   it — and both the selected language and the quote cell sit on Transmuted
   Gold, where Kindled Gold measures 1.3:1. On gold, the ring obeys the Ink
   Floor Rule like any other mark on gold. */
.lang-toggle button.is-active:focus-visible,
.mobile-bar a.bar-quote:focus-visible { outline-color: var(--on-gold); }
/* The handle is a zero-width divider: at offset 0 the ring resolves to a gold
   line along the split, reinforcing the affordance it belongs to. Its knob
   scale and line brightening still carry most of the signal. */
.ba-handle:focus-visible { outline-offset: 0; }

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

/* Skip link: ten sections behind a fixed header is a long tab-through.
   Off-screen until focused, then lands as a gold pill under the header. */
.skip-link {
  position: fixed;
  top: 0;
  left: 50%;
  z-index: 100;
  transform: translate(-50%, -120%);
  padding: 0.75rem 1.5rem;
  border-radius: 0 0 var(--radius) var(--radius);
  background: var(--gold);
  color: var(--on-gold);
  font-weight: 600;
  text-decoration: none;
  box-shadow: 0 6px 18px rgba(201, 162, 75, 0.35);
  transition: transform 0.18s ease;
}
/* :focus, not :focus-visible — a skip link is only ever reached by keyboard,
   and :focus-visible heuristics can withhold the style on programmatic focus. */
.skip-link:focus {
  transform: translate(-50%, 0);
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
/* #top receives focus after the skip; it must never draw a ring around the
   whole page. The skip already moved the user — that is the feedback. */
main:focus { outline: none; }

/* Shown only inside <noscript> (see the head of index.html). */
.noscript-note {
  display: none;
  margin: 0;
  padding: calc(var(--header-h) + 1rem) 1.25rem 1rem;
  background: var(--ink-2);
  color: var(--text-on-ink);
  text-align: center;
  font-size: var(--t-base);
}
.noscript-note a { color: var(--gold-bright); }

/* Gallery empty state: a filter matched nothing, or no transformation has
   real photos yet. Quiet by design — an empty gallery is not an error. */
.gallery-empty {
  margin: 0;
  padding: 2.5rem 1.25rem;
  border: 1.5px dashed rgba(241, 236, 225, 0.22);
  border-radius: var(--radius);
  color: var(--muted-on-ink);
  text-align: center;
}

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

  /* Reduce motion, not feedback. Movement and looping playback go; colour,
     border and shadow transitions stay, so hover, focus and the FAQ marker
     still respond. A blanket `transition: none` would make the interface
     feel broken rather than calm. */
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-property: color, background-color, border-color, box-shadow, opacity, outline-color !important;
    transition-duration: 0.15s !important;
    scroll-behavior: auto !important;
  }

  /* The video is the motion. Removing it reveals the self-hosted fallback
     surface painted on .hero, so the headline still sits on a designed field. */
  .hero-video { display: none; }
}
