/*
Theme Name:   GCG Reports
Theme URI:    https://comparablty.com/
Description:  Child theme of Hello Elementor for the Comparablty transfer-pricing report store. Carries the Black & Steel design tokens, the "Arm's Length" brand mark, and the generated typographic report covers that remove the need for per-product artwork.
Author:       Web Impetus
Author URI:   https://www.webimpetus.com/
Template:     hello-elementor
Version:      1.34.3
Text Domain:  gcg-reports

Designed and developed by Web Impetus - https://www.webimpetus.com
Hand-built: no page builder, no framework, no component library.
*/

/* ==========================================================================
   Tokens - Black & Silver, approved 8 September 2026. Every colour on the site
   resolves from this block; nothing below hard-codes a hex value.
   ========================================================================== */

:root {
  /* Black & Silver, approved 8 September 2026. Replaced the warm Ink & Bone
     scheme; the token names are unchanged, so this was a values-only swap. */
  --gcg-ink:        #0E1013;
  --gcg-ink-soft:   #171A1F;
  --gcg-ink-line:   #272B32;
  --gcg-bone:       #F4F5F7;
  --gcg-tint:       #E3E6EA;
  /* Steel blue, chosen by the client from the duotone options on 21 September
     2026. The logo highlight and the site accent are deliberately the SAME two
     values - picking a colour for the wordmark and leaving the store in slate
     would have read as two brands. Verified against every ground it lands on:
     6.2:1 on bone, 6.8:1 on white, 5.4:1 on tint, 8.4:1 on ink. */
  --gcg-accent-dk:  #8AB0D0;   /* accent on dark grounds */
  --gcg-accent-lt:  #2D5F86;   /* accent on light grounds */

  /* Two muted tones, not one. The old single --gcg-secondary was used on both
     grounds; in this palette a value light enough for ink falls to 3.9:1 on a
     white card, which fails AA at the sizes it is used. Light grounds get the
     darker one by default - that is the majority of its uses - and the five
     dark-ground places name the lighter one explicitly. */
  --gcg-secondary:    #5F6975;  /* muted text on LIGHT grounds */
  --gcg-secondary-dk: #98A1AD;  /* muted text on DARK grounds */
  --gcg-on-dark:      #C0C7D1;  /* secondary text on DARK grounds - nav, ledes, labels */

  --gcg-line:       #D7DBE1;
  --gcg-white:      #FFFFFF;
  --gcg-body:       #39404A;

  --gcg-wrap: 1180px;
  --gcg-gutter: 24px;
  --gcg-sans: "Manrope", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --gcg-serif: "Newsreader", Georgia, "Times New Roman", serif;
}

/* ==========================================================================
   Base
   ========================================================================== */

html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--gcg-bone);
  color: var(--gcg-ink);
  font-family: var(--gcg-sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;

  /* clip, not hidden: "hidden" on one axis forces the other to "auto", which
     makes body a scroll container and silently kills position:sticky on the
     product page. "clip" contains stray overflow without that side effect. */
  overflow-x: clip;
}

h1, h2, h3, h4,
.gcg-serif {
  font-family: var(--gcg-serif);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.01em;
  text-wrap: balance;
  overflow-wrap: break-word;
}

img { max-width: 100%; height: auto; }

/* Hello Elementor styles every bare button as a pink outline button (#c36),
   including on hover. Nothing in this palette is pink, and any control that is
   not one of ours inherits it - the nav toggle and WordPress's password-reveal
   button both did.

   Match the parent's selector list exactly, attribute selectors included. It
   writes `[type="button"]:hover` alongside `button:hover`, and every button we
   render carries a type, so a plain `button:hover` here (0,1,1) loses to the
   attribute form (0,2,0). Same shape means the same specificity, and a child
   theme loads later, so we win the tie.

   This is the base. Each control opts into its own look through a class further
   down the file, which either outranks this or ties and wins on order - so keep
   this block above the components. See trap 10. */
button,
[type="button"],
[type="submit"],
[type="reset"] {
  background-color: transparent;
  border: 0;
  border-radius: 0;
  color: inherit;
  font: inherit;
}
button:hover, button:focus,
[type="button"]:hover, [type="button"]:focus,
[type="submit"]:hover, [type="submit"]:focus,
[type="reset"]:hover, [type="reset"]:focus {
  background-color: transparent;
  color: inherit;
}

/* Links: the browser default blue has no place in this palette.
 *
 * Hover colour resolves from a surface-level custom property rather than a
 * stack of ancestor rules. Each surface declares what a hovered link should
 * become; because custom properties inherit, a light panel nested inside a dark
 * one - the mini-cart, the account menu - just re-declares it and everything
 * inside follows. Ancestor-selector rules could not do that: they only ever get
 * more specific going down, so a dark-header rule would always beat a
 * light-panel rule and repaint the panel's links bone-on-bone.
 */
:root { --gcg-link-hover: var(--gcg-accent-lt); }

/* The logo's "blty" highlight. Same ground-flipping idiom as --gcg-link-hover
   below: slate on light, silver on dark, set once per surface rather than per
   component. It is the palette's own accent, not a new hue - the identity is
   two inks and an accent, and adding a fourth colour to shout one syllable
   would cost more than it buys. To try a real hue, change these two lines. */
:root { --gcg-logo-accent: var(--gcg-accent-lt); }

/* Dark grounds */
.gcg-header, .gcg-footer, .gcg-hero,
.gcg-band-dark, .gcg-cover { --gcg-link-hover: var(--gcg-bone); }

.gcg-header, .gcg-footer, .gcg-band-dark,
.gcg-search-panel, .gcg-search-bar { --gcg-logo-accent: var(--gcg-accent-dk); }

/* Light panels that sit inside a dark ground */
.gcg-account-menu { --gcg-link-hover: var(--gcg-ink); }

/* The tint band is dark enough that the light accent only reaches 3.97:1 on it,
   just under AA. Ink instead. */
.gcg-band-tint, .gcg-related, .gcg-hero,
.gcg-page-head, .gcg-shop-head { --gcg-link-hover: var(--gcg-ink); }

a { color: inherit; text-decoration-color: var(--gcg-line); }
a:hover, a:focus { color: var(--gcg-link-hover); }

.gcg-prose a,
.gcg-split-main a:not(.gcg-btn):not(.gcg-channel),
.page-content a,
.comments-area a { color: var(--gcg-accent-lt); text-decoration: underline; text-underline-offset: 3px; }
.gcg-prose a:hover, .gcg-split-main a:not(.gcg-btn):not(.gcg-channel):hover, .page-content a:hover { color: var(--gcg-ink); }

:focus-visible { outline: 2px solid var(--gcg-accent-lt); outline-offset: 2px; }
.gcg-header :focus-visible, .gcg-footer :focus-visible,
.gcg-band-dark :focus-visible { outline-color: var(--gcg-accent-dk); }

.gcg-wrap { max-width: var(--gcg-wrap); margin: 0 auto; padding: 0 var(--gcg-gutter); }

/* Hello Elementor caps .site-main at 1140px, which would break the full-bleed
   bands. Our templates carry their own .gcg-wrap, so the cap is removed. */
body:not([class*="elementor-page-"]) .site-main,
.content-area { max-width: none; width: 100%; padding-inline: 0; }

.gcg-eyebrow {
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--gcg-accent-lt); margin: 0 0 14px;
}
.gcg-band-dark .gcg-eyebrow { color: var(--gcg-accent-dk); }

.gcg-lede { font-size: 1.08rem; color: var(--gcg-body); max-width: 62ch; }
.gcg-band-dark .gcg-lede { color: var(--gcg-on-dark); }

/* ==========================================================================
   Header
   ========================================================================== */

.gcg-header { background: var(--gcg-ink); color: var(--gcg-bone); border-bottom: 1px solid var(--gcg-ink-line); }
.gcg-header-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; min-height: 76px; flex-wrap: wrap;
}

/* The "Arm's Length" lockup: inline mark, wordmark, descriptor.

   Nothing in this block names a palette colour. The mark is inline SVG filled
   with currentColor and the wordmark inherits, so the whole lockup takes the
   colour of the surface it sits on - bone in the dark header today, ink the day
   that header turns light, with no edit here. The previous version hard-coded
   --gcg-bone on the wordmark and --gcg-secondary-dk on the descriptor, which
   would have painted both invisible on a light header. See trap 08. */
.gcg-logo {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; line-height: 1; flex: 0 0 auto;
  color: var(--gcg-logo-ink);
}
.gcg-logo-glyph { flex: 0 0 auto; display: block; }
.gcg-logo-lockup { display: flex; flex-direction: column; min-width: 0; }

/* Sized down from 1.75rem, which crowded the cart and the nav toggle on a
   narrow header. The wordmark went from thirteen letters to eleven in the
   Comparables rename, and to ten in the Comparablty rename, so there is a little
   more room again - but the size stays, because it is set against the mark, not
   against the header. Steps down under 380px. */
.gcg-logo-accent { color: var(--gcg-logo-accent); }

.gcg-logo-name { font-family: var(--gcg-serif); font-size: 1.45rem; letter-spacing: -0.02em; color: inherit; }

/* Muted from the surface colour rather than from a fixed token, for the same
   reason. 62% of bone on ink lands at ~7:1 and 62% of ink on bone at 5.5:1,
   so it clears AA at this size on either ground.

   Size and tracking were retuned for the Comparables rename and re-checked for
   Comparablty, which is one letter shorter again. Under the old thirteen-letter
   wordmark this sat at 0.53rem/0.26em and the two lined up; against eleven
   letters that same setting ran 45% wider than the word above
   it, which made the descriptor read as the dominant element. It cannot match
   the wordmark exactly - at 0.53rem the glyph advances alone already equal it,
   before any tracking - so it is set to overhang by under 10%, which reads as
   deliberate rather than as a lockup that has come apart. */
.gcg-logo-tag {
  font-size: 0.46rem; letter-spacing: 0.15em; text-transform: uppercase;
  color: color-mix(in srgb, currentColor 62%, transparent); margin-top: 5px;
}

/* Rest and hover are both surface properties, declared the same way as
   --gcg-link-hover above.

   Rest cannot simply be `inherit`: the footer deliberately sets its body text
   to the muted --gcg-secondary-dk, and a logo inheriting that renders grey
   against the bone headings beside it. The lockup wants the surface's PRIMARY
   colour, which no amount of inheritance can work out on its own.

   THREE surfaces carry a logo, so three are listed. If the header turns light,
   remove it from this line and the whole lockup - mark included - follows,
   because everything inside resolves from currentColor.

   .gcg-search-bar was missing here until 21 September 2026, and the logo in the
   search panel had been rendering ink-on-ink - invisible - for as long as that
   panel has existed. Nobody saw it because the whole lockup disappeared
   together and read as "no logo in the modal". It only became reportable when
   the duotone gave "blty" its own colour from --gcg-logo-accent, which IS set
   on the panel: half the word appeared, and the missing half finally had
   something to be missing next to.

   The lesson is in the line above: a list of surfaces is a thing to update when
   a surface is added, and this one was added without it. */
:root           { --gcg-logo-ink: var(--gcg-ink);  --gcg-logo-hover: var(--gcg-accent-lt); }
.gcg-header,
.gcg-footer,
.gcg-search-bar { --gcg-logo-ink: var(--gcg-bone); --gcg-logo-hover: var(--gcg-accent-dk); }

/* (0,2,0) here beats the global a:hover at (0,1,1). */
.gcg-logo:hover, .gcg-logo:focus-visible { color: var(--gcg-logo-hover); }

.gcg-nav { display: flex; align-items: center; }
.gcg-nav ul { display: flex; align-items: center; gap: 26px; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.gcg-nav a { font-size: 0.86rem; text-decoration: none; color: var(--gcg-on-dark); white-space: nowrap; }
.gcg-nav a:hover, .gcg-nav a:focus,
.gcg-nav .current-menu-item > a { color: var(--gcg-bone); }

/* Benchmarking carries the methods beneath it. Everything on this store is a
   benchmarking study, so the catalogue hangs off one nav item rather than
   spreading across several top-level ones.

   Deliberately CSS-only: :hover opens it for pointers and :focus-within opens it
   for keyboards, so it needs no script and cannot break if one fails to load.
   Scoped above the mobile breakpoint - below it the panel is just a nested list,
   styled at the bottom of this file. */
@media (min-width: 901px) {
  .gcg-nav li { position: relative; }
  .gcg-nav .sub-menu {
    position: absolute; top: calc(100% + 20px); left: -18px; z-index: 60;
    display: block; min-width: 200px; padding: 8px 0; gap: 0;
    background: var(--gcg-white); color: var(--gcg-ink);
    border: 1px solid var(--gcg-line); border-radius: 2px;
    box-shadow: 0 18px 40px color-mix(in srgb, var(--gcg-ink) 28%, transparent);
    opacity: 0; visibility: hidden; transform: translateY(-6px);
    transition: opacity .16s ease, transform .16s ease, visibility .16s;

    /* Light panel hanging inside the dark header: without this the header's
       bone hover colour would paint bone links on a white ground. See trap 08. */
    --gcg-link-hover: var(--gcg-ink);
  }
  /* Bridges the gap between the item and the panel so the pointer can cross it. */
  .gcg-nav .sub-menu::before { content: ""; position: absolute; top: -22px; left: 0; right: 0; height: 22px; }
  .gcg-nav li:hover > .sub-menu,
  .gcg-nav li:focus-within > .sub-menu { opacity: 1; visibility: visible; transform: translateY(0); }
  .gcg-nav .sub-menu a { display: block; padding: 9px 18px; color: var(--gcg-body); white-space: nowrap; }
  .gcg-nav .sub-menu a:hover,
  .gcg-nav .sub-menu a:focus { background: var(--gcg-bone); color: var(--gcg-ink); }
  .gcg-nav .sub-menu .current-menu-item > a { color: var(--gcg-ink); }
}

.gcg-header-actions { display: flex; align-items: center; gap: 10px; order: 3; }

.gcg-cart {
  display: inline-flex; align-items: center; gap: 8px; white-space: nowrap;
  border: 1px solid var(--gcg-ink-line); border-radius: 2px;
  padding: 8px 14px; font-size: 0.82rem; text-decoration: none; color: var(--gcg-bone);
}
.gcg-cart:hover { border-color: var(--gcg-accent-dk); color: var(--gcg-bone); }
.gcg-cart-count {
  background: var(--gcg-accent-dk); color: var(--gcg-ink); border-radius: 999px;
  min-width: 18px; height: 18px; display: inline-grid; place-items: center;
  font-size: 0.68rem; font-weight: 700; padding: 0 5px;
}

/* Account control, sitting beside the cart. */
.gcg-account-wrap { position: relative; }
.gcg-account {
  display: inline-flex; align-items: center; white-space: nowrap;
  padding: 8px 4px; font-size: 0.82rem; text-decoration: none; color: var(--gcg-on-dark);
}
.gcg-account:hover { color: var(--gcg-bone); }
.gcg-account-signin { border-bottom: 1px solid transparent; }
.gcg-account-signin:hover { border-bottom-color: var(--gcg-accent-dk); }

.gcg-account-menu {
  position: absolute; top: calc(100% + 22px); right: 0; z-index: 60;
  min-width: 210px; padding: 8px 0;
  background: var(--gcg-white); color: var(--gcg-ink);
  border: 1px solid var(--gcg-line); border-radius: 2px;
  box-shadow: 0 18px 40px color-mix(in srgb, var(--gcg-ink) 28%, transparent);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
}
.gcg-account-menu::before { content: ""; position: absolute; top: -24px; left: 0; right: 0; height: 24px; }
.gcg-account-wrap.is-open .gcg-account-menu { opacity: 1; visibility: visible; transform: translateY(0); }
.gcg-account-menu ul { list-style: none; margin: 0; padding: 0; }
.gcg-account-menu a {
  display: block; padding: 9px 18px; font-size: 0.86rem;
  text-decoration: none; color: var(--gcg-body);
}
.gcg-account-menu a:hover { background: var(--gcg-bone); color: var(--gcg-ink); }

@media (hover: none), (max-width: 900px) {
  .gcg-account-menu { display: none; }
}

.gcg-nav-toggle {
  display: none; align-items: center; justify-content: center;
  width: 40px; height: 38px; padding: 0; cursor: pointer;
  background: transparent; border: 1px solid var(--gcg-ink-line); border-radius: 2px;
}
.gcg-nav-toggle:hover { border-color: var(--gcg-accent-dk); }
.gcg-nav-toggle-bars { display: block; width: 18px; }
.gcg-nav-toggle-bars span {
  display: block; height: 1.5px; background: var(--gcg-bone);
  margin: 4px 0; transition: transform .15s ease, opacity .15s ease;
}
.gcg-nav-toggle[aria-expanded="true"] .gcg-nav-toggle-bars span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.gcg-nav-toggle[aria-expanded="true"] .gcg-nav-toggle-bars span:nth-child(2) { opacity: 0; }
.gcg-nav-toggle[aria-expanded="true"] .gcg-nav-toggle-bars span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

/* ==========================================================================
   Footer
   ========================================================================== */

.gcg-footer { background: var(--gcg-ink); color: var(--gcg-secondary-dk); padding: 56px 0 30px; font-size: 0.86rem; }
.gcg-footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 34px; }
.gcg-footer-grid h4 { font-family: var(--gcg-sans); font-size: 0.68rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gcg-bone); margin: 0 0 14px; }
.gcg-footer-grid ul { list-style: none; padding: 0; margin: 0; }
.gcg-footer-grid li { margin-bottom: 9px; }
.gcg-footer-grid a { text-decoration: none; }
.gcg-footer-blurb { max-width: 34ch; margin-top: 14px; }
.gcg-footer-bottom {
  border-top: 1px solid var(--gcg-ink-line); margin-top: 42px; padding-top: 22px;
  display: flex; justify-content: space-between; gap: 12px 16px; flex-wrap: wrap;
  font-size: 0.78rem; color: var(--gcg-secondary-dk);
}

/* --- agency credit --------------------------------------------------------
   Sits opposite the copyright in the footer's bottom bar. Markup comes from
   inc/credit.php, not from this template, so it survives a footer rebuild.
   ------------------------------------------------------------------------ */
/* The visible agency credit was removed in 1.28.0 at the client's request;
   its .gcg-credit* rules went with it. Attribution is source-only now. */

/* ==========================================================================
   Bands and buttons
   ========================================================================== */

.gcg-band { padding: 76px 0; }
.gcg-band-dark { background: var(--gcg-ink); color: var(--gcg-bone); }
.gcg-band-tint { background: var(--gcg-tint); }
.gcg-band-white { background: var(--gcg-white); }
.gcg-band-tight { padding: 48px 0; }

.gcg-hero {
  /* Light, at the client's instruction - the banner may not be dark. Tint
     rather than the page ground, so the hero still separates from the section
     under it without a rule. The texture and glows below carry the presence
     the ink used to. */
  background: var(--gcg-tint); color: var(--gcg-ink);
  padding: 92px 0 84px; position: relative; isolation: isolate; overflow: hidden;
}

/* The hero's own buttons. The shared .gcg-btn-primary is silver-on-ink, which
   is a dark-ground button; on tint it has almost no contrast. Ink instead. */
.gcg-hero .gcg-btn-primary { background: var(--gcg-ink); color: var(--gcg-bone); }
.gcg-hero .gcg-btn-primary:hover, .gcg-hero .gcg-btn-primary:focus { background: var(--gcg-ink-soft); color: var(--gcg-bone); }
.gcg-hero .gcg-btn-ghost { border-color: var(--gcg-line); color: var(--gcg-ink); }
.gcg-hero .gcg-btn-ghost:hover, .gcg-hero .gcg-btn-ghost:focus { border-color: var(--gcg-ink); color: var(--gcg-ink); }
.gcg-hero > .gcg-wrap { position: relative; z-index: 2; }
.gcg-hero h1 { max-width: 20ch; font-size: clamp(1.9rem, 5vw, 3.4rem); margin: 0; }
.gcg-hero .gcg-lede { margin-top: 22px; }
.gcg-hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }

/* --- hero background -----------------------------------------------------
   A fine dot grid over the ground, plus two very slow drifting accent glows.
   Both are decorative, compositor-only (transform/opacity), and stop entirely
   under prefers-reduced-motion. Kept low-contrast so the hero still reads as
   an institutional page.
   ------------------------------------------------------------------------ */

.gcg-hero-bg {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  overflow: hidden;
}

/* dot grid */
.gcg-hero-bg::before {
  content: ""; position: absolute; inset: -10%;
  background-image: radial-gradient(circle at center, color-mix(in srgb, var(--gcg-ink) 9%, transparent) 1px, transparent 1px);
  background-size: 26px 26px;
  /* fade the grid out toward the edges so it never fights the type */
  -webkit-mask-image: radial-gradient(ellipse 90% 75% at 30% 45%, #000 20%, transparent 78%);
          mask-image: radial-gradient(ellipse 90% 75% at 30% 45%, #000 20%, transparent 78%);
}

/* a hairline horizon, the kind of rule an instrument panel has */
.gcg-hero-bg::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--gcg-accent-lt) 30%, transparent), transparent);
}

.gcg-hero-glow {
  position: absolute; border-radius: 50%; filter: blur(70px);
  opacity: 0.5; will-change: transform;
}
.gcg-hero-glow-a {
  width: 46vw; height: 46vw; max-width: 640px; max-height: 640px;
  top: -18%; right: -6%;
  background: radial-gradient(circle, color-mix(in srgb, var(--gcg-accent-lt) 13%, transparent), transparent 68%);
  animation: gcg-drift-a 26s ease-in-out infinite alternate;
}
.gcg-hero-glow-b {
  width: 38vw; height: 38vw; max-width: 520px; max-height: 520px;
  bottom: -24%; left: 4%;
  background: radial-gradient(circle, color-mix(in srgb, var(--gcg-accent-lt) 10%, transparent), transparent 70%);
  animation: gcg-drift-b 34s ease-in-out infinite alternate;
}

@keyframes gcg-drift-a {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-7%, 9%, 0) scale(1.12); }
}
@keyframes gcg-drift-b {
  from { transform: translate3d(0, 0, 0) scale(1.06); }
  to   { transform: translate3d(9%, -7%, 0) scale(0.94); }
}

/* --- the same treatment on the other dark grounds ------------------------
   Page heads, the dark band and the footer get the hero's dot grid and one
   soft glow, drawn with pseudo-elements so no extra markup is needed.
   The drift stays exclusive to the hero: it is the one surface tall enough
   for the motion to read, and keeping it there preserves the hierarchy
   rather than making every dark band move.
   ------------------------------------------------------------------------ */

.gcg-page-head,
.gcg-shop-head,
.gcg-band-dark,
.gcg-footer {
  position: relative; isolation: isolate; overflow: hidden;
}

/* Content sits above the texture. */
.gcg-page-head > *,
.gcg-shop-head > *,
.gcg-band-dark > *,
.gcg-footer > * { position: relative; z-index: 2; }

/* dot grid */
.gcg-page-head::before,
.gcg-shop-head::before,
.gcg-band-dark::before,
.gcg-footer::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: radial-gradient(circle at center, color-mix(in srgb, var(--gcg-bone) 11%, transparent) 1px, transparent 1px);
  background-size: 26px 26px;
  -webkit-mask-image: radial-gradient(ellipse 85% 100% at 26% 40%, #000 12%, transparent 76%);
          mask-image: radial-gradient(ellipse 85% 100% at 26% 40%, #000 12%, transparent 76%);
}

/* The two page banners are light now, so their grid is drawn in ink; the dark
   band and the footer keep the bone one above. Placed after that rule on
   purpose - same specificity, so order decides it and no !important is needed. */
.gcg-page-head::before,
.gcg-shop-head::before {
  background-image: radial-gradient(circle at center, color-mix(in srgb, var(--gcg-ink) 9%, transparent) 1px, transparent 1px);
}

/* glow */
.gcg-page-head::after,
.gcg-shop-head::after,
.gcg-band-dark::after {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  top: -60%; right: -8%; width: 46%; aspect-ratio: 1;
  border-radius: 50%; filter: blur(70px); opacity: 0.55;
  background: radial-gradient(circle, color-mix(in srgb, var(--gcg-accent-dk) 28%, transparent), transparent 68%);
}

/* The band is tall enough for a second, opposing glow. */
.gcg-band-dark::after { top: -46%; }

/* The footer is a closing surface, so it takes the grid but no glow -
   a lit footer competes with the content above it. */
.gcg-footer::before {
  -webkit-mask-image: radial-gradient(ellipse 70% 120% at 18% 30%, #000 8%, transparent 72%);
          mask-image: radial-gradient(ellipse 70% 120% at 18% 30%, #000 8%, transparent 72%);
}

/* The hero already has its own layers; do not double them up. */
.gcg-hero::before, .gcg-hero::after { content: none; }

/* The trust strip is a thin rule between two dark surfaces - a grid there
   would read as dirt at that height. It keeps its flat ground. */

.gcg-btn,
.woocommerce a.button, .woocommerce button.button, .woocommerce input.button,
.woocommerce #respond input#submit, .woocommerce a.button.alt,
.woocommerce button.button.alt, .woocommerce input.button.alt,
.wpcf7 input[type="submit"] {
  display: inline-block; padding: 13px 26px; border-radius: 2px;
  font-family: var(--gcg-sans); font-size: 0.86rem; font-weight: 600; letter-spacing: 0.02em;
  text-decoration: none; cursor: pointer; border: 1px solid transparent;
  background: var(--gcg-ink); color: var(--gcg-bone); line-height: 1.4;
  text-transform: none;
}
.woocommerce a.button:hover, .woocommerce button.button:hover,
.woocommerce input.button:hover, .woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover, .woocommerce input.button.alt:hover,
.wpcf7 input[type="submit"]:hover {
  background: var(--gcg-ink-soft); color: var(--gcg-bone);
}

.gcg-btn-primary { background: var(--gcg-accent-dk); color: var(--gcg-ink); }
.gcg-btn-primary:hover, .gcg-btn-primary:focus { background: var(--gcg-bone); color: var(--gcg-ink); }
.gcg-btn-ghost { background: transparent; border-color: color-mix(in srgb, var(--gcg-bone) 26%, var(--gcg-ink)); color: var(--gcg-bone); }
.gcg-btn-ghost:hover, .gcg-btn-ghost:focus { border-color: var(--gcg-accent-dk); background: transparent; color: var(--gcg-bone); }
.gcg-btn-dark { background: var(--gcg-ink); color: var(--gcg-bone); }
.gcg-btn-dark:hover, .gcg-btn-dark:focus { background: var(--gcg-ink-soft); color: var(--gcg-bone); }
.gcg-btn-outline { background: transparent; border-color: var(--gcg-ink); color: var(--gcg-ink); }
.gcg-btn-outline:hover, .gcg-btn-outline:focus { background: var(--gcg-ink); color: var(--gcg-bone); }
.gcg-btn-lg { padding: 16px 32px; font-size: 0.94rem; }
.gcg-btn-block { display: block; width: 100%; text-align: center; }

/* ==========================================================================
   Trust strip
   ========================================================================== */

/* The .gcg-trust "Sourced from" strip was removed on 16 September 2026 along
   with the PHP behind it — see the note in functions.php. */

/* ==========================================================================
   Section heads, category cards, steps
   ========================================================================== */

.gcg-section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px 24px; margin-bottom: 34px; flex-wrap: wrap; }
.gcg-section-head h2 { font-size: clamp(1.5rem, 3.4vw, 2.4rem); margin: 0; }
.gcg-section-head .gcg-link { font-size: 0.84rem; font-weight: 600; text-decoration: none; border-bottom: 1px solid var(--gcg-accent-lt); padding-bottom: 2px; white-space: nowrap; }
.gcg-band-dark .gcg-section-head .gcg-link { border-color: var(--gcg-accent-dk); }
.gcg-band-dark .gcg-section-head .gcg-link:hover { color: var(--gcg-bone); border-color: var(--gcg-bone); }

.gcg-cat-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; }
.gcg-cat { border: 1px solid var(--gcg-line); background: var(--gcg-white); border-radius: 2px; padding: 26px 22px; text-decoration: none; color: inherit; transition: border-color .15s ease; display: block; }
.gcg-cat:hover { border-color: var(--gcg-accent-lt); color: inherit; }
.gcg-cat h3 { margin: 0 0 8px; font-size: 1.25rem; }
.gcg-cat p { font-size: 0.86rem; color: var(--gcg-secondary); margin: 0 0 14px; }
.gcg-cat .gcg-count { font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--gcg-accent-lt); }

.gcg-steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 34px; }
/* The steps band is light now, so the numeral takes the light-ground accent
   and the body copy takes the ordinary body colour. */
.gcg-step-num { font-family: var(--gcg-serif); font-size: 2.2rem; color: var(--gcg-accent-lt); line-height: 1; }
.gcg-step h3 { margin: 12px 0 8px; font-size: 1.25rem; }
.gcg-step p { font-size: 0.9rem; color: var(--gcg-body); margin: 0; }

.gcg-cols-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.gcg-cols-3 h3 { margin: 0 0 10px; font-size: 1.25rem; }
.gcg-cols-3 p { font-size: 0.94rem; color: var(--gcg-body); margin: 0; }

/* Both of the grids above hold lists whose length tracks the business rather
   than the design: two benchmarking methods today and three once Financial
   Transactions is published, two purchase steps today and three if the branding
   step returns. A hard-coded column count leaves a visibly empty column whenever
   those disagree, so the count is published in the markup and read back here.

   Scoped to the wide breakpoints deliberately. These are attribute selectors,
   (0,2,0), while the narrow-screen rules further down this file are plain class
   selectors, (0,1,0) - and a media query adds no specificity of its own. Left
   unscoped these would outrank the stacking rules and quietly break the mobile
   layout. See trap 10. */
@media (min-width: 1025px) {
  .gcg-cat-grid[data-count="1"] { grid-template-columns: minmax(0, 420px); }
  .gcg-cat-grid[data-count="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gcg-cat-grid[data-count="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 901px) {
  .gcg-steps[data-count="1"] { grid-template-columns: minmax(0, 520px); }
  .gcg-steps[data-count="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ==========================================================================
   Customer support
   ==========================================================================
   Channels are configured in inc/support.php. Anything not configured is not
   rendered, so these rules have to hold up with the WhatsApp elements missing.
   ========================================================================== */

/* ONE COLUMN since 1.28.0.

   This was a two-column grid with the copy on the left and the enquiry card on
   the right. The card was removed at the client's request, and a two-column
   grid with one child does not collapse - it kept reserving 437px of empty
   column and squeezed the copy into little over half the band for nothing. */
.gcg-support-band .gcg-support-inner {
  display: block;
}
.gcg-support-band .gcg-support-copy { max-width: 62ch; }
.gcg-support-copy h2 { margin: 0 0 16px; }
.gcg-support-lede { color: var(--gcg-body); margin: 0 0 16px; max-width: 60ch; }
.gcg-support-meta {
  font-size: 0.8rem; letter-spacing: 0.04em; color: var(--gcg-accent-lt); margin: 0;
}
/* STACKED, not a row. The client asked for the address to sit on its own line
   under WhatsApp with a mail icon beside it - as a row they read as one
   run-on sentence and the email looked like an afterthought. */
.gcg-support-alt {
  list-style: none; margin: 20px 0 0; padding: 0;
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
  font-size: 0.9rem;
}
.gcg-support-alt a {
  display: inline-flex; align-items: center; gap: 9px;
  color: var(--gcg-accent-lt); text-decoration: none;
}
.gcg-support-alt a:hover, .gcg-support-alt a:focus { color: var(--gcg-ink); }
.gcg-support-alt svg { flex: none; }
/* The mail glyph is stroked and the WhatsApp mark is filled, so at the same box
   size the envelope reads a little lighter. A hair more weight evens them up. */
.gcg-mail-icon { width: 17px; height: 17px; }

/* The enquiry card.
   Was translucent glass while this band was ink. The band is tinted now, so
   glass over it would be a barely-there rectangle - the card is solid white
   instead, which is what gives it separation from the ground it sits on. */
.gcg-support-form {
  padding: 26px 24px;
  background: var(--gcg-white);
  border: 1px solid var(--gcg-line);
  border-radius: 3px;
  box-shadow: 0 14px 34px rgba(14, 16, 19, 0.06);
}
.gcg-support-form-title {
  font-family: var(--gcg-sans); font-size: 0.68rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--gcg-accent-lt); margin: 0 0 18px;
}

/* The form inside the card.
   Every selector here carries `.gcg-support-form .wpcf7` on purpose. The site's
   own CF7 rules further down this file are `.wpcf7 input[...]`, (0,2,0), and
   they are LATER in the file - a matching (0,2,0) here would tie and lose, which
   is exactly what happened first time round: white boxes on a dark card. Adding
   the wrapper makes these (0,3,0) and settles it on specificity rather than
   ordering, so moving this block cannot break it. See trap 10. */
.gcg-support-form .wpcf7 { margin-top: 0; max-width: none; }
.gcg-support-form .gcg-form-row { margin: 0 0 14px; }
.gcg-support-form .gcg-form-row label {
  display: block;
  font-family: var(--gcg-sans); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--gcg-secondary);
}
.gcg-support-form .gcg-req { color: var(--gcg-accent-lt); }

.gcg-support-form .wpcf7 input[type="text"],
.gcg-support-form .wpcf7 input[type="email"],
.gcg-support-form .wpcf7 textarea {
  display: block; width: 100%; margin-top: 7px; padding: 11px 13px;
  font-family: var(--gcg-sans); font-size: 0.92rem;
  color: var(--gcg-ink);
  background: var(--gcg-bone);
  border: 1px solid var(--gcg-line);
  border-radius: 2px;
  transition: border-color .15s ease, background .15s ease;
}
.gcg-support-form .wpcf7 textarea { resize: vertical; min-height: 84px; }
.gcg-support-form .wpcf7 input::placeholder,
.gcg-support-form .wpcf7 textarea::placeholder { color: var(--gcg-secondary); }
.gcg-support-form .wpcf7 input:focus,
.gcg-support-form .wpcf7 textarea:focus {
  outline: none;
  border-color: var(--gcg-accent-lt);
  background: var(--gcg-white);
}

/* The submit is an <input>, so `.gcg-btn-primary` (0,1,0) never reached it -
   `.wpcf7 input[type="submit"]` (0,2,0) in the button block sets ink and wins.
   State the colour here at (0,3,0) instead of relying on the class. */
.gcg-support-form .gcg-form-actions { margin: 18px 0 0; }
.gcg-support-form .wpcf7 input[type="submit"] {
  width: 100%;
  background: var(--gcg-ink); color: var(--gcg-bone);
  border-color: transparent;
}
.gcg-support-form .wpcf7 input[type="submit"]:hover,
.gcg-support-form .wpcf7 input[type="submit"]:focus {
  background: var(--gcg-ink-soft); color: var(--gcg-bone);
}

/* CF7's own status and validation messages, on the light card. */
.gcg-support-form .wpcf7-not-valid-tip { display: block; margin-top: 6px; font-size: 0.78rem; color: #9B3B2F; }
.gcg-support-form .wpcf7 form .wpcf7-response-output {
  margin: 16px 0 0; padding: 11px 13px;
  background: var(--gcg-bone);
  border: 1px solid var(--gcg-line); border-radius: 2px;
  font-size: 0.85rem; color: var(--gcg-ink);
}
.gcg-support-form .wpcf7 .wpcf7-spinner { margin: 10px auto 0; display: block; }

/* Buttons that carry the glyph need it centred against the label. */
.gcg-btn-wa, .gcg-support-wa, .gcg-wa-float { display: inline-flex; align-items: center; justify-content: center; gap: 9px; }
.gcg-wa-icon { flex: 0 0 auto; }

.gcg-footer-support { margin-top: 26px; }
.gcg-footer-support h4 {
  font-family: var(--gcg-sans); font-size: 0.68rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--gcg-bone); margin: 0 0 10px;
}
.gcg-support-reply { font-size: 0.84rem; color: var(--gcg-secondary-dk); margin: 0 0 12px; max-width: 34ch; }
.gcg-support-links { list-style: none; margin: 0; padding: 0; }
.gcg-support-links li { margin-bottom: 8px; }
.gcg-support-links a { text-decoration: none; font-size: 0.88rem; }

/* The floating WhatsApp button.
   Only reaches the page when a number is saved at Settings → Support.

   Shaped as an app-style floating action button: a circle at rest that widens
   into a pill on hover to show its label, with real elevation and a press
   state. The label is always in the DOM - it is revealed by width, not by
   display - so a screen reader announces "Chat with us" whether or not a
   pointer has ever hovered it.

   Palette, not WhatsApp green. The client has already asked once for a colour
   we do not use elsewhere to be taken off the site, so the button is ink and
   accent like every other control. To go brand-green instead, set --gcg-wa-bg
   to #25D366 and --gcg-wa-fg to #FFFFFF on the rule below; nothing else needs
   to change. */
.gcg-wa-float {
  --gcg-wa-bg: var(--gcg-ink);
  --gcg-wa-fg: var(--gcg-bone);

  position: fixed; right: 28px; bottom: 28px; z-index: 80;
  display: inline-flex; align-items: center; justify-content: center;
  /* No side padding at rest: with a 22px glyph, min-width is what makes this a
     true circle. The padding arrives on hover, when there is a label to sit
     inside it - and padding animates, so the widening stays smooth. */
  height: 56px; min-width: 56px; padding: 0;

  /* gap: 0, overriding the 9px shared with the inline WhatsApp links above.
     A collapsed label is still a flex item, so the gap survives it: the row
     measured 22px glyph + 9px gap + 0px label = 31px, and centring 31px inside
     56px sat the glyph 4.5px left of centre. Those inline links always show
     their label and want the gap; this one spaces itself with the label's own
     margin instead, so it can go to zero when the label does. */
  gap: 0;
  border-radius: 999px;
  background: var(--gcg-wa-bg); color: var(--gcg-wa-fg);
  border: 1px solid color-mix(in srgb, var(--gcg-accent-dk) 34%, transparent);
  font-family: var(--gcg-sans); font-size: 0.86rem; font-weight: 600;
  text-decoration: none; white-space: nowrap;

  /* Two layers: a tight contact shadow and a wide ambient one. A single blur
     reads as a sticker; the pair reads as something lifted off the page. */
  box-shadow: 0 2px 6px color-mix(in srgb, var(--gcg-ink) 28%, transparent), 0 12px 32px color-mix(in srgb, var(--gcg-ink) 30%, transparent);
  transition: background .18s ease, color .18s ease, box-shadow .18s ease,
              padding .26s cubic-bezier(.2, .7, .3, 1),
              transform .18s cubic-bezier(.2, .7, .3, 1);
}
.gcg-wa-float-icon { display: inline-flex; flex: 0 0 auto; }
.gcg-wa-float .gcg-wa-icon { width: 22px; height: 22px; }

/* Ripples, to catch the eye.
   Two rings on the pseudo-elements, the second half a cycle behind the first,
   so one is always on its way out. Only transform and opacity animate, which
   the compositor handles without repainting anything.

   They stop on hover: by then they have done their job, and the button has
   become a pill - a border-radius: 50% ring on a 165x56 box is an ellipse. */
.gcg-wa-float::before,
.gcg-wa-float::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 50%;
  border: 2px solid var(--gcg-accent-dk);
  pointer-events: none;
  opacity: 0;
  animation: gcg-wa-ripple 2.6s cubic-bezier(.22, .61, .36, 1) infinite;
}
.gcg-wa-float::after { animation-delay: 1.3s; }

.gcg-wa-float:hover::before, .gcg-wa-float:hover::after,
.gcg-wa-float:focus-visible::before, .gcg-wa-float:focus-visible::after {
  animation: none; opacity: 0;
}

@keyframes gcg-wa-ripple {
  /* Holding the fade until 85% keeps the ring readable most of the way out.
     Dying at 70% left the second half of the travel invisible, which read as a
     faint flicker at the rim rather than a ripple. */
  0%   { transform: scale(1);    opacity: .6; }
  85%  {                         opacity: 0; }
  100% { transform: scale(2.05); opacity: 0; }
}

/* Collapsed to nothing at rest, so the button is a circle. */
.gcg-wa-float-label {
  max-width: 0; margin-left: 0; opacity: 0; overflow: hidden;
  transition: max-width .26s cubic-bezier(.2, .7, .3, 1), margin-left .26s ease, opacity .18s ease;
}
.gcg-wa-float:hover .gcg-wa-float-label,
.gcg-wa-float:focus-visible .gcg-wa-float-label { max-width: 180px; margin-left: 10px; opacity: 1; }

.gcg-wa-float:hover,
.gcg-wa-float:focus-visible {
  /* accent-dk is the light tan used by the primary button - ~10:1 against ink.
     accent-lt, the darker brown, only reaches ~3.5:1 and fails AA for the label. */
  background: var(--gcg-accent-dk); color: var(--gcg-ink);
  padding: 0 20px;
  transform: translateY(-2px);
  box-shadow: 0 4px 10px color-mix(in srgb, var(--gcg-ink) 30%, transparent), 0 18px 40px color-mix(in srgb, var(--gcg-ink) 34%, transparent);
}
.gcg-wa-float:focus-visible { outline: 2px solid var(--gcg-bone); outline-offset: 3px; }

/* Press: settle back down, as a real button would. */
.gcg-wa-float:active {
  transform: translateY(0) scale(.97);
  box-shadow: 0 2px 6px color-mix(in srgb, var(--gcg-ink) 30%, transparent);
  transition-duration: .08s;
}

@media (max-width: 600px) {
  /* Stays a circle on a phone - a pill this wide covers too much of the screen,
     and there is no hover to expand it anyway. */
  .gcg-wa-float,
  .gcg-wa-float:hover { right: 16px; bottom: 16px; height: 52px; min-width: 52px; padding: 0; }
  .gcg-wa-float-label,
  .gcg-wa-float:hover .gcg-wa-float-label { max-width: 0; margin-left: 0; opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .gcg-wa-float, .gcg-wa-float-label { transition: background .18s ease, color .18s ease; }
  .gcg-wa-float:hover, .gcg-wa-float:focus-visible, .gcg-wa-float:active { transform: none; }
  .gcg-wa-float:hover .gcg-wa-float-label,
  .gcg-wa-float:focus-visible .gcg-wa-float-label { max-width: 180px; margin-left: 10px; opacity: 1; }

  /* A ring pulsing forever is exactly what this setting is asking us not to do.
     The button keeps its own presence; it just stops moving. */
  .gcg-wa-float::before, .gcg-wa-float::after { animation: none; opacity: 0; }
}

@media print {
  .gcg-wa-float { display: none; }
}

.gcg-cta-split { display: flex; align-items: center; justify-content: space-between; gap: 24px 28px; flex-wrap: wrap; }
.gcg-cta-split h2 { font-size: clamp(1.35rem, 3vw, 1.6rem); margin: 0 0 8px; }
.gcg-cta-split p { margin: 0; color: var(--gcg-body); }

/* ==========================================================================
   The generated report cover
   ========================================================================== */

.gcg-cover {
  aspect-ratio: 3 / 4;
  color: var(--gcg-bone);
  padding: 22px;
  display: flex; flex-direction: column; justify-content: space-between;
  position: relative; overflow: hidden;

  /* Two stacked layers give the ground depth instead of flat black: a soft
     wash from the top-right, and the same fine dot grid the hero carries. */
  background-color: var(--gcg-ink);
  background-image:
    radial-gradient(115% 85% at 82% 6%, color-mix(in srgb, var(--gcg-accent-dk) 17%, transparent), transparent 60%),
    radial-gradient(circle at center, color-mix(in srgb, var(--gcg-bone) 9%, transparent) 1px, transparent 1px);
  background-size: 100% 100%, 17px 17px;
  background-repeat: no-repeat, repeat;
}
.gcg-cover::before {
  content: ""; position: absolute; top: 0; left: 22px; right: 22px;
  height: 2px; background: var(--gcg-accent-dk); z-index: 2;
}

/* ---- the ghosted motif -------------------------------------------------
   Each category carries a mark drawn from what it actually is. The default,
   used by the benchmarking and royalty studies, is a miniature arm's-length
   range plot: axis, interquartile band, median tick. That chart is GCG's most
   credible visual asset, so it is the right thing for a report cover to echo.
   ----------------------------------------------------------------------- */

/* Default, and what the benchmarking studies carry: a histogram of comparable
   margins over a baseline axis. A benchmarking set *is* a distribution, so the
   distribution is the honest mark for it.
   (The first attempt drew a box-and-whisker band instead. At card size the
   interquartile rectangle read as a grey smudge rather than a chart, which is
   why this is bars: thin verticals stay legible when small.) */
.gcg-cover::after {
  content: ""; position: absolute; z-index: 1; pointer-events: none;
  left: 11%; right: 11%; bottom: 20%; height: 16%;
  opacity: 0.5;
  background-repeat: no-repeat;
  /* Fading the edges keeps the motif reading as texture on the ground rather
     than a graphic pasted onto it. */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
  background-image:
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 30%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 30%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent));
  background-size:
    100% 1px,
    2px 22%, 2px 40%, 2px 61%, 2px 82%, 2px 97%,
    2px 86%, 2px 66%, 2px 44%, 2px 24%;
  background-position:
    0 100%,
    2% 100%, 14% 100%, 26% 100%, 38% 100%, 50% 100%,
    62% 100%, 74% 100%, 86% 100%, 98% 100%;
}

/* Royalties: a rising rate curve, stepped. */
.gcg-cover--royalties::after {
  left: 9%; right: 9%; bottom: 20%; height: 15%;
  background-image:
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 28%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 28%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent)),
    linear-gradient(color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent), color-mix(in srgb, var(--gcg-accent-dk) 42%, transparent));
  background-size: 100% 1px, 18% 1px, 18% 1px, 18% 1px, 18% 1px;
  background-position: 0 100%, 4% 74%, 28% 52%, 52% 30%, 76% 8%;
}

/* Below card size the motif is noise rather than texture. */
.gcg-cart-thumb .gcg-cover::after { content: none; }
.gcg-cover-cat { font-size: 0.6rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--gcg-accent-dk); margin: 12px 0 0; }
.gcg-cover-title { font-family: var(--gcg-serif); font-size: 1.22rem; line-height: 1.25; margin: 14px 0 0; }
.gcg-cover-meta { font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--gcg-secondary-dk); margin: 0; }

.gcg-cover-lg { padding: 28px; }
.gcg-cover-lg .gcg-cover-title { font-size: 1.5rem; }

/* ==========================================================================
   Product cards (shop loop)
   ========================================================================== */

.woocommerce ul.products,
.woocommerce-page ul.products {
  display: grid; gap: 24px; margin: 0; padding: 0; list-style: none;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.woocommerce ul.products.columns-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.woocommerce ul.products.columns-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* WooCommerce clearfixes ul.products with ::before/::after. In a grid container
   those become grid items and push the last products onto a phantom row. */
.woocommerce ul.products::before,
.woocommerce ul.products::after,
.woocommerce-page ul.products::before,
.woocommerce-page ul.products::after { content: none; display: none; }

.woocommerce ul.products li.product,
.woocommerce-page ul.products li.product {
  width: auto !important; margin: 0 !important; float: none !important;
  background: var(--gcg-white); border: 1px solid var(--gcg-line); border-radius: 2px;
  display: flex; flex-direction: column; min-width: 0;
  transition: border-color .15s ease, transform .15s ease;
}
.woocommerce ul.products li.product:hover { border-color: var(--gcg-accent-lt); transform: translateY(-2px); }
.woocommerce ul.products li.product::before,
.woocommerce ul.products li.product::after { content: none; }

.woocommerce ul.products li.product a.woocommerce-LoopProduct-link { text-decoration: none; color: inherit; display: block; }
.woocommerce ul.products li.product a:hover { color: inherit; }

.gcg-card-body { padding: 18px 20px 20px; display: flex; flex-direction: column; flex: 1; }
.gcg-card-cat { font-size: 0.64rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gcg-accent-lt); margin: 0; }
.woocommerce ul.products li.product .woocommerce-loop-product__title,
.gcg-card-title {
  font-family: var(--gcg-serif); font-size: 1.06rem; line-height: 1.3;
  margin: 8px 0 10px; padding: 0; font-weight: 400;
}
.gcg-card-meta { font-size: 0.78rem; color: var(--gcg-secondary); margin: 0 0 16px; }
.gcg-card-foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }

.woocommerce ul.products li.product .price,
.gcg-price {
  font-family: var(--gcg-serif); font-size: 1.2rem; color: var(--gcg-ink);
  font-variant-numeric: tabular-nums; margin: 0; font-weight: 400;
}
.woocommerce ul.products li.product .price del { color: var(--gcg-secondary); font-size: 0.9rem; margin-right: 6px; }
.woocommerce ul.products li.product .price ins { text-decoration: none; }
.gcg-card-cta { font-size: 0.78rem; font-weight: 600; color: var(--gcg-accent-lt); }

/* The loop add-to-cart button is noise on a report catalogue - the card links
   to the page, where the buy box does the work. */
.woocommerce ul.products li.product .button { display: none; }

.woocommerce span.onsale {
  background: var(--gcg-accent-dk); color: var(--gcg-ink); border-radius: 2px;
  font-family: var(--gcg-sans); font-size: 0.64rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; padding: 5px 10px;
  min-height: 0; min-width: 0; line-height: 1.2; top: 10px; left: 10px; right: auto; margin: 0;
}

/* ==========================================================================
   Shop archive
   ========================================================================== */

/* The banner on inner pages - same instruction as the hero, so same treatment. */
.gcg-shop-head { background: var(--gcg-tint); color: var(--gcg-ink); padding: 48px 0; }
.gcg-shop-head h1 { font-size: clamp(1.7rem, 3.6vw, 2.6rem); margin: 0; }
.gcg-shop-head .gcg-lede { margin-top: 14px; }

.gcg-shop-layout { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 40px; align-items: start; }
.gcg-shop-results { min-width: 0; }

.gcg-filters { border: 1px solid var(--gcg-line); background: var(--gcg-white); border-radius: 2px; position: sticky; top: 24px; }
.gcg-filters-details { padding: 22px; }
.gcg-filters-summary {
  display: none; cursor: pointer; list-style: none;
  font-size: 0.8rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--gcg-ink); align-items: center; gap: 10px;
}
.gcg-filters-summary::-webkit-details-marker { display: none; }
.gcg-filters-summary::after { content: "+"; font-size: 1.2rem; font-weight: 400; line-height: 1; margin-left: auto; }
.gcg-filters-details[open] .gcg-filters-summary::after { content: "\2212"; }
.gcg-filters-active {
  font-size: 0.6rem; letter-spacing: 0.12em; background: var(--gcg-accent-dk);
  color: var(--gcg-ink); border-radius: 2px; padding: 3px 7px;
}

.gcg-filter-group { margin-bottom: 24px; }
.gcg-filter-group:last-child { margin-bottom: 0; }
.gcg-filter-group h4 { font-family: var(--gcg-sans); font-size: 0.68rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gcg-accent-lt); margin: 0 0 12px; }
.gcg-filter-group ul { list-style: none; margin: 0; padding: 0; }
.gcg-filter-group li { margin-bottom: 8px; font-size: 0.86rem; }
.gcg-filter-group a { text-decoration: none; color: var(--gcg-body); }
.gcg-filter-group a:hover { color: var(--gcg-ink); }
.gcg-filter-group .gcg-active > a { color: var(--gcg-ink); font-weight: 600; }

/* --------------------------------------------------------------------------
   Long filter groups
   -------------------------------------------------------------------------- */

/* The button only appears once nav.js has hidden the overflow rows - it ships
   `hidden`, so a reader with no JavaScript sees the full list and no control
   that would not work. */
.gcg-filter-more {
  margin-top: 8px; padding: 0; border: 0; background: none; cursor: pointer;
  font-family: var(--gcg-sans); font-size: 0.74rem; font-weight: 600;
  letter-spacing: 0.04em; color: var(--gcg-ink);
  border-bottom: 1px solid var(--gcg-accent-lt); padding-bottom: 1px;
}
.gcg-filter-more:hover, .gcg-filter-more:focus { color: var(--gcg-accent-lt); }

.gcg-filter-count { color: var(--gcg-secondary); }
.gcg-filter-reset { font-size: 0.78rem; color: var(--gcg-accent-lt); text-decoration: none; border-bottom: 1px solid var(--gcg-accent-lt); }

/* --- the active-filter row ----------------------------------------------
   Above the results at every width. Below 900px the sidebar becomes a drawer,
   so this is the only place the reader can see what is narrowing the list, and
   the only way to undo it without reopening the drawer.
   ------------------------------------------------------------------------ */

.gcg-active-filters {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px 12px;
  margin-bottom: 22px; padding-bottom: 18px;
  border-bottom: 1px solid var(--gcg-line);
}
.gcg-active-filters-label {
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--gcg-secondary);
}
.gcg-chips { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: 0; padding: 0; }

.gcg-chip {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 6px 11px; border-radius: 2px;
  border: 1px solid var(--gcg-line); background: var(--gcg-white);
  font-size: 0.82rem; line-height: 1.3; text-decoration: none; color: var(--gcg-ink);
  transition: border-color .15s ease, background-color .15s ease;
}
.gcg-chip:hover, .gcg-chip:focus-visible {
  border-color: var(--gcg-ink); background: var(--gcg-bone); color: var(--gcg-ink);
}
/* The group name is what stops "TNMM" in Report type reading the same as
   "TNMM" in Method - both exist, and both can be on at once. */
.gcg-chip-group { font-size: 0.64rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--gcg-secondary); }
.gcg-chip-label { font-weight: 600; }
.gcg-chip-x { font-size: 0.72rem; color: var(--gcg-secondary); }
.gcg-chip:hover .gcg-chip-x { color: var(--gcg-ink); }

.gcg-chips-clear {
  font-size: 0.78rem; text-decoration: none; white-space: nowrap;
  color: var(--gcg-accent-lt); border-bottom: 1px solid var(--gcg-accent-lt);
}

/* --- order received: what happens next ------------------------------------
   WooCommerce's confirmation screen ends at the order summary, which is a dead
   end when the thing bought is a download sitting in an account the buyer may
   not know they have.
   ------------------------------------------------------------------------ */

/* --- the free-sample form -------------------------------------------------
   Opens under the button rather than in a modal: it lives in a narrow column
   where a dialog would need focus trapping and would cover the price on a
   phone. Inline keeps the context visible and needs none of that.
   ------------------------------------------------------------------------ */

.gcg-sample-form {
  margin-top: 12px; padding: 16px;
  background: var(--gcg-bone); border: 1px solid var(--gcg-line); border-radius: 2px;
}
.gcg-sample-note { font-size: 0.82rem; color: var(--gcg-secondary); margin: 0 0 14px; }
.gcg-sample-field { display: block; margin-bottom: 12px; }
.gcg-sample-field > span {
  display: block; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--gcg-secondary); margin-bottom: 6px;
}
.gcg-sample-field input {
  width: 100%; font-family: var(--gcg-sans); font-size: 0.9rem;
  padding: 10px 12px; border: 1px solid var(--gcg-line); border-radius: 2px;
  background: var(--gcg-white); color: var(--gcg-ink);
}
.gcg-sample-field input:focus-visible { outline: 2px solid var(--gcg-accent-lt); outline-offset: -1px; }
.gcg-sample-error {
  font-size: 0.82rem; color: #B3261E; margin: 0 0 12px;
}
.gcg-sample-privacy { font-size: 0.72rem; color: var(--gcg-secondary); margin: 12px 0 0; line-height: 1.5; }
.gcg-sample-privacy a { color: var(--gcg-accent-lt); text-decoration: underline; text-underline-offset: 2px; }
.gcg-sample-send[disabled] { opacity: 0.6; cursor: default; }

.gcg-order-next {
  margin-top: 40px; padding: 30px 32px;
  background: var(--gcg-tint); border-radius: 2px;
}
.gcg-order-next-title { font-size: 1.3rem; margin: 0 0 10px; }
.gcg-order-next-lede { font-size: 0.96rem; color: var(--gcg-body); margin: 0 0 22px; max-width: 62ch; }
.gcg-order-next-actions { display: flex; flex-wrap: wrap; gap: 12px; }
.gcg-order-next-note { font-size: 0.84rem; color: var(--gcg-secondary); margin: 20px 0 0; }

/* The tint band already separates this from the order table above it; a border
   on the outline button as well reads as two boxes. */
.gcg-order-next .gcg-btn-outline { border-color: var(--gcg-ink); }

.gcg-shop-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px 16px; margin-bottom: 26px; flex-wrap: wrap; }
.woocommerce .woocommerce-result-count { font-size: 0.86rem; color: var(--gcg-secondary); margin: 0; float: none; }
.woocommerce .woocommerce-ordering { margin: 0; float: none; }
.woocommerce .woocommerce-ordering select {
  font-family: var(--gcg-sans); font-size: 0.86rem; padding: 9px 12px; max-width: 100%;
  border: 1px solid var(--gcg-line); border-radius: 2px; background: var(--gcg-white); color: var(--gcg-ink);
}

.woocommerce nav.woocommerce-pagination { margin-top: 40px; text-align: left; }
.woocommerce nav.woocommerce-pagination ul { border: 0; display: flex; gap: 6px; flex-wrap: wrap; }
.woocommerce nav.woocommerce-pagination ul li { border: 0; margin: 0; }
.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
  border: 1px solid var(--gcg-line); border-radius: 2px; padding: 9px 15px;
  font-size: 0.84rem; background: var(--gcg-white); color: var(--gcg-ink);
}
.woocommerce nav.woocommerce-pagination ul li span.current,
.woocommerce nav.woocommerce-pagination ul li a:hover {
  background: var(--gcg-ink); color: var(--gcg-bone); border-color: var(--gcg-ink);
}

/* ==========================================================================
   Single product

   row 1   cover | title + specs | buy box
   row 2   description (spans cols 1-2) | buy box continues

   align-items:start is what lets the sticky columns travel inside their grid
   area; with the default stretch they would fill the row and never move.
   ========================================================================== */

.gcg-crumbs { font-size: 0.8rem; color: var(--gcg-secondary); padding: 20px 0; }
.gcg-crumbs a { text-decoration: none; }
.gcg-crumb-sep { margin: 0 8px; color: var(--gcg-line); }
.gcg-crumb-current { color: var(--gcg-body); }

.gcg-product-layout {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr) 300px;
  grid-template-areas:
    "cover specs buy"
    "desc  desc  buy";
  column-gap: 44px;
  row-gap: 0;
  align-items: start;
  padding-bottom: 72px;
}

/* The cover column stretches to the full height of row 1 and the sticky travel
   happens on the child inside it. Sticking the grid item itself would bound the
   travel to the grid container, not the row, and the cover would ride down over
   the description. The buy box does span both rows, so it sticks directly. */
.gcg-col-cover { grid-area: cover; align-self: stretch; }
.gcg-cover-sticky { position: sticky; top: 24px; }
.gcg-col-specs { grid-area: specs; min-width: 0; }
.gcg-col-buy   { grid-area: buy;   position: sticky; top: 24px; }
.gcg-col-desc  { grid-area: desc;  min-width: 0; padding-top: 40px; }

.gcg-col-specs h1 { font-size: clamp(1.5rem, 3.2vw, 2.35rem); margin: 0; }
.gcg-col-specs .gcg-lede { margin: 18px 0 26px; }

.gcg-tag-row { margin-bottom: 28px; }
.gcg-tag {
  display: inline-block; font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase;
  border: 1px solid var(--gcg-line); border-radius: 2px; padding: 4px 9px;
  color: var(--gcg-accent-lt); margin: 0 6px 6px 0; text-decoration: none;
}
.gcg-tag:hover { border-color: var(--gcg-accent-lt); color: var(--gcg-ink); }

.gcg-spec-wrap { overflow-x: auto; }
.gcg-spec-table { width: 100%; border-collapse: collapse; margin: 8px 0 0; font-size: 0.88rem; }
.gcg-spec-table th, .gcg-spec-table td { text-align: left; padding: 11px 0; vertical-align: top; }
.gcg-spec-table th { width: 38%; font-weight: 600; color: var(--gcg-secondary); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; padding-top: 14px; padding-right: 16px; }

/* Parent and WooCommerce table styling both fight the spec table. */
.gcg-spec-table,
.gcg-spec-table tbody,
.gcg-spec-table tr,
.gcg-spec-table th,
.gcg-spec-table td {
  background: transparent !important;
  border-left: 0; border-right: 0; border-top: 0;
}
.gcg-spec-table th, .gcg-spec-table td { border-bottom: 1px solid var(--gcg-line) !important; }

.gcg-prose h2, .gcg-split-main h2 { font-size: 1.4rem; margin: 34px 0 14px; }
.gcg-prose h2:first-child, .gcg-split-main h2:first-child { margin-top: 0; }
.gcg-prose h3, .gcg-split-main h3 { font-size: 1.15rem; margin: 24px 0 10px; }
.gcg-prose ul, .gcg-prose ol,
.gcg-split-main ul, .gcg-split-main ol { padding-left: 20px; margin: 0 0 18px; }
.gcg-prose li, .gcg-split-main li { margin-bottom: 8px; font-size: 0.94rem; }
.gcg-prose p, .gcg-split-main p { color: var(--gcg-body); margin: 0 0 1rem; }

.gcg-buybox { border: 1px solid var(--gcg-line); background: var(--gcg-white); border-radius: 2px; padding: 26px; }
.gcg-buybox .price,
.gcg-buybox .gcg-price { font-size: 2rem; display: block; margin: 0; }
.gcg-buybox .price del { font-size: 1.1rem; color: var(--gcg-secondary); }

/* WooCommerce paints the single-product price #958E09 - a mustard that hid
   inside the old warm palette and is glaring against silver. Its own selector
   is `.woocommerce:where(...) div.product span.price`; :where() contributes
   nothing, so that is (0,3,2) and this has to be heavier to win. */
.woocommerce div.product .gcg-buybox span.price { color: var(--gcg-ink); }
.woocommerce div.product .gcg-buybox span.price del { color: var(--gcg-secondary); }
.woocommerce div.product .gcg-buybox span.price ins { color: var(--gcg-ink); text-decoration: none; }
.gcg-buybox .price ins { text-decoration: none; }
.gcg-price-note { font-size: 0.78rem; color: var(--gcg-secondary); margin: 6px 0 20px; }
.gcg-buybox form.cart { margin: 0 0 10px; }
.gcg-buybox .quantity { display: none; }
.gcg-buybox button.single_add_to_cart_button {
  display: block; width: 100%; text-align: center;
  padding: 16px 32px; font-size: 0.94rem;
  background: var(--gcg-ink); color: var(--gcg-bone);
}
.gcg-buybox-list { list-style: none; padding: 18px 0 0; margin: 20px 0 0; border-top: 1px solid var(--gcg-line); }
.gcg-buybox-list li { font-size: 0.82rem; color: var(--gcg-body); margin-bottom: 9px; padding-left: 18px; position: relative; }
.gcg-buybox-list li::before { content: "\2014"; position: absolute; left: 0; color: var(--gcg-accent-lt); }
.gcg-refund-note { font-size: 0.78rem; color: var(--gcg-secondary); margin: 18px 0 0; line-height: 1.55; }

.gcg-related { background: var(--gcg-tint); padding: 76px 0; }
.gcg-related h2 { font-size: clamp(1.5rem, 3.4vw, 2.4rem); margin: 0 0 34px; }

/* ==========================================================================
   Cart / checkout / account
   ========================================================================== */

.woocommerce table.shop_table {
  border: 1px solid var(--gcg-line); border-radius: 2px; background: var(--gcg-white);
  border-collapse: collapse;
}
.woocommerce table.shop_table th {
  font-family: var(--gcg-sans); font-size: 0.7rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--gcg-secondary); font-weight: 600;
}
.woocommerce table.shop_table td, .woocommerce table.shop_table th { border-top: 1px solid var(--gcg-line); }
.woocommerce table.shop_table img { width: 48px; height: auto; }
.woocommerce .woocommerce-cart-form { overflow-x: auto; }

/* Every report is sold_individually, so the quantity column is always "1" and
   the Update cart button it exists to serve has nothing to update. Both are
   removed rather than left as dead controls. */
.woocommerce table.shop_table td.product-quantity,
.woocommerce table.shop_table th.product-quantity,
.woocommerce button[name="update_cart"],
.woocommerce input[name="update_cart"] { display: none !important; }

.woocommerce .actions .coupon { display: flex; gap: 10px; flex-wrap: wrap; float: none; }
.woocommerce .actions .coupon input#coupon_code { width: auto; flex: 1 1 160px; min-width: 0; }
.woocommerce td.actions { padding: 16px !important; }

.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.woocommerce-page form .form-row input.input-text,
.wpcf7 input[type="text"], .wpcf7 input[type="email"],
.wpcf7 input[type="tel"], .wpcf7 input[type="url"],
.wpcf7 textarea, .wpcf7 select {
  border: 1px solid var(--gcg-line); border-radius: 2px; padding: 11px 13px;
  font-family: var(--gcg-sans); font-size: 0.9rem; background: var(--gcg-white); color: var(--gcg-ink);
  width: 100%; max-width: 100%;
}
.woocommerce form.checkout_coupon, .woocommerce form.login, .woocommerce form.register {
  border: 1px solid var(--gcg-line); border-radius: 2px; background: var(--gcg-white);
}
.woocommerce-info, .woocommerce-message, .woocommerce-error {
  border-top-color: var(--gcg-accent-lt); background: var(--gcg-white);
  font-size: 0.9rem; border-radius: 2px;
}
.woocommerce-info::before, .woocommerce-message::before { color: var(--gcg-accent-lt); }
.woocommerce-info a, .woocommerce-message a { color: var(--gcg-accent-lt); }

/* The checkout template stacks billing above additional information in one
   column; WooCommerce's own two-up float is unset here. */
.woocommerce .woocommerce-checkout .col2-set { display: block; }
.woocommerce .woocommerce-checkout .col2-set .col-1,
.woocommerce .woocommerce-checkout .col2-set .col-2 { float: none; width: 100%; margin: 0; }
.woocommerce #order_review { overflow-x: auto; }

/* ==========================================================================
   Account area
   ========================================================================== */

.woocommerce-account .woocommerce-MyAccount-navigation {
  float: none; width: auto;
}
.woocommerce-account .woocommerce-MyAccount-content {
  float: none; width: auto;
}
/* The nav/content split only exists once signed in; signed out this wrapper
   holds the login and register forms instead. */
body.logged-in.woocommerce-account .gcg-shop-page > .woocommerce {
  display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 48px; align-items: start;
}
/* .woocommerce and .col2-set both carry a ::before/::after clearfix which, in a
   grid container, becomes two grid items and pushes real children out of their
   columns. */
body.logged-in.woocommerce-account .gcg-shop-page > .woocommerce::before,
body.logged-in.woocommerce-account .gcg-shop-page > .woocommerce::after,
.woocommerce-account .u-columns.col2-set::before,
.woocommerce-account .u-columns.col2-set::after { content: none; display: none; }

.woocommerce-account .woocommerce-MyAccount-navigation ul {
  list-style: none; padding: 0; margin: 0;
  border: 1px solid var(--gcg-line); border-radius: 2px; background: var(--gcg-white);
  position: sticky; top: 24px; overflow: hidden;
}
.woocommerce-account .woocommerce-MyAccount-navigation li { border-bottom: 1px solid var(--gcg-line); }
.woocommerce-account .woocommerce-MyAccount-navigation li:last-child { border-bottom: 0; }
.woocommerce-account .woocommerce-MyAccount-navigation li a {
  display: block; padding: 13px 18px; text-decoration: none; font-size: 0.88rem;
  color: var(--gcg-body); border-left: 2px solid transparent;
}
.woocommerce-account .woocommerce-MyAccount-navigation li a:hover { color: var(--gcg-ink); background: var(--gcg-bone); }
.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a {
  font-weight: 700; color: var(--gcg-ink);
  border-left-color: var(--gcg-accent-lt); background: var(--gcg-bone);
}

/* dashboard */
.gcg-account-intro { margin-bottom: 28px; }
.gcg-account-intro h2 { font-size: clamp(1.5rem, 3vw, 2rem); margin: 0 0 12px; }
.gcg-account-intro .gcg-lede { margin: 0; }

.gcg-account-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; margin-bottom: 28px; }
.gcg-stat {
  border: 1px solid var(--gcg-line); background: var(--gcg-white); border-radius: 2px;
  padding: 22px; text-decoration: none; color: inherit; display: block;
  transition: border-color .15s ease;
}
.gcg-stat:hover { border-color: var(--gcg-accent-lt); color: inherit; }
.gcg-stat-n { display: block; font-family: var(--gcg-serif); font-size: 2.2rem; line-height: 1; font-variant-numeric: tabular-nums; }
.gcg-stat-l { display: block; font-size: 0.76rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--gcg-accent-lt); margin-top: 8px; }

.gcg-account-actions { display: flex; gap: 12px; flex-wrap: wrap; margin: 0 0 32px; }
.gcg-account-count { font-size: 0.7rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gcg-accent-lt); margin: 0 0 18px; }

.gcg-account-empty {
  border: 1px solid var(--gcg-line); background: var(--gcg-white); border-radius: 2px;
  padding: 32px; text-align: center;
}
.gcg-account-empty p { max-width: 46ch; margin: 0 auto 18px; }

.gcg-account-note {
  border-top: 1px solid var(--gcg-line); padding-top: 20px; margin-top: 32px;
  font-size: 0.84rem; color: var(--gcg-secondary);
}
.gcg-account-note p { margin: 0 0 8px; color: inherit; }
.gcg-account-note p:last-child { margin-bottom: 0; }

/* the report library */
.gcg-library { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--gcg-line); }
.gcg-library-item {
  display: grid; grid-template-columns: 64px minmax(0, 1fr) auto;
  gap: 20px; align-items: start;
  padding: 20px 0; border-bottom: 1px solid var(--gcg-line);
}
.gcg-library-item::before, .gcg-library-item::after { content: none !important; }
.gcg-library-thumb img { display: block; width: 100%; height: auto; border: 1px solid var(--gcg-line); border-radius: 2px; }
.gcg-library-cat { font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gcg-accent-lt); margin: 0 0 6px; }
.gcg-library-name { font-family: var(--gcg-serif); font-size: 1.05rem; line-height: 1.3; margin: 0 0 6px; }
.gcg-library-name a { text-decoration: none; }
.gcg-library-meta { font-size: 0.8rem; color: var(--gcg-secondary); margin: 0 0 4px; }
.gcg-library-updated { font-size: 0.76rem; color: var(--gcg-secondary); margin: 0; }
.gcg-library-files { display: grid; gap: 8px; min-width: 200px; }
.gcg-library-file { padding: 10px 16px; font-size: 0.8rem; text-align: center; white-space: nowrap; }

/* login / register */
.woocommerce-account .u-columns.col2-set { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 40px; }
.woocommerce-account .u-columns .col-1,
.woocommerce-account .u-columns .col-2 { float: none; width: auto; }
.woocommerce-account h2 { font-size: 1.4rem; margin: 0 0 18px; }
.woocommerce form.login, .woocommerce form.register { padding: 26px; margin: 0; }

/* ==========================================================================
   The product page buy box

   Two states, both rendered by gcg_render_buy_action() in functions.php:
   "add", and "in your cart" with a remove control. assets/nav.js swaps the
   whole block after an AJAX change, so there is no state to keep in sync.
   ========================================================================== */

.gcg-buy-action { position: relative; }
.gcg-buy-action.is-busy { opacity: 0.6; cursor: progress; }

.gcg-in-cart-note {
  display: flex; align-items: center; gap: 8px;
  font-size: 0.76rem; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--gcg-accent-lt); margin: 0 0 12px;
}
.gcg-in-cart-note::before {
  content: ""; width: 15px; height: 15px; flex: 0 0 auto;
  border: 1px solid var(--gcg-accent-lt); border-radius: 50%;
  background: linear-gradient(var(--gcg-accent-lt), var(--gcg-accent-lt)) no-repeat center;
  background-size: 7px 7px; background-clip: content-box; padding: 3px;
}

/* A quiet text control, not a third button - three stacked buttons would give
   equal weight to "view", "remove" and "sample", which they do not have.
   Backgrounds are stated on every state, not just at rest: leaving hover
   undeclared lets the parent theme paint it (trap 10). */
.gcg-buy-remove {
  display: block; width: 100%; margin: 12px 0 0; padding: 4px 0;
  background: none; border: 0; cursor: pointer;
  font-family: var(--gcg-sans); font-size: 0.8rem; line-height: 1.4;
  color: var(--gcg-secondary); text-align: center;
  text-decoration: underline; text-decoration-thickness: 1px;
  text-underline-offset: 3px; text-decoration-color: transparent;
  transition: color .15s ease, text-decoration-color .15s ease;
}
.gcg-buy-remove:hover,
.gcg-buy-remove:focus-visible {
  background: none;
  color: var(--gcg-ink);
  text-decoration-color: var(--gcg-line);
}

.gcg-buy-error { font-size: 0.8rem; color: #9B3B2F; margin: 10px 0 0; }

/* The sample sits in its own group. Without this the outline button touches the
   dark one above it, and on hover - when the outline fills with ink - the two
   merge into a single block. */
.gcg-buy-sample { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--gcg-line); }

/* ==========================================================================
   Cart page
   ========================================================================== */

.gcg-shop-page { width: 100%; }

.gcg-cart-layout,
.gcg-checkout-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 48px;
  align-items: start;
}

.gcg-summary-box {
  border: 1px solid var(--gcg-line); background: var(--gcg-white);
  border-radius: 2px; padding: 26px; position: sticky; top: 24px;
}

.gcg-cart-heading {
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--gcg-accent-lt); margin: 0 0 18px;
}

.gcg-cart-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--gcg-line); }
.gcg-cart-item {
  display: grid; grid-template-columns: 72px minmax(0, 1fr) auto;
  gap: 22px; align-items: start;
  padding: 22px 0; border-bottom: 1px solid var(--gcg-line);
}
.gcg-cart-thumb a { display: block; }
.gcg-cart-thumb img {
  display: block; width: 100%; height: auto; border-radius: 2px;
  border: 1px solid var(--gcg-line);
}

.gcg-cart-cat { font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--gcg-accent-lt); margin: 0 0 6px; }
.gcg-cart-name { font-family: var(--gcg-serif); font-size: 1.08rem; line-height: 1.3; margin: 0 0 6px; }
.gcg-cart-name a { text-decoration: none; }
.gcg-cart-meta { font-size: 0.8rem; color: var(--gcg-secondary); margin: 0 0 10px; }
/* WooCommerce ships a.remove as a big red glyph with !important on the colour,
   which is why these need the same weight to win. */
.woocommerce a.gcg-cart-remove,
.woocommerce a.gcg-cart-remove:hover {
  display: inline; width: auto; height: auto; border-radius: 0;
  font-size: 0.78rem; line-height: inherit; text-align: left;
  background: transparent !important; text-decoration: none;
  border-bottom: 1px solid var(--gcg-line);
  color: var(--gcg-secondary) !important;
}
.woocommerce a.gcg-cart-remove:hover { color: var(--gcg-ink) !important; border-color: var(--gcg-ink); }

.gcg-cart-price { font-family: var(--gcg-serif); font-size: 1.2rem; white-space: nowrap; font-variant-numeric: tabular-nums; }

.gcg-cart-coupon { margin-top: 26px; }
.gcg-cart-coupon label { display: block; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--gcg-accent-lt); margin-bottom: 10px; }
.gcg-cart-coupon-row { display: flex; gap: 10px; flex-wrap: wrap; }
.gcg-cart-coupon-row input {
  flex: 1 1 180px; min-width: 0;
  border: 1px solid var(--gcg-line); border-radius: 2px; padding: 11px 13px;
  font-family: var(--gcg-sans); font-size: 0.9rem; background: var(--gcg-white); color: var(--gcg-ink);
}
.gcg-cart-continue { display: inline-block; margin-top: 26px; font-size: 0.84rem; color: var(--gcg-accent-lt); text-decoration: none; border-bottom: 1px solid var(--gcg-accent-lt); }

/* WooCommerce's own totals block, restyled inside our summary box.
   It ships as float:right at 48% width, which inside a 360px box leaves the
   totals squeezed into 147px against the right edge. */
.woocommerce .cart-collaterals,
.woocommerce-page .cart-collaterals { width: 100%; }
.woocommerce .cart-collaterals .cart_totals,
.woocommerce-page .cart-collaterals .cart_totals,
.gcg-summary-box .cart_totals {
  float: none; width: 100%; margin: 0; padding: 0;
}
.gcg-summary-box .cart_totals h2 { font-size: 1.15rem; margin: 0 0 16px; }
.gcg-summary-box .cart_totals table.shop_table { border: 0; background: transparent; margin: 0; }
.gcg-summary-box .cart_totals table.shop_table th,
.gcg-summary-box .cart_totals table.shop_table td {
  border-top: 0; border-bottom: 1px solid var(--gcg-line);
  padding: 12px 0; font-size: 0.9rem; background: transparent;
}
.gcg-summary-box .cart_totals table.shop_table th { text-transform: uppercase; font-size: 0.68rem; letter-spacing: 0.12em; color: var(--gcg-secondary); width: 50%; }
.gcg-summary-box .cart_totals table.shop_table td { text-align: right; font-variant-numeric: tabular-nums; }
.gcg-summary-box .cart_totals tr.order-total td { font-family: var(--gcg-serif); font-size: 1.5rem; padding-top: 14px; }
.gcg-summary-box .cart_totals tr.order-total th { vertical-align: middle; padding-top: 14px; }
.gcg-summary-box .wc-proceed-to-checkout { padding: 20px 0 0; }
.gcg-summary-box .wc-proceed-to-checkout a.checkout-button {
  display: block; width: 100%; text-align: center; margin: 0;
  padding: 16px 18px; font-size: 0.94rem;
  background: var(--gcg-ink); color: var(--gcg-bone);
}
.gcg-summary-box .gcg-buybox-list { margin-top: 18px; }

/* ==========================================================================
   Checkout page
   ========================================================================== */

.gcg-checkout-fields .col2-set { display: block; }
.gcg-checkout-fields .col-1,
.gcg-checkout-fields .col-2 { width: 100%; float: none; }
.gcg-checkout-fields h3 { font-size: 1.2rem; margin: 0 0 18px; }
.gcg-checkout-fields .col-2 h3 { margin-top: 34px; }
.woocommerce form .form-row { padding: 0; margin: 0 0 16px; }
.woocommerce form .form-row label { font-size: 0.76rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--gcg-accent-lt); margin-bottom: 7px; display: block; }
.woocommerce form .form-row .required { color: var(--gcg-accent-lt); text-decoration: none; }

.gcg-checkout-review h3#order_review_heading { font-size: 1.15rem; margin: 0 0 16px; }
.gcg-checkout-review table.shop_table { border: 0; background: transparent; margin: 0; }
.gcg-checkout-review table.shop_table th,
.gcg-checkout-review table.shop_table td {
  border-top: 0; border-bottom: 1px solid var(--gcg-line);
  padding: 12px 0; font-size: 0.9rem; background: transparent;
}
.gcg-checkout-review table.shop_table thead th { font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--gcg-secondary); }
.gcg-checkout-review tr.order-total td { font-family: var(--gcg-serif); font-size: 1.5rem; }
.gcg-checkout-review .product-name { line-height: 1.35; padding-right: 16px; }
.gcg-checkout-review table.shop_table { border-collapse: collapse; }
.gcg-checkout-review table.shop_table td,
.gcg-checkout-review table.shop_table th { border-left: 0; border-right: 0; }
.gcg-checkout-review table.shop_table td.product-total,
.gcg-checkout-review table.shop_table tfoot td { text-align: right; font-variant-numeric: tabular-nums; }
.gcg-checkout-review table.shop_table tfoot th { font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--gcg-secondary); font-weight: 600; }
/* Quantity is always one on this store. */
.gcg-checkout-review .product-quantity { display: none; }

.woocommerce-checkout #payment { background: transparent; border-radius: 0; }
.woocommerce-checkout #payment ul.payment_methods { border-bottom: 1px solid var(--gcg-line); padding: 18px 0; margin: 0; }
.woocommerce-checkout #payment ul.payment_methods li { list-style: none; }
.woocommerce-checkout #payment ul.payment_methods label { font-size: 0.9rem; text-transform: none; letter-spacing: 0; color: var(--gcg-ink); font-weight: 600; display: inline; }
.woocommerce-checkout #payment div.payment_box {
  background: var(--gcg-bone); color: var(--gcg-body); font-size: 0.84rem;
  border-radius: 2px; margin-top: 10px;
}
.woocommerce-checkout #payment div.payment_box::before { border-bottom-color: var(--gcg-bone); }
.woocommerce-checkout #payment div.form-row.place-order { padding: 20px 0 0; margin: 0; }
.woocommerce-checkout #payment #place_order {
  display: block; width: 100%; float: none; text-align: center;
  padding: 16px 32px; font-size: 0.94rem;
  background: var(--gcg-ink); color: var(--gcg-bone);
}
.woocommerce-privacy-policy-text { font-size: 0.78rem; color: var(--gcg-secondary); }
.woocommerce-privacy-policy-text p { margin: 0 0 10px; }
.gcg-checkout-assurance { font-size: 0.78rem; color: var(--gcg-secondary); margin: 18px 0 0; line-height: 1.55; }

/* Login / coupon prompts above the form. */
.woocommerce-form-login-toggle, .woocommerce-form-coupon-toggle { margin-bottom: 24px; }
.woocommerce form.login, .woocommerce form.checkout_coupon { padding: 22px; margin: 0 0 24px; }

/* ==========================================================================
   Content pages
   ========================================================================== */

.gcg-page-head { background: var(--gcg-tint); color: var(--gcg-ink); padding: 48px 0; margin-bottom: 48px; }
.gcg-page-head h1 { font-size: clamp(1.7rem, 3.6vw, 2.6rem); margin: 0; }
.gcg-page-body { padding-bottom: 76px; }
.gcg-page-body .gcg-prose { max-width: 68ch; }

/* --- content-page layout components --------------------------------------
   Three blocks a page can opt into from its own content. page.php widens the
   container when it finds one, so none of them has to fight the 68ch column.
   ------------------------------------------------------------------------ */

/* Two columns: the argument on the left, the thing to fill in on the right.
   The aside sticks, so the form stays reachable while the reader works down a
   long page. */
.gcg-split {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 400px);
  gap: 56px; align-items: start;
}
.gcg-split-main { min-width: 0; max-width: 62ch; }
.gcg-split-main > *:first-child { margin-top: 0; }
.gcg-split-aside { min-width: 0; position: sticky; top: 28px; }

/* The form card. Ink border rather than a fill, so it reads as a panel on the
   page rather than a second background competing with the band above it. */
.gcg-form-card {
  background: var(--gcg-white); border: 1px solid var(--gcg-line);
  border-radius: 2px; padding: 28px;
}
.gcg-form-card > h2,
.gcg-form-card > h3 { margin-top: 0; font-size: 1.3rem; }
.gcg-form-card .gcg-form-note { font-size: 0.86rem; color: var(--gcg-secondary); margin: 0 0 20px; }

/* --- the steps flow ------------------------------------------------------
   An ordered list, numbered by CSS counter rather than by hand: the markup
   carries no digits, so a step cannot be inserted in the middle and leave the
   numbering wrong. The connector is a single line behind the row, masked at
   both ends, not a border per item - a border would stop short at the last
   numeral and look like a mistake.
   ------------------------------------------------------------------------ */

.gcg-steps-flow {
  list-style: none; margin: 44px 0 0; padding-left: 0;
  counter-reset: gcg-step;
  /* auto-fit rather than repeat(3). The run is written by hand in the page
     editor, so the number of cells changes when the client adds or drops one -
     it has already gone from three to two. Empty tracks collapse and hand their
     share back, so whatever the count is, the cells divide the row evenly and
     no dead column is left at the end of the line. */
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 32px;
  position: relative;
}
.gcg-steps-flow::before {
  content: ""; position: absolute; z-index: 0;
  left: 0; right: 0; top: 27px; height: 1px;
  background: var(--gcg-line);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}
.gcg-steps-flow > li { position: relative; z-index: 1; counter-increment: gcg-step; padding-top: 0; }
.gcg-steps-flow > li::before {
  content: counter(gcg-step, decimal-leading-zero);
  display: grid; place-items: center;
  width: 54px; height: 54px; margin-bottom: 22px;
  border: 1px solid var(--gcg-line); border-radius: 50%;
  background: var(--gcg-white);
  font-family: var(--gcg-serif); font-size: 1.15rem; color: var(--gcg-accent-lt);
}
.gcg-steps-flow h2,
.gcg-steps-flow h3 { font-size: 1.25rem; margin: 0 0 10px; }
.gcg-steps-flow p { margin: 0; font-size: 0.94rem; color: var(--gcg-body); max-width: 46ch; }
.gcg-steps-flow p + p { margin-top: 10px; }

/* The last cell in the run is not a step, it is where the run leads: the
   catalogue. It takes no number - a numeral would make it read as a third
   thing to do - and it caps the connector rule with a solid node so the line
   terminates in something rather than trailing off the row. The arrow is set
   in content, not as an SVG, to keep this stylesheet free of url() and of
   hard-coded colour; every browser's fallback stack carries U+2192. */
.gcg-steps-flow > .gcg-steps-end { counter-increment: none; }
.gcg-steps-flow > .gcg-steps-end::before {
  content: "\2192";
  background: var(--gcg-ink); border-color: var(--gcg-ink);
  color: var(--gcg-white);
  font-family: var(--gcg-sans); font-size: 1.3rem; line-height: 1;
}
/* justify-self is inert on the desktop cell, which is block flow. It matters
   at <=900px, where the cell becomes a grid and would otherwise blockify the
   button to the full column width. */
.gcg-steps-flow > .gcg-steps-end .gcg-btn { margin-top: 18px; justify-self: start; }

/* --- the contact channels card ------------------------------------------- */

.gcg-channels {
  background: var(--gcg-white); border: 1px solid var(--gcg-line);
  border-radius: 2px; padding: 26px;
}
.gcg-channels-title { font-size: 1.15rem; margin: 0 0 6px; }
.gcg-channels-reply { font-size: 0.88rem; color: var(--gcg-secondary); margin: 0 0 20px; }

.gcg-channel {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 0; border-top: 1px solid var(--gcg-line);
  text-decoration: none; color: var(--gcg-ink);
}
.gcg-channel:hover { color: var(--gcg-ink); }
.gcg-channel:hover .gcg-channel-value { color: var(--gcg-ink); }
.gcg-channel svg { flex: 0 0 auto; margin-top: 2px; }
.gcg-channel-label { display: block; font-size: 0.92rem; font-weight: 600; }
.gcg-channel-value {
  display: block; font-size: 0.84rem; color: var(--gcg-secondary);
  margin-top: 2px; overflow-wrap: anywhere;
}
/* WhatsApp is the one the client wants used, so it gets the accent. The green
   is deliberately not used - see the note on the floating button. */
.gcg-channel-wa .gcg-channel-label { color: var(--gcg-accent-lt); }
.gcg-channels-hours {
  font-size: 0.78rem; color: var(--gcg-secondary); margin: 16px 0 0;
  padding-top: 14px; border-top: 1px solid var(--gcg-line);
}

/* --- closing callout ------------------------------------------------------ */

.gcg-callout {
  margin-top: 56px; padding: 30px 32px;
  background: var(--gcg-tint); border-radius: 2px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 18px 32px; flex-wrap: wrap;
}
.gcg-callout > div { min-width: 0; }
.gcg-callout h2,
.gcg-callout h3 { margin: 0 0 6px; font-size: 1.25rem; }
.gcg-callout p { margin: 0; font-size: 0.92rem; color: var(--gcg-body); max-width: 60ch; }
.gcg-callout .gcg-btn { flex: 0 0 auto; }

@media (max-width: 900px) {
  .gcg-split { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  /* Sticky in a single column pins the form over the copy as you scroll. */
  .gcg-split-aside { position: static; }
  .gcg-steps-flow { grid-template-columns: minmax(0, 1fr); gap: 0; }
  /* Vertical run: the connector becomes a rule down the left of the numerals. */
  .gcg-steps-flow::before {
    left: 27px; right: auto; top: 0; bottom: 0; width: 1px; height: auto;
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 6%, #000 94%, transparent);
            mask-image: linear-gradient(to bottom, transparent, #000 6%, #000 94%, transparent);
  }
  .gcg-steps-flow > li { display: grid; grid-template-columns: 54px minmax(0, 1fr); gap: 0 20px; padding-bottom: 30px; }
  .gcg-steps-flow > li::before { margin-bottom: 0; grid-row: span 2; }
  .gcg-steps-flow > li > :last-child { grid-column: 2; }
  .gcg-steps-flow h2,
  .gcg-steps-flow h3 { grid-column: 2; align-self: center; }
}

/* ==========================================================================
   Contact Form 7
   ========================================================================== */

.wpcf7 { margin-top: 28px; max-width: 640px; }
.gcg-form-row { margin: 0 0 18px; }
.gcg-form-row label { display: block; font-size: 0.8rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--gcg-accent-lt); }
.gcg-form-row input, .gcg-form-row textarea, .gcg-form-row select { margin-top: 8px; }
.gcg-req { color: var(--gcg-accent-lt); }
.gcg-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 20px; }
.gcg-form-actions { margin: 26px 0 0; }
.wpcf7 .wpcf7-spinner { margin: 0 0 0 12px; }
.wpcf7 form .wpcf7-response-output {
  border-width: 1px; border-color: var(--gcg-line); border-radius: 2px;
  background: var(--gcg-white); font-size: 0.88rem; margin: 20px 0 0; padding: 14px 16px;
}
.wpcf7 form.sent .wpcf7-response-output { border-color: var(--gcg-accent-lt); }
.wpcf7-not-valid-tip { font-size: 0.78rem; color: #9B3B2F; text-transform: none; letter-spacing: 0; font-weight: 500; }
.wpcf7 input.wpcf7-not-valid, .wpcf7 textarea.wpcf7-not-valid, .wpcf7 select.wpcf7-not-valid { border-color: #9B3B2F; }

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
  /* The glows stay as static colour; only the drift stops. */
  .gcg-hero-glow { opacity: 0.38; }
}

/* --- cart and checkout stack below the desktop range ------------------- */
@media (max-width: 1080px) {
  .gcg-cart-layout,
  .gcg-checkout-layout { grid-template-columns: minmax(0, 1fr) 320px; gap: 32px; }
}
@media (max-width: 900px) {
  .gcg-cart-layout,
  .gcg-checkout-layout { grid-template-columns: minmax(0, 1fr); gap: 36px; }
  .gcg-summary-box { position: static; }

  body.logged-in.woocommerce-account .gcg-shop-page > .woocommerce { grid-template-columns: minmax(0, 1fr); gap: 28px; }
  .woocommerce-account .woocommerce-MyAccount-navigation ul { position: static; }
  .woocommerce-account .u-columns.col2-set { grid-template-columns: minmax(0, 1fr); gap: 28px; }
}

@media (max-width: 700px) {
  .gcg-library-item { grid-template-columns: 56px minmax(0, 1fr); gap: 16px; }
  .gcg-library-files { grid-column: 1 / -1; min-width: 0; grid-auto-flow: column; }
  .gcg-account-stats { grid-template-columns: minmax(0, 1fr); }
}

/* --- 1200 and below: pull the product side columns in ------------------- */
@media (max-width: 1200px) {
  .gcg-product-layout { grid-template-columns: 280px minmax(0, 1fr) 270px; column-gap: 32px; }
  .gcg-cover-lg { padding: 22px; }
  .gcg-cover-lg .gcg-cover-title { font-size: 1.3rem; }
}

/* --- 1024 and below: buy box moves under the specs ---------------------- */
@media (max-width: 1024px) {
  .gcg-product-layout {
    grid-template-columns: 260px minmax(0, 1fr);
    grid-template-areas:
      "cover specs"
      "buy   buy"
      "desc  desc";
    row-gap: 40px;
  }
  .gcg-col-buy { position: static; }
  .gcg-buybox { max-width: 420px; }
  .gcg-col-desc { padding-top: 0; }
  .woocommerce ul.products.columns-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .gcg-cat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- 980 and below: shop filters collapse above the results ------------- */
@media (max-width: 980px) {
  .gcg-shop-layout { grid-template-columns: 1fr; gap: 24px; }
  .gcg-filters { position: static; }
  .gcg-filters-summary { display: flex; }
  .gcg-filters-details[open] .gcg-filters-body { margin-top: 22px; padding-top: 22px; border-top: 1px solid var(--gcg-line); }
  .gcg-filter-group { columns: 2; column-gap: 24px; }
  .gcg-filter-group h4 { column-span: all; }
  .woocommerce ul.products.columns-3,
  .woocommerce ul.products.columns-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gcg-footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .woocommerce .woocommerce-checkout .col2-set { grid-template-columns: 1fr; gap: 0; }
}

/* --- 900 and below: mobile navigation ---------------------------------- */
@media (max-width: 900px) {
  .gcg-header-inner { min-height: 68px; }
  .gcg-nav-toggle { display: inline-flex; }
  .gcg-nav {
    order: 4; flex-basis: 100%; display: none;
    border-top: 1px solid var(--gcg-ink-line); padding: 6px 0 14px;
  }
  .gcg-nav.is-open { display: block; }
  .gcg-nav ul { flex-direction: column; align-items: stretch; gap: 0; }
  .gcg-nav li { border-bottom: 1px solid var(--gcg-ink-line); }
  .gcg-nav li:last-child { border-bottom: 0; }
  .gcg-nav a { display: block; padding: 14px 2px; font-size: 0.95rem; }

  /* No dropdown on a touch panel - the methods are simply listed under
     Benchmarking, indented and always visible. Three extra rows is cheaper than
     a tap-to-expand control that a thumb has to find. */
  .gcg-nav .sub-menu { padding: 0 0 6px; }
  .gcg-nav .sub-menu li { border-bottom: 0; }
  .gcg-nav .sub-menu a { padding: 10px 2px 10px 18px; font-size: 0.88rem; color: var(--gcg-secondary-dk); }
  .gcg-nav .sub-menu a:hover, .gcg-nav .sub-menu a:focus { color: var(--gcg-bone); }

  .gcg-band { padding: 60px 0; }
  .gcg-related { padding: 60px 0; }
  .gcg-hero { padding: 68px 0 60px; }
  .gcg-steps { grid-template-columns: 1fr; gap: 28px; }
  .gcg-cols-3 { grid-template-columns: 1fr; gap: 28px; }
}

/* --- 780 and below: product page stacks fully -------------------------- */
@media (max-width: 780px) {
  .gcg-product-layout {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "cover" "specs" "buy" "desc";
    row-gap: 32px;
    padding-bottom: 56px;
  }
  .gcg-col-cover { max-width: 260px; }
  .gcg-cover-sticky { position: static; }
  .gcg-buybox { max-width: none; }
  .gcg-crumbs { font-size: 0.75rem; }
  .gcg-crumb-current { display: none; }
}

/* --- 600 and below: single column everywhere --------------------------- */
@media (max-width: 600px) {
  :root { --gcg-gutter: 18px; }

  body { font-size: 15px; }

  /* Two cards across, not one.
     A single full-width card made the 3:4 cover about 470px tall on a phone -
     one report filled the screen and the catalogue became a scroll. Two-up
     halves the cover and lets a reader compare without scrolling.
     Everything inside the card steps down to suit the narrower column. */
  .woocommerce ul.products,
  .woocommerce ul.products.columns-3,
  .woocommerce ul.products.columns-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }

  .gcg-cover { padding: 13px; }
  .gcg-cover-cat { font-size: 0.5rem; letter-spacing: 0.13em; margin-top: 8px; }
  .gcg-cover-title { font-size: 0.92rem; line-height: 1.22; margin-top: 9px; }
  .gcg-cover-meta { font-size: 0.53rem; letter-spacing: 0.05em; }

  .gcg-card-body { padding: 12px 12px 14px; }
  .gcg-card-cat { font-size: 0.55rem; letter-spacing: 0.12em; }
  .woocommerce ul.products li.product .woocommerce-loop-product__title,
  .gcg-card-title { font-size: 0.9rem; margin: 6px 0 7px; }

  /* The spec line runs to four facts. Unbounded it wraps to five lines in a
     column this narrow and drives the card height; two lines is enough of a
     taste, and the full set is on the report's own page. */
  .gcg-card-meta {
    font-size: 0.68rem; margin-bottom: 10px;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
  }

  .gcg-card-foot { gap: 4px 10px; }
  .woocommerce ul.products li.product .price,
  .gcg-price { font-size: 1rem; }
  .gcg-card-cta { font-size: 0.68rem; }

  .gcg-cat-grid { grid-template-columns: 1fr; }
  .gcg-footer-grid { grid-template-columns: 1fr; gap: 28px; }
  .gcg-footer-bottom { flex-direction: column; gap: 10px; }

  .gcg-band { padding: 48px 0; }
  .gcg-band-tight { padding: 36px 0; }
  .gcg-related { padding: 48px 0; }
  .gcg-hero { padding: 52px 0 48px; }
  .gcg-shop-head, .gcg-page-head { padding: 36px 0; }
  .gcg-page-head { margin-bottom: 32px; }

  .gcg-hero-actions .gcg-btn { flex: 1 1 100%; text-align: center; }
  .gcg-btn-lg { padding: 14px 24px; }

  .gcg-form-grid { grid-template-columns: 1fr; }

  /* A two-line spec row reads better than a squeezed two-column one. */
  .gcg-spec-table, .gcg-spec-table tbody, .gcg-spec-table tr,
  .gcg-spec-table th, .gcg-spec-table td { display: block; width: auto; }
  .gcg-spec-table th { padding: 14px 0 0; border-bottom: 0 !important; }
  .gcg-spec-table td { padding: 4px 0 12px; }

  .gcg-filter-group { columns: 1; }

  .gcg-cart-label { display: none; }
  .gcg-cart { padding: 8px 11px; }


  .gcg-cart-item { grid-template-columns: 56px minmax(0, 1fr); gap: 16px; }
  .gcg-cart-price { grid-column: 2; margin-top: 4px; }
  .gcg-summary-box { padding: 20px; }
  .gcg-hero-glow { filter: blur(50px); }
}

/* --- 380 and below ----------------------------------------------------- */
@media (max-width: 380px) {
  /* The mark shrinks with the wordmark so the lockup keeps its proportion. */
  .gcg-logo { gap: 8px; }
  .gcg-logo-glyph { width: 27px; height: 27px; }
  .gcg-logo-name { font-size: 1.25rem; }
  .gcg-logo-tag { font-size: 0.41rem; letter-spacing: 0.11em; }
  .gcg-cover-lg .gcg-cover-title { font-size: 1.15rem; }
}

/* ==========================================================================
   Mobile bottom bar + drawers
   ==========================================================================
   Below 900px the site gets an app-style tab bar. The first slot opens a
   drawer: the filters on an archive, the navigation everywhere else. Both
   drawers are the same mechanism - the panel is already in the page, and these
   rules simply re-home it as a fixed sliding sheet rather than moving any DOM
   about, which would have to be undone on every resize.

   THIS BLOCK MUST STAY LAST IN THE FILE. It re-declares .gcg-nav, which the
   mobile navigation rules above also set at this same breakpoint and the same
   specificity - order is the only thing deciding it. Move this up and the nav
   goes back to being a panel under the header.
   ========================================================================== */

.gcg-tabbar { display: none; }
.gcg-scrim { display: none; }

/* nav.js injects a heading and close button into both panels on every page
   load, drawer widths or not. Above the breakpoint those panels are an ordinary
   header nav and an ordinary sidebar, where a "Menu ✕" row is nonsense - so the
   head is hidden by default and only shown as flex inside the media query
   below. Without this base rule it renders as a plain block on desktop. */
.gcg-drawer-head { display: none; }

@media (max-width: 900px) {

  .gcg-tabbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    background: var(--gcg-ink);
    /* Declare the text colour, do not just let the tabs set their own. The base
       button reset (trap 10) neutralises the parent theme with
       `button:focus { color: inherit }` at (0,1,1), which outranks `.gcg-tab`
       at (0,1,0) - so a focused tab takes whatever this bar inherits. Without
       this line that is the body's ink: dark text on a dark bar, invisible,
       and it showed the moment a drawer was closed with Escape. */
    color: var(--gcg-on-dark);
    border-top: 1px solid var(--gcg-ink-line);
    /* Clears the iOS home indicator without leaving a gap on anything else. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
    box-shadow: 0 -8px 24px color-mix(in srgb, var(--gcg-ink) 22%, transparent);
  }

  .gcg-tab {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 4px; padding: 9px 4px 8px; min-height: 56px;
    background: none; border: 0; cursor: pointer;
    color: var(--gcg-on-dark); text-decoration: none;
    font-family: var(--gcg-sans); font-size: 0.62rem; letter-spacing: 0.06em;
    transition: color .15s ease, background .15s ease;
  }
  /* The filled "active" look is driven by state only - the tab whose drawer is
     open, or the tab for the page you are on.

     :focus-visible is deliberately NOT in this list. Closing a drawer returns
     focus to the tab that opened it, and a programmatic focus() on a button
     counts as focus-visible - so including it here left the icon stuck in its
     active colour after the drawer had closed. Focus gets a ring instead. */
  .gcg-tab:hover, .gcg-tab.is-current, .gcg-tab[aria-expanded="true"] {
    color: var(--gcg-bone); background: color-mix(in srgb, var(--gcg-accent-dk) 9%, transparent);
  }
  .gcg-tab:focus-visible { outline: 2px solid var(--gcg-accent-dk); outline-offset: -2px; }
  .gcg-tab-icon, .gcg-tab .gcg-wa-icon { width: 22px; height: 22px; }
  .gcg-tab-label { line-height: 1; }

  .gcg-tab-icon-wrap { position: relative; display: inline-flex; }
  .gcg-tab-count {
    position: absolute; top: -5px; right: -9px;
    min-width: 17px; height: 17px; padding: 0 4px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 999px;
    background: var(--gcg-accent-dk); color: var(--gcg-ink);
    font-size: 0.6rem; font-weight: 700; line-height: 1;
  }
  .gcg-tab-count.is-empty { display: none; }

  /* The bar floats over the page, so the page needs room to end above it. */
  body { padding-bottom: calc(56px + env(safe-area-inset-bottom, 0px)); }

  /* The floating button would land on top of the bar, and WhatsApp already has
     a slot in it. One home per breakpoint. */
  .gcg-wa-float { display: none; }

  /* ---------------------------------------------------------- the scrim */
  /* Opacity and pointer-events only. No `visibility` and no `hidden`
     attribute: both gate interaction in ways that fought the transition, and
     this is a decorative overlay - aria-hidden keeps it out of the reading
     order without needing either. */
  .gcg-scrim {
    position: fixed; inset: 0; z-index: 95;
    display: block;
    background: color-mix(in srgb, var(--gcg-ink) 55%, transparent);
    opacity: 0; pointer-events: none;
    transition: opacity .22s ease;
  }
  body.gcg-drawer-open .gcg-scrim { opacity: 1; pointer-events: auto; }

  /* -------------------------------------------------------- the drawers */
  .gcg-nav,
  .gcg-filters {
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 96;
    width: min(86vw, 340px);
    margin: 0; padding: 20px 20px calc(24px + env(safe-area-inset-bottom, 0px));
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    transform: translateX(-100%);
    /* Off-screen alone would leave the closed panel focusable and readable by a
       screen reader. That is handled by the `inert` attribute, which nav.js
       toggles - NOT by `visibility` here.

       visibility was tried first and does not work for this: it gates focus, so
       a panel opened and focused in the same tick is still measured as hidden
       and the browser silently refuses the focus. inert has no such coupling,
       and it takes the panel out of the tab order and the accessibility tree in
       one attribute. */
    transition: transform .26s cubic-bezier(.2, .7, .3, 1), box-shadow .26s ease;

    /* No shadow at rest, and this is not a style preference.

       The panel is pinned to left: 0 and parked off-screen with a transform, so
       at rest it occupies x = -width .. 0. A shadow cast 12px to the RIGHT with
       a 40px blur therefore lands entirely ON the visible page - about 50px of
       permanent grey gradient down the left edge of every mobile screen, with
       the drawer shut. A transform moves the box, not what it casts.

       Only the open panel gets one. */
    box-shadow: none;
  }
  .gcg-nav { display: block; background: var(--gcg-ink); border-top: 0; }
  .gcg-filters { background: var(--gcg-white); }

  .gcg-nav.is-open,
  .gcg-filters.is-open {
    transform: translateX(0);
    box-shadow: 12px 0 40px color-mix(in srgb, var(--gcg-ink) 28%, transparent);
  }

  /* The nav is a header child; as a drawer it must not sit in the header's flow. */
  .gcg-header-inner .gcg-nav { order: 0; flex-basis: auto; }

  /* Each drawer gets a heading bar with a close control, injected by nav.js. */
  .gcg-drawer-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; margin: 0 0 18px; padding-bottom: 14px;
    border-bottom: 1px solid var(--gcg-line);
  }
  .gcg-nav .gcg-drawer-head { border-bottom-color: var(--gcg-ink-line); }
  .gcg-drawer-title {
    font-family: var(--gcg-sans); font-size: 0.68rem; font-weight: 700;
    letter-spacing: 0.16em; text-transform: uppercase; margin: 0;
    color: var(--gcg-secondary);
  }
  .gcg-nav .gcg-drawer-title { color: var(--gcg-accent-dk); }
  .gcg-drawer-close {
    width: 34px; height: 34px; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    background: none; border: 1px solid var(--gcg-line); border-radius: 999px;
    color: inherit; cursor: pointer; font-size: 1rem; line-height: 1;
  }
  .gcg-nav .gcg-drawer-close { border-color: var(--gcg-ink-line); color: var(--gcg-bone); }
  .gcg-drawer-close:hover, .gcg-drawer-close:focus-visible {
    background: var(--gcg-accent-dk); color: var(--gcg-ink); border-color: transparent;
  }

  /* In a drawer the filters are always expanded - the panel is the disclosure,
     so the <summary> that does that job at 901-980px is redundant here. */
  .gcg-filters-summary { display: none; }
  .gcg-filters-details[open] .gcg-filters-body { margin-top: 0; padding-top: 0; border-top: 0; }
  .gcg-filter-group { columns: 1; }

  /* Scroll lock, without the jump to top that position:fixed on body causes. */
  body.gcg-drawer-open { overflow: hidden; }
}

@media (prefers-reduced-motion: reduce) {
  .gcg-nav, .gcg-filters, .gcg-scrim { transition: none; }
}

@media print {
  .gcg-tabbar, .gcg-scrim { display: none; }
}
/* ==========================================================================
   SEARCH
   A trigger in the header, and one panel: a full-width sheet under the header
   on desktop, the whole viewport on a phone. Results are the archive's own
   product cards, rendered server-side by inc/search.php.

   The header carries only a fixed-size icon button. An earlier version put the
   text input in the header actions row and widened it on focus - a growing
   element in a flex row shoves its neighbours sideways, so the account link and
   the cart moved every time anyone clicked into it. That is what this layout
   exists to avoid.
   ========================================================================== */

.gcg-search-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; flex: none; padding: 0;
  background: none; border: 1px solid transparent; border-radius: 2px;
  color: var(--gcg-on-dark); cursor: pointer;
  transition: color .16s ease, border-color .16s ease, background-color .16s ease;
}
.gcg-search-toggle:hover {
  color: var(--gcg-bone);
  border-color: var(--gcg-ink-line);
  background: color-mix(in srgb, var(--gcg-bone) 7%, transparent);
}
.gcg-search-toggle[aria-expanded="true"] {
  color: var(--gcg-ink); background: var(--gcg-bone); border-color: var(--gcg-bone);
}
.gcg-search-toggle svg { display: block; }

/* --------------------------------------------------------------------------
   The panel
   -------------------------------------------------------------------------- */

.gcg-search-panel {
  position: fixed; left: 0; right: 0; top: 0; z-index: 120;
  display: flex; flex-direction: column;
  max-height: 100dvh;
  background: var(--gcg-white);
  border-bottom: 1px solid var(--gcg-line);
  box-shadow: 0 24px 60px color-mix(in srgb, var(--gcg-ink) 22%, transparent);
}
/* [hidden] alone loses to display:flex - the attribute selector and the class
   have the same specificity, and the class wins on source order. */
.gcg-search-panel[hidden] { display: none; }

.gcg-search-panel.is-open { animation: gcg-search-drop .2s ease both; }
@keyframes gcg-search-drop {
  from { opacity: 0; transform: translateY(-10px); }
  to   { opacity: 1; transform: none; }
}

/* The scrim. Its own element rather than a ::after on the panel, because the
   panel is a flex column and a pseudo-element would become a flex item. */
.gcg-search-scrim {
  position: fixed; inset: 0; z-index: 119;
  background: color-mix(in srgb, var(--gcg-ink) 55%, transparent);
  opacity: 0; transition: opacity .2s ease;
}
.gcg-search-scrim.is-open { opacity: 1; }
.gcg-search-scrim[hidden] { display: none; }

/* --------------------------------------------------------------------------
   The field row - dark, so it reads as part of the header it drops from
   -------------------------------------------------------------------------- */

.gcg-search-bar {
  flex: none;
  background: var(--gcg-ink); color: var(--gcg-bone);
  border-bottom: 1px solid var(--gcg-ink-line);
}
.gcg-search-bar-inner {
  display: flex; align-items: center; gap: 22px;
  min-height: 76px; /* matches .gcg-header-inner, so the bar sits exactly where
                       the header was and the swap reads as a transformation */
}

/* The lockup inside the bar. Fixed width so the field cannot shunt it about as
   its content grows - the same mistake the old header layout made. */
.gcg-search-bar .gcg-logo { flex: none; }

.gcg-search-form {
  display: flex; align-items: center; gap: 12px;
  flex: 1 1 auto; min-width: 0;
}
.gcg-search-field-icon { display: flex; flex: none; color: var(--gcg-secondary-dk); }
.gcg-search-form:focus-within .gcg-search-field-icon { color: var(--gcg-accent-dk); }

.gcg-search-input {
  flex: 1 1 auto; width: 100%; min-width: 0;
  padding: 6px 0; margin: 0;
  background: none; border: 0; outline: 0;
  /* 1.05rem, not the 1.5rem this launched with: at that size the placeholder
     ran the width of the bar and read as a headline rather than a field. */
  font-family: var(--gcg-serif); font-size: 1.05rem; line-height: 1.35;
  color: var(--gcg-bone);
}
.gcg-search-input::placeholder { color: var(--gcg-secondary-dk); opacity: 1; }
.gcg-search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

.gcg-search-clear,
.gcg-search-close {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  padding: 8px 10px; background: none; border: 1px solid transparent;
  border-radius: 2px; color: var(--gcg-on-dark);
  font-family: var(--gcg-sans); font-size: 0.8rem; cursor: pointer;
  transition: color .14s ease, border-color .14s ease;
}
.gcg-search-clear:hover, .gcg-search-close:hover {
  color: var(--gcg-bone); border-color: var(--gcg-ink-line);
}
.gcg-search-clear[hidden] { display: none; }
.gcg-search-close-x { display: none; }

/* --------------------------------------------------------------------------
   The results area
   -------------------------------------------------------------------------- */

.gcg-search-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--gcg-bone);
  padding: 26px 0 34px;
}

.gcg-search-results[aria-busy="true"] { opacity: .5; transition: opacity .12s ease; }

.gcg-search-count {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin: 0 0 18px;
}
.gcg-search-count-label {
  font-size: 0.68rem; font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--gcg-secondary);
}
.gcg-search-all {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 0.82rem; font-weight: 600; color: var(--gcg-ink);
  text-decoration: none; border-bottom: 1px solid var(--gcg-line);
  padding-bottom: 2px;
}
.gcg-search-all:hover { color: var(--gcg-ink); border-bottom-color: var(--gcg-accent-lt); }
.gcg-search-all-arrow { transition: transform .16s ease; }
.gcg-search-all:hover .gcg-search-all-arrow { transform: translateX(3px); }

/* The cards come from WooCommerce's own loop inside a .woocommerce wrapper, so
   every archive card rule already applies. What follows only compacts them:
   the archive card is sized to be browsed, and a search panel is scanned. */

.gcg-search-grid ul.products { margin: 0; }

/* Four across rather than the archive's three, and squarer covers. The archive
   cover is 3:4, which at panel width is nearly 500px tall - one row of results
   filled the whole screen. Square at four columns puts six results in view
   without scrolling, which is the entire point of the panel. */
.woocommerce.gcg-search-grid ul.products.columns-3 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}
.gcg-search-grid .gcg-cover { aspect-ratio: 1 / 1; padding: 15px; }
.gcg-search-grid .gcg-cover-title { font-size: 0.95rem; line-height: 1.2; margin-top: 9px; }
.gcg-search-grid .gcg-cover-cat { font-size: 0.54rem; }
.gcg-search-grid .gcg-cover-meta { font-size: 0.5rem; }

.gcg-search-grid .gcg-card-body { padding: 13px 14px 14px; }
.woocommerce.gcg-search-grid ul.products li.product .woocommerce-loop-product__title { font-size: 0.95rem; line-height: 1.25; }
.gcg-search-grid .gcg-card-meta { font-size: 0.7rem; }
.gcg-search-grid .gcg-card-foot { margin-top: 10px; }
.gcg-search-grid .gcg-price { font-size: 0.9rem; }
.gcg-search-grid .gcg-card-cta { font-size: 0.72rem; }

@media (max-width: 1100px) {
  .gcg-search-grid ul.products.columns-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}


/* Idle and empty states ---------------------------------------------------- */

.gcg-search-idle,
.gcg-search-empty { max-width: 58ch; padding: 6px 0 10px; }

.gcg-search-idle-head,
.gcg-search-empty-head {
  margin: 0 0 8px; font-family: var(--gcg-serif);
  font-size: 1.3rem; line-height: 1.25; color: var(--gcg-ink);
}
.gcg-search-idle-note,
.gcg-search-empty-note {
  margin: 0 0 18px; font-size: 0.88rem; line-height: 1.6; color: var(--gcg-secondary);
}
.gcg-search-idle-label {
  margin: 0 0 10px; font-size: 0.66rem; font-weight: 600; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--gcg-secondary);
}

.gcg-search-suggestions {
  display: flex; flex-wrap: wrap; gap: 8px;
  list-style: none; margin: 0; padding: 0;
}
.gcg-search-suggestion {
  display: inline-block; padding: 7px 14px;
  background: var(--gcg-white); border: 1px solid var(--gcg-line); border-radius: 2px;
  font-size: 0.82rem; color: var(--gcg-body); text-decoration: none;
  transition: border-color .14s ease, color .14s ease, background-color .14s ease;
}
.gcg-search-suggestion:hover {
  border-color: var(--gcg-accent-lt); color: var(--gcg-ink); background: var(--gcg-white);
}

.gcg-search-error {
  margin: 0; padding: 12px 14px;
  background: color-mix(in srgb, #a4453c 8%, transparent);
  border-left: 2px solid #a4453c; border-radius: 2px;
  font-size: 0.86rem; color: #7d3229;
}

/* --------------------------------------------------------------------------
   Phone: the panel is the whole screen
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  .gcg-search-panel { height: 100dvh; max-height: 100dvh; border-bottom: 0; }

  .gcg-search-bar .gcg-logo { display: none; }
  .gcg-search-bar-inner { min-height: 64px; gap: 10px; }
  .gcg-search-input { font-size: 1rem; }

  /* The word "Close" costs width the field needs; the × does the same job. */
  .gcg-search-close-label { display: none; }
  .gcg-search-close-x { display: inline; font-size: 0.95rem; }
  .gcg-search-close { padding: 9px 10px; }

  .gcg-search-body { padding: 20px 0 40px; }

  /* --- On a phone the cards become a list ---------------------------------
     A grid of cards is the wrong shape on a 375px screen: two columns make the
     titles unreadable, one column makes a single result fill the viewport.
     Same markup, restyled as rows - thumbnail left, everything else right. The
     card markup is WooCommerce's own, so none of this touches the template. */

  .woocommerce.gcg-search-grid ul.products.columns-3 {
    display: block;
    border-top: 1px solid var(--gcg-line);
  }
  .woocommerce.gcg-search-grid ul.products li.product {
    border: 0; border-bottom: 1px solid var(--gcg-line);
    border-radius: 0; background: none; transform: none;
  }
  .woocommerce.gcg-search-grid ul.products li.product:hover { border-color: var(--gcg-line); transform: none; }

  .woocommerce.gcg-search-grid ul.products li.product a.woocommerce-LoopProduct-link {
    display: flex; align-items: flex-start; gap: 14px; padding: 14px 2px;
  }

  /* The cover becomes a thumbnail. Its own text is hidden: this is a generated
     TYPOGRAPHIC cover, and at 66px the title inside it is unreadable noise
     sitting next to the same title set properly beside it. The motif and the
     category ground survive, which is what makes it recognisable. */
  .gcg-search-grid .gcg-cover {
    width: 66px; flex: none; aspect-ratio: 3 / 4; padding: 0; border-radius: 2px;
  }
  .gcg-search-grid .gcg-cover-cat,
  .gcg-search-grid .gcg-cover-title,
  .gcg-search-grid .gcg-cover-meta { display: none; }

  .gcg-search-grid .gcg-card-body { flex: 1 1 auto; min-width: 0; padding: 0; }
  .gcg-search-grid .gcg-card-cat { margin-bottom: 3px; }
  .woocommerce.gcg-search-grid ul.products li.product .woocommerce-loop-product__title {
    font-size: 0.98rem; line-height: 1.25; margin: 0 0 4px;
  }
  .gcg-search-grid .gcg-card-meta {
    font-size: 0.72rem; margin: 0;
    /* Two lines maximum: a spec line that wraps to four turns the list back
       into the cards this replaced. */
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .gcg-search-grid .gcg-card-foot {
    margin-top: 8px; padding-top: 0; border-top: 0;
    display: flex; align-items: baseline; gap: 12px;
  }
  .gcg-search-grid .gcg-price { font-size: 0.92rem; }


  .gcg-search-scrim { display: none; }
}

/* Deliberately NO single-column fallback at narrow widths. These covers are
   3:4, so one card per row is roughly 640px tall - less than a full result per
   screen, which turns six matches into a scroll. Two columns keeps the panel
   scannable, which is the entire reason it exists. */

@media (prefers-reduced-motion: reduce) {
  .gcg-search-panel.is-open { animation: none; }
  .gcg-search-scrim, .gcg-search-all-arrow, .gcg-search-results { transition: none; }
}


/* ==========================================================================
   INQUIRY-ONLY REPORTS
   The "Inquire now" button in the buy box, and the dialog behind it.
   ========================================================================== */

.gcg-inquiry-note {
  margin: 10px 0 0; font-size: 0.78rem; line-height: 1.5;
  color: var(--gcg-secondary); text-align: center;
}

/* --------------------------------------------------------------------------
   The dialog

   A real <dialog>, so the browser owns focus trapping, Escape and the backdrop.
   UA styles for it are opinionated - fixed max sizes, a border, its own
   margin - so they are all reset here rather than worked around.
   -------------------------------------------------------------------------- */

.gcg-inquiry-dialog {
  width: min(440px, calc(100vw - 32px));
  max-width: none; max-height: min(88vh, 720px);
  padding: 0; border: 1px solid var(--gcg-line); border-radius: 2px;
  margin: auto; /* centres it in both axes; the UA default is top-aligned */
  background: var(--gcg-white); color: var(--gcg-ink);
  box-shadow: 0 30px 70px color-mix(in srgb, var(--gcg-ink) 34%, transparent);
  overflow: auto;
}
.gcg-inquiry-dialog::backdrop {
  background: color-mix(in srgb, var(--gcg-ink) 62%, transparent);
  backdrop-filter: blur(2px);
}
.gcg-inquiry-dialog[open] { animation: gcg-inquiry-in .18s ease both; }
@keyframes gcg-inquiry-in {
  from { opacity: 0; transform: translateY(8px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

.gcg-inquiry-form,
.gcg-inquiry-done { position: relative; padding: 30px 30px 26px; }

.gcg-inquiry-dialog h2 {
  margin: 0 0 10px; font-family: var(--gcg-serif);
  font-size: 1.35rem; line-height: 1.22; color: var(--gcg-ink);
}
.gcg-inquiry-lede {
  margin: 0 0 20px; font-size: 0.86rem; line-height: 1.55; color: var(--gcg-secondary);
}

.gcg-inquiry-close {
  position: absolute; top: 14px; right: 14px;
  width: 30px; height: 30px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: 2px;
  color: var(--gcg-secondary); font-size: 0.86rem; cursor: pointer;
  transition: background-color .12s ease, color .12s ease;
}
.gcg-inquiry-close:hover { background: var(--gcg-bone); color: var(--gcg-ink); }

.gcg-inquiry-field { display: block; margin: 0 0 14px; }
.gcg-inquiry-field > span {
  display: flex; align-items: baseline; gap: 6px; margin-bottom: 5px;
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--gcg-ink);
}
.gcg-inquiry-optional {
  font-style: normal; font-weight: 500; letter-spacing: 0.04em;
  text-transform: none; color: var(--gcg-secondary);
}
.gcg-inquiry-field input {
  width: 100%; padding: 11px 13px;
  font-family: var(--gcg-sans); font-size: 0.92rem; color: var(--gcg-ink);
  background: var(--gcg-white);
  border: 1px solid var(--gcg-line); border-radius: 2px;
  transition: border-color .14s ease, box-shadow .14s ease;
}
.gcg-inquiry-field input:focus {
  outline: 0; border-color: var(--gcg-accent-lt);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gcg-accent-lt) 16%, transparent);
}
.gcg-inquiry-field input:user-invalid { border-color: #a4453c; }

/* The honeypot. Off-screen rather than display:none - some bots skip anything
   that is not rendered, and the point is for them to fill it in. */
.gcg-inquiry-hp {
  position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden;
}

.gcg-inquiry-error {
  margin: 0 0 12px; padding: 9px 12px;
  background: color-mix(in srgb, #a4453c 8%, transparent);
  border-left: 2px solid #a4453c; border-radius: 2px;
  font-size: 0.82rem; color: #7d3229;
}

.gcg-inquiry-send { margin-top: 4px; }
.gcg-inquiry-send[disabled] { opacity: .6; cursor: default; }

.gcg-inquiry-privacy {
  margin: 14px 0 0; font-size: 0.72rem; line-height: 1.5; color: var(--gcg-secondary);
}

/* The confirmation. Deliberately says the team will be in touch and NOT that
   anything will be emailed - see the note at the top of inc/inquiry.php. */
.gcg-inquiry-done { text-align: center; padding-top: 38px; }
.gcg-inquiry-done-mark {
  width: 46px; height: 46px; margin: 0 auto 16px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--gcg-bone);
  color: var(--gcg-accent-lt); font-size: 1.25rem;
}
.gcg-inquiry-done p { margin: 0 0 20px; font-size: 0.88rem; line-height: 1.6; color: var(--gcg-secondary); }
.gcg-inquiry-done h2 { margin-bottom: 8px; }

@media (max-width: 600px) {
  .gcg-inquiry-form, .gcg-inquiry-done { padding: 26px 20px 22px; }
}

@media (prefers-reduced-motion: reduce) {
  .gcg-inquiry-dialog[open] { animation: none; }
  .gcg-inquiry-field input, .gcg-inquiry-close { transition: none; }
}

/* ==========================================================================
   PRODUCT ACTION BAR (phones) + the sample bottom sheet

   A second bar above the tab bar on product pages. The buy box is near the top
   of a long page; by the time a reader has been through the spec table and the
   description - which is when they decide - it is several screens behind them.

   Every button in it forwards to the real control in the buy box (see nav.js
   section 7), so nothing here reimplements adding to a cart, opening the
   inquiry dialog or requesting a sample.
   ========================================================================== */

.gcg-product-bar { display: none; }

@media (max-width: 900px) {

  .gcg-product-bar {
    position: fixed; left: 0; right: 0;
    /* Sits ON TOP OF the tab bar, not over it. Both offsets have to clear the
       iOS home indicator or the two overlap on a notched phone. */
    bottom: calc(56px + env(safe-area-inset-bottom, 0px));
    z-index: 95;
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    align-items: center;
    gap: 10px; padding: 0 16px;
    /* Pinned height, not derived from the buttons. The page clearance below has
       to equal this exactly, and a height that moves with font metrics would
       leave the footer grazing the bar - which it did, by 2px. */
    height: 68px;
    background: var(--gcg-white);
    border-top: 1px solid var(--gcg-line);
    box-shadow: 0 -10px 26px color-mix(in srgb, var(--gcg-ink) 12%, transparent);
  }

  /* One button or two, the bar is the same height - an inquiry-only report has
     no sample, so its bar carries a single full-width button. */
  .gcg-product-bar .gcg-btn {
    margin: 0; padding: 12px; font-size: 0.86rem; white-space: nowrap;
  }

  /* The page has to end above BOTH bars: 56 for the tab bar, 68 for this one,
     matching the pinned height above. Change one, change the other. */
  body.gcg-has-product-bar {
    padding-bottom: calc(56px + 68px + env(safe-area-inset-bottom, 0px));
  }

  /* ------------------------------------------------------------------------
     The sample form as a bottom sheet

     Same markup and the same open/close logic as the desktop panel - only the
     presentation changes. A drawer is the right shape here because the button
     that opens it is pinned to the bottom of the screen, and a form that opened
     four screens up would look like nothing had happened.
     ------------------------------------------------------------------------ */

  .gcg-sample-gate .gcg-sample-form {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 140;
    margin: 0; max-height: 86dvh; overflow-y: auto;
    padding: 24px 20px calc(24px + env(safe-area-inset-bottom, 0px));
    background: var(--gcg-white);
    border: 0; border-top: 1px solid var(--gcg-line);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -20px 54px color-mix(in srgb, var(--gcg-ink) 30%, transparent);
    animation: gcg-sheet-up .22s ease both;
  }

  /* The grab handle. Decoration, but it is the thing that makes a sheet read as
     dismissable rather than as a panel that has escaped its container. */
  .gcg-sample-gate .gcg-sample-form::before {
    content: ""; display: block;
    width: 38px; height: 4px; margin: -8px auto 16px;
    border-radius: 999px; background: var(--gcg-line);
  }

  @keyframes gcg-sheet-up {
    from { transform: translateY(100%); }
    to   { transform: none; }
  }

  /*
   * The scrim hangs off the body, not off the form.
   *
   * A full-viewport pseudo-element on the form itself cannot work: the form is a
   * positioned element, so its own ::before paints ABOVE its background within
   * its stacking context, and the scrim would cover the sheet it is meant to sit
   * behind. nav.js puts the state on <body> instead.
   */
  body.gcg-sheet-open::after {
    content: ""; position: fixed; inset: 0; z-index: 135;
    background: color-mix(in srgb, var(--gcg-ink) 52%, transparent);
  }

  /* The sheet is the interaction while it is open; the bars beneath it are not. */
  body.gcg-sheet-open .gcg-product-bar,
  body.gcg-sheet-open .gcg-tabbar { pointer-events: none; }
}

@media (prefers-reduced-motion: reduce) {
  .gcg-sample-gate .gcg-sample-form { animation: none; }
}

/* ==========================================================================
   SECTION ACTIONS, THE FRESHNESS CHIP, AND THE LATEST STRIP
   Added 1.28.0 with the homepage revisions.
   ========================================================================== */

/* The right-hand side of a section heading: a search trigger next to the
   "See all reports" link. Both sections that list reports carry this. */
.gcg-section-actions {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 20px;
}

/* The trigger is a <button> so it can open the panel, but it has to read as the
   link beside it - the base button reset (trap 10) is what makes that possible
   without fighting the parent theme. */
.gcg-search-link {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 0; background: none; border: 0; cursor: pointer;
  font-family: var(--gcg-sans); font-size: inherit; color: inherit;
}
.gcg-search-link svg { display: block; flex: none; }

/* The shop archive's copy of the trigger is button-shaped. It is the only
   control in that page head, with no sibling link to borrow its look from, and
   an understated text link there was too easy to miss.

   Deliberately NOT built on .gcg-btn: the reset above and .gcg-btn set the same
   six properties at the same specificity, so which one won would depend on
   source order in two places at once. This block sits after the reset, is also
   a single class, and therefore decides those properties outright. */
.gcg-search-btn {
  padding: 11px 20px; border: 1px solid var(--gcg-ink); border-radius: 2px;
  background: transparent; color: var(--gcg-ink);
  font-size: 0.84rem; font-weight: 600; letter-spacing: 0.02em;
}
.gcg-search-btn:hover,
.gcg-search-btn:focus { background: var(--gcg-ink); color: var(--gcg-bone); }

/* Clears the lede above it. */
.gcg-head-actions { margin-top: 24px; }


/* ==========================================================================
   Newsletter signup popup
   ==========================================================================
   Only ever on the page when ?subscribe= is in the URL — the server does not
   print the dialog otherwise, so none of this loads for an ordinary visitor
   beyond the few hundred bytes of CSS below.
   ========================================================================== */

.gcg-sub {
  width: min(30rem, calc(100vw - 32px));
  max-height: calc(100dvh - 32px);
  padding: 0;
  border: 1px solid var(--gcg-line);
  border-radius: 3px;
  background: var(--gcg-white);
  color: var(--gcg-body);
  box-shadow: 0 18px 50px rgb(14 16 19 / 22%);
  overflow: auto;
}
.gcg-sub::backdrop { background: rgb(14 16 19 / 58%); }

.gcg-sub-dismiss { margin: 0; }
.gcg-sub-close {
  position: absolute; top: 10px; right: 10px;
  display: grid; place-items: center; width: 32px; height: 32px;
  padding: 0; border: 0; border-radius: 2px;
  background: none; color: var(--gcg-secondary); cursor: pointer;
}
.gcg-sub-close:hover, .gcg-sub-close:focus { color: var(--gcg-ink); background: var(--gcg-tint); }

.gcg-sub-inner { padding: 26px 24px 22px; }

.gcg-sub-inner h2 {
  margin: 5px 0 0;
  font-family: var(--gcg-serif); font-weight: 400;
  font-size: clamp(1.4rem, 5.4vw, 1.75rem); line-height: 1.14;
  letter-spacing: -0.012em; color: var(--gcg-ink);
  text-wrap: balance;
}
.gcg-sub-lede { margin: 8px 0 0; font-size: 0.9rem; color: var(--gcg-secondary); }

/* --- the form ------------------------------------------------------------ */

/* CF7 wraps every row in a <p>, and the parent theme gives <p> a bottom
   margin. Zeroing it here and spacing the rows from this side means the gaps
   are set in one place instead of two fighting each other. */
.gcg-sub .wpcf7 { margin-top: 16px; }
.gcg-sub .wpcf7-form br { display: none; }

/* All three selectors are qualified the same way ON PURPOSE. Written as a bare
   `.gcg-sub-row`, the row margin lost to the `p { margin: 0 }` reset above it —
   (0,1,0) against (0,2,1) — and every gap in the form collapsed to nothing.
   Keeping the reset and the overrides at one specificity level is what stops
   that happening again. */
.gcg-sub .wpcf7-form p { margin: 0; }
.gcg-sub .wpcf7-form p.gcg-sub-row { margin-bottom: 10px; }
.gcg-sub .wpcf7-form p.gcg-sub-actions { margin-top: 14px; }

/* The labels are present and hidden, not removed. A placeholder disappears the
   instant someone types, is not reliably announced, and leaves nothing on
   screen naming the field if autofill puts the wrong value in it. This is the
   standard clip-rect pattern rather than display:none, which would take the
   label out of the accessibility tree along with the layout. */
.gcg-sub-row label {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

.gcg-sub-row input[type="text"],
.gcg-sub-row input[type="email"] {
  width: 100%;
  padding: 13px 14px;
  border: 1px solid var(--gcg-line); border-radius: 2px;
  background: var(--gcg-white); color: var(--gcg-ink);
  font-family: var(--gcg-sans);
  /* 16px minimum: iOS Safari zooms the page in on focus below it, so the
     visitor's first action at a stand would be pinching back out. Most of
     these will be opened on a phone, which makes this the one non-negotiable
     number in the block. */
  font-size: 16px;
  line-height: 1.3;
}
.gcg-sub-row input::placeholder { color: var(--gcg-secondary); opacity: 1; }
.gcg-sub-row input:focus {
  outline: 2px solid var(--gcg-accent-lt); outline-offset: 1px;
  border-color: var(--gcg-accent-lt);
}

.gcg-sub .wpcf7-submit {
  width: 100%;
  padding: 14px 24px;
  border: 1px solid var(--gcg-ink); border-radius: 2px;
  background: var(--gcg-ink); color: var(--gcg-bone);
  font-family: var(--gcg-sans); font-size: 0.94rem; font-weight: 600; letter-spacing: 0.02em;
  cursor: pointer;
}
.gcg-sub .wpcf7-submit:hover, .gcg-sub .wpcf7-submit:focus { background: var(--gcg-ink-soft); }

.gcg-sub-privacy { margin: 12px 0 0; font-size: 0.76rem; line-height: 1.45; color: var(--gcg-secondary); }
.gcg-sub-privacy a { color: var(--gcg-accent-lt); text-decoration: underline; text-underline-offset: 2px; }

/* CF7's own messages, in this theme's voice rather than its default red. */
.gcg-sub .wpcf7-response-output {
  margin: 14px 0 0 !important; padding: 10px 12px !important;
  border: 1px solid var(--gcg-line) !important; border-radius: 2px;
  background: var(--gcg-tint); font-size: 0.84rem;
}
.gcg-sub .wpcf7-not-valid-tip { margin-top: 4px; font-size: 0.76rem; color: #8C2F39; }
.gcg-sub form.sent .wpcf7-response-output {
  border-color: var(--gcg-accent-lt) !important;
  background: color-mix(in srgb, var(--gcg-accent-lt) 10%, var(--gcg-white));
}
/* CF7's spinner is absolutely positioned, so it needs somewhere to BE — given
   no offsets it stayed at its static position after the full-width button and
   hung past the dialog's right edge, which showed as a horizontal scrollbar.
   Anchored inside the button instead. */
.gcg-sub .wpcf7-form p.gcg-sub-actions { position: relative; }
.gcg-sub .wpcf7-spinner {
  position: absolute; right: 14px; top: 50%; margin: 0;
  transform: translateY(-50%);
}

/* Phone: the dialog is most of the screen, so it earns its edges back. */
@media (max-width: 520px) {
  .gcg-sub { width: calc(100vw - 24px); border-radius: 2px; }
  .gcg-sub-inner { padding: 24px 20px 20px; }
}

/* ==========================================================================
   Hero variations — scrolling report pages
   ==========================================================================
   Used only by page-home-straight.php and page-home-angled.php. The live
   homepage loads none of it; .gcg-hero on its own is unaffected.

   Everything that moves is a `transform` on a track element, so the whole
   thing runs on the compositor: no layout, no paint, no main-thread work per
   frame. The cards are static.

   Everything inside a card is sized in `em` against the card's own font-size,
   so the two variants scale one component instead of needing two sets of
   rules. Change .gcg-hr-card's font-size and the whole page rescales.
   ========================================================================== */

/* --- shared: the stage, columns and tracks ------------------------------- */

/* Both spacings are variables so the flood variant can run denser without
   touching the split variant, which the client has already approved. */
.gcg-hr-stage { display: grid; gap: var(--hr-col-gap, 18px); height: 100%; }
.gcg-hr-col   { position: relative; overflow: hidden; min-width: 0; }

.gcg-hr-track {
  display: flex; flex-direction: column;
  animation-name: gcg-hr-up;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  /* Promoted once per column, deliberately. will-change on the cards instead
     would hand the compositor two dozen layers to juggle for no benefit. */
  will-change: transform;
}
.gcg-hr-track.is-down { animation-name: gcg-hr-down; }

/* The track holds its cards twice and travels exactly half its own height, so
   copy two lands where copy one began. The spacing is a bottom margin on each
   card, not `gap` on the track: with `gap` the repeating unit is not a whole
   card-plus-space and 50% lands mid-gap, which shows as a jump. */
@keyframes gcg-hr-up {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, -50%, 0); }
}
@keyframes gcg-hr-down {
  from { transform: translate3d(0, -50%, 0); }
  to   { transform: translate3d(0, 0, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .gcg-hr-track { animation: none; transform: translate3d(0, -14%, 0); }
}

/* --- the flood hero (tilted, full-bleed, copy on top) -------------------- */

.gcg-hero-flood { padding-block: 104px 96px; position: relative; }

.gcg-hero-flood-bg {
  position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
}

/* The grid sits on the RIGHT, not across everything.
   It began as `inset: -22%` — the whole section — which put pages underneath
   the headline where the scrim then had to hide them, so most of the work was
   being thrown away. Starting at 44% means nothing is drawn where the copy
   goes, and the top/bottom/right overhang is what lets it still run off those
   three edges. A rotated rectangle no longer covers the box it came from, which
   is why the overhang is needed at all.

   The left edge is NOT clipped — the scrim dissolves it. That was the original
   complaint and it is the reason there is no `left: 0` here. */
.gcg-hero-flood-bg .gcg-hr-stage {
  position: absolute;
  /* 50%, not 44%: the tilt swings the grid's top-left corner leftward, so the
     figure that matters is where the ROTATED shape lands, not where the box
     starts. At 44% that corner reached back under the lede. */
  top: -20%; bottom: -20%; left: 50%; right: -14%;
  grid-template-columns: repeat(4, 1fr);
  transform: rotate(-9deg);
  height: auto;
  --hr-col-gap: 13px;
  --hr-gap: 1.05em;
}

/* Smaller pages than the split hero: at 10.5px a page filled most of a column,
   so one took a third of a minute to clear and the column read as mostly empty
   space between two documents. At 8.1px three sit in view at once and the
   catalogue reads as a catalogue. */
.gcg-hero-flood-bg .gcg-hr-card { font-size: 8.1px; }

/* What keeps the copy readable. A gradient, not backdrop-filter: a backdrop
   blur over animating content re-blurs that area every frame, which is the one
   thing here that would actually cost something. Opaque under the text, gone
   by the time the reports are meant to be seen. */
.gcg-hero-scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(100deg,
      var(--gcg-tint) 0%,
      var(--gcg-tint) 40%,
      color-mix(in srgb, var(--gcg-tint) 62%, transparent) 50%,
      color-mix(in srgb, var(--gcg-tint) 16%, transparent) 60%,
      transparent 70%),
    linear-gradient(to bottom,
      var(--gcg-tint) 0%, transparent 12%,
      transparent 88%, var(--gcg-tint) 100%);
}

.gcg-hero-flood > .gcg-wrap { position: relative; z-index: 2; }
.gcg-hero-flood .gcg-hero-copy { max-width: 31rem; }

/* Below 900px the tilt and the scrim both go: the reports would sit under the
   text with nowhere to be seen, so the hero returns to text on the plain
   ground, which is what the live homepage already is. */
@media (max-width: 900px) {
  .gcg-hero-flood-bg, .gcg-hero-scrim { display: none; }
  .gcg-hero-flood { padding-block: 92px 84px; }
}

/* --- the report page ----------------------------------------------------- */

.gcg-hr-card {
  flex: none;
  margin-bottom: var(--hr-gap, 1.9em);   /* the repeating unit — see @keyframes */
  padding: 1.15em 1.15em 0.9em;
  background: var(--gcg-white);
  border: 1px solid var(--gcg-line);
  box-shadow: 0 1px 3px rgb(14 16 19 / 7%), 0 6px 16px rgb(14 16 19 / 4%);
  font-family: var(--gcg-sans);
  font-size: 9px;                        /* overridden per variant */
  line-height: 1.35;
  color: var(--gcg-body);
  display: flex; flex-direction: column; gap: 0.85em;
  aspect-ratio: 1 / 1.414;               /* A4 — it is a report page */
  overflow: hidden;
}

.gcg-hr-brand {
  display: flex; align-items: center; gap: 0.45em;
  font-size: 0.66em; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--gcg-secondary);
}
.gcg-hr-dot {
  flex: none; width: 0.85em; height: 0.85em; border-radius: 50%;
  background: var(--gcg-ink);
}

.gcg-hr-hd h4 {
  margin: 0; font-family: var(--gcg-serif); font-weight: 400;
  font-size: 1.5em; line-height: 1.12; letter-spacing: -0.01em;
  color: var(--gcg-ink);
}
.gcg-hr-hd p {
  margin: 0.25em 0 0; font-size: 0.78em; color: var(--gcg-secondary);
}

/* the results table */
.gcg-hr-tbl {
  width: 100%; border-collapse: collapse;
  font-size: 0.72em; font-variant-numeric: tabular-nums;
}
.gcg-hr-tbl th {
  padding: 0.4em 0.35em; text-align: right;
  background: var(--gcg-ink); color: var(--gcg-bone);
  font-weight: 600; letter-spacing: 0.04em;
}
.gcg-hr-tbl th:first-child, .gcg-hr-tbl td:first-child { text-align: left; }
.gcg-hr-tbl td {
  padding: 0.38em 0.35em; text-align: right;
  border-bottom: 1px solid var(--gcg-line);
  color: var(--gcg-body);
}
.gcg-hr-tbl tbody tr:nth-child(even) { background: color-mix(in srgb, var(--gcg-tint) 42%, transparent); }

/* the quartile band — the graphic that says "benchmarking", not "chart" */
.gcg-hr-quart { display: flex; flex-direction: column; gap: 0.45em; }
.gcg-hr-quart-band {
  position: relative; height: 0.5em; border-radius: 0.25em;
  background: color-mix(in srgb, var(--gcg-tint) 70%, transparent);
}
.gcg-hr-quart-iqr {
  position: absolute; left: 18%; right: 24%; top: 0; bottom: 0;
  background: color-mix(in srgb, var(--gcg-accent-lt) 34%, transparent);
  border-radius: 0.25em;
}
.gcg-hr-quart-tick {
  position: absolute; top: -0.2em; width: 1.5px; height: 0.9em;
  background: var(--gcg-accent-lt);
}
.gcg-hr-quart-tick.is-med { background: var(--gcg-ink); width: 2px; height: 1.15em; top: -0.33em; }
.gcg-hr-quart-keys {
  display: flex; justify-content: space-between;
  font-size: 0.64em; font-weight: 600; letter-spacing: 0.03em;
  color: var(--gcg-secondary); font-variant-numeric: tabular-nums;
}

/* the bar chart */
.gcg-hr-chart { margin-top: auto; display: flex; flex-direction: column; gap: 0.4em; }
.gcg-hr-chart-cap {
  font-size: 0.62em; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--gcg-secondary);
}
.gcg-hr-bars {
  display: flex; align-items: flex-end; gap: 0.22em; height: 3.4em;
  border-bottom: 1px solid var(--gcg-line);
}
.gcg-hr-bars span { flex: 1; background: var(--gcg-ink); opacity: 0.34; }
.gcg-hr-bars span:nth-child(4n) { opacity: 0.66; }

/* narrative pages */
.gcg-hr-prose { display: flex; flex-direction: column; gap: 0.42em; }
.gcg-hr-prose span { height: 0.3em; background: var(--gcg-line); border-radius: 1px; }
.gcg-hr-keys { display: flex; flex-wrap: wrap; gap: 0.35em; margin-top: 0.2em; }
.gcg-hr-keys span {
  padding: 0.2em 0.45em; font-size: 0.62em; font-weight: 700; letter-spacing: 0.05em;
  border: 1px solid var(--gcg-line); color: var(--gcg-secondary);
}

.gcg-hr-ft {
  margin-top: auto; padding-top: 0.6em; border-top: 1px solid var(--gcg-line);
  display: flex; justify-content: space-between;
  font-size: 0.6em; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--gcg-secondary);
}

/* A few pages are a different length, so a column reads as a set of documents
   rather than one page repeated. */
.gcg-hr-shape-1 { aspect-ratio: 1 / 1.28; }
.gcg-hr-shape-3 { aspect-ratio: 1 / 1.22; }

/* --------------------------------------------------------------------------
   The freshness chip on a product card
   -------------------------------------------------------------------------- */

/* Category left, chip right, baselines aligned so the eyebrow and the chip sit
   on one line rather than one nudging the other down. */
.gcg-card-top {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-bottom: 4px;
}
.gcg-card-top .gcg-card-cat { margin: 0; }

.gcg-card-updated {
  flex: none;
  padding: 3px 8px; border-radius: 999px;
  background: var(--gcg-bone); border: 1px solid var(--gcg-line);
  font-size: 0.6rem; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--gcg-secondary);
  white-space: nowrap;
}
/* Revised inside thirty days: worth noticing, so it takes the accent rather
   than the muted grey. Everything older stays quiet on purpose - a catalogue
   where every chip is highlighted has highlighted nothing. */
.gcg-card-updated.is-fresh {
  background: color-mix(in srgb, var(--gcg-accent-lt) 12%, var(--gcg-white));
  border-color: color-mix(in srgb, var(--gcg-accent-lt) 35%, transparent);
  color: var(--gcg-accent-lt);
}
.gcg-card-updated time { font: inherit; color: inherit; }

/* --------------------------------------------------------------------------
   The Latest strip
   -------------------------------------------------------------------------- */

/* Rendered by a custom loop rather than the [products] shortcode, so it needs
   the same .woocommerce scope the shortcode would have supplied - without it
   ul.products has no grid at all. Handbook trap 18. */
.gcg-latest-grid ul.products { margin: 0; }

@media (max-width: 600px) {
  /* At this width the card is narrow enough that eyebrow + chip on one line
     squeezes both. Stack them and let the chip sit under the category. */
  .gcg-card-top { flex-direction: column; align-items: flex-start; gap: 5px; }
}

/* In the search panel's phone list the row is already tight, and the chip is
   the least important thing in it. */
@media (max-width: 900px) {
  .woocommerce.gcg-search-grid ul.products li.product .gcg-card-updated { display: none; }
}
