/* =========================================================================
   FITZROY OF LONDON - SEARCH RESULTS
   =========================================================================
   ADDITIVE. Append to the search results module's CSS tab. Nothing here
   overrides an existing theme rule. Every selector is namespaced `fz-`
   except the theme classes reused below, which are used, not redefined.

   -------------------------------------------------------------------------
   THEME THINGS THIS FILE RELIES ON
   -------------------------------------------------------------------------
   Read from the live stylesheets on 15 Sep 2026.

   1. Custom properties from template_main.css:
        --gold: #C58E34;  --dark-gold: #76551F;  --black: #000;
        --white: #fff;    --grey: #D9D9D9;       --blue-5: #F7F8FB;
        --transition: 0.5s ease-in-out;
      Every use below has a literal fallback, so this file still renders
      correctly if a property is renamed or dropped.

   2. .content-wrapper { max-width: 1400px; padding: 0 32px; margin: 0 auto }
      Used by module.html. Not redefined here.

   3. .primary-cta { text-transform: uppercase; letter-spacing: 2px;
        font-size: 14px } and .primary-cta--small { font-size: 10px;
        padding: 15px 30px }, plus .solid-gold-cta (filled) and .gold-cta
        (outlined). The empty state uses .solid-gold-cta, "Show more" uses
        .gold-cta. Both are theme classes; this file only adds spacing.

   4. .highlight { background: var(--gold); color: #fff; padding: 4px }
      Already defined by the theme and used by the header search. The rule
      below is scoped to <mark> only, to cancel the browser's default yellow
      mark background and to stop 4px of vertical padding forcing line
      boxes apart in a paragraph. It does not change .highlight elsewhere.

   5. Fonts: 'loretta-display' (serif) for headings, 'aktiv-grotesk-extended'
      for body copy. Both loaded by the theme. Fallback stacks are written
      out in full so the preview and any page missing the font render sanely.

   -------------------------------------------------------------------------
   DESIGN NOTES THAT ARE NOT COSMETIC
   -------------------------------------------------------------------------
   * Article cards are image led. Blog posts return featuredImageUrl 20 times
     out of 20.
   * Case study and page cards are TEXT LED. Case studies return a featured
     image 1 time in 20, so an image-first layout would show a placeholder as
     its normal state. The optional image is a side strip the layout does not
     reserve space for.
   * The product card image is hidden below 900px, matching the behaviour of
     the module this replaces.
   * Focus is never removed. :focus-visible is used where supported, with a
     plain :focus fallback first so older browsers still get a ring.
   ========================================================================= */

/* =========================================================================
   1. SHELL
   ========================================================================= */

.fz-search {
  --fz-gold: var(--gold, #c58e34);
  --fz-dark-gold: var(--dark-gold, #76551f);
  --fz-black: var(--black, #000);
  --fz-white: var(--white, #fff);
  --fz-grey: var(--grey, #d9d9d9);
  --fz-tint: var(--blue-5, #f7f8fb);
  --fz-body: 'aktiv-grotesk-extended', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --fz-display: 'loretta-display', Georgia, 'Times New Roman', serif;

  color: var(--fz-black);
  font-family: var(--fz-body);
  padding: 64px 0 96px;
}

.fz-search *,
.fz-search *::before,
.fz-search *::after {
  box-sizing: border-box;
}

/*
 * The `hidden` attribute is how every section in this module is shown and
 * hidden. A `display` rule anywhere below would otherwise beat the user-agent
 * `[hidden] { display: none }`, which is exactly what happened with the
 * loading skeleton: `display: grid` kept a 320px shimmer on screen after the
 * results had rendered. This rule makes `hidden` mean hidden, full stop.
 */
.fz-search [hidden] {
  display: none !important;
}

/* One focus treatment for everything interactive in the module. */
.fz-search a:focus,
.fz-search button:focus,
.fz-search input:focus {
  outline: 2px solid var(--fz-dark-gold);
  outline-offset: 3px;
}

@supports selector(:focus-visible) {
  .fz-search a:focus,
  .fz-search button:focus,
  .fz-search input:focus {
    outline: none;
  }
  .fz-search a:focus-visible,
  .fz-search button:focus-visible,
  .fz-search input:focus-visible {
    outline: 2px solid var(--fz-dark-gold);
    outline-offset: 3px;
  }
}

/* =========================================================================
   2. HEAD: eyebrow, query echo, refine form, live count
   ========================================================================= */

.fz-search__eyebrow {
  color: var(--fz-dark-gold);
  font-size: 11px;
  letter-spacing: 2px;
  margin: 0 0 12px;
  text-transform: uppercase;
}

.fz-search__title {
  font-family: var(--fz-display);
  font-size: clamp(30px, 4vw, 52px);
  font-weight: 400;
  line-height: 1.15;
  margin: 0 0 24px;
  /* loretta-display ships text (old style) figures, so digits are drawn at x-height with
     descenders. Beside capitals in a product code such as FL01-010-00-E01P they read as
     the wrong size, which is UAT 869f8uf20 and 869f8ugaz. Ask for lining figures instead.
     Measured: this changes the rendered advance, so it is not a no-op on this webfont.
     Added 30 Sep 2026. */
  font-variant-numeric: lining-nums;
  font-feature-settings: "lnum" 1, "onum" 0;
}

.fz-search__title__lead {
  display: block;
  font-size: 0.5em;
  letter-spacing: 1px;
  opacity: 0.6;
  text-transform: uppercase;
}

/* The query is user input echoed back. It is set with textContent, and
   wrapping is forced so a pasted 300-character string cannot break layout. */
.fz-search__term {
  overflow-wrap: anywhere;
  word-break: break-word;
}

.fz-search__refine {
  align-items: stretch;
  display: flex;
  gap: 0;
  margin: 0 0 24px;
  max-width: 640px;
  /* The theme sets a global `form { padding: 45px }` in
     template_theme-overrides.min.css, intended for HubSpot's own forms. That
     wrapped this 55px input in 90px of dead space. Scoped to this form only,
     so every other form on the site keeps the theme's padding. */
  padding: 0;
  position: relative;
}

/* Visually hidden, still read. Used for both the field label and the submit
   button's text, so the button has an accessible name without visible text. */
.fz-search__refine__label {
  border: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

.fz-search__refine__field {
  background-color: var(--fz-white);
  border: 1px solid var(--fz-grey);
  border-right: 0;
  color: var(--fz-black);
  flex: 1 1 auto;
  font-family: var(--fz-body);
  font-size: 15px;
  font-weight: 300;
  min-width: 0;
  padding: 18px 20px;
}

.fz-search__refine__submit {
  align-items: center;
  background-color: var(--fz-black);
  border: 1px solid var(--fz-black);
  cursor: pointer;
  display: flex;
  flex: 0 0 auto;
  justify-content: center;
  padding: 0 28px;
  transition: background-color 0.2s ease-in-out;
}

.fz-search__refine__submit:hover {
  background-color: var(--fz-dark-gold);
  border-color: var(--fz-dark-gold);
}

.fz-search__refine__submit img {
  display: block;
  filter: invert(1);
}

.fz-search__count {
  color: #4a4a4a;
  flex: 0 0 auto;
  font-size: 13px;
  letter-spacing: 0.5px;
  margin: 0;
  min-height: 1.4em; /* reserve the line so the row does not jump on load */
  padding-bottom: 10px;
}

/* =========================================================================
   3. TABS
   ========================================================================= */

/* Tabs and the result count on one row. The border lives here so both align
   to the same rule, and wrapping is allowed so the count drops below the tabs
   on narrow screens rather than squeezing them. */
.fz-search__filters {
  align-items: baseline;
  border-bottom: 1px solid var(--fz-grey);
  column-gap: 24px;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  margin: 24px 0 0;
}

.fz-search__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0;
}

.fz-tab {
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: #4a4a4a;
  cursor: pointer;
  display: inline-flex;
  font-family: var(--fz-body);
  font-size: 12px;
  gap: 8px;
  letter-spacing: 1.5px;
  margin-bottom: -1px;
  padding: 16px 20px;
  text-transform: uppercase;
  transition: color 0.2s ease-in-out, border-color 0.2s ease-in-out;
}

.fz-tab:hover {
  color: var(--fz-black);
}

.fz-tab[aria-selected='true'] {
  border-bottom-color: var(--fz-gold);
  color: var(--fz-black);
  font-weight: 500;
}

.fz-tab__count {
  color: var(--fz-dark-gold);
  font-variant-numeric: tabular-nums;
}

.fz-tab__count:empty {
  display: none;
}

.fz-search__panel {
  padding-top: 40px;
}

.fz-search__panel:focus {
  outline: none; /* the panel is programmatically focusable, not a control */
}

/* =========================================================================
   4. LOADING SKELETON
   ========================================================================= */

.fz-search__loading {
  display: grid;
  gap: 16px;
}

.fz-skeleton {
  background: linear-gradient(90deg, var(--fz-tint) 25%, #eceef4 37%, var(--fz-tint) 63%);
  background-size: 400% 100%;
  animation: fz-shimmer 1.4s ease-in-out infinite;
}

.fz-skeleton--row {
  height: 96px;
}

@keyframes fz-shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* Respect the OS setting. A shimmer is decoration, not information. */
@media (prefers-reduced-motion: reduce) {
  .fz-skeleton {
    animation: none;
  }
  .fz-search * {
    transition: none !important;
  }
}

/* =========================================================================
   5. GROUPS
   ========================================================================= */

.fz-group + .fz-group {
  margin-top: 56px;
}

.fz-group__head {
  align-items: baseline;
  border-bottom: 1px solid var(--fz-grey);
  display: flex;
  gap: 16px;
  justify-content: space-between;
  margin-bottom: 24px;
  padding-bottom: 12px;
}

.fz-group__title {
  font-family: var(--fz-display);
  font-size: 24px;
  font-weight: 400;
  margin: 0;
}

.fz-group__count {
  color: #4a4a4a;
  font-size: 12px;
  letter-spacing: 1px;
  text-transform: uppercase;
  white-space: nowrap;
}

.fz-group__list {
  display: grid;
  gap: 16px;
}

.fz-group__more {
  display: inline-block;
  margin-top: 28px;
  text-decoration: none;
}

.fz-group__error {
  background-color: var(--fz-tint);
  border-left: 3px solid var(--fz-dark-gold);
  font-size: 14px;
  margin: 0;
  padding: 16px 20px;
}

.fz-search__tabempty {
  color: #4a4a4a;
  font-size: 14px;
  margin: 0;
  padding: 24px 0;
}

/* =========================================================================
   6. CARDS
   ========================================================================= */

.fz-card {
  background-color: var(--fz-white);
  border: 1px solid var(--fz-grey);
  display: flex;
  gap: 24px;
  padding: 20px;
  transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}

.fz-card:hover {
  border-color: var(--fz-gold);
  box-shadow: 10px 10px 48px -19px rgba(0, 0, 0, 0.1);
}

.fz-card__body {
  flex: 1 1 auto;
  min-width: 0; /* lets long words wrap instead of stretching the grid */
}

.fz-card__kicker {
  color: var(--fz-dark-gold);
  font-size: 10px;
  letter-spacing: 2px;
  margin: 0 0 8px;
  text-transform: uppercase;
}

.fz-card__title {
  font-family: var(--fz-display);
  font-size: 19px;
  font-weight: 400;
  line-height: 1.35;
  margin: 0 0 8px;
  overflow-wrap: anywhere;
}

.fz-card__link {
  color: var(--fz-black);
  text-decoration: none;
}

.fz-card__link:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* The whole card is clickable, but the <a> remains the real control, so
   keyboard and screen reader behaviour is unchanged and the link target is
   announced normally. */
.fz-card__link::after {
  content: '';
  inset: 0;
  position: absolute;
}

.fz-card {
  position: relative;
}

/* The variant links sit above the card-wide overlay so they stay clickable. */
.fz-variants {
  position: relative;
  z-index: 1;
}

.fz-card__desc {
  color: #4a4a4a;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  font-size: 14px;
  line-height: 1.6;
  margin: 0 0 8px;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.fz-card__meta {
  color: #6a6a6a;
  font-size: 12px;
  letter-spacing: 0.5px;
  margin: 0;
  overflow-wrap: anywhere;
}

/* ---- media --------------------------------------------------------------
   Image-led (products, articles): a fixed 160px column.
   Text-led (case studies, pages): a 120px strip AFTER the body in source
   order, so a card with no image is simply a card with no image. No
   placeholder, no reserved empty box.
   ------------------------------------------------------------------------ */

.fz-card__media {
  background-color: var(--fz-tint);
  flex: 0 0 160px;
  height: 130px;
  overflow: hidden;
}

.fz-card__media--aside {
  flex: 0 0 120px;
  height: 96px;
}

.fz-card__img {
  display: block;
  height: 100%;
  object-fit: cover;
  width: 100%;
}

/* =========================================================================
   7. VARIANT ACCORDION
   -------------------------------------------------------------------------
   max-height animation, as in the module this replaces. The list also
   carries the `hidden` attribute when collapsed, so collapsed variant links
   are out of the tab order and out of the accessibility tree. `hidden` and
   max-height are set together by search-results.js.
   ========================================================================= */

.fz-variants {
  margin-top: 14px;
}

.fz-variants__toggle {
  align-items: center;
  background: none;
  border: 0;
  color: var(--fz-dark-gold);
  cursor: pointer;
  display: inline-flex;
  font-family: var(--fz-body);
  font-size: 11px;
  gap: 8px;
  letter-spacing: 1.5px;
  padding: 6px 0;
  text-transform: uppercase;
}

.fz-variants__toggle__chevron {
  border-bottom: 1px solid currentColor;
  border-right: 1px solid currentColor;
  display: inline-block;
  height: 6px;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 0.2s ease-in-out;
  width: 6px;
}

.fz-variants__toggle[aria-expanded='true'] .fz-variants__toggle__chevron {
  transform: rotate(-135deg) translate(-2px, -2px);
}

.fz-variants__list {
  list-style: none;
  margin: 8px 0 0;
  max-height: 0;
  overflow: hidden;
  padding: 0;
  transition: max-height 0.3s ease-in-out;
}

.fz-variants.is-open .fz-variants__list {
  max-height: 60vh;
  overflow-y: auto;
}

.fz-variants__item {
  border-top: 1px solid var(--fz-grey);
}

.fz-variants__link {
  color: var(--fz-black);
  display: flex;
  gap: 16px;
  justify-content: space-between;
  padding: 10px 0;
  text-decoration: none;
}

.fz-variants__link:hover {
  color: var(--fz-dark-gold);
}

.fz-variants__name {
  font-size: 13px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.fz-variants__code {
  font-size: 12px;
  letter-spacing: 1px;
  white-space: nowrap;
}

/* =========================================================================
   8. HIGHLIGHT
   -------------------------------------------------------------------------
   .highlight already exists in the theme (gold background, white text, 4px
   padding). Scoped here to <mark> only: cancels the browser's default yellow
   and trims the vertical padding so highlighted words inside a paragraph do
   not push the line boxes apart.
   ========================================================================= */

.fz-search mark.highlight {
  background-color: var(--fz-gold);
  color: var(--fz-white);
  padding: 0 3px;
}

/* =========================================================================
   9. OVERALL EMPTY STATE
   ========================================================================= */

.fz-search__empty {
  background-color: var(--fz-tint);
  max-width: 720px;
  padding: 48px 40px;
}

.fz-search__empty__title {
  font-variant-numeric: lining-nums;
  font-feature-settings: "lnum" 1, "onum" 0;
  font-family: var(--fz-display);
  font-size: 26px;
  font-weight: 400;
  margin: 0 0 16px;
  overflow-wrap: anywhere;
}

.fz-search__empty__body {
  color: #4a4a4a;
  font-size: 14px;
  line-height: 1.7;
  margin: 0 0 24px;
  max-width: 56ch;
}

.fz-search__empty__links {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  list-style: none;
  margin: 0 0 32px;
  padding: 0;
}

.fz-search__empty__links a {
  color: var(--fz-black);
  font-size: 13px;
  letter-spacing: 1px;
  text-underline-offset: 4px;
}

.fz-search__empty .primary-cta {
  display: inline-block;
  text-decoration: none;
}

/* =========================================================================
   10. RESPONSIVE
   ========================================================================= */

@media screen and (max-width: 900px) {
  /* Matches the module this replaces: below 900px the product image is
     dropped rather than shrunk, so the name, code and variants keep the
     full width. Article images are kept: they are the card's subject. */
  .fz-card--product .fz-card__media {
    display: none;
  }
  .fz-card__media--aside {
    display: none;
  }
}

/* Narrow screens: the four tab labels total ~529px, so side by side with the
   count they squeezed the tab strip to 247px and wrapped it onto four lines
   (136px tall). Stack instead, and let the strip scroll horizontally on one
   line rather than wrap. Keyboard users are unaffected: arrow-key navigation
   focuses each tab and the browser scrolls it into view. */
@media screen and (max-width: 640px) {
  .fz-search__filters {
    align-items: stretch;
    flex-direction: column;
    row-gap: 4px;
  }

  .fz-search__tabs {
    /* Four tabs need 529px. The page nests two content wrappers (20px + 32px
       padding), leaving 247px. A horizontal scroll strip was tried first and
       rejected: it hid Articles behind an edge with no reliable cue, and the
       viewport-based breakout it needed measured 620px wide inside a 375px
       screen. Wrapping is simpler and hides nothing.

       min-width:0 is still required. A flex item will not shrink below its
       content by default, which is what let the strip overflow in the first
       place. */
    flex-wrap: wrap;
    min-width: 0;
    row-gap: 0;

    /* Pull out to the edge of the inner content wrapper only (32px, a fixed
       value from the theme, not a viewport calculation). 247px -> 311px, which
       fits the four tabs onto two lines instead of three. */
    margin-inline: -32px;
    padding-inline: 32px;
  }

  .fz-search__tabs::-webkit-scrollbar {
    display: none;
  }

  .fz-tab {
    flex: 0 0 auto;
  }

  .fz-search__count {
    padding-bottom: 10px;
  }
}

@media screen and (max-width: 640px) {
  .fz-search {
    padding: 40px 0 64px;
  }
  .fz-search__panel {
    padding-top: 28px;
  }
  .fz-card {
    flex-direction: column;
    gap: 16px;
  }
  .fz-card--article .fz-card__media {
    flex: 0 0 auto;
    height: 180px;
    width: 100%;
  }
  .fz-tab {
    /* Kept at 12px. Tightening to 8px was tried to fit the tabs onto two rows
       and did not work: the strip's breakout adds 32px of padding back, so
       flex still wraps at the 247px content box. No row was saved, so the
       roomier tap target stays.
       NB this shorthand sits later in the file than the tab rules above and
       overrides any padding-inline set there. Change it here, not there. */
    padding: 14px 12px;
  }
  .fz-search__refine {
    flex-wrap: wrap;
  }
  .fz-search__refine__field {
    border-right: 1px solid var(--fz-grey);
    width: 100%;
  }
  .fz-search__refine__submit {
    justify-content: center;
    padding: 14px;
    width: 100%;
  }
  .fz-variants__link {
    flex-direction: column;
    gap: 4px;
  }
  .fz-search__empty {
    padding: 32px 24px;
  }
}
