/*
 * Shared across every brand. Only the three tokens in :root differ per site:
 * they are injected from brands/<id>/brand.json by the base layout, so brands
 * look distinct while sharing one architecture and one stylesheet.
 */

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

/* Any author `display` beats the UA sheet's `[hidden] { display: none }`, so a
   styled element that is also hidden shows anyway. That is how the 404 page
   offered "View this page in English" on English 404s: the script correctly
   left the box hidden and .notfound-english's display:inline-block un-hid it.
   One guard is safer than auditing every rule that sets display. */
[hidden] {
  display: none !important;
}

:root {
  --ink: #16212b;
  --ink-soft: #55636f;
  --line: #e3e8ec;
  --bg: #ffffff;
  --bg-soft: #f6f8f9;
  --radius: 10px;
  --wrap: 60rem;
}

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

body {
  margin: 0;
  font-family: var(--brand-font);
  color: var(--ink);
  background: var(--bg);
  line-height: 1.6;
}

.wrap {
  width: min(100% - 2.5rem, var(--wrap));
  margin-inline: auto;
}

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

.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: 1rem;
  top: 1rem;
  background: #fff;
  padding: 0.5rem 1rem;
  z-index: 10;
}

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

/* Header + footer. The header keeps its brand colours in dark mode too. It is
   the one element that must match the parent site's identity, not the theme. */
.site-header {
  border-bottom: 1px solid var(--line);
  background: var(--brand-header-bg);
}
.header-inner,
.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 1rem;
  flex-wrap: wrap;
}
.brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
  color: var(--brand-header-ink);
  min-width: 0;
}
.brand-logo {
  height: 30px;
  width: auto;
  display: block;
}
.brand-kb {
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
  padding-left: 0.75rem;
  border-left: 1px solid color-mix(in srgb, var(--brand-header-ink) 30%, transparent);
  white-space: nowrap;
}
/* Header search button + the modal it opens. */
.header-search {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  color: var(--brand-header-ink);
  background: none;
  border: 1px solid color-mix(in srgb, var(--brand-header-ink) 25%, transparent);
  border-radius: 7px;
  cursor: pointer;
  transition: background-color 130ms ease;
}
.header-search svg {
  width: 1.05rem;
  height: 1.05rem;
}
.header-search:hover,
.header-search:focus-visible {
  background: color-mix(in srgb, var(--brand-header-ink) 12%, transparent);
}

.search-modal {
  width: min(100% - 2rem, 42rem);
  max-height: 80vh;
  /* Near the top rather than centred: results grow downwards, and a centred
     dialog jumps as they appear. */
  margin: 8vh auto auto;
  /* Extra room at the top so the close button has its own line rather than
     crowding the Ask button. */
  padding: 2.6rem 1.5rem 1.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink);
  overflow: visible;
}
.search-modal::backdrop {
  background: rgb(8 14 20 / 45%);
}
.search-modal .search-results {
  max-height: 52vh;
  overflow-y: auto;
}
.search-modal-close {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  display: inline-flex;
  width: 1.9rem;
  height: 1.9rem;
  padding: 0;
  align-items: center;
  justify-content: center;
  color: var(--ink-soft);
  background: none;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}
.search-modal-close svg {
  width: 1rem;
  height: 1rem;
}
.search-modal-close:hover {
  background: var(--bg-soft);
  color: var(--ink);
}

.header-links {
  display: flex;
  align-items: center;
  gap: 1.35rem;
  flex-wrap: wrap;
}
.header-link {
  position: relative;
  font-size: 0.88rem;
  text-decoration: none;
  color: var(--brand-header-ink);
  opacity: 0.82;
  white-space: nowrap;
  transition: opacity 130ms ease;
}
/* An underline that grows from the left rather than a static one: it keeps the
   header quiet at rest, which matters because these links sit next to the logo
   and must not compete with it. Drawn on a pseudo-element so appearing costs no
   layout shift, which text-decoration would. */
.header-link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 1.5px;
  border-radius: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 180ms cubic-bezier(0.4, 0, 0.2, 1);
}
.header-link:hover,
.header-link:focus-visible {
  opacity: 1;
}
.header-link:hover::after,
.header-link:focus-visible::after {
  transform: scaleX(1);
}
/* Copyright and build id sit together as one flex child. */
.footer-meta {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.35rem 0.85rem;
}
.footer-meta p {
  margin: 0;
}

/* Build identifier. Quiet on purpose: readers do not need it, support does. */
.kb-version {
  color: var(--ink-soft);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  opacity: 0.75;
}

.site-footer {
  border-top: 1px solid var(--line);
  margin-top: 4rem;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

/* Hero + search */
.hero {
  background: var(--bg-soft);
  border-bottom: 1px solid var(--line);
  padding-block: 3rem;
  text-align: center;
}
.hero h1 {
  margin: 0 0 0.5rem;
  font-size: clamp(1.7rem, 4vw, 2.4rem);
  line-height: 1.2;
}
/* Wide, deliberately short product banner cropped from the brand's own
   imagery. Height is fixed so square source photos become a letterbox strip. */
.hero-banner {
  display: block;
  width: 100%;
  /* The banner artwork is a designed 3.2:1 composition: show it whole rather
     than cover-cropping illustrated figures. Height scales with the window. */
  height: auto;
  border-radius: var(--radius);
  margin: 0 auto 1.5rem;
}
.hero-sub {
  margin: 0 auto 1.75rem;
  max-width: 42rem;
  color: var(--ink-soft);
}
.search {
  display: flex;
  gap: 0.5rem;
  max-width: 38rem;
  margin-inline: auto;
}
/* The field is a positioned wrapper so the magnifier can sit inside the input
   rather than stealing a flex column from it. */
.search-field {
  position: relative;
  flex: 1;
  display: flex;
  min-width: 0;
}
.search-icon {
  position: absolute;
  left: 0.9rem;
  top: 50%;
  translate: 0 -50%;
  width: 1.15rem;
  height: 1.15rem;
  color: var(--ink-soft);
  pointer-events: none;
}
.search input {
  flex: 1;
  padding: 0.85rem 1rem 0.85rem 2.7rem;
  font: inherit;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  min-width: 0;
}
.search input:focus-visible {
  outline: 2px solid var(--brand-primary);
  outline-offset: 1px;
}
.search button {
  padding: 0.85rem 1.4rem;
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: var(--brand-primary);
  border: 0;
  border-radius: var(--radius);
  cursor: pointer;
}
.search-modal .search,
.search-modal .search-results {
  max-width: none;
  margin-inline: 0;
}
.search-hint {
  margin: 0.75rem 0 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}
.search-results {
  max-width: 38rem;
  margin: 1rem auto 0;
  text-align: left;
}
.search-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  overflow: hidden;
}
.search-list li + li {
  border-top: 1px solid var(--line);
}
.search-list a {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  padding: 0.7rem 1rem;
  text-decoration: none;
  color: var(--ink);
}
/* The title gets the room. Without this the nowrap category name on the right
   takes its full width first and a long title wraps to one word per line,
   which is what a narrow modal makes obvious. */
.search-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
/* The line of article text around the match. Two lines at most: it explains a
   hit that the title does not, without turning the list into prose. */
.search-excerpt {
  color: var(--ink-soft);
  font-size: 0.83rem;
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.search-list a:hover {
  background: var(--bg-soft);
}
/* Scoped to the category label. It used to match every span in the row, which
   held the excerpt to a single clipped line once one existed. */
.search-list .search-cat {
  flex: none;
  color: var(--ink-soft);
  font-size: 0.85rem;
  white-space: nowrap;
}
.no-matches {
  margin: 0;
  padding: 0.75rem 0;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

/* Narrow enough that the two cannot share a line at all: stack them. */
@media (max-width: 34rem) {
  .search-list a {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.15rem;
  }
  .search-list .search-cat {
    white-space: normal;
    font-size: 0.8rem;
  }
}

/* Category cards */
.categories {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1rem;
  margin-block: 2.5rem;
}
.category-card {
  display: block;
  padding: 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--ink);
  background: #fff;
}
.category-card:hover {
  border-color: var(--brand-primary);
}
.category-card h2 {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 0.4rem;
  font-size: 1.1rem;
  color: var(--brand-primary);
}

/* The sprite itself must not occupy a line box. width/height 0 is not quite
   enough. An inline <svg> still contributes leading, so take it out of flow
   rather than display:none, which historically broke <use> references. */
.icon-sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* Category icons.

   Sized in em so they track whatever text they sit beside (a card heading, a
   category h1, an article h1) instead of needing a size per context. They
   inherit currentColor, which is what makes one sprite work for four brands. */
.cat-icon {
  flex: none;
  width: 1.35em;
  height: 1.35em;
  color: var(--brand-primary);
}
.category-card:hover .cat-icon {
  color: var(--brand-accent);
}

/* Titles that carry an icon. Centred against the whole title block, wrapped
   lines included, so it matches the category cards on the home page. */
h1.titled {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
h1.titled .cat-icon {
  width: 1.1em;
  height: 1.1em;
}
.category-card p {
  margin: 0 0 0.75rem;
  color: var(--ink-soft);
  font-size: 0.92rem;
}
.count {
  font-size: 0.8rem;
  color: var(--ink-soft);
}

/* Lists + article */
.breadcrumbs {
  margin-block: 1.5rem 0.5rem;
  font-size: 0.88rem;
  color: var(--ink-soft);
}
.breadcrumbs a {
  text-decoration: none;
}
.article,
.wrap > h1 {
  margin-bottom: 2rem;
}
.lede {
  color: var(--ink-soft);
  font-size: 1.05rem;
}
.article-list {
  list-style: none;
  margin: 1.5rem 0;
  padding: 0;
}
.article-list li {
  border-bottom: 1px solid var(--line);
}
/* The whole row is one link, with a chevron and hover state so it reads as
   clickable rather than as static text. */
.article-list a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem 0.6rem;
  text-decoration: none;
  color: var(--ink);
  border-radius: var(--radius);
  transition: background-color 120ms ease;
}
.article-list a:hover,
.article-list a:focus-visible {
  background: var(--bg-soft);
}
.article-list a:hover strong,
.article-list a:focus-visible strong {
  color: var(--brand-primary);
  text-decoration: underline;
}
.article-list strong {
  font-weight: 600;
}
.article-list-text {
  min-width: 0;
}
.article-list-desc {
  display: block;
  margin-top: 0.25rem;
  color: var(--ink-soft);
  font-size: 0.92rem;
  font-weight: 400;
}
.article-list .chevron {
  flex-shrink: 0;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--ink-soft);
  transition: transform 120ms ease, color 120ms ease;
}
.article-list a:hover .chevron,
.article-list a:focus-visible .chevron {
  color: var(--brand-primary);
  transform: translateX(3px);
}

.prose {
  margin-block: 1.5rem;
}
.prose img {
  max-width: 100%;
  height: auto;
  border-radius: var(--radius);
}
.prose iframe {
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  border: 0;
  border-radius: var(--radius);
}
.prose table {
  width: 100%;
  border-collapse: collapse;
  display: block;
  overflow-x: auto;
}
.prose th,
.prose td {
  border: 1px solid var(--line);
  padding: 0.5rem 0.7rem;
  text-align: left;
}
.prose pre {
  background: var(--bg-soft);
  padding: 1rem;
  border-radius: var(--radius);
  overflow-x: auto;
}
.prose code {
  font-size: 0.92em;
}
.prose h2,
.prose h3 {
  margin-top: 2rem;
  line-height: 1.3;
}

.cross-published,
.updated {
  font-size: 0.87rem;
  color: var(--ink-soft);
}

.ask-more {
  margin-top: 3rem;
  padding: 1.5rem;
  background: var(--bg-soft);
  border-radius: var(--radius);
}
.ask-more h2 {
  margin: 0 0 0.4rem;
  font-size: 1.05rem;
}
.ask-more p {
  margin: 0 0 1rem;
  color: var(--ink-soft);
}
.ask-more button {
  padding: 0.6rem 1.1rem;
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: var(--brand-primary);
  border: 0;
  border-radius: var(--radius);
  cursor: pointer;
}
.ticket-link {
  margin-left: 0.75rem;
  font-size: 0.9rem;
}

.empty {
  color: var(--ink-soft);
  padding-block: 2rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink: #e8edf1;
    --ink-soft: #a3b0bb;
    --line: #2a3641;
    --bg: #10171d;
    --bg-soft: #172029;
  }
  .search input,
  .category-card,
  .search-list {
    background: var(--bg-soft);
    color: var(--ink);
  }
  .panel {
    background: var(--bg);
    color: var(--ink);
  }
  .panels-band {
    background: var(--bg-soft);
  }
  .search-modal {
    background: var(--bg-soft);
  }
}

/* Language selector + machine-translation notice */
.header-right {
  display: flex;
  align-items: center;
  gap: 1.35rem;
  flex-wrap: wrap;
}
.header-right .lang-menu {
  padding-left: 1.35rem;
}
.header-right .header-links + .lang-menu::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  translate: 0 -50%;
  width: 1px;
  height: 1.15em;
  background: color-mix(in srgb, var(--brand-header-ink) 28%, transparent);
}
.lang-switch {
  display: flex;
  gap: 0.15rem;
  font-size: 0.78rem;
  font-weight: 600;
}
.lang-switch a,
.lang-switch span {
  padding: 0.2rem 0.4rem;
  border-radius: 5px;
  text-decoration: none;
  color: var(--brand-header-ink);
  opacity: 0.65;
}
.lang-switch a:hover {
  opacity: 1;
  background: color-mix(in srgb, var(--brand-header-ink) 12%, transparent);
}
.lang-switch span[aria-current] {
  opacity: 1;
  background: color-mix(in srgb, var(--brand-header-ink) 16%, transparent);
}
.mt-notice {
  margin: 0.75rem 0 0;
  padding: 0.55rem 0.9rem;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 0.85rem;
  color: var(--ink-soft);
}

/* Language dropdown */
.lang-menu {
  position: relative;
}
.lang-menu summary {
  list-style: none;
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--brand-header-ink);
  padding: 0.35rem 0.6rem;
  border: 1px solid color-mix(in srgb, var(--brand-header-ink) 25%, transparent);
  border-radius: 7px;
  white-space: nowrap;
  user-select: none;
}
.lang-menu summary::-webkit-details-marker {
  display: none;
}
.lang-menu summary:hover {
  background: color-mix(in srgb, var(--brand-header-ink) 10%, transparent);
}
.lang-menu .caret {
  font-size: 0.7em;
  opacity: 0.7;
}
.lang-menu[open] .caret {
  display: inline-block;
  transform: rotate(180deg);
}
.lang-menu ul {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  margin: 0;
  padding: 0.3rem;
  list-style: none;
  min-width: 11rem;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  z-index: 50;
}
.lang-menu ul a,
.lang-menu ul span {
  display: block;
  padding: 0.45rem 0.7rem;
  border-radius: 7px;
  text-decoration: none;
  color: var(--ink);
  font-size: 0.9rem;
}
.lang-menu ul a:hover {
  background: var(--bg-soft);
  color: var(--brand-primary);
}
.lang-menu ul span[aria-current] {
  background: var(--bg-soft);
  font-weight: 600;
}

@media (max-width: 40rem) {
  .header-right,
  .header-links {
    gap: 0.9rem;
  }
  .header-link {
    font-size: 0.82rem;
  }
  /* The bar wraps to two rows here, which strands the hairline on a row of its
     own to the left of the picker. It only means anything as a separator. */
  .header-right .lang-menu {
    padding-left: 0;
  }
  .header-right .header-links + .lang-menu::before {
    display: none;
  }
}

/* Nothing here is load-bearing: the underline and the fade are decoration. */
@media (prefers-reduced-motion: reduce) {
  .header-link,
  .header-link::after,
  .header-search {
    transition: none;
  }
}

/* The band the panels sit on. Full-bleed and tinted, because the panels share
   the category cards' shape and would otherwise read as six more categories
   rather than three links off the site. It also closes the page the way the
   hero band opens it. */
.panels-band {
  background: var(--bg-soft);
  border-top: 1px solid var(--line);
  margin-top: 3rem;
  padding-block: 2.25rem 3rem;
}
/* When the page ends in the band, the footer's usual 4rem of air becomes a
   white strip between two tinted areas. Sit them flush instead. Falls back to
   the normal margin where :has() is unsupported, which is merely the old look. */
main:has(.panels-band) + .site-footer {
  margin-top: 0;
}

.panels-heading {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Sibling-product panels below the categories.

   Each panel is one link, so the whole card is the target rather than just the
   call to action. The media box has a fixed aspect ratio and object-fit: cover
   because the three source images do not share one (a 4:3 photo, a portrait
   screenshot, a 3:2 product shot); object-position is per panel, so the
   dashboard screenshot can be pinned to its top where the meaning is. */
.panels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1.25rem;
  margin-top: 1.1rem;
}
.panel {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  text-decoration: none;
  color: var(--ink);
  transition: border-color 140ms ease, transform 140ms ease;
}
.panel:hover,
.panel:focus-visible {
  border-color: var(--brand-primary);
  transform: translateY(-2px);
}
.panel-media {
  display: block;
  aspect-ratio: 16 / 10;
  background: var(--bg-soft);
  /* Product shots are cut out on white, which would otherwise dissolve into
     the card. The hairline gives every panel the same edge regardless. */
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}
.panel-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: scale 320ms ease;
}
.panel:hover .panel-media img {
  scale: 1.04;
}
.panel-text {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 1.1rem 1.25rem 1.25rem;
  flex: 1;
}
.panel-title {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--brand-primary);
}
.panel-blurb {
  color: var(--ink-soft);
  font-size: 0.92rem;
  flex: 1;
}
.panel-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.35rem;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--brand-primary);
}
.panel-cta svg {
  width: 1em;
  height: 1em;
  transition: translate 160ms ease;
}
.panel:hover .panel-cta svg,
.panel:focus-visible .panel-cta svg {
  translate: 3px 0;
}
@media (prefers-reduced-motion: reduce) {
  .panel,
  .panel-media img,
  .panel-cta svg {
    transition: none;
  }
  .panel:hover {
    transform: none;
  }
  .panel:hover .panel-media img {
    scale: 1;
  }
}

/* Home banner (below categories) + 404 */
.home-banner {
  margin-block: 1rem 2.5rem;
}
.notfound {
  padding-block: 4rem;
  text-align: center;
}
.notfound h1 {
  font-size: 5rem;
  margin: 0;
  color: var(--brand-primary);
  line-height: 1;
}
.notfound-english {
  padding: 0.75rem 1rem;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  display: inline-block;
}
.notfound-home {
  text-decoration: none;
  font-weight: 600;
}

/* Dark mode: the header joins the theme rather than staying a glaring brand bar.
   Logos swap to their dark-background variants via the <picture> element. */
@media (prefers-color-scheme: dark) {
  :root {
    --brand-header-bg: #10171d;
    --brand-header-ink: #e8edf1;
  }
  .site-header {
    border-bottom-color: var(--line);
  }
  .lang-menu ul {
    background: var(--bg-soft);
  }
  .search button {
    color: #fff;
  }
  .prose pre,
  .mt-notice,
  .notfound-english,
  .ask-more {
    background: var(--bg-soft);
  }
}
