/* =====================================================================
   QA Madness - Services / Coverage / Industries hub pages (redesign)
   ---------------------------------------------------------------------
   SCOPING RULE: every selector is prefixed with `.shub` (the page's <main>
   wrapper) or `body.qm-services-hub`, so nothing here can reach another
   template. The shared redesign header chrome lives in
   shared/home-header.css, which also defines the --h-* / --ds-* tokens this
   file inherits; both load together (see qm_shub_enqueue()).

   Reference: Figma "Services/redesign", a 1600px frame with a 1200px
   container - so the gutter is (1600-1200)/2 = 200px at the reference width,
   and the container is what carries the measurement below that.
   Enqueued only on page-parent-for-single.php.
   ===================================================================== */

/* ---------- Fonts (self-hosted, shipped with the theme) ---------- */
@font-face {
  font-family: "GT Sectra Display";
  src: url("../../fonts/GTSectraDisplaySuper.woff2") format("woff2"),
       url("../../fonts/GTSectraDisplaySuper.woff") format("woff");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Noto Sans";
  src: url("../fonts/NotoSans-Regular.ttf") format("truetype");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Noto Sans";
  src: url("../fonts/NotoSans-Medium.ttf") format("truetype");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Noto Sans";
  src: url("../fonts/NotoSans-Bold.ttf") format("truetype");
  font-weight: 700; font-style: normal; font-display: swap;
}

/* ---------- Design tokens ----------
   Named after the Figma variables they carry, so a value can be traced back
   to the design without guessing. */
.shub {
  --shub-bg-1: #110d1a;            /* main/background/1 - grid + CTA bands   */
  --shub-bg-2: #08060d;            /* main/background/2 - figures band       */
  --shub-white: #f9f7ff;           /* main/white                             */
  --shub-purple: #7d51f1;          /* main/purple                            */
  --shub-purple-dark: #5336a1;     /* secondary/dark purple                  */
  --shub-purple-light: #cbb9f9;    /* secondary/light purple/100             */
  --shub-green: #00cca6;           /* main/green                             */
  --shub-green-dark: #00886f;      /* secondary/dark green 1                 */
  --shub-green-light: #68dcc7;     /* secondary/light green                  */
  --shub-ink: #0d1a18;             /* secondary/dark green 2/100 - on green  */
  --shub-glass: rgba(21, 17, 30, 0.5); /* secondary/dark purple 2 @ 50%      */

  --shub-card-purple: #120e1c;
  --shub-card-green: #0e1319;
  --shub-card-trust: #0a1012;

  --shub-container: var(--h-container, 1200px);
  --shub-gutter: 20px;
  --shub-gap: 16px;
  --shub-section-y: 64px;

  --shub-r-card: 16px;
  --shub-r-tile: 14px;
  --shub-r-figure: 24px;
  --shub-r-cta: 40px;
  --shub-pill: 999px;

  --shub-font: var(--h-font, "Noto Sans", "Helvetica Neue", Arial, sans-serif);
  --shub-serif: var(--h-serif, "GT Sectra Display", Georgia, "Times New Roman", serif);

  --shub-ease: var(--ds-ease, cubic-bezier(0.4, 0, 0.2, 1));
  --shub-dur: var(--ds-dur, 200ms);
}

/* ---------- Wrapper base ---------- */
body.qm-services-hub {
  background: var(--shub-bg-1);
}
.shub {
  font-family: var(--shub-font);
  color: var(--shub-white);
  background: var(--shub-bg-1);
  font-size: 14px;
  line-height: 1.6;
  overflow-x: clip;
}
.shub *,
.shub *::before,
.shub *::after { box-sizing: border-box; }
.shub h1,
.shub h2,
.shub h3 {
  margin: 0;
  color: var(--shub-white);
  font-family: var(--shub-font); /* the theme's global serif headings are not wanted here */
  font-weight: 700;
}
.shub p { margin: 0; }
.shub ul { margin: 0; padding: 0; list-style: none; }
.shub img { max-width: 100%; height: auto; }

/* --shub-container is the CONTENT width, which is what the design measures:
   the cards span exactly 1200px and the gutter sits outside that, so the
   max-width has to carry the padding on top of it. */
.shub-container {
  width: 100%;
  max-width: calc(var(--shub-container) + var(--shub-gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--shub-gutter);
}

/* Visible focus for every interactive thing on the page. The theme suppresses
   the tap highlight globally but leaves focus rings alone - this makes sure
   they actually read against the dark ground. */
.shub a:focus-visible,
.shub button:focus-visible {
  outline: 2px solid var(--shub-green-light);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Buttons borrowed from the Service templates bring their own focus ring:
   `:is(body.service-v2, .sv-scope) .sv-btn:focus-visible` paints
   --sv-green-light at (0,3,1), which outranks the rule above at (0,2,0). The
   two tokens are the same colour today (#68DCC7 / #68dcc7), so this changes
   nothing on screen - it changes which palette owns the decision, so the ring
   tracks the hub if its green is ever retuned.

   Four classes to clear (0,3,1): .shub and .sv-scope are the same element -
   the page's <main> - so this costs no extra markup.

   No border-radius here, unlike the rule above. That 4px is for elements with
   no radius of their own; .sv-btn is a 999px pill and an outline already
   follows its border-radius. */
.shub.sv-scope .sv-btn:focus-visible {
  outline-color: var(--shub-green-light);
}

.shub-arrow { flex: none; display: block; }

/* =====================================================================
   Hero
   ===================================================================== */
.shub-hero {
  position: relative;
  /* One full screen. MIN-height, not height: the hero carries a two-line title,
     a description, two actions and the four figures, and on a short laptop
     viewport that stack is already taller than the screen - a fixed height
     would crop it. This way the hero fills the viewport when there is room to
     spare and grows past it when there is not.

     100svh, not 100vh: on mobile `vh` resolves to the LARGE viewport, the one
     you only get once the browser's address bar has retracted, so a 100vh hero
     sits partly under the chrome on first paint. `svh` is the small viewport
     and always fits. `dvh` would fit too but re-lays-out as the bar hides and
     shows, which visibly jumps the centred content. The plain `vh` line stays
     as the fallback for anything that does not know `svh`. */
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* 200px clears the transparent fixed header and matches the design's
     distance from the top of the frame to the title. Now that the content is
     centred, the heavier top padding also does the centring work: it offsets
     the block downward by half the difference against the 128px bottom, which
     is what keeps it optically centred in the space BELOW the header rather
     than in the section as a whole. */
  padding: 200px 0 128px;
  background: var(--shub-bg-1);
  text-align: center;
  overflow: hidden;
}
.shub-hero--art::before {
  content: "";
  position: absolute;
  /* The artwork is bled slightly past every edge, as it is in the design, so
     no hard seam shows where the gradient meets the flat background. */
  inset: -2% -1%;
  background-image: var(--shub-hero-art);
  background-size: cover;
  background-position: center;
  pointer-events: none;
}
.shub-hero > .shub-container { position: relative; }

.shub .shub-hero__title {
  font-family: var(--shub-serif);
  font-weight: 900;
  font-size: 60px;
  line-height: 56px;
  letter-spacing: 0;
  overflow-wrap: break-word;
}
.shub-hero__title-lead,
.shub-hero__title-accent { display: block; }
.shub-hero__title-lead { color: var(--shub-white); }
.shub-hero__title-accent {
  background-image: linear-gradient(90deg, var(--shub-purple) 0%, var(--shub-green) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.shub .shub-hero__desc {
  max-width: 800px;
  margin: 32px auto 0;
  font-size: 20px;
  line-height: 28px;
  color: var(--shub-white);
}

.shub-hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--shub-gap);
  margin-top: 32px;
}
.shub-hero__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--shub-white);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
  transition: color var(--shub-dur) var(--shub-ease);
}
.shub-hero__link:hover,
.shub-hero__link:focus-visible { color: var(--shub-green-light); }
.shub-hero__link .shub-arrow { transition: transform var(--shub-dur) var(--shub-ease); }
.shub-hero__link:hover .shub-arrow { transform: translateX(3px); }

/* =====================================================================
   Figures (hero band + "Trusted Quality" band share the card)
   ===================================================================== */
.shub-figures {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--shub-gap);
  align-items: stretch;
}
.shub-figure {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 24px;
  text-align: center;
}
.shub .shub-figure__value {
  font-size: 32px;
  font-weight: 700;
  /* `normal`, not a ratio - the design's figure card is 122px tall, which only
     works out with the font's own 1.36 default leading. */
  line-height: normal;
}
.shub-figure__label {
  font-size: 14px;
  line-height: 22px;
  color: var(--shub-white);
}

/* Hero band: translucent glass over the artwork. */
.shub .shub-figures--hero { margin-top: 64px; }
.shub-figures--hero .shub-figure {
  background: var(--shub-glass);
  border-radius: var(--shub-r-figure);
  box-shadow: 0 20px 60px rgba(8, 6, 13, 0.75);
}
.shub-figures--hero .shub-figure__value { color: var(--shub-purple-light); }

/* Trust band: outlined, green. */
.shub .shub-figures--trust { margin-top: 40px; }
.shub-figures--trust .shub-figure {
  min-height: 162px;
  background: var(--shub-card-trust);
  border: 1px solid var(--shub-green-dark);
  border-radius: var(--shub-r-card);
}
.shub-figures--trust .shub-figure__value { color: var(--shub-green-light); }

/* =====================================================================
   Filter row + card grid
   ===================================================================== */
.shub-grid-section {
  padding: var(--shub-section-y) 0;
  background: var(--shub-bg-1);
}

.shub-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--shub-gap);
  margin-bottom: 64px;
}
.shub-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  padding: 0 32px;
  border: 1px solid var(--shub-purple-light);
  border-radius: var(--shub-pill);
  background: transparent;
  color: var(--shub-purple-light);
  font-family: inherit;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--shub-dur) var(--shub-ease),
              border-color var(--shub-dur) var(--shub-ease),
              color var(--shub-dur) var(--shub-ease);
}
.shub-pill:hover {
  border-color: var(--shub-purple);
  color: var(--shub-white);
}
.shub-pill.is-active {
  border-color: var(--shub-purple);
  background: var(--shub-purple);
  color: var(--shub-white);
}
/* Clicking a pill leaves it focused, and the browser's OWN default focus ring -
   which Chromium draws as a white halo on a dark ground - was showing through
   on top of the selected state. The :focus-visible rule near the top of this
   file only ever styled the keyboard case; nothing suppressed the UA one.
   A mouse user has just pointed at the pill and does not need telling where it
   is. Keyboard users are untouched - :focus-visible does not match here, so
   tabbing onto a pill still gets the green ring from that shared rule.
   Deliberately scoped to the pills: every other control on these pages keeps
   the browser's default ring after a click. */
.shub-pill:focus:not(:focus-visible) {
  outline: none;
}

.shub-group + .shub-group { margin-top: 60px; }
.shub-group[hidden] { display: none; }
/* font-family is repeated on the component rule, not left to the `.shub h2`
   reset above: the parent theme's `h2:not(.noto-font)` has the same
   specificity as that reset and loads after this file, so only a
   two-class selector reliably keeps the serif off the section headings. */
.shub .shub-group__title {
  margin-bottom: 24px;
  font-family: var(--shub-font);
  font-size: 32px;
  line-height: 1;
}

.shub-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--shub-gap);
  align-items: stretch;
}

/* ---------- Card ---------- */
.shub-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 24px;
  border: 1px solid var(--shub-purple-dark);
  border-radius: var(--shub-r-card);
  background: var(--shub-card-purple);
  transition: border-color var(--shub-dur) var(--shub-ease),
              transform var(--shub-dur) var(--shub-ease),
              box-shadow var(--shub-dur) var(--shub-ease);
}
.shub-card--green {
  border-color: var(--shub-green-dark);
  background: var(--shub-card-green);
}

.shub-card__head {
  display: flex;
  align-items: center;
  gap: var(--shub-gap);
}
.shub-card__icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: var(--shub-r-tile);
  background: var(--shub-purple-dark);
  color: var(--shub-purple-light);
}
.shub-card--green .shub-card__icon {
  background: var(--shub-green-dark);
  color: var(--shub-green-light);
}
/* An uploaded icon keeps the designed 24px leaf inside the 48px tile rather
   than filling it - the tile is the artwork's ground, not its frame. */
.shub-card__icon img {
  width: 24px;
  height: 24px;
  object-fit: contain;
}

/* The BUNDLED set is different: each file is the whole 48px tile, rounded
   corner and tinted ground included, in the card's own purple or green. So
   --art drops the CSS tile and lets the artwork be it, at full size - the same
   modifier name and the same reasoning as .home-mega-card__ico--art in
   assets/styles/shared/home-header.css, where supplied artwork hits exactly
   this problem. Without it the two grounds stack and the icon shows a ring.

   BOTH accent classes are named on purpose. `.shub-card--green .shub-card__icon`
   above sets `background` at (0,2,0); a plain `.shub-card__icon--art` is (0,1,0)
   and would lose to it on green cards no matter where it sits in the file. */
.shub-card--purple .shub-card__icon--art,
.shub-card--green .shub-card__icon--art {
  background: none;
  padding: 0;
  overflow: hidden;
}
.shub-card .shub-card__icon--art img {
  width: 100%;
  height: 100%;
  display: block;
}

/* font-family is stated here, not left to the `.shub h1, .shub h2, .shub h3`
   reset near the top of this file - the same reason .shub-group__title states
   it. The theme's global `h1..h6:not(.noto-font)` serif rule has the SAME
   specificity as that reset (0,1,1) and loads after this file, so it wins, and
   a two-class selector like this one (0,2,0) is what reliably beats it.

   It only showed on Coverage and Industries. The card heading level depends on
   whether its group has a label: Services groups are labelled, so their cards
   are h3 under an h2 group heading, while Coverage and Industries render one
   unlabelled group and their cards ARE the h2 - which is the level the global
   rule was reaching. Setting the family here fixes every level at once rather
   than depending on which heading a page happens to use. */
.shub .shub-card__title {
  margin: 0;
  font-family: var(--shub-font);
  font-size: 18px;
  font-weight: 700;
  line-height: 1.22;
  color: var(--shub-purple-light);
}
.shub-card--green .shub-card__title { color: var(--shub-green-light); }
.shub-card__link {
  color: inherit;
  text-decoration: none;
}
/* The whole card is the target; the heading link stays the ONE accessible
   name for it, so there is no duplicate "Learn more" link for screen readers. */
.shub-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.shub .shub-card__text {
  margin-top: var(--shub-gap);
  font-size: 14px;
  line-height: 22px;
  color: var(--shub-white);
  /* The design's card is a fixed two-line summary, and the grid row takes the
     height of its tallest card - so one service whose description is a full
     paragraph (several of them are, inherited from the post's
     `short_description`) would otherwise stretch its whole row. Clamped rather
     than truncated in PHP so the full text stays in the document for search
     engines and screen readers. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  /* Two lines are RESERVED, not just capped: the design's cards are a uniform
     190px because every summary in it runs to two lines, and a one-line
     description would otherwise leave its row short next to a two-line one. */
  min-height: 44px;
}

/* White at rest, the card's accent on hover - the same move, and the same two
   colours, the homepage gives its own "Learn more"
   (body.home .home-service--purple/--green .home-service__more:hover in
   css/home.css). */
.shub-card__more {
  display: inline-flex;
  align-items: center;
  align-self: flex-end;
  gap: 8px;
  margin-top: var(--shub-gap);
  color: var(--shub-white);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.5;
  transition: color var(--shub-dur) var(--shub-ease);
}
/* :focus-within as well as :hover - the whole card is one link, so a keyboard
   user tabbing onto it gets the same feedback a pointer does. */
.shub-card:hover .shub-card__more,
.shub-card:focus-within .shub-card__more { color: var(--shub-purple-light); }
.shub-card--green:hover .shub-card__more,
.shub-card--green:focus-within .shub-card__more { color: var(--shub-green-light); }
/* Pushes the row to the bottom when a card is taller than its content, so the
   "Learn more" baselines line up across a row. */
.shub-card__text + .shub-card__more { margin-top: auto; padding-top: var(--shub-gap); }

.shub-card:hover {
  border-color: var(--shub-purple);
  transform: translateY(-2px);
  box-shadow: 0 16px 40px rgba(8, 6, 13, 0.6);
}
.shub-card--green:hover { border-color: var(--shub-green); }
.shub-card:hover .shub-card__more .shub-arrow { transform: translateX(3px); }
.shub-card__more .shub-arrow { transition: transform var(--shub-dur) var(--shub-ease); }

/* =====================================================================
   Trusted Quality band
   ===================================================================== */
.shub-trust {
  padding: var(--shub-section-y) 0;
  background: var(--shub-bg-2);
  text-align: center;
}
.shub .shub-trust__title {
  font-family: var(--shub-font); /* see the note on .shub-group__title */
  font-size: 48px;
  line-height: 68px;
}
.shub-trust__lead,
.shub-trust__accent { display: block; }
.shub-trust__accent { color: var(--shub-green-light); }

/* =====================================================================
   Responsive
   ---------------------------------------------------------------------
   The design ships a 1600px desktop frame only, so everything below 1280px
   is a transition built from it: the container stops being a fixed 1200 and
   starts taking gutters, the card grid drops a column at a time, and the type
   ramps down instead of scaling uniformly.
   ===================================================================== */

@media (max-width: 1280px) {
  .shub-hero { padding: 168px 0 96px; }
  .shub .shub-hero__title { font-size: 52px; line-height: 50px; }
}

@media (max-width: 1024px) {
  .shub { --shub-section-y: 56px; }
  .shub-hero { padding: 148px 0 80px; }
  .shub .shub-hero__title { font-size: 44px; line-height: 44px; }
  .shub .shub-hero__desc { font-size: 18px; line-height: 26px; }
  .shub .shub-figures--hero { margin-top: 48px; }

  .shub-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .shub .shub-trust__title { font-size: 40px; line-height: 52px; }
}

@media (max-width: 900px) {
  .shub-filters { gap: 12px; }
  .shub-pill { height: 40px; padding: 0 22px; font-size: 16px; }
  .shub-group + .shub-group { margin-top: 48px; }
  .shub .shub-group__title { font-size: 28px; margin-bottom: 20px; }
}

@media (max-width: 768px) {
  .shub { --shub-gutter: 16px; --shub-section-y: 48px; }
  .shub-hero { padding: 124px 0 64px; }
  .shub .shub-hero__title { font-size: 34px; line-height: 34px; }
  .shub .shub-hero__desc { margin-top: 24px; font-size: 16px; line-height: 24px; }
  .shub-hero__actions { margin-top: 24px; }

  .shub-figures { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .shub .shub-figures--hero { margin-top: 32px; }
  .shub .shub-figures--trust { margin-top: 32px; }
  .shub-figures--trust .shub-figure { min-height: 0; }
  .shub-figure { padding: 20px 16px; }
  .shub .shub-figure__value { font-size: 26px; }

  .shub-filters { margin-bottom: 40px; }

  .shub .shub-trust__title { font-size: 30px; line-height: 38px; }
}

/* Two cards still read well down to here - at ~340px each they are the same
   width as the desktop card, so the grid keeps its proportions rather than
   jumping to one very wide column the moment a tablet turns portrait. */
@media (max-width: 620px) {
  .shub-cards { grid-template-columns: minmax(0, 1fr); }

  /* The filters become a stacked list of full-width pills, per the mobile
     design - not a wrapped row. Same threshold as the card grid above, and for
     the same reason: by this width the row breaks into ragged lines of two and
     one, which reads as a layout accident rather than a set of choices.
     `align-items: stretch` is what widens them; the pill's own
     `justify-content: center` keeps each label centred in its new width. */
  .shub-filters {
    flex-direction: column;
    align-items: stretch;
  }
  /* Back to the full 44px. The 900px rule shortens the pill to 40px to fit more
     onto a wrapped row; stacked, that constraint is gone and 44px is the
     comfortable minimum for a touch target. */
  .shub-pill { height: 44px; }

  /* The trust band goes to one card per row, per the mobile design. Only this
     band: the HERO figures stay two-up, which is what their design shows and
     what their short captions ("years in QA and tech") suit. These captions are
     sentences - "of placed candidates pass probation" - and in a ~163px column
     they wrap to four ragged lines.

     Later in the file than the 768px rule that sets two columns, at equal
     specificity, so this wins below 620px while the hero band keeps that rule. */
  .shub-figures--trust { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 560px) {
  /* Full-width button: at this width a pill sized to its label looks stranded,
     and the design's own mobile CTA pattern elsewhere in the theme is a block
     button. */
  .shub-hero__actions { flex-direction: column; align-items: stretch; }
  /* Three classes on purpose. .sv-btn is delivered by
     `:is(body.service-v2, .sv-scope) .sv-btn`, which weighs (0,2,1) - a plain
     `.shub-hero .sv-btn` at (0,2,0) would lose to it however late it loads.
     `justify-content` is the reason this matters: .sv-btn anchors its content
     LEFT so its hover gap only grows rightward, which is right for a pill sized
     to its label and wrong for one stretched across the screen, where the label
     would sit off in the left corner. */
  .shub .shub-hero .sv-btn {
    width: 100%;
    justify-content: center;
  }
  .shub-hero__link { justify-content: center; }
}

@media (max-width: 480px) {
  .shub .shub-hero__title { font-size: 30px; line-height: 31px; }
  /* Padding and type shrink; the 44px HEIGHT does not. That shrink existed to
     fit more pills onto a wrapped row, and below 620px there is no row - each
     pill is its own full-width line with room to spare. Keeping 44px also keeps
     them at the minimum comfortable touch target, which 36px is under. */
  .shub-pill { padding: 0 16px; font-size: 14px; }
  .shub .shub-figure__value { font-size: 22px; }
  .shub-figure__label { font-size: 13px; line-height: 19px; }
}

/* ---------- Motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .shub *,
  .shub *::before,
  .shub *::after {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
  }
  .shub-card:hover { transform: none; }
}
