/* ==========================================================================
   Fonts — Helvetica Neue everywhere. It is a system font (macOS / iOS), not
   a downloadable web font, so there is no @font-face: other platforms fall
   back to Helvetica / Arial.
   ========================================================================== */

/* ==========================================================================
   Design tokens
   ==========================================================================
   These override Bootstrap's own CSS variables and heading selectors —
   they do not replace or duplicate Bootstrap components. See
   design-system.html for the full visual reference.
   ========================================================================== */

:root {
  /* Colors */
  --bs-primary: #000;
  --bs-primary-rgb: 0, 0, 0;
  --bs-dark: #0b0b0b;
  --bs-dark-rgb: 11, 11, 11;
  --bs-light: #f3f3f3;
  --bs-light-rgb: 243, 243, 243;
  --bs-body-color: #000;
  --bs-body-bg: #fff;
  /* Revised from the source file's rgba(0,0,0,.4) secondary text, which is
     ~2.8:1 contrast on white and fails WCAG AA. This shade is ~5.7:1.
     Two separate Bootstrap tokens both need this: --bs-secondary-color
     (read by .text-body-secondary and similar) and --bs-secondary /
     --bs-secondary-rgb (the "secondary" theme color, confusingly what the
     .text-secondary *utility* actually reads — not --bs-secondary-color). */
  --bs-secondary-color: #595959;
  --bs-secondary: #595959;
  --bs-secondary-rgb: 89, 89, 89;
  --bs-border-color: rgba(0, 0, 0, .08);
  /* Literal source-spec value (unlike --bs-secondary-color above) — used
     only for the stat-card sublabel, a tertiary caption line under the
     bolder label text above it. */
  --stat-sublabel-color: rgba(0, 0, 0, .4);
  /* Bootstrap's actual `a` rule reads the -rgb variant, not --bs-link-color
     itself — both need to be set or a plain link renders Bootstrap's
     default blue regardless of --bs-link-color. */
  --bs-link-color: #000;
  --bs-link-color-rgb: 0, 0, 0;
  --bs-link-hover-color: #000;
  --bs-link-hover-color-rgb: 0, 0, 0;

  /* Radius */
  --bs-border-radius: .5rem;
  --bs-border-radius-sm: .375rem;
  --bs-border-radius-lg: .75rem;
  --bs-border-radius-pill: 50rem;

  /* Fonts */
  --font-display: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-condensed: var(--font-display);
  --font-body: var(--font-display);
  --bs-body-font-family: var(--font-body);
  --bs-body-font-size: 1rem;
  --bs-body-line-height: 1.5;

  /* Brand-colored focus ring instead of Bootstrap's default blue */
  --bs-focus-ring-color: rgba(0, 0, 0, .25);
}

/* Cards are flat/square in this brand — buttons and icon chips are the only
   rounded shapes. Bootstrap's own .card rule sets --bs-card-border-radius
   directly on .card itself, so a :root-level override is inherited and
   loses to that direct match; it has to be set on .card here too. */
.card {
  --bs-card-border-radius: 0;
}

[data-bs-theme="dark"] {
  /* Revised from the source file's rgba(255,255,255,.4)/.6 for consistency;
     this shade holds ~4.6:1+ on black at any text size. Same two-token
     note as :root above — --bs-secondary-rgb can't carry its own alpha, so
     this is the flat equivalent of ~72% white composited on black. */
  --bs-secondary-color: rgba(255, 255, 255, .72);
  --bs-secondary: rgb(184, 184, 184);
  --bs-secondary-rgb: 184, 184, 184;
  --bs-border-color: rgba(255, 255, 255, .1);
  /* Bootstrap sets its own --bs-link-color(-rgb) directly on this same
     attribute, which otherwise beats our :root override (a direct match on
     the element always wins over an inherited one) and reverts plain links
     on dark surfaces to Bootstrap's light-blue default. */
  --bs-link-color: #fff;
  --bs-link-color-rgb: 255, 255, 255;
  --bs-link-hover-color: #fff;
  --bs-link-hover-color-rgb: 255, 255, 255;
}

body {
  font-family: var(--bs-body-font-family);
}

/* Bootstrap's compiled base `a` rule hardcodes text-decoration:underline —
   it doesn't read --bs-link-decoration at all, despite that variable
   existing, so setting it does nothing. None of the source's links are
   underlined; this is the only way to actually turn it off. */
a {
  text-decoration: none;
}

/* Inline body-copy links (terms-of-use.html, privacy-policy.html): muted
   and underlined at rest so they read as links against the surrounding
   text, resolving to solid black with no underline on hover/focus. */
.legal-content a {
  text-decoration: underline;
  color: var(--bs-secondary-color);
}

.legal-content a:hover,
.legal-content a:focus-visible {
  text-decoration: none;
  color: var(--bs-body-color);
}

/* Display headings use the brand's heavy display face; card titles use
   Korolev italic; nav/eyebrow/group headings use Korolev Condensed. Sizes
   are fluid (clamp) so the scale works mobile-first without a breakpoint
   per size. */
h1, h2, .display-1, .display-2, .display-3 {
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: none;
  letter-spacing: -0.01em;
}

h1 { font-size: clamp(2rem, 1.2rem + 4vw, 3.5rem); line-height: 1; }
h2 { font-size: clamp(1.75rem, 1.3rem + 2vw, 2.25rem); line-height: 1.1; }

h3 {
  font-size: 1.75rem;
  font-family: var(--font-body);
  font-weight: 800;
  text-transform: none;
  letter-spacing: 0.02em;
}

h4 {
  font-size: 1.25rem;
  font-family: var(--font-condensed);
  font-weight: 800;
  text-transform: none;
}

h5 {
  font-size: 1rem;
  font-family: var(--font-condensed);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0.05em;
}

h6 {
  font-size: .875rem;
  font-family: var(--font-condensed);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0.05em;
}

.btn {
  font-family: var(--font-body);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
  line-height: 1;
  /* Equal top/bottom padding alone doesn't visually center text — the
     brand's custom @font-face metrics sit off-center in their line box.
     Flex centering fixes it regardless of font metrics, and is what the
     icon buttons already relied on individually. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Every button in this brand is a pill or a circle, never a slightly
     rounded rectangle — set on the un-guarded base so it also wins over
     .btn-sm/.btn-lg's own (smaller) corner radius. */
  --bs-btn-border-radius: var(--bs-border-radius-pill);
}

/* Default button padding is the source's exact values (16px top / 14px
   bottom / 32px sides — optically-balanced asymmetric padding, not a
   rounding artifact). Combined with line-height:1 (16px) and zero border
   on the filled variants below, that's exactly 46px tall, matching the
   source's pill buttons and the default input height. Guarded with :not()
   so this doesn't clobber .btn-sm/.btn-lg's own padding — and each :not()
   argument counts toward specificity, so .btn-icon/.btn-icon-sm (a single
   class) must also be excluded here, or this rule (3 classes' worth of
   specificity) beats their own padding:0 regardless of file order. */
.btn:not(.btn-sm):not(.btn-lg):not(.btn-icon):not(.btn-icon-sm) {
  padding: .9375rem 2rem;
}

/* Bootstrap's own .btn-sm/.btn-lg padding was scaled for Bootstrap's much
   smaller default button — against our larger default above, .btn-lg
   rendered *smaller* than the default. Rescaled so sm < default < lg.

   Padding is asymmetric (top 2px more than bottom) for the same reason the
   default button's source padding is 16px/14px, not 15px/15px: Korolev
   Bold's font metrics are ascent-heavy with almost no descent (uppercase
   button text never uses one), so centering the *line box* with
   line-height:1 leaves visible extra space under the text, not around it.
   The effect scales with font-size, so it's barely visible at 14px but
   plainly off at 18px if left symmetric — 2px extra top padding corrects
   the optical centering at both sizes without touching the total height. */
.btn-sm {
  padding: .625rem 1.25rem;
  --bs-btn-font-size: .875rem;
}

.btn-lg {
  padding: 1.125rem 2.5rem;
  --bs-btn-font-size: 1.125rem;
}

/* Bootstrap's compiled .btn-primary bakes a literal hex into its own
   --bs-btn-* variables rather than reading root --bs-primary, so setting
   --bs-primary alone doesn't retint it. Point its variables at the token
   directly so the main/primary button actually follows --bs-primary.
   Filled buttons carry no border in the source (--bs-btn-border-width: 0),
   which is also what makes the padding above land on exactly 46px. */
.btn-primary {
  --bs-btn-border-width: 0;
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--bs-primary);
  --bs-btn-border-color: var(--bs-primary);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: color-mix(in srgb, var(--bs-primary) 85%, white);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--bs-primary) 85%, white);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: color-mix(in srgb, var(--bs-primary) 75%, white);
  --bs-btn-active-border-color: color-mix(in srgb, var(--bs-primary) 75%, white);
  --bs-btn-disabled-color: #fff;
  --bs-btn-disabled-bg: var(--bs-primary);
  --bs-btn-disabled-border-color: var(--bs-primary);
  --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}

/* Secondary button: solid white per source (not Bootstrap's --bs-light,
   which is this brand's #f3f3f3 card-background gray) — and no border. */
.btn-light {
  --bs-btn-border-width: 0;
  --bs-btn-color: #000;
  --bs-btn-bg: #fff;
  --bs-btn-border-color: #fff;
  --bs-btn-hover-color: #000;
  --bs-btn-hover-bg: color-mix(in srgb, #fff 90%, black);
  --bs-btn-hover-border-color: color-mix(in srgb, #fff 90%, black);
  --bs-btn-active-color: #000;
  --bs-btn-active-bg: color-mix(in srgb, #fff 80%, black);
  --bs-btn-active-border-color: color-mix(in srgb, #fff 80%, black);
  --bs-btn-disabled-color: #000;
  --bs-btn-disabled-bg: #fff;
  --bs-btn-disabled-border-color: #fff;
}

/* Fixed circular icon buttons — no Bootstrap utility produces this shape.
   Each size is self-sufficient (not meant to be paired with the other) —
   padding must be reset to 0 here, since the default button padding
   (2rem horizontal) would otherwise force these past their fixed width. */
.btn-icon,
.btn-icon-sm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  padding: 0;
  border-radius: 50%;
}

.btn-icon {
  width: 3.5rem;
  height: 3.5rem;
}

.btn-icon-sm {
  width: 2.5rem;
  height: 2.5rem;
}

/* Fixed icon chip used in stat/trust cards — no Bootstrap utility for this. */
.icon-box {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  flex-shrink: 0;
  border-radius: var(--bs-border-radius);
  background: var(--bs-dark);
  color: #fff;
}

/* Legibility scrim for text-on-image cards — Bootstrap's .bg-gradient is a
   subtle highlight, not an opaque-enough scrim for overlaid white text. */
.bg-scrim {
  background-image: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .85) 100%);
}

/* 12px corner radius on every field, including textarea — no longer pill
   now that a fixed radius is used, so there's no "pill-shaped textarea"
   problem left to guard against. */
.form-control,
.form-select {
  border-radius: 12px;
}

/* Default input height pinned to match the default .btn height (46px)
   exactly. Padding + line-height alone doesn't guarantee this: with the
   brand's custom @font-face metrics, a single-line <input> renders a few px
   taller than a <button> at identical padding/line-height, so the height
   is set explicitly instead of computed. Guarded with :not() so
   .form-control-sm/.form-control-lg keep their own sizing; textarea keeps
   auto height since it wraps to multiple lines; and a .form-floating
   input/select is excluded because it needs Bootstrap's own taller
   min-height and top-heavy padding to fit the floating label without the
   value text overlapping it. */
.form-control:not(.form-control-sm):not(.form-control-lg):not(textarea):not(.form-floating > .form-control),
.form-select:not(.form-select-sm):not(.form-select-lg):not(.form-floating > .form-select) {
  height: 2.875rem;
  padding: 0 1.25rem;
}

textarea.form-control {
  padding: .875rem 1.25rem;
}

/* Keep the attached button's outer corners matching a rounded input it's
   grouped with (Bootstrap only flattens the shared seam). */
.input-group > .btn:last-child {
  border-top-right-radius: 12px;
  border-bottom-right-radius: 12px;
}

/* Newsletter signup (source spec, node 721:761): at rest, a single
   pill-shaped shell (not Bootstrap's .input-group, which butts the input
   and button edge-to-edge with no outer shell) holds a borderless email
   field and the black submit button, with generous padding around both.
   That shell needs the email field to hold a 300px min-width to look
   right, which doesn't fit next to the button below ~576px — so mobile
   gets its own stacked, full-width fallback (each field its own pill)
   instead of shrinking the 300px floor and overflowing the viewport. */
.newsletter-form {
  flex-direction: column;
  align-items: stretch;
  gap: .75rem;
  width: 100%;
  max-width: 26rem;
  margin-inline: auto;
}

.newsletter-input {
  width: 100%;
  height: 2.875rem;
  padding: 0 1.25rem;
  border: 1px solid rgba(0, 0, 0, .1);
  border-radius: 6rem;
  background: #fff;
  color: rgba(0, 0, 0, .6);
  font-size: 1rem;
  letter-spacing: .6px;
}

/* Typed text reads full black, not the placeholder's muted gray — checked
   via :not(:placeholder-shown) rather than :focus, so it stays black
   after the field is filled in and then blurred, not just while typing. */
.newsletter-input:not(:placeholder-shown) {
  color: #000;
}

.newsletter-form .btn {
  width: 100%;
  justify-content: center;
}

.newsletter-input:focus {
  outline: none;
  box-shadow: 0 0 0 .25rem var(--bs-focus-ring-color);
  color: #000;
}

/* Live "valid email" state — the field's own type="email"/required
   attributes already give the browser real-time constraint-validation
   state, so :valid is used directly rather than a JS-toggled class; no
   :invalid styling is added, so nothing turns red before the visitor's
   finished typing, only green once it's actually a valid address. A
   checkmark on the field itself (rather than only a border-color change,
   which design-system.html's .is-valid example relies on) because the
   field is borderless at the desktop breakpoint below — a border-color
   there would have nothing visible to color. */
.newsletter-input:valid {
  padding-right: 2.5rem;
  border-color: #198754;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 1rem 1rem;
}

.newsletter-input:valid:focus {
  box-shadow: 0 0 0 .25rem rgba(var(--bs-success-rgb), .25);
}

@media (min-width: 576px) {
  .newsletter-form {
    flex-direction: row;
    align-items: center;
    width: auto;
    max-width: none;
    gap: 1rem;
    padding: .5rem;
    border: 1px solid rgba(0, 0, 0, 1);
    border-radius: 6rem;
    background: #fff;
    transition: box-shadow .15s ease;
  }

  /* The email field goes borderless once it's nested in the pill shell
     above — the shell's own border/radius takes over. The visible focus
     indicator (WCAG 2.4.7) moves from the field to the shell via
     :focus-within, since the field no longer has its own border to
     outline. */
  .newsletter-form:focus-within {
    box-shadow: 0 0 0 .25rem var(--bs-focus-ring-color);
  }

  /* Same green accent as .newsletter-input:valid above, but on the shell
     around it — :has() lets the outer pill react to the inner field's
     validity without any JS. Scoped to this breakpoint because the shell
     (with its own visible border) only exists here; below it the field
     carries its own border directly. */
  .newsletter-form:has(.newsletter-input:valid) {
    border-color: #198754;
  }

  .newsletter-form:has(.newsletter-input:valid):focus-within {
    box-shadow: 0 0 0 .25rem rgba(var(--bs-success-rgb), .25);
  }

  .newsletter-input {
    min-width: 300px;
    width: auto;
    padding: 0 1rem;
    border: 0;
    border-radius: 0;
    background: transparent;
  }

  .newsletter-input:focus {
    box-shadow: none;
  }

  /* The field's own green focus ring (base rule above) would otherwise
     still win here — same :valid:focus selector, but this declaration
     comes later in the cascade — since the shell's ring above is what
     should show instead of a second ring around the now-borderless
     field. */
  .newsletter-input:valid:focus {
    box-shadow: none;
  }

  .newsletter-form .btn {
    width: auto;
  }
}

/* ==========================================================================
   Card blocks
   ==========================================================================
   Named components instead of repeating the same utility-class combo on
   every card. Scope the layout under the parent block's class, on
   Bootstrap's own .card-body — see design-system.html's Cards section. */

/* Feature / promo tile: content stacked and centered, pinned top/bottom.
   Aspect ratio matches the source's 382.5:560 tiles instead of a fixed
   height, so it scales correctly at any column width. The whole tile is a
   click target (its .card-cta text is a .stretched-link); on hover the
   circular CTA button rotates from pointing diagonally to pointing right. */
.feature-card {
  aspect-ratio: 382.5 / 560;
}

.feature-card .card-body {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  text-align: center;
  /* Source spec: 40px top, 24px sides, 8px bottom (the CTA row's own
     vertical padding makes up the rest of the visual bottom gap). */
  padding: 2.5rem 1.5rem .5rem;
}

/* Title + subtitle group at the top of the tile. */
.feature-card .card-body > div:first-child {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

/* Subtitle under the card title — Korolev Condensed Medium per source,
   distinct from the italic Korolev title (h3) above it. */
.feature-card .card-body p {
  margin: 0;
  font-family: var(--font-condensed);
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: .4px;
}

.feature-card .card-cta .btn-icon {
  transition: transform .2s ease;
}

/* Smaller circular CTA button below the xl breakpoint, where these cards
   stack narrower (row-cols-sm-2, then row-cols-lg-4 still fairly tight)
   and the default 3.5rem size crowds the card-cta row. */
@media (max-width: 1199.98px) {
  .feature-card .card-cta .btn-icon {
    width: 2.5rem;
    height: 2.5rem;
  }
}

/* The CTA text is a real <a> (a .stretched-link, so the whole card is
   clickable) but must read as plain label text, not a colored hyperlink —
   Bootstrap's link color depends on --bs-link-color-rgb, which resolves
   differently per data-bs-theme and isn't what a "global text color"
   override would suggest. Inheriting sidesteps all of that. */
.card-cta a,
.card-cta a:hover {
  color: inherit;
  text-decoration: none;
}

.feature-card:hover .card-cta .btn-icon {
  transform: rotate(45deg);
}

/* Hover: the card lifts slightly and its image zooms; link text is regular
   weight per the design. */
.feature-card {
  overflow: hidden;
  transition: transform .3s ease;
}

.feature-card img {
  transition: transform .4s ease;
}

.feature-card:hover {
  transform: translateY(-6px);
}

.feature-card:hover img {
  transform: scale(1.06);
}

.feature-card .card-cta a {
  font-weight: 400;
  font-size: 1.5rem;
  line-height: 3rem;
  letter-spacing: normal;
  text-shadow: none;
}

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

  .feature-card:hover,
  .feature-card:hover img {
    transform: none;
  }
}

/* Icon + stat row (trust-bar style blocks). Source spec: a horizontal
   divider was the wrong model entirely — these sit side by side in a row
   with a *vertical* divider (border-right) between them, and generous,
   asymmetric padding (40px/32px/32px left/right/vertical), not a 16px
   top-padding list item. */
.stat-card {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  height: 100%;
  padding: 2rem 2rem 2rem 2.5rem;
}

/* Dividers live on the card, not the section, and depend on how many
   columns the row has at each breakpoint (1 → 2 → 3 → 5, see .trust-row's
   row-cols-* classes on the markup). Vertical divider = border-right on
   every card that isn't last in its row; horizontal divider = border-bottom
   on every card that isn't in the last row. Both are written per
   breakpoint because the nth-child patterns differ. Assumes 5 cards. */
.trust-row .stat-card {
  --stat-divider: 1px solid rgba(0, 0, 0, .05);
  padding: 1rem 0;
}

/* Each block is confined to its own breakpoint range so no rule has to
   undo another. */

/* 1 column (<576px): stacked, horizontal dividers only. */
@media (max-width: 575.98px) {
  .trust-row > .col:not(:last-child) .stat-card {
    border-bottom: var(--stat-divider);
  }
}

/* 2 columns (576–991px): rows [1,2] [3,4] [5]. */
@media (min-width: 576px) and (max-width: 991.98px) {
  .trust-row .stat-card {
    padding: 1.5rem 1.5rem 1.5rem 2rem;
  }

  .trust-row > .col:nth-child(odd):not(:last-child) .stat-card {
    border-right: var(--stat-divider);
  }

  .trust-row > .col:nth-child(-n+4) .stat-card {
    border-bottom: var(--stat-divider);
  }

  /* The orphan fifth card fills the whole last row. */
  .trust-row > .col:last-child {
    flex: 0 0 100%;
    width: 100%;
  }
}

/* 3 columns (992–1199px): rows [1,2,3] [4,5]. */
@media (min-width: 992px) and (max-width: 1199.98px) {
  .trust-row .stat-card {
    padding: 1.5rem 1.5rem 1.5rem 2rem;
  }

  .trust-row > .col:not(:nth-child(3n)):not(:last-child) .stat-card {
    border-right: var(--stat-divider);
  }

  .trust-row > .col:nth-child(-n+3) .stat-card {
    border-bottom: var(--stat-divider);
  }

  /* The short last row's two cards split the full width instead of
     leaving an empty third slot. */
  .trust-row > .col:nth-child(n+4) {
    flex: 0 0 50%;
    width: 50%;
  }
}

/* 5 columns (≥1200px): single row, vertical dividers only. */
@media (min-width: 1200px) {
  .trust-row .stat-card {
    padding: 2rem 2rem 2rem 2.5rem;
  }

  .trust-row > .col:not(:last-child) .stat-card {
    border-right: var(--stat-divider);
  }
}

/* Smaller icon chip on phones. */
@media (max-width: 575.98px) {
  .stat-card {
    gap: .75rem;
  }

  .stat-card .icon-box {
    width: 2.25rem;
    height: 2.25rem;
  }

  .stat-card .icon-box img {
    width: 1.125rem;
    height: 1.125rem;
  }
}

.stat-card .icon-box {
  margin-top: .125rem;
}

.stat-card .stat-value {
  margin: 0;
  font-family: var(--font-condensed);
  font-weight: 800;
  font-size: 1.5rem;
  line-height: 1;
  letter-spacing: -.6px;
}

.stat-card .stat-label {
  margin: .125rem 0 0;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: .875rem;
  line-height: 1.25;
  letter-spacing: .4px;
}

.stat-card .stat-sublabel {
  margin: .125rem 0 0;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: .75rem;
  line-height: 1.333;
  letter-spacing: .4px;
  color: var(--stat-sublabel-color);
}

/* Text + icon-button row at the bottom of a card, or standalone. Source
   spec: 16px padding top AND bottom (not just top), and a divider at 10%
   opacity — slightly different from the site-wide --bs-border-color (8%
   light-mode), so it's set directly rather than reusing that token. */
.card-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 0;
  border-top: 1px solid rgba(0, 0, 0, .1);
}

[data-bs-theme="dark"] .card-cta {
  border-top-color: rgba(255, 255, 255, .1);
}

/* CTA link text: Korolev Bold 18px per source — reads as plain label text
   (see the color/text-decoration rule above), not a colored hyperlink. */
.card-cta a {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1.125rem;
  line-height: 1;
  letter-spacing: 1px;
}

/* Browse by Sport's prev/next controls: only the outline is dimmed at
   rest (icon stays full-strength currentColor), and hover swaps to the
   brand's exact black rather than Bootstrap's default #212529, so it
   matches --bs-primary used everywhere else on the site. */
.btn-outline-dark.btn-icon {
  --bs-btn-border-color: rgba(0, 0, 0, .25);
  --bs-btn-hover-bg: var(--bs-primary);
  --bs-btn-hover-border-color: var(--bs-primary);
  --bs-btn-active-bg: var(--bs-primary);
  --bs-btn-active-border-color: var(--bs-primary);
  /* Bootstrap's default disabled opacity (.65) still reads as too "live"
     for the sport slider's prev/next arrows at a scroll boundary — this
     scopes a much fainter state to just this button variant instead of
     changing --bs-btn-disabled-opacity for every disabled button. */
  --bs-btn-disabled-opacity: .1;
}

/* Sport/category image tile with a bottom-left label chip (Browse by
   Sport section) — matches the "Image card with label chip" pattern in
   the Cards section of design-system.html. */
.sport-card {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--bs-light);
  aspect-ratio: 516 / 576;
  color: inherit;
}

.sport-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .4s ease;
}

.sport-card:hover img {
  transform: scale(1.06);
}

.sport-card .sport-card-label {
  position: absolute;
  left: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .5rem;
  padding: 1rem 1.5rem;
  color: #fff;
  font-size: 1.5rem;
  line-height: 3rem;
  text-shadow: 0 1px 4px rgba(0, 0, 0, .25);
}

.sport-card .sport-card-label .btn {
  text-shadow: none;
}

/* Browse by Sport slider: a native scroll container (not Bootstrap's
   Carousel, which shows one slide at a time) so the same track shows 1
   card below 576px, 2 up to 992px, 3 up to 1400px, and 4 above that (see
   .sport-slide below) — scrollable instead of a static row. Scroll-snap
   gives clean stops for the arrow buttons and touch swipe;
   initSportSlider() in main.js adds mouse click-and-drag on top, since
   touchscreens already scroll this natively but a mouse has no
   equivalent gesture. */
.sport-slider {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  cursor: grab;
}

.sport-slider::-webkit-scrollbar {
  display: none;
}

/* Dragging disables smooth-scroll/snap so the card tracks the pointer
   exactly, instead of fighting a smooth-scroll animation or snapping
   back mid-drag. */
.sport-slider.is-dragging {
  scroll-snap-type: none;
  scroll-behavior: auto;
  cursor: grabbing;
  user-select: none;
}

.sport-slide {
  flex: 0 0 100%;
  min-width: 0;
  scroll-snap-align: start;
}

/* Visible-cards-per-page steps up at Bootstrap's own sm/lg/xxl minimums
   (576/992/1400px) — each tier's flex-basis subtracts the gap(s) between
   that many cards from 100%, since .sport-slider's own gap is 1rem. */
@media (min-width: 576px) {
  .sport-slide {
    flex: 0 0 calc((100% - 1rem) / 2);
  }
}

@media (min-width: 992px) {
  .sport-slide {
    flex: 0 0 calc((100% - 2rem) / 3);
  }
}

@media (min-width: 1400px) {
  .sport-slide {
    flex: 0 0 calc((100% - 3rem) / 4);
  }
}

/* Instagram section (source spec, node 721:731): 80px above the title
   row instead of the sitewide 48px py-5 top, and 40px between the title
   row and the image grid below it. */
.feed-section {
  padding-top: 20px;
}

/* padding, not margin-bottom: the grid row below has its own gutter
   (g-2) negative margin-top that would otherwise collapse into an
   adjoining margin here and shrink the visible gap. */
.feed-toolbar {
  padding-bottom: 2.5rem;
}

/* Source title is mixed-case ("#GearUpForPerformance with Sinalli"), not
   the all-caps h3 default used elsewhere on the site. */
.feed-title {
  text-transform: none;
  margin-top: 6px;
}

/* Full-bleed grid image used in the Instagram feed strip — source spec
   is a portrait tile (roughly 4:5), not square. */
.feed-tile {
  display: block;
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--bs-light);
}

/* Direct child only — the overlay's own icon below is also an <img>
   inside .feed-tile, and would otherwise be stretched to fill the tile
   by this same rule. */
.feed-tile > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Dark scrim + centered Instagram mark on hover/focus, hidden otherwise. */
.feed-tile-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, .6);
  opacity: 0;
  transition: opacity .25s ease;
}

.feed-tile-overlay img {
  width: 40px;
  height: 40px;
}

.feed-tile:hover .feed-tile-overlay,
.feed-tile:focus-visible .feed-tile-overlay {
  opacity: 1;
}

/* Long-form body copy (brand story) reads noticeably tighter than intended
   at the sitewide default of 1.5 — source spec is line-height 28px on
   16px text (1.75), a wider measure than the short labels/buttons the
   1.5 default was tuned for. */
.story p {
  line-height: 1.75;
}

/* ==========================================================================
   Nav icon buttons — search/wishlist/bag, and the custom hamburger (a
   static background-image SVG, Bootstrap's default, can't be animated) +
   right-side offcanvas.
   ========================================================================== */

/* Bootstrap's default 1rem margin-end, plus the 4px .gap-1 previously
   used between the icon buttons, left only ~2px of headroom at 375px
   wide once the icon buttons below were widened to a 44px touch target —
   the row wrapped onto its own line. Both are trimmed here to keep brand
   + icons on one line down to the ~360px floor this site targets. */
.navbar-brand {
  margin-right: 0;
}

.navbar-actions {
  gap: .125rem;
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  transition: background-color .2s ease;
}

.icon-btn:hover {
  background: var(--bs-light);
}

.icon-btn:active {
  background: var(--bs-border-color);
}

.icon-btn img {
  transition: transform .2s ease;
}

.icon-btn:hover img {
  transform: scale(1.12);
}

/* Top-right of the bag icon (20px icon centered in the 44px button). */
.icon-btn-badge {
  position: absolute;
  top: calc(50% - 10px);
  left: calc(50% + 10px);
  transform: translate(-50%, -50%);
  font-size: 11px;
  line-height: 10px;
}

.navbar-toggler {
  position: relative;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: none !important;
  transition: background-color .2s ease;
}

.navbar-toggler:hover {
  background: var(--bs-light);
}

.navbar-toggler .hamburger-bar,
.navbar-toggler .hamburger-bar::before,
.navbar-toggler .hamburger-bar::after {
  position: absolute;
  left: 50%;
  width: 1.25rem;
  height: 2px;
  background: #000;
  border-radius: 2px;
  transform: translateX(-50%);
  transition: transform .25s ease, width .25s ease, top .25s ease, opacity .15s ease;
}

.navbar-toggler .hamburger-bar {
  top: 50%;
  margin-top: -1px;
}

.navbar-toggler .hamburger-bar::before {
  content: "";
  top: -6px;
}

.navbar-toggler .hamburger-bar::after {
  content: "";
  top: 6px;
}

/* Hover: bars fan out unevenly instead of just sitting there. */
.navbar-toggler:hover .hamburger-bar {
  width: 1rem;
}

.navbar-toggler:hover .hamburger-bar::before {
  top: -7px;
  width: 1.5rem;
}

.navbar-toggler:hover .hamburger-bar::after {
  top: 7px;
  width: 1.25rem;
}

/* Open (aria-expanded, kept in sync with the offcanvas by main.js): morph
   into an X. */
.navbar-toggler[aria-expanded="true"] .hamburger-bar {
  width: 1.25rem;
  background: transparent;
}

.navbar-toggler[aria-expanded="true"] .hamburger-bar::before {
  top: 0;
  width: 1.25rem;
  transform: translateX(-50%) rotate(45deg);
}

.navbar-toggler[aria-expanded="true"] .hamburger-bar::after {
  top: 0;
  width: 1.25rem;
  transform: translateX(-50%) rotate(-45deg);
}

.offcanvas .nav-link {
  color: #000;
}

/* Bootstrap's .nav-link inside .navbar reads --bs-navbar-color, not
   --bs-link-color (our token) — its default is rgba(emphasis, .65), a
   muted gray, not solid black. Override directly and add a hover
   underline that grows in from the left. */
.navbar .nav-link {
  position: relative;
  color: #000;
}

.navbar .nav-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .25s ease;
}

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

/* Hero tagline sits directly on the image, above the CTA buttons — plain
   sentence case, not the small/uppercase treatment used for labels. */
.hero p {
  font-size: 1.125rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
}

/* Bootstrap's [data-bs-theme="dark"] sets --bs-carousel-indicator-active-bg
   to black — it assumes "dark theme" means light carousel content needing
   dark indicators, the opposite of our dark photo needing white ones. Since
   .hero carries data-bs-theme="dark" (for the white text/links elsewhere
   in it), it inherits that assumption too; put it back to white. */
.hero {
  --bs-carousel-indicator-active-bg: #fff;
}

/* Below ~576px, the source's 1700:825 aspect ratio makes the hero image
   (and therefore the overlay) shorter than the tagline + CTA buttons +
   indicators actually need — the overlay's justify-content:end then pins
   the indicators to the bottom and pushes the tagline up past the top
   edge, clipping it entirely. A min-height floor keeps enough room for
   the overlay content; object-fit:cover absorbs the extra crop. */
@media (max-width: 575.98px) {
  .hero .carousel-item img {
    min-height: 320px;
  }
}

/* Hero carousel indicators: short dot per slide, active one stretches into
   a pill — Bootstrap's default is a uniform 30x3px bar for every state. */
.hero .carousel-indicators [data-bs-target] {
  width: .5rem;
  height: .5rem;
  /* Bootstrap gives this a 10px transparent top/bottom border (content-box
     sizing) for a bigger invisible tap target, making the real border-box
     40x26px. border-radius then clamps per-axis against that 26px-tall
     box, but only the inner 6px slice is visible (background-clip:
     padding-box) — so the vertical radius shrinks by the 10px border while
     the horizontal one doesn't, leaving mismatched x/y corner radii (an
     oval) instead of a circular pill cap. Dropping the border removes the
     mismatch: border-radius clamps uniformly against the real 40x6 box. */
  position: relative;
  border: 0;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, .1);
  opacity: 1;
  transition: background-color .3s ease;
}

/* The visible bar is only 6px tall — too small a tap target on touch
   devices. A transparent pseudo-element (not a border/padding change,
   which would reintroduce the oval clamping bug above) pads the actual
   hit area out to a comfortable ~44px without affecting how the bar
   looks or how border-radius clamps it. */
.hero .carousel-indicators [data-bs-target]::before {
  content: "";
  position: absolute;
  inset: -19px -4px;
}

.hero .carousel-indicators [data-bs-target].active {
  background-color: rgba(255, 255, 255, .6);
  opacity: 1;
}

/* ==========================================================================
   Search panel — a full-width overlay dropped below the header (nav +
   promo bar), not pushing page content down. Positioned against #site-
   header (given position:relative below), so it always sits exactly at
   that header's height regardless of how tall the nav gets when wrapped.
   ========================================================================== */

#site-header {
  position: relative;
}

#searchPanel {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1030;
  width: 100%;
  background: #fff;
  border-bottom: 1px solid rgba(0, 0, 0, .08);
  box-shadow: 0 20px 12.5px rgba(0, 0, 0, .1), 0 8px 5px rgba(0, 0, 0, .1);
}

#searchPanel .search-field {
  border-bottom: 2px solid #000;
}

#searchPanel .search-field input {
  border: 0;
  outline: 0;
  padding: 0;
  flex: 1 0 0;
  font-family: var(--font-condensed);
  font-size: 1.5rem;
  letter-spacing: .6px;
  color: #000;
}

#searchPanel .search-field input::placeholder {
  color: rgba(0, 0, 0, .3);
}

#searchPanel .search-field img {
  opacity: .4;
}

#searchPanel .popular-searches-label {
  font-family: var(--font-condensed);
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: 1.1px;
  text-transform: uppercase;
  color: rgba(0, 0, 0, .35);
}

#searchPanel .search-chip {
  border: 1px solid rgba(0, 0, 0, .15);
  border-radius: 50rem;
  padding: .5rem 1rem;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: .875rem;
  color: rgba(0, 0, 0, .6);
  background: #fff;
  transition: background-color .2s ease, border-color .2s ease;
}

#searchPanel .search-chip:hover {
  background: var(--bs-light);
  border-color: rgba(0, 0, 0, .3);
}

/* ==========================================================================
   Partner logo marquee — the track holds the logo set twice back to back;
   animating exactly -50% moves past one full set and lands on an
   identical frame, so the loop reads as continuous and never visibly
   resets.
   ========================================================================== */

.marquee {
  overflow: hidden;
  width: 100%;
  /* Fade the edges instead of hard-clipping logos mid-image — the loop
     itself already has no seam, but a hard clip at the container edge
     still reads as an abrupt cut. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 6rem, #000 calc(100% - 6rem), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 6rem, #000 calc(100% - 6rem), transparent 100%);
}

.marquee-track {
  display: flex;
  align-items: center;
  width: max-content;
  gap: 3rem;
  padding-inline: 1.5rem;
  animation: marquee-scroll 35s linear infinite;
}

.marquee:hover .marquee-track {
  animation-play-state: paused;
}

@keyframes marquee-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

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

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

/* Below xl the widget sits on top of a 2-column link grid. At xl the
   widget and the 4 link columns become one space-between row (the links
   grid uses display: contents so its columns join the parent flex), so
   the *visible* gap between every pair of blocks is identical — equal-width
   grid tracks would not be, since the widget's text is far wider than
   the link columns. */
.footer-top {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}

.footer-widget {
  width: 100%;
  max-width: 320px;
}

.footer-links-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: 3rem;
  row-gap: 2rem;
  width: 100%;
}

@media (min-width: 1200px) {
  .footer-top {
    flex-wrap: nowrap;
    justify-content: space-between;
    gap: 2rem;
    padding-right: 4rem;
  }

  .footer-widget {
    width: 320px;
    flex-shrink: 0;
  }

  .footer-links-grid {
    display: contents;
  }
}

.footer-social {
  width: 2.5rem;
  height: 2.5rem;
  background: rgba(255, 255, 255, .06);
  transition: background-color .2s ease;
}

.footer-social:hover,
.footer-social:focus-visible {
  background: rgba(255, 255, 255, .18);
}

.footer-social img {
  transition: transform .2s ease;
}

.footer-social:hover img,
.footer-social:focus-visible img {
  transform: scale(1.12);
}

/* Footer nav/legal links use --bs-secondary directly rather than the
   .text-secondary utility, since that utility sets color with !important
   and would beat a plain :hover override on the same element. */
.footer-link {
  color: var(--bs-secondary);
  transition: color .2s ease;
}

.footer-link:hover,
.footer-link:focus-visible {
  color: #fff;
}

/* ==========================================================================
   Shared page layout (contact + size chart): a title block, then a
   side rail (aside/sidebar) beside the main content from lg up.
   ========================================================================== */

.page-header {
  padding-block: 1.5rem;
}

.page-header h1 {
  margin-bottom: 1rem;
}

.page-layout {
  display: flex;
  flex-direction: column;
  gap: var(--page-layout-gap, 2.5rem);
}

.page-content {
  flex: 1 1 0%;
  min-width: 0;
}

@media (min-width: 992px) {
  .page-header {
    padding-block: 2.5rem;
  }

  .page-layout {
    flex-direction: row;
    align-items: flex-start;
    gap: 5rem;
  }
}

/* ==========================================================================
   Contact page (Figma 1372:4254)
   ========================================================================== */

.contact-main {
  padding-block: 1.5rem 3rem;
}

.contact-aside {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.contact-aside-block p {
  margin: 0;
  font-size: .875rem;
  line-height: 1.43;
}

.contact-aside-title {
  margin: 0 0 .625rem;
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
}

/* Lines the text up with the title, past its 18px icon and .5rem gap. */
.contact-aside-block p.contact-aside-indent {
  padding-left: calc(18px + .5rem);
}

.contact-aside p.contact-aside-note {
  font-size: .75rem;
  letter-spacing: .4px;
  color: #969696;
}

/* Two columns below lg, a single list in the sidebar from lg up. */
.contact-reps {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: 1.5rem;
}

@media (min-width: 992px) {
  .contact-reps {
    grid-template-columns: 1fr;
  }
}

.contact-rep {
  padding-block: 1rem;
  border-bottom: 1px solid #ddd;
}

.contact-rep-state {
  margin: 0 0 .25rem;
  font-style: normal;
  text-transform: none;
  font-size: 1.125rem;
  font-weight: 700;
  line-height: 1.45;
}

.contact-rep-detail {
  margin: 0;
  font-size: .875rem;
  line-height: 1.43;
  letter-spacing: .4px;
}

.contact-rep-detail a,
.contact-value a {
  color: inherit;
  text-decoration: none;
}

.contact-rep-detail a:hover,
.contact-value a:hover,
.contact-value a:focus-visible {
  text-decoration: underline;
}

@media (min-width: 992px) {
  .contact-main {
    padding-block: 2.5rem 5rem;
  }

  .contact-aside {
    flex: 0 0 320px;
    padding-right: 1.5rem;
  }
}

/* ---- Enquiry type cards: the selected one gets a black frame ---- */
/* Hidden on phones — the form's "Enquiry type" select does the same job. */
.enquiry-cards {
  display: none;
}

@media (min-width: 768px) {
  .enquiry-cards {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
  }
}

.enquiry-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 1.5rem;
  padding: 1.25rem 1.875rem;
  border: 2px solid #f6f6f6;
  transition: border-color .15s ease;
}

.enquiry-card:hover,
.enquiry-card.active {
  border-color: #000;
}

.enquiry-card-head {
  display: flex;
  align-items: center;
  gap: .75rem;
}

.enquiry-card-title {
  flex: 1 1 auto;
  margin: 0;
  font-size: 1.25rem;
  line-height: 1.2;
}

/* The whole card is the click target (stretched-link on the title button). */
.enquiry-card-select {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
}

.enquiry-card-text {
  margin: 0;
  font-size: .875rem;
  line-height: 1.43;
}

.enquiry-card:not(.active) .enquiry-card-text {
  color: #969696;
  transition: color .15s ease;
}

.enquiry-card:not(.active):hover .enquiry-card-text {
  color: inherit;
}

.enquiry-card-chevron {
  flex: 0 0 auto;
  opacity: .3;
  transition: transform .15s ease, opacity .15s ease;
}

.enquiry-card.active .enquiry-card-chevron {
  opacity: 1;
  transform: rotate(90deg);
}

.contact-form .btn {
  text-transform: none;
}

/* The order icon is exported upside-down from Figma (flipped mask). */
.enquiry-card[data-enquiry="order"] .enquiry-card-head > img:first-child {
  transform: scaleY(-1);
}

.enquiry-heading-row {
  margin: 1.5rem 0 1.25rem;
}

.enquiry-heading {
  font-size: 1.5rem;
  line-height: 1.375;
}

@media (min-width: 768px) {
  .enquiry-heading-row {
    margin-top: 2.5rem;
  }

  .enquiry-heading {
    font-size: 2rem;
  }
}

.enquiry-body {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

@media (min-width: 992px) {
  .enquiry-body {
    flex-direction: row;
    align-items: flex-start;
    gap: 2.5rem;
  }

  .contact-info {
    flex: 0 0 300px;
  }

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

.contact-info {
  display: flex;
  flex-direction: column;
  gap: 1.875rem;
  padding: 1.875rem;
  border: 1px solid #f4f4f4;
  border-radius: .75rem;
  background: #fafafa;
}

/* Phone and Email side by side above 400px, until the lg layout puts the
   panel in its own 300px column. */
@media (min-width: 401px) and (max-width: 991.98px) {
  .contact-info {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.875rem;
  }
}

.contact-label {
  margin: 0;
  font-size: .75rem;
  font-weight: 700;
  line-height: 1.33;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: #969696;
}

.contact-value {
  margin: .25rem 0 0;
  font-size: .875rem;
  letter-spacing: .4px;
  color: #000;
}

/* Figma fields are 12px-radius with a hairline border, not the site's
   default pill, so a multi-line message box matches the single-line ones. */
.contact-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.contact-form .form-control,
.contact-form .form-select {
  min-height: 3.5rem;
  border-color: #ddd;
  border-radius: .75rem;
  letter-spacing: .4px;
}

.contact-form textarea.form-control {
  min-height: 7.5rem;
  resize: vertical;
}

/* Black border on focus (same for the select and the floating inputs),
   replacing the default glow. */
.contact-form .form-control:focus,
.contact-form .form-select:focus {
  border-color: #000;
  box-shadow: none;
}

/* ---- Floating labels ---- */
.contact-form .form-floating > .form-control,
.contact-form .form-floating > .form-select {
  padding: 1.625rem 1rem .5rem;
  font-size: 1rem;
  line-height: 1.25;
  color: #000;
}

.contact-form .form-floating > .form-select {
  padding-right: 2.5rem;
}

.contact-form .form-floating > label {
  padding: 1rem;
  font-size: 1rem;
  letter-spacing: .4px;
  color: #969696;
  transition: opacity .15s ease, transform .15s ease, color .15s ease;
}

/* Resting placeholder text stays hidden so the label alone reads as the
   placeholder; once floated, the label shrinks to 12px above the value. */
.contact-form .form-floating > .form-control::placeholder {
  color: transparent;
}

.contact-form .form-floating > .form-control:focus ~ label,
.contact-form .form-floating > .form-control:not(:placeholder-shown) ~ label,
.contact-form .form-floating > .form-select ~ label {
  color: #969696;
  opacity: 1;
  transform: scale(.75) translateY(-.5rem) translateX(.15rem);
}

.contact-form .form-floating > .form-control:focus ~ label {
  color: #000;
}

/* Textarea: Bootstrap paints the label background white, which hides the
   value's first line once floated — make it transparent and let the
   textarea's own padding clear the label instead. */
.contact-form .form-floating > textarea.form-control {
  height: 7.5rem;
  min-height: 7.5rem;
  padding-top: 1.75rem;
}

.contact-form .form-floating > textarea.form-control ~ label::after {
  background: transparent;
}

/* ==========================================================================
   Size chart — garment sidebar + table
   ========================================================================== */

/* Global (not scoped to this page) since it's a document-level property —
   harmless elsewhere since no other page currently has in-page anchor
   links. Respects reduced motion like the hero carousel/promo bar do. */
html {
  scroll-behavior: smooth;
}

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

/* Mobile-first: picker, then sections stack. lg puts the picker in a
   sticky left rail; xl puts each section's diagram beside its table. */
.size-main {
  padding-bottom: 3rem;
}

.size-layout {
  --page-layout-gap: 1.5rem;
}

.size-content {
  display: flex;
  flex-direction: column;
  gap: 3rem;
}

/* Below lg the type picker (label, search, pills) stays pinned to the top
   while the tables scroll underneath. */
.size-sidebar {
  position: sticky;
  top: 0;
  z-index: 10;
  padding-block: .75rem;
  background: #fff;
}

@media (min-width: 992px) {
  .size-layout {
    padding-block: 1.5rem;
  }

  .size-sidebar {
    padding-block: 0;
    flex: 0 0 220px;
    position: sticky;
    top: 1.5rem;
    max-height: calc(100vh - 3rem);
    overflow-y: auto;
  }

  .size-content {
    gap: 5rem;
  }
}

/* ---- Segmented Centimeter / Inches toggle ---- */
.unit-toggle {
  display: inline-flex;
  gap: .5rem;
  padding: .5rem;
  background: #f4f4f4;
  border-radius: 2rem;
}

.unit-toggle-btn {
  border: 0;
  background: none;
  display: inline-flex;
  align-items: center;
  padding: .625rem .75rem;
  border-radius: 1.5rem;
  font-family: var(--font-body);
  font-size: .875rem;
  letter-spacing: .4px;
  line-height: 1;
  color: #696969;
  transition: background-color .15s ease, color .15s ease, box-shadow .15s ease;
}

.unit-toggle-btn.active {
  background: #fff;
  color: #000;
  font-size: 1rem;
  box-shadow: 0 2px 2px rgba(0, 0, 0, .02);
}

/* ---- Sidebar ---- */
.size-sidebar-label {
  margin: 0 0 .5rem;
  font-size: .8125rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: #bebebe;
}

.size-search-wrap {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-bottom: 1rem;
  padding: .5rem 1rem .5rem .75rem;
  border: 1px solid #ddd;
  border-radius: 2.25rem;
  background: #fff;
}

.size-search {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  outline: 0;
  background: none;
  padding: 0;
  font-size: .875rem;
  letter-spacing: .4px;
}

.size-search::placeholder {
  color: #969696;
}

.size-search-wrap:focus-within {
  border-color: #000;
}

.size-nav-empty {
  margin: 0;
  font-size: .875rem;
  color: #969696;
}

/* Mobile: one swipeable row of pills so 16 links don't push the tables
   off-screen. lg+: the Figma vertical list with a left-border marker. */
.size-nav {
  display: flex;
  flex-wrap: nowrap;
  gap: .5rem;
  overflow-x: auto;
  padding-bottom: .5rem;
  scrollbar-width: thin;
}

.size-nav-item {
  flex: 0 0 auto;
  padding: .5rem 1rem;
  border: 1px solid var(--bs-border-color);
  border-radius: 50rem;
  background: none;
  color: #969696;
  font-size: .875rem;
  font-weight: 700;
  letter-spacing: .4px;
  white-space: nowrap;
  text-align: left;
  transition: color .15s ease, background-color .15s ease, border-color .15s ease;
}

.size-nav-item:hover {
  color: #000;
}

.size-nav-item.active {
  border-color: #000;
  background: #000;
  color: #fff;
}

@media (min-width: 992px) {
  .size-nav {
    flex-direction: column;
    gap: .25rem;
    overflow: visible;
    padding-bottom: 0;
  }

  .size-nav-item {
    padding: .25rem .75rem .5rem;
    border: 0;
    border-left: 2px solid transparent;
    border-radius: 0;
    font-size: 1rem;
    white-space: normal;
  }

  .size-nav-item.active {
    border-left-color: #000;
    background: none;
    color: #000;
  }
}

/* ---- Sections: heading, table, diagram ---- */
.size-section-heading {
  margin: 0 0 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid #000;
  font-family: var(--font-body);
  font-size: 1.5rem;
  font-weight: 700;
  font-style: normal;
  line-height: 1.2;
  text-transform: none;
}

/* Below lg the diagram image is dropped and only its "How to measure?"
   link is kept, on the right of the section title. That works by
   flattening the section body / diagram wrappers (display: contents) so
   title, link and tables are all direct children of the section grid:
   the title spans the row (so its rule runs full width) and the link
   shares that row, pushed right. From lg up they are real boxes again
   (see below). */
.size-section {
  display: grid;
  grid-template-columns: 100%;
}

.size-section-heading {
  grid-area: 1 / 1;
}

.size-section-body,
.size-diagram {
  display: contents;
}

.size-diagram-img {
  display: none;
}

.size-diagram-link {
  grid-area: 1 / 1;
  align-self: start;
  justify-self: end;
  margin-top: .35rem;
}

@media (min-width: 768px) {
  .size-diagram-link {
    margin-top: .7rem;
  }
}

@media (min-width: 992px) {
  .size-section {
    display: block;
  }

  .size-section-body {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
  }

  .size-diagram {
    display: flex;
  }

  .size-diagram-img {
    display: block;
  }

  .size-diagram-link {
    align-self: auto;
    margin-top: 0;
  }
}

@media (min-width: 768px) {
  .size-section-heading {
    font-size: 2.25rem;
  }
}

@media (min-width: 1200px) {
  /* Figma column widths: size 140, garment table 280, rest shared. */
  .size-table-wrap-body .size-table {
    table-layout: fixed;
  }

  /* Fixed layout reads column widths from the first row, which is the
     full-width title cell (colspan), so the width has to sit on the <col>. */
  .size-table-wrap-body .size-col-first {
    width: 140px;
  }

  .size-tables .size-table-wrap-garment {
    flex: 0 0 280px;
  }
}

/* Tables always span the full section width; the diagram only sits beside
   them when there is room for the Figma proportions (880 + 360), otherwise
   it drops underneath. */
@media (min-width: 1600px) {
  .size-section-body {
    flex-direction: row;
    align-items: flex-start;
    gap: 2.5rem;
  }

  .size-tables {
    flex: 1 1 0%;
    width: auto;
  }

  .size-diagram {
    flex: 0 0 360px;
    margin-left: auto;
  }
}

.size-diagram {
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding: 1.25rem;
}

.size-diagram-img {
  width: 100%;
  max-width: 320px;
  height: auto;
}

.size-diagram-img.is-kids {
  max-width: 226px;
}

.size-diagram-link {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  padding: 0;
  border: 0;
  background: none;
  font-size: .875rem;
  font-weight: 700;
  color: #000;
}

.size-diagram-link:hover {
  text-decoration: underline;
}

/* ---- Table (Figma: heavy rule under the header, hairline rows, zebra) ---- */
.size-table {
  --bs-table-bg: transparent;
  width: 100%;
}

.size-table th,
.size-table td {
  padding: .75rem .5rem;
  border: 0;
  text-align: left;
  letter-spacing: .55px;
  font-family: var(--font-body);
  vertical-align: middle;
}

.size-table thead tr:first-child th {
  padding-left: 0;
  white-space: nowrap;
  padding-block: 1rem;
  font-size: 1rem;
  font-weight: 700;
}

.size-table thead tr:last-child th {
  border-bottom: 3px solid #000;
  font-size: .8125rem;
  font-weight: 700;
  text-transform: uppercase;
}

.size-table tbody th,
.size-table tbody td {
  border-bottom: 1px solid rgba(0, 0, 0, .05);
  font-size: .875rem;
  white-space: nowrap;
}

.size-table tbody th {
  font-weight: 700;
  text-transform: uppercase;
}

.size-table tbody tr:nth-of-type(even) > * {
  background: #fafafa;
}

/* Body table + garment table, side by side with a 20px gap. */
.size-tables {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  width: 100%;
  min-width: 0;
}

.size-table-wrap {
  min-width: 0;
}

.size-table-wrap-body {
  flex: 1 1 0%;
}

.size-table-wrap-garment {
  flex: 0 0 auto;
}

@media (min-width: 768px) {
  .size-tables {
    flex-direction: row;
    gap: 1.25rem;
  }
}

.size-note {
  margin-left: .5rem;
  font-size: .75rem;
  font-weight: 400;
  color: #969696;
}

@media (min-width: 768px) {
  .size-table th,
  .size-table td {
    padding: 1rem .5rem;
  }

  .size-table tbody th,
  .size-table tbody td {
    font-size: 1rem;
  }
}

/* Black round badge used by the "How to Measure" modal callouts — the
   letter matches the one circled on the diagram. */
.size-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;
  padding: .25rem .625rem;
  border-radius: 50rem;
  background: #000;
  color: #fff;
  font-family: var(--font-condensed);
  font-weight: 700;
  font-size: .8125rem;
}

.size-chip-callout {
  flex-shrink: 0;
  width: 1.75rem;
  height: 1.75rem;
  min-width: 0;
  padding: 0;
  border-radius: 50%;
}

/* Modal corners stay square, same as this brand's flat/square cards
   (see .card above) — only buttons and chips are rounded. Bootstrap sets
   --bs-modal-border-radius directly on .modal-content, so the override
   has to live on that same selector rather than :root. */
.modal-content {
  --bs-modal-border-radius: 0;
}


/* ---- "How to measure" modal (Figma 1560:2406): 800px, 30px gutters ---- */
.measure-modal .modal-header,
.measure-modal .modal-body,
.measure-modal .modal-footer {
  padding-inline: 1.25rem;
  border: 0;
}

.measure-modal .modal-header {
  justify-content: space-between;
  padding-block: 1.25rem .5rem;
}

.measure-modal .modal-title {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.3;
  text-transform: none;
}

/* 40px circular close button on the light surface colour. */
.measure-modal .btn-close,
.offcanvas .btn-close {
  width: 2.5rem;
  height: 2.5rem;
  margin: 0 0 0 auto;
  padding: 0;
  border-radius: 50%;
  background-color: #fafafa;
  background-size: 1rem;
  background-position: center;
  opacity: 1;
}

#site-header {
  display: contents;
}

.site-sticky {
  position: sticky;
  top: 0;
  z-index: 1020;
  background: #fff;
}

@media (min-width: 992px) {
  .hero-tagline {
    font-size: 2rem !important;
  }
}

.fs-12 {
  font-size: .75rem;
}

.measure-intro {
  margin: 0;
  font-size: .875rem;
  line-height: 1.43;
  letter-spacing: .4px;
}

.measure-guide {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
  padding-block: 1.5rem;
}

.measure-guide-img {
  width: 100%;
  max-width: 280px;
  height: auto;
}

.measure-items {
  display: flex;
  flex-direction: column;
  gap: 2rem;
  width: 100%;
}

.measure-item {
  display: flex;
  gap: .9375rem;
}

.measure-item-title {
  margin: 0 0 .5rem;
  font-family: var(--font-body);
  font-size: 1.125rem;
  font-weight: 700;
  font-style: normal;
  line-height: 1.33;
  text-transform: none;
}

.measure-item-text {
  margin: 0;
  font-size: .875rem;
  line-height: 1.43;
  letter-spacing: .4px;
  color: #696969;
}

.measure-extra {
  display: grid;
  gap: 1.25rem;
  padding-block: 1.25rem;
  border-top: 1px solid #f4f4f4 !important;
  text-align: left;
}

.measure-extra > div {
  margin: 0;
}

.measure-extra-title {
  margin: 0 0 .25rem;
  font-family: var(--font-body);
  font-size: .75rem;
  font-weight: 700;
  font-style: normal;
  line-height: 1.33;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}

.measure-extra-text {
  margin: 0;
  font-size: .875rem;
  line-height: 1.625;
  color: #696969;
}

@media (min-width: 768px) {
  .measure-modal .modal-header,
  .measure-modal .modal-body,
  .measure-modal .modal-footer {
    padding-inline: 1.875rem;
  }

  .measure-modal .modal-header {
    padding-block: 1.25rem .75rem;
  }

  .measure-modal .modal-title {
    font-size: 1.75rem;
  }

  .measure-guide {
    flex-direction: row;
    align-items: flex-start;
    gap: 2.5rem;
    padding-block: 2.5rem;
  }

  .measure-guide-img {
    flex: 0 0 280px;
  }

  .measure-items {
    flex: 1 1 0%;
    min-width: 0;
  }

  .measure-extra {
    grid-template-columns: 1fr 1fr;
    gap: 1.375rem;
    padding-block: 1.875rem;
  }
}

.measure-category {
  margin: 0;
  font-size: .75rem;
  line-height: 1.33;
  letter-spacing: .4px;
  text-transform: uppercase;
  color: #969696;
}

/* Testimonial slider: every slide sits in the same grid cell, so the
   carousel is always as tall as its tallest quote and the prev/next
   buttons below it never move. Bootstrap hides inactive slides with
   display:none, which would take them out of the height calculation, so
   they are hidden with visibility instead. */
.testimonial-carousel .carousel-inner {
  display: grid;
}

.testimonial-carousel .carousel-item {
  display: block;
  grid-area: 1 / 1;
  margin-right: 0;
  visibility: hidden;
}

.testimonial-carousel .carousel-item.active,
.testimonial-carousel .carousel-item-next,
.testimonial-carousel .carousel-item-prev {
  visibility: visible;
}

.testimonial-quote {
  line-height: 1.75;
}

/* Fade rather than slide, and sequenced: Bootstrap's fade keeps the
   outgoing slide fully opaque while the incoming one fades in over it, so
   two different quotes are readable on top of each other. Here the
   outgoing quote drops out almost immediately and the incoming one only
   starts to appear once it's gone. Both keep Bootstrap's .6s duration, which
   is what its transition-end cleanup waits for. */
.testimonial-carousel.carousel-fade .active.carousel-item-start,
.testimonial-carousel.carousel-fade .active.carousel-item-end {
  transition: opacity .6s cubic-bezier(0, 1, 0, 1);
}

.testimonial-carousel.carousel-fade .carousel-item-next.carousel-item-start,
.testimonial-carousel.carousel-fade .carousel-item-prev.carousel-item-end {
  transition: opacity .6s cubic-bezier(.7, 0, 1, .6);
}

@media (prefers-reduced-motion: reduce) {
  .testimonial-carousel.carousel-fade .carousel-item {
    transition: none;
  }
}

.testimonial-rule {
  width: 60px;
}

/* Below lg the "How to measure" modal spans the full viewport width. */
@media (max-width: 991.98px) {
  .measure-modal .modal-dialog {
    --bs-modal-margin: 0;
    max-width: none;
  }
}

/* ==========================================================================
   Checkout page: form (reuses .contact-form field styling) + order summary
   ========================================================================== */

.checkout-fieldset-title {
  margin: 1rem 0 0;
  font-size: 1rem;
  font-weight: 700;
}

/* Checkbox / radio: primary (black) when checked — Bootstrap hardcodes its
   own blue on :checked rather than reading --bs-primary. */
.form-check-input:checked,
.form-check-input[type="checkbox"]:indeterminate {
  background-color: var(--bs-primary);
  border-color: var(--bs-primary);
}

.form-check-input:focus {
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 .25rem rgba(var(--bs-primary-rgb), .15);
}

/* Delivery option: the whole row is one click target (the label fills it);
   checked state is a 2px black outline over a light tint. */
.checkout-option {
  position: relative;
  padding: 0;
  margin-bottom: .75rem;
  border: 1px solid #ddd;
  border-radius: .75rem;
  transition: border-color .2s ease, box-shadow .2s ease, background-color .2s ease;
}

.checkout-option:hover {
  border-color: #999;
}

.checkout-option .form-check-input {
  position: absolute;
  top: 50%;
  left: 1.25rem;
  margin: -.5rem 0 0;
}

.checkout-option .form-check-label {
  align-items: center;
  padding: 1.125rem 1.25rem 1.125rem 3.25rem;
  cursor: pointer;
}

.checkout-option:has(input:checked) {
  border-color: #000;
  box-shadow: 0 0 0 1px #000;
  background: #f7f7f7;
}

.checkout-summary {
  padding: 0;
}

.checkout-summary summary {
  cursor: pointer;
  list-style: none;
}

.checkout-summary summary::-webkit-details-marker {
  display: none;
}

.checkout-summary summary img {
  transform: rotate(90deg);
}

.checkout-summary details[open] summary img {
  transform: rotate(-90deg);
}

@media (min-width: 992px) {
  .checkout-summary {
    flex: 0 0 26rem;
    position: sticky;
    top: 1.5rem;
  }
}

/* Bag page quantity stepper: one hairline box, borderless − / + and number
   (same border and radius as the form fields). */
.qty-stepper {
  border: 1px solid #ddd;
  border-radius: .75rem;
}

.qty-stepper .btn,
.qty-stepper .form-control {
  border: 0;
  background: transparent;
  box-shadow: none;
}

/* .btn-sm / .form-control-sm on the markup keep the global default-size
   padding/height rules (4-class :not() chains) from applying here. */
.qty-stepper .btn {
  width: 2.25rem;
  height: 2.5rem;
  padding: 0;
  color: #000;
}

.qty-stepper .form-control {
  width: 2.5rem;
  height: 2.5rem;
  min-height: 0;
  padding: 0;
  border-radius: 0;
  font-size: .875rem;
  appearance: textfield;
  -moz-appearance: textfield;
}

.qty-stepper .form-control::-webkit-inner-spin-button,
.qty-stepper .form-control::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.bag-remove {
  font-weight: 400;
  color: #a7a7a7 !important;
}

/* Bag: first item sits flush under the title (no top rule or padding). */
.bag-items > li:first-child {
  padding-top: 0 !important;
}

.checkout-summary .input-group > .btn {
  height: 2.875rem;
}

.summary-legal-link {
  color: var(--bs-secondary);
  font-weight: 700;
  text-decoration: none;
  transition: color .2s ease;
}

.summary-legal-link:hover,
.summary-legal-link:focus-visible {
  color: #000;
  text-decoration: underline;
}

/* Checkout: larger section titles. */
.checkout-fieldset-title {
  font-size: 1.25rem;
  margin-top: 2rem;
}

.flip-x {
  transform: scaleX(-1);
}

.signin-prompt {
  background: #fafafa;
}

/* Billing fields sit inside a collapse, so they miss .contact-form's flex gap. */
.billing-fields {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Parallax full-width image: the image is 20% taller than its frame and
   initParallax() in main.js slides it up as the frame scrolls through the
   viewport. Without JS it just shows static. */
.parallax {
  overflow: hidden;
}

.parallax > img {
  height: 120%;
  will-change: transform;
}

.checkout-note-text {
  letter-spacing: .4px;
}
