/* ================================================================
   Happy Ratters design tokens

   Semantic tokens are the source of truth for shared UI. Page-specific
   illustration colors (medals, gems, welfare categories) may remain local,
   but structural color, type, spacing, shape, elevation, and motion should
   use this system. The legacy token names are retained as aliases so older
   page rules remain compatible while components are progressively cleaned.
================================================================ */

:root {
  /* Brand and semantic color roles */
  --color-brand: #76bdb9;
  --color-brand-hover: #3f8380;
  --color-brand-strong: #326c69;
  --color-accent: #e08e2b;
  --color-accent-hover: #c8791d;
  /* Used solely for the two "Get Started" buttons' background, now that
     their text is white — --color-accent itself is only ~2.6:1 against
     white, below even WCAG's large-text minimum (3:1). Rather than
     darkening toward brown/ochre to chase full AA (4.5:1), this keeps the
     same brand hue (32.8°) but boosts saturation for a brighter, more
     vivid "sporty" orange and dials lightness down only as far as 3:1
     requires (~3.1:1, with a small safety margin) — the text-shadow on
     the label (see .nav-cta/.btn-primary) covers the rest of the real-
     world legibility gap. Everywhere else that uses orange as a
     decorative accent (not button text contrast) keeps using
     --color-accent/--color-accent-hover, which are unchanged. */
  --color-accent-button: #d87b0b;
  /* Hover deliberately goes LIGHTER, not darker (same hue/saturation as
     --color-accent-button, +13.5 lightness) — matches the lighter-on-
     hover treatment used by the hero teal buttons. Label stays white on
     both, so this is only ~2.15:1 against white on its own; the
     text-shadow on .nav-cta/.btn-primary (and their shared hover state)
     carries real-world legibility instead of darkening the label. */
  --color-accent-button-hover: #f59d33;
  --color-text: #242019;
  --color-text-muted: #5c5648;
  --color-text-on-dark: #ffffff;
  --color-page: #faf7f2;
  --color-surface: #ffffff;
  --color-surface-subtle: #f7f3eb;
  --color-surface-brand: #eaf5f0;
  --color-border: #e6e0d4;
  --color-border-strong: #d8d2c4;
  /* Lighter teal border that pairs with --color-surface-brand fills —
     used for "selected"/"in-progress" states (chosen list card, active
     title row, callouts) so they read as brand-tinted, not just bordered. */
  --color-border-brand: #cfe2df;
  --color-focus-ring: rgba(63, 131, 128, 0.55);
  --color-error: #b3261e;
  --color-error-border: #e3b3ad;

  /* Backwards-compatible aliases */
  --color-primary: var(--color-brand);
  --color-primary-dark: var(--color-brand-hover);
  --color-bg: var(--color-page);
  --color-card-bg: var(--color-surface);
  --color-text-light: var(--color-text-muted);

  /* Brand gradients — reused as-is (not just color) by several button and
     icon-tile variants. Named so a rebrand only edits these two pairs
     instead of hunting down each place the gradient was copy-pasted. */
  --gradient-accent: linear-gradient(145deg, #e99a39 0%, var(--color-accent) 58%, var(--color-accent-hover) 100%);
  --gradient-accent-hover: linear-gradient(145deg, #f0a645 0%, #d98522 65%, #bd6f16 100%);
  --gradient-teal: linear-gradient(145deg, #4b918e 0%, var(--color-brand-hover) 62%, var(--color-brand-strong) 100%);
  --gradient-teal-hover: linear-gradient(145deg, #58a09c 0%, #3b7d7a 65%, #2d625f 100%);

  /* Typography */
  --font-family-sans: "Baloo 2", -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-size-2xs: 0.8rem;
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.875rem;
  --font-size-body: 1rem;
  --font-size-body-lg: 1.125rem;
  --font-size-heading-sm: 1.125rem;
  --font-size-heading-md: clamp(1.5rem, 3vw, 2.1rem);
  --font-size-heading-lg: clamp(2rem, 4vw, 2.6rem);
  --line-height-tight: 1.2;
  --line-height-body: 1.6;
  --line-height-compact: 1.4;
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-weight-extrabold: 800;
  --measure-copy: 65ch;
  --measure-lead: 52ch;

  /* 4px/8px spacing scale */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 5rem;
  --container-gutter: 1.25rem;
  --section-padding-block: var(--space-8);
  --section-padding-block-compact: var(--space-6);
  --section-padding-block-mobile: var(--space-7);
  --grid-gap: var(--space-5);
  --grid-gap-compact: var(--space-4);
  --card-padding: var(--space-5);
  --card-padding-compact: var(--space-4);
  --max-width: 1100px;
  --max-width-wide: 1360px;
  /* Shared by .top-bar and .site-footer so the two slim bars stay the
     same height as each other by construction, not by coincidence. */
  --bar-padding-block: 7px;

  /* Shape and elevation */
  --radius-sm: 0.5rem;
  --radius-md: 0.75rem;
  --radius-lg: 1rem;
  --radius-pill: 999px;
  --border-subtle: 1px solid var(--color-border);
  --shadow-card: 0 3px 8px rgba(47, 48, 43, 0.065);
  --shadow-hover: 0 8px 18px rgba(37, 83, 76, 0.13);
  --shadow-overlay: 0 20px 60px rgba(0, 0, 0, 0.35);
  /* Soft lift under the rotated icon tiles (stats, welfare pillars,
     resource cards) — one shadow shape shared by all of them. */
  --shadow-icon: 0 5px 12px rgba(37, 58, 51, 0.08);

  /* Motion */
  --duration-fast: 150ms;
  --duration-standard: 250ms;
  --duration-reveal: 500ms;
  /* Default stagger step between siblings in a .fade-up card/tile grid
     (events, news, resource cards, etc). The hero/page-banner entrance
     uses a slower, more deliberate step defined directly in js/fade-up.js,
     since a heading->subhead->buttons sequence reads better spaced out
     more than a grid of same-weight cards does. */
  --duration-stagger: 75ms;
  --fade-up-delay: 0ms;
  --ease-standard: ease;
  /* Decelerating curve for content easing into place (.fade-up) — kept
     distinct from --ease-standard, which is tuned for hover/interaction
     feedback, not entrance motion. */
  --ease-out: ease-out;
  /* The de facto standard speed for card/tile hover lift (border, background,
     shadow, transform together) — used far more than --duration-standard for
     this exact interaction, so it gets its own name instead of staying an
     unlabeled literal repeated across every card-like component. */
  --duration-hover: 220ms;
  /* Accelerating curve for content easing out of place (nav dropdowns
     closing) — the close-side counterpart to --ease-out. */
  --ease-in: ease-in;
  /* Nav dropdown open speed. The close side reuses --duration-fast (150ms)
     for both the close animation itself and the close-delay before it
     starts — see .dropdown in the "About dropdown" section. */
  --duration-dropdown-open: 200ms;

  /* Sticky header stack + scroll offsets
     The top bar, main nav, and (on interior pages) the page banner all
     stick to the viewport top and stack on top of each other. Anything
     that scrolls to an in-page anchor, or sticks below that stack itself,
     needs to clear its total height — these are that stack's measurements
     in one place instead of copy-pasted per component. js/page-banner-
     sticky.js reads --sticky-banner-top directly so the JS and CSS can't
     drift apart the way two separately hand-maintained numbers can. */
  --sticky-header-top: 34.5px;
  --sticky-banner-top: 125.5px;
  --sticky-titles-subnav-top: 171.5px;
  --scroll-offset: 180px;
  --scroll-offset-titles: 230px;
}

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

/* ---------- Handler FAQs / Help Center ----------
   Declared after .container (moved above) so these rules' own
   padding-top/bottom values aren't clobbered by .container's shorthand
   padding when an element carries both classes (e.g. class="faq-search-
   section container") — equal specificity means source order decides.
------------------------------------------------ */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.skip-link { position: fixed; top: var(--space-2); left: var(--space-2); z-index: 100; padding: var(--space-2) var(--space-4); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-brand-hover); font-weight: var(--font-weight-bold); box-shadow: var(--shadow-hover); transform: translateY(-150%); }
.skip-link:focus { transform: none; }
.faq-search-section { padding: 40px 20px 0; }
.faq-library { display: grid; grid-template-columns: 230px minmax(0, 1fr); gap: 50px; align-items: start; padding-top: 22px; padding-bottom: 80px; }
.faq-sidebar { position: sticky; top: var(--scroll-offset); }
.faq-sidebar > p { margin: 0 0 10px; color: var(--color-text-light); font-size: .76rem; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; }
.faq-sidebar nav { display: flex; flex-direction: column; }
.faq-sidebar nav a { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 12px; border-left: 3px solid transparent; color: var(--color-text-light); text-decoration: none; font-size: .9rem; font-weight: 600; transition: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard), border-left-color var(--duration-fast) var(--ease-standard); }
.faq-sidebar nav a:hover, .faq-sidebar nav a.active { border-left-color: var(--color-accent); background: #f1ece3; color: var(--color-primary-dark); }
.faq-sidebar nav a > span { display: inline-flex; align-items: center; gap: 9px; min-width: 0; }
.faq-sidebar nav svg { width: 18px; height: 18px; flex: 0 0 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.faq-sidebar nav small { color: #918a7c; }
.faq-sidebar-help { margin-top: var(--space-7); padding: var(--card-padding-compact); border: var(--border-subtle); border-radius: var(--radius-md); background: var(--color-surface-brand); }
.faq-sidebar-help p { margin: 4px 0 10px; color: var(--color-text-light); font-size: .82rem; line-height: 1.45; }
.faq-sidebar-help a { font-size: .82rem; font-weight: 700; }
.faq-mobile-nav { display: none; }
.faq-search-status { min-height: 28px; color: var(--color-text-light); font-size: .9rem; }
.faq-category { scroll-margin-top: var(--scroll-offset); margin-bottom: 64px; }
.faq-category-head { display: flex; gap: 16px; align-items: center; margin-bottom: 20px; }
.faq-category-head > span { display: grid; place-items: center; width: 44px; height: 44px; flex: 0 0 44px; border-radius: 13px; background: linear-gradient(145deg,var(--color-surface-brand),#cfe6df); color: var(--color-primary-dark); font-size: .8rem; font-weight: 800; box-shadow: inset 0 1px #fff; }
.faq-category-head svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.faq-icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.faq-category-head h2 { margin: 0; font-size: 1.65rem; }
.faq-category-head p { margin: 2px 0 0; color: var(--color-text-light); font-size: .9rem; }
.faq-list { border: var(--border-subtle); border-radius: var(--radius-lg); overflow: hidden; background: var(--color-surface); box-shadow: var(--shadow-card); }
.faq-item { scroll-margin-top: var(--scroll-offset); border-bottom: var(--border-subtle); }
.faq-item:last-child { border-bottom: 0; }
.faq-item summary { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 19px 22px; cursor: pointer; list-style: none; font-weight: 700; line-height: 1.35; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; display: grid; place-items: center; width: 27px; height: 27px; flex: 0 0 27px; border-radius: 50%; background: var(--color-page); color: var(--color-brand-hover); font-size: 1.25rem; transition: transform var(--duration-standard) var(--ease-standard), background var(--duration-standard) var(--ease-standard); }
.faq-item[open] summary { color: var(--color-primary-dark); }
.faq-item[open] summary::after { transform: rotate(45deg); background: #e5f2ee; }
.faq-answer { padding: 0 56px 20px 22px; animation: faq-open var(--duration-standard) var(--ease-standard) both; }
.faq-answer p { margin: 0 0 10px; color: var(--color-text-light); font-size: .94rem; }
.faq-answer a { font-size: .82rem; font-weight: 700; text-decoration: none; }
@keyframes faq-open { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: none; } }
.faq-dyk { display: flex; gap: 15px; margin-top: 18px; padding: 19px 22px; border: 1px solid #ecd2a8; border-radius: 13px; background: #fff5e5; color: #754815; }
.faq-dyk > span { font-size: 1.4rem; color: var(--color-accent); }
.faq-dyk strong { font-size: .85rem; letter-spacing: .04em; text-transform: uppercase; }
.faq-dyk p { margin: 2px 0 0; font-size: .9rem; }
.faq-empty { padding: 60px var(--container-gutter); text-align: center; }
.faq-empty > span { display: grid; place-items: center; width: 62px; height: 62px; margin: 0 auto 16px; border-radius: 50%; background: #e7f2ef; color: var(--color-primary-dark); font-size: 2rem; font-weight: 800; }
.faq-empty h2 { margin-bottom: 5px; }
.faq-empty p { margin: 0 0 22px; color: var(--color-text-light); }
.faq-item[hidden], .faq-category[hidden], .faq-empty[hidden] { display: none; }

@media (max-width: 900px) {
  .faq-library { grid-template-columns: 190px minmax(0,1fr); gap: 28px; }
}
@media (max-width: 720px) {
  .faq-mobile-nav { display: flex; flex-direction: column; gap: 6px; padding-top: 4px; padding-bottom: 18px; }
  .faq-mobile-nav label { font-size: .78rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--color-text-light); }
  .faq-mobile-nav select { width: 100%; padding: var(--space-3); border: 1px solid var(--color-border-strong); border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-text); font: var(--font-weight-semibold) .95rem inherit; }
  .faq-sidebar { display: none; }
  .faq-library { display: block; padding-top: 0; }
  .faq-category, .faq-item { scroll-margin-top: var(--scroll-offset); }
}
@media (max-width: 520px) {
  .faq-category-head h2 { font-size: 1.4rem; }
  .faq-item summary { padding: 17px 16px; }
  .faq-answer { padding: 0 16px 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .faq-item summary::after { transition: none; }
  .faq-answer { animation: none; }
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--scroll-offset);
}

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

body {
  margin: 0;
  font-family: var(--font-family-sans);
  font-size: var(--font-size-body);
  color: var(--color-text);
  background: var(--color-page);
  line-height: var(--line-height-body);
  /* .page-banner's height changes when it collapses to its compact state
     on scroll (see js/header-shrink.js and js/page-banner-sticky.js).
     Without this, the browser's scroll-anchoring tries to "helpfully"
     compensate for that shift by nudging scrollY itself — which can drag
     scrollY back under the shrink script's own expand threshold
     mid-animation, undoing the shrink it just did. */
  overflow-anchor: none;
}

h1, h2, h3 {
  font-family: var(--font-family-sans);
  line-height: var(--line-height-tight);
  margin-top: 0;
}

a {
  color: var(--color-brand-hover);
}

:where(a, button, input, select, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 3px;
}

/* ---------- Fade-up entrance animation ----------
   Add class="fade-up" to any element (any page) to have it ease up ~20px
   from 0 opacity into place — either right away if it's already on screen
   at load (hero heading/subhead/buttons, page-banner title), or the first
   time it scrolls into view otherwise. Wired up site-wide by js/fade-up.js.
   See CLAUDE.md for full usage.

   The hidden starting state only applies under the .js scope, which
   js/fade-up.js's very first inline <script> (in every page's <head>)
   stamps onto <html> before the page paints. If JavaScript fails to load
   or is disabled, that class never appears, this rule never matches, and
   .fade-up elements simply render normally — content is never stuck
   invisible waiting on a script that didn't run.

   :where(.js) keeps that scoping from adding any specificity (same trick
   already used for the site-wide :focus-visible rule above) — this rule
   stays a plain one-class selector, equal to .stat-item, .page-banner h1/p,
   and the .intro-gallery img hover rule it shares a few elements with. That
   matters: a couple of those elements carry their own `transition` too, and
   since `transition` doesn't merge across rules — whichever rule wins gets
   to keep ALL of its transitions, the other's are silently dropped — those
   few rules deliberately list opacity/transform themselves alongside their
   own properties instead of relying on this one to win. Search "also
   carries .fade-up" to find them if you're adding a transition to a new
   component that elements in css/style.css or CLAUDE.md mark as fade-up-able. */

:where(.js) .fade-up {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  transition: opacity var(--duration-reveal) var(--ease-out), transform var(--duration-reveal) var(--ease-out);
  transition-delay: var(--fade-up-delay, 0ms);
  will-change: opacity, transform;
}

.fade-up.in {
  opacity: 1;
  transform: none;
  will-change: auto;
}

@media (prefers-reduced-motion: reduce) {
  :where(.js) .fade-up {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ---------- Top bar ---------- */

.top-bar {
  background: var(--color-primary-dark);
  padding: var(--bar-padding-block) 0;
  position: sticky;
  top: 0;
  z-index: 11;
}

.top-bar-inner {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 20px;
}

.top-bar-link {
  display: flex;
  align-items: center;
  gap: 5px;
  color: #fff;
  text-decoration: none;
  font-size: var(--font-size-2xs);
  font-weight: 500;
}

.top-bar-link svg {
  width: 14px;
  height: 14px;
  fill: #fff;
}

.top-bar-link:hover,
.social-icon:hover {
  opacity: 0.8;
}

.social-icon {
  display: flex;
  align-items: center;
}

.social-icon svg {
  width: 16px;
  height: 16px;
  fill: #fff;
}

.social-icon-img {
  width: 16px;
  height: 16px;
  object-fit: contain;
  filter: brightness(0) invert(1);
}

/* ---------- Header / Nav ---------- */

.site-header {
  background: var(--color-page);
  border-bottom: var(--border-subtle);
  position: sticky;
  top: var(--sticky-header-top);
  z-index: 10;
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 4px;
  padding-bottom: 4px;
  max-width: var(--max-width-wide);
}

/* js/header-shrink.js still toggles .site-header.is-shrunk using a
   hysteresis band on window.scrollY (shrink past ~80px, re-expand below
   ~20px), but no rule below keys off it anymore — the navbar itself stays
   at full height at all times. That script is left running as-is (class
   toggle and --sticky-banner-top/--sticky-titles-subnav-top offset sync
   included) since .page-banner's own title-bar collapse below still reads
   --sticky-banner-top. */

.logo {
  display: flex;
  flex-direction: row;
  align-items: center;
  text-decoration: none;
  color: var(--color-primary-dark);
}

.logo-text-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.logo-text {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 0.85;
}

.logo-line {
  font-size: 2.5rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: #000;
}

.logo-line-ratters {
  color: var(--color-brand);
}

.logo-est {
  margin-top: -4px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #000;
}

.main-nav {
  display: flex;
  align-items: center;
  gap: 28px;
}

.main-nav a,
.nav-drop-toggle {
  text-decoration: none;
  color: var(--color-text);
  font-weight: 600;
  font-size: 0.95rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.nav-drop-toggle {
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  cursor: pointer;
}

.main-nav a.active,
.nav-item.has-active-link > .nav-drop-toggle {
  color: var(--color-primary-dark);
}

.nav-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--color-accent-button);
  color: #fff !important;
  /* This label is 600-weight / 0.95rem (inherited from .main-nav a) — not
     bold enough or large enough to qualify as WCAG "large text" (needs
     700+ weight at 18.66px+, or 24px+ at any weight), so it doesn't get
     the relaxed 3:1 threshold for free. --color-accent-button already
     clears 3:1 on its own; this small, low-opacity shadow (not a glow or
     outline — no text-stroke) adds real-world legibility on top of that
     without needing to darken the orange further. */
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.35);
  padding: var(--space-2) var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  box-shadow: 0 4px 10px rgba(131, 75, 13, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.2);
  transition: background var(--duration-standard) var(--ease-standard), box-shadow var(--duration-standard) var(--ease-standard);
}

.nav-cta:hover {
  background: var(--color-accent-button-hover);
  color: #fff !important;
  box-shadow: 0 8px 18px rgba(173, 99, 18, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

/* Deliberately no .nav-cta.active treatment: unlike a plain text nav link,
   this is already a distinct, colored button — stacking an "active page"
   indicator (ring or underline) on top of it just reads as a stray orange
   mark, most visible on get-started.html itself (the page it links to). */

.nav-cta:active {
  box-shadow: 0 2px 5px rgba(131, 75, 13, 0.22), inset 0 2px 3px rgba(0, 0, 0, 0.08);
}

.nav-cta:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 3px;
}

.nav-toggle-label {
  display: none;
  border: 0;
  background: transparent;
  font: inherit;
}

/* ---------- About dropdown ---------- */

.nav-item {
  position: relative;
}

.nav-item.has-dropdown > a::after,
.nav-item.has-dropdown > .nav-drop-toggle::after {
  content: " \25BE"; /* small down-caret */
  font-size: 0.7em;
}

/* Animated open/close: fades and slides 10px, consistent with the site's
   .fade-up motion language — opens with --ease-out, closes slightly faster
   with --ease-in, and (on close only) waits --duration-fast before the
   animation even starts, so quickly passing the cursor across the seam
   between the nav item and the dropdown doesn't cause a flicker. There is
   no dead zone to bridge for that crossing in the first place: .dropdown
   is a DOM child of .nav-item positioned flush at top:100%, so :hover
   already stays true continuously between them without a gap.

   display stays "flex" always — never "none" — because display can't be
   transitioned. visibility/pointer-events do the "actually inert and
   unclickable while closed" job instead: both flip the instant the
   dropdown opens, but only *after* the full close sequence (delay + fade)
   finishes when it closes, via transition-delay, so a closed or closing
   dropdown never blocks clicks on whatever is underneath it. */
.dropdown {
  display: flex;
  flex-direction: column;
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 190px;
  background: var(--color-surface);
  border: var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: var(--space-2) 0;
  box-shadow: var(--shadow-hover);
  z-index: 20;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-10px);
  transition: opacity var(--duration-fast) var(--ease-in) var(--duration-fast),
    transform var(--duration-fast) var(--ease-in) var(--duration-fast),
    visibility 0s linear calc(var(--duration-fast) * 2),
    pointer-events 0s linear calc(var(--duration-fast) * 2);
}

.nav-item.has-dropdown:hover .dropdown,
.nav-item.has-dropdown:focus-within .dropdown,
.nav-item.has-dropdown.is-open .dropdown {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(0);
  transition: opacity var(--duration-dropdown-open) var(--ease-out),
    transform var(--duration-dropdown-open) var(--ease-out),
    visibility 0s linear,
    pointer-events 0s linear;
}

.dropdown a {
  padding: 8px 18px;
  font-weight: 500;
  white-space: nowrap;
}

.dropdown a:hover {
  background: var(--color-bg);
  color: var(--color-primary-dark);
}

/* The global reduced-motion catch-all near the bottom of this file forces
   every transition-duration to ~0, but it can't reach transition-delay —
   without this, a reduced-motion user would still sit through the
   close-delay (transition-duration: 0.01ms *after* a real 150-300ms wait
   is still a real 150-300ms wait). This collapses the delay too, so open
   and close are both genuinely instant. */
@media (prefers-reduced-motion: reduce) {
  .dropdown {
    transition: none;
  }
}

/* ---------- Hero ---------- */

.hero {
  position: relative;
  overflow: hidden;
  color: #fff;
  min-height: 360px;
}

.hero-slide {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  padding: 56px 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 1.4s ease-in-out, visibility 1.4s ease-in-out;
}

.hero-slide.active {
  opacity: 1;
  visibility: visible;
  z-index: 1;
}

/* Darkest where the text sits (left), fading to fully transparent by 82%
   so the photo's right-hand side still reads bright and clear. Stronger
   in the middle band (30-60%) than a purely cosmetic overlay needs to be,
   so the heading/paragraph stay readable regardless of what's actually in
   that part of a given photo — not just tuned to look right on this one. */
.hero-slide-main {
  /* hero.jpg is a watermarked placeholder (to be replaced with a
     licensed photo later) — the dog's nose sits at roughly this point
     within the image file itself. When the photo is swapped, re-estimate
     the nose position and update just these two values. Kept within
     0%-100% deliberately: background-position is only guaranteed to keep
     a "cover"-sized image at full bleed (no gaps on any edge) for values
     in that range — going outside it (as a previous version of this rule
     did, combined with an oversized background-size to manufacture
     horizontal pan room) pushes the image past its own edge, opening a
     gap and, because the oversize made everything bigger, badly
     over-zooming the shot. Fixed size at plain "cover" and a plain
     position are what guarantee edge-to-edge coverage with no added
     zoom. */
  --hero1-focal-x: 47%;
  --hero1-focal-y: 44%;

  background-image: linear-gradient(
      to right,
      rgba(32, 29, 56, 0.85) 0%,
      rgba(32, 29, 56, 0.7) 30%,
      rgba(32, 29, 56, 0.32) 60%,
      rgba(32, 29, 56, 0) 82%
    ),
    url("../images/hero.jpg");
  background-size: cover;
  /* Puts the nose at its native fraction of the section, at every
     viewport width. Below ~720px the hero is taller/narrower than
     hero.jpg's own 3:2 aspect, so "cover" genuinely crops horizontally
     and this keeps the dog's face centered behind the text rather than
     showing a random slice of the photo. From roughly 900px up, the hero
     is wider/shorter than the photo's aspect, so "cover" is
     width-constrained — the image's full width always spans edge-to-edge
     with zero horizontal slack, meaning background-position-x has no
     visible effect at all there and the nose unavoidably sits at this
     same native fraction regardless of what position is requested. That
     puts the nose clearly right of the text column at 1920/1536px but
     only marginally at 1366px (where the text column happens to reach
     almost as far as 47%) — panning it further right isn't achievable
     without either the gap or the over-zoom this rule was fixed to
     remove, so this is as close as the hard constraints allow. */
  background-position: var(--hero1-focal-x) var(--hero1-focal-y);
  background-repeat: no-repeat;
}

.hero-slide-announcement {
  background-image: linear-gradient(
      to right,
      rgba(31, 40, 52, 0.88) 0%,
      rgba(31, 40, 52, 0.72) 30%,
      rgba(31, 40, 52, 0.34) 60%,
      rgba(31, 40, 52, 0) 82%
    ),
    url("../images/hero-announcement.jpg");
  background-size: cover;
  background-position: right 20%;
  background-repeat: no-repeat;
}

/* On very wide screens the hero's fixed height reveals a much thinner
   horizontal slice of the photo, so the crop that keeps the dog's head
   in frame on laptops rides too low and clips the ears. Shift up. */
@media (min-width: 1600px) {
  .hero-slide-announcement {
    background-position: right 14%;
  }
}

.hero-slide-announcement h2 {
  margin-bottom: 14px;
}

.btn-icon {
  width: 18px;
  height: 18px;
  fill: currentColor;
  flex-shrink: 0;
}

.hero-dots {
  position: absolute;
  bottom: 14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  gap: 8px;
}

.hero-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.6);
  background: transparent;
  padding: 0;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}

.hero-dot:hover {
  border-color: #fff;
}

.hero-dot.active {
  background: #fff;
  border-color: #fff;
}

.hero-inner {
  max-width: 700px;
  text-align: left;
  padding-left: clamp(24px, 8vw, 120px);
  padding-right: 20px;
}

.hero h1 {
  margin-bottom: 14px;
}

.hero-divider {
  width: 64px;
  height: 4px;
  border-radius: 2px;
  /* Brand teal, not orange — orange is reserved for the two "Get Started"
     buttons site-wide. The brighter (not the darker/hover) teal shade
     reads clearly against the hero's dark photo scrim, the same way the
     orange it replaces did. */
  background: var(--color-brand);
  margin: 0 0 20px;
}

.hero-sub {
  max-width: 520px;
  margin: 0 0 32px;
  font-size: 1.1rem;
  color: #ece8dd;
}

.hero-buttons {
  display: flex;
  gap: 16px;
  justify-content: flex-start;
  flex-wrap: wrap;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: var(--space-3) var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  text-decoration: none;
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 1.25;
  cursor: pointer;
  box-shadow: 0 4px 10px rgba(37, 42, 39, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  transition: background var(--duration-standard) var(--ease-standard), border-color var(--duration-standard) var(--ease-standard),
    color var(--duration-standard) var(--ease-standard), box-shadow var(--duration-standard) var(--ease-standard);
}

.btn:active {
  box-shadow: 0 2px 5px rgba(37, 42, 39, 0.15), inset 0 2px 3px rgba(0, 0, 0, 0.08);
}

.btn:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 3px;
}

/* Flat color that shifts to a darker shade on hover — no movement, no
   gradient. --color-accent/--color-accent-hover and --color-brand-hover/
   --color-brand-strong are the same token pairs used everywhere else on
   the site for these two colors, just applied flat instead of as a
   gradient here. */
.btn-primary {
  background: var(--color-accent-button);
  color: #fff;
  /* Same reasoning as .nav-cta's text-shadow: this label (.btn's 600
     weight / 1rem) doesn't qualify as WCAG large text either, so the
     shadow — not a darker orange — carries the rest of the real-world
     legibility. */
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.35);
}

.btn-primary:hover {
  background: var(--color-accent-button-hover);
  color: #fff;
  box-shadow: 0 8px 18px rgba(173, 99, 18, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

.btn-dark-teal {
  background: var(--color-brand-hover);
  color: var(--color-text-on-dark);
}

.btn-dark-teal:hover {
  background: var(--color-brand-strong);
  color: #fff;
  box-shadow: 0 8px 18px rgba(37, 83, 76, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

/* Hero carousel exception (all 3 hero buttons: "Find a Trial", "Rulebook",
   "Follow Along on Facebook"): hover to the lighter --color-brand (the
   same teal as the "RATTERS" wordmark) instead of darkening like every
   other .btn-dark-teal. Label stays white on hover by deliberate choice
   (contrast is lower on this hover state, ~2.15:1 — accepted as a
   temporary-state tradeoff, do not "fix" by darkening the label).
   box-shadow/transition aren't redeclared here, so they still come from
   the .btn-dark-teal:hover rule above unchanged. Shared via .hero-btn-teal
   so all 3 buttons update from one place; nothing outside the hero
   carousel uses this class. Same low-opacity text-shadow as .nav-cta/
   .btn-primary's labels, applied at all times (not just on :hover) since
   these buttons' base state is already fairly light (--color-brand-hover)
   and the shadow helps there too. */
.hero-btn-teal {
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.35);
}

.hero-btn-teal:hover {
  background: var(--color-brand);
}

.btn-outline {
  background: transparent;
  color: var(--color-brand-strong);
  border-color: var(--color-brand-hover);
}

.btn-outline:hover {
  background: var(--color-surface-brand);
  border-color: var(--color-brand-strong);
  color: var(--color-brand-strong);
  box-shadow: var(--shadow-hover);
}

/* A second, quieter accent for cases that need to sit directly next to a
   teal button (e.g. the Email/Phone icon buttons on a listing card) and
   read as visually distinct from it without reaching for orange, which is
   reserved for the two "Get Started" CTAs site-wide. */
.btn-cream {
  background: var(--color-surface-subtle);
  color: var(--color-brand-strong);
  border-color: var(--color-border-strong);
}

.btn-cream:hover {
  background: var(--color-surface);
  border-color: var(--color-brand-hover);
  color: var(--color-brand-hover);
  box-shadow: var(--shadow-hover);
}

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

/* ---------- Stats banner ---------- */

.stats-banner {
  background: var(--color-card-bg);
  border-bottom: 1px solid var(--color-border);
}

.stats-banner-inner {
  display: flex;
}

.stat-item {
  flex: 1 1 0;
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 22px var(--container-gutter);
  text-decoration: none;
  color: inherit;
  border-right: 1px solid var(--color-border);
  /* opacity/transform also carries the .fade-up entrance fade (this element
     also carries .fade-up) — transition doesn't merge across equal-
     specificity rules, so listing them here is what makes both this
     element's own hover transition AND its fade-up entrance animate. */
  transition: background var(--duration-standard) var(--ease-standard), box-shadow var(--duration-standard) var(--ease-standard), opacity var(--duration-reveal) var(--ease-out), transform var(--duration-reveal) var(--ease-out);
}

.stat-item:last-child {
  border-right: none;
}

a.stat-item:hover {
  background: linear-gradient(180deg, #f5fbf9 0%, #eaf5f1 100%);
  box-shadow: inset 0 -3px 0 rgba(63, 131, 128, 0.28);
}

a.stat-item:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: -3px;
  background: #f0f8f5;
}

.stat-icon {
  position: relative;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
  border-radius: 16px;
  color: var(--color-primary-dark);
  background: linear-gradient(145deg, #f2faf7, #d8ebe5);
  box-shadow: var(--shadow-icon), inset 0 1px 0 rgba(255, 255, 255, 0.85);
  transform: rotate(-2deg);
  transition: transform var(--duration-standard) var(--ease-standard), box-shadow var(--duration-standard) var(--ease-standard), background var(--duration-standard) var(--ease-standard);
}

.stat-icon::after {
  content: "";
  position: absolute;
  top: 6px;
  right: 6px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.22;
}

.stat-icon svg {
  width: 30px;
  height: 30px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform: rotate(2deg);
  transition: transform var(--duration-standard) var(--ease-standard);
}

a.stat-item:hover .stat-icon,
a.stat-item:focus-visible .stat-icon {
  background: linear-gradient(145deg, #f8fdfb, #cce5dc);
  box-shadow: 0 9px 18px rgba(37, 83, 76, 0.16), inset 0 1px 0 #fff;
  transform: translateY(-3px) rotate(0deg);
}

a.stat-item:hover .stat-icon svg,
a.stat-item:focus-visible .stat-icon svg {
  transform: rotate(0deg) scale(1.04);
}

.stat-text {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}

.stat-heading {
  font-weight: 800;
  font-size: 1.5rem;
  color: var(--color-primary-dark);
}

.stat-number {
  font-weight: 800;
  font-size: 1.5rem;
  color: var(--color-primary-dark);
}

.stat-caption {
  font-size: 0.85rem;
  color: var(--color-text-light);
  margin-top: 2px;
}

/* ---------- Intro ---------- */

.intro {
  padding: 60px var(--container-gutter);
}

.intro-layout {
  display: flex;
  gap: 48px;
  align-items: flex-start;
}

.intro-text {
  flex: 1 1 50%;
  min-width: 0;
  max-width: 560px;
}

.intro-gallery {
  flex: 1 1 50%;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 160px;
  grid-auto-flow: dense;
  gap: 14px;
  align-self: stretch;
}

.intro-gallery img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 10px;
  display: block;
}

.intro-gallery .gallery-featured {
  grid-row: span 2;
}

.intro h2 {
  margin-bottom: 16px;
}

.intro h3 {
  margin-top: 32px;
  margin-bottom: 16px;
}

.intro-list {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
}

.intro-list li {
  position: relative;
  padding-left: 26px;
  margin-bottom: 14px;
  line-height: 1.5;
}

.intro-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 9px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-accent);
}

.intro-list strong {
  color: var(--color-primary-dark);
}

/* ---------- Cards (quick links & news) ---------- */

.quick-links,
.news {
  padding: 20px 20px 60px;
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--grid-gap);
  margin-top: var(--space-5);
}

.card {
  background: var(--color-surface);
  border: var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--card-padding);
  box-shadow: var(--shadow-card);
}

.card h3 {
  font-size: 1.15rem;
  margin-bottom: 10px;
}

.card p {
  color: var(--color-text-light);
  font-size: 0.95rem;
}

.card-link {
  display: inline-block;
  margin-top: 8px;
  font-weight: 600;
  color: var(--color-accent);
  text-decoration: none;
}

.news-date {
  display: inline-block;
  font-size: var(--font-size-2xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-accent);
  margin-bottom: 8px;
}

/* ---------- Interior page banner ---------- */

.page-banner {
  background: var(--color-brand-hover);
  color: #fff;
  padding: var(--section-padding-block-compact) 0;
  text-align: center;
  position: sticky;
  top: var(--sticky-banner-top);
  z-index: 9;
  overflow: hidden;
  transition: padding 0.35s ease;
}

.page-banner-sentinel {
  height: 1px;
  margin-bottom: -1px;
}

/* Both also carry .fade-up on every interior page (the page-banner title
   doubles as that page's "hero" for the entrance animation). transition
   doesn't merge across equal-specificity rules, so opacity/transform have
   to be listed here too, alongside this element's own sticky-compact
   transition — otherwise whichever rule wins drops the other entirely. */
.page-banner h1 {
  margin-bottom: 8px;
  font-size: 2rem;
  transition: font-size 0.35s ease, margin-bottom 0.35s ease, opacity var(--duration-reveal) var(--ease-out), transform var(--duration-reveal) var(--ease-out);
}

.page-banner p {
  margin: 0;
  color: #eafffd;
  max-height: 40px;
  opacity: 1;
  /* opacity intentionally stays at the faster --duration-standard, not
     --duration-reveal: it's shared with the frequent sticky-compact
     collapse (scrolling this in and out of compact mode over and over
     should feel snappy), not just the one-time entrance fade — a minor,
     deliberate compromise for this one element. transform is fade-up's
     alone to set, so that gets the full entrance duration. */
  transition: max-height 0.35s ease, opacity var(--duration-standard) var(--ease-standard), margin-top 0.35s ease, transform var(--duration-reveal) var(--ease-out);
}

.page-banner.is-compact {
  padding: 12px 0;
}

.page-banner.is-compact h1 {
  font-size: 1.15rem;
  margin-bottom: 0;
}

.page-banner.is-compact p {
  max-height: 0;
  opacity: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .page-banner,
  .page-banner h1,
  .page-banner p {
    transition: none;
  }
}

/* ---------- Judges page ---------- */

.listing-section {
  padding: 40px 20px 70px;
}

.listing-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  grid-template-areas: "list map";
  gap: 32px;
  align-items: start;
}

.listing-list-column {
  grid-area: list;
  min-width: 0;
}

.listing-map-column {
  grid-area: map;
  min-width: 0;
  /* Must clear the sticky top-bar + nav + compact page-banner stack
     (~172px, z-index: 9) or the banner paints over the top of the map
     once both are stuck. Matches .faq-sidebar's top on the FAQ page and
     .game-panel's old value on the games page, which clear the same
     header stack. */
  position: sticky;
  top: var(--scroll-offset);
}

.site-map {
  width: 100%;
  height: 75vh;
  border: 1px solid var(--color-border);
  border-radius: 14px;
  box-shadow: 0 4px 12px rgba(37, 42, 39, 0.04);
  overflow: hidden;
  background: var(--color-bg);
}

/* Shown in place of the map itself (site-map.js swaps the container's
   content) if the Maps API fails to load or auth fails. Same icon-badge +
   message pattern as .faq-empty. */
.site-map.is-unavailable {
  display: flex;
  align-items: center;
  justify-content: center;
}

.site-map-fallback {
  max-width: 320px;
  padding: 24px;
  text-align: center;
}

.site-map-fallback-icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: #e7f2ef;
  color: var(--color-primary-dark);
}

.site-map-fallback-icon svg {
  width: 26px;
  height: 26px;
}

.site-map-fallback p {
  margin: 0;
  color: var(--color-text-light);
  font-size: 0.92rem;
}

@media (max-width: 900px) {
  .listing-layout {
    grid-template-columns: 1fr;
    grid-template-areas:
      "map"
      "list";
  }

  .listing-map-column {
    position: static;
  }

  .site-map {
    height: 300px;
  }

  /* Collapse the empty map area on mobile so the list moves up, instead
     of reserving a full 300px box for a one-line message. */
  .site-map.is-unavailable {
    height: auto;
  }

  .site-map-fallback {
    padding: 16px;
  }

}

/* Google Maps renders InfoWindow content directly into the page, so it
   picks up the site's font via inheritance — these just add spacing and
   brand color to match the rest of the page. */
.site-map-infowindow h3 {
  margin: 0 0 6px;
  font-size: 1rem;
  color: var(--color-primary-dark);
}

.site-map-infowindow p {
  margin: 0;
  font-size: 0.9rem;
}

.site-map-contact a {
  color: var(--color-primary-dark);
}

.site-map-contact-none {
  color: var(--color-text-light);
  font-style: italic;
}

/* Shared-pin info window: one .site-map-infowindow-entry per judge/club at
   that location, divided by a hairline, capped so a big group (e.g. five
   judges in one city) scrolls internally instead of overflowing the map. */
.site-map-infowindow--group {
  max-height: 260px;
  overflow-y: auto;
}

.site-map-infowindow-entry {
  padding: 10px 0;
  border-top: 1px solid var(--color-border);
}

.site-map-infowindow-entry:first-child {
  padding-top: 0;
  border-top: none;
}

/* Tint for whichever entry was reached via a specific card click, so it
   reads clearly among its co-located neighbors. Same selection color as
   .listing-card.is-selected. */
.site-map-infowindow-entry--active {
  background: var(--color-surface-brand);
  border-radius: 8px;
  padding: 8px 10px;
}

/* Hover/select highlight for a pin, driven by listing.js via
   setHighlighted(). Same scale-up + transition-speed convention as the
   games page's level-row hover (translateX nudge, 0.22s ease). Applied to
   the wrapper (not just the pin glyph) so the count badge scales with it. */
.site-map-pin-wrap {
  position: relative;
  display: inline-block;
  transition: transform var(--duration-hover) var(--ease-standard);
}

.site-map-pin-wrap--highlight {
  transform: scale(1.25);
}

@media (prefers-reduced-motion: reduce) {
  .site-map-pin-wrap {
    transition: none;
  }
}

.judges-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-bottom: 20px;
}

.filter-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1 1 200px;
}

.filter-field-search {
  flex: 2 1 260px;
}

.filter-field label {
  font-size: var(--font-size-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-light);
}

/* Base look, focus ring, and hover treatment for these inputs live in the
   shared form-controls rule further down — kept in one place instead of
   here and there so every filter/search field on the site stays in sync. */

.judges-count {
  font-size: 0.9rem;
  color: var(--color-text-light);
  margin: 0 0 12px;
}

/* ---------- Judges/Clubs card list ----------
   Store-locator layout: a scrollable stack of self-contained cards next
   to the sticky map (like the old table before it, and the accordion
   before that — this replaces the accordion's expand-to-see-more pattern
   with everything visible up front, since the wide table doesn't fit the
   narrower list column beside the map). */
.listing-card-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.listing-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: linear-gradient(155deg, #fff 0%, #fdfbf7 58%, #f7f3eb 100%);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 18px 20px;
  cursor: pointer;
  box-shadow: 0 3px 8px rgba(47, 48, 43, 0.065), inset 0 1px 0 #fff;
  /* transition lives in the shared "Cards: shared polish" rule further down
     (it needs to, to also cover this card's .fade-up fade-in correctly —
     see the comment there) */
}

.listing-card:hover {
  border-color: var(--color-primary-dark);
  box-shadow: 0 8px 18px rgba(37, 83, 76, 0.13);
  transform: translateY(-2px);
}

.listing-card:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.listing-card.is-selected {
  background: var(--color-surface-brand);
  border-color: var(--color-primary-dark);
  box-shadow: inset 0 0 0 1px var(--color-border-brand), 0 8px 18px rgba(37, 83, 76, 0.13);
}

.listing-card-top {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

/* Matches the number glyph rendered inside this card's map pin (see
   site-map.js) so the two are easy to pair up at a glance. */
.listing-card-number {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--color-primary-dark);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 700;
  box-shadow: 0 2px 6px rgba(37, 83, 76, 0.25);
}

.listing-card.is-selected .listing-card-number {
  background: var(--color-accent);
  box-shadow: 0 2px 6px rgba(173, 99, 18, 0.3);
}

/* flex: 1 so this fills whatever room the number badge and the actions
   (now a sibling here, not a separate row below) don't need — that's what
   pushes the actions flush to the card's right edge regardless of how
   long the name/location/secretary text is. */
.listing-card-heading {
  flex: 1 1 auto;
  min-width: 0;
}

.listing-card-name-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.listing-card-name {
  margin: 0;
  font-size: 1.05rem;
  overflow-wrap: break-word;
}

.listing-card-location {
  margin: 4px 0 0;
  font-size: 0.88rem;
  color: var(--color-text-light);
}

.listing-card-secretary {
  margin: 4px 0 0;
  font-size: 0.85rem;
  color: var(--color-text-light);
}

.listing-card-secretary strong {
  color: var(--color-text);
  font-weight: 600;
}

.listing-card-website {
  display: inline-block;
  margin-top: 6px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-primary-dark);
}

.listing-card-actions {
  display: flex;
  flex-wrap: wrap;
  flex-shrink: 0;
  justify-content: flex-start;
  gap: 10px;
}

/* Icon-only, not width-filling — small enough to read as a quiet secondary
   action, not a second headline CTA competing with the card itself. Fixed
   44px circle meets the site's tap-target minimum at every breakpoint on
   its own, so unlike the old text+icon pill this doesn't need a separate,
   larger mobile size. */
.listing-card-btn {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  padding: 0;
  border-radius: 50%;
}

.listing-card-actions-empty {
  margin: 0;
  flex-shrink: 0;
  white-space: nowrap;
  font-size: 0.85rem;
  color: var(--color-text-light);
  font-style: italic;
}

@media (prefers-reduced-motion: reduce) {
  .listing-card {
    transition: none;
  }

  .listing-card:hover {
    transform: none;
  }
}

.judge-category-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--color-bg);
  border: 1px solid var(--color-border-strong);
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}

.judges-no-results {
  display: none;
  padding: 24px 16px;
  text-align: center;
  color: var(--color-text-light);
}

/* ---------- Games page ---------- */

.games-section {
  padding: 40px 20px 70px;
  display: flex;
  align-items: flex-start;
  gap: 32px;
}

.games-groups {
  flex: 0 0 320px;
  margin-bottom: 28px;
}

.game-panel {
  flex: 1 1 auto;
  min-width: 0;
  /* Not sticky: the panel's own height is locked (see lockPanelHeight()
     in games.js) to fit the tallest game/level combo, so it's routinely
     taller than the viewport itself. A sticky element that tall has no
     room to hold a "top" offset within its container without its bottom
     blowing past the container's bottom edge — the browser then clamps
     it back up above the fixed header, cutting off the panel's own top
     (and whatever sidebar button triggered the navigation). Static flow
     avoids that clamp entirely. */
}

@media (max-width: 960px) {
  .games-section {
    flex-direction: column;
  }

  .games-groups {
    flex-basis: auto;
    width: 100%;
  }

  .game-panel {
    width: 100%;
  }
}

.games-group {
  margin-bottom: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--color-border);
}

.games-group:first-child {
  padding-top: 0;
  border-top: none;
}

.games-group-label {
  font-size: var(--font-size-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-accent);
  margin: 0 0 12px;
}

.games-group-main .game-square {
  border-color: rgba(63, 131, 128, 0.45);
}

.games-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 12px;
}

.game-square {
  position: relative;
  width: 100%;
  background: linear-gradient(155deg, #fff 0%, #fdfbf7 58%, #f7f3eb 100%);
  border: 1px solid #ddd6c8;
  border-radius: 12px;
  padding: 16px 10px;
  font-family: inherit;
  font-weight: 700;
  font-size: 0.95rem;
  text-align: center;
  color: var(--color-text);
  cursor: pointer;
  box-shadow: 0 3px 8px rgba(47, 48, 43, 0.065), inset 0 1px 0 #fff;
  /* transition lives in the shared "Cards: shared polish" rule further down
     (it needs to, to also cover this tile's .fade-up fade-in correctly —
     see the comment there) */
}

.game-square:not(.active):hover {
  border-color: var(--color-primary-dark);
  background: linear-gradient(180deg, #f7fcfa 0%, #e8f4f0 100%);
  color: var(--color-primary-dark);
  box-shadow: 0 8px 18px rgba(37, 83, 76, 0.13), inset 0 -3px 0 rgba(63, 131, 128, 0.18);
  transform: translateY(-2px);
}

.game-square:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 3px;
  border-color: var(--color-primary-dark);
}

.game-square:active {
  transform: translateY(0);
  box-shadow: 0 2px 6px rgba(37, 83, 76, 0.12);
}

.game-square.active {
  background: var(--gradient-teal);
  border-color: var(--color-primary-dark);
  color: #fff;
  box-shadow: 0 7px 16px rgba(37, 83, 76, 0.24), inset 0 1px 0 rgba(255, 255, 255, 0.22);
  transform: translateY(-1px);
}

.game-square.active::before {
  content: "";
  position: absolute;
  inset: 7px auto 7px 0;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: rgba(255, 255, 255, 0.72);
  box-shadow: 0 0 8px rgba(255, 255, 255, 0.28);
}

.game-square.active:hover {
  box-shadow: 0 10px 21px rgba(37, 83, 76, 0.29), inset 0 1px 0 rgba(255, 255, 255, 0.25);
  transform: translateY(-2px);
}

.game-panel {
  scroll-margin-top: var(--scroll-offset);
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 28px;
  overflow: hidden;
}

.panel-content {
  transition: transform var(--duration-standard) var(--ease-standard), opacity var(--duration-standard) var(--ease-standard);
}

.panel-content.slide-out-left {
  transform: translateX(-30px);
  opacity: 0;
}

.panel-content.slide-out-right {
  transform: translateX(30px);
  opacity: 0;
}

.panel-content.slide-in-left {
  transition: none;
  transform: translateX(-30px);
  opacity: 0;
}

.panel-content.slide-in-right {
  transition: none;
  transform: translateX(30px);
  opacity: 0;
}

.panel-inner {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  align-items: flex-start;
}

.panel-text {
  flex: 1 1 280px;
  min-width: 0;
}

.panel-summary {
  flex: 1 1 300px;
  min-width: 0;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 20px;
  overflow: hidden;
}

@keyframes panel-summary-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.panel-summary.summary-animate {
  animation: panel-summary-in var(--duration-hover) var(--ease-standard);
}

.panel-summary-title {
  margin: 0 0 10px;
  font-size: 1rem;
  color: var(--color-primary-dark);
}

.panel-summary-bullets {
  margin: 0;
  padding-left: 20px;
  font-size: 0.92rem;
  color: var(--color-text);
  line-height: 1.5;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.panel-summary-points {
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--color-border);
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.panel-summary-image {
  display: block;
  max-width: 100%;
  height: auto;
  margin-top: 14px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
}

.panel-header h2 {
  margin-bottom: 10px;
}

.panel-desc {
  color: var(--color-text-light);
  margin-bottom: 18px;
}

.titles-heading {
  font-size: var(--font-size-2xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-light);
  margin-bottom: 10px;
}

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

.title-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border-radius: 8px;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard), transform var(--duration-hover) var(--ease-standard);
}

/* No transform here: .ribbon-icon inside already lifts/rotates/scales on
   this same hover (below) — moving both the row and its icon at once reads
   as busy. One motion per hover, same rule as the medallions/gems. */
.title-row:not(.active):hover {
  background: var(--color-bg);
}

.title-row.active {
  background: var(--color-surface-brand);
  box-shadow: inset 0 0 0 1px var(--color-border-brand);
}

.title-row:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.ribbon-icon {
  display: inline-flex;
  width: 26px;
  height: 32px;
  flex-shrink: 0;
  filter: drop-shadow(0 2px 2px rgba(35, 38, 35, 0.16));
  transition: transform var(--duration-hover) var(--ease-standard), filter var(--duration-hover) var(--ease-standard);
}

.ribbon-icon-svg {
  width: 100%;
  height: 100%;
}

.title-row:hover .ribbon-icon,
.title-row.active .ribbon-icon {
  transform: translateY(-1px) scale(1.07) rotate(-2deg);
  filter: drop-shadow(0 3px 3px rgba(35, 38, 35, 0.2));
}

.title-row.active .award-trophy {
  filter: drop-shadow(0 0 3px rgba(232, 185, 35, 0.42));
}

.title-name {
  font-weight: 700;
  font-size: 0.92rem;
}

.game-note {
  font-size: 0.85rem;
  color: var(--color-text-light);
  font-style: italic;
  margin-top: 6px;
}

@media (prefers-reduced-motion: reduce) {
  .title-row,
  .game-square,
  .ribbon-icon {
    transition: none;
  }

  .title-row:hover .ribbon-icon,
  .title-row.active .ribbon-icon,
  .game-square:not(.active):hover,
  .game-square.active,
  .game-square.active:hover {
    transform: none;
  }

  .panel-summary.summary-animate {
    animation: none;
  }
}

/* ---------- Rat Care page ---------- */

.care-intro {
  max-width: 720px;
  text-align: center;
  padding: 40px 20px 10px;
  font-size: 1.05rem;
  color: var(--color-text-light);
}

.welfare-pillars {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  padding: 40px 20px;
}

/* Surface, border, radius, and padding come from the shared card rules
   further down — this only needs the one thing that makes it distinct
   from the other card types that share that treatment. */
.welfare-pillar {
  text-align: center;
}

.pillar-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
  border-radius: 18px;
  margin-bottom: 17px;
  color: var(--color-primary-dark);
  box-shadow: var(--shadow-icon);
  transform: rotate(-2deg);
}

.pillar-icon::after {
  content: "";
  position: absolute;
  top: 7px;
  right: 7px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.22;
}

.pillar-icon svg {
  width: 33px;
  height: 33px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform: rotate(2deg);
}

.pillar-icon-rose {
  color: #a4525f;
  background: linear-gradient(145deg, #fff6f7, #f3dadd);
}

.pillar-icon-mint {
  color: #34765b;
  background: linear-gradient(145deg, #f0fbf5, #d5eddf);
}

.pillar-icon-amber {
  color: #9a6417;
  background: linear-gradient(145deg, #fff8e9, #f8e2b9);
}

.pillar-icon-blue {
  color: #3d6f94;
  background: linear-gradient(145deg, #f2f8fd, #d6e7f4);
}

.welfare-pillar h3 {
  font-size: 1.05rem;
  margin-bottom: 8px;
}

.welfare-pillar p {
  font-size: 0.9rem;
  color: var(--color-text-light);
  margin: 0;
}

.care-blocks {
  padding: 20px 20px 60px;
  display: flex;
  flex-direction: column;
  gap: 56px;
}

.care-block {
  display: flex;
  align-items: center;
  gap: 40px;
}

.care-block-reverse {
  flex-direction: row-reverse;
}

.care-block-image {
  width: 420px;
  max-width: 45%;
  flex-shrink: 0;
  border-radius: 14px;
  height: auto;
}

.care-block-text {
  flex: 1 1 auto;
  min-width: 0;
}

.care-block-text h2 {
  margin-bottom: 14px;
}

.care-block-text p {
  margin-bottom: 14px;
  line-height: 1.6;
}

.care-block-text p:last-child {
  margin-bottom: 0;
}

.care-closing {
  text-align: center;
  max-width: 640px;
  padding: 20px 20px 70px;
}

.care-closing h2 {
  margin-bottom: 14px;
}

.care-closing p {
  color: var(--color-text-light);
  margin-bottom: 24px;
}

/* ---------- Get Started page ---------- */

.get-started-section {
  padding: 48px 20px 70px;
  max-width: 780px;
}

.welcome-block {
  text-align: center;
  margin-bottom: 40px;
}

.welcome-icons {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-bottom: 14px;
}

.welcome-icon {
  width: 64px;
  height: 64px;
}

.welcome-block h2 {
  margin-bottom: 12px;
}

.welcome-block p {
  color: var(--color-text-light);
  max-width: 560px;
  margin: 0 auto;
}

.steps-list {
  list-style: none;
  margin: 0 0 32px;
  padding: 0;
  counter-reset: none;
}

.step {
  display: flex;
  gap: 18px;
  padding: 20px 0;
  border-top: 1px solid var(--color-border);
}

.step:first-child {
  border-top: none;
}

.step-number {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--color-primary-dark);
  color: #fff;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.step-body h3 {
  margin-bottom: 6px;
  font-size: 1.1rem;
}

.step-body p {
  margin: 0 0 6px;
  color: var(--color-text-light);
}

.step-note {
  font-size: 0.88rem;
  font-style: italic;
}

.step-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  font-weight: 600;
  color: var(--color-primary-dark);
  text-decoration: none;
}

.step-link:hover {
  text-decoration: underline;
}

.step-link svg {
  width: 18px;
  height: 18px;
  fill: var(--color-primary-dark);
}

.callout-note {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  background: #fdf3e4;
  border: 1px solid #ecd6ab;
  border-left: 4px solid var(--color-accent);
  border-radius: 8px;
  padding: 16px 18px;
  margin-bottom: 40px;
}

.callout-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  fill: var(--color-accent);
  margin-top: 2px;
}

.callout-note p {
  margin: 0;
  font-size: 0.92rem;
}

.secreterrier-cta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 20px;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 24px;
  margin-bottom: 56px;
}

.secreterrier-cta-logo {
  width: 56px;
  height: 56px;
  flex-shrink: 0;
}

.secreterrier-cta div {
  flex: 1 1 240px;
}

.secreterrier-cta h3 {
  margin-bottom: 4px;
}

.secreterrier-cta p {
  margin: 0;
  color: var(--color-text-light);
  font-size: 0.92rem;
}

.whats-next h2 {
  margin-bottom: 8px;
  text-align: center;
}

/* ---------- Footer ---------- */

.site-footer {
  background: var(--color-primary-dark);
  color: #d9d4c6;
  padding: 6px 0;
  margin-top: 40px;
}

.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 0.9rem;
}

.footer-inner p {
  margin: 0;
}

/* ---------- Nav collapse ----------
   Wider than the general mobile breakpoint: with 7 links plus the
   "Get Started" button, the nav needs to drop to the hamburger menu
   well before the page's other content needs to restack.
------------------------------------------------------------------ */

@media (max-width: 1180px) {
  .nav-toggle-label {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: var(--radius-sm);
    font-size: 1.6rem;
    cursor: pointer;
    color: var(--color-primary-dark);
  }

  .main-nav {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.35s ease;
    gap: 0;
  }

  .main-nav a,
  .nav-drop-toggle {
    display: block;
    width: 100%;
    text-align: left;
    padding: 12px 0;
    border-top: 1px solid var(--color-border);
  }

  .nav-cta {
    text-align: center;
    margin: 14px 0 4px;
    padding: 12px 0;
    border-top: none;
  }

  /* Capped to the viewport (minus the sticky top-bar + header stack above
     it, via the same --sticky-banner-top token that stack's own height is
     already measured with elsewhere) instead of a flat 1000px, so a long
     open menu — especially with a dropdown expanded inside it — scrolls
     within itself past that point rather than extending below the screen
     with no way to reach the rest of it except scrolling the page behind
     it (which js/site-chrome.js locks while the menu is open anyway). */
  .main-nav.is-open {
    /* 100vh fallback for browsers without dvh support; the dvh version
       below overrides it wherever it's understood. 100vh alone uses the
       *largest* possible viewport (address bar hidden), which is taller
       than what's actually visible whenever the address bar is showing —
       so the menu was letting itself grow past the real visible area
       without triggering its own scrollbar, and the page behind it can't
       scroll to compensate (see body.mobile-nav-lock). 100dvh tracks the
       real, current viewport instead. */
    max-height: calc(100vh - var(--sticky-banner-top) - 16px);
    max-height: calc(100dvh - var(--sticky-banner-top) - 16px);
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Without this, the scrollable area ends exactly at the last item's
       edge, so you can scroll its top into view but never far enough to
       clear it (or tap it) — most obvious on .nav-cta, the last item,
       especially once a submenu like Rules/Resources is expanded above it
       and pushes it further down. */
    padding-bottom: var(--space-6);
  }

  /* Mobile dropdowns use the same explicit disclosure behavior — only an
     explicit tap on the toggle (handled by js/site-chrome.js, which
     toggles .is-open) opens one; hover/focus-within are suppressed here
     exactly as before this component was animated, since a focused
     .nav-drop-toggle <button> already opens via Enter/Space triggering
     that same click handler, and the whole mobile nav is hidden behind
     the hamburger toggle until it's expanded regardless.

     This is an in-flow accordion, not a floating flyout, so unlike the
     desktop version it collapses via max-height (matching .main-nav's own
     open/close mechanism above) instead of opacity/transform alone — those
     wouldn't free up the vertical space a "closed" dropdown would
     otherwise still occupy in the stacked mobile menu. */
  .dropdown {
    display: flex;
    position: static;
    min-width: 0;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
    max-height: 0;
    opacity: 0;
    visibility: visible;
    pointer-events: none;
    transform: none;
    overflow: hidden;
    transition: max-height var(--duration-fast) var(--ease-in), opacity var(--duration-fast) var(--ease-in);
  }

  .nav-item.has-dropdown:hover > .dropdown,
  .nav-item.has-dropdown:focus-within > .dropdown {
    max-height: 0;
    opacity: 0;
    pointer-events: none;
  }

  .nav-item.has-dropdown.is-open > .dropdown {
    max-height: 500px;
    opacity: 1;
    pointer-events: auto;
    transition: max-height var(--duration-dropdown-open) var(--ease-out), opacity var(--duration-dropdown-open) var(--ease-out);
  }

  .nav-drop-toggle[aria-expanded="true"]::after {
    transform: rotate(180deg);
  }

  .dropdown a {
    padding: 10px 0 10px 20px;
    font-size: 0.9rem;
    font-weight: 500;
  }

  .header-inner {
    flex-wrap: wrap;
  }
}

/* ---------- Club/Judge Resources page ---------- */

.judge-resources-section {
  padding: 40px 20px 70px;
}

.judge-hero-card {
  display: flex;
  align-items: center;
  gap: 28px;
  background: var(--color-surface-brand);
  border: 1px solid #d3e8de;
  border-radius: 14px;
  padding: 32px;
}

.judge-hero-icon {
  position: relative;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 84px;
  height: 84px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 23px;
  background: var(--gradient-teal);
  box-shadow: 0 9px 20px rgba(37, 83, 76, 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.2);
  transform: rotate(-2deg);
}

.judge-hero-icon::after {
  content: "";
  position: absolute;
  top: 10px;
  right: 10px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #fff;
  opacity: 0.25;
}

.judge-hero-icon svg {
  width: 47px;
  height: 47px;
  fill: none;
  stroke: #fff;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform: rotate(2deg);
}

.judge-hero-text h2 {
  margin-bottom: 8px;
}

.judge-hero-text p {
  color: var(--color-text-light);
  margin-bottom: 18px;
}

.essentials-outline {
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 32px;
  margin-bottom: 48px;
}

.essentials-heading {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 24px;
}

.essentials-star svg {
  width: 26px;
  height: 26px;
  fill: var(--color-accent);
}

.essentials-heading h2 {
  margin-bottom: 2px;
}

.essentials-heading p {
  color: var(--color-text-light);
  margin: 0;
}

.essentials-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

.essential-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 22px;
}

.essential-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 58px;
  height: 58px;
  border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
  border-radius: 17px;
  margin-bottom: 17px;
  color: var(--color-primary-dark);
  box-shadow: var(--shadow-icon);
  transform: rotate(-2deg);
}

.essential-icon::after {
  content: "";
  position: absolute;
  top: 7px;
  right: 7px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.22;
}

.essential-icon svg {
  width: 31px;
  height: 31px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform: rotate(2deg);
}

.essential-icon-amber {
  color: #9a6417;
  background: linear-gradient(145deg, #fff8e9, #f8e2b9);
}

.essential-icon-lavender {
  color: #775296;
  background: linear-gradient(145deg, #faf5ff, #e8d9f4);
}

.essential-icon-mint {
  color: #34765b;
  background: linear-gradient(145deg, #f0fbf5, #d5eddf);
}

.essential-icon-blue {
  color: #3d6f94;
  background: linear-gradient(145deg, #f2f8fd, #d6e7f4);
}

.essential-card h3 {
  font-size: 1.05rem;
  margin-bottom: 6px;
}

.essential-card p {
  color: var(--color-text-light);
  font-size: 0.9rem;
  margin-bottom: 16px;
}

.btn-small {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 16px;
  font-size: 0.85rem;
  margin-top: auto;
}

.essential-btn-icon {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}

.essential-pages {
  margin-top: 10px;
  font-size: var(--font-size-2xs);
  color: var(--color-text-light);
}

/* ---------- Mobile ---------- */

@media (max-width: 720px) {
  .card-grid {
    grid-template-columns: 1fr;
  }

  .welfare-pillars {
    grid-template-columns: 1fr 1fr;
  }

  .judge-hero-card {
    flex-direction: column;
    text-align: center;
  }

  .ckc-announcement {
    flex-direction: column;
    text-align: center;
  }

  .titles-gem-spotlight {
    flex-direction: column;
    text-align: center;
  }

  .titles-xrex-header {
    flex-direction: column;
    text-align: center;
  }

  .essentials-outline {
    padding: 20px;
  }

  .essentials-grid {
    grid-template-columns: 1fr 1fr;
  }

  .care-block,
  .care-block-reverse {
    flex-direction: column;
    align-items: stretch;
    gap: 20px;
  }

  .care-block-image {
    width: 100%;
    max-width: none;
  }

  .intro-layout {
    flex-direction: column;
  }

  .intro-text {
    max-width: none;
  }

  .intro-gallery {
    width: 100%;
  }

  .top-bar-inner {
    gap: 14px;
  }

  .stats-banner-inner {
    flex-direction: column;
  }

  .stat-item {
    border-right: none;
    border-bottom: 1px solid var(--color-border);
  }

  .stat-item:last-child {
    border-bottom: none;
  }
}

/* ---------- PDF viewer modal ---------- */

.pdf-modal {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 14, 0.75);
  z-index: 200;
  align-items: center;
  justify-content: center;
  padding: 30px;
}

.pdf-modal.is-open {
  display: flex;
}

.pdf-modal-inner {
  background: var(--color-card-bg);
  width: 100%;
  max-width: 900px;
  height: 100%;
  max-height: 850px;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}

.pdf-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 18px;
  background: var(--color-primary-dark);
  color: #fff;
}

.pdf-modal-title {
  font-weight: 700;
  font-size: 1rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pdf-modal-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-shrink: 0;
}

.pdf-modal-open {
  color: #fff;
  font-size: 0.85rem;
  text-decoration: underline;
  white-space: nowrap;
}

.pdf-modal-close {
  background: none;
  border: none;
  color: #fff;
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
}

.pdf-modal-frame {
  flex: 1;
  width: 100%;
  border: none;
}

body.pdf-modal-lock {
  overflow: hidden;
}

/* Same background-scroll lock, for the open mobile nav menu (see
   .main-nav.is-open and js/site-chrome.js). */
body.mobile-nav-lock {
  overflow: hidden;
}

@media (max-width: 720px) {
  .pdf-modal {
    padding: 0;
  }

  .pdf-modal-inner {
    max-width: none;
    max-height: none;
    border-radius: 0;
  }
}

/* ---------- Titles page ---------- */

.ckc-announcement {
  display: flex;
  align-items: center;
  gap: 24px;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 14px var(--container-gutter);
  margin-top: 32px;
}

.ckc-announcement-logo {
  width: 96px;
  height: 96px;
  flex-shrink: 0;
  object-fit: contain;
}

.ckc-announcement-text h2 {
  font-size: 1.3rem;
  margin-bottom: 6px;
}

.ckc-announcement-text p {
  color: var(--color-text-light);
  margin: 0;
}

.ckc-announcement-text a {
  color: var(--color-primary-dark);
  font-weight: 600;
}

.titles-subnav {
  border-bottom: 1px solid var(--color-border);
  background: var(--color-bg);
  position: sticky;
  top: var(--sticky-titles-subnav-top);
  z-index: 5;
}

.titles-subnav-inner {
  display: flex;
  align-items: center;
  gap: 22px;
  height: 52px;
  overflow-x: auto;
}

.titles-subnav-inner a {
  color: var(--color-text-light);
  text-decoration: none;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  padding: 6px 2px;
  border-bottom: 2px solid transparent;
  transition: color var(--duration-fast) var(--ease-standard), border-bottom-color var(--duration-fast) var(--ease-standard);
}

.titles-subnav-inner a:hover {
  color: var(--color-primary-dark);
  border-bottom-color: var(--color-primary-dark);
}

.titles-section {
  padding: 56px 20px;
  scroll-margin-top: var(--scroll-offset-titles);
}

.titles-section + .titles-section {
  border-top: 1px solid var(--color-border);
}

.titles-sec-head {
  margin-bottom: 32px;
  max-width: 62ch;
}

.titles-eyebrow {
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-primary-dark);
  font-weight: 700;
}

.titles-sec-head h2 {
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  margin: 6px 0 8px;
}

.titles-sec-head p {
  color: var(--color-text-light);
}

/* ladder */

.titles-ladder {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 14px;
  align-items: end;
}

.titles-rung {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 18px 16px 16px;
  position: relative;
}

.titles-rung .titles-code {
  font-size: 1.5rem;
  font-weight: 800;
  color: var(--color-primary-dark);
}

.titles-rung-name {
  font-weight: 700;
  font-size: 0.95rem;
  margin: 2px 0 10px;
}

.titles-rung ul {
  list-style: none;
  font-size: 0.82rem;
  color: var(--color-text-light);
  padding: 0;
  margin: 0;
}

.titles-rung li {
  padding: 3px 0;
  border-top: 1px dashed var(--color-border);
}

.titles-rung li strong {
  color: var(--color-text);
}

.titles-step {
  position: absolute;
  top: -11px;
  left: 16px;
  background: var(--color-primary-dark);
  color: #fff;
  font-weight: 700;
  font-size: 0.72rem;
  padding: 2px 10px;
  border-radius: 99px;
}

.titles-rung:nth-child(1) { padding-bottom: 16px; }
.titles-rung:nth-child(2) { padding-bottom: 34px; }
.titles-rung:nth-child(3) { padding-bottom: 52px; }
.titles-rung:nth-child(4) { padding-bottom: 70px; }
.titles-rung:nth-child(5) { padding-bottom: 88px; }

/* XREX pinnacle */

.titles-pinnacle {
  margin-top: 26px;
  background: var(--color-text);
  color: #f4efe2;
  border-radius: 18px;
  border: 2px solid var(--color-accent);
  padding: 34px 34px 30px;
  position: relative;
  overflow: hidden;
  scroll-margin-top: var(--scroll-offset-titles);
  display: grid;
  grid-template-columns: minmax(300px, 380px) 1fr;
  gap: 34px;
}

.titles-pinnacle::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(600px 220px at 12% 0%, rgba(224, 142, 43, 0.22), transparent 70%);
  pointer-events: none;
}

.titles-xrex-header {
  display: flex;
  align-items: center;
  gap: 20px;
}

.titles-xrex-header-text {
  min-width: 0;
}

.titles-xrex-trophy {
  position: relative;
  flex-shrink: 0;
  width: 90px;
  height: 86px;
  filter: drop-shadow(0 6px 6px rgba(0, 0, 0, 0.32));
  transition: transform 0.3s ease, filter 0.3s ease;
}

.titles-xrex-trophy::after {
  content: "";
  position: absolute;
  top: 5px;
  left: 8px;
  width: 14px;
  height: 54px;
  background: rgba(255, 255, 255, 0.55);
  filter: blur(1px);
  transform: rotate(32deg);
  opacity: 0;
  pointer-events: none;
  transition: transform 0.5s ease, opacity var(--duration-standard) var(--ease-standard);
}

.titles-xrex-trophy svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: none;
  stroke: url(#xrex-trophy-gold);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.titles-xrex-trophy .titles-xrex-star {
  fill: url(#xrex-trophy-gold);
  stroke-width: 1.3;
}

.titles-pinnacle:hover .titles-xrex-trophy {
  transform: translateY(-4px) rotate(-3deg) scale(1.07);
  filter: drop-shadow(0 10px 9px rgba(0, 0, 0, 0.4)) saturate(1.12);
}

.titles-pinnacle:hover .titles-xrex-trophy::after {
  opacity: 0.75;
  transform: translateX(59px) rotate(32deg);
}

.titles-ribbon {
  display: inline-block;
  background: var(--color-accent);
  color: var(--color-text);
  font-weight: 800;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 4px 14px;
  border-radius: 99px;
  margin-bottom: 14px;
}

.titles-big-code {
  font-size: clamp(2.6rem, 6vw, 4rem);
  font-weight: 800;
  line-height: 1;
  color: var(--color-accent);
}

.titles-big-name {
  font-weight: 700;
  margin-top: 6px;
  font-size: 1.05rem;
}

.titles-subline {
  color: #c9c2b0;
  font-size: 0.9rem;
  margin-top: 10px;
  max-width: 26ch;
}

.titles-pinnacle h3 {
  font-size: 1rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: 14px;
  font-weight: 700;
}

.titles-req {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}

.titles-req div {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(224, 142, 43, 0.35);
  border-radius: 12px;
  padding: 14px;
}

.titles-req-n {
  font-weight: 800;
  font-size: 1.7rem;
  color: var(--color-accent);
}

.titles-req p {
  font-size: 0.84rem;
  color: #ddd6c4;
  margin-top: 4px;
}

.titles-fine {
  font-size: var(--font-size-2xs);
  color: #a49d8b;
  margin-top: 16px;
}

.titles-fine b {
  color: #ddd6c4;
}

/* medallions */

.titles-medals {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}

.titles-medal {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 28px 20px 20px;
  text-align: center;
  /* transition lives in the shared "Cards: shared polish" rule further down
     (it needs to, to also cover this card's .fade-up fade-in correctly —
     see the comment there) */
}

.titles-disc {
  position: relative;
  isolation: isolate;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  margin: 8px auto 14px;
  border: 3px solid var(--medal-rim);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 1.15rem;
  color: var(--medal-ink);
  background:
    radial-gradient(circle at 34% 28%, rgba(255, 255, 255, 0.75) 0 7%, transparent 8%),
    linear-gradient(145deg, var(--medal-light) 5%, var(--medal-mid) 48%, var(--medal-dark) 100%);
  box-shadow: 0 5px 10px rgba(48, 38, 25, 0.2), inset 0 0 0 3px rgba(255, 255, 255, 0.3),
    inset 0 -5px 8px rgba(68, 43, 18, 0.14);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4);
  transition: transform 0.28s ease, box-shadow 0.28s ease;
}

.titles-disc::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 11px;
  top: -27px;
  width: 34px;
  height: 33px;
  background: linear-gradient(90deg, #326c69 0 28%, #faf4e7 28% 38%, #e08e2b 38% 62%, #faf4e7 62% 72%, #326c69 72%);
  clip-path: polygon(0 0, 100% 0, 88% 100%, 50% 82%, 12% 100%);
  box-shadow: inset 0 -4px 5px rgba(0, 0, 0, 0.12);
}

.titles-disc::after {
  content: "";
  position: absolute;
  inset: 5px;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 50%;
  pointer-events: none;
}

.titles-medal-bronze .titles-disc {
  --medal-light: #efbf91; --medal-mid: #c7834f; --medal-dark: #8b4d27;
  --medal-rim: #9b5b32; --medal-ink: #633617;
}
.titles-medal-silver .titles-disc {
  --medal-light: #f8fafb; --medal-mid: #c9d0d5; --medal-dark: #8e989f;
  --medal-rim: #9ca6ad; --medal-ink: #566068;
}
.titles-medal-gold .titles-disc {
  --medal-light: #fff0a8; --medal-mid: #e5b84f; --medal-dark: #a97722;
  --medal-rim: #b8892c; --medal-ink: #705013;
}
.titles-medal-platinum .titles-disc {
  --medal-light: #ffffff; --medal-mid: #d8e2e7; --medal-dark: #9cabb4;
  --medal-rim: #aebbc3; --medal-ink: #53636d;
}

.titles-medal:hover {
  border-color: var(--color-border-strong);
  box-shadow: 0 9px 22px rgba(48, 38, 25, 0.09);
}

.titles-medal:hover .titles-disc {
  transform: translateY(-4px) rotate(-3deg) scale(1.04);
  box-shadow: 0 10px 18px rgba(48, 38, 25, 0.26), inset 0 0 0 3px rgba(255, 255, 255, 0.38),
    inset 0 -5px 8px rgba(68, 43, 18, 0.12);
}

.titles-medal-name {
  font-weight: 700;
}

.titles-pts {
  color: var(--color-primary-dark);
  font-weight: 800;
  font-size: 1.2rem;
}

.titles-callout {
  margin-top: 18px;
  background: var(--color-surface-brand);
  border: 1px solid var(--color-border-brand);
  border-radius: 14px;
  padding: 16px 20px;
  font-size: 0.92rem;
  color: var(--color-primary-dark);
}

.titles-callout code {
  font-weight: 700;
  background: #fff;
  padding: 1px 7px;
  border-radius: 6px;
  border: 1px solid var(--color-border-brand);
}

/* games */

.titles-games-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}

.titles-gcard {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 18px;
}

.titles-gcard h3 {
  font-size: 0.85rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-primary-dark);
  margin-bottom: 10px;
}

.titles-gcard ul {
  list-style: none;
  font-size: 0.88rem;
  padding: 0;
  margin: 0;
}

.titles-gcard li {
  padding: 4px 0;
  border-top: 1px dashed var(--color-border);
}

.titles-gcard li:first-of-type {
  border-top: none;
}

.titles-tag {
  display: block;
  font-size: 0.78rem;
  color: var(--color-text-light);
  margin-top: 10px;
}

/* versatility */

.titles-formula {
  display: flex;
  align-items: stretch;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.titles-chip {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 14px 18px;
  flex: 1;
  min-width: 180px;
}

.titles-chip-lbl {
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-light);
}

.titles-chip-val {
  font-weight: 800;
  font-size: 1.15rem;
  color: var(--color-primary-dark);
}

.titles-op {
  display: flex;
  align-items: center;
  font-weight: 800;
  font-size: 1.5rem;
  color: var(--color-text-light);
}

.titles-chip-result {
  border-color: var(--color-accent);
  background: #fbead0;
}

.titles-chip-result .titles-chip-val {
  color: var(--color-accent);
}

.titles-note-text {
  color: var(--color-text-light);
  max-width: 64ch;
}

.titles-vmap {
  width: 100%;
  border-collapse: collapse;
  margin-top: 26px;
  font-size: 0.88rem;
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  overflow: hidden;
}

.titles-vmap th,
.titles-vmap td {
  padding: 11px 14px;
  text-align: left;
  border-bottom: 1px solid var(--color-border);
}

.titles-vmap th {
  background: var(--color-primary-dark);
  color: #fff;
  font-weight: 700;
  font-size: var(--font-size-2xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.titles-vmap tr:last-child td {
  border-bottom: none;
}

.titles-vmap td:first-child {
  font-weight: 700;
}

.titles-mini-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 22px;
}

.titles-mini {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 18px;
}

.titles-mini-code {
  font-weight: 800;
  font-size: 1.15rem;
  color: var(--color-primary-dark);
}

.titles-mini p {
  font-size: 0.88rem;
  color: var(--color-text-light);
  margin-top: 4px;
}

/* lifetime gems */

.titles-gems {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 10px;
}

.titles-gem {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 16px 8px 14px;
  text-align: center;
  position: relative;
  /* transition lives in the shared "Cards: shared polish" rule further down
     (it needs to, to also cover this card's .fade-up fade-in correctly —
     see the comment there) */
}

.titles-stone {
  position: relative;
  width: 44px;
  height: 42px;
  margin: 0 auto 11px;
  clip-path: polygon(50% 0, 84% 13%, 100% 42%, 82% 76%, 50% 100%, 18% 76%, 0 42%, 16% 13%);
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.72) 0 12%, transparent 13%),
    linear-gradient(35deg, transparent 0 46%, rgba(255, 255, 255, 0.32) 47% 52%, transparent 53%),
    linear-gradient(145deg, var(--gem-light) 0 28%, var(--gem-mid) 29% 66%, var(--gem-dark) 67% 100%);
  filter: drop-shadow(0 4px 4px rgba(31, 26, 34, 0.25));
  transition: transform 0.3s ease, filter 0.3s ease;
}

.titles-stone::after {
  content: "";
  position: absolute;
  width: 10px;
  height: 22px;
  top: -7px;
  left: 6px;
  background: rgba(255, 255, 255, 0.48);
  transform: rotate(38deg);
  filter: blur(1px);
  opacity: 0;
  transition: transform 0.45s ease, opacity var(--duration-standard) var(--ease-standard);
}

.titles-gem-amethyst .titles-stone { --gem-light: #d9b9fa; --gem-mid: #9364c8; --gem-dark: #57307e; }
.titles-gem-topaz .titles-stone { --gem-light: #ffe49a; --gem-mid: #e2aa3f; --gem-dark: #9e6417; }
.titles-gem-ruby .titles-stone { --gem-light: #ff9aa5; --gem-mid: #d84358; --gem-dark: #851c31; }
.titles-gem-emerald .titles-stone { --gem-light: #91e3b5; --gem-mid: #31a36a; --gem-dark: #12613a; }
.titles-gem-sapphire .titles-stone { --gem-light: #9dbbff; --gem-mid: #456fd0; --gem-dark: #1d397f; }
.titles-gem-diamond .titles-stone { --gem-light: #ffffff; --gem-mid: #d7e7ee; --gem-dark: #9cb2be; }
.titles-gem-blackd .titles-stone { --gem-light: #777783; --gem-mid: #34343d; --gem-dark: #0d0d12; }
.titles-gem-platinum .titles-stone { --gem-light: #ffffff; --gem-mid: #c7d2d9; --gem-dark: #84949e; }
.titles-gem-fools .titles-stone { --gem-light: #f4db78; --gem-mid: #bb8f2d; --gem-dark: #6f5314; }

.titles-gem:hover {
  border-color: var(--color-border-strong);
  box-shadow: 0 8px 18px rgba(38, 32, 45, 0.09);
}

.titles-gem:hover .titles-stone {
  transform: translateY(-4px) rotate(3deg) scale(1.08);
  filter: drop-shadow(0 8px 7px rgba(31, 26, 34, 0.3)) saturate(1.08);
}

.titles-gem:hover .titles-stone::after {
  opacity: 0.75;
  transform: translateX(27px) rotate(38deg);
}

@media (prefers-reduced-motion: reduce) {
  .titles-disc,
  .titles-stone,
  .titles-stone::after,
  .titles-gem-spotlight-stone,
  .titles-gem-spotlight-stone::after,
  .titles-xrex-trophy,
  .titles-xrex-trophy::after {
    transition: none;
  }

  .titles-medal:hover .titles-disc,
  .titles-gem:hover .titles-stone,
  .titles-gem-spotlight:hover .titles-gem-spotlight-stone,
  .titles-pinnacle:hover .titles-xrex-trophy {
    transform: none;
  }

  .titles-gem:hover .titles-stone::after,
  .titles-gem-spotlight:hover .titles-gem-spotlight-stone::after,
  .titles-pinnacle:hover .titles-xrex-trophy::after {
    opacity: 0;
  }
}

.titles-gem-name {
  font-weight: 700;
  font-size: var(--font-size-2xs);
  line-height: 1.2;
}

.titles-gem-pts {
  font-weight: 800;
  font-size: 0.85rem;
  color: var(--color-primary-dark);
}

.titles-gem-spotlight {
  margin-top: 20px;
  display: flex;
  align-items: center;
  gap: 28px;
  background: var(--color-text);
  color: #f4efe2;
  border: 2px solid var(--color-accent);
  border-radius: 18px;
  padding: 28px 34px;
  position: relative;
  overflow: hidden;
}

.titles-gem-spotlight::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(600px 220px at 12% 0%, rgba(224, 142, 43, 0.22), transparent 70%);
  pointer-events: none;
}

.titles-gem-spotlight-stone {
  position: relative;
  flex-shrink: 0;
  width: 90px;
  height: 86px;
  clip-path: polygon(50% 0, 84% 13%, 100% 42%, 82% 76%, 50% 100%, 18% 76%, 0 42%, 16% 13%);
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.72) 0 12%, transparent 13%),
    linear-gradient(35deg, transparent 0 46%, rgba(255, 255, 255, 0.32) 47% 52%, transparent 53%),
    linear-gradient(145deg, #f4db78 0 28%, #bb8f2d 29% 66%, #6f5314 67% 100%);
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.35));
  transition: transform 0.3s ease, filter 0.3s ease;
}

.titles-gem-spotlight-stone::after {
  content: "";
  position: absolute;
  width: 20px;
  height: 44px;
  top: -14px;
  left: 12px;
  background: rgba(255, 255, 255, 0.48);
  transform: rotate(38deg);
  filter: blur(1px);
  opacity: 0;
  transition: transform 0.45s ease, opacity var(--duration-standard) var(--ease-standard);
}

.titles-gem-spotlight:hover .titles-gem-spotlight-stone {
  transform: translateY(-4px) rotate(3deg) scale(1.08);
  filter: drop-shadow(0 8px 7px rgba(31, 26, 34, 0.3)) saturate(1.08);
}

.titles-gem-spotlight:hover .titles-gem-spotlight-stone::after {
  opacity: 0.75;
  transform: translateX(54px) rotate(38deg);
}

.titles-gem-spotlight-text {
  position: relative;
}

.titles-gem-spotlight-text .titles-subline {
  max-width: 42ch;
}

/* juniors */

.titles-jr {
  display: grid;
  grid-template-columns: 0.85fr 1.1fr 1fr;
  gap: 26px;
  align-items: start;
}

.titles-jr-photo {
  width: 100%;
  height: 100%;
  min-height: 260px;
  object-fit: cover;
  border-radius: 14px;
}

.titles-jr-list {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: 14px;
  padding: 8px 20px;
}

.titles-jr-list div {
  display: flex;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px dashed var(--color-border);
  font-size: 0.92rem;
}

.titles-jr-list div:last-child {
  border-bottom: none;
}

.titles-jr-list span {
  color: var(--color-primary-dark);
  font-weight: 700;
}

.titles-jr-note {
  background: var(--color-surface-brand);
  border: 1px solid var(--color-border-brand);
  border-radius: 14px;
  padding: 18px 20px;
  font-size: 0.92rem;
  color: var(--color-primary-dark);
}

.titles-jr-note a {
  color: var(--color-primary-dark);
  font-weight: 600;
}

.titles-footnote {
  text-align: center;
  max-width: 640px;
  margin: 0 auto;
  padding: 0 20px 56px;
  font-size: 0.88rem;
  color: var(--color-text-light);
}

/* ---------- Titles page responsive ---------- */

@media (max-width: 900px) {
  .titles-ladder { grid-template-columns: 1fr 1fr; }
  .titles-rung { padding-bottom: 16px !important; }
  .titles-pinnacle { grid-template-columns: 1fr; gap: 22px; }
  .titles-req { grid-template-columns: 1fr; }
  .titles-medals { grid-template-columns: 1fr 1fr; }
  .titles-games-grid { grid-template-columns: 1fr 1fr; }
  .titles-gems { grid-template-columns: repeat(3, 1fr); }
  .titles-jr { grid-template-columns: 1fr; }
  .titles-jr-photo { height: 260px; min-height: 0; }
  .titles-mini-cards { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  .titles-subnav {
    top: 0;
    position: static;
  }

  .titles-section,
  .titles-pinnacle {
    scroll-margin-top: var(--scroll-offset);
  }
}

@media (max-width: 520px) {
  .titles-ladder { grid-template-columns: 1fr; }
  .titles-games-grid { grid-template-columns: 1fr; }
  .titles-vmap { display: block; overflow-x: auto; }
}

/* ================================================================
   Shared component normalization

   These grouped rules keep the established page-specific components while
   giving them one structural language. Decorative colors and layouts remain
   owned by their pages; surfaces, borders, spacing, type, and motion do not.
================================================================ */

/* Consistent section rhythm */
.intro,
.titles-section {
  padding: var(--section-padding-block) var(--container-gutter);
}

.listing-section,
.games-section,
.judge-resources-section {
  padding: var(--section-padding-block-compact) var(--container-gutter) var(--section-padding-block);
}

.get-started-section {
  padding: var(--section-padding-block-compact) var(--container-gutter) var(--section-padding-block);
}

.quick-links,
.news,
.care-blocks {
  padding-inline: var(--container-gutter);
  padding-bottom: var(--section-padding-block);
}

.care-intro,
.faq-search-section {
  padding-inline: var(--container-gutter);
  padding-top: var(--section-padding-block-compact);
}

.welfare-pillars {
  padding: var(--section-padding-block-compact) var(--container-gutter);
}

.card-grid,
.welfare-pillars,
.essentials-grid,
.titles-jr {
  gap: var(--grid-gap);
}

.listing-card-list,
.games-grid,
.titles-ladder,
.titles-medals,
.titles-games-grid,
.titles-mini-cards {
  gap: var(--grid-gap-compact);
}

/* Consistent text hierarchy and readable measures */
.hero h1,
.hero-slide-announcement h2 {
  font-size: var(--font-size-heading-lg);
}

.titles-sec-head h2,
.care-block-text h2 {
  font-size: var(--font-size-heading-md);
}

.card h3,
.welfare-pillar h3,
.essential-card h3,
.step-body h3,
.listing-card-name {
  font-size: var(--font-size-heading-sm);
}

.hero-sub,
.intro-text,
.care-intro,
.titles-sec-head,
.titles-note-text {
  max-width: var(--measure-copy);
}

.card p,
.welfare-pillar p,
.essential-card p,
.listing-card-location,
.listing-card-secretary,
.step-body p,
.secreterrier-cta p {
  color: var(--color-text-muted);
  line-height: var(--line-height-compact);
}

.news-date,
.filter-field label,
.titles-eyebrow,
.titles-tag,
.essential-pages {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
}

/* Shared card surface */
.card,
.listing-card,
.game-square,
.game-panel,
.panel-summary,
.welfare-pillar,
.secreterrier-cta,
.essential-card,
.titles-rung,
.titles-medal,
.titles-gcard,
.titles-chip,
.titles-vmap,
.titles-mini,
.titles-gem,
.titles-jr-list {
  border: var(--border-subtle);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-card);
}

.listing-card,
.game-panel,
.judge-hero-card,
.essentials-outline,
.titles-rung,
.titles-medal,
.titles-callout,
.titles-gcard,
.titles-vmap,
.titles-mini,
.titles-jr-photo,
.titles-jr-list,
.titles-jr-note {
  border-radius: var(--radius-lg);
}

.card,
.game-square,
.panel-summary,
.welfare-pillar,
.secreterrier-cta,
.essential-card,
.titles-chip,
.titles-gem {
  border-radius: var(--radius-md);
}

.card,
.welfare-pillar,
.secreterrier-cta,
.essential-card {
  padding: var(--card-padding);
}

.listing-card:hover,
.game-square:not(.active):hover,
.titles-medal:hover,
.titles-gem:hover {
  box-shadow: var(--shadow-hover);
}

/* Shared form controls */
.filter-field input,
.filter-field select,
.faq-mobile-nav select {
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
}

.filter-field input:focus,
.filter-field select:focus,
.faq-mobile-nav select:focus {
  border-color: var(--color-brand-hover);
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* Shared borders and interaction timing */
.stats-banner,
.site-map,
.essentials-outline,
.ckc-announcement,
.titles-subnav,
.titles-section + .titles-section {
  border-color: var(--color-border);
}

.listing-card,
.game-square,
.title-row,
.titles-medal,
.titles-gem {
  transition-duration: var(--duration-standard);
  transition-timing-function: var(--ease-standard);
}

.hero-dot {
  position: relative;
  padding: 0;
  border: 0;
  background: transparent;
  width: 44px;
  height: 44px;
}

.hero-dot::before {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 10px;
  height: 10px;
  border: 2px solid var(--color-border-strong);
  border-radius: 50%;
  background: transparent;
  transform: translate(-50%, -50%);
  transition: background var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}

/* Filled (not just outlined) even at rest, so a dot doesn't disappear
   against a bright or busy part of whichever photo is showing. */
.hero-dot::before {
  width: 9px;
  height: 9px;
  border-color: rgba(255, 255, 255, 0.7);
  background: rgba(255, 255, 255, 0.5);
}

.hero-dot:hover,
.hero-dot.active {
  border: 0;
  background: transparent;
}

.hero-dot:hover::before,
.hero-dot.active::before {
  border-color: var(--color-text-on-dark);
}

.hero-dot:hover::before {
  background: rgba(255, 255, 255, 0.8);
}

.hero-dot.active::before {
  background: var(--color-text-on-dark);
}

/* ---------- Component states and variants ---------- */

/* Buttons: one interaction model for links and native buttons */
.btn,
.nav-cta,
.listing-card-btn {
  min-height: 44px;
}

.btn[disabled],
.btn:disabled,
.listing-card-btn[disabled],
.listing-card-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
  box-shadow: none;
  transform: none;
}

/* .pdf-modal-open deliberately isn't part of this group: every other link
   here sits on a light card/page background, where --color-brand-strong
   (dark teal) reads fine. .pdf-modal-open sits in the modal's dark-teal
   title bar (--color-primary-dark) — the same dark-on-slightly-less-dark
   teal would be nearly unreadable there, so it keeps its own white color
   further up in the "PDF viewer modal" section instead. */
.card-link,
.step-link,
.faq-answer a,
.listing-card-website {
  color: var(--color-brand-strong);
  font-weight: var(--font-weight-bold);
  text-decoration-line: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.2em;
  transition: color var(--duration-fast) var(--ease-standard), text-decoration-color var(--duration-fast) var(--ease-standard);
}

.card-link:hover,
.step-link:hover,
.faq-answer a:hover,
.listing-card-website:hover {
  color: var(--color-brand-hover);
  text-decoration-color: currentColor;
}

.card-link,
.step-link {
  transition: color var(--duration-fast) var(--ease-standard), text-decoration-color var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-standard);
}

.card-link:hover,
.step-link:hover {
  transform: translateX(2px);
}

.step-link svg {
  transition: transform var(--duration-fast) var(--ease-standard);
}

.step-link:hover svg {
  transform: translateX(2px);
}

/* Cards: shared polish without flattening page-specific layouts

   Every one of these also carries the .fade-up class (directly in HTML, or
   added by JS for judges/clubs/games tiles) and needs an opacity transition
   to fade in rather than pop — but .fade-up's own transition rule and this
   one are equal specificity, so whichever comes later in the file wins
   *entirely* for the shared `transition` property, not property-by-property.
   Since this rule comes later, opacity has to be listed here too (at the
   same --ease-out curve .fade-up itself uses), or the fade-in silently
   stops working for every card on the site. background/color are along
   for the same reason (.game-square's hover changes both) — harmless
   no-ops for the cards that never change those properties. */
.card,
.essential-card,
.welfare-pillar,
.secreterrier-cta,
.listing-card,
.game-square,
.titles-medal,
.titles-gcard,
.titles-mini,
.titles-gem {
  transition: opacity var(--duration-reveal) var(--ease-out), transform var(--duration-standard) var(--ease-standard), border-color var(--duration-standard) var(--ease-standard), background var(--duration-standard) var(--ease-standard), color var(--duration-standard) var(--ease-standard), box-shadow var(--duration-standard) var(--ease-standard);
}

@media (hover: hover) {
  .card:hover,
  .essential-card:hover,
  .welfare-pillar:hover,
  .titles-gcard:hover,
  .titles-mini:hover {
    border-color: var(--color-border-strong);
    box-shadow: var(--shadow-hover);
    transform: translateY(-2px);
  }

  /* .intro-gallery img and .titles-jr-photo also carry .fade-up (.care-
     block-image doesn't — its entrance is animated on its .care-block
     parent instead). opacity is listed here so those two still get their
     fade-up entrance fade; transform was already here for the hover-scale
     effect and doing double duty for fade-up's slide-up costs nothing extra. */
  .intro-gallery img,
  .care-block-image,
  .titles-jr-photo {
    transition: transform var(--duration-standard) var(--ease-standard), box-shadow var(--duration-standard) var(--ease-standard), opacity var(--duration-reveal) var(--ease-out);
  }

  .intro-gallery img:hover,
  .care-block:hover .care-block-image,
  .titles-jr-photo:hover {
    box-shadow: var(--shadow-hover);
    transform: scale(1.012);
  }
}

/* A faint edge carries the eye between long sections without introducing
   a new background-color pattern or competing with page-specific artwork. */
.news,
.care-blocks,
.whats-next,
.titles-section + .titles-section {
  background-image: linear-gradient(to bottom, rgba(63, 131, 128, 0.045), transparent 80px);
  border-top-color: var(--color-border);
}

:where(section, article, details)[id] {
  scroll-margin-top: var(--scroll-offset);
}

/* Heroes: aligned title, copy, and CTA rhythm */
.hero-slide {
  padding-block: var(--section-padding-block);
}

.hero-inner {
  max-width: min(700px, calc(100% - (2 * var(--container-gutter))));
  padding-right: var(--container-gutter);
}

.hero h1,
.hero-slide-announcement h2,
.page-banner h1 {
  font-weight: var(--font-weight-bold);
  letter-spacing: -0.01em;
}

.hero-sub,
.page-banner p {
  line-height: var(--line-height-compact);
}

.hero-buttons {
  gap: var(--space-4);
}

.page-banner {
  padding-inline: var(--container-gutter);
}

.page-banner p {
  max-width: var(--measure-lead);
  margin-inline: auto;
}

/* Navigation */
.logo {
  gap: var(--space-3);
}

.logo-img {
  width: 72px;
  height: 72px;
}

.main-nav {
  gap: var(--space-6);
}

.main-nav a:not(.nav-cta),
.nav-drop-toggle {
  position: relative;
  padding-block: var(--space-2);
}

/* :not(.nav-cta) matters here: .nav-cta is also a direct <a> child of
   .main-nav and also gets .active on get-started.html (it links there),
   but it's already a distinct, colored button — this underline treatment
   is for plain text links and reads as a stray mark stacked on a button
   that isn't relatively positioned to contain it cleanly in the first
   place. See the "no .nav-cta.active treatment" note further up.

   The underline is a pseudo-element on every link (not just .active), kept
   at opacity:0/scaleX(0.4) by default, so hover/focus can transition it in
   from the center without shifting layout (a border-bottom would). */
.main-nav a:not(.nav-cta)::after,
.nav-drop-toggle::before {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 3px;
  border-radius: var(--radius-pill);
  background: var(--color-primary-dark);
  opacity: 0;
  transform: scaleX(0.4);
  transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
}

.main-nav a:not(.nav-cta):hover::after,
.main-nav a:not(.nav-cta):focus-visible::after,
.nav-drop-toggle:hover::before,
.nav-drop-toggle:focus-visible::before,
.main-nav a.active:not(.nav-cta)::after,
.nav-item.has-active-link > .nav-drop-toggle::before {
  opacity: 1;
  transform: scaleX(1);
}

/* The active link's underline is simply always-on — no entrance to animate. */
.main-nav a.active:not(.nav-cta)::after,
.nav-item.has-active-link > .nav-drop-toggle::before {
  transition: none;
}

.nav-item.has-dropdown > .nav-drop-toggle::after {
  display: inline-block;
  transition: transform var(--duration-fast) var(--ease-standard);
}

.dropdown a {
  padding: var(--space-2) var(--space-4);
  border-radius: calc(var(--radius-sm) / 2);
  margin-inline: var(--space-1);
  transition: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);
}

.dropdown a.active {
  background: var(--color-surface-brand);
  color: var(--color-brand-strong);
}

/* Footer
   padding-block matches --bar-padding-block (same token .top-bar uses) so
   the footer bar is the same height as the top bar — no min-height here
   either, for the same reason: .top-bar-link/.social-icon don't enforce
   one, so this stays sized the same way that slim bar already is. */
.site-footer {
  padding-block: var(--bar-padding-block);
  color: var(--color-text-on-dark);
}

.footer-inner {
  gap: var(--space-4);
  line-height: var(--line-height-compact);
}

.footer-inner a {
  color: var(--color-text-on-dark);
  font-weight: var(--font-weight-semibold);
  text-decoration-color: rgba(255, 255, 255, 0.55);
  text-underline-offset: 0.2em;
}

.footer-inner a:hover {
  text-decoration-color: currentColor;
}

/* Forms and search */
.filter-field label,
.faq-mobile-nav label {
  color: var(--color-text-muted);
  font-weight: var(--font-weight-bold);
}

.filter-field input::placeholder,
.faq-search-section input::placeholder {
  color: var(--color-text-muted);
  opacity: 0.75;
}

.filter-field input:hover,
.filter-field select:hover,
.faq-mobile-nav select:hover {
  border-color: var(--color-brand);
}

/* Accordions */
.faq-item summary {
  min-height: 60px;
  padding: var(--space-4) var(--space-5);
  transition: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard);
}

.faq-item summary:hover {
  background: var(--color-surface-subtle);
  color: var(--color-brand-strong);
}

.faq-item[open] summary {
  background: var(--color-surface-brand);
  color: var(--color-brand-strong);
}

.faq-item[open] summary::after {
  background: var(--color-surface);
  transform: rotate(45deg);
}

.faq-answer {
  padding: 0 56px var(--space-5) var(--space-5);
}

@media (max-width: 720px) {
  :root {
    --container-gutter: var(--space-4);
    --card-padding: var(--space-4);
    --grid-gap: var(--space-4);
  }

  .intro,
  .titles-section,
  .listing-section,
  .games-section,
  .get-started-section,
  .judge-resources-section {
    padding-top: var(--section-padding-block-mobile);
    padding-bottom: var(--section-padding-block-mobile);
  }

  .hero-slide {
    padding-block: var(--section-padding-block-mobile);
  }

  .hero-inner {
    padding-left: var(--container-gutter);
  }

  .hero-buttons .btn {
    flex: 1 1 180px;
  }

  .page-banner {
    padding-block: var(--space-6);
  }

  .footer-inner {
    flex-direction: column;
    justify-content: center;
    gap: var(--space-2);
    padding-block: var(--space-2);
    text-align: center;
  }

  .faq-item summary {
    padding-inline: var(--space-4);
  }

  .faq-answer {
    padding-right: var(--space-4);
    padding-left: var(--space-4);
  }
}

@media (max-width: 1180px) {
  .main-nav a:not(.nav-cta),
  .nav-drop-toggle {
    padding: var(--space-3) 0;
  }

  .main-nav a:not(.nav-cta)::after,
  .nav-drop-toggle::before {
    right: auto;
    width: var(--space-6);
  }

  .dropdown a {
    margin-inline: 0;
    padding-left: var(--space-5);
  }
}

/* ---------- Contact page ---------- */

.contact-section {
  padding: var(--section-padding-block-compact) var(--container-gutter) var(--section-padding-block);
}

.contact-layout {
  display: flex;
  gap: var(--space-7);
  align-items: flex-start;
}

.contact-form-wrap {
  flex: 1 1 55%;
  min-width: 0;
}

.contact-image-wrap {
  flex: 1 1 45%;
  align-self: flex-start;
}

/* aspect-ratio matches the source photo exactly (917 x 1440), so the box
   is always shaped like the photo itself — object-fit: cover then never
   has anything to crop, at any viewport width, which keeps the dog's
   face (and mouth) fully in frame instead of depending on a guessed
   object-position that could clip it at some breakpoint. */
.contact-image-wrap img {
  width: 100%;
  aspect-ratio: 917 / 1440;
  object-fit: cover;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  display: block;
}

.contact-intro {
  margin-bottom: var(--space-6);
}

.contact-intro p {
  color: var(--color-text-light);
}

.contact-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.contact-form[hidden] {
  display: none;
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-field > label {
  font-weight: var(--font-weight-semibold);
  font-size: 0.9rem;
  color: var(--color-text);
}

.form-hint {
  font-size: var(--font-size-sm);
  color: var(--color-text-light);
  font-weight: var(--font-weight-regular);
}

.form-field input[type="text"],
.form-field input[type="email"],
.form-field select,
.form-field textarea {
  min-height: 48px;
  padding: var(--space-3);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  width: 100%;
  transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
}

.form-field textarea {
  min-height: 140px;
  resize: vertical;
}

.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  border-color: var(--color-brand-hover);
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.form-field.has-error input,
.form-field.has-error select,
.form-field.has-error textarea {
  border-color: var(--color-error);
}

.form-error-message {
  color: var(--color-error);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  display: none;
}

.form-field.has-error .form-error-message {
  display: block;
}

.form-radio-group {
  display: flex;
  gap: var(--space-5);
  flex-wrap: wrap;
}

.form-radio-option {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: var(--font-weight-medium);
  cursor: pointer;
}

.form-radio-option input {
  width: 18px;
  height: 18px;
  accent-color: var(--color-brand-hover);
}

.form-file-field {
  display: none;
}

.form-file-field.is-visible {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.form-file-drop {
  border: 2px dashed var(--color-border-strong);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  text-align: center;
  color: var(--color-text-light);
  background: var(--color-surface-subtle);
}

.form-file-drop input[type="file"] {
  display: block;
  margin: 10px auto 0;
  font: inherit;
  max-width: 100%;
}

.form-file-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.form-file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  font-size: 0.88rem;
}

.form-file-name {
  overflow-wrap: anywhere;
}

.form-file-remove {
  flex-shrink: 0;
  border: 0;
  background: none;
  color: var(--color-brand-hover);
  font-weight: var(--font-weight-bold);
  cursor: pointer;
  padding: 2px 6px;
}

.form-file-remove:hover {
  color: var(--color-error);
}

.form-honeypot-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.contact-turnstile {
  margin-top: var(--space-1);
}

.form-submit-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.form-submit-btn {
  min-width: 210px;
}

.form-submit-btn[disabled] {
  opacity: 0.75;
  cursor: not-allowed;
}

.form-spinner {
  display: none;
  width: 18px;
  height: 18px;
  border: 3px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: contact-spin 0.7s linear infinite;
}

.form-submit-btn.is-loading .form-spinner {
  display: inline-block;
}

.form-submit-btn.is-loading .form-submit-label {
  opacity: 0.85;
}

@keyframes contact-spin {
  to {
    transform: rotate(360deg);
  }
}

.form-status-banner {
  display: none;
  align-items: flex-start;
  gap: 12px;
  border-radius: var(--radius-md);
  padding: var(--space-4);
  font-size: 0.92rem;
  margin-bottom: var(--space-5);
}

.form-status-banner.is-visible {
  display: flex;
}

.form-status-banner.is-error {
  background: #fdf3e4;
  border: 1px solid #ecd6ab;
  border-left: 4px solid var(--color-accent);
  color: var(--color-text);
}

.contact-success {
  text-align: center;
  padding: var(--space-8) var(--space-5);
  background: var(--color-surface-brand);
  border: 1px solid var(--color-border-brand);
  border-radius: var(--radius-lg);
}

.contact-success-icon {
  font-size: 2.6rem;
  margin-bottom: var(--space-3);
}

.contact-success h2 {
  margin-bottom: 10px;
  color: var(--color-primary-dark);
}

.contact-success p {
  color: var(--color-text-light);
  max-width: 420px;
  margin: 0 auto;
}

@media (max-width: 900px) {
  .contact-layout {
    flex-direction: column;
  }
}

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

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