/* ============================================================================
   Decorum Events — design system
   Brand values sampled from the client's own artwork, never invented.
   Palette : cream #f3eae5 ; metallic gold #9f7239 → #a4773d → #b18547 → #fbce86
   Faces   : Chequers Regular (display) · Perpetua Titling MT Light (titling)
   Language: Editorial Luxury. Generous whitespace, concentric "double bezel"
             enclosures, hairline gold rules, spring-like motion.
   ========================================================================= */

/* ---------- fonts (self-hosted, per brand guidelines) ---------------------- */
@font-face {
  font-family: "Chequers";
  src: url("../fonts/chequers-regular.woff2?v=18ca0388") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Perpetua Titling";
  src: url("../fonts/perpetua-titling-mt-light.woff2?v=396e1a69") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
/* Body face — the client chose Spectral (concept B2). The brand supplies only two
   capitals-only display faces, so neither can set a paragraph in sentence case.
   Self-hosted, SIL OFL — licence beside the file at assets/fonts/Spectral-OFL.txt.
   ebgaramond-variable.ttf is still on disk as a swap-in alternative but is deliberately
   NOT declared here: an unreferenced @font-face would ship ~850KB for nothing. */
@font-face {
  font-family: "Spectral";
  src: url("../fonts/spectral-regular.woff2?v=80cc48c0") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ---------- tokens -------------------------------------------------------- */
:root {
  /* the light theme is the default; the dark theme below sets color-scheme: dark */
  color-scheme: light;

  /* brand */
  --cream: #f3eae5;
  --cream-raise: #f9f3ef;
  --cream-deep: #e9dcd4;
  --gold-deep: #9f7239;
  /* Small caps at label size need genuine contrast. Measured on the cream pill:
     --gold 3.26:1 and --gold-deep 3.49:1, both below the 4.5:1 that text this small
     requires. This deeper bronze measures 5.39:1 and still reads as gold.
     Verified by tools/contrast_check.py — re-run it if the palette ever changes. */
  --gold-text: #7d5522;
  --gold: #a4773d;
  --gold-mid: #b18547;
  --gold-soft: #c9a25f;
  --gold-light: #e8c184;
  --gold-sheen: #fbce86;
  --gold-white: #fef6eb;

  /* ink */
  --ink: #2b2520;
  --ink-soft: #6d6259;
  --ink-faint: #9a8f85;

  /* error state — gold cannot carry "something is wrong" without reading as decoration,
     so the form gets its own pair. Both values are measured, not guessed. */
  --danger: #8f2f1c;
  --danger-wash: rgba(143, 47, 28, 0.07);

  /* gradients — matches the client's prepared Button asset */
  --grad-gold: linear-gradient(135deg, var(--gold-sheen) 0%, var(--gold-light) 28%, var(--gold-mid) 62%, var(--gold-deep) 100%);
  /* Gold surfaces that carry WHITE glyphs (footer social medallions, nav icon hover).
     White measures 3.31:1 at the light end and 4.73:1 at the deep end, clearing the 3:1
     minimum for non-text UI. The buttons deliberately use the full lighter-to-deeper
     gradient instead, per client direction — see tools/check_gold_contrast.py. */
  --grad-gold-deep: linear-gradient(135deg, var(--gold-mid) 0%, var(--gold-deep) 100%);
  /* The light, glossy ramp the client chose for the kebab button: a wide light-to-deep run at
     160°, so it reads as a gradient rather than as flat metal. Shared with the footer's
     contact medallions and the nav icons' hover on the client's instruction ("anywhere else
     it's like this, replace it with the gradient one like you have used for the kebab"). */
  --grad-gold-gloss: linear-gradient(160deg, #f6dfb8 0%, #dcb268 42%, #b18547 100%);
  /* The kebab ramp's middle stop, on its own. Markers that have to match the gold the client is
     happy with — the selection ring, the focus ring — use this rather than --gold, which is a
     darker, browner gold and reads as "a brown line" beside the gloss gold. */
  --gold-gloss: #dcb268;
  /* The kebab ramp with its dark end removed. The full ramp finishes at #b18547, and on a ring that
     stop shows as a brown line beside the gold the client is happy with ("the brown line is still
     there ... I am happy with the gold one"). Markers use this instead. */
  --grad-gold-marker: linear-gradient(160deg, #f6dfb8 0%, #dcb268 100%);
  --grad-gold-soft: linear-gradient(135deg, #f7ddaa 0%, #dcb377 45%, #b98c4b 100%);
  --grad-cream: linear-gradient(180deg, var(--cream-raise), var(--cream));

  /* hairlines */
  --line: rgba(159, 114, 57, 0.18);
  --line-strong: rgba(159, 114, 57, 0.34);
  --line-soft: rgba(159, 114, 57, 0.10);

  /* elevation — diffuse, warm, never harsh */
  --shadow-ambient: 0 24px 60px -28px rgba(90, 66, 34, 0.28), 0 2px 8px -4px rgba(90, 66, 34, 0.10);
  --shadow-raise: 0 40px 90px -40px rgba(90, 66, 34, 0.34);
  --shadow-inset: inset 0 1px 1px rgba(255, 255, 255, 0.55);

  /* translucent surfaces and button elevation — theme-aware tokens, so no component
     hardcodes a fill. Every one of these is overridden under :root[data-theme="dark"]. */
  --surface-glass-soft: rgba(255, 255, 255, 0.42);   /* bezel frames */
  --surface-glass: rgba(255, 255, 255, 0.5);          /* eyebrow pills */
  --surface-glass-strong: rgba(255, 255, 255, 0.6);   /* ghost button hover */
  --surface-glass-icon: rgba(255, 255, 255, 0.22);    /* icon well in a gold button */
  --surface-nav: rgba(249, 243, 239, 0.72);           /* sticky header */
  --surface-overlay: rgba(249, 243, 239, 0.9);        /* mobile menu — frosted, see .menu */
  /* Liquid glass for the menu surface (client request). Three layers on top of the backdrop
     blur: a translucent base, a specular sheen falling from the top left, and a 1px light
     edge. The base stays well above half-opaque — the blur alone cannot guarantee legible
     navy-on-cream over whatever photograph happens to be behind the overlay. */
  --glass-menu-base: rgba(249, 243, 239, 0.76);
  --glass-menu-sheen: linear-gradient(152deg, rgba(255,255,255,0.62) 0%, rgba(255,255,255,0.16) 32%, rgba(255,255,255,0) 60%);
  --glass-menu-edge: rgba(255,255,255,0.55);
  --glass-menu-glow: rgba(60, 42, 22, 0.22);
  --surface-card: rgba(243, 234, 229, 0.94);          /* band card */
  --tint-gold: rgba(159, 114, 57, 0.06);              /* faint gold wash */
  --switch-off: rgba(43, 37, 32, 0.2);                /* dark-mode switch, off track */
  --shadow-btn: 0 14px 30px -14px rgba(120, 84, 36, 0.6);
  --shadow-btn-hover: 0 22px 44px -16px rgba(120, 84, 36, 0.66);

  /* type */
  --font-display: "Chequers", "Times New Roman", serif;
  --font-titling: "Perpetua Titling", "Perpetua", "Times New Roman", serif;
  /* Client direction: a THIRD face for bodies of text (Spectral, concept B2).
     The two brand faces are capitals-only display faces, so neither can set a
     paragraph in sentence case. Chequers stays confined to the menu bar; the
     titling face keeps headings and labels. */
  --font-text: "Spectral", Georgia, "Times New Roman", serif;

  /* rhythm — density dial is low, so the page breathes */
  --space-section: clamp(5rem, 11vw, 10rem);
  --space-block: clamp(2rem, 4vw, 3.5rem);
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --maxw: 84rem;          /* 1344px content column */
  --maxw-text: 62ch;

  /* radii — concentric */
  --r-shell: 2rem;
  --r-core: calc(2rem - 0.4rem);
  --r-tile: 1.35rem;
  --r-pill: 999px;

  /* motion — never linear, never ease-in-out */
  --ease-spring: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-glide: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-fast: 240ms;
  --dur: 520ms;
  --dur-slow: 820ms;
}

/* ---------- dark theme ----------------------------------------------------- *
 * Overrides the semantic tokens only. Every component reads tokens, so layout, spacing
 * and typography are untouched — this block is the whole dark mode.
 *
 * data-theme is set on <html> by a tiny inline script in each page's <head>, from the
 * stored choice or, failing that, the system preference. That means ONE token set serves
 * both the toggle and prefers-color-scheme: no duplicated declarations, and no flash of
 * the wrong theme. With JavaScript off the attribute is simply absent and the light
 * theme stands (the menu and the toggle need JS anyway).
 *
 * The ground is a warm near-black, not a blue-grey, so it still reads as Decorum rather
 * than as a generic dark skin. Every value was measured with tools/contrast.py —
 * body 15.3:1, secondary 8.8:1, faint labels 5.8:1, small gold caps 10.4:1, ghost-button
 * gold 7.9:1 — all clear of the 4.5:1 small-text floor. */
:root[data-theme="dark"] {
  color-scheme: dark;

  /* surfaces */
  --cream: #17130f;
  --cream-raise: #201a15;
  --cream-deep: #100d0a;

  /* ink */
  --ink: #f2e8de;
  --ink-soft: #c0b0a1;
  --ink-faint: #9c8e7c;
  --danger: #ffb3a1;
  --danger-wash: rgba(255, 179, 161, 0.10);

  /* gold — lifted off the dark ground so small caps stay legible */
  --gold-text: #e0bd85;
  --gold: #d8b478;
  --gold-deep: #cba45a;

  /* hairlines and elevation — gold-tinted rather than grey */
  --line: rgba(224, 189, 133, 0.16);
  --line-strong: rgba(224, 189, 133, 0.32);
  --line-soft: rgba(224, 189, 133, 0.09);
  --shadow-ambient: 0 24px 60px -28px rgba(0, 0, 0, 0.66), 0 2px 8px -4px rgba(0, 0, 0, 0.44);
  --shadow-raise: 0 40px 90px -40px rgba(0, 0, 0, 0.72);
  --shadow-inset: inset 0 1px 1px rgba(255, 255, 255, 0.07);
  --shadow-btn: 0 14px 30px -14px rgba(0, 0, 0, 0.6);
  --shadow-btn-hover: 0 22px 44px -16px rgba(0, 0, 0, 0.66);

  /* translucent surfaces — light washes become faint white ones */
  --surface-glass-soft: rgba(255, 255, 255, 0.03);
  --surface-glass: rgba(255, 255, 255, 0.05);
  --surface-glass-strong: rgba(255, 255, 255, 0.08);
  --surface-glass-icon: rgba(255, 255, 255, 0.14);
  --surface-nav: rgba(23, 19, 15, 0.74);
  --surface-overlay: rgba(17, 14, 11, 0.93);
  --glass-menu-base: rgba(17, 14, 11, 0.78);
  --glass-menu-sheen: linear-gradient(152deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.05) 32%, rgba(255,255,255,0) 60%);
  --glass-menu-edge: rgba(255, 255, 255, 0.16);
  --glass-menu-glow: rgba(0, 0, 0, 0.55);
  --surface-card: rgba(32, 26, 21, 0.94);
  --tint-gold: rgba(224, 189, 133, 0.10);
  --switch-off: rgba(255, 255, 255, 0.18);

  /* The gold gradients are deliberately NOT overridden: they are the brand's, and they
     carry ink or white per the long-standing rule, so buttons look identical in both
     themes and stay legible. */
}

/* Long unbroken strings — social handles, email addresses, URLs — must never burst their
   container. The Instagram handle escaped its tile on /enquire/ and was clipped at the
   card edge. Text-level rule rather than a per-component patch, so the same value is safe
   anywhere it later appears (headings, notes, footer rows). */
h1, h2, h3, .display, .section-title, .lede, .tile__name, .tile__note,
.footer__social-name, .step p {
  overflow-wrap: break-word;
  word-break: break-word;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body, h1, h2, h3, h4, p, figure, blockquote, ul, ol, dl { margin: 0; }
ul[class], ol[class] { list-style: none; padding: 0; }
img, picture, svg { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }

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

body {
  font-family: var(--font-text);
  /* Spectral is a sturdier text face with a larger x-height than a Garamond, so it
     needs a touch less size to sit at the same optical weight */
  font-weight: 400;
  font-size: clamp(1.05rem, 0.5vw + 0.94rem, 1.19rem);
  line-height: 1.64;
  color: var(--ink);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* the single fixed grain layer — never on scrolling containers */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- typography ---------------------------------------------------- */
/* Client direction: Chequers is confined to the menu bar, so the headings use the
   titling face. Perpetua's capitals run wide, so the negative tracking that suited
   the display face would crowd them — hence the small positive values. */
.display {
  font-family: var(--font-titling);
  font-weight: 300;
  line-height: 1.3;
  letter-spacing: 0.025em;
  font-size: clamp(2.6rem, 6.4vw, 5.6rem);
}
.display--md { font-size: clamp(2.1rem, 4.6vw, 3.9rem); line-height: 1.18; }

h2.section-title {
  font-family: var(--font-titling);
  font-weight: 300;
  font-size: clamp(1.9rem, 3.6vw, 3.1rem);
  line-height: 1.2;
  letter-spacing: 0.03em;
}

.eyebrow {
  font-family: var(--font-titling);
  font-weight: 300;
  /* was 0.68rem with 0.34em tracking: too small and too airy for a hairline face */
  font-size: 0.82rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold-text);
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  padding: 0.45em 1em;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--surface-glass);
}
.eyebrow--bare { border: 0; background: none; padding: 0; }

.lede { font-size: 1.12em; color: var(--ink-soft); max-width: var(--maxw-text); }
.text-gold { color: var(--gold); }

/* gold hairline rule with a centred emblem notch */
.rule {
  height: 1px; border: 0; margin: 0;
  background: linear-gradient(90deg, transparent, var(--line-strong) 18%, var(--line-strong) 82%, transparent);
}

/* ---------- layout -------------------------------------------------------- */
.wrap { width: min(100% - (var(--gutter) * 2), var(--maxw)); margin-inline: auto; }
.section { padding-block: var(--space-section); }
.section--tight { padding-block: clamp(3rem, 6vw, 5.5rem); }
.stack > * + * { margin-top: var(--space-block); }
.center { text-align: center; }
.measure { max-width: var(--maxw-text); }

/* ---------- double bezel (nested enclosure) ------------------------------- */
.bezel {
  padding: 0.6rem;
  border-radius: var(--r-shell);
  background: var(--surface-glass-soft);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-ambient);
}
.bezel__core {
  border-radius: var(--r-core);
  overflow: hidden;
  background: var(--cream-raise);
  box-shadow: var(--shadow-inset);
}
.bezel--flush { padding: 0; box-shadow: none; background: none; border: 0; }
.bezel--tall .bezel__core { aspect-ratio: 3 / 4; }
.bezel--wide .bezel__core { aspect-ratio: 16 / 10; }
/* the <picture> wrapper sits between core and img — size it too, or the img
   falls back to intrinsic sizing and the frame crops from the top */
.bezel__core picture { display: block; width: 100%; height: 100%; }
.bezel__core img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- buttons ------------------------------------------------------- */
.btn {
  --btn-bg: var(--grad-gold);
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.95rem 1.15rem 0.95rem 1.7rem;
  border-radius: var(--r-pill);
  background: var(--btn-bg);
  color: #fff;
  font-family: var(--font-titling);
  /* 10% larger on request ("increase the enquire font by 10%"): 0.74rem → 0.814rem, 11.84px → 13.02px.
     Written as a multiple of the original so the intent survives the next reader. */
  font-size: calc(0.74rem * 1.1);
  /* Bold on request. The brand's titling face ships a single cut — Perpetua Titling MT *Light* — and
     licensing for the family is unresolved, so there is no real bold to load. This weight is drawn
     by the browser's synthesis (it thickens each glyph's outline), which is why the same word
     measures identically at 400 and 700 in that face. It is honest about what it is: if it looks
     smeared on the fine serifs, `-webkit-text-stroke` gives a controlled, even weight instead. */
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  box-shadow: var(--shadow-btn), var(--shadow-inset);
  transition: transform var(--dur) var(--ease-spring), box-shadow var(--dur) var(--ease-spring), filter var(--dur) var(--ease-spring);
}@media (hover: hover) {
  .btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-btn-hover), var(--shadow-inset);
  }
}
.btn:active { transform: scale(0.985); }
.btn__icon {
  width: 2.05rem; height: 2.05rem;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  background: var(--surface-glass-icon);
  transition: transform var(--dur) var(--ease-spring);
}@media (hover: hover) {
  .btn:hover .btn__icon { transform: translate(3px, -2px) scale(1.06);
  }
}

.btn--ghost {
  --btn-bg: transparent;
  /* 19 Sep 2026: was --gold-deep (#9f7239, 3.59:1 on cream) — failed WCAG AA for
     text this size. --gold-text is the palette's existing deep bronze (5.54:1). */
  color: var(--gold-text);
  border: 1px solid var(--line-strong);
  box-shadow: none;
  padding: 0.95rem 1.7rem;
}@media (hover: hover) {
  .btn--ghost:hover { background: var(--surface-glass-strong); box-shadow: var(--shadow-ambient);
  }
}

.link-underline {
  font-family: var(--font-titling);
  font-size: 0.8rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--gold-text);
  padding-bottom: 0.25rem;
  background-image: linear-gradient(var(--gold-mid), var(--gold-mid));
  background-size: 100% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size var(--dur) var(--ease-spring), color var(--dur) var(--ease-spring);
}@media (hover: hover) {
  .link-underline:hover { background-size: 0 1px; color: var(--ink);
  }
}

/* ---------- navigation ---------------------------------------------------- */
.skip { position: absolute; left: -9999px; }
.skip:focus { left: 1rem; top: 1rem; z-index: 80; background: var(--cream-raise); padding: 0.6rem 1rem; border-radius: var(--r-pill); }

.nav {
  position: fixed;
  top: 1.4rem; left: 50%;
  transform: translateX(-50%);
  z-index: 40;
  width: min(100% - 2rem, 72rem);
  display: flex; align-items: center; gap: 1rem;
  padding: 1rem 0.6rem 1rem 1.3rem;
  border-radius: var(--r-pill);
  background: var(--surface-nav);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-ambient);
  -webkit-backdrop-filter: blur(18px) saturate(1.1);
  backdrop-filter: blur(18px) saturate(1.1);
  transition: transform var(--dur) var(--ease-spring), opacity var(--dur) var(--ease-spring);
}
.nav__brand { display: flex; align-items: center; gap: 0.8rem; margin-right: auto; }
/* Client direction: a horizontal lockup — the emblem, then the wordmark to its right.
   Both parts are the client's own high-resolution artwork, so the pair scales far
   larger than the old stacked lockup, whose wordmark was tiny at any sane bar height.
   The emblem is a derived asset: tools/build_lockup.py strips the two decorative side
   dots, which only make sense when the wordmark is stacked underneath. */
.nav__emblem { height: 5.2rem; width: auto; }
.nav__wordmark { height: 4rem; width: auto; }
@media (max-width: 61.99rem) {
  .nav__emblem { height: 4.8rem; }
  .nav__wordmark { height: 3.6rem; }
  .nav { padding: 0.7rem 0.5rem 0.7rem 1rem; }
}
.nav__links { display: none; gap: 1.6rem; }
.nav__socials { display: none; }
/* Client direction: the brand's display face carries the navigation, as it does
   the page headings. Chequers is a swashed display serif, so it wants more size
   and less tracking than the titling face it replaces. */
.nav__links a {
  font-family: var(--font-display);
  font-size: 1.06rem;
  letter-spacing: 0.045em;
  line-height: 1.25;
  color: var(--ink-soft);
  transition: color var(--dur-fast) var(--ease-spring);
}@media (hover: hover) {
  .nav__links a:hover, .nav__links a[aria-current="page"] { color: var(--gold-deep);
  }
}

/* Roomy desktop bar (client: "make the menu bar on the desktop version slightly bigger so everything
   is better distributed and fits better"). The row fills the bar exactly at 1152px, so there was no
   slack at all — every gap was as tight as it could be. The bar grows to 75rem (1200px), the space
   between the groups from 1rem to 1.5rem, the space between the links from 1.6rem to 1.8rem, and the
   side padding enough that the logo and the button clear the pill's curves.

   Gated at 80rem because the contents need roughly 1120px: from 992px to 1279px the tighter values
   above still apply, so the row can never overflow or squeeze the logo. */
@media (min-width: 80rem) {
  .nav {
    /* Wider on request ("the width could be wider"), height left alone — the 122px it reached is
       "perfect". 75rem → 80rem (1200px → 1280px); with the flex row sharing the slack, every gap
       grows with it. */
    width: min(100% - 2rem, 80rem);
    gap: 1.5rem;
    padding: 1.15rem 0.8rem 1.15rem 1.6rem;
    /* The brand's `margin-right: auto` on phones is what pushes the hamburger to the far edge — here
       it just dumped all the slack into one hole after the logo, which read as the bar being
       lopsided. Letting the flex row share it instead gives every gap the same rhythm. */
    justify-content: space-between;
  }
  .nav__brand { margin-right: 0; }
  .nav__links { gap: 1.8rem; }
}
.nav__cta { display: none; }
.nav__ig, .nav__wa, .nav__tt { display: none; }

@media (min-width: 62rem) {
  /* The links were a shrinkable flex item, so the row squeezed them to 528px and wrapped "Mendhi &
     Haldi" onto two lines — which is what made the spacing read as uneven in the client's
     screenshot ("fix the spacing of the menu bar"): one item two lines tall, its two lines different
     widths, and the gaps around it looking larger than the rest. They need 534px on one line, and
     the bar is 977px at the narrowest desktop width, so they simply must not shrink. */
  .nav__links, .nav__cta { display: flex; }
  /* The socials as one section (client: "distribute the menu as 4 sections for the desktop version":
     logo · pages · socials · Enquire). Grouped, they are one stretch of the flex row instead of three
     loose items. Hidden below 62rem like the links and the button — the wrapper's own `display: none`
     lives with those, outside this block, so it cannot sit in the mobile row as an empty gap. */
  .nav__socials { display: flex; align-items: center; gap: 0.6rem; }
  .nav__links { flex: 0 0 auto; }
  .nav__links a { white-space: nowrap; }
  .nav__ig, .nav__wa, .nav__tt { display: grid; }
  /* The desktop dark-mode switch is defined at the end of this file — see the block headed
     "desktop floating dark-mode switch". It used to live here, inside this media query, which left
     it with no display rule at all below 62rem: as a <button> it then defaulted to inline-block and
     floated visibly in the mobile nav, where the menu's own switch is the one that should show. */
}

.nav__ig, .nav__wa, .nav__tt {
  width: 3rem; height: 3rem;
  place-items: center;
  border-radius: var(--r-pill);
  color: var(--gold-deep);
  border: 1px solid var(--line);
  transition: color var(--dur-fast) var(--ease-spring), background var(--dur) var(--ease-spring),
              border-color var(--dur) var(--ease-spring);
}@media (hover: hover) {
  .nav__ig:hover, .nav__wa:hover, .nav__tt:hover { color: #fff; background: var(--grad-gold-deep); border-color: transparent;
  }
}

/* ---------- dark-mode switch ------------------------------------------------- *
 * A switch, not a button with a changing label: the track and the sliding knob carry the
 * state, and the label stays fixed at "Dark mode" — which is what a switch means. A label
 * that flipped to "Light mode" while the switch read ON would contradict itself. State
 * reaches assistive tech through aria-checked on a role="switch".
 *
 * It lives in the mobile menu only, on client instruction. Above 62rem the menu is
 * unreachable, so dark mode is a mobile-only affordance by design. */
.theme-switch {
  display: inline-flex; align-items: center; gap: 0.85rem;
  font: inherit; color: inherit;
  background: none; border: 0; padding: 0.3rem 0; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
/* The visible words follow the theme: they name what you would switch TO ("change the text to
   light mode" once dark mode is on). Driven by the attribute rather than by script, so the word is
   correct at first paint even for a visitor whose operating system is dark.

   The button's accessible name deliberately does NOT flip. WAI-ARIA's guidance for a switch is
   explicit that the label describes the setting and stays constant while `aria-checked` carries
   the state; a name that flips announces backwards ("Light mode, on" reads as light mode being
   switched on, which is the opposite of the truth). Hence `aria-label="Dark mode"` in the markup. */
.theme-switch__label-when-dark { display: none; }
:root[data-theme="dark"] .theme-switch__label-when-light { display: none; }
:root[data-theme="dark"] .theme-switch__label-when-dark { display: inline; }

.theme-switch__track {
  position: relative; flex: 0 0 auto;
  width: 3.1rem; height: 1.8rem;
  border-radius: 999px;
  background: var(--switch-off);
  border: 1px solid var(--line-strong);
  transition: background var(--dur-fast) var(--ease-spring), border-color var(--dur-fast) var(--ease-spring);
}
.theme-switch__knob {
  position: absolute; top: 50%; left: 3px;
  width: 1.4rem; height: 1.4rem;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(60, 42, 22, 0.45);
  transform: translateY(-50%);
  transition: transform var(--dur-fast) var(--ease-spring);
}
/* On: the brand's gold gradient, not iOS green — the switch form is iOS, the colour is
   Decorum's. The white knob sits at 3.3:1 against the deep end of this gradient. */
:root[data-theme="dark"] .theme-switch__track {
  background: var(--grad-gold);
  border-color: transparent;
}
:root[data-theme="dark"] .theme-switch__knob {
  transform: translateY(-50%) translateX(1.3rem);
}

/* Kebab menu button: three vertical white dots on the brand's glossy gold.
   The fill is --grad-gold-gloss — the ramp the client asked for, and the reference point for
   "make it look like the kebab menu icon" anywhere else on the site.
   Colour note: the dots are WHITE by explicit request. On this ramp white measures 1.30:1 at
   the lightest stop, 1.98:1 where the dots sit (#dcb268 band) and 3.33:1 at the darkest edge
   (tools/contrast.py) — below the 3:1 an icon needs, so they read faintly in bright daylight.
   Ink dots measured 7.64:1. Changing the two `background: #fff` values below back to
   `var(--ink)` reverts it. */
.nav__toggle {
  margin-left: auto;
  position: relative;
  width: 3rem; height: 3rem;
  border-radius: 50%;
  background: var(--grad-gold-gloss);
  display: grid; place-content: center; gap: 4px;
  box-shadow: 0 6px 14px -6px rgba(120,84,36,.5), inset 0 1px 0 rgba(255,255,255,.6);
}
@media (min-width: 62rem) { .nav__toggle { display: none; } }
.nav__toggle span {
  display: block; width: 4.5px; height: 4.5px; border-radius: 50%; background: #fff;
  transition: transform var(--dur) var(--ease-spring), opacity var(--dur-fast) var(--ease-spring);
}
/* Three dots cannot morph into a cross, so on open the dots cross-fade out while two bars
   fade in as the close X. */
.nav__toggle::before,
.nav__toggle::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 1.15rem; height: 1.5px; background: #fff; border-radius: 2px;
  opacity: 0; transform: rotate(0deg);
  transition: transform var(--dur) var(--ease-spring), opacity var(--dur-fast) var(--ease-spring);
}
.nav[data-open="true"] .nav__toggle span { opacity: 0; }
.nav[data-open="true"] .nav__toggle::before { opacity: 1; transform: rotate(45deg); }
.nav[data-open="true"] .nav__toggle::after { opacity: 1; transform: rotate(-45deg); }

/* full-bleed menu overlay */
.menu {
  position: fixed;
  /* Not `inset: 0`: on iOS the bottom toolbar can sit below the layout viewport, which left
     a strip of page visible under the overlay. The element now runs 14rem past the bottom
     edge so the frosted surface paints over that strip too, and the bottom padding is
     increased by exactly the same 14rem so the content box — and therefore the centring —
     is unchanged. */
  top: 0; left: 0; right: 0; bottom: -14rem;
  z-index: 39;
  display: grid; place-content: center; gap: 0.4rem;
  text-align: center;
  padding: 2rem;
  padding-block: calc(12rem + env(safe-area-inset-top, 0px)) calc(16.5rem + env(safe-area-inset-bottom, 0px));
  /* Headroom for the floating nav bar, and for the switch that sits under it. The overlay
     sits beneath a fixed pill nav, so the content needs real clearance at the top — without
     it the first item ("Nikah") slid under the bar. `safe` centring is what stops the top
     being clipped when the content is taller than the box (plain centring makes the
     overflow unreachable); scrolling covers the genuinely tiny viewports. */
  align-content: safe center;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Liquid glass: a translucent base, a specular sheen, and a wider, more saturated blur than
     the plain frost this started as. `brightness(1.04)` keeps the base from going muddy over a
     dark photograph. */
  background-color: var(--glass-menu-base);
  background-image: var(--glass-menu-sheen);
  box-shadow: inset 0 1px 0 var(--glass-menu-edge), 0 30px 80px var(--glass-menu-glow);
  -webkit-backdrop-filter: blur(60px) saturate(1.8) brightness(1.04);
  backdrop-filter: blur(60px) saturate(1.8) brightness(1.04);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur) var(--ease-spring), visibility var(--dur);
}
.menu[data-open="true"] { opacity: 1; visibility: visible; }
.menu a {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 8vw, 3rem);
  color: var(--ink);
  opacity: 0; transform: translateY(2.5rem);
  transition: opacity var(--dur-slow) var(--ease-spring), transform var(--dur-slow) var(--ease-spring), color var(--dur) var(--ease-spring);
}
.menu[data-open="true"] a { opacity: 1; transform: none; }
/* One stagger for the whole stack, in document order. The switch is the first child now,
   so every delay is expressed as a plain nth-child rather than tying them to the links. */
.menu[data-open="true"] > *:nth-child(1) { transition-delay: 60ms; }
.menu[data-open="true"] > *:nth-child(2) { transition-delay: 105ms; }
.menu[data-open="true"] > *:nth-child(3) { transition-delay: 150ms; }
.menu[data-open="true"] > *:nth-child(4) { transition-delay: 195ms; }
.menu[data-open="true"] > *:nth-child(5) { transition-delay: 240ms; }
.menu[data-open="true"] > *:nth-child(6) { transition-delay: 285ms; }
.menu[data-open="true"] > *:nth-child(7) { transition-delay: 330ms; }
.menu[data-open="true"] > *:nth-child(8) { transition-delay: 375ms; }
.menu[data-open="true"] > *:nth-child(9) { transition-delay: 420ms; }
.menu[data-open="true"] > *:nth-child(10) { transition-delay: 465ms; }@media (hover: hover) {
  .menu[data-open="true"] a:hover { color: var(--gold-deep);
  }
}
.menu a.menu__meta {
  font-family: var(--font-titling);
  font-size: 0.85rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-text);
  margin-top: 1.4rem;
  /* the logo leads and the text follows, centred as a unit */
  display: flex; align-items: center; justify-content: center; gap: 0.6em;
}
/* Genuine network marks, drawn in the current colour so they take the meta gold. Sized in
   rem rather than em so they stay the same size next to the small-caps text. */
.menu__mark { flex: 0 0 auto; display: grid; place-items: center; width: 1rem; height: 1rem; }
.menu__mark svg { width: 100%; height: 100%; }@media (hover: hover) {
  .menu a.menu__meta:hover { color: var(--gold-deep);
  }
}

/* The switch sits at the top right of the overlay, directly beneath the kebab button,
   rather than inside the centred stack. Measured against the real bar: the kebab's right
   edge is 25px from the viewport edge and the pill ends 124px down, so `right` puts the
   track under the kebab and `top` clears the pill. Positioned absolutely because the stack
   below is centred — in that flow the switch drifts with the content height instead of
   staying put. The menu's top padding reserves its space. */
.menu .theme-switch {
  position: absolute;
  top: calc(8.5rem + env(safe-area-inset-top, 0px));
  right: calc(1.5625rem + env(safe-area-inset-right, 0px));
  /* same face as the desktop box and the menu links beside it — see the .nav__theme rule */
  font-family: var(--font-display);
  font-size: 0.85rem; letter-spacing: 0.045em; line-height: 1.2; text-transform: uppercase;
  color: var(--gold-text);
  border: 0;
  opacity: 0; transform: translateY(2.5rem);
  transition: opacity var(--dur-slow) var(--ease-spring), transform var(--dur-slow) var(--ease-spring), color var(--dur) var(--ease-spring);
}
.menu[data-open="true"] .theme-switch { opacity: 1; transform: none; }@media (hover: hover) {
  .menu .theme-switch:hover { color: var(--gold-deep);
  }
}

/* Short viewports (and phones whose browser chrome eats the height): tighten the stack so
   the whole menu fits without scrolling. Only the vertical rhythm changes — the display
   face stays large enough to carry the page. */
@media (max-height: 740px) {
  .menu { gap: 0.2rem; }
  .menu a { font-size: clamp(1.5rem, 6.4vw, 2.2rem); }
  .menu a.menu__meta { margin-top: 0.9rem; }
}

/* Narrow phones: the widest meta line ("TikTok · @decorumevents.official") broke mid-item
   and orphaned the separator on a 390px screen. Tightening the tracking keeps it on one
   line without shrinking the type. */
@media (max-width: 26rem) {
  .menu a.menu__meta, .menu .theme-switch { letter-spacing: 0.1em; }
}

/* ---------- hero ---------------------------------------------------------- */
.hero { padding-top: clamp(8rem, 15vw, 12rem); padding-bottom: clamp(3rem, 6vw, 5rem); }
.hero__grid { display: grid; gap: clamp(2rem, 5vw, 3.5rem); align-items: center; }
@media (min-width: 62rem) {
  .hero__grid { grid-template-columns: 1.02fr 0.98fr; gap: clamp(2.5rem, 5vw, 5rem); }
}
.hero__type { display: grid; gap: 1.6rem; justify-items: start; }
/* Client direction: the hero headline uses the titling face, not the display face.
   Perpetua Titling draws lowercase as capitals and its caps run wide, so it needs a
   smaller optical size and genuine letterspacing to keep two lines balanced. */
.hero__type .display {
  font-family: var(--font-titling);
  font-weight: 300;
  margin-block: 0.2rem;
  font-size: clamp(1.75rem, 3.9vw, 3.5rem);
  line-height: 1.26;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.9rem; align-items: center; margin-top: 0.5rem; }
.hero__art { position: relative; display: grid; gap: 1.1rem; }
/* z-axis cascade: the smaller frame overlaps the tall one */
@media (min-width: 40rem) {
  .hero__art { grid-template-columns: 1.25fr 0.85fr; align-items: end; }
  .hero__art > :nth-child(2) { transform: translateY(-3.5rem) rotate(1.4deg); }
}

/* ---------- event bento --------------------------------------------------- */
.bento { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }
@media (min-width: 48rem) {
  .bento { grid-template-columns: repeat(6, 1fr); }
  .bento > :nth-child(1) { grid-column: span 6; }
  /* Four tiles, not five — the client consolidated Baraat and Walima into one
     broad 'Weddings' page. Two across on tablet... */
  .bento > :nth-child(2), .bento > :nth-child(3) { grid-column: span 3; }
  .bento > :nth-child(4) { grid-column: span 6; }
}
@media (min-width: 62rem) {
  /* ...and three across on desktop, filling the row so the grid never ends
     on a half-row with a hole beside it. */
  .bento > :nth-child(2), .bento > :nth-child(3), .bento > :nth-child(4) { grid-column: span 2; }
}
/* Client direction: the CTA-style gold frame was tried on the tiles and rejected —
   reverted to the original hairline border on a cream surface. */
.tile { position: relative; display: block; overflow: hidden; border-radius: var(--r-shell);
        border: 1px solid var(--line); box-shadow: var(--shadow-ambient); background: var(--cream-raise); }
.tile__media { aspect-ratio: 4 / 3; overflow: hidden; }
.tile__media img { width: 100%; height: 100%; object-fit: cover;
                   transition: transform 1.1s var(--ease-glide), filter 1.1s var(--ease-glide); }@media (hover: hover) {
                     .tile:hover .tile__media img { transform: scale(1.045);
                     }
                   }
.tile__body { padding: 1.35rem 1.5rem 1.6rem; display: grid; gap: 0.45rem; }
.tile__name { font-family: var(--font-titling); font-weight: 300; font-size: 1.6rem; line-height: 1.2; letter-spacing: 0.03em; }
/* Handles and email addresses are long and contain no spaces, so at the standard name size
   they either burst the card or break mid-word ("…EVENTS.OF / FICIAL"). A step smaller and
   they sit on one line, which is how an address should read. */
.tile__name--handle { font-size: 1.18rem; letter-spacing: 0.015em; }
.tile__meta { font-family: var(--font-titling); font-size: 0.78rem; letter-spacing: 0.16em;
              text-transform: uppercase; color: var(--gold-text); }
.tile__note { color: var(--ink-soft); font-size: 0.98em; }
.tile--feature .tile__media { aspect-ratio: 16 / 9; }

/* ---------- small tile grids ---------------------------------------------- */
/* Used by the interior pages for 3-up and 2-up groups of tiles. A shared class rather
   than repeated inline grid styles, so the column behaviour stays consistent and
   responsive breakpoints actually apply (an inline style would win over these). */
.tiles-3 { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }
@media (min-width: 40rem) { .tiles-3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 62rem) { .tiles-3 { grid-template-columns: repeat(3, 1fr); } }

.tiles-2 { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }
@media (min-width: 48rem) { .tiles-2 { grid-template-columns: repeat(2, 1fr); } }

/* ---------- steps --------------------------------------------------------- */
.steps { display: grid; gap: 1.6rem; counter-reset: step; }
@media (min-width: 48rem) { .steps { grid-template-columns: repeat(3, 1fr); gap: 2rem; } }
.step { display: grid; gap: 0.6rem; padding-top: 1.4rem; border-top: 1px solid var(--line); }
.step::before {
  counter-increment: step; content: "0" counter(step);
  font-family: var(--font-titling); font-size: 0.82rem; letter-spacing: 0.18em; color: var(--gold-text);
}
.step h3 { font-family: var(--font-titling); font-weight: 300; font-size: 1.35rem; letter-spacing: 0.03em; }

/* ---------- gallery strip ------------------------------------------------- */
.strip { display: grid; gap: 1rem; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 48rem) { .strip { grid-template-columns: repeat(4, 1fr); } }
.strip figure { margin: 0; overflow: hidden; border-radius: var(--r-tile); border: 1px solid var(--line); }
.strip img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 3 / 4;
             transition: transform 1.1s var(--ease-glide); }@media (hover: hover) {
               .strip figure:hover img { transform: scale(1.05);
               }
             }
.strip figure:nth-child(even) img { aspect-ratio: 3 / 4; }

/* ---------- feature band (full-bleed image + cream card) ------------------ */
.band { position: relative; overflow: hidden; }
.band img.band__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.band__inner { position: relative; z-index: 2; padding-block: clamp(5rem, 12vw, 9rem); }
.band__card {
  max-width: 34rem;
  padding: clamp(1.6rem, 3vw, 2.6rem);
  border-radius: var(--r-shell);
  background: var(--surface-card);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-raise);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

/* ---------- CTA band — gold frame around a cream core (contrast-safe) ----- */
.cta {
  border-radius: var(--r-shell);
  padding: 0.7rem;
  background: var(--grad-gold);
  box-shadow: var(--shadow-raise);
}
.cta__core {
  border-radius: calc(var(--r-shell) - 0.35rem);
  background: var(--cream-raise);
  padding: clamp(2rem, 4.5vw, 3.6rem);
  box-shadow: var(--shadow-inset);
}
.cta h2 { font-family: var(--font-titling); font-weight: 300; color: var(--ink); letter-spacing: 0.03em;
          font-size: clamp(1.9rem, 4vw, 3rem); line-height: 1.25; }
.cta p { color: var(--ink-soft); max-width: 46ch; }
.cta .btn { --btn-bg: var(--grad-gold); color: #fff; }

/* The band's channel buttons sit in one grid so they share a width and their edges line up,
   instead of each sizing to its own label and wrapping into a ragged two-by-two. The column
   minimum is chosen so exactly two fit the band's 44rem column; on a phone the same rule
   collapses them to one per row with no extra code.

   The button base is built for a left-aligned label (asymmetric padding), which leaves an
   obvious gap once every pill is the same width — so inside the band the padding is evened
   out and the label-plus-mark group is centred, which also keeps each mark beside its own
   words rather than stranding it at the far edge. */
.cta__actions {
  display: grid;
  gap: 0.9rem;
  margin-top: 0.4rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
}
.cta__actions .btn { justify-content: center; padding: 0.95rem 1.25rem; position: relative; }

/* Client direction: the channel marks must line up down the column instead of each sitting
   wherever its own label happens to end. The label stays centred — on a phone these are a
   stack of full-width pills and a centred label keeps them reading as one set — so the mark
   is lifted out of the flow and pinned to the right edge, where all four share one x.
   The padding stays symmetric so that centring is honest: with the button base's asymmetric
   padding the label would centre on the pill's box rather than on the pill.
   The hover transform is restated because the base rule's translate() would otherwise replace
   this declaration and drop the vertical centring with it. */
.cta__actions .btn__icon { position: absolute; right: 1.1rem; top: 50%; transform: translateY(-50%); }@media (hover: hover) {
  .cta__actions .btn:hover .btn__icon { transform: translateY(-50%) translate(3px, -2px) scale(1.06);
  }
}
.cta .btn--ghost { --btn-bg: transparent; color: var(--gold-deep); border-color: var(--line-strong); }@media (hover: hover) {
  .cta .btn--ghost:hover { background: var(--tint-gold);
  }
}

/* ---------- footer -------------------------------------------------------- */
.footer { padding-block: clamp(3rem, 6vw, 5rem) 2rem; border-top: 1px solid var(--line); }
.footer__grid { display: grid; gap: 2rem; }
/* Two columns, not three: the "Events" column of page links was removed on instruction. The
   column list has to be re-stated when a child is deleted, or the remaining two keep their old
   sizes and the row is left with a hole where the third used to be. */
@media (min-width: 48rem) { .footer__grid { grid-template-columns: 1.4fr 1fr; } }
.footer img.footer__logo { height: 4.6rem; width: auto; margin-bottom: 1rem;
  /* Client direction: centre the DECORUM EVENTS wordmark on the heading row beside it. The
     column headings are a single line at 1.5 leading (20px / 1.25rem) and their top sits at the
     column's top, so the 74px logo's centre fell 26px below the heading's centre. Shifting the
     logo up by half the difference puts the two centres on one line. Re-derive the 1.25rem if
     the footer heading's size or leading changes. */
  margin-top: calc((1.25rem - 4.6rem) / 2);
}
/* `line-height` is stated rather than inherited because the logo above is centred against this
   box's height, and an implicit value would make the alignment drift with the body leading. */
.footer h3 { font-family: var(--font-titling); font-size: 0.82rem; letter-spacing: 0.18em;
             line-height: 1.5;
             text-transform: uppercase; color: var(--gold-text); margin-bottom: 0.9rem; }
.footer ul { display: grid; gap: 0.5rem; }
.footer a { color: var(--ink-soft); transition: color var(--dur-fast) var(--ease-spring); }@media (hover: hover) {
  .footer a:hover { color: var(--gold-deep);
  }
}

/* Contact channels: logo, then the handle to its right. Client direction — the
   handles must read as handles, so they are NOT uppercase, and they show at every
   width (they were previously suppressed on phones). Sits after `.footer a`
   deliberately: same specificity, so source order decides. */
.footer ul.footer__social { display: flex; flex-direction: column; align-items: flex-start; gap: 0.8rem; margin-bottom: 1.15rem; }
.footer__social a { display: inline-flex; align-items: center; gap: 0.75rem; color: var(--gold-deep); }
/* Concept A3, chosen by the client: the genuine brand marks reversed out of gold, echoing the
   nav circles and the buttons. The fill is now --grad-gold-gloss, the kebab button's light
   glossy ramp, on the client's instruction — the previous deep two-stop gold read to them as
   flat metal ("it's a solid gold and I don't like it"), which is the same direction the kebab
   was given.

   Cost, stated once rather than argued: the mark is white, and on this ramp white measures
   1.30:1 at the lightest stop / 1.98:1 across the band the glyph actually sits on / 3.33:1 at
   the darkest edge, against 2.40:1 and 4.25:1 for the deep gold it replaces. So the marks read
   fainter, in daylight especially. This is the client's call, taken knowingly;
   `background: var(--grad-gold-deep)` reverts it in one line. */
.footer__social-mark {
  display: grid; place-items: center; flex: 0 0 auto;
  width: 2.9rem; height: 2.9rem;
  border-radius: var(--r-pill);
  background: var(--grad-gold-gloss);
  color: #fff;
  border: 0;
  box-shadow: var(--shadow-inset);
  transition: transform var(--dur-fast) var(--ease-spring), filter var(--dur-fast) var(--ease-spring);
}@media (hover: hover) {
  .footer__social a:hover .footer__social-mark { transform: translateY(-2px); filter: brightness(1.07);
  }
}
.footer__social-name { display: inline; color: var(--ink-soft); text-transform: none; letter-spacing: 0; }@media (hover: hover) {
  .footer__social a:hover .footer__social-name { color: var(--gold-text);
  }
}
.footer__enquire { color: var(--ink-soft); max-width: 30ch; margin-top: 0.7rem; }
/* 19 Sep 2026: was --gold-deep (3.59:1) — --gold-text measures 5.54:1 */
.footer__enquire a { color: var(--gold-text); text-decoration: underline; text-underline-offset: 3px; }
.footer__legal { margin-top: 2.5rem; padding-top: 1.4rem; border-top: 1px solid var(--line-soft);
                 display: flex; flex-wrap: wrap; gap: 0.8rem 1.5rem; justify-content: space-between;
                 font-size: 0.86rem; /* 19 Sep 2026: was --ink-faint (#9a8f85, 2.67:1) — --ink-soft is 5.00:1 */
                 color: var(--ink-soft); }

/* ---------- scroll reveals ------------------------------------------------ */
[data-reveal] {
  opacity: 0;
  transform: translateY(2.5rem);
  filter: blur(6px);
  transition: opacity var(--dur-slow) var(--ease-spring),
              transform var(--dur-slow) var(--ease-spring),
              filter var(--dur-slow) var(--ease-spring);
}
[data-reveal].is-in { opacity: 1; transform: none; filter: blur(0); }
[data-reveal][data-delay="1"] { transition-delay: 90ms; }
[data-reveal][data-delay="2"] { transition-delay: 180ms; }
[data-reveal][data-delay="3"] { transition-delay: 270ms; }
[data-reveal][data-delay="4"] { transition-delay: 360ms; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
  [data-reveal] { opacity: 1; transform: none; filter: none; }
  .menu a { opacity: 1; transform: none; }
}

/* ---------- floating WhatsApp bubble (mobile only) ------------------------- */
/* Client direction: a one-tap route into chat on phones. The breakpoint is the one
   the navigation already uses, so "mobile version" means the same thing here as it
   does for the hamburger menu.
   Gold, matching the social marks; WhatsApp's own green would fight the palette.
   The entrance animates `translate`, not `transform`, so that `transform` stays free
   for the press feedback — an animation with fill:forwards would otherwise win over
   the :active rule (animations outrank normal declarations for the properties they
   touch). */
.wa-bubble { display: none; }

@media (max-width: 61.99rem) {
  .wa-bubble {
    position: fixed;
    right: max(1rem, env(safe-area-inset-right));
    bottom: calc(1rem + env(safe-area-inset-bottom));
    z-index: 35;                /* below the menu overlay (39) so the menu covers it */
    display: grid;
    justify-items: center;
    gap: 0.4rem;
    /* VISIBLE by default. The entrance uses `backwards` fill, so the hidden state only
       exists while the delay runs — if animations never execute, the button is simply
       already there. (The first attempt hid it with `forwards` fill, which meant a
       stalled animation clock left an invisible call-to-action.) */
    opacity: 1;
    translate: 0 0;
    animation: wa-enter 0.55s var(--ease-spring) 0.5s backwards;
    transition: transform 160ms var(--ease-spring);
    -webkit-tap-highlight-color: transparent;
  }

  /* The round bubble itself, in WhatsApp's own green — the exact value from the glyph in
     their Brand Resource Center pack, flat, because that is how they ship it. Recognition is
     the entire point of this element: it has to look like the mark already on people's
     phones, so it is deliberately NOT tuned to the page palette.

     Cost, stated once rather than argued: white on #25D366 measures 1.98:1, so the glyph
     itself sits below the 3:1 used for meaningful UI graphics. That is inherent to the
     official lockup — WhatsApp's own app icon measures the same. The written word is the
     part that has to pass, and it does: the wordmark sits on the cream chip below at 5.98:1,
     not on the green. */
  .wa-bubble__mark {
    position: relative;
    display: grid;
    place-items: center;
    width: 3.6rem;
    height: 3.6rem;             /* 58px — past the 44px tap minimum */
    border-radius: 50%;
    background: #25d366;
    color: #fff;
    box-shadow: 0 12px 28px -10px rgba(37, 211, 102, 0.55), var(--shadow-inset);
    transition: transform 160ms var(--ease-spring);
  }
  /* 62% of the circle, which is the proportion the brand pack's own lockups use. At the
     previous 52% the mark read as a small badge inside a large disc rather than as the
     familiar app icon. */
  .wa-bubble__mark svg { width: 2.25rem; height: 2.25rem; }

  /* The wordmark now sits OUTSIDE the circle, so it floats over whatever is behind it.
     The cream chip keeps it legible over photography, matching the eyebrow pill the
     site already uses. Set in the text face so it reads as proper mixed-case
     "WhatsApp" — both brand faces are capitals-only and would give "WHATSAPP". */
  .wa-bubble__label {
    font-size: 0.78rem;
    line-height: 1;
    color: var(--gold-text);
    background: var(--cream-raise);
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    padding: 0.34em 0.8em;
    box-shadow: var(--shadow-ambient);
  }

  .wa-bubble:active .wa-bubble__mark { transform: scale(0.94); }

  /* one slow halo, so it reads as the primary action without nagging */
  .wa-bubble__mark::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid rgba(11, 122, 75, 0.5);
    pointer-events: none;
    animation: wa-halo 3.4s var(--ease-glide) 1.8s infinite;
  }
}

@keyframes wa-enter {
  from { opacity: 0; translate: 0 0.9rem; }
  to   { opacity: 1; translate: 0 0; }
}
@keyframes wa-halo {
  0%   { transform: scale(1);   opacity: 0.5; }
  70%  { transform: scale(1.6); opacity: 0; }
  100% { transform: scale(1.6); opacity: 0; }
}

/* The global reduced-motion rule zeroes durations but NOT delays, so without this the
   bubble would sit invisible for over a second before snapping in. */
@media (prefers-reduced-motion: reduce) {
  .wa-bubble { opacity: 1; translate: 0 0; animation: none; }
  .wa-bubble__mark::after { animation: none; opacity: 0; }
}
  /* ==========================================================================
     Enquiry form (site/enquire/)

     Built only from the tokens above, so the form inherits both themes without a
     single hardcoded colour — the one exception is --danger, which is a new token
     because an error state cannot borrow gold without reading as decoration.

     Accessibility notes, since this page is held to 0 axe violations:
       * fields are stacked label-above-input, never placeholder-as-label
       * the focus ring is 2px of --gold-text at 2px offset — visible in both themes
     ========================================================================== */

  /* max-width alone left the form hugging the left edge on a desktop screen — 864px wide with 48px
     to its left and 528px of empty space to its right ("the desktop website is not showing the
     enquiry form as centred, looks weird"). The auto margins centre the column in whatever room the
     page gives it at every width. */
  .enq { display: grid; gap: var(--space-block); max-width: 54rem; margin-inline: auto; }

  /* The enquiry page is the form and nothing above it, so its opening block is centred (client:
     "Centre the text on the page."). Only that block: the form's legends, labels and fields stay
     left-aligned, which is where they are read. `margin-inline: auto` is needed as well as
     `text-align` because the lede carries a max-width of its own. */
  #enquiry > .wrap > .section-title,
  #enquiry > .wrap > .lede { text-align: center; }
  #enquiry > .wrap > .lede { margin-inline: auto; }
  /* The pill is an inline-flex box, so centring its *text* would only centre the words inside it —
     it needs to become a block that shrinks to its content and takes the auto margins. Also gives it
     air above "Your details", which it was sitting on. */
  #enquiry > .wrap > .eyebrow {
    display: flex;
    width: fit-content;
    /* More air above than below (client: "increase the spacing between the enquiry form button and the
       text above"): 0.2rem left the pill almost touching the lede. It reads as a label for what
       follows, so it hangs closer to "Your details" than to the paragraph above. */
    margin: 2.5rem auto 1.9rem;
  }
  /* The form's own section labels follow the page, so the block reads as one centred column; the
     labels and fields below them stay left-aligned, which is where they are read. */
  #enquiry .enq__legend { text-align: center; }

  .enq__group { border: 0; padding: 0; margin: 0; display: grid; gap: 1rem; min-width: 0; }

  .enq__legend {
    font-family: var(--font-titling);
    font-weight: 300;
    font-size: 0.82rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--gold-text);
    padding: 0;
    margin-bottom: 0.2rem;
  }

  .enq__row { display: grid; gap: 1rem; }
  /* minmax(0, 1fr), not 1fr: a bare 1fr keeps a child's *intrinsic* minimum, so one wide control
     drags the whole row past the page edge instead of shrinking */
  @media (min-width: 44rem) { .enq__row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

  .enq__field { display: grid; gap: 0.45rem; min-width: 0; }

  .enq__field > label,
  .enq__services > legend {
    font-family: var(--font-text);
    font-size: 0.95rem;
    color: var(--ink);
  }

  .enq__hint { font-family: var(--font-text); font-size: 0.82rem; color: var(--ink-soft); }

  /* Venue suggestions — an ordinary <ul> that enquiry.js builds. Without JS it never exists, and the
     field is a plain text box with the browser's own autocomplete switched off. */
  .enq__field--venue { position: relative; }
  .enq__suggest {
    position: absolute;
    z-index: 40;
    margin: 0.35rem 0 0;
    padding: 0.3rem;
    list-style: none;
    min-width: 14rem;   /* the width itself is set by enquiry.js, to match the field */
    max-height: 16rem;
    overflow: auto;
    border: 1px solid var(--line-strong);
    border-radius: var(--r-md);
    background: var(--surface-nav);
    box-shadow: var(--shadow-lift);
    backdrop-filter: blur(18px) saturate(1.1);
  }
  .enq__suggest-item {
    padding: 0.62rem 0.75rem;
    border-radius: var(--r-sm);
    font-size: 0.95rem;
    cursor: pointer;
  }
  .enq__suggest-item[aria-selected="true"] { background: var(--tint-gold); }
  .enq__error { font-family: var(--font-text); font-size: 0.82rem; color: var(--danger); font-weight: 600; }
  .enq__error[hidden] { display: none; }

  /* --- controls ---------------------------------------------------------- */
  .enq input[type="text"],
  .enq input[type="email"],
  .enq input[type="tel"],
  .enq input[type="number"],
  .enq input[type="date"],
  .enq textarea {
    font-family: var(--font-text);
    font-size: 1rem;
    color: var(--ink);
    background: var(--surface-glass-strong);
    border: 1px solid var(--line-strong);
    border-radius: 0.85rem;
    padding: 0.7rem 0.85rem;
    width: 100%;
    min-width: 0;
    transition: border-color var(--dur-fast) var(--ease-glide),
                box-shadow var(--dur-fast) var(--ease-glide);
  }
  .enq textarea { resize: vertical; min-height: 7rem; line-height: 1.55; }@media (hover: hover) {
    .enq input:hover, .enq textarea:hover { border-color: var(--gold);
    }
  }
  .enq input:focus-visible,
  .enq textarea:focus-visible,
  .enq input[type="file"]:focus-visible,
  .enq button:focus-visible,
  .enq__check input:focus-visible {
    outline: 2px solid var(--gold-text);
    outline-offset: 2px;
  }

  /* --- the date field: always dd/mm/yyyy -----------------------------------------------
     A native <input type="date"> is drawn in whatever format the DEVICE is set to, so a visitor
     on a US-configured phone saw 04/17/2027 on a British site. The visible control is therefore a
     text field that reads dd/mm/yyyy (slashes inserted as they type), and the real date input sits
     invisibly on top of the calendar button — so tapping still opens the platform's own picker,
     with no JavaScript involved. */
  .enq__date { position: relative; display: block; }
  .enq input[data-date-uk] { padding-right: 3rem; }

  .enq__date-format {
    font-family: var(--font-text);
    font-size: 0.8rem;
    font-weight: 400;
    color: var(--ink-soft);
  }

  .enq__date-pick {
    position: absolute;
    top: 50%;
    right: 0.3rem;
    transform: translateY(-50%);
    display: grid;
    place-items: center;
    width: 2.4rem;
    height: 2.4rem;
    color: var(--gold-text);
    border-radius: 0.6rem;
  }
  .enq__date-pick:focus-within { outline: 2px solid var(--gold-text); outline-offset: 2px; }

  .enq__date-native {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    opacity: 0;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
  }
  :root[data-theme="dark"] .enq input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(1); opacity: 0.7; }

  /* --- checkboxes -------------------------------------------------------- */
  .enq__checks { display: grid; gap: 0.55rem 1.2rem; }
  @media (min-width: 34rem) { .enq__checks { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); } }
  /* An option alone on the last row sits in the middle column instead of hanging on the left
     ("centre the walkway option for the nikah"). Harmless where the grid is two columns: item
     auto-placement fills column one first, so the pair still lands side by side. */
  @media (min-width: 34rem) { .enq__service--orphan { grid-column: 2; } }
  .enq__checks--events { margin-top: 0.4rem; }

  .enq__check {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    font-family: var(--font-text);
    font-size: 0.98rem;
    color: var(--ink);
    cursor: pointer;
    padding: 0.15rem 0;
  }
  .enq__check input {
    flex: none;
    width: 1.1rem;
    height: 1.1rem;
    margin-top: 0.18rem;
    accent-color: var(--gold-deep);
    cursor: pointer;
  }

  /* --- one block per event ----------------------------------------------- */
  .enq__events { display: grid; gap: 1.2rem; }
  .enq__event {
    border: 1px solid var(--line);
    border-radius: var(--r-tile);
    background: var(--tint-gold);
    padding: 1.3rem;
    display: grid;
    gap: 1.1rem;
    min-width: 0;
  }
  .enq__event[hidden] { display: none; }
  .enq__event-name {
    font-family: var(--font-titling);
    font-weight: 300;
    font-size: 1rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--gold-text);
    /* a heading inside the card now, not a legend straddling its edge — see the note in
       tools/build_enquiry_form.py for why the fieldset had to go */
    margin: 0;
    padding: 0;
  }
  .enq__services { border: 0; padding: 0; margin: 0; display: grid; gap: 0.7rem; min-width: 0; }

  /* --- file input -------------------------------------------------------- */
  .enq input[type="file"] {
    font-family: var(--font-text);
    font-size: 0.9rem;
    color: var(--ink-soft);
    background: var(--surface-glass-strong);
    border: 1px dashed var(--line-strong);
    border-radius: 0.85rem;
    padding: 0.7rem;
    width: 100%;
    cursor: pointer;
  }
  .enq input[type="file"]::file-selector-button {
    font-family: var(--font-text);
    font-size: 0.9rem;
    color: var(--ink);
    background: var(--cream-raise);
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    padding: 0.35rem 0.85rem;
    margin-right: 0.7rem;
    cursor: pointer;
  }
  .enq__file-list { display: grid; gap: 0.3rem; margin: 0; padding: 0; list-style: none; }
  .enq__file-list li {
    font-family: var(--font-text);
    font-size: 0.85rem;
    color: var(--ink-soft);
    display: flex;
    gap: 0.5rem;
    justify-content: space-between;
    border-bottom: 1px solid var(--line-soft);
    padding-bottom: 0.25rem;
  }

  /* --- honeypot: off-screen, not display:none (some bots skip hidden fields) */
  .enq__trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

  /* --- messages ---------------------------------------------------------- */
  .enq__alert,
  .enq__note-box {
    border: 1px solid var(--line-strong);
    border-radius: var(--r-tile);
    padding: 1rem 1.15rem;
    font-family: var(--font-text);
    background: var(--surface-glass-strong);
  }
  .enq__alert { border-color: var(--danger); background: var(--danger-wash); display: grid; gap: 0.5rem; }
  .enq__alert[hidden] { display: none; }
  .enq__alert h3 { font-family: var(--font-titling); font-size: 0.9rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--danger); }
  .enq__alert ul { margin: 0; padding-left: 1.1rem; display: grid; gap: 0.3rem; }
  .enq__alert a { color: var(--danger); text-decoration: underline; text-underline-offset: 2px; }
  .enq__note-box[hidden] { display: none; }
  .enq__note-box p { margin: 0 0 0.6rem; }
  .enq__note-box p:last-child { margin-bottom: 0; }
  .enq__note-box a { color: var(--gold-text); text-decoration: underline; text-underline-offset: 2px; }
  .enq__note-box--bad { border-color: var(--danger); background: var(--danger-wash); }

  /* a field that failed validation, marked by more than colour: the message is real text */
  .enq__field--bad input,
  .enq__field--bad textarea { border-color: var(--danger); border-width: 2px; }

  /* --- submit ------------------------------------------------------------ */
  .enq__submit { display: grid; gap: 0.9rem; justify-items: start; }
  .enq__submit .btn { cursor: pointer; border: 0; }
  .enq__submit .btn[disabled] { opacity: 0.65; cursor: default; transform: none; }
  .enq__foot { font-family: var(--font-text); font-size: 0.82rem; color: var(--ink-soft); max-width: 46ch; }

  /* a visitor who has sent the form sees the form step back, not vanish */
  .enq--sent .enq__group,
  .enq--sent .enq__events,
  .enq--sent .enq__submit { opacity: 0.45; }
  .enq--sent .enq__submit .btn { pointer-events: none; }
  /* ==========================================================================
     Photo rails — the horizontal strip of our own setups that opens inside a ticked
     service option.

     Each rail lives in a <template> and is copied in by enquiry.js only when its option
     is ticked, so none of these images cost anything until someone asks to see them.

     The strip is deliberately scrollable rather than a grid: a rail of six to eight
     photographs is a glance, and a grid would push the rest of the form down the page.
     ========================================================================== */

  .enq__service { display: grid; gap: 0.55rem; min-width: 0; }

  .enq__rail {
    display: grid;
    gap: 0.45rem;
    /* lines the strip up with the option's own text, not with its checkbox */
    margin-left: 1.7rem;
    min-width: 0;
  }
  .enq__rail[hidden] { display: none; }

  .enq__rail-scroll {
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    /* Breathing room around the photographs in the strip, 24px above and below. The bottom half of
       this is what the client first asked for ("increase the space between the image and scroll
       bar") — the scroll indicator is drawn inside the container's bottom padding, so that padding
       *is* the gap they see. 0.35rem (5.6px) left the bar against the gold ring under a tile; it
       went to 16px, then 24px ("got to 24px"), then the same 24px above the photographs on request
       ("increase the gap above the image") so the strip sits evenly in its row. */
    padding-block: 1.5rem;
    /* a scroll container has to be reachable by keyboard to be scrollable by keyboard */
    border-radius: 0.75rem;
  }
  .enq__rail-scroll:focus-visible {
    outline: 2px solid var(--gold-text);
    outline-offset: 3px;
  }

  .enq__rail-list {
    display: flex;
    gap: 0.55rem;
    margin: 0;
    padding: 0;
    list-style: none;
    width: max-content;
  }
  /* Centre, not start: a selected tile is scrolled to the middle of the strip (see centreThumb in
     enquiry.js), and with a `start` snap point the strip would pull it back to the left edge. Tiles
     now settle in the middle after a swipe too. */
  .enq__rail-list li { scroll-snap-align: center; }

  /* Uniform tiles. The width used to follow each photograph's own shape — measured on a phone,
     the seven tiles in one strip came out 182, 92, 92, 122, 92, 112 and 181 px wide, so a portrait
     shot sat at half the width of a landscape one and the strip read as a ragged row of mismatched
     pictures ("the selection still doesn't look right"). Every tile is now the same 4:3 box and the
     photograph fills it. Nothing is lost to the cropping: tapping a tile opens that photograph at
     full size, uncropped, in the viewer. */
  .enq__rail-list img {
    display: block;
    /* border-box so the photograph keeps exactly the same footprint when a marked tile has its
       hairline taken off — nothing shifts, the picture simply fills that extra 1px */
    box-sizing: border-box;
    inline-size: 9.5rem;
    block-size: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    /* Concentric corners: inner radius = outer radius - padding (14.4px - 5px = 9.4px). The tile's
       radius was 0.9rem with a 0.7rem inner corner, which is 2px off concentric — the sort of
       mismatch that reads as "something's wrong here" without anyone naming it. Derived rather than
       hard-coded, so it stays right if either value moves. */
    border-radius: calc(0.9rem - 5px);
    /* No hairline. The client does not want an edge drawn on the photograph itself ("remove the
       hairline entirely — it is not needed"): on a chosen tile it sat between the gold marker and
       the picture and read as a second, browner line. The gold marker is the only frame a tile
       needs. box-sizing keeps the photograph's footprint identical, so nothing shifts. */
    border: 0;
    background: var(--surface-glass-soft);
  }

  .enq__rail-hint {
    font-family: var(--font-text);
    font-size: 0.78rem;
    color: var(--ink-soft);
  }

  .enq__rail-upload { margin-top: 0.35rem; }
  .enq__rail-upload .enq__file-summary {
    font-family: var(--font-text);
    font-size: 0.8rem;
    color: var(--gold-text);
  }
  /* ==========================================================================
     Options that say what they do, and setups that open when tapped.

     Two changes on the client's instruction:
       * the whole option is the tap target, not just its checkbox, and its own words turn
         gold when it is on — so the function that is selected is obvious at a glance
       * tapping a setup in a rail opens it at full size in a <dialog>, captioned with the
         option it belongs to
     ========================================================================== */

  /* --- the option: checkbox beside a text block, all of it tappable --------- */
  .enq__service {
    /* A gold RING marks the option that is on, with a heavier left edge so it still reads as a
       margin rule. Every width is set here and never changes — only the colours do — so nothing
       shifts when an option is chosen. The client asked for this twice: thicker ("make it more
       obvious what the selection is, so the gold border to be thicker"), and then as a closed ring
       ("the gold selection ring ... is chopped" — it was a left bar alone, which looks like a ring
       that has been cut off). */
    border: 2px solid transparent;
    border-left-width: 5px;
    border-radius: 0 0.8rem 0.8rem 0;
    padding-left: 0.55rem;
    margin-left: -0.72rem;
    /* no colour transition: choosing an option has to be visible at once, and a transitioned
       property is also the one thing a headless check cannot measure */
  }
  /* The chosen option, made obvious. It used to be a 2px gold edge plus gold text, which is easy
     to miss on a phone — and the client could not see it at all while the photograph view was
     covering the form, which is exactly when he presses Select this. The wash is NOT transitioned
     on purpose: it appears the instant the option is chosen. */
  .enq__service.is-on { border-color: var(--gold-gloss); background: var(--tint-gold); }

  .enq__check {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: start;
    gap: 0.6rem;
  }
  .enq__check-text { display: grid; gap: 0.15rem; min-width: 0; }
  .enq__check-name { font-family: var(--font-text); font-size: 0.98rem; color: var(--ink); }
  .enq__service-note {
    font-family: var(--font-text);
    font-size: 0.82rem;
    color: var(--ink-soft);
    /* no colour transition here on purpose: choosing an option must be visible at once, and a
       transitioned colour is also the one thing a headless check cannot measure (see the skill) */
  }

  /* The function that is selected says so in colour, in size, and in words. The client asked for a
     lot more emphasis once chosen ("make the selection a lot bigger once selected, so that when the
     customer reviews it easy to see what's selected") and for the way out to be equally obvious. */
  .enq__service.is-on .enq__check-name {
    color: var(--gold-text);
    font-weight: 600;
    font-size: 1.18rem;
  }

  .enq__service-actions { display: none; }
  .enq__service.is-on .enq__service-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
  }

  /* Same treatment as the chips in the photograph view, which are already measured and pass in
     both themes. Cream on the gold gradient would have measured 3.95:1 at this size — the gradient
     is only ever used for glyphs (3:1), never for small text. */
  .enq__service-remove {
    padding: 0.42rem 0.95rem;
    font-family: var(--font-text);
    font-size: 0.88rem;
    color: var(--ink);
    background: var(--surface-glass-strong);
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    cursor: pointer;
  }@media (hover: hover) {
    .enq__service-remove:hover { border-color: var(--gold); color: var(--gold-text);
    }
  }
  .enq__service-remove:focus-visible { outline: 2px solid var(--gold-text); outline-offset: 2px; }
  .enq__service.is-on .enq__service-note { color: var(--gold-text); }

  /* The wash lifts the ground beneath everything inside a chosen option, and the hint lines are
     small text: --ink-soft on it measures 4.41:1, under the 4.5:1 that size needs. --ink on the
     wash measures 11.25:1. (Re-run tools/check_form_contrast.py and axe if the wash changes.) */
  .enq__service.is-on .enq__rail-hint,
  .enq__service.is-on .enq__hint { color: var(--ink); }

  /* --- a setup in a rail is a button --------------------------------------- */
  .enq__thumb {
    display: block;
    position: relative;
    /* 5px of room: exactly the marker's thickness, so the gold sits straight against the photograph
       and the tile shows ONE box. The 3px that used to hold the ring clear of the picture is gone —
       with the ring flush there is no pale band for the eye to read as a second frame
       ("there are still two boxes around the image"). Reserved on every tile, so the marker still
       costs no layout shift and every tap target is that much bigger. */
    padding: 5px;
    margin: 0;
    border: 0;
    background: none;
    line-height: 0;
    border-radius: 0.9rem;
    cursor: zoom-in;
    transition: transform var(--dur-fast) var(--ease-spring);
  }@media (hover: hover) {
    .enq__thumb:hover { transform: translateY(-2px);
    }
  }
  .enq__thumb:active { transform: scale(0.98); }
  /* The ring around a tile is drawn INSIDE it. A tile sits flush with the top and left of the
     strip's scrolling box, so an outline drawn outside could only ever show part of itself — the
     chopped ring the client reported ("the gold selection ring ... is chopped"). Inset, it is
     whole whichever tile it is on. */
  /* Dashed and in the gloss gold: a rectangular focus cue that cannot be confused with the solid
     gold marker, and never the browner --gold-text beside it. */
  .enq__thumb:focus-visible { outline: 3px dashed var(--gold-gloss); outline-offset: -3px; }
  /* the hover lift is on the tile itself; with no border on the photograph there is no border
     colour left to change */

  /* --- the tap-to-enlarge viewer --------------------------------------------
     A modal dialog, and deliberately nothing else: NO position override. The browser
     positions a modal dialog with position: fixed, which is what keeps it centred in the
     viewport however far the page is scrolled. Setting position: relative here (as an earlier
     version did, so the Close button could be absolutely positioned) moved it into the
     document's coordinate space and it opened at the top of the page instead. The Close
     button hangs off .enq__viewer-inner, which is the positioning context it needs. */
  .enq__viewer {
    border: 1px solid var(--line-strong);
    border-radius: var(--r-tile);
    background: var(--cream-raise);
    color: var(--ink);
    padding: 0;
    width: min(92vw, 34rem);
    max-height: 88vh;
    overflow: auto;
    box-shadow: var(--shadow-raise);
  }
  .enq__viewer::backdrop { background: rgba(23, 19, 15, 0.72); }
  .enq__viewer-inner { position: relative; }
  .enq__viewer-figure { margin: 0; display: grid; }
  .enq__viewer-img {
    display: block;
    width: 100%;
    height: auto;
    background: var(--tint-gold);
  }
  /* The counter sits between the controls and the caption, so it brings its own rhythm. */
  .enq__viewer-count {
    display: block;
    padding: 0.7rem 1.15rem 0;
    font-family: var(--font-text);
    font-size: 0.78rem;
    color: var(--ink-soft);
  }

  .enq__viewer-caption {
    display: grid;
    gap: 0.35rem;
    padding: 1rem 1.15rem 1.2rem;
    border-top: 1px solid var(--line);
  }
  .enq__viewer-name {
    font-family: var(--font-titling);
    font-weight: 300;
    font-size: 0.92rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--gold-text);
  }
  .enq__viewer-note { font-family: var(--font-text); font-size: 0.86rem; color: var(--ink-soft); }
  .enq__viewer-desc { font-family: var(--font-text); font-size: 0.92rem; color: var(--ink); }
  

  /* --- what they have chosen so far ---------------------------------------- */
  .enq__viewer-chosen {
    margin: 0;
    padding: 0 1.15rem 0.9rem;
    font-family: var(--font-text);
    font-size: 0.87rem;
    line-height: 1.45;
    color: var(--ink);
  }
  .enq__viewer-chosen-label { display: block; margin-bottom: 0.45rem; }
  .enq__viewer-chip {
    display: inline-block;
    margin: 0 0.35rem 0.35rem 0;
    padding: 0.24rem 0.62rem;
    font-size: 0.83rem;
    color: var(--gold-text);
    background: var(--tint-gold);
    border: 1px solid var(--gold);
    border-radius: 999px;
  }

  /* the note that appears when their last answers have been put back */
  .enq__restored {
    margin: 0 0 1.5rem;
    padding: 0.85rem 1rem;
    font-family: var(--font-text);
    font-size: 0.9rem;
    color: var(--ink);
    background: var(--surface-glass-strong);
    border: 1px solid var(--gold);
    border-radius: var(--r-tile);
  }

  /* what pressing the select button did, said plainly, where the visitor is looking */
  .enq__viewer-status {
    margin: 0;
    padding: 0 1.15rem 1.1rem;
    font-family: var(--font-text);
    font-size: 0.86rem;
    color: var(--gold-text);
  }
  .enq__viewer-status:empty { display: none; }

  /* --- arrows and the select button ---------------------------------------- */
  .enq__viewer-controls {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0 1.15rem 1.2rem;
    border-top: 1px solid var(--line);
    padding-top: 0.9rem;
  }
  .enq__viewer-arrow {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    color: var(--ink);
    background: var(--surface-glass-strong);
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    cursor: pointer;
  }@media (hover: hover) {
    .enq__viewer-arrow:hover { border-color: var(--gold); color: var(--gold-text);
    }
  }
  .enq__viewer-arrow:focus-visible,
  .enq__viewer-select:focus-visible { outline: 2px solid var(--gold-text); outline-offset: 2px; }

  .enq__viewer-select {
    flex: 1;
    font-family: var(--font-titling);
    font-weight: 300;
    font-size: 0.82rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--gold-white);
    background: var(--grad-gold);
    border: 0;
    border-radius: 999px;
    padding: 0.75rem 1rem;
    cursor: pointer;
    box-shadow: var(--shadow-btn);
  }@media (hover: hover) {
    .enq__viewer-select:hover { box-shadow: var(--shadow-btn-hover);
    }
  }
  /* already chosen: the button keeps its wording (it is an action) and stays usable — it will say
     the option is already in the enquiry — but it stops looking like the call to action. The line
     above lists what has been chosen; unticking belongs to the tickbox. */
  .enq__viewer-select[data-chosen="true"] {
    color: var(--gold-text);
    background: var(--surface-glass-strong);
    border: 1px solid var(--gold);
    box-shadow: none;
  }

  .enq__viewer-close {
    position: absolute;
    top: 0.6rem;
    right: 0.6rem;
    font-family: var(--font-text);
    font-size: 0.85rem;
    color: var(--ink);
    background: var(--cream-raise);
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    padding: 0.3rem 0.8rem;
    cursor: pointer;
  }
  .enq__viewer-close:focus-visible { outline: 2px solid var(--gold-text); outline-offset: 2px; }

  /* the thumbnail that is currently open says so */
  /* The marker: 6px of the kebab's gloss gold, standing 3px clear of the photograph — the offset is
     the client's ("retain the offset of 3px and reduce the marker to 6px"). The 9px it needs is
     inside the tile, so the strip's scrolling box cannot chop it, and it stays after the view closes,
     which is when it can actually be seen. */
  /* No second edge inside the ring: the photograph's own 1px hairline showed as an extra line
     between the gold and the picture (the client: "some kind of brow line around the selection I
     don't need that — I am happy with the gold one"). The width stays, so nothing moves. */
  .enq__thumb[data-seen="1"] img {
    /* fallback where mask compositing is unavailable: a solid ring in the ramp's deeper end, which
       still measures about 3:1 against the card */
    outline: 5px solid var(--gold-gloss);
    outline-offset: 3px;
  }
  @supports ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
    /* with masks, the gloss ramp itself can be the ring: 6px thick, 3px from the photograph */
    .enq__thumb[data-seen="1"] img { outline: 0; }
    .enq__thumb[data-seen="1"]::after {
      content: "";
      position: absolute;
      inset: 0;
      border-radius: 0.9rem;
      padding: 5px;
      background: var(--grad-gold-marker);
      -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
      -webkit-mask-composite: xor;
      mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
      mask-composite: exclude;
      pointer-events: none;
    }
  }




/* ---------- desktop floating dark-mode switch ------------------------------ */
/* The client's ask: "floating on the top right with the text and the button below", then
   "go further to the top right. Make it smaller too."

   Two things were learned on the way, and both are deliberate here:
   1. Hidden at EVERY width by default, shown only from 62rem up. The first version put
      `display: none` inside the desktop media query, so on a phone the control had no display rule
      to fall back on, defaulted to inline-block (it is a <button>) and appeared as a second switch
      floating in the mobile nav.
   2. It is positioned against the VIEWPORT, so its markup sits outside <header>. The nav bar
      carries a `backdrop-filter`, and a filtered ancestor becomes the containing block for
      `position: fixed`: inside the bar, `right: 1.6rem` measured from the bar's right edge rather
      than the screen's, leaving the switch 178px short of the corner. (Nav pill measured at 1440px:
      137,22 to 1289,139.)

   Placement is two-tier so it never lands on the "Enquire" button: from 74rem (1184px) the centring
   nav pill — 72rem max — leaves real margin beside it, and the switch sits in the corner level with
   the bar; between 62rem and 74rem there is no margin to float in, so it drops just below the bar at
   the screen's right edge. Smaller than the menu's copy throughout, on request: 0.68rem label and a
   2.2rem track against the menu's 0.85rem and 3.1rem. */
.nav__theme { display: none; }

@media (min-width: 62rem) {
  .nav__theme {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
    position: fixed;
    top: calc(10rem + env(safe-area-inset-top, 0px));
    right: calc(50px + env(safe-area-inset-right, 0px));
    z-index: 30;
    /* Same shape and surface as the menu bar ("have the dark mode box match the same shape as the
       menu bar"): the bar's computed values are radius 999px (a stadium), a 1px --line hairline,
       --surface-nav and blur(18px) saturate(1.1). The horizontal padding is 0.75rem on purpose — a
       999px radius eats ~7px of each side at the label's height, so the text needs to clear it. */
    /* Room for the words. A 999px radius eats into a 71px-tall box by about 11px at the label's
       height, so 0.85rem of side padding left the text "barely fitting" against the curved ends:
       1.3rem of side padding puts ~9px of clear pill either side of the word. Vertically up a notch
       too, so the whole box reads bigger rather than just wider. */
    padding: 0.75rem 1.3rem 0.8rem;
    border-radius: 999px;
    border: 1px solid var(--line);
    background-color: var(--surface-nav);
    -webkit-backdrop-filter: blur(18px) saturate(1.1);
    backdrop-filter: blur(18px) saturate(1.1);
    box-shadow: var(--shadow-ambient);
    /* It leaves with the menu bar on the way down and, unlike the bar, only returns at the top of
       the page (client request). The toggle lives in the scroll handler in site.js. */
    transition: opacity var(--dur) var(--ease-spring), transform var(--dur) var(--ease-spring);
    /* The face the menu links use (client: "use the same font that is used for the menu for the dark
       mode/light mode button"). Chequers is a swashed display serif, so it wants more size and less
       tracking than the titling face it replaces — the same reasoning that applies to `.nav__links a`.
       Sized up from 0.78rem partly because Chequers is drawn for display use and starts to clog at
       titling sizes, and partly because the label is the only text in the bar that small. */
    font-family: var(--font-display);
    font-size: 0.85rem; letter-spacing: 0.045em; line-height: 1.2; text-transform: uppercase;
    color: var(--gold-text);
    white-space: nowrap;
  }
  /* the last ungated one: this sat inside the desktop media query, not a hover one, so a touch
     device still got it — the same fake-hover tap as everywhere else */
  @media (hover: hover) {
    .nav__theme:hover { color: var(--gold-deep); }
  }
  .nav__theme .theme-switch__track { width: 2.5rem; height: 1.46rem; }
  .nav__theme .theme-switch__knob { width: 1.12rem; height: 1.12rem; left: 2px; }
  :root[data-theme="dark"] .nav__theme .theme-switch__knob { transform: translateY(-50%) translateX(1.02rem); }
}

/* The corner placement, at the client's numbers: *"line it up to the same height as the menu bar and
   increase the distance to 50px from the right edge."* `top: 1.4rem` is exactly the value the nav bar
   uses (`.nav { top: 1.4rem }`, 22.4px), so the two start on the same line. 50px from the right edge.

   The breakpoint is 90rem, not 74rem, because the numbers have to fit: the switch is 94px wide, so
   50px from the edge plus the switch needs 144px of margin beside the centred bar. The bar is 72rem
   wide, so that margin only exists from a 1440px viewport up. Between 62rem and 90rem the switch keeps
   the under-the-bar position instead — floating in the corner there would put it on top of the bar. */
/* Recalculated for the wider bar: the box is 136px, the distance 50px, plus 8px of air, so the
   corner needs 194px of margin beside an 80rem bar — from a 1680px viewport up. Below that the box
   sits under the bar, still 50px in from the right edge. */
@media (min-width: 105rem) {
  .nav__theme {
    top: 1.4rem;
    right: calc(50px + env(safe-area-inset-right, 0px));
  }
}
