/*
Theme Name: Ceylon Veritas Gems
Theme URI: https://ceylonveritasgems.com
Author: Sameera
Author URI: https://ormc.lk
Description: Dark, modern, single-house theme for Ceylon Veritas Gems, a fine Ceylon gemstone house. Ported from the phase one static build; tokens, type scale and components per CLAUDE.md.
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: cvg
Domain Path: /languages/
Tags: one-column, two-columns, custom-menu, full-width-template, theme-options, threaded-comments,
*/
:root {
  color-scheme: light dark;

  /* Grounds and ink — CLAUDE.md token set */ 
  --cvg-navy: #0A1633;
  --cvg-gold: #C8A24C;
  --cvg-cream: #FAF8F2;
  --cvg-white: #FFFFFF;
  --cvg-script: #E9ECF6;
  --cvg-text: #22252D;
  --cvg-text-2: #4B5563;
  --cvg-surface: #111E42;
  --cvg-surface-2: #182A54;
  --cvg-border-dark: #24365F;
  --cvg-text-dark-2: #AEB6CC;
  --cvg-gold-hi: #E4C97A;
  --cvg-gold-shadow: #A67C33;
  --cvg-gold-hairline: rgba(200, 162, 76, 0.35);
  --cvg-hairline: rgba(10, 22, 51, 0.10);

  /* Decorative only: gradients and hero lighting. Never text, icons,
     borders or fills behind text. */
  --cvg-royal-glow: #1E3FB0;
  --cvg-royal-bright: #2C4FD6;

  /* Type families */
  --font-title: "Baskervville", Georgia, "Times New Roman", serif;
  --font-text: "DM Sans", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Type scale — every size on the page comes from this ramp.
     Display clamps top out at a 1200px viewport, where the container stops. */
  --fs-display: clamp(2.25rem, 5vw, 3.5rem);
  --fs-h2: clamp(1.75rem, 3.5vw, 2.5rem);
  --fs-h3: clamp(1.35rem, 2.4vw, 1.6rem);
  --fs-h4: 1.2rem;
  --fs-h5: 21px;
  --fs-h6: 19px;
  --fs-lead: 18px;
  --fs-body: 16px;
  --fs-small: 15px;
  --fs-caps: 14px;

  /* Leading — ratio grows as size shrinks */
  --lh-title: 1.14;
  --lh-snug: 1.25;
  --lh-body: 1.6;
  --lh-lead: 1.55;

  /* Uppercase tracking — one value for every micro-label */
  --ls-caps: 0.13em;

  /* Frame */
  --cvg-container: 1200px;
  --cvg-gutter: 2rem;
  --cvg-header-pad: clamp(20px, 3.5vw, 56px);
  --cvg-header-h: 80px;
  --cvg-control-h: 44px;
  /* Classic scrollbar width, measured at runtime. 100vw includes the
     scrollbar, which would make the hero bleed overshoot by half of it. */
  --sbw: 0px;

  /* Radius */
  --r-sm: 2px;
  --r-md: 5px;
  --r-lg: 8px;
  --r-pill: 999px;

  /* Motion */
  --ease-out: cubic-bezier(0.2, 0.7, 0.3, 1);
  --ease-soft: cubic-bezier(0.16, 1, 0.3, 1);
  --t-fast: 180ms var(--ease-out);
  --t-med: 320ms var(--ease-out);

  /* Arrow used by .btn, .btn-outline and .link-arrow. A mask, not text, so it
     draws the same shape without being announced by screen readers. */
  --cvg-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12h16M13 5l7 7-7 7'/%3E%3C/svg%3E");

  /* The arrow's chevron, same stroke without the shaft, for the caret on
     nav items that carry a panel (the two megas and the About dropdown). */
  --cvg-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");

  /* Tick used by .list-check, the same mask discipline as the arrow. */
  --cvg-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5 5L20 6.5'/%3E%3C/svg%3E");

  --bs-body-font-family: var(--font-text);
  --bs-body-bg: var(--cvg-navy);
  --bs-body-color: var(--cvg-script);
}

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

.svg-sprite {
  display: none;
}

html {
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-text);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  background: var(--cvg-navy);
  color: var(--cvg-script);
  /* clip, not hidden: it guards against stray horizontal overflow without
     creating a scroll container, so position: sticky keeps working. */
  overflow-x: clip;
  letter-spacing: 0.5px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Baskervville ships weight 400 only — never let a browser fake a bold. */
  font-synthesis: none;
}

/* Headings must never inherit Bootstrap's font-weight:500 onto the serif. */
h1, h2, h3, h4,
.h1, .h2, .h3, .h4 {
  font-family: var(--font-title);
  font-weight: 400;
}

h1, .h1 {
  font-size: var(--fs-display);
  line-height: 1.4;
  letter-spacing: 0.2px;
  text-transform: capitalize;
}

h2, .h2 { font-size: var(--fs-h2); line-height: 1.25; letter-spacing: 0.2px; }
h3, .h3 { font-size: var(--fs-h3); line-height: 1.3; }
h4, .h4 { font-size: var(--fs-h4); line-height: 1.4; }

h5, h6 {
  font-family: var(--font-text);
  font-weight: 500;
}

::selection {
  background: var(--cvg-gold);
  color: var(--cvg-navy);
}

/* Gold fails 3:1 on cream, so the ring is navy on light grounds and
   gold only on the navy ones. */
:focus-visible {
  outline: 2px solid var(--cvg-navy);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.site-header :focus-visible,
.site-footer :focus-visible,
.bg-navy :focus-visible,
.bg-navy-raised :focus-visible {
  outline-color: var(--cvg-gold);
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: var(--cvg-navy);
}

::-webkit-scrollbar-thumb {
  background: var(--cvg-border-dark);
  border-radius: var(--r-pill);
  border: 2px solid var(--cvg-navy);
}

section[id] {
  scroll-margin-top: calc(var(--cvg-header-h) + 16px);
}

img {
  max-width: 100%;
}

/* Content frame — 1200px. This sheet loads after Bootstrap, so the cap on
   the base rule wins over Bootstrap's per breakpoint .container widths at
   every viewport; there is no snap at any breakpoint. */
.container {
  width: 100%;
  max-width: var(--cvg-container);
  margin-inline: auto;
  --bs-gutter-x: 3rem;
}

@media (min-width: 992px) {
  .container {
    --bs-gutter-x: calc(var(--cvg-gutter) * 2);
  }
}

/* Row gutters. Bootstrap's .g- / .gx- / .gy- utilities are !important, so
   these are used WITHOUT a Bootstrap gutter class on the row. Declared
   unconditionally (not gated to >=992px) so sub-992px behaviour is stated
   rather than an accidental fallback to the container's own gutter. */
.gx-cvg {
  --bs-gutter-x: 3rem;
}

.gx-cvg-wide {
  --bs-gutter-x: 3rem;
}

.g-cvg {
  --bs-gutter-x: 3rem;
  --bs-gutter-y: 25px;
}

.gy-cvg {
  --bs-gutter-y: 50px;
}

/* Wider gutter only once the container's own padding (32px at >=992px) is
   large enough to absorb the extra half-gutter margin without the row
   overflowing the viewport (see .container's own >=992px override
   above, and note this rule must stay AFTER the unconditional .gx-cvg-wide
   base above so it wins the tie at equal specificity). */
@media (min-width: 992px) {
  .gx-cvg-wide {
    --bs-gutter-x: 3.5rem;
  }
}

/* --------------------------------------------------------------------------
   Utilities
   -------------------------------------------------------------------------- */
.object-cover {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.tnum { font-variant-numeric: tabular-nums; }
.balance { text-wrap: balance; }
.pretty { text-wrap: pretty; }

/* Measure caps */
.ch-32 { max-width: 32ch; }
.ch-40 { max-width: 40ch; }
.ch-48 { max-width: 48ch; }
.ch-56 { max-width: 56ch; }

.text-soft { color: var(--cvg-text-dark-2); }
.text-quiet { color: var(--cvg-text-2); margin-bottom: 0; }

/* Section grounds */
.bg-navy {
  background-color: var(--cvg-navy);
  /* script white @ 4% fading to 0 */
  background-image: linear-gradient(180deg, rgba(233, 236, 246, 0.04) 0%, rgba(233, 236, 246, 0) 220px);
  color: var(--cvg-script);
}

.bg-navy-raised {
  background-color: var(--cvg-surface);
  /* script white @ 4% fading to 0 */
  background-image: linear-gradient(180deg, rgba(233, 236, 246, 0.04) 0%, rgba(233, 236, 246, 0) 220px);
  color: var(--cvg-script);
}

.bg-cream {
  background-color: var(--cvg-cream);
  /* navy @ 2.8% fading to 0 */
  background-image: linear-gradient(180deg, rgba(10, 22, 51, 0.028) 0%, rgba(10, 22, 51, 0) 200px);
  color: var(--cvg-text);
}

/* Distinct from .bg-cream: flat colour, no top gradient wash. */
.bg-cream-deep {
  background-color: var(--cvg-cream);
  color: var(--cvg-text);
}

.bg-paper {
  background-color: var(--cvg-white);
  color: var(--cvg-text);
}

.hairline-top-dark { border-top: 1px solid var(--cvg-border-dark); }
.hairline-bottom-dark { border-bottom: 1px solid var(--cvg-border-dark); }
.hairline-top-light { border-top: 1px solid var(--cvg-hairline); }
.hairline-bottom-light { border-bottom: 1px solid var(--cvg-hairline); }


/* Shared "heading left, action right, rule under" block */
.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  padding-bottom: 24px;
  margin-bottom: 20px;
}

/* Reviews' heading sits alone in its .section-head (no lede paragraph), so
   the shared bottom margin above is not wanted here. */
#reviews .section-head {
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   Typography — titles in Baskervville, body and UI in DM Sans
   -------------------------------------------------------------------------- */
.hero-title,
.section-title,
.card-product-title,
.card-colour-name,
.card-info-value,
.card-guide-title,
.card-review-quote,
.flourish {
  font-family: var(--font-title);
  font-weight: 400;
  letter-spacing: -0.008em;
}

/* .hero-title's sizing and its 0.2px tracking live with the hero block, which
   sits after the shared group above and therefore wins the tie it used to
   need a stub here to win. */

/* Section headings, one tier */
.section-title {
  font-size: var(--fs-h2);
  line-height: var(--lh-title);
  letter-spacing: -0.015em;
  margin-bottom: 0;
}

.eyebrow {
  display: inline-block;
  font-family: var(--font-text);
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: 1.5px;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--cvg-navy);
  margin-bottom: 0;
}

.on-dark .eyebrow,
.eyebrow.on-dark {
  color: var(--cvg-gold-hi);
}


.lead-cvg {
  font-size: 17px;
  line-height: var(--lh-lead);
  font-weight: 400;
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   Links, .link-arrow. Primary ink on light, script white on dark, gold arrow.
   -------------------------------------------------------------------------- */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 44px;
  /* --fs-caps is 14px: the caps scale, same as .eyebrow and .fact-label. */
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  /* Primary ink on light, the same colour as the body text beside it. Every
     link on a navy ground carries .on-dark (see below), which takes it to
     script white; that variant also covers a link on a navy surface sitting
     inside a light section. */
  color: var(--cvg-text);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--t-fast), color var(--t-fast);
}

.link-arrow::after {
  content: "";
  flex: 0 0 auto;
  width: 0.85em;
  height: 0.85em;
  background-color: var(--cvg-gold-shadow);
  -webkit-mask: var(--cvg-arrow) center / contain no-repeat;
  mask: var(--cvg-arrow) center / contain no-repeat;
  transition: transform var(--t-fast);
}

.link-arrow:hover {
  border-bottom-color: var(--cvg-gold-shadow);
}

.link-arrow:hover::after,
.link-arrow:focus::after {
  transform: translateX(3px);
}

.on-dark .link-arrow,
.link-arrow.on-dark {
  color: var(--cvg-script);
}

.on-dark .link-arrow::after,
.link-arrow.on-dark::after {
  background-color: var(--cvg-gold);
}

.on-dark .link-arrow:hover,
.link-arrow.on-dark:hover {
  border-bottom-color: var(--cvg-gold);
}

@media (prefers-reduced-motion: reduce) {
  .link-arrow,
  .link-arrow::after {
    transition: none;
  }

  .link-arrow:hover::after,
  .link-arrow:focus::after {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   Buttons — .btn and .btn-outline. The arrow is drawn by CSS, never typed
   into the markup. Navy on gold is 7.4:1; white on gold is 2.4:1 and banned.
   -------------------------------------------------------------------------- */
.btn,
.btn-outline {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 8px 24px;
  border-radius: var(--r-sm);
  font-family: var(--font-text);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: 0.3px;
  line-height: 1.2;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast), transform var(--t-fast);
}

.btn::after,
.btn-outline::after {
  content: "";
  flex: 0 0 auto;
  width: 0.85em;
  height: 0.85em;
  background-color: currentColor;
  -webkit-mask: var(--cvg-arrow) center / contain no-repeat;
  mask: var(--cvg-arrow) center / contain no-repeat;
  transition: transform var(--t-fast);
}

.btn:hover::after,
.btn:focus::after,
.btn-outline:hover::after,
.btn-outline:focus::after {
  transform: translateX(3px);
}

.btn:active,
.btn-outline:active {
  transform: translateY(1px);
}

.btn {
  background: var(--cvg-gold);
  border-color: var(--cvg-gold);
  color: var(--cvg-navy);
  font-weight: 700;
  text-transform: capitalize;
}

/* Hover lightens the gold rather than swapping to navy. Navy text stays:
   it measures about 11:1 on the gold highlight. */
.btn:hover,
.btn:focus {
  background: var(--cvg-gold-hi);
  border-color: var(--cvg-gold-hi);
  color: var(--cvg-navy);
}

/* Outline CTA: navy grounds only. The border sits at .38 alpha, which
   composites to 3.1:1 on navy, just clearing the non-text minimum. */
.btn-outline {
  background: transparent;
  border-color: rgba(233, 236, 246, 0.38);
  color: var(--cvg-script);
}

.btn-outline:hover,
.btn-outline:focus {
  background: var(--cvg-gold);
  border-color: var(--cvg-gold);
  color: var(--cvg-navy);
}

/* Bootstrap's .btn:focus-visible sets outline:0 at (0,2,0). These tie that
   specificity and load later, so they win. */
.btn:focus-visible,
.btn-outline:focus-visible {
  outline: 2px solid var(--cvg-gold);
  outline-offset: 2px;
  box-shadow: none;
}

.bg-cream .btn:focus-visible,
.bg-cream-deep .btn:focus-visible,
.bg-paper .btn:focus-visible {
  outline-color: var(--cvg-navy);
}

@media (prefers-reduced-motion: reduce) {
  .btn,
  .btn-outline,
  .btn::after,
  .btn-outline::after {
    transition: none;
  }

  .btn:hover::after,
  .btn:focus::after,
  .btn-outline:hover::after,
  .btn-outline:focus::after {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   Header — full-bleed bar, 1200px content beneath it
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 1030;
  /* navy @ 70% */
  background: rgba(10, 22, 51, 0.70);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  /* script white @ 10% */
  border-bottom: 1px solid rgba(233, 236, 246, 0.1);
  transition: background-color var(--t-med), box-shadow var(--t-med), border-color var(--t-med);
}

/* No backdrop-filter (older Firefox): fall back to an opaque bar. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header { background: var(--cvg-navy); }
}

.site-header.is-scrolled {
  /* navy @ 92% */
  background: rgba(10, 22, 51, 0.92);
  /* script white @ 6% hairline; drop shadow removed, no elevation scale */
  box-shadow: 0 1px 0 rgba(233, 236, 246, 0.06);
}

.site-header .navbar {
  padding-block: 0;
}

/* Full width: replaces .container so the bar is not capped at 1200px. */
.header-inner {
  display: flex;
  flex-wrap: inherit;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding-block: 20px;
  padding-inline: var(--cvg-header-pad);
  transition: padding var(--t-med);
}

/* Scrolling reduces the bar: the padding halves and the ground deepens. */
.site-header.is-scrolled .header-inner {
  padding-block: 10px;
}

/* Centered main menu: brand left, nav dead-centre in the full header width,
   actions right. #primaryNav collapses to display:contents so its two
   children (the nav list and the action buttons) become direct grid items
   instead of being centered only within the collapse's own box.
   Gated at xl (1200px), not lg (992px): the five nav labels plus the
   "Talk to a Gemologist" button need ~1120px of content width just to lay
   out on one line, so anything narrower has to stay on the hamburger menu
   or the fixed side columns force the centre track to wrap. */
@media (min-width: 1200px) {
  .header-inner {
    display: grid;
    /* Equal-width side columns, sized exactly to the wider side (the
       action buttons), so the centre track — and the nav inside it —
       sits on the true midline of the header rather than the midpoint of
       whatever space happens to be left between two unevenly sized
       brand/action blocks. */
    grid-template-columns: 258px 1fr 258px;
    column-gap: 20px;
  }

  #primaryNav {
    display: contents !important;
  }

  .brand-lockup {
    justify-self: start;
  }

  .header-nav {
    justify-self: center;
  }

  .header-actions {
    justify-self: end;
  }
}

/* Horizontal lockup: ornament + wordmark, cropped from the stacked logo so a
   slim bar is possible without shrinking the wordmark into illegibility. */
.brand-lockup {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 0;
  margin: 0;
  flex: 0 0 auto;
}

.brand-mark {
  width: 39px;
  height: 39px;
  display: block;
  flex: 0 0 auto;
}

.brand-wordmark {
  width: 166px;
  height: auto;
  aspect-ratio: 541 / 152;
  display: block;
}

.header-nav {
    column-gap: 30px;
    row-gap: 4px;
}

/* Between the xl breakpoint and 1400px the five nav labels, their three
   carets and both action buttons only just fit the centre grid track, and
   the track sizes to the nav's min-content. The gap tightens and the fixed
   side columns give back what their content actually uses (the brand
   lockup is 217px, the action pair about 202px), still equal so the
   centre track keeps the true midline; without this the carets wrap the
   whole bar onto two lines between 1200 and about 1285px. */
@media (min-width: 1200px) and (max-width: 1399.98px) {
  .header-nav { column-gap: 14px; }

  .header-inner {
    grid-template-columns: 220px minmax(0, 1fr) 220px;
  }
}

/* Bootstrap's .navbar-expand-lg .navbar-nav .nav-link injects 8px of inline
   padding at >=992px; this ties its specificity and loads later. */
.site-header .navbar-nav .nav-link-cvg {
  position: relative;
  padding: 8px 0;
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--cvg-text-dark-2);
  transition: color var(--t-fast);
}

.site-header .navbar-nav .nav-link-cvg:hover,
.site-header .navbar-nav .nav-link-cvg:focus {
  color: var(--cvg-script);
}

/* Underline grows from the left and hugs the text exactly. */
.nav-link-cvg::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 2px;
  width: 100%;
  height: 1px;
  background: var(--cvg-gold);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-med);
}

.nav-link-cvg:hover::after,
.nav-link-cvg:focus::after {
  transform: scaleX(1);
}

/* Gemstones mega menu. A full width panel under the bar, anchored to the
   sticky header (the nearest positioned ancestor). It lives inside its nav
   item, so hovering the panel keeps the item's hover chain alive, and the
   short visibility delay on close bridges the cursor's path across the
   header's bottom padding. Focus within opens it for keyboard users. */
@media (min-width: 1200px) {
  .has-mega .mega {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    /* Solid navy: at any translucency the hero's white headline ghosts
       through the panel, which reads as a defect rather than depth. */
    background: var(--cvg-navy);
    border-top: 1px solid var(--cvg-border-dark);
    border-bottom: 1px solid var(--cvg-border-dark);
    /* Navy at 35%: the panel floats over the page rather than sitting
       flush against it. */
    box-shadow: 0 24px 48px rgba(10, 22, 51, 0.35);
    opacity: 0;
    visibility: hidden;
    transform: translateY(6px);
    transition: opacity var(--t-fast), transform var(--t-fast),
      visibility 0s linear 250ms;
  }

  .has-mega:hover .mega,
  .has-mega:focus-within .mega {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition-delay: 0s;
  }

  /* Three ruled columns: the sapphire colours split in two, the other
     gems in one, then the concierge card. Hairline rules carry the
     architecture, so the lists never float loose on the navy. */
  .mega-inner {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 0.9fr) minmax(0, 1.02fr);
    padding-block: 44px 52px;
  }

  .mega-group {
    padding-right: 48px;
  }

  .mega-group + .mega-group {
    border-left: 1px solid var(--cvg-border-dark);
    padding-left: 48px;
  }

  .mega-label {
    font-size: var(--fs-caps);
    font-weight: 500;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    color: var(--cvg-gold-hi);
    margin-bottom: 20px;
  }

  .mega-links {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 2px;
  }

  .mega-links-split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 28px;
  }

  /* Family names in the title face, with the house arrow sliding in on
     hover the way it nudges on .btn and .link-arrow. */
  .mega-link {
    position: relative;
    display: inline-flex;
    align-items: center;
    padding: 7px 0;
    font-family: var(--font-title);
    font-size: var(--fs-lead);
    font-weight: 400;
    line-height: var(--lh-snug);
    color: var(--cvg-script);
    text-decoration: none;
    transition: color var(--t-fast), padding-left var(--t-fast);
  }

  .mega-link::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 0.7em;
    height: 0.7em;
    background-color: var(--cvg-gold);
    -webkit-mask: var(--cvg-arrow) center / contain no-repeat;
    mask: var(--cvg-arrow) center / contain no-repeat;
    opacity: 0;
    transform: translate(-8px, -50%);
    transition: opacity var(--t-fast), transform var(--t-fast);
  }

  .mega-link:hover,
  .mega-link:focus {
    color: var(--cvg-white);
    padding-left: 24px;
  }

  .mega-link:hover::before,
  .mega-link:focus::before {
    opacity: 1;
    transform: translate(0, -50%);
  }

  .mega-all {
    margin-top: 18px;
  }

  /* The concierge card: the one raised surface on the panel, restating
     the concierge lead's first clause. */
  .mega-note {
    align-self: start;
    background: var(--cvg-surface);
    border: 1px solid var(--cvg-border-dark);
    border-radius: var(--r-lg);
    padding: 26px 28px 22px;
  }

  /* Rich links: a name in the title face over a plain-language note, for
     panels whose destinations are not self-explanatory. The arrow sits on
     the first line rather than the middle of the block. */
  .mega-links-rich { gap: 6px; }

  .mega-links-rich .mega-link {
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
    /* Longhands, not the padding shorthand: this variant only means to
       change the vertical rhythm, and a shorthand here would reset
       padding-left and silently beat the hover indent above, which sits at
       the same specificity and earlier in the file. */
    padding-top: 9px;
    padding-bottom: 9px;
  }

  .mega-links-rich .mega-link::before { top: 20px; }

  .mega-link-note {
    font-family: var(--font-text);
    font-size: var(--fs-small);
    line-height: 1.45;
    color: var(--cvg-text-dark-2);
    transition: color var(--t-fast);
  }

  .mega-link:hover .mega-link-note,
  .mega-link:focus .mega-link-note { color: var(--cvg-script); }

  /* A second label inside one column, where a panel stacks two groups. */
  .mega-label-2 { margin-top: 28px; }

  /* The pricing guide panel: three more even columns than the Gemstones
     panel, whose first column carries a two-column split. */
  .mega-guide .mega-inner {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) minmax(0, 0.95fr);
  }

  .mega-note-line {
    font-family: var(--font-title);
    font-size: var(--fs-lead);
    line-height: var(--lh-snug);
    color: var(--cvg-script);
    text-wrap: pretty;
    margin-bottom: 10px;
  }
}

/* The About dropdown: the mega machinery at its smallest. A narrow navy
   panel inside its own nav item, wearing the mega's solid ground, seam
   colour, shadow and close delay. The item anchors it, and the panel's top
   is computed onto the header's bottom edge (the item centre plus half the
   header height, the two centres being aligned) so it hangs from the bar
   exactly as the mega does; the 250ms visibility delay bridges the
   cursor's path across the bar's lower padding. Opens on hover and on
   focus within, so it works by keyboard. */
@media (min-width: 1200px) {
  .has-drop {
    position: relative;
  }

  /* The caret on every item that carries a panel: the two megas and the
     About dropdown wear the same one. The house chevron in currentColor,
     so it follows the link's own states, and it turns over while the
     panel is open. */
  .nav-caret {
    display: inline-block;
    width: 0.6em;
    height: 0.6em;
    margin-left: 6px;
    vertical-align: -0.02em;
    background-color: currentColor;
    -webkit-mask: var(--cvg-caret) center / contain no-repeat;
    mask: var(--cvg-caret) center / contain no-repeat;
    transition: transform var(--t-fast);
  }

  .has-mega:hover .nav-caret,
  .has-mega:focus-within .nav-caret,
  .has-drop:hover .nav-caret,
  .has-drop:focus-within .nav-caret {
    transform: rotate(180deg);
  }

  .has-drop .drop {
    position: absolute;
    top: calc(50% + var(--cvg-header-h) / 2);
    left: 50%;
    min-width: 300px;
    margin: 0;
    padding: 18px 28px 20px;
    display: grid;
    gap: 6px;
    list-style: none;
    background: var(--cvg-navy);
    border: 1px solid var(--cvg-border-dark);
    border-radius: 0 0 var(--r-md) var(--r-md);
    box-shadow: 0 24px 48px rgba(10, 22, 51, 0.35);
    opacity: 0;
    visibility: hidden;
    transform: translate(-50%, 6px);
    transition: opacity var(--t-fast), transform var(--t-fast),
      visibility 0s linear 250ms;
  }

  .has-drop:hover .drop,
  .has-drop:focus-within .drop {
    opacity: 1;
    visibility: visible;
    transform: translate(-50%, 0);
    transition-delay: 0s;
  }

  /* is-scrolled halves the bar's padding, lifting its bottom edge 10px
     nearer the item centre this offset is computed from; follow it. */
  .site-header.is-scrolled .has-drop .drop {
    top: calc(50% + var(--cvg-header-h) / 2 - 10px);
  }

  /* The gold underline keeps hugging the text: the caret adds 0.6em plus
     its 6px margin to the link's content box, so the line stops short of
     it, matching the plain items beside these. */
  .has-mega > .nav-link-cvg::after,
  .has-drop > .nav-link-cvg::after {
    width: calc(100% - 0.6em - 6px);
  }

  /* Escape parks a panel shut (custom.js adds the class, and removes it
     when pointer or focus leaves the item). After the open rules at the
     same specificity, so it wins while present. */
  .has-mega.is-dismissed .mega,
  .has-drop.is-dismissed .drop {
    opacity: 0;
    visibility: hidden;
    transition: none;
  }
}

/* Below the desktop nav the mega panel stays out of the hamburger drawer;
   the Gemstones link itself still works. */
@media (max-width: 1199.98px) {
  .mega {
    display: none;
  }
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
}

/* Circular icon button — pairs with the pill Contact button */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--cvg-control-h);
  height: var(--cvg-control-h);
  padding: 0;
  /* script white @ 24% */
  border: 1px solid rgba(233, 236, 246, 0.24);
  border-radius: var(--r-pill);
  color: var(--cvg-script);
  background: transparent;
  text-decoration: none;
  transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast), transform var(--t-fast);
}

.icon-btn svg {
  width: 20px;
  height: 20px;
  display: block;
  fill: currentColor;
}

.icon-btn:hover,
.icon-btn:focus {
  color: var(--cvg-navy);
  background: var(--cvg-gold);
  border-color: var(--cvg-gold);
  transform: translateY(-1px);
}

/* Burger — animates to a close cross */
.site-header .navbar-toggler {
  width: var(--cvg-control-h);
  height: var(--cvg-control-h);
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* script white @ 24% */
  border: 1px solid rgba(233, 236, 246, 0.24);
  border-radius: var(--r-sm);
  box-shadow: none;
}

/* This sheet loads after Bootstrap, so the display above would otherwise
   beat .navbar-expand-xl .navbar-toggler{display:none} at equal specificity. */
@media (min-width: 1200px) {
  .site-header .navbar-toggler {
    display: none;
  }
}

.burger,
.burger::before,
.burger::after {
  display: block;
  width: 18px;
  height: 1.5px;
  background: var(--cvg-script);
  border-radius: 2px;
  transition: transform var(--t-med), background-color var(--t-fast);
}

.burger {
  position: relative;
}

.burger::before,
.burger::after {
  content: "";
  position: absolute;
  left: 0;
}

.burger::before { top: -6px; }
.burger::after { top: 6px; }

.navbar-toggler[aria-expanded="true"] .burger { background: transparent; }
.navbar-toggler[aria-expanded="true"] .burger::before { transform: translateY(6px) rotate(45deg); }
.navbar-toggler[aria-expanded="true"] .burger::after { transform: translateY(-6px) rotate(-45deg); }

/* Mobile panel — the bar is translucent, so the dropdown needs its own ground */
@media (max-width: 1199.98px) {
  .nav-panel {
    display: none;
  }

  .nav-panel.is-open {
    display: block;
  }

  .site-header .nav-panel {
    margin-inline: calc(-1 * var(--cvg-header-pad));
    padding: 4px var(--cvg-header-pad) 20px;
    background: var(--cvg-navy);
    /* script white @ 10% */
    border-top: 1px solid rgba(233, 236, 246, 0.1);
  }

  .header-nav {
    padding-block: 8px;
  }

  .site-header .navbar-nav .nav-link-cvg {
    font-size: var(--fs-lead);
    padding: 10px 0;
  }

  /* The About group in the hamburger: no dropdown to operate, the two
     links sit inline under their label, indented behind a hairline. */
  .nav-caret {
    display: none;
  }

  .drop {
    list-style: none;
    margin: 0 0 6px;
    padding: 0 0 0 16px;
    border-left: 1px solid var(--cvg-border-dark);
  }

  .drop .mega-link {
    display: block;
    /* 10px, not 8: at the body size this is what clears the 44px touch
       target the accessibility rules set. */
    padding: 10px 0;
    font-size: var(--fs-body);
    color: var(--cvg-text-dark-2);
    text-decoration: none;
    transition: color var(--t-fast);
  }

  .drop .mega-link:hover,
  .drop .mega-link:focus {
    color: var(--cvg-script);
  }

  /* The rich links' plain-language notes are a desktop nicety; the
     hamburger stays terse. */
  .drop .mega-link-note {
    display: none;
  }

  .header-actions {
    padding-top: 12px;
  }
}

/* --------------------------------------------------------------------------
   Hero. Three zones: eyebrow, title and a browse action ranged right in the
   left column, the stone centred, the supporting note and the talk action on
   the right. The image, eyebrow and title rotate; the note and both actions
   never move.
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  background-color: var(--cvg-navy);
  /* Wins over .bg-navy's top-glow gradient by source order. Decorative silk
     texture; the navy colour beneath is the real ground if it fails. */
  background-image: url("assets/img/Ceylon-Veritas-Gems-Hero-Bg.webp");
  background-size: cover;
  background-position: center;
}

.hero .container {
  position: relative;
}

.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 40px;
  align-items: center;
  min-height: calc(100svh - var(--cvg-header-h));
  padding-block: 64px 72px;
}

@media (min-width: 992px) {
  /* One row, split three, six, three: words and browse action left, the stone
     across the centre half, the concierge note right. The column gap is wide
     so the stone keeps clear air on both sides. */
  .hero-grid {
    grid-template-columns: minmax(0, 3fr) minmax(0, 6fr) minmax(0, 3fr);
    gap: 48px clamp(48px, 5vw, 72px);
  }
}

.hero-zone {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 30px;
}

.hero-rotator {
  position: relative;
  width: 100%;
}

.hero-slide-text {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  pointer-events: none;
}

.hero-title {
  font-size: 38px;
  line-height: 1.4;
  letter-spacing: 0.2px;
  text-transform: capitalize;
  /* Overrides the .balance utility: in a three column track, balancing shreds
     the line into single words, where pretty fills each line and only guards
     the last. */
  text-wrap: pretty;
  margin-bottom: 0;
}

.hero-note {
  max-width: 38ch;
  margin-bottom: 0;
}

.hero-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--r-lg);
  overflow: hidden;
}

.hero-stage img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Slide states. Hidden starts are gated on scripting so a browser with JS off
   sees slide one in full, and the first slide carries the same 5s failsafe as
   the reveal system, so a dead script can never strand an empty hero. */
.hero-slide-text .eyebrow,
.hero-slide-text .hero-title {
  transition: opacity 600ms var(--ease-soft), transform 600ms var(--ease-soft);
}

.hero-slide-text .hero-title {
  transition-delay: 120ms;
}

.hero-stage img {
  transition: opacity 800ms var(--ease-soft), transform 800ms var(--ease-soft);
}

@media (scripting: enabled) {
  /* Everything travels leftward: in from the right, out to the left. */
  .js-hero .hero-slide-text .eyebrow,
  .js-hero .hero-slide-text .hero-title {
    opacity: 0;
    transform: translateX(44px);
  }

  .js-hero .hero-stage img {
    opacity: 0;
    transform: translateX(44px);
  }

  .js-hero .hero-slide-text:first-child .eyebrow,
  .js-hero .hero-slide-text:first-child .hero-title,
  .js-hero .hero-stage img:first-child {
    animation: cvg-reveal-failsafe 0s linear 5s forwards;
  }

  /* Once the script has taken charge it adds .hero-live, and the failsafe
     stands down for good. Without this, the filled animation would outrank
     every later opacity declaration (its :first-child selector is 0,4,0
     against is-active's 0,3,0) and slide one's text would stay visible
     underneath slide two's after the 5s mark. */
  .js-hero.hero-live .hero-slide-text:first-child .eyebrow,
  .js-hero.hero-live .hero-slide-text:first-child .hero-title,
  .js-hero.hero-live .hero-stage img:first-child {
    animation: none;
  }
}

/* The first words carry no entrance at all: the script marks slide one
   hero-instant for its opening frame, so the eyebrow and title are simply
   there when the page is. The class comes off straight after, restoring the
   transition for the slide's later exits. */
.hero-slide-text.hero-instant .eyebrow,
.hero-slide-text.hero-instant .hero-title {
  transition: none;
}

.hero-slide-text.is-active {
  pointer-events: auto;
}

.hero-slide-text.is-active .eyebrow,
.hero-slide-text.is-active .hero-title,
.hero-stage img.is-active {
  opacity: 1;
  transform: none;
  animation: none;
}

/* Leaving: out to the left, the eyebrow a beat ahead of the title, so the
   outgoing and incoming lines read as one continuous leftward movement. */
.hero-slide-text.is-leaving .eyebrow {
  opacity: 0;
  transform: translateX(-44px);
  transition-delay: 0ms;
}

.hero-slide-text.is-leaving .hero-title {
  opacity: 0;
  transform: translateX(-44px);
  transition-delay: 100ms;
}

.hero-stage img.is-leaving {
  opacity: 0;
  transform: translateX(-44px);
}

@media (prefers-reduced-motion: reduce) {
  .hero-slide-text .eyebrow,
  .hero-slide-text .hero-title,
  .hero-stage img {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   Cards (stones, trade)
   -------------------------------------------------------------------------- */
/* White on cream is barely a percent and a half apart in luminance, so the
   card needs a hairline to read as an object rather than floating text. */
.card-product,
.card-guide {
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

/* Very light lift on hover; navy at 8% so no new hex enters the palette. */
.card-product:hover,
.card-product:focus {
  box-shadow: 0 8px 20px rgba(10, 22, 51, 0.08);
}

.card-guide:hover {
  border-bottom-color: var(--cvg-gold-shadow);
}

/* News cards lift like the product cards: shadow only, no gold base
   hairline; the buyer's guide tiles keep theirs. */
.card-grid-3 .card-guide:hover,
.card-grid-3 .card-guide:focus-visible {
  border-bottom-color: var(--cvg-hairline);
  box-shadow: 0 8px 20px rgba(10, 22, 51, 0.08);
}

/* Stone grid. Deterministic column counts: auto-fit leaves orphan cells at
   some widths, and an orphan reads as a missing stone rather than a layout. */
.card-grid:not(.owl-loaded) {
  display: grid;
  gap: 20px 15px;
}

@media (min-width: 576px) {
  .card-grid:not(.owl-loaded) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 992px) {
  .card-grid:not(.owl-loaded) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* The news listing runs three to the row where the stones grid runs four. */
@media (min-width: 992px) {
  .card-grid-3:not(.owl-loaded) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* The whole card is the link, like the colour tile and the guide card. */
.card-product {
  display: flex;
  flex-direction: column;
  color: var(--cvg-text);
  text-decoration: none;
}

/* Square, because a cut stone is as tall as it is wide and a 4:3 crop wastes
   the frame on the cloth either side of it. */
.card-product-thumb {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--cvg-cream);
}

.card-product-body {
  padding: 20px 20px 22px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  flex: 1 1 auto;
}

/* Certified marker. Solid navy rather than gold: gold is reserved for the one
   verification moment, and four gold badges in a row would spend it here. */
.card-product-cert {
  position: absolute;
  top: 10px;
  left: 10px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* navy @ 72%, blurred: legible over any ground the photograph has */
  background: rgba(10, 22, 51, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--cvg-white);
  border-radius: var(--r-sm);
  padding: 6px 8px;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: var(--ls-caps);
  line-height: 1;
  text-transform: uppercase;
  margin-bottom: 0;
}

.card-product-cert::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--cvg-gold);
  flex: 0 0 auto;
}

/* Two lines are reserved whether or not the name needs them, so every card in
   a row keeps the same internal rhythm and the gap above the price is constant
   rather than whatever the title length leaves over. */
/* A stone whose report has not been issued cannot wear the certified marker,
   so it takes the outline treatment instead. This is a designed state, not a
   greyed card: the stone is still shown and still named, the page simply does
   not claim figures it cannot yet stand behind. */
.card-product-cert-pending {
  /* script white @ 45% ring on the same scrim; the hollow dot and the ring,
     not colour alone, say this one is different */
  border: 1px solid rgba(233, 236, 246, 0.45);
  color: var(--cvg-script);
  padding: 5px 7px;
}

.card-product-cert-pending::before {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--cvg-gold-shadow);
}

.card-product-title {
  font-size: 24px;
  line-height: var(--lh-snug);
  min-height: calc(var(--lh-snug) * 2em);
  color: var(--cvg-text);
  margin-bottom: 0;
}

.card-product-meta {
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--cvg-text-2);
  margin-bottom: 0;
}

/* The foot row: price left in gold serif, the arrow pinned to the right edge.
   Sits on the card's baseline so a row of cards aligns whatever the titles
   wrap to. Gold shadow, not full gold: #A67C33 measures 3.78:1 on white where
   #C8A24C fails at 2.4:1. Note: at 20px the price sits below the 24px
   large-text threshold, so 3.78:1 is under the 4.5:1 normal-text bar; set at
   the client's instruction on 2026-08-16, recorded in CLAUDE.md. */
.card-product-foot {
  display: flex;
  align-items: center;
  gap: 10px;
  align-self: stretch;
  margin-top: auto;
  padding-top: 16px;
}

.card-product-foot::after {
  content: "";
  width: 15px;
  height: 15px;
  margin-left: auto;
  background-color: var(--cvg-gold-shadow);
  -webkit-mask: var(--cvg-arrow) center / contain no-repeat;
  mask: var(--cvg-arrow) center / contain no-repeat;
  transition: transform var(--t-fast);
}

.card-product:hover .card-product-foot::after,
.card-product:focus .card-product-foot::after {
  transform: translateX(3px);
}

.card-product-price {
  font-family: var(--font-title);
  font-size: 20px;
  white-space: nowrap;
  line-height: 1.2;
  color: var(--cvg-gold-shadow);
  margin-bottom: 0;
}
.card-guide {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
    padding: 28px 26px 26px;
    text-decoration: none;
}
.card-guide-kicker {
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-gold-shadow);
}
.card-guide-title {
    color: var(--cvg-text);
    margin-bottom: 20px;
}
.card-guide-note {
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--cvg-text-2);
  margin-bottom: 10px;
}

/* Reads as the card's action but is not a nested control: the card itself
   is the anchor, so the label is presentational and aria-hidden. */
.card-guide-cta {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-navy);
}

.card-guide-cta::after {
  content: "";
  width: 0.85em;
  height: 0.85em;
  background-color: var(--cvg-gold-shadow);
  -webkit-mask: var(--cvg-arrow) center / contain no-repeat;
  mask: var(--cvg-arrow) center / contain no-repeat;
  transition: transform var(--t-fast);
}

.card-guide:hover .card-guide-cta::after,
.card-guide:focus-visible .card-guide-cta::after {
  transform: translateX(3px);
}

/* News cards: a guide card carrying its entry's photograph. The thumb
   bleeds to the card edges, so its margins mirror the card's 28px 26px
   padding; change one and the other follows. The card's own overflow
   clip rounds the top corners. */
.card-guide-thumb {
  align-self: stretch;
  margin: -28px -26px 0;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--cvg-cream);
}

.card-guide-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}


/* --------------------------------------------------------------------------
   Gems by colour
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Carousel. Reusable: the behaviour is driven by data attributes on
   .js-carousel, so a second one needs markup only.
   -------------------------------------------------------------------------- */
.carousel {
  position: relative;
}

/* The dots row, declared once so anything that needs to line up with the
   images rather than with the whole carousel can subtract it. */
:root {
  --carousel-dots-gap: 30px;
  --carousel-controls-h: calc(var(--carousel-dots-gap) + var(--cvg-control-h));
}

/* Owl hides .owl-carousel until it adds .owl-loaded, so a CDN failure would
   leave an empty section. Until then the track renders as the grid it
   replaced, which means the stones stay visible whatever happens to the
   script. Two columns is the floor at every width: this section exists so a
   buyer can compare hues side by side, and one column destroys the only thing
   it does. */
.carousel-track:not(.owl-loaded) {
  display: grid;
}

/* Each carousel declares its own fallback columns, because the right count is
   a property of the content, not of the component. */
.card-colour-grid:not(.owl-loaded) {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 25px 20px;
}

@media (min-width: 768px) {
  .card-colour-grid:not(.owl-loaded) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 992px) {
  .card-colour-grid:not(.owl-loaded) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Owl stretches items to the tallest in view; make the card fill that height
   so a row of tiles keeps one baseline. */
.carousel-track .owl-item .card-colour,
.carousel-track .owl-item .card-product {
  height: 100%;
  width: 100%;
}

.carousel-track .owl-stage {
  display: flex;
}

.carousel-track .owl-item {
  display: flex;
}

/* Owl's default dots are grey pills. These are the project's own. The row is
   given the full control height so the dots and the pause button share one
   band beneath the cards, rather than the button floating over the last one. */
.carousel-track .owl-dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  min-height: var(--cvg-control-h);
  margin-top: var(--carousel-dots-gap);
}

.carousel-track .owl-dot span {
  display: block;
  width: 8px;
  height: 8px;
  margin: 0;
  border-radius: var(--r-pill);
  background: var(--cvg-border-dark);
  transition: background-color var(--t-fast);
}

.carousel-track .owl-dot:hover span {
  background: var(--cvg-text-dark-2);
}

.carousel-track .owl-dot.active span {
  background: var(--cvg-gold);
}

.carousel-track .owl-dot:focus-visible {
  outline: 2px solid var(--cvg-gold);
  outline-offset: 3px;
  border-radius: var(--r-pill);
}

/* The stone is the product, so it gets the tile. The old layout gave it a 76px
   thumbnail beside the text, which made the one thing being sold the smallest
   element in the section. */
.card-colour {
  display: flex;
  flex-direction: column;
  background: var(--cvg-surface);
  border: 1px solid var(--cvg-border-dark);
  border-radius: var(--r-md);
  overflow: hidden;
  color: var(--cvg-script);
  text-decoration: none;
  transition: background-color var(--t-fast), border-color var(--t-fast);
}

.card-colour:hover,
.card-colour:focus {
  background: var(--cvg-surface-2);
  border-color: var(--cvg-gold);
  color: var(--cvg-script);
}

.card-colour-thumb {
  aspect-ratio: 1 / 1;
  display: block;
  overflow: hidden;
  background: var(--cvg-surface-2);
}

.card-colour-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 16px 16px 18px;
  min-width: 0;
  flex: 1 1 auto;
}

.card-colour-name {
  font-size: 24px;
  line-height: var(--lh-snug);
}

.card-colour-desc {
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--cvg-text-dark-2);
}

/* Pinned to the foot so the count sits on one baseline across a row, whatever
   the descriptor's line count. */
.card-colour-count {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  align-self: stretch;
  margin-top: auto;
  padding-top: 10px;
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--cvg-text-dark-2);
}

/* Same hover arrow as the product price, full gold on the dark tile. */
.card-colour-count::after {
  content: "";
  width: 15px;
  height: 15px;
  margin-left: auto;
  background-color: var(--cvg-gold);
  -webkit-mask: var(--cvg-arrow) center / contain no-repeat;
  mask: var(--cvg-arrow) center / contain no-repeat;
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity var(--t-fast), transform var(--t-fast);
}

.card-colour:hover .card-colour-count::after,
.card-colour:focus .card-colour-count::after {
  opacity: 1;
  transform: none;
}

/* Three zones: an eyebrow rail, the copy and media stacked in the centre, and
   the aside beside the media. The media and the copy share column two so the
   images line up with the heading rather than with the eyebrow. */
.valley-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 30px;
}

@media (min-width: 992px) {
  .valley-grid {
    grid-template-columns: 150px minmax(0, 1.7fr) minmax(0, 1fr);
    column-gap: 40px;
    row-gap: 55px;
    align-items: start;
  }

  .valley-eyebrow { grid-column: 1; grid-row: 1; margin-top: 8px; }
  .valley-copy    { grid-column: 2; grid-row: 1; }
  .valley-media   { grid-column: 2; grid-row: 2; }
  .valley-aside   { grid-column: 3; grid-row: 2; }
  .stat-band      { grid-column: 1 / -1; grid-row: 3; }

  /* The media and the quote share a row, so both stretch to it and the quote
     panel fills the height the images set. */
  .valley-media,
  .valley-aside {
    align-self: stretch;
  }

  /* The quote lines up with the photographs, not with the carousel as a whole,
     so it stops short of the dots row beneath them. */
  .valley-aside {
    display: flex;
    padding-bottom: var(--carousel-controls-h);
  }
}

.valley-copy > :last-child,
.valley-aside > :last-child {
  margin-bottom: 0;
}

/* One column, the two paragraphs stacked. */
.valley-copy-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
  max-width: 62ch;
}

.valley-copy-cols > p {
  margin-bottom: 0;
}

/* Two squares side by side, the shape the reference sets and the shape a
   loose stone photographs into. */
.valley-media-grid:not(.owl-loaded) {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
}

.valley-shot {
  aspect-ratio: 1 / 1;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--cvg-white);
}

.carousel-track .owl-item .valley-shot {
  width: 100%;
}

/* Figures band. Hairline divided rather than boxed, so it reads as a footing
   under the section rather than a fifth card competing with the grids above. */
.stat-band {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  border-top: 1px solid var(--cvg-hairline);
  margin: 0;
}

@media (min-width: 576px) {
  .stat-band { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 992px) {
  .stat-band { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.stat {
  padding: 30px 28px 30px 0;
  border-bottom: 1px solid var(--cvg-hairline);
}

@media (min-width: 576px) {
  /* Vertical rules between columns only, so the band never ends on a stray
     edge at whichever count the breakpoint is showing. */
  .stat:not(:nth-child(2n + 1)) {
    padding-left: 28px;
    border-left: 1px solid var(--cvg-hairline);
  }
}

@media (min-width: 992px) {
  .stat:not(:first-child) {
    padding-left: 28px;
    border-left: 1px solid var(--cvg-hairline);
  }

  .stat:nth-child(2n + 1) {
    padding-left: 28px;
  }

  .stat:first-child {
    padding-left: 0;
    border-left: 0;
  }
}

.stat-figure {
  font-family: var(--font-title);
  font-weight: 400;
  font-size: clamp(2.5rem, 1.9rem + 2.4vw, 3.75rem);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--cvg-text);
  margin: 0 0 14px;
}

.stat-label {
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--cvg-text-2);
  max-width: 26ch;
  margin: 0;
}

/* The full height gold rule is gone. The panel is now a quiet card, and the
   gold survives as a short mark above the attribution, which is the hairline
   or mark use the palette permits on a light ground. */
.flourish-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-md);
  padding: 30px 28px 26px;
  margin: 0;
}

/* The quotation mark is set in the display face and sized like display type,
   sitting above the quote rather than behind it. It carries aria-hidden in the
   markup: blockquote already tells a screen reader this is a quotation, and a
   spoken "left double quotation mark" would be noise. */
.flourish-mark {
  display: block;
  font-family: var(--font-title);
  font-size: 64px;
  line-height: 0.7;
  color: var(--cvg-gold);
  margin-bottom: 14px;
  user-select: none;
}

.flourish {
  font-family: var(--font-title);
  font-style: italic;
  font-size: 30px;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--cvg-text);
  margin: 0 0 22px;
}

/* Pinned to the foot so the panel can stretch to the carousel beside it
   without leaving the attribution floating mid-card. */
.flourish-attrib {
  position: relative;
  margin-top: auto;
  padding-top: 18px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-text-2);
  margin-bottom: 0;
}

.flourish-attrib::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 28px;
  height: 2px;
  background: var(--cvg-gold);
}

/* --------------------------------------------------------------------------
   Bespoke steps
   -------------------------------------------------------------------------- */
/* Split section intro: heading and index on the left, the supporting sentence
   on the right. Used where a section needs more setup than a heading alone. */
.section-intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
  margin-bottom: 60px;
}

@media (min-width: 992px) {
  .section-intro {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: 60px;
    align-items: end;
  }
}

.section-intro-head > :last-child {
  margin-bottom: 0;
}

.section-intro-lede {
  max-width: 46ch;
  margin-bottom: 0;
}

/* Feature list. The steps carried 01 / 02 / 03, which the project reserves for
   the one genuine ordered sequence on the page, so the marker becomes an icon
   drawn from the gemmologist's own tools: loupe, drawing, finished ring. */
.feature-list {
  list-style: none;
  margin: 0 0 40px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 30px;
}

.feature {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}

.feature-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-pill);
  background: var(--cvg-navy);
  color: var(--cvg-gold);
  flex: 0 0 auto;
}

.feature-icon svg {
  width: 21px;
  height: 21px;
  display: block;
}

.feature-title {
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: var(--lh-snug);
  color: var(--cvg-text);
  margin-bottom: 5px;
}

.feature-note {
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--cvg-text-2);
  max-width: 42ch;
  margin-bottom: 0;
}

/* Landscape now that it sits in the wider column beside the feature list.
   Capped and pushed right so it sits against the container edge rather than
   filling the column.

   Right-aligned with margin-left rather than float. The frame has no intrinsic
   width, since the image inside is sized at 100%, so floating made it
   shrink-to-fit to 0 and, being out of flow, collapsed its column to 0 height
   as well. margin-left: auto gives the same alignment and keeps it in flow. */
.ring-frame {
  aspect-ratio: 4 / 3;
  border-radius: var(--r-lg);
  overflow: hidden;
  width: 100%;
  max-width: 510px;
  margin-left: auto;
}

/* --------------------------------------------------------------------------
   After you buy
   -------------------------------------------------------------------------- */
/* Separate tiles rather than one bordered slab divided by 1px gaps. The old
   treatment read as a table; these read as four cards, matching the grids in
   the two sections above. */
.card-info-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
}

@media (min-width: 576px) {
  .card-info-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 992px) {
  .card-info-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.card-info {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--cvg-surface);
  border: 1px solid var(--cvg-border-dark);
  border-radius: var(--r-md);
  padding: 30px 26px 28px;
  overflow: hidden;
  transition: border-color var(--t-fast);
}

.card-info:hover {
  border-color: var(--cvg-gold-shadow);
}

/* The step, set as a watermark rather than a label: large enough to be read as
   sequence at a glance, quiet enough that the value below it stays the thing
   you actually read. Baskervville because a numeral this size is display type.
   aria-hidden in the markup, since the reading order already carries it. */
.card-info-num {
  position: absolute;
  top: -6px;
  right: 14px;
  font-family: var(--font-title);
  font-size: 78px;
  line-height: 1;
  letter-spacing: -0.02em;
  /* script white @ 9%, a watermark on the surface rather than a second label */
  color: rgba(233, 236, 246, 0.09);
  pointer-events: none;
  user-select: none;
}

.card-info-label {
  position: relative;
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--cvg-gold);
  margin-bottom: 18px;
}

.card-info-value {
  position: relative;
  font-size: var(--fs-h5);
  line-height: var(--lh-snug);
  color: var(--cvg-script);
  margin-bottom: 10px;
}

/* Pushed to the foot so the notes sit on one baseline across the row, whatever
   the value above them wraps to. */
.card-info-note {
  position: relative;
  margin-top: auto;
  padding-top: 4px;
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--cvg-text-dark-2);
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   FAQ accordion (plain markup, jQuery-driven)
   -------------------------------------------------------------------------- */
.faq {
  border-top: 1px solid var(--cvg-hairline);
}

.faq-item {
  border-bottom: 1px solid var(--cvg-hairline);
}

.faq-q {
  margin: 0;
}

.faq-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  min-height: 44px;
  padding: 22px 0;
  background: none;
  border: 0;
  font-family: var(--font-text);
  font-size: var(--fs-lead);
  font-weight: 500;
  line-height: 1.4;
  text-align: left;
  color: var(--cvg-text);
  cursor: pointer;
  transition: color var(--t-fast);
}

.faq-toggle:hover {
  color: var(--cvg-navy);
}

.faq-toggle:focus-visible {
  outline: 2px solid var(--cvg-navy);
  outline-offset: 2px;
}

.faq-toggle::after {
  content: "";
  flex: 0 0 auto;
  width: 15px;
  height: 15px;
  background-image: linear-gradient(currentColor, currentColor), linear-gradient(currentColor, currentColor);
  background-size: 15px 1.5px, 1.5px 15px;
  background-position: center, center;
  background-repeat: no-repeat;
  transition: background-size var(--t-med);
}

.faq-toggle[aria-expanded="true"]::after {
  background-size: 15px 1.5px, 1.5px 0;
}

.faq-a {
  display: none;
}

.faq-item:first-child .faq-a {
  display: block;
}

.faq-a-inner {
  padding-bottom: 24px;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--cvg-text-2);
}

/* --------------------------------------------------------------------------
   Reviews
   -------------------------------------------------------------------------- */
/* Centred section head: the eyebrow and title sit on the section's midline
   rather than against the left edge. */
.section-head-centred {
  justify-content: center;
  text-align: center;
}

.section-head-centred .stars {
  vertical-align: -2px;
  margin-right: 6px;
}

.stars {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}

.stars svg {
  width: 15px;
  height: 15px;
  display: block;
  fill: var(--cvg-gold-shadow);
}

.card-review-grid:not(.owl-loaded) {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 25px;
}

.card-review {
  height: 100%;
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  padding: 30px 28px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.card-review-quote {
  font-size: var(--fs-lead);
  line-height: 1.55;
  color: var(--cvg-text);
  margin-bottom: 0;
}

.card-review-footer {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 12px;
  padding-top: 4px;
}

/* An initial in a disc, not a portrait. We have no photograph of any buyer and
   a stock face on a testimonial would be an invention. */
.card-review-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: var(--r-pill);
  background: var(--cvg-navy);
  color: var(--cvg-white);
  font-family: var(--font-title);
  font-size: var(--fs-small);
  line-height: 1;
}

.card-review-name {
  font-size: var(--fs-small);
  font-weight: 500;
  line-height: 1.3;
  color: var(--cvg-text);
  margin-bottom: 2px;
}

.card-review-meta {
  font-size: var(--fs-caps);
  line-height: 1.3;
  color: var(--cvg-text-2);
  margin-bottom: 0;
}

/* Peek carousel: the two items in view are full strength, the ones sliding in
   either side are held back so the eye stays on the pair being read. The fade
   is timed to the carousel's own slide so the two read as one movement. */
.carousel-peek .owl-item .card-review {
  opacity: 0.28;
  transition: opacity var(--t-med);
}

.carousel-peek .owl-item.active .card-review {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .carousel-peek .owl-item .card-review {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   Badges
   -------------------------------------------------------------------------- */
.badge-treat,
.badge-lab,
.badge-certified {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  font-size: var(--fs-small);
  font-weight: 500;
  line-height: 1;
  padding: 0.28rem 0.6rem;
}

.badge-treat {
  border: 1px solid var(--cvg-navy);
  border-radius: var(--r-pill);
  color: var(--cvg-navy);
}

.badge-lab {
  background: var(--cvg-navy);
  border-radius: var(--r-sm);
  color: var(--cvg-white);
}

.badge-certified {
  background: var(--cvg-gold);
  border-radius: var(--r-sm);
  color: var(--cvg-navy);
}

/* --------------------------------------------------------------------------
   Concierge
   -------------------------------------------------------------------------- */
/* The contact panel: a quiet inset card on the raised band, carrying the
   three expectations the page can already stand behind. The gemmologist's
   photograph takes this slot once it exists. */
.concierge-panel {
  background: var(--cvg-navy);
  border: 1px solid var(--cvg-border-dark);
  border-radius: var(--r-lg);
  padding: 32px 30px 30px;
}

.concierge-panel-label {
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-gold-hi);
  margin-bottom: 24px;
}

.concierge-panel .feature-list {
  margin-bottom: 0;
  gap: 26px;
}

/* Feature list on a dark ground. */
.on-dark .feature-icon {
  background: var(--cvg-surface-2);
  border: 1px solid var(--cvg-border-dark);
  color: var(--cvg-gold);
}

.on-dark .feature-title {
  color: var(--cvg-script);
}

.on-dark .feature-note {
  color: var(--cvg-text-dark-2);
}

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid var(--cvg-border-dark);
  padding: 72px 0 40px;
}

.footer-logo {
  width: 152px;
  height: auto;
  aspect-ratio: 541 / 358;
  display: block;
}

.footer-blurb {
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--cvg-text-dark-2);
  margin-bottom: 0;
}

/* An h2 for the heading tree, styled as the caps label the mega menu and the
   concierge panel use. The body face is pinned because the bare h2 rule would
   set the serif. */
.footer-heading {
  font-family: var(--font-text);
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--cvg-gold-hi);
  margin-bottom: 18px;
}

.footer-links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.footer-link {
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--cvg-text-dark-2);
  text-decoration: none;
  transition: color var(--t-fast);
}

.footer-link:hover,
.footer-link:focus {
  color: var(--cvg-script);
}

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-top: 28px;
}

.footer-fine {
  font-size: var(--fs-caps);
  line-height: 1.5;
  color: var(--cvg-text-dark-2);
  margin-bottom: 0;
}

/* The legal pair in the footer's bottom row: caps scale, hairline
   separated, beside the fine print rather than in a column of its own. */
.footer-legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 20px;
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: var(--fs-caps);
}

.footer-motto {
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--cvg-text-dark-2);
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   Stone pages: the gems archive at /stones/ and the single stone. The cards
   are the shared .card-product; everything here is the page furniture.
   -------------------------------------------------------------------------- */
.gem-crumb {
  font-size: var(--fs-caps);
  color: var(--cvg-text-2);
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.gem-crumb a {
  color: var(--cvg-navy);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.gem-crumb a:hover {
  border-bottom-color: var(--cvg-gold-shadow);
}

/* Filter bar: a GET form on a white panel, labels visible above each
   select. The fields sit inset on cream and carry the house arrow, rotated
   to a chevron, on a wrapper span because a select cannot hold a
   pseudo-element. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px 20px;
  padding: 20px;
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  margin-bottom: 30px;
}

.filter-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1 1 180px;
  min-width: 160px;
  max-width: 320px;
}

.filter-label {
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-text-2);
}

.filter-select {
  position: relative;
  display: block;
}

.filter-select::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 14px;
  width: 14px;
  height: 14px;
  transform: translateY(-50%) rotate(90deg);
  background-color: var(--cvg-navy);
  -webkit-mask: var(--cvg-arrow) center / contain no-repeat;
  mask: var(--cvg-arrow) center / contain no-repeat;
  pointer-events: none;
}

.filter-bar select {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  min-height: var(--cvg-control-h);
  padding: 8px 40px 8px 14px;
  font-family: var(--font-text);
  font-size: var(--fs-small);
  color: var(--cvg-text);
  background: var(--cvg-cream);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: border-color var(--t-fast);
}

.filter-bar select:hover {
  border-color: var(--cvg-gold-shadow);
}

.filter-actions {
  display: flex;
  align-items: center;
  gap: 20px;
  flex: 0 0 auto;
}

@media (max-width: 575.98px) {
  .filter-field {
    flex-basis: 100%;
    max-width: none;
  }

  .filter-actions {
    flex-basis: 100%;
  }

  .filter-actions .btn {
    flex: 1 1 auto;
    justify-content: center;
  }
}

.gem-count {
  font-size: var(--fs-small);
  color: var(--cvg-text-2);
  margin-bottom: 25px;
}

/* Single stone: photograph left, the facts right. */
.gem-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 40px;
  align-items: start;
}

@media (min-width: 992px) {
  .gem-split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 60px;
  }
}

.gem-stage {
  position: relative;
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  overflow: hidden;
  aspect-ratio: 1 / 1;
}

.gem-stage img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The stage's video: contained rather than cropped, because a video frame
   is rarely square and cover would cut the stone out of its own film. */
.gem-stage video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--cvg-white);
}

/* .gem-stage img sets display, which would beat the browser's own hidden
   rule; restore it for the server-rendered first paint. */
.gem-stage [hidden] {
  display: none;
}

/* Magnifier: on hover the photograph scales to twice its size and
   custom.js pins transform-origin under the pointer, so the spot beneath
   the cursor stays put while everything around it magnifies; moving the
   pointer pans the magnified image directly, clipped by the stage. The
   ease applies only to the scale in and out. Gated on motion preference,
   so a reduced-motion visitor keeps the still image and no zoom cursor,
   and off entirely while the video holds the stage. */
@media (prefers-reduced-motion: no-preference) {
  .gem-stage:not(.is-video) {
    cursor: zoom-in;
  }

  .gem-stage img {
    transition: transform 600ms var(--ease-soft);
  }

  .gem-stage:not(.is-video):hover img {
    transform: scale(2);
  }
}

/* Five thumbnails to the width; a rail holding more scrolls behind the
   prev and next arrows. custom.js pages it two thumbs at a time; touch
   drags it directly, and a thumb focused by keyboard scrolls itself into
   view. The scrollbar stays hidden; the arrows are the affordance. */
.gem-thumbs-wrap {
  position: relative;
  /* 16 less the rail's 4px ring allowance reads as the designed 12. */
  margin-top: 16px;
}

.gem-thumbs {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  scrollbar-width: none;
  /* Breathing room inside the scrollport, cancelled by the margin, so a
     focused thumb's ring is not clipped at the rail's edges. */
  padding: 4px;
  margin: -4px;
}

.gem-thumbs::-webkit-scrollbar {
  display: none;
}

.gem-thumb {
  position: relative;
  flex: 0 0 calc((100% - 40px) / 5);
  aspect-ratio: 1 / 1;
  padding: 0;
  overflow: hidden;
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-sm);
  cursor: pointer;
}

/* The video thumbnail wears a play badge over its poster frame; the
   triangle is drawn from borders, so no new icon asset enters the theme. */
.gem-thumb-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* navy @ 35%: a light veil that still lets the poster read */
  background: rgba(10, 22, 51, 0.35);
}

/* The disc behind the triangle takes the certified marker's navy @ 72%
   scrim, so the white triangle clears 3:1 over even a pure white poster. */
.gem-thumb-play::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 30px;
  height: 30px;
  border-radius: var(--r-pill);
  background: rgba(10, 22, 51, 0.72);
}

.gem-thumb-play::after {
  content: "";
  position: relative;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 7px 0 7px 12px;
  border-color: transparent transparent transparent var(--cvg-white);
  margin-left: 2px;
}

/* The rail arrows: white discs on the rail's edges, revealed by custom.js
   only when the rail actually overflows, and only on the side that still
   has somewhere to go. */
.gem-thumbs-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  /* white @ 92% so the thumb beneath still reads at the edge */
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: border-color var(--t-fast);
}

.gem-thumbs-nav[hidden] {
  display: none;
}

.gem-thumbs-nav:hover,
.gem-thumbs-nav:focus {
  border-color: var(--cvg-gold-shadow);
}

.gem-thumbs-nav::after {
  content: "";
  width: 16px;
  height: 16px;
  background-color: var(--cvg-navy);
  -webkit-mask: var(--cvg-arrow) center / contain no-repeat;
  mask: var(--cvg-arrow) center / contain no-repeat;
}

/* The discs straddle the rail's edges rather than sitting on the thumbs,
   so they cover as little of the first and last visible thumb as a 44px
   target allows; at either end the nearer disc hides entirely and frees
   its thumb, and touch can always drag the rail past them. */
.gem-thumbs-prev {
  left: -10px;
}

.gem-thumbs-prev::after {
  transform: rotate(180deg);
}

.gem-thumbs-next {
  right: -10px;
}

.gem-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.gem-thumb.is-active {
  border-color: var(--cvg-gold-shadow);
  /* a second inner line, so the active state reads as weight, not colour
     alone; aria-current carries it to assistive tech */
  box-shadow: inset 0 0 0 1px var(--cvg-gold-shadow);
}

.gem-title {
  font-size: var(--fs-h2);
  line-height: var(--lh-title);
}

.gem-meta {
  font-size: var(--fs-lead);
  color: var(--cvg-text-2);
}

.gem-badges {
  display: flex;
  flex-wrap: wrap; 
  gap: 10px;
}

/* Gold shadow at 28px: large text, where 3.78:1 clears the 3:1 bar. */
.gem-price {
  font-family: var(--font-title);
  font-size: 28px;
  line-height: 1.2;
  color: var(--cvg-gold-shadow);
}

/* The report panel: the verification moment, so it alone takes the gold
   hairline frame on light. Lab badge left, the number as a labelled serif
   figure (a click selects the whole number for copying), the laboratory
   lookup ranged right. */
.gem-report {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 24px;
  padding: 24px 28px;
  background: var(--cvg-white);
  border: 1px solid var(--cvg-gold-hairline);
  border-radius: var(--r-lg);
  margin-top: 40px;
}

.gem-report .badge-lab {
  /* The badge base sets align-self: flex-start; centre it in this row. */
  align-self: center;
  font-size: var(--fs-body);
  padding: 0.45rem 0.8rem;
}

.gem-report-body {
  flex: 1 1 auto;
}

.gem-report-label {
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-text-2);
  margin-bottom: 2px;
}

.gem-report-no {
  font-family: var(--font-title);
  font-size: var(--fs-h5);
  color: var(--cvg-text);
  margin-bottom: 0;
  -webkit-user-select: all;
  user-select: all;
}

.gem-specs {
  margin-bottom: 0;
  max-width: 720px;
}

.gem-specs-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: 20px;
  padding-block: 12px;
  border-bottom: 1px solid var(--cvg-hairline);
}

.gem-specs-row dt {
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-text-2);
}

.gem-specs-row dd {
  margin-bottom: 0;
  color: var(--cvg-text);
}

.gem-story p {
  color: var(--cvg-text-2);
}

/* Pagination: paginate_links list output. */
.pagination-cvg .page-numbers {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.pagination-cvg .page-numbers li a,
.pagination-cvg .page-numbers li span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--cvg-control-h);
  min-height: var(--cvg-control-h);
  padding: 8px 14px;
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--cvg-navy);
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-sm);
  text-decoration: none;
}

.pagination-cvg .page-numbers li a:hover {
  border-color: var(--cvg-gold-shadow);
}

.pagination-cvg .page-numbers li span.current {
  background: var(--cvg-navy);
  border-color: var(--cvg-navy);
  color: var(--cvg-white);
}

.pagination-cvg .page-numbers li span.dots {
  border-color: transparent;
  background: transparent;
}

/* --------------------------------------------------------------------------
   Landing pages: the /sapphire/, /ceylon-gems/, /data/ and utility layer.
   Copy for the retired route lived in docs/retired/; these are
   the shells it renders into.
   -------------------------------------------------------------------------- */
.landing-lead {
  font-size: var(--fs-lead);
  line-height: var(--lh-lead);
  max-width: 56ch;
}

/* Key facts: the machine-readable spine of the page, a dl on white. */
.fact-band {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--cvg-hairline);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  overflow: hidden;
  margin-bottom: 0;
}

@media (min-width: 768px) {
  .fact-band { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.fact {
  background: var(--cvg-white);
  padding: 18px 20px;
}

.fact-label {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  margin-bottom: 2px;
}

.fact-value {
  font-family: var(--font-title);
  font-size: var(--fs-h5);
  color: var(--cvg-text);
  margin-bottom: 0;
}

/* Question-led editorial sections. */
.landing-section { max-width: 720px; }
.landing-prose p { color: var(--cvg-text-2); }
.landing-prose p:last-child { margin-bottom: 0; }

/* Concierge band: navy, one gold action. */
.cta-band {
  background: var(--cvg-surface);
  border-radius: var(--r-lg);
  padding: 40px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.cta-band .section-title { color: var(--cvg-script); }

/* Hub tiles: one link per child page, dark tiles like the colour cards. */
.hub-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
}

@media (min-width: 576px) { .hub-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 992px) { .hub-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.hub-tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 24px 26px;
  background: var(--cvg-surface);
  border: 1px solid var(--cvg-border-dark);
  border-radius: var(--r-md);
  color: var(--cvg-script);
  text-decoration: none;
  transition: background-color var(--t-fast), border-color var(--t-fast);
}

.hub-tile:hover,
.hub-tile:focus {
  background: var(--cvg-surface-2);
  border-color: var(--cvg-gold);
  color: var(--cvg-script);
}

.hub-tile-name {
  font-family: var(--font-title);
  font-size: 24px;
  line-height: var(--lh-snug);
}

.hub-tile-note {
  font-size: var(--fs-small);
  color: var(--cvg-text-dark-2);
  margin-bottom: 0;
}

/* Data tables: live inventory figures on white, numbers tabular. */
.data-table {
  width: 100%;
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
}

.data-table th {
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-text-2);
  text-align: left;
  padding: 14px 20px;
  border-bottom: 1px solid var(--cvg-hairline);
}

.data-table td {
  padding: 14px 20px;
  color: var(--cvg-text);
  border-bottom: 1px solid var(--cvg-hairline);
  font-variant-numeric: tabular-nums;
}

.data-table tr:last-child td { border-bottom: 0; }
.data-table tr:last-child th[scope="row"] { border-bottom: 0; }

/* Matrix tables: the row's own header cell, body-cased and full ink,
   against the caps column headers. */
.data-table th[scope="row"] {
  font-size: var(--fs-body);
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  color: var(--cvg-text);
  padding: 14px 20px;
  border-bottom: 1px solid var(--cvg-hairline);
}

.data-basis {
  font-size: var(--fs-small);
  color: var(--cvg-text-2);
  margin-top: 12px;
  margin-bottom: 0;
}

.data-scroll { overflow-x: auto; }

/* --------------------------------------------------------------------------
   Legal documents (.legal-*): the terms and the privacy policy. The body of
   each document is dressed by .gem-family-desc below, which already gives an
   authored h2 the section-title scale over a hairline rule and a paragraph
   the 18px lead, so only two pieces are new here: the date line under the
   title and the contents panel above the document.
   -------------------------------------------------------------------------- */
.legal-updated {
  margin: 24px 0 0;
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-text-dark-2);
}

/* On a light ground the same line takes secondary ink. */
.bg-cream .legal-updated,
.bg-paper .legal-updated { color: var(--cvg-text-2); }

/* The contents panel: a quiet white card, not a second heading block. */
.legal-toc {
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  padding: 26px 28px;
  margin-bottom: 50px;
}

.legal-toc-list {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 2px 32px;
  counter-reset: legal-toc;
}

/* Below the tablet breakpoint the panel would run past a whole screen
   before the document began, so it stands down there the way the mega
   panels do: the links duplicate headings that are still on the page, and
   nothing is lost but the shortcut. */
@media (max-width: 767.98px) {
  .legal-toc { display: none; }
}

@media (min-width: 768px) {
  .legal-toc-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1200px) {
  .legal-toc-list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.legal-toc-list > li { counter-increment: legal-toc; }

.legal-toc-list a {
  display: flex;
  gap: 10px;
  /* The house minimum touch target, even in a dense list. */
  min-height: 44px;
  align-items: center;
  padding: 5px 0;
  font-size: var(--fs-small);
  line-height: var(--lh-snug);
  color: var(--cvg-text);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

/* The numeral is decoration, so it is drawn rather than read: the link text
   alone is the accessible name. */
.legal-toc-list a::before {
  content: counter(legal-toc, decimal-leading-zero);
  flex: 0 0 auto;
  font-family: var(--font-title);
  font-size: var(--fs-small);
  color: var(--cvg-gold-shadow);
}

.legal-toc-list a:hover,
.legal-toc-list a:focus-visible { border-bottom-color: var(--cvg-gold-shadow); }

/* --------------------------------------------------------------------------
   Long-form editorial copy (.gem-family-desc): admin-entered WYSIWYG content
   at full container width, on light grounds. First use is the gem family
   archive's gem_family_desc term field; reusable on any page that renders a
   client-authored block, the terms and privacy documents included. Element
   rules are guarded so component markup pasted into the field (.faq,
   .section-title, .eyebrow, grid rows) keeps its own styling and only
   authored copy takes these. The guard counts two things as authored copy:
   an element with no class at all, and one carrying a wp-block-* class,
   because the block editor stamps wp-block-heading and wp-block-paragraph
   on every block it writes. Without the second half a page whose copy came
   from the editor rather than a WYSIWYG field fell through every rule here
   and its headings sat 16px under the paragraph above them.
   -------------------------------------------------------------------------- */
.gem-family-desc {
  color: var(--cvg-text-2);
  max-width: 800px;
  margin: 0 auto;
}
.gem-family-desc > :last-child { margin-bottom: 0; }

/* Section headings: the section-title scale over a hairline rule, so each
   authored section reads as a section of the page. */
.gem-family-desc h2:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) {
  font-size: var(--fs-h2);
  line-height: 1.25;
  letter-spacing: 0.2px;
  color: var(--cvg-text);
  border-top: 1px solid var(--cvg-hairline);
  padding-top: 36px;
  margin: 56px 0 18px;
}

.gem-family-desc h2:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]):first-child {
  border-top: 0;
  padding-top: 0;
  margin-top: 0;
}

.gem-family-desc h3:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) {
  font-size: var(--fs-h3);
  color: var(--cvg-text);
  margin: 36px 0 12px;
}

.gem-family-desc h4:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) {
  font-size: var(--fs-h4);
  color: var(--cvg-text);
  margin: 28px 0 10px;
}

.gem-family-desc p:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) {
  font-size: var(--fs-lead);
  line-height: var(--lh-lead);
  color: var(--cvg-text-2);
  text-wrap: pretty;
  margin-bottom: 16px;
}

/* WYSIWYG bold is emphasis, DM Sans 500 in full ink, never a faked heavy. */
.gem-family-desc p:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) strong,
.gem-family-desc li strong {
  font-weight: 500;
  color: var(--cvg-text);
}

.gem-family-desc ul:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]),
.gem-family-desc ol:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) {
  font-size: var(--fs-lead);
  line-height: var(--lh-lead);
  margin: 0 0 20px;
  padding-left: 24px;
}

.gem-family-desc ul:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) > li,
.gem-family-desc ol:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) > li {
  margin-bottom: 8px;
}

.gem-family-desc ul:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) > li::marker,
.gem-family-desc ol:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) > li::marker {
  color: var(--cvg-navy);
}

/* Content links: navy over a gold hairline underline that fills on hover. */
.gem-family-desc p:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a,
.gem-family-desc ul:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a,
.gem-family-desc ol:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a,
.gem-family-desc table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a {
  color: var(--cvg-navy);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--cvg-gold-hairline);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color var(--t-fast);
}

.gem-family-desc p:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a:hover,
.gem-family-desc p:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a:focus,
.gem-family-desc ul:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a:hover,
.gem-family-desc ul:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a:focus,
.gem-family-desc ol:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a:hover,
.gem-family-desc ol:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a:focus,
.gem-family-desc table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a:hover,
.gem-family-desc table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) a:focus {
  text-decoration-color: var(--cvg-gold-shadow);
}

/* Authored tables take the data-table treatment: white panel, hairline
   border, caps header row, the first column carried in full ink. */
.gem-family-desc table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) {
  width: 100%;
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
  margin: 24px 0 28px;
}

.gem-family-desc table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) th {
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-text-2);
  text-align: left;
  padding: 14px 20px;
  border-bottom: 1px solid var(--cvg-hairline);
}

.gem-family-desc table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) td {
  padding: 14px 20px;
  font-size: var(--fs-body);
  color: var(--cvg-text-2);
  border-bottom: 1px solid var(--cvg-hairline);
  font-variant-numeric: tabular-nums;
  vertical-align: top;
}

.gem-family-desc table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) td:first-child {
  font-weight: 500;
  color: var(--cvg-text);
}

.gem-family-desc table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) tr:last-child td { border-bottom: 0; }

/* The template wraps each authored table in the /data/ pages' .data-scroll,
   so a wide table scrolls inside its own box on narrow screens; the block
   spacing moves to the wrapper. */
.gem-family-desc .data-scroll { margin: 24px 0 28px; }
.gem-family-desc .data-scroll > table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) { margin: 0; }

@media (max-width: 640px) {
  .gem-family-desc table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) th,
  .gem-family-desc table:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) td {
    padding: 12px 14px;
  }
}

.gem-family-desc blockquote:is(:not([class]), [class^="wp-block-"], [class*=" wp-block-"]) {
  font-family: var(--font-title);
  font-style: italic;
  font-size: var(--fs-h5);
  line-height: var(--lh-snug);
  color: var(--cvg-text);
  border-left: 1px solid var(--cvg-gold-hairline);
  padding-left: 24px;
  margin: 28px 0;
}

.gem-family-desc img {
  max-width: 100%;
  height: auto;
  border-radius: var(--r-lg);
}

.gem-family-desc hr {
  border: 0;
  border-top: 1px solid var(--cvg-hairline);
  margin: 40px 0;
  opacity: 1;
}

/* --------------------------------------------------------------------------
   Editorial page components: the bespoke guide and business page templates
   (templates/page-*.php, the guide and business pages plan). Added once so
   every page composes from the same pieces: the split page head, framed
   figures, the photograph placeholder, the dark stat band variant and
   numbered process rows.
   -------------------------------------------------------------------------- */

/* Split page head on navy: copy left, figure right, stacked below lg. */
.page-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 40px;
  align-items: center;
}

@media (min-width: 992px) {
  .page-hero {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: 56px;
  }
}

/* Framed figure: hairline, radius, cropped media. */
.figure-frame {
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  overflow: hidden;
  margin: 0;
  background: var(--cvg-white);
}

.figure-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.figure-frame-43 { aspect-ratio: 4 / 3; }
.figure-frame-11 { aspect-ratio: 1 / 1; }

.bg-navy .figure-frame,
.bg-navy-raised .figure-frame,
.on-dark .figure-frame {
  border-color: var(--cvg-border-dark);
  background: var(--cvg-surface);
}

/* Placeholder figure, used where no photograph suits yet; the label is
   real markup (a span), never generated content. */
.ph-figure {
  display: grid;
  place-items: center;
  background: var(--cvg-cream);
}

.ph-figure span {
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-text-2);
  padding: 20px;
  text-align: center;
}

.bg-navy .ph-figure,
.bg-navy-raised .ph-figure,
.on-dark .ph-figure {
  background: var(--cvg-surface);
}

.bg-navy .ph-figure span,
.bg-navy-raised .ph-figure span,
.on-dark .ph-figure span {
  color: var(--cvg-text-dark-2);
}

/* Stat rows reuse .fact-band; this variant sets it on navy grounds. */
.fact-band-dark {
  background: var(--cvg-border-dark);
  border-color: var(--cvg-border-dark);
}

/* A two-cell band keeps two columns at every width, so no empty third
   cell opens up past the band's own 768px breakpoint. */
.fact-band-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.fact-band-dark .fact { background: var(--cvg-surface); }
.fact-band-dark .fact-label { color: var(--cvg-text-dark-2); }
.fact-band-dark .fact-value { color: var(--cvg-script); }

/* Numbered process rows: methodology, makers, shipping journeys. The
   numeral is a Baskervville counter; the row is a real ol so the order
   is announced, not decorated. */
.steps-list {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: cvg-step;
}

.steps-list > li {
  counter-increment: cvg-step;
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  gap: 24px;
  align-items: start;
  padding-block: 28px;
  border-top: 1px solid var(--cvg-hairline);
}

.steps-list > li:first-child {
  border-top: 0;
  padding-top: 0;
}

.steps-list > li::before {
  content: counter(cvg-step, decimal-leading-zero);
  font-family: var(--font-title);
  font-size: var(--fs-h3);
  line-height: 1.1;
  color: var(--cvg-navy);
}

.steps-list h3 {
  font-family: var(--font-text);
  font-size: var(--fs-h6);
  font-weight: 500;
  color: var(--cvg-text);
  margin-bottom: 6px;
}

.steps-list p {
  color: var(--cvg-text-2);
  margin-bottom: 0;
}

.on-dark .steps-list > li { border-top-color: var(--cvg-border-dark); }
.on-dark .steps-list > li::before { color: var(--cvg-script); }
.on-dark .steps-list h3 { color: var(--cvg-script); }
.on-dark .steps-list p { color: var(--cvg-text-dark-2); }

/* Founder cards: the about page's people, text forward, no portraits
   until real photography is supplied. */
.founder-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 25px;
}

@media (min-width: 992px) {
  .founder-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.founder-card {
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  padding: 32px;
}

.founder-card h3 { margin-bottom: 4px; }
.founder-card p:not(.eyebrow) { color: var(--cvg-text-2); }
.founder-card p:last-child { margin-bottom: 0; }

.founder-motto {
  font-family: var(--font-title);
  font-style: italic;
  font-size: var(--fs-h5);
  color: var(--cvg-text);
  margin-bottom: 0;
}

/* The index stat: one headline figure on a white panel, the serif number
   in gold shadow (the .gem-price treatment at display size, large text on
   white). Figure left, the basis and its note right. */
.index-stat {
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  padding: 40px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 28px;
  align-items: center;
}

@media (min-width: 992px) {
  .index-stat { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); }
}

.index-stat-figure {
  font-family: var(--font-title);
  font-size: clamp(2.75rem, 6vw, 4.25rem);
  line-height: 1.05;
  letter-spacing: 0.2px;
  color: var(--cvg-gold-shadow);
  font-variant-numeric: tabular-nums;
  margin-bottom: 6px;
}

.index-stat-unit {
  font-size: var(--fs-h5);
  color: var(--cvg-text);
  margin-bottom: 0;
}

.index-stat-side {
  border-top: 1px solid var(--cvg-hairline);
  padding-top: 20px;
}

@media (min-width: 992px) {
  .index-stat-side {
    border-top: 0;
    border-left: 1px solid var(--cvg-hairline);
    padding-top: 0;
    padding-left: 32px;
  }
}

/* The at-a-glance takeaways panel: a guide page's rules, scannable before
   the prose. Pair with .list-check for the list itself. */
.takeaways {
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  padding: 28px 32px;
}

/* Ticked list, reusable on any ground: the tick is the --cvg-check mask,
   gold shadow on light and full gold on navy, a mark rather than text so
   screen readers never announce it. */
.list-check {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}

.list-check li {
  position: relative;
  padding-left: 30px;
}

.list-check li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.3em;
  width: 16px;
  height: 16px;
  background-color: var(--cvg-gold-shadow);
  -webkit-mask: var(--cvg-check) center / contain no-repeat;
  mask: var(--cvg-check) center / contain no-repeat;
}

.on-dark .list-check li { color: var(--cvg-text-dark-2); }
.on-dark .list-check li::before { background-color: var(--cvg-gold); }

/* The contact form: dresses whatever Contact Form 7 markup the client
   pastes into the page editor, so the form needs no classes of its own.
   Field chrome mirrors the filter bar: white panel ground, inset cream
   fields, the house focus ring. */
.contact-form {
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  padding: 32px;
}

.contact-form label {
  display: block;
  font-size: var(--fs-caps);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--cvg-text-2);
  margin-bottom: 6px;
}

.contact-form p { margin-bottom: 18px; }
.contact-form p:last-child { margin-bottom: 0; }

.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form input[type="tel"],
.contact-form input[type="url"],
.contact-form select,
.contact-form textarea,
.contact-form .wpcf7-text,
.contact-form .wpcf7-email,
.contact-form .wpcf7-tel,
.contact-form .wpcf7-url,
.contact-form .wpcf7-number,
.contact-form .wpcf7-date,
.contact-form .wpcf7-select,
.contact-form .wpcf7-textarea {
  width: 100%;
  min-height: var(--cvg-control-h);
  padding: 10px 14px;
  font-family: var(--font-text);
  font-size: var(--fs-body);
  color: var(--cvg-text);
  background: var(--cvg-cream);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-md);
}

.contact-form textarea,
.contact-form .wpcf7-textarea {
  height: 160px;
  resize: vertical;
}

.contact-form input:focus-visible,
.contact-form select:focus-visible,
.contact-form textarea:focus-visible {
  outline: 2px solid var(--cvg-navy);
  outline-offset: 2px;
}

/* The submit control mirrors .btn; a pseudo-element arrow cannot attach
   to an input, so the button stands on its colours alone. */
.contact-form input[type="submit"],
.contact-form button[type="submit"] {
  display: inline-flex;
  align-items: center;
  min-height: var(--cvg-control-h);
  padding: 8px 24px;
  background: var(--cvg-gold);
  border: 1px solid var(--cvg-gold);
  border-radius: var(--r-sm);
  color: var(--cvg-navy);
  font-family: var(--font-text);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: capitalize;
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast);
}

.contact-form input[type="submit"]:hover,
.contact-form input[type="submit"]:focus,
.contact-form button[type="submit"]:hover,
.contact-form button[type="submit"]:focus {
  background: var(--cvg-gold-hi);
  border-color: var(--cvg-gold-hi);
  color: var(--cvg-navy);
}

.contact-form input[type="submit"]:focus-visible,
.contact-form button[type="submit"]:focus-visible {
  outline: 2px solid var(--cvg-gold);
  outline-offset: 2px;
}

/* Contact Form 7's own feedback lines, kept to the palette. */
.contact-form .wpcf7-not-valid-tip {
  font-size: var(--fs-small);
  color: var(--cvg-text);
  margin-top: 4px;
}

.contact-form .wpcf7-response-output {
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-md);
  padding: 12px 16px;
  margin: 18px 0 0;
  font-size: var(--fs-small);
  color: var(--cvg-text);
}

.contact-note {
  font-size: var(--fs-small);
}

/* The contact channels, one card each. auto-fit keeps the row filled
   however many details are confirmed, since a card renders only once its
   value is supplied. */
.contact-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 25px;
}

.contact-card {
  background: var(--cvg-white);
  border: 1px solid var(--cvg-hairline);
  border-radius: var(--r-lg);
  padding: 28px;
}

.contact-card .fact-label {
  color: var(--cvg-text-2);
  margin-bottom: 10px;
}

.contact-card-value {
  font-family: var(--font-title);
  font-size: var(--fs-h5);
  line-height: var(--lh-snug);
  color: var(--cvg-text);
  margin-bottom: 8px;
  overflow-wrap: anywhere;
}

.contact-card-value a {
  color: var(--cvg-navy);
  text-decoration: underline;
  text-decoration-color: var(--cvg-gold-hairline);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color var(--t-fast);
}

.contact-card-value a:hover,
.contact-card-value a:focus {
  text-decoration-color: var(--cvg-gold-shadow);
}

.contact-card-note {
  font-size: var(--fs-small);
  color: var(--cvg-text-2);
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   Reveal-on-scroll. The hidden state is gated on `scripting: enabled` rather
   than on a class added by JavaScript: the media query is evaluated at first
   paint, so there is no flash of visible-then-hidden content, and a browser
   with JavaScript off (or one that does not support the feature) ignores the
   block entirely and shows everything.
   -------------------------------------------------------------------------- */
@media (scripting: enabled) {
  /* The hidden state must never outlive the code that clears it. This
     animation reveals the element with no JavaScript involvement at all, so a
     blocked CDN, a 404 on custom.js or a thrown error cannot strand content
     invisible. When JS is healthy, .is-visible wins long before this fires. */
  .reveal {
    opacity: 0;
    transform: translate3d(0, 22px, 0);
    transition: opacity 700ms var(--ease-soft), transform 700ms var(--ease-soft);
    animation: cvg-reveal-failsafe 0s linear 5s forwards;
  }

  .reveal.is-visible {
    opacity: 1;
    transform: none;
    animation: none;
  }

  @keyframes cvg-reveal-failsafe {
    to {
      opacity: 1;
      transform: none;
    }
  }

  .reveal-d2 { transition-delay: 70ms; }
  .reveal-d3 { transition-delay: 140ms; }
  .reveal-d4 { transition-delay: 210ms; }
  .reveal-d5 { transition-delay: 280ms; }
  .reveal-d6 { transition-delay: 350ms; }
  .reveal-d7 { transition-delay: 420ms; }
  .reveal-d8 { transition-delay: 490ms; }
}

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

  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .card-product,
  .card-guide,
  .icon-btn,
  .header-inner,
  .mega-link,
  .mega-link::before,
  .nav-caret,
  .nav-link-cvg::after,
  .card-product-foot::after,
  .card-colour-count::after {
    transition: none;
  }

}

/* The header panels under reduced motion, desktop only (below 1200px the
   drop is the hamburger's static list and must not be translated). They
   need their own, more specific rules: the transition-none list above
   sits at one class of specificity and the base transitions live on two,
   so a bare .mega or .drop entry there would never apply. The fade and
   slide go, but the 250ms close delay stays, because it is what lets a
   pointer cross the bar's lower padding into the panel; without it the
   panel vanishes before it can be reached. The open rules' higher
   specificity still zeroes the delay, so opening stays instant. */
@media (prefers-reduced-motion: reduce) and (min-width: 1200px) {
  .has-mega .mega {
    transform: none;
    transition: opacity 0s linear 250ms, visibility 0s linear 250ms;
  }

  .has-drop .drop {
    transform: translate(-50%, 0);
    transition: opacity 0s linear 250ms, visibility 0s linear 250ms;
  }
}

/* --------------------------------------------------------------------------
   Phone-width fixes (last, so they win over the base component rules)
   -------------------------------------------------------------------------- */
@media (max-width: 575.98px) {
  .section-head {
    margin-bottom: 36px;
  }
}

/* --------------------------------------------------------------------------
   Vertical spacing utilities. Last in the file so they win over component
   rules. Horizontal and micro spacing use Bootstrap (.me-*, .gap-*).
   -------------------------------------------------------------------------- */
.p-t-5   { padding-top: 5px; }
.p-t-10  { padding-top: 10px; } 
.p-t-15  { padding-top: 15px; }
.p-t-20  { padding-top: 20px; }
.p-t-25  { padding-top: 25px; }
.p-t-30  { padding-top: 30px; }
.p-t-40  { padding-top: 40px; }
.p-t-50  { padding-top: 50px; }
.p-t-60  { padding-top: 60px; }
.p-t-70  { padding-top: 70px; }
.p-t-80  { padding-top: 80px; }
.p-t-100 { padding-top: 100px; }

.p-b-5   { padding-bottom: 5px; }
.p-b-10  { padding-bottom: 10px; }
.p-b-15  { padding-bottom: 15px; }
.p-b-20  { padding-bottom: 20px; }
.p-b-25  { padding-bottom: 25px; }
.p-b-30  { padding-bottom: 30px; }
.p-b-40  { padding-bottom: 40px; }
.p-b-50  { padding-bottom: 50px; }
.p-b-60  { padding-bottom: 60px; }
.p-b-70  { padding-bottom: 70px; }
.p-b-80  { padding-bottom: 80px; }
.p-b-100 { padding-bottom: 100px; }

.m-b-5   { margin-bottom: 5px; }
.m-b-10  { margin-bottom: 10px; }
.m-b-15  { margin-bottom: 15px; }
.m-b-20  { margin-bottom: 20px; }
.m-b-25  { margin-bottom: 25px; }
.m-b-30  { margin-bottom: 30px; }
.m-b-40  { margin-bottom: 40px; }
.m-b-50  { margin-bottom: 50px; }
.m-b-60  { margin-bottom: 60px; }
.m-b-70  { margin-bottom: 70px; }
.m-b-80  { margin-bottom: 80px; }
.m-b-100 { margin-bottom: 100px; }
