/* ==========================================================================
   One Identity — Filterable listing

   One stylesheet for every listing that is a letter rail plus a grid of
   cards: the A-Z Product Index, Contact Sales, Trials. Enqueued by
   inc/listing/listing-assets.php on any page whose content carries a
   [data-oi-list] root. Pairs with assets/js/oi-listing.js.

   Nothing here is scoped to one page. What tells the listings apart is the
   id on the root — #az-listing, #cs-listing, #trial-listing — and anything
   that has to differ between them hangs off that id, in its own section at
   the end of this file rather than scattered through it.

   ⚠️ A CONTAINER HOLDING A CONTROL GOES ON ONE LINE IN THE MARKUP.
   These listings render through the OI - HTML block, whose field passes
   through wpautop(). label, select, input and button are not block level to
   wpautop, so a blank line around them becomes a stray paragraph and a single
   newline becomes a line break — which is what once pushed the two selects
   out of line with each other. .oi-list-bar, .oi-list-filters and
   .oi-list-search-wrap are therefore written as one line each. Every other
   element is block level and keeps its indentation.

   Hand-written, NOT compiled from SCSS. It is the one stylesheet in the
   theme that is not, because it is ten kilobytes that only one page needs
   and folding it into theme.scss would ship it on all of them. Do not look
   for a source partial in assets/sass/ — this file is the source.

   Every colour and face comes from the theme tokens that theme.css already
   puts on :root, with the literal from the design sheet as a fallback so the
   component still renders if it is ever pasted somewhere the theme is absent.

   One value is NOT a token yet: loblolly #CAD4D7, the inactive letter. It is
   declared once below. If it turns up in another component, promote it to
   $oi-secondary-loblolly in assets/sass/abstracts/_site-oi.scss and delete it
   from here — see actualiza.md for why brand colours live in tokens.

   Solid CTAs deliberately reuse the theme's own .btn-v3 / .btn-arrow instead
   of redeclaring them: the design sheet for these buttons is the same one the
   rest of the site already follows, and duplicating it would let the two
   drift apart.
   ========================================================================== */

.oi-list {
  --oi-list-ink: var(--oi-rule-active, #020B5F);
  --oi-list-ink-alt: var(--oi-color-primary, #020B71);
  --oi-list-loblolly: #CAD4D7;
  --oi-list-rule: var(--oi-gray-700, #40535D);
  --oi-list-surface: var(--oi-bg-white, #FFF);
  --oi-list-lime: var(--oi-color-accent, #B8EC00);
  --oi-list-body: var(--oi-gray-700, #40535D);

  font-family: var(--oi-font-body, "Noto Sans", sans-serif);
}

/* Utility. `!important` because the state is set from script and must beat
   whatever layout rule a host page puts on the card. */
.oi-list-is-hidden {
  display: none !important;
}

.oi-list-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Layout: letter rail on the left, results on the right.
   -------------------------------------------------------------------------- */

/* Mobile first throughout this file: the rules outside a media query are the
   narrow layout, and every query widens it with min-width. Nothing here uses
   max-width, so a phone never parses a desktop rule only to have it undone. */
/* `clip`, not `hidden`. base/_reset.scss sets overflow-x: hidden on body to
   keep full-bleed sections from opening a sideways scrollbar. `hidden` on one
   axis forces the other to `auto`, which makes body a scroll container — and
   a scroll container that never scrolls, because html is what scrolls. Every
   position: sticky inside it then has a scrollport that never moves, so it
   never pins. Measured: the letter rail below went to -958 instead of 87.

   `overflow-x: clip` does the same clipping without creating that scroll
   container, so the guard stays and sticky works. Verified at 320, 390, 768,
   1280 and 1440: no horizontal scrollbar at any of them, rail pinned at 87 at
   all of them.

   Scoped by construction: this stylesheet is enqueued only on the page using
   the A-Z template (see az-search-prodlisting.php), so no other page sees it.
   It wins over theme.css at equal specificity because it is printed after —
   the enqueue depends on 'ct-main' precisely to guarantee that order.

   Where `clip` is not supported (Safari below 16) the declaration is dropped,
   theme.css's `hidden` stands, and the only loss is that the rail scrolls
   with the page. Nothing breaks. */
body {
  overflow-x: clip;
}

/* No top margin here, on purpose.

   This file used to open the listing with margin-top: 80px, from when the
   listing was printed after the entry by a page template and had nothing
   above it to space itself from. Inside the OI - HTML block that separation
   is the block's job: its Style group writes pt-v3 and pb-v3 on the wrapper
   and the editor sets them per page. The 80px sat on top of that and, worse,
   ignored the editor — turning the block's top padding off left the gap
   exactly where it was, with nothing in the editor to explain it.

   A listing that still renders from a template and does need the gap sets it
   on its own wrapper, where it is visible to whoever reads that template. */

.oi-list-layout {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* The narrow layout paints in the order the design asks for — search,
   filters, letters, results — while the markup keeps the rail before the
   results, which is the order a screen reader and the tab key follow.
   `display: contents` is what lets the rail slot between two children of
   .oi-list-main without moving a single tag. */
.oi-list-main {
  display: contents;
}

.oi-list-controls { order: 1; }
.oi-list-bar      { order: 2; }
.oi-list-nav      { order: 3; }
.oi-list-results  { order: 4; }

/* The letter rail moves beside the results once the column can spare 216px
   for it plus the 40px gutter. */
@media (min-width: 992px) {
  .oi-list-layout {
    flex-direction: row;
    align-items: flex-start;
    gap: 10px;
  }

  /* A real box again: the rail is a column beside it, so the painted order is
     the markup order and there is nothing to reorder. Leaving the rail on
     order 3 here would put it to the RIGHT of the results. */
  .oi-list-main {
    display: block;
    flex: 1 1 auto;
    min-width: 0;
  }

  /* The rest of the desktop rail — its width and its position — is undone
     further down, next to the base rules it overrides. It has to be: those
     rules come later in the file, and at equal specificity the later one
     wins no matter which media query it sits in. */
  .oi-list-nav { order: 0; }
}

/* --------------------------------------------------------------------------
   Letter rail — four per row, as drawn: A B C D / E F G H / ...
   -------------------------------------------------------------------------- */

/* The rail parks under the site header at every width, and the results
   scroll past it. 87px is measured, not guessed: header.oi-header.oi-is-stuck
   is fixed, 72px tall and sits 15px down, identical at 390, 768 and 1440 in
   Chrome, so its bottom edge is at 87.

   This only works because of the overflow-x: clip on body at the top of this
   file — see the note there.

   z-index 1 puts the rail over the cards and well under the header (500) and
   the mobile nav drawer (800, 900). The background is what stops the cards
   showing through as they slide under, which matters below 992px where the
   rail spans the column; on desktop it sits in its own column and the
   background is switched off again. */
.oi-list-nav {
  position: sticky;
  top: 87px;
  z-index: 1;
  flex: 0 0 auto;
  padding: 8px 0;
  background: var(--oi-list-surface);
}

.oi-list-nav ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-content: center;
  /* Full width and a tight gap, so the 26 letters land in a few rows across
     the column instead of the seven the narrow desktop rail would give. The
     fixed width comes back with the sidebar at 992px. */
  gap: 6px;
  width: auto;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Back to the 180px column beside the results. This sits here, after the
   rules it undoes, because source order decides the winner at equal
   specificity — a media query does not raise it.

   The sticky stays: the rail follows the page on desktop too. Only the
   padding and the background go, because up here the rail has its own column
   and nothing passes underneath it. */
@media (min-width: 992px) {
  .oi-list-nav {
    padding: 0;
    background: none;
  }

  .oi-list-nav ul {
    /* 4 x 42px + 3 x 16px gap. Fixing the width is what makes the rows break
       after the fourth letter without a grid. */
    width: 180px;
    gap: 10px;
  }
}

.oi-list-nav li {
  margin: 0;
}

.oi-list-nav a {
  display: flex;
  width: 32px;
  height: 32px;
  padding: 14px;
  justify-content: center;
  align-items: center;
  gap: 10px;
  box-sizing: border-box;
  border-radius: 4px;
  border: 1.5px solid var(--oi-list-ink);
  opacity: 0.7;
  background: var(--oi-list-surface);
  color: var(--oi-list-ink);
  font-family: var(--oi-font-heading, "Noto Sans", sans-serif);
  font-size: 20px;
  font-weight: 600;
  line-height: 124%;
  text-decoration: none;
  transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.oi-list-nav a:hover,
.oi-list-nav a:focus-visible {
  background: var(--oi-list-lime);
  color: var(--oi-list-ink);
  text-decoration: none;
}

.oi-list-nav a:focus-visible {
  outline: 2px solid var(--oi-list-ink);
  outline-offset: 2px;
}

/* Undoing the theme's content-list styling on the letter rail.

   The index sits inside the legacy wrapper, whose .txt-v3 class makes the
   theme treat every list under it as prose: it pads each item 22px on the
   left and draws a round bullet with a li:before. Both land on the rail. The
   bullet is a generated element, so list-style: none never touched it, and
   the padding turned a 42px letter into a 64px one — which is why four
   stopped fitting in the 216px row and the rail came out two across.

   These have to win against theme.css line 416,
     .txt-v3 ul:not(.slick-dots):not(.splide__pagination)
             :not(.vjs-menu-content):not(.dropdown-menu) li
   which is (0,5,2) — five classes and two elements.

   This block used to carry the component's own id, which cleared it at
   (1,…). That stopped being possible when the three listings started
   sharing this file: each root has a different id (#az-listing, #cs-listing,
   #trial-listing), so naming one would leave the other two with bullets, and
   naming all three would leave the next listing broken until someone
   remembered to come back here. A list that has to be edited to keep working
   is the kind of failure this file exists to avoid.

   So: !important, on the declarations that undo prose styling and only
   those. It is not a shortcut around specificity — it is the statement that
   a letter rail is not prose and nothing downstream gets to treat it as
   such. ⚠️ If the bullets or the 22px indent ever come back, check that
   these kept their !important before looking anywhere else.

   The link rules are here for the same reason: whatever adds an underline on
   hover in another stylesheet, this outranks it. */
.oi-list .oi-list-nav ul {
  margin: 0 !important;
  padding: 0 !important;
  list-style: none !important;
}

.oi-list .oi-list-nav li {
  margin: 0 !important;
  padding: 0 !important;
}

.oi-list .oi-list-nav li::before {
  content: none !important;
}

.oi-list .oi-list-nav a,
.oi-list .oi-list-nav a:hover,
.oi-list .oi-list-nav a:focus,
.oi-list .oi-list-nav a:focus-visible {
  text-decoration: none !important;
}

/* A letter with nothing under it. `pointer-events: none` alone would leave it
   reachable by keyboard, so the script also sets aria-disabled and strips the
   href — this rule is only the look. */
.oi-list-nav a.oi-list-is-disabled {
  border-color: var(--oi-list-loblolly);
  color: var(--oi-list-loblolly);
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   Controls: search box and the two filter selects.
   -------------------------------------------------------------------------- */

/* The search row holds only the search, so it spans the whole column. The
   filters moved down to .oi-list-bar, beside the result count. */
.oi-list-controls {
  display: flex;
  margin-bottom: 16px;
}

/* Phone: the two selects on one row, the count and Clear all on the next, as
   drawn. .oi-list-filters goes to `contents` below so its three controls land
   on this grid directly — the two labels inside it are .oi-list-sr, absolutely
   positioned, so they claim no cell. From 768px up it is one row again, the
   count on one edge and the filters on the other. */
.oi-list-bar {
  display: grid;
  /* Not 1fr 1fr: "All Product Lines" is the longer of the two labels and came
     out clipped to "All Product Line" at half the bar. Measured, the closed
     labels need 92px and 125px, so the second column takes the extra. At
     1.25fr with an 8px gutter both clear it from 360px up. */
  grid-template-columns: 1fr 1.25fr;
  align-items: center;
  gap: 8px 8px;
  margin-bottom: 24px;
}

.oi-list-bar > .oi-list-total { grid-area: 2 / 1; }
.oi-list-bar .oi-list-reset   { grid-area: 2 / 2; justify-self: end; }
.oi-list-bar #oi-list-solution { grid-area: 1 / 1; }
.oi-list-bar #oi-list-brand    { grid-area: 1 / 2; }

@media (min-width: 768px) {
  .oi-list-bar {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 16px;
  }
}

.oi-list-search-wrap {
  display: flex;
  flex: 1 1 320px;
  height: 42px;
  padding: 16px;
  justify-content: space-between;
  align-items: center;
  box-sizing: border-box;
  border-radius: 4px;
  border: 1.5px solid var(--oi-list-rule);
  background: var(--oi-list-surface);
}

.oi-list-search-wrap:focus-within {
  outline: 2px solid var(--oi-list-ink);
  outline-offset: 2px;
}

/* The field itself carries no chrome: the wrapper draws the box, so the
   magnifier can sit inside it without overlaying the input. */
.oi-list-search {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: none;
  color: var(--oi-list-ink-alt);
  font-family: inherit;
  font-size: 16px;
  line-height: 124%;
}

.oi-list-search:focus {
  outline: none;
}

.oi-list-search-icon {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  aspect-ratio: 1/1;
}

/* `contents` on the phone so the selects and Clear all are placed by the bar
   grid above. A real flex row again from 768px. */
.oi-list-filters {
  display: contents;
}

@media (min-width: 768px) {
  .oi-list-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
  }
}

/* Borderless by design. `appearance: none` drops the platform arrow so the
   one from the design sheet, set as a background image, is the only one. */
.oi-list-select {
  display: flex;
  /* On the phone each select owns half the bar grid, so it fills its column
     and reads from the left edge of it. The fixed desktop width is set in the
     768px query below. */
  width: 100%;
  min-width: 0;
  /* No left padding on the phone: the label reads flush with the edge of its
     grid column, and those 10px are what "All Product Lines" needs. */
  padding: 10px 0;
  justify-content: flex-start;
  align-items: center;
  gap: 10px;
  box-sizing: border-box;
  border: 0;
  background: none;
  color: var(--oi-list-ink-alt);
  font-family: inherit;
  font-size: 16px;
  font-weight: 400;
  line-height: 124%;
  cursor: pointer;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  /* The caret from the sheet, inlined so the component needs no image file. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M12.0014 14.6537L7.59766 10.25H16.4052L12.0014 14.6537Z' fill='%23020B71'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right center;
  background-size: 24px 24px;
  padding-right: 28px;
}

@media (min-width: 768px) {
  .oi-list-select {
    /* 123px is the width on the design sheet, but "All Product Lines" does
       not fit in it — the label came out clipped to "All Product".
       `width: auto` is not the answer either: a select sizes itself to its
       WIDEST OPTION, and one of these is "Cloud Infrastructure Entitlement
       Management", which blew the control up and pushed the filters onto
       their own row. 178px is the closed label plus the caret. */
    width: 178px;
    padding: 10px;
    padding-right: 28px;
    justify-content: flex-end;
  }
}

.oi-list-select:focus-visible {
  outline: 2px solid var(--oi-list-ink);
  outline-offset: 2px;
}

/* The open list. Colours only — the box, the spacing and the highlight stay
   the browser's, which is the whole reason a native select is used here.
   Firefox and Chromium on Windows and Linux honour this; Safari and Chrome on
   macOS draw the menu with the OS and ignore it, so the list there reads in
   the system colours. There is no CSS fix for that short of replacing the
   select with a scripted widget. */
.oi-list-select option {
  background-color: var(--oi-list-surface);
  color: var(--oi-list-ink-alt);
}

.oi-list-reset {
  border: 0;
  background: none;
  padding: 10px;
  color: var(--oi-list-ink-alt);
  font-family: inherit;
  font-size: 16px;
  font-weight: 400;
  line-height: 124%;
  cursor: pointer;
}

.oi-list-reset:hover {
  text-decoration: underline;
}

.oi-list-total {
  margin: 0;
  color: var(--oi-list-body);
  font-size: 16px;
  line-height: 140%;
}

/* --------------------------------------------------------------------------
   Sections and cards.
   -------------------------------------------------------------------------- */

/* Every letter opens with its rule, the first one included — the line belongs
   to the start of a section, not to the end of the one before it.

   It is a border on the section rather than a separate element so that a
   section hidden by the filter takes its rule with it. Were it an element of
   its own, filtering down to two letters would leave the rules of the other
   twenty-four stacked on the page.

   The adjacent-sibling version this replaces looked identical while nothing
   was filtered, and read as a line under the last card the moment the first
   letter changed. */
.oi-list-section {
  padding: 30px 0;
  border-top: 1px solid var(--oi-list-rule);
}

.oi-list-letter {
  margin: 0 0 24px;
  color: var(--oi-list-ink);
  font-family: var(--oi-font-heading, "Noto Sans", sans-serif);
  font-size: 40px;
  font-weight: 700;
  line-height: 132%;
  letter-spacing: -0.8px;
}

/* A grid, not wrapping flex. Two per row has to be exactly two at any
   container width, and flex-wrap only ever gives "as many as fit" — which is
   how the cards ended up one per row: at 440px each plus the 24px gap they
   needed 904px and the column is 884px. */
/* minmax(0, 1fr) and not 1fr. A `1fr` track is shorthand for
   `minmax(auto, 1fr)`, and that `auto` floor is the card's min-content width
   — 440px, the width its CTA row wants. Below that the column refused to
   shrink and the card ran past the component: 119px over at a 390 viewport,
   242px over at 768. Nothing showed it because the theme's
   `overflow-x: hidden` on body clips the overspill instead of scrolling.
   A zero floor lets the track follow the device and the card text rewrap. */
.oi-list-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
}

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

.oi-list-card {
  display: flex;
  padding: 24px;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
  box-sizing: border-box;
  border-radius: 24px;
  border: 1px solid rgba(202, 212, 215, 0.16);
  background: rgba(202, 212, 215, 0.16);
}

.oi-list-card-title {
  align-self: stretch;
  margin: 0;
  color: var(--oi-list-ink-alt);
  font-family: var(--oi-font-heading, "Noto Sans", sans-serif);
  font-size: 24px;
  font-weight: 600;
  line-height: 32px;
  letter-spacing: -0.24px;
}

.oi-list-card-title a {
  color: inherit;
  text-decoration: none;
}

.oi-list-card-title a:hover {
  text-decoration: underline;
}

.oi-list-card-desc {
  align-self: stretch;
  margin: 0;
  color: var(--oi-list-body);
  font-size: 16px;
  font-weight: 400;
  line-height: 140%;
}

/* Pushed to the bottom so cards of different copy length keep their CTA row
   on the same line. */
.oi-list-card-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin-top: auto;
}

/* The bare CTA: no background, no border, arrow inherits the text colour. */
.oi-list-cta-link {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--oi-list-ink);
  font-size: 16px;
  font-weight: 400;
  line-height: 124%;
  text-decoration: none;
}

.oi-list-cta-link:hover {
  color: var(--oi-list-ink);
  text-decoration: underline;
}

.oi-list-cta-link svg {
  flex: 0 0 auto;
}

/* --------------------------------------------------------------------------
   "Try" — the two-option CTA three Safeguard products use.
   Closed it is a lime button; open it drops a dark panel with the two trials.
   -------------------------------------------------------------------------- */

/* A native details element, not a scripted menu.

   It was a button plus a panel toggled by JavaScript, and it kept arriving
   broken: the panel is only closed by the hidden attribute, whose UA rule is
   a bare [hidden] that any class selector outranks, and the whole thing dies
   if the script does not load. details/summary has neither failure mode. The
   browser owns the open state, it works with JavaScript off, and summary is
   keyboard-operable without any aria of our own.

   The script is now an enhancement: it closes the other menus, closes on a
   click outside and closes on Escape. None of that is needed to open one. */
.oi-list-try {
  position: relative;
  display: inline-block;
}


/* The toggle is a real button, but it has to read as the same CTA as the
   solid links beside it. Rather than restate that design here and let the two
   drift, it wears the theme's own .btn-v3 .btn-primary-dark and this block
   only undoes what a button element brings with it. The legacy did the same
   thing: its toggle carried btn-default-color, the class its plain Try
   buttons used. */
/* list-style removes the disclosure triangle everywhere except WebKit, which
   needs its own pseudo-element. Neither covers for the other, so both stay. */
.oi-list-try-toggle {
  display: inline-flex;
  list-style: none;
  border: 2px solid transparent;
  font-family: inherit;

  /* .btn-v3 centres its label and arrow and lets the button shrink to fit.
     That reads fine on a long label, but "Try" is three characters, and the
     caret ends up tucked against the word instead of sitting at the right
     edge the way every other button on the card does. A floor on the width
     plus space-between restores that alignment. */
  min-width: 160px;
  justify-content: space-between;
}


/* .btn-arrow forces 18x12 for the arrow glyph. The caret is a 24x24 drawing
   and comes out squashed at that size. */
.oi-list-try-toggle::-webkit-details-marker {
  display: none;
}

.oi-list-try-toggle .btn-arrow svg {
  width: 24px;
  height: 24px;
  transition: transform 0.2s ease;
}

.oi-list-try[open] .btn-arrow svg {
  transform: rotate(180deg);
}

/* Closed means closed, said out loud.
   How a browser hides the contents of a closed details element is not
   something to lean on: the rule moved to the ::details-content pseudo, it
   differs between engines, and an absolutely positioned child slips past it
   anyway. Measured here, the closed panel kept a 208x96 box and its links
   stayed in the tab order — invisible, and reachable by keyboard. A class
   selector is unambiguous and outranks anything the theme brings. */
.oi-list-try:not([open]) .oi-list-try-panel {
  display: none;
}

.oi-list-try-panel {
  position: absolute;
  z-index: 2;
  top: calc(100% + 4px);
  left: 0;
  min-width: 100%;
  padding: 8px 0;
  border-radius: 8px;
  background: var(--oi-list-ink-alt);
  white-space: nowrap;
}

.oi-list-try-panel a {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  color: var(--oi-bg-white, #FFF);
  font-size: 16px;
  font-weight: 400;
  line-height: 124%;
  text-decoration: none;
}

/* Hover keeps the white and adds the underline — the underline is the only
   thing that changes between the two states.

   The container id is what makes it stick. These links carry no class and sit
   inside the legacy .txt-v3 wrapper az-render.php emits, so the theme's prose
   rule matches them:

     .txt-v3 a:not([class]):hover { color: var(--oi-link-inline-hover); }

   That is (0,3,1) — class, element, the attribute selector inside :not, and
   the pseudo-class. A plain `.oi-list-try-panel a:hover` is (0,2,1) and loses,
   which is why hover came out #030B60 on a dark panel.

   This used to outrank it with the container id, which tied the rule to one
   page. Naming the ancestors instead gets to (0,4,1) and wins outright on
   any of the three listings, still with no reliance on source order. Same
   reasoning as the .btn-v3 rule at the end of this file. */
.oi-list .oi-list-try .oi-list-try-panel a:hover,
.oi-list .oi-list-try .oi-list-try-panel a:focus-visible {
  color: var(--oi-bg-white, #FFF);
  text-decoration: underline;
}

.oi-list-empty {
  margin: 40px 0;
  color: var(--oi-list-body);
  font-size: 16px;
  line-height: 140%;
}


/* The theme sets .btn-v3 to font-weight 700 at (0,1,0). A listing wants the
   regular face, so this outranks it on classes rather than with !important.

   It named the legacy wrapper id before — #contactaz here, #productsa-z in
   the A-Z copy of this file — which is exactly why there were two copies.
   (0,3,0) clears (0,1,0) with room to spare and belongs to no single page.
   Worth remembering how that rule failed once: it named an id that did not
   exist on the page, and matched nothing whatever its weight. A selector
   that cannot match is not a weak selector, it is a dead one. */
.oi-list .btn-v3 {
  font-weight: 400;
}