@font-face {
  font-display: swap;

  font-family: 'Bricolage Grotesque';

  font-style: normal;

  font-weight: 200 800;

  font-stretch: 75% 100%;

  src: url(../assets/fonts/bricolage-grotesque-latin-ext.woff2) format('woff2');

  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-display: swap;

  font-family: 'Bricolage Grotesque';

  font-style: normal;

  font-weight: 200 800;

  font-stretch: 75% 100%;

  src: url(../assets/fonts/bricolage-grotesque-latin.woff2) format('woff2');

  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-display: swap;

  font-family: 'Inter';

  font-style: normal;

  font-weight: 100 900;

  src: url(../assets/fonts/inter-latin-ext.woff2) format('woff2');

  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-display: swap;

  font-family: 'Inter';

  font-style: normal;

  font-weight: 100 900;

  src: url(../assets/fonts/inter-latin.woff2) format('woff2');

  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

*, ::before, ::after {
  --tw-border-spacing-x: 0;
  --tw-border-spacing-y: 0;
  --tw-translate-x: 0;
  --tw-translate-y: 0;
  --tw-rotate: 0;
  --tw-skew-x: 0;
  --tw-skew-y: 0;
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  --tw-pan-x:  ;
  --tw-pan-y:  ;
  --tw-pinch-zoom:  ;
  --tw-scroll-snap-strictness: proximity;
  --tw-gradient-from-position:  ;
  --tw-gradient-via-position:  ;
  --tw-gradient-to-position:  ;
  --tw-ordinal:  ;
  --tw-slashed-zero:  ;
  --tw-numeric-figure:  ;
  --tw-numeric-spacing:  ;
  --tw-numeric-fraction:  ;
  --tw-ring-inset:  ;
  --tw-ring-offset-width: 0px;
  --tw-ring-offset-color: #fff;
  --tw-ring-color: rgb(59 130 246 / 0.5);
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  --tw-blur:  ;
  --tw-brightness:  ;
  --tw-contrast:  ;
  --tw-grayscale:  ;
  --tw-hue-rotate:  ;
  --tw-invert:  ;
  --tw-saturate:  ;
  --tw-sepia:  ;
  --tw-drop-shadow:  ;
  --tw-backdrop-blur:  ;
  --tw-backdrop-brightness:  ;
  --tw-backdrop-contrast:  ;
  --tw-backdrop-grayscale:  ;
  --tw-backdrop-hue-rotate:  ;
  --tw-backdrop-invert:  ;
  --tw-backdrop-opacity:  ;
  --tw-backdrop-saturate:  ;
  --tw-backdrop-sepia:  ;
  --tw-contain-size:  ;
  --tw-contain-layout:  ;
  --tw-contain-paint:  ;
  --tw-contain-style:  ;
}

::backdrop {
  --tw-border-spacing-x: 0;
  --tw-border-spacing-y: 0;
  --tw-translate-x: 0;
  --tw-translate-y: 0;
  --tw-rotate: 0;
  --tw-skew-x: 0;
  --tw-skew-y: 0;
  --tw-scale-x: 1;
  --tw-scale-y: 1;
  --tw-pan-x:  ;
  --tw-pan-y:  ;
  --tw-pinch-zoom:  ;
  --tw-scroll-snap-strictness: proximity;
  --tw-gradient-from-position:  ;
  --tw-gradient-via-position:  ;
  --tw-gradient-to-position:  ;
  --tw-ordinal:  ;
  --tw-slashed-zero:  ;
  --tw-numeric-figure:  ;
  --tw-numeric-spacing:  ;
  --tw-numeric-fraction:  ;
  --tw-ring-inset:  ;
  --tw-ring-offset-width: 0px;
  --tw-ring-offset-color: #fff;
  --tw-ring-color: rgb(59 130 246 / 0.5);
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --tw-shadow: 0 0 #0000;
  --tw-shadow-colored: 0 0 #0000;
  --tw-blur:  ;
  --tw-brightness:  ;
  --tw-contrast:  ;
  --tw-grayscale:  ;
  --tw-hue-rotate:  ;
  --tw-invert:  ;
  --tw-saturate:  ;
  --tw-sepia:  ;
  --tw-drop-shadow:  ;
  --tw-backdrop-blur:  ;
  --tw-backdrop-brightness:  ;
  --tw-backdrop-contrast:  ;
  --tw-backdrop-grayscale:  ;
  --tw-backdrop-hue-rotate:  ;
  --tw-backdrop-invert:  ;
  --tw-backdrop-opacity:  ;
  --tw-backdrop-saturate:  ;
  --tw-backdrop-sepia:  ;
  --tw-contain-size:  ;
  --tw-contain-layout:  ;
  --tw-contain-paint:  ;
  --tw-contain-style:  ;
}

/*
! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com
*/

/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/

*,
::before,
::after {
  box-sizing: border-box;
  /* 1 */
  border-width: 0;
  /* 2 */
  border-style: solid;
  /* 2 */
  border-color: #e5e7eb;
  /* 2 */
}

::before,
::after {
  --tw-content: '';
}

/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
5. Use the user's configured `sans` font-feature-settings by default.
6. Use the user's configured `sans` font-variation-settings by default.
7. Disable tap highlights on iOS
*/

html,
:host {
  line-height: 1.5;
  /* 1 */
  -webkit-text-size-adjust: 100%;
  /* 2 */
  -moz-tab-size: 4;
  /* 3 */
  -o-tab-size: 4;
     tab-size: 4;
  /* 3 */
  font-family: Inter, system-ui, -apple-system, sans-serif;
  /* 4 */
  font-feature-settings: normal;
  /* 5 */
  font-variation-settings: normal;
  /* 6 */
  -webkit-tap-highlight-color: transparent;
  /* 7 */
}

/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/

body {
  margin: 0;
  /* 1 */
  line-height: inherit;
  /* 2 */
}

/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/

hr {
  height: 0;
  /* 1 */
  color: inherit;
  /* 2 */
  border-top-width: 1px;
  /* 3 */
}

/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/

abbr:where([title]) {
  -webkit-text-decoration: underline dotted;
          text-decoration: underline dotted;
}

/*
Remove the default font size and weight for headings.
*/

h1,
h2,
h3,
h4,
h5,
h6 {
  font-size: inherit;
  font-weight: inherit;
}

/*
Reset links to optimize for opt-in styling instead of opt-out.
*/

a {
  color: inherit;
  text-decoration: inherit;
}

/*
Add the correct font weight in Edge and Safari.
*/

b,
strong {
  font-weight: bolder;
}

/*
1. Use the user's configured `mono` font-family by default.
2. Use the user's configured `mono` font-feature-settings by default.
3. Use the user's configured `mono` font-variation-settings by default.
4. Correct the odd `em` font sizing in all browsers.
*/

code,
kbd,
samp,
pre {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  /* 1 */
  font-feature-settings: normal;
  /* 2 */
  font-variation-settings: normal;
  /* 3 */
  font-size: 1em;
  /* 4 */
}

/*
Add the correct font size in all browsers.
*/

small {
  font-size: 80%;
}

/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/

sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sub {
  bottom: -0.25em;
}

sup {
  top: -0.5em;
}

/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/

table {
  text-indent: 0;
  /* 1 */
  border-color: inherit;
  /* 2 */
  border-collapse: collapse;
  /* 3 */
}

/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/

button,
input,
optgroup,
select,
textarea {
  font-family: inherit;
  /* 1 */
  font-feature-settings: inherit;
  /* 1 */
  font-variation-settings: inherit;
  /* 1 */
  font-size: 100%;
  /* 1 */
  font-weight: inherit;
  /* 1 */
  line-height: inherit;
  /* 1 */
  letter-spacing: inherit;
  /* 1 */
  color: inherit;
  /* 1 */
  margin: 0;
  /* 2 */
  padding: 0;
  /* 3 */
}

/*
Remove the inheritance of text transform in Edge and Firefox.
*/

button,
select {
  text-transform: none;
}

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/

button,
input:where([type='button']),
input:where([type='reset']),
input:where([type='submit']) {
  -webkit-appearance: button;
  /* 1 */
  background-color: transparent;
  /* 2 */
  background-image: none;
  /* 2 */
}

/*
Use the modern Firefox focus style for all focusable elements.
*/

:-moz-focusring {
  outline: auto;
}

/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/

:-moz-ui-invalid {
  box-shadow: none;
}

/*
Add the correct vertical alignment in Chrome and Firefox.
*/

progress {
  vertical-align: baseline;
}

/*
Correct the cursor style of increment and decrement buttons in Safari.
*/

::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
  height: auto;
}

/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/

[type='search'] {
  -webkit-appearance: textfield;
  /* 1 */
  outline-offset: -2px;
  /* 2 */
}

/*
Remove the inner padding in Chrome and Safari on macOS.
*/

::-webkit-search-decoration {
  -webkit-appearance: none;
}

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/

::-webkit-file-upload-button {
  -webkit-appearance: button;
  /* 1 */
  font: inherit;
  /* 2 */
}

/*
Add the correct display in Chrome and Safari.
*/

summary {
  display: list-item;
}

/*
Removes the default spacing and border for appropriate elements.
*/

blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
  margin: 0;
}

fieldset {
  margin: 0;
  padding: 0;
}

legend {
  padding: 0;
}

ol,
ul,
menu {
  list-style: none;
  margin: 0;
  padding: 0;
}

/*
Reset default styling for dialogs.
*/

dialog {
  padding: 0;
}

/*
Prevent resizing textareas horizontally by default.
*/

textarea {
  resize: vertical;
}

/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/

input::-moz-placeholder, textarea::-moz-placeholder {
  opacity: 1;
  /* 1 */
  color: #9ca3af;
  /* 2 */
}

input::placeholder,
textarea::placeholder {
  opacity: 1;
  /* 1 */
  color: #9ca3af;
  /* 2 */
}

/*
Set the default cursor for buttons.
*/

button,
[role="button"] {
  cursor: pointer;
}

/*
Make sure disabled buttons don't get the pointer cursor.
*/

:disabled {
  cursor: default;
}

/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
   This can trigger a poorly considered lint error in some tools but is included by design.
*/

img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
  display: block;
  /* 1 */
  vertical-align: middle;
  /* 2 */
}

/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/

img,
video {
  max-width: 100%;
  height: auto;
}

/* Make elements with the HTML hidden attribute stay hidden by default */

[hidden]:where(:not([hidden="until-found"])) {
  display: none;
}

:root {
  --ease-smooth: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  /* The bar's height. Raised from 72 so the pill has room around what sits
     inside it: the Signup button is 46px, and in a 52px pill it left three
     pixels above and below, which reads as a button jammed into a bar rather
     than sitting in one. 98 now, which is 16px of air, the 66px pill and 16px
     again — the proportions of the reference. Every clearance below is stated
     against this token, so the bar's height is one number and not eleven. */
  --nav-h: 98px;
}

/* Phones: 86, which is what makes the pill's own padding even.

   The pill is .nav-shell::before, inset 12px on every side below 1024, and the
   bar pads its contents by 20 below 640 — so the gap from the pill's edge to
   the logo and the menu button is 20 - 12 = 8. Vertically it was 98 - 24 = 74
   of pill around a 46px button, which is 14 above and below: nearly twice the
   8 at the ends, and it read as a button floating in a tall lozenge.

   86 makes the pill 62, which is 8 above and below the same button.

   640, not the 768 the rest of the phone rules use, because the bar's own
   padding steps to 32 at 640. From there up it is already 14 against 20, which
   is close to the 10 against 20 the desktop bar is drawn with; shrinking the
   pill there would make it 8 against 20 and unbalance what is currently fine.
   Desktop keeps its 98 either way — that bar carries the nav links and wants
   the air.

   The token, not the inset: every clearance on the site is stated against
   --nav-h, so the bar shortening takes the heroes and the sticky offsets with
   it rather than leaving the pill floating lower in a bar that did not move. */

@media (max-width: 639px) {
  :root {
    --nav-h: 86px;
  }
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: 96px;
  -webkit-text-size-adjust: 100%;
}

body {
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
  font-family: Inter, system-ui, -apple-system, sans-serif;
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-optical-sizing: auto;
  overflow-x: clip;
}

::-moz-selection {
  background-color: rgb(0 153 255 / 0.2);
}

::selection {
  background-color: rgb(0 153 255 / 0.2);
}

h1, h2, h3, h4, h5 {
  font-family: "Bricolage Grotesque", system-ui, sans-serif;
  font-weight: 600;
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
  font-variation-settings: 'wdth' 100, 'opsz' 48;
}

img {
  max-width: 100%;
}

:focus-visible {
  outline: 2px solid #0099FF;
  outline-offset: 3px;
  border-radius: 6px;
}

.container {
  width: 100%;
}

@media (min-width: 430px) {
  .container {
    max-width: 430px;
  }
}

@media (min-width: 640px) {
  .container {
    max-width: 640px;
  }
}

@media (min-width: 768px) {
  .container {
    max-width: 768px;
  }
}

@media (min-width: 1024px) {
  .container {
    max-width: 1024px;
  }
}

@media (min-width: 1280px) {
  .container {
    max-width: 1280px;
  }
}

@media (min-width: 1536px) {
  .container {
    max-width: 1536px;
  }
}

.shell {
  margin-left: auto;
  margin-right: auto;
  width: 100%;
  max-width: 1260px;
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}

@media (min-width: 640px) {
  .shell {
    padding-left: 30px;
    padding-right: 30px;
  }
}

.content {
  margin-left: auto;
  margin-right: auto;
  width: 100%;
  max-width: 1200px;
}

.\!section {
  position: relative;
  padding-top: 70px;
  padding-bottom: 70px;
}

@media (min-width: 768px) {
  .\!section {
    padding-top: 100px;
    padding-bottom: 100px;
  }
}

.section {
  position: relative;
  padding-top: 70px;
  padding-bottom: 70px;
}

@media (min-width: 768px) {
  .section {
    padding-top: 100px;
    padding-bottom: 100px;
  }
}

/* Section eyebrow pill — "Core features", "Use cases", … */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border-radius: 100px;
  --tw-bg-opacity: 1;
  background-color: rgb(237 241 244 / var(--tw-bg-opacity, 1));
  padding-left: 1rem;
  padding-right: 1rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  font-size: 14px;
  line-height: 1.3;
  font-weight: 500;
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
}

.badge--light {
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}

/* The same tablet on a dark ground. .badge sits a shade darker than the
     white it is used on; this sits a shade lighter than the near-black, so
     the two read as the same object on their own backgrounds. */

.badge--dark {
  background-color: rgba(255, 255, 255, 0.08);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
  color: #ffffff;
}

.section-title {
  font-family: "Bricolage Grotesque", system-ui, sans-serif;
  font-size: 34px;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.6px;
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
}

@media (min-width: 640px) {
  .section-title {
    font-size: 40px;
  }
}

@media (min-width: 768px) {
  .section-title {
    font-size: 48px;
    line-height: 1.2;
    letter-spacing: -1px;
  }
}

.section-lead {
  font-size: 16px;
  font-weight: 500;
  line-height: 1.35;
  --tw-text-opacity: 1;
  color: rgb(77 88 95 / var(--tw-text-opacity, 1));
}

@media (min-width: 768px) {
  .section-lead {
    font-size: 18px;
    line-height: 1.3;
  }
}

/* ------------------------------------------------------------------
     BUTTONS
     ------------------------------------------------------------------ */

.btn {
  /* 15px, not the text-body-md scale — every variant @applies this rule, so
       this one line is what sets button type across the site. */
  position: relative;
  display: inline-flex;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  align-items: center;
  justify-content: center;
  gap: 14px;
  border-radius: 100px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  transition:
      transform 300ms var(--ease-smooth),
      box-shadow 300ms var(--ease-smooth),
      background-color 300ms var(--ease-soft),
      color 300ms var(--ease-soft),
      filter 300ms var(--ease-soft);
  will-change: transform;
}

.btn:active {
  transform: translateY(-1px) scale(0.98);
  transition-duration: 90ms;
}

/* icon capsule inside a button */

.btn__icon {
  display: grid;
  height: 38px;
  width: 38px;
  flex-shrink: 0;
  place-items: center;
  border-radius: 9999px;
  transition: transform 350ms var(--ease-smooth), background-color 300ms var(--ease-soft);
}

.btn__icon img,
  .btn__icon svg {
  transition: transform 350ms var(--ease-smooth);
}

.btn:hover .btn__icon img,
  .btn:hover .btn__icon svg {
  transform: translateX(3px);
}

/* Blue gradient primary */

.btn-primary {
  /* 15px, not the text-body-md scale — every variant @applies this rule, so
       this one line is what sets button type across the site. */
  position: relative;
  display: inline-flex;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  align-items: center;
  justify-content: center;
  gap: 14px;
  border-radius: 100px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  transition:
      transform 300ms var(--ease-smooth),
      box-shadow 300ms var(--ease-smooth),
      background-color 300ms var(--ease-soft),
      color 300ms var(--ease-soft),
      filter 300ms var(--ease-soft);
  will-change: transform;
}

.btn-primary:active {
  transform: translateY(-1px) scale(0.98);
  transition-duration: 90ms;
}

.btn-primary:hover .btn__icon img,.btn-primary:hover .btn__icon svg {
  transform: translateX(3px);
}

.btn-primary {
  padding-top: 10px;
  padding-bottom: 10px;
  padding-left: 30px;
  padding-right: 10px;
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}

@media (prefers-reduced-motion: reduce) {
  .btn-primary {
    transition-duration: 1ms;
  }

  .btn-primary:hover {
    transform: none;
  }
}

.btn-primary {
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  box-shadow: 0 8px 20px -8px rgba(37, 99, 235, 0.55);
}

/* ---- the white button, when it carries an arrow ----

   .btn__icon is a 38px disc with no ground of its own; each variant supplies
   one. .btn-primary sets white, .btn-white set nothing — so on the white
   button the arrow floated in an invisible circle, and the 34px of padding
   after it (sized for a button with no icon) opened the gap beside it.

   A pale disc, and the primary's padding exactly: 10 top and bottom, 30 before
   the label and 10 after the badge. All four matter — .btn-white's own 18 top
   and bottom made it 74px tall against the primary's 58, so the pair sat at
   different heights beside each other.

   :has(), so this reaches only the white buttons that actually hold an arrow.
   Six of the ten on the site do not — the calculator's Back, the 404's Contact
   us, the contact page's demo link — and giving those a 10px right edge would
   pull their label off centre. The selector is the same device
   #site-nav:has(.mobile-menu.is-open) already uses here. */

.btn-white:has(.btn__icon) {
  padding-top: 10px;
  padding-bottom: 10px;
  padding-left: 30px;
  padding-right: 10px;
}

.btn-white .btn__icon {
  background-color: #EDF1F4;
}

.btn-white:hover .btn__icon {
  background-color: #E2E8F0;
}

.btn-primary .btn__icon {
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}

.btn-primary:hover {
  transform: translateY(-2px);
  filter: saturate(1.08) brightness(1.03);
  box-shadow: 0 16px 30px -10px rgba(37, 99, 235, 0.6);
}

/* Solid dark */

.btn-dark {
  /* 15px, not the text-body-md scale — every variant @applies this rule, so
       this one line is what sets button type across the site. */
  position: relative;
  display: inline-flex;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  align-items: center;
  justify-content: center;
  gap: 14px;
  border-radius: 100px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  transition:
      transform 300ms var(--ease-smooth),
      box-shadow 300ms var(--ease-smooth),
      background-color 300ms var(--ease-soft),
      color 300ms var(--ease-soft),
      filter 300ms var(--ease-soft);
  will-change: transform;
}

.btn-dark:active {
  transform: translateY(-1px) scale(0.98);
  transition-duration: 90ms;
}

.btn-dark:hover .btn__icon img,.btn-dark:hover .btn__icon svg {
  transform: translateX(3px);
}

.btn-dark {
  --tw-bg-opacity: 1;
  background-color: rgb(29 29 29 / var(--tw-bg-opacity, 1));
  padding-top: 10px;
  padding-bottom: 10px;
  padding-left: 30px;
  padding-right: 10px;
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}

@media (prefers-reduced-motion: reduce) {
  .btn-dark {
    transition-duration: 1ms;
  }

  .btn-dark:hover {
    transform: none;
  }
}

.btn-dark {
  background-image: linear-gradient(180deg, #333 0%, #1d1d1d 60%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 8px 20px -10px rgba(29, 29, 29, 0.7);
}

.btn-dark .btn__icon {
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}

.btn-dark:hover {
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 16px 30px -12px rgba(29, 29, 29, 0.65);
}

/* Dark, no ring (nav / plain) */

.btn-solid {
  /* 15px, not the text-body-md scale — every variant @applies this rule, so
       this one line is what sets button type across the site. */
  position: relative;
  display: inline-flex;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  align-items: center;
  justify-content: center;
  gap: 14px;
  border-radius: 100px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  transition:
      transform 300ms var(--ease-smooth),
      box-shadow 300ms var(--ease-smooth),
      background-color 300ms var(--ease-soft),
      color 300ms var(--ease-soft),
      filter 300ms var(--ease-soft);
  will-change: transform;
}

.btn-solid:active {
  transform: translateY(-1px) scale(0.98);
  transition-duration: 90ms;
}

.btn-solid:hover .btn__icon img,.btn-solid:hover .btn__icon svg {
  transform: translateX(3px);
}

.btn-solid {
  --tw-bg-opacity: 1;
  background-color: rgb(29 29 29 / var(--tw-bg-opacity, 1));
  padding-left: 26px;
  padding-right: 26px;
  padding-top: 15px;
  padding-bottom: 15px;
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}

@media (prefers-reduced-motion: reduce) {
  .btn-solid {
    transition-duration: 1ms;
  }

  .btn-solid:hover {
    transform: none;
  }
}

.btn-solid {
  background-image: linear-gradient(180deg, #363636 0%, #1d1d1d 65%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 4px 14px -6px rgba(29, 29, 29, 0.5);
}

.btn-solid:hover {
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 12px 24px -10px rgba(29, 29, 29, 0.55);
}

/* White pill */

.btn-white {
  /* 15px, not the text-body-md scale — every variant @applies this rule, so
       this one line is what sets button type across the site. */
  position: relative;
  display: inline-flex;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  align-items: center;
  justify-content: center;
  gap: 14px;
  border-radius: 100px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  transition:
      transform 300ms var(--ease-smooth),
      box-shadow 300ms var(--ease-smooth),
      background-color 300ms var(--ease-soft),
      color 300ms var(--ease-soft),
      filter 300ms var(--ease-soft);
  will-change: transform;
}

.btn-white:active {
  transform: translateY(-1px) scale(0.98);
  transition-duration: 90ms;
}

.btn-white:hover .btn__icon img,.btn-white:hover .btn__icon svg {
  transform: translateX(3px);
}

.btn-white {
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
  padding-left: 34px;
  padding-right: 34px;
  padding-top: 18px;
  padding-bottom: 18px;
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
}

@media (prefers-reduced-motion: reduce) {
  .btn-white {
    transition-duration: 1ms;
  }

  .btn-white:hover {
    transform: none;
  }
}

.btn-white {
  box-shadow: 0 1px 2px rgba(29, 29, 29, 0.06), 0 6px 18px -10px rgba(29, 29, 29, 0.2);
}

.btn-white:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(29, 29, 29, 0.08), 0 14px 28px -12px rgba(29, 29, 29, 0.28);
}

/* Brand purple pill — the "Signup" action */

/* Same blue gradient as .btn-primary ("Get started now"), on the pill shape. */

.btn-brand {
  /* 15px, not the text-body-md scale — every variant @applies this rule, so
       this one line is what sets button type across the site. */
  position: relative;
  display: inline-flex;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  align-items: center;
  justify-content: center;
  gap: 14px;
  border-radius: 100px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  transition:
      transform 300ms var(--ease-smooth),
      box-shadow 300ms var(--ease-smooth),
      background-color 300ms var(--ease-soft),
      color 300ms var(--ease-soft),
      filter 300ms var(--ease-soft);
  will-change: transform;
}

.btn-brand:active {
  transform: translateY(-1px) scale(0.98);
  transition-duration: 90ms;
}

.btn-brand:hover .btn__icon img,.btn-brand:hover .btn__icon svg {
  transform: translateX(3px);
}

.btn-brand {
  border-radius: 100px;
  padding-left: 26px;
  padding-right: 26px;
  padding-top: 13px;
  padding-bottom: 13px;
  font-weight: 600;
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}

@media (prefers-reduced-motion: reduce) {
  .btn-brand {
    transition-duration: 1ms;
  }

  .btn-brand:hover {
    transform: none;
  }
}

.btn-brand {
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  box-shadow: 0 8px 20px -8px rgba(37, 99, 235, 0.55);
}

.btn-brand:hover {
  transform: translateY(-2px);
  filter: saturate(1.08) brightness(1.03);
  box-shadow: 0 16px 30px -10px rgba(37, 99, 235, 0.6);
}

/* Compact nav CTA */

.btn-nav .btn__icon {
  height: 1.75rem;
  width: 1.75rem;
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}

/* ------------------------------------------------------------------
     CARDS
     ------------------------------------------------------------------ */

.card {
  position: relative;
  overflow: hidden;
  border-radius: 30px;
  --tw-bg-opacity: 1;
  background-color: rgb(237 241 244 / var(--tw-bg-opacity, 1));
  transition:
      transform 420ms var(--ease-smooth),
      box-shadow 420ms var(--ease-smooth),
      background-color 420ms var(--ease-soft);
  will-change: transform;
}

/* The class is doubled on purpose: many cards are also `.reveal`, and
     `.reveal.is-visible` sets `transform` at the same specificity. Doubling
     wins without resorting to !important. */

.card-hover.card-hover:hover {
  transform: translateY(-4px);
  box-shadow: 0 18px 40px -18px rgba(29, 29, 29, 0.22), 0 2px 6px rgba(29, 29, 29, 0.05);
}

/* Illustration inside a hoverable card drifts a touch further */

.card-hover .card-art {
  transition: transform 520ms var(--ease-smooth);
  will-change: transform;
}

.card-hover:hover .card-art {
  transform: translateY(-5px) scale(1.015);
}

/* Section edge fades.
     Framer calls these "BG Top" / "BG Bottom": a 200 px band that dissolves a
     photographic section into the white page. The stops are the reference's —
     the fade is complete by the halfway mark, so the outer 100 px is solid. */

.bg-fade-bottom {
  background-image: linear-gradient(
      rgba(255, 255, 255, 0) 0%,
      rgba(255, 255, 255, 0.7) 25%,
      rgb(255, 255, 255) 50%
    );
}

.bg-fade-top {
  background-image: linear-gradient(
      0deg,
      rgba(255, 255, 255, 0) 0%,
      rgba(255, 255, 255, 0.7) 25%,
      rgb(255, 255, 255) 50%
    );
}

/* Ring-outlined panel used for the pricing shell and dashboards */

.panel-ring {
  box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.6), 0 24px 60px -28px rgba(29, 29, 29, 0.35);
}

/* ------------------------------------------------------------------
     NAVBAR
     ------------------------------------------------------------------ */

/* Full-bleed bar: spans the viewport, content padded to the edges.
     Transparent at the top of the page; frosts into white once scrolled. */

.nav-shell {
  display: flex;
  height: var(--nav-h);
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  background-color: transparent;
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}

@media (min-width: 640px) {
  .nav-shell {
    padding-left: 2rem;
    padding-right: 2rem;
  }
}

@media (min-width: 1024px) {
  .nav-shell {
    padding-left: 2.5rem;
    padding-right: 2.5rem;
  }
}

.nav-shell {
  position: relative;
  box-shadow: none;
  transition: box-shadow 420ms var(--ease-soft), background-color 420ms var(--ease-soft);
}

/* Scrolled no longer paints the whole bar: the pill below is what the reader
   sees, and a frosted full-width panel behind it would box it in. */
.is-scrolled .nav-shell {
  background-color: transparent;
  box-shadow: none;
}

/* THE PILL
   A white lozenge behind the bar's contents, so the links are readable over a
   photographic hero instead of sitting on whatever the page happens to put
   under them.

   PAINTED, NOT LAID OUT
   It is a pseudo-element inset inside the bar rather than a change to the
   bar's own box. The bar has to stay 72px and full width: the mega panel is
   `top: 100%` of the header wrapper and runs edge to edge, so shrinking the
   bar into a real pill would move the panel off the bottom of it. Nothing
   here touches layout, so the panel still meets the bar exactly where it did.

   It stands down when a menu opens. The bar goes solid white then (see the
   rule below) so the bar and the panel hanging off it read as one object; a
   pill floating inside a white bar with a white panel under it would be a
   third shape nobody asked for. */

.nav-shell::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 12px 12px;
  /* A rounded rectangle, not a 100px pill. At this height a full pill turns the
     two ends into half-circles and the bar reads as a lozenge; the reference
     keeps the corners soft and the sides straight. */
  border-radius: 16px;
  /* Frosted, not solid. The page reads through it, which keeps the bar part of
     the page rather than a white plate laid over it. The blur belongs with the
     transparency: it is what holds the links legible when what passes under
     the bar is a photograph or a dark band. */
  background-color: rgba(255, 255, 255, 0.42);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  /* One ring, and nothing else. No drop shadow and no bloom: the ring alone is
     what lifts the bar off whatever is behind it, and a shadow under a shape
     that is already ringed reads as two effects doing one job. */
  box-shadow: 0 0 0 1px rgba(221, 229, 237, 0.7);
  transition:
    opacity 420ms var(--ease-soft),
    background-color 420ms var(--ease-soft),
    box-shadow 420ms var(--ease-soft);
}

@media (min-width: 1024px) {
  .nav-shell::before {
    inset: 16px 20px;
  }
}

/* Scrolled, the pill carries the lift the full-width bar used to. */
.is-scrolled .nav-shell::before {
  background-color: #ffffff;
}

#site-nav:has(.nav-link:hover) .nav-shell::before,
#site-nav:has(.nav-item:hover) .nav-shell::before,
#site-nav:has(.nav-item.is-open) .nav-shell::before,
#site-nav:has(.mobile-menu.is-open) .nav-shell::before {
  opacity: 0;
}


/* With the mobile sheet open the bar must sit on a solid ground, or the
     links would show through the gap above the sheet. */

/* Hovering any nav link, dropdown or not: the bar sits on the panel's own
     white ground. Without this the bar stays transparent over the hero while a
     white panel hangs off it, and the two read as separate objects with the
     page showing between them.

     :hover as well as .is-open because hover opens the panel in CSS; .is-open
     is what keyboard and touch set. */

#site-nav:has(.nav-link:hover) .nav-shell,
  #site-nav:has(.nav-item:hover) .nav-shell,
  #site-nav:has(.nav-item.is-open) .nav-shell {
  background-color: #ffffff;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

#site-nav:has(.mobile-menu.is-open) .nav-shell {
  background-color: rgba(255, 255, 255, 0.95);
  backdrop-filter: saturate(180%) blur(16px);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
}

.nav-link {
  position: relative;
  border-radius: 100px;
  padding-left: 13px;
  padding-right: 13px;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.3;
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
  transition: color 260ms var(--ease-soft), background-color 260ms var(--ease-soft);
}

/* Brand blue, and a white pill under it. The pill is what the Products item
     already gets for free: hovering it turns the whole bar white, so the item
     reads as sitting on white. Every other item was hovering over the
     translucent bar with nothing behind it. Stated as plain declarations
     rather than @apply because css/style.css is committed as generated output
     with no build step to regenerate it, and the two had already drifted: this
     rule compiled to #5A41D8 there, a purple that is not a brand colour. */

/* Colour only, no pill. The white background was a hangover from when the
     bar was transparent over the hero and a hovered link needed something to
     sit on; with the bar going white whenever a panel opens, the pill reads as
     a second button appearing beside the real ones. */

.nav-link:hover {
  color: #2563EB;
}

.nav-link.is-active {
  --tw-bg-opacity: 1;
  background-color: rgb(237 241 244 / var(--tw-bg-opacity, 1));
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
}

/* ------------------------------------------------------------------
     NAV DROPDOWNS
     ------------------------------------------------------------------ */

.nav-caret {
  flex-shrink: 0;
  color: rgb(29 29 29 / 0.7);
  transition: transform 320ms var(--ease-smooth), color 260ms var(--ease-soft);
}

.nav-item:hover .nav-caret,
  .nav-item.is-open .nav-caret {
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
  transform: rotate(180deg);
}

.nav-menu {
  pointer-events: none;
  position: absolute;
  left: 50%;
  top: calc(100% + 14px);
  z-index: 50;
  width: 232px;
  --tw-translate-x: -50%;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
  border-radius: 14px;
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
  padding: 6px;
  opacity: 0;
  box-shadow:
      0 0 0 4px rgba(221, 229, 237, 0.7),
      0 18px 40px -18px rgba(29, 29, 29, 0.28);
  transform: translate(-50%, -8px);
  transition:
      opacity 240ms var(--ease-soft),
      transform 380ms var(--ease-smooth),
      visibility 240ms;
  visibility: hidden;
}

/* Invisible bridge so the pointer can cross the gap without closing */

.nav-menu::before {
  content: '';
  position: absolute;
  left: 0px;
  right: 0px;
  top: -14px;
  height: 14px;
}

.nav-item:hover .nav-menu,
  .nav-item.is-open .nav-menu,
  .nav-menu:focus-within {
  pointer-events: auto;
  opacity: 1;
  transform: translate(-50%, 0);
  visibility: visible;
}

.nav-menu__item {
  display: block;
  border-radius: 9px;
  padding-left: 13px;
  padding-right: 13px;
  padding-top: 10px;
  padding-bottom: 10px;
  font-size: 14px;
  line-height: 1.3;
  font-weight: 500;
  --tw-text-opacity: 1;
  color: rgb(77 88 95 / var(--tw-text-opacity, 1));
  transition: background-color 220ms var(--ease-soft), color 220ms var(--ease-soft);
}

.nav-menu__item:hover {
  --tw-bg-opacity: 1;
  background-color: rgb(237 241 244 / var(--tw-bg-opacity, 1));
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
}

/* Hamburger */

.burger-line {
  display: block;
  height: 2px;
  width: 18px;
  border-radius: 9999px;
  --tw-bg-opacity: 1;
  background-color: rgb(29 29 29 / var(--tw-bg-opacity, 1));
  transition: transform 380ms var(--ease-smooth), opacity 220ms var(--ease-soft);
}

/* Lines are 2 px tall with a 4 px gap, so the outer two are 6 px from
     the middle — translating by exactly that makes them concentric. */

.is-open .burger-line:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

.is-open .burger-line:nth-child(2) {
  opacity: 0;
  transform: scaleX(0.4);
}

.is-open .burger-line:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.mobile-menu {
  pointer-events: none;
  position: absolute;
  left: 0px;
  right: 0px;
  top: 100%;
  /* 100vh is the viewport with the browser's own chrome RETRACTED, which on a
     phone is taller than what is actually on screen. The sheet was sized to
     that, so its scroll ran out before the last rows came into view and
     everything under "Blog" was unreachable. dvh tracks the visible area and
     changes as the URL bar hides and returns; the vh line above stays as the
     fallback for anything that does not know the unit. */
  max-height: calc(100vh - var(--nav-h));
  max-height: calc(100dvh - var(--nav-h));
  /* The page behind must not take over once the sheet hits its end. */
  overscroll-behavior: contain;
  transform-origin: top;
  overflow-y: auto;
  background-color: rgb(255 255 255 / 0.95);
  padding: 1rem;
  opacity: 0;
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  box-shadow: 0 1px 0 rgba(221, 229, 237, 0.9), 0 24px 48px -20px rgba(29, 29, 29, 0.3);
  transform: translateY(-10px) scale(0.98);
  transition:
      opacity 300ms var(--ease-soft),
      transform 420ms var(--ease-smooth),
      visibility 300ms;
  visibility: hidden;
}

.mobile-menu.is-open {
  pointer-events: auto;
  opacity: 1;
  transform: translateY(0) scale(1);
  visibility: visible;
}

.mobile-menu a {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 380ms var(--ease-smooth), transform 380ms var(--ease-smooth);
}

.mobile-menu.is-open a {
  opacity: 1;
  transform: translateY(0);
}

/* ------------------------------------------------------------------
     LISTS / MISC
     ------------------------------------------------------------------ */

.check-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 18px;
  line-height: 1.3;
  font-weight: 500;
  --tw-text-opacity: 1;
  color: rgb(77 88 95 / var(--tw-text-opacity, 1));
}

/* ------------------------------------------------------------------
     STATEMENT
     One centred sentence on a dot grid, pinned while the page scrolls past.
     The track is four viewports tall and the panel inside it sticks, so the
     extra height is travel; animations.js splits that travel into three
     stages, each lighting one keyword and crossfading in its own widgets.
     Plain CSS rather than @apply: the headline is sized with clamp() so the
     line holds the same optical weight from a 390 px phone to a 1600 px
     desktop, and the widget field is laid out in absolute pixels so it can
     be scaled as one piece.
     ------------------------------------------------------------------ */

.statement {
  position: relative;
  background-color: #fff;
}

.statement__track {
  position: relative;
}

/* Phone padding. This is the mobile rule: the 768 and 1024 blocks below
   override it, so 40 here is only ever what a phone gets. It ran at 110, which
   on a 390px screen was most of a viewport of white above and below a single
   sentence. */
.statement__panel {
  position: relative;
  padding-top: 40px;
  padding-bottom: 40px;
}

/* ---- Stage wash ------------------------------------------------------
     A soft bloom of the live stage's accent, top and bottom, kept clear
     through the middle band so the headline still sits on near-white and
     holds its contrast. Three layers crossfade rather than one layer
     changing colour, because custom properties cannot be transitioned.
     -------------------------------------------------------------------- */

.statement__tints {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.st-tint {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 700ms var(--ease-smooth);
  background:
      radial-gradient(
        120% 78% at 50% 0%,
        rgba(var(--tint), 0.22) 0%,
        rgba(var(--tint), 0.07) 42%,
        rgba(var(--tint), 0) 72%
      ),
      radial-gradient(
        110% 62% at 50% 100%,
        rgba(var(--tint), 0.16) 0%,
        rgba(var(--tint), 0.04) 46%,
        rgba(var(--tint), 0) 76%
      );
}

.statement[data-stage='0'] .st-tint--0,
  .statement[data-stage='1'] .st-tint--1,
  .statement[data-stage='2'] .st-tint--2,
  .statement[data-stage='3'] .st-tint--3 {
  opacity: 1;
}

@media (min-width: 768px) {
  .statement__panel {
    padding-top: 180px;
    padding-bottom: 180px;
  }
}

/* The pin — and the widgets with it — is a desktop effect. Below lg the
     panel is an ordinary padded block and the sentence stands on its own.

     Height is one pinned viewport plus the travel that drives the stages, so
     240vh leaves about 140vh of travel — a third of a viewport per stage
     across the four of them, which is about one scroll gesture each. Raise it
     to slow the stages down, and raise it again if a fifth stage is added.

     The panel pins below the fixed 72 px navbar rather than at the top of the
     viewport: it clips its own overflow, so anything that would have slid up
     behind the bar is kept out of that band entirely. */

@media (min-width: 1024px) {
  .statement__track {
    height: 240vh;
  }

  .statement__panel {
    position: sticky;
    top: var(--nav-h);
    display: flex;
    align-items: center;
    height: calc(100vh - var(--nav-h));
    padding: 0;
    overflow: hidden;
  }
}

.statement__inner {
  position: relative;
  z-index: 2;
  margin-left: auto;
  margin-right: auto;
  width: 100%;
  /* Widened with the type: the sentence is tuned to break onto three lines,
       and the container has to grow at the same rate as the font or the larger
       size spills onto a fourth. */
  max-width: 1160px;
  padding-left: 24px;
  padding-right: 24px;
}

.statement__text {
  text-align: center;
  text-wrap: balance;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(26px, 4.4vw, 56px);
  font-weight: 600;
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: #1D1D1D;
}

/* Each word animates on its own: opacity + a 5 px rise + a 3 px blur that
     sharpens as it lands. The blur is what stops it reading as a plain slide. */

.statement__word {
  display: inline-block;
}

.statement__word.reveal {
  opacity: 0.001;
  transform: translate3d(0, 5px, 0);
  filter: blur(3px);
  transition:
      opacity 620ms var(--ease-smooth) var(--d, 0ms),
      transform 620ms var(--ease-smooth) var(--d, 0ms),
      filter 620ms var(--ease-smooth) var(--d, 0ms);
}

.statement__word.reveal.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  filter: blur(0);
}

/* One keyword per stage picks up its accent as that stage comes round; the
     others sit in ink, so the sentence reads as a whole either way. */

.statement__key {
  color: inherit;
  transition: color 520ms var(--ease-smooth);
}

/* One selector per stage, and the count has to match $STATEMENT_STAGES in
     includes/config.php. The sentence gained a fourth keyword — payroll — and
     this list did not follow it, so that word alone never lit: the stage ran,
     its wash came round (.st-tint--3 was updated), the widgets crossfaded, and
     the word it was all about stayed in ink. */

.statement[data-stage='0'] .statement__key[data-key='0'],
  .statement[data-stage='1'] .statement__key[data-key='1'],
  .statement[data-stage='2'] .statement__key[data-key='2'],
  .statement[data-stage='3'] .statement__key[data-key='3'] {
  color: var(--key-accent);
}

/* Without the pin there are no stages to step through, so every keyword
     carries its accent at once. */

@media (max-width: 1023px) {
  .statement__key {
    color: var(--key-accent);
  }
}

/* ---- The widget field -------------------------------------------------
     Every stage is a zero-size point at the centre of the panel; the widgets
     hang off it at fixed pixel offsets. Scaling the point scales positions
     and cards together, which is how the whole arrangement holds its shape
     on a narrower or shorter viewport.
     -------------------------------------------------------------------- */

.statement__stages {
  --st-zoom: 0.65;
  position: absolute;
  inset: 0;
  z-index: 2;
  display: none;
  pointer-events: none;
}

@media (min-width: 1024px) {
  .statement__stages {
    display: block;
  }
}

/* No breakpoints here on purpose. animations.js measures what the slots
     actually occupy and solves --st-zoom so the field fits the panel exactly,
     which is the only thing that stays correct when a card is resized. The
     value below is just the pre-script fallback. */

.st-stage {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  transform: translate3d(-50%, -50%, 0) scale(var(--st-zoom));
  opacity: 0;
  transition: opacity 620ms var(--ease-smooth);
}

.st-stage[data-state='in'] {
  opacity: 1;
}

/* Outer element: position, plus the drift. --drift is rewritten every frame
     by the scroll driver and runs from -half to +half across the pin, so each
     card slides steadily along its own (--dx, --dy) heading and sits at rest
     exactly halfway through. No transition here — the value is already
     continuous, and easing it would only smear it. */

.st-w {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--w);
  transform: translate3d(
      calc(-50% + var(--dx) * var(--drift, 0px)),
      calc(-50% + var(--dy) * var(--drift, 0px)),
      0
    );
}

/* Inner element: the stage change. Outgoing cards sink and shrink a little,
     so a swap reads as a swap rather than a plain dissolve. */

.st-w__in {
  transform: translate3d(0, var(--rise, 0px), 0) scale(var(--pop, 1));
  transition: transform 700ms var(--ease-smooth);
}

.st-stage[data-state='out'] .st-w__in {
  --rise: 16px;
  --pop: 0.96;
}

/* Slots: a and b sit above the sentence, c, d and e below it. The offsets
     are measured from the centre of the panel; --dx/--dy are unit vectors, so
     every card travels the same distance on its own bearing. */

.st-w--a {
  --x: -429px;
  --y: -340px;
  --w: 250px;
  --dx:  0.447;
  --dy: -0.894;
}

.st-w--b {
  --x:  335px;
  --y: -320px;
  --w: 330px;
  --dx:  0.894;
  --dy:  0.447;
}

.st-w--c {
  --x: -430px;
  --y:  285px;
  --w: 305px;
  --dx: -0.894;
  --dy: -0.447;
}

.st-w--d {
  --x:   30px;
  --y:  360px;
  --w: 340px;
  --dx: -0.894;
  --dy:  0.447;
}

.st-w--e {
  --x:  410px;
  --y:  270px;
  --w: 370px;
  --dx: -0.447;
  --dy:  0.894;
}

/* ---- Widget cards ---------------------------------------------------- */

.st-card {
  border-radius: 14px;
  background: #fff;
  border: 1px solid rgba(221, 229, 237, 0.9);
  box-shadow:
      0 1px 2px rgba(29, 29, 29, 0.05),
      0 18px 40px -22px rgba(29, 29, 29, 0.35);
  font-family: 'Inter', system-ui, sans-serif;
}

.st-card--dark {
  background: #1D1D1D;
  border-color: rgba(255, 255, 255, 0.08);
  color: #fff;
}

.st-card--dash {
  border: 1px dashed #C9D4E0;
  box-shadow: none;
}

.st-ico {
  width: 16px;
  height: 16px;
  flex: none;
}

.st-photo {
  display: block;
  width: 100%;
  height: 250px;
  -o-object-fit: cover;
     object-fit: cover;
  border-radius: 14px;
  box-shadow: 0 18px 40px -22px rgba(29, 29, 29, 0.45);
}

/* Switch row and action pill share a layout and differ only in radius. */

.st-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  font-size: 13px;
  color: #1D1D1D;
}

.st-row .st-ico {
  color: #2563EB;
}

.st-row__label {
  flex: 1;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.st-row--pill {
  gap: 12px;
  border-radius: 100px;
  padding: 11px 11px 11px 18px;
  font-size: 15px;
}

.st-row--pill .st-ico {
  width: 19px;
  height: 19px;
}

.st-row--toggle {
  gap: 12px;
  padding: 15px 18px;
  border-radius: 16px;
  font-size: 15px;
}

.st-row--toggle .st-ico {
  width: 19px;
  height: 19px;
}

.st-row--toggle .st-switch {
  width: 46px;
  height: 27px;
}

.st-row--toggle .st-switch i {
  top: 3px;
  left: 3px;
  width: 21px;
  height: 21px;
}

.st-row--toggle .st-switch.is-on i {
  transform: translateX(19px);
}

.st-switch {
  position: relative;
  flex: none;
  width: 36px;
  height: 20px;
  border-radius: 100px;
  background: #DDE5ED;
}

.st-switch i {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}

.st-switch.is-on {
  background: #10B981;
}

.st-switch.is-on i {
  transform: translateX(16px);
}

.st-plus {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: #3B82F6;
  color: #fff;
  font-size: 18px;
  line-height: 30px;
  text-align: center;
}

.st-stat {
  padding: 16px 18px 14px;
}

.st-stat__value {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 34px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
}

.st-stat__arrow {
  width: 12px;
  height: 12px;
  margin-top: 3px;
  color: #10B981;
}

.st-stat__caption {
  margin-top: 10px;
  font-size: 12px;
  line-height: 1.35;
  color: rgba(255, 255, 255, 0.55);
}

.st-stat__caption b {
  font-weight: 500;
  color: rgba(255, 255, 255, 0.9);
}

.st-stat__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 12px;
}

.st-chip {
  display: inline-block;
  padding: 5px 10px;
  border-radius: 100px;
  background: rgba(255, 255, 255, 0.12);
  font-size: 11px;
  font-weight: 500;
}

.st-chip--soft {
  background: #EDF1F4;
  color: #4D585F;
}

.st-dots {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  font-size: 9px;
  letter-spacing: 0.5px;
  opacity: 0.7;
}

.st-meter {
  overflow: hidden;
}

.st-meter__head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px;
  background: #1D1D1D;
  color: #fff;
  font-size: 12px;
  font-weight: 500;
}

.st-meter--brand .st-meter__head {
  background: #2563EB;
}

.st-meter__body {
  padding: 12px 14px 14px;
}

.st-meter__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 12px;
  color: #4D585F;
}

.st-meter__value {
  font-weight: 500;
  color: #1D1D1D;
}

.st-track {
  position: relative;
  height: 10px;
  margin-top: 10px;
  border-radius: 100px;
  background: #EDF1F4;
}

.st-track__fill {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: var(--pct);
  border-radius: 100px;
  background: #1D1D1D;
}

.st-meter--brand .st-track__fill {
  background: #2563EB;
}

.st-track__knob {
  position: absolute;
  top: 50%;
  left: var(--pct);
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 1px solid #DDE5ED;
  background: #fff;
  transform: translate(-60%, -50%);
}

.st-badge {
  display: inline-block;
  margin-top: 10px;
  padding: 4px 10px;
  border-radius: 100px;
  background: #EDF1F4;
  font-size: 11px;
  font-weight: 500;
  color: #4D585F;
}

.st-task {
  padding: 16px 18px;
}

.st-task .st-chip {
  padding: 6px 12px;
  font-size: 12.5px;
}

.st-task__head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.st-task__head .st-ico {
  width: 17px;
  height: 17px;
  color: #3B82F6;
}

.st-task__line {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed #DDE5ED;
  font-size: 14px;
  white-space: nowrap;
  color: #4D585F;
}

.st-chart {
  position: relative;
  height: 168px;
  padding: 16px;
  overflow: hidden;
}

.st-chart__bars {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  height: 100%;
}

.st-chart__bars i {
  flex: 1;
  border-radius: 6px 6px 0 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.04));
}

/* Sits over the bars, so it carries its own plate to stay readable. */

.st-chart__tag {
  position: absolute;
  top: 16px;
  right: 16px;
  padding: 8px 11px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.1);
  text-align: right;
}

.st-chart__tag b {
  display: block;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.st-chart__tag span {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.55);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

.pointer-events-none {
  pointer-events: none;
}

.visible {
  visibility: visible;
}

.invisible {
  visibility: hidden;
}

.collapse {
  visibility: collapse;
}

.static {
  position: static;
}

.fixed {
  position: fixed;
}

.absolute {
  position: absolute;
}

.\!relative {
  position: relative !important;
}

.relative {
  position: relative;
}

.sticky {
  position: sticky;
}

.inset-0 {
  inset: 0px;
}

.inset-\[10px\] {
  inset: 10px;
}

.inset-x-0 {
  left: 0px;
  right: 0px;
}

.-right-9 {
  right: -2.25rem;
}

.-top-4 {
  top: -1rem;
}

.bottom-0 {
  bottom: 0px;
}

.left-1\/2 {
  left: 50%;
}

.left-\[-10px\] {
  left: -10px;
}

.left-\[-130px\] {
  left: -130px;
}

.left-\[42\%\] {
  left: 42%;
}

.left-\[460px\] {
  left: 460px;
}

.left-\[6\%\] {
  left: 6%;
}

.left-\[916px\] {
  left: 916px;
}

.right-\[-10px\] {
  right: -10px;
}

.right-\[-40px\] {
  right: -40px;
}

.top-0 {
  top: 0px;
}

.top-1\/2 {
  top: 50%;
}

.top-\[-40px\] {
  top: -40px;
}

.top-\[48\%\] {
  top: 48%;
}

.top-\[50px\] {
  top: 50px;
}

.top-\[52\%\] {
  top: 52%;
}

.top-\[6px\] {
  top: 6px;
}

.top-\[80px\] {
  top: 80px;
}

.isolate {
  isolation: isolate;
}

.-z-10 {
  z-index: -10;
}

.-z-20 {
  z-index: -20;
}

.-z-\[15\] {
  z-index: -15;
}

.z-10 {
  z-index: 10;
}

.z-20 {
  z-index: 20;
}

.z-30 {
  z-index: 30;
}

.z-40 {
  z-index: 40;
}

.z-50 {
  z-index: 50;
}

.mx-3 {
  margin-left: 0.75rem;
  margin-right: 0.75rem;
}

.mx-4 {
  margin-left: 1rem;
  margin-right: 1rem;
}

.mx-auto {
  margin-left: auto;
  margin-right: auto;
}

.my-8 {
  margin-top: 2rem;
  margin-bottom: 2rem;
}

.mb-1 {
  margin-bottom: 0.25rem;
}

.mb-3 {
  margin-bottom: 0.75rem;
}

.mb-8 {
  margin-bottom: 2rem;
}

.mb-\[-24px\] {
  margin-bottom: -24px;
}

.mb-\[80px\] {
  margin-bottom: 80px;
}

.ml-4 {
  margin-left: 1rem;
}

.mt-1 {
  margin-top: 0.25rem;
}

.mt-10 {
  margin-top: 2.5rem;
}

.mt-12 {
  margin-top: 3rem;
}

.mt-2 {
  margin-top: 0.5rem;
}

.mt-3 {
  margin-top: 0.75rem;
}

.mt-4 {
  margin-top: 1rem;
}

.mt-5 {
  margin-top: 1.25rem;
}

.mt-6 {
  margin-top: 1.5rem;
}

.mt-7 {
  margin-top: 1.75rem;
}

.mt-8 {
  margin-top: 2rem;
}

.mt-9 {
  margin-top: 2.25rem;
}

.mt-\[-1px\] {
  margin-top: -1px;
}

.mt-\[30px\] {
  margin-top: 30px;
}

.mt-\[43px\] {
  margin-top: 43px;
}

.mt-\[50px\] {
  margin-top: 50px;
}

.mt-\[60px\] {
  margin-top: 60px;
}

.mt-\[6px\] {
  margin-top: 6px;
}

.mt-\[70px\] {
  margin-top: 70px;
}

.block {
  display: block;
}

.inline-block {
  display: inline-block;
}

.inline {
  display: inline;
}

.flex {
  display: flex;
}

.inline-flex {
  display: inline-flex;
}

.\!table {
  display: table !important;
}

.table {
  display: table;
}

.\!grid {
  display: grid !important;
}

.grid {
  display: grid;
}

.contents {
  display: contents;
}

.hidden {
  display: none;
}

.h-10 {
  height: 2.5rem;
}

.h-5 {
  height: 1.25rem;
}

.h-7 {
  height: 1.75rem;
}

.h-8 {
  height: 2rem;
}

.h-\[104px\] {
  height: 104px;
}

.h-\[1080px\] {
  height: 1080px;
}

.h-\[10px\] {
  height: 10px;
}

.h-\[110px\] {
  height: 110px;
}

.h-\[112\%\] {
  height: 112%;
}

.h-\[11px\] {
  height: 11px;
}

.h-\[130px\] {
  height: 130px;
}

.h-\[14px\] {
  height: 14px;
}

.h-\[18px\] {
  height: 18px;
}

.h-\[196px\] {
  height: 196px;
}

.h-\[200px\] {
  height: 200px;
}

.h-\[26px\] {
  height: 26px;
}

.h-\[280px\] {
  height: 280px;
}

.h-\[290px\] {
  height: 290px;
}

.h-\[2px\] {
  height: 2px;
}

.h-\[30px\] {
  height: 30px;
}

.h-\[34px\] {
  height: 34px;
}

.h-\[360px\] {
  height: 360px;
}

.h-\[38px\] {
  height: 38px;
}

.h-\[3px\] {
  height: 3px;
}

.h-\[420px\] {
  height: 420px;
}

.h-\[42px\] {
  height: 42px;
}

.h-\[44px\] {
  height: 44px;
}

.h-\[50px\] {
  height: 50px;
}

.h-\[64px\] {
  height: 64px;
}

.h-\[74px\] {
  height: 74px;
}

.h-\[9px\] {
  height: 9px;
}

.h-auto {
  height: auto;
}

.h-full {
  height: 100%;
}

.min-h-\[260px\] {
  min-height: 260px;
}

.min-h-\[360px\] {
  min-height: 360px;
}

.w-10 {
  width: 2.5rem;
}

.w-5 {
  width: 1.25rem;
}

.w-7 {
  width: 1.75rem;
}

.w-8 {
  width: 2rem;
}

.w-\[104px\] {
  width: 104px;
}

.w-\[10px\] {
  width: 10px;
}

.w-\[11px\] {
  width: 11px;
}

.w-\[14px\] {
  width: 14px;
}

.w-\[280px\] {
  width: 280px;
}

.w-\[2px\] {
  width: 2px;
}

.w-\[300px\] {
  width: 300px;
}

.w-\[320px\] {
  width: 320px;
}

.w-\[34px\] {
  width: 34px;
}

.w-\[38\%\] {
  width: 38%;
}

.w-\[38px\] {
  width: 38px;
}

.w-\[3px\] {
  width: 3px;
}

.w-\[42px\] {
  width: 42px;
}

.w-\[455px\] {
  width: 455px;
}

.w-\[50px\] {
  width: 50px;
}

.w-\[519px\] {
  width: 519px;
}

.w-\[52\%\] {
  width: 52%;
}

.w-\[584px\] {
  width: 584px;
}

.w-\[602px\] {
  width: 602px;
}

.w-\[60px\] {
  width: 60px;
}

.w-\[64px\] {
  width: 64px;
}

.w-\[74px\] {
  width: 74px;
}

.w-\[9px\] {
  width: 9px;
}

.w-auto {
  width: auto;
}

.w-full {
  width: 100%;
}

.w-px {
  width: 1px;
}

.min-w-0 {
  min-width: 0px;
}

.max-w-\[1060px\] {
  max-width: 1060px;
}

.max-w-\[130px\] {
  max-width: 130px;
}

.max-w-\[250px\] {
  max-width: 250px;
}

.max-w-\[300px\] {
  max-width: 300px;
}

.max-w-\[320px\] {
  max-width: 320px;
}

.max-w-\[330px\] {
  max-width: 330px;
}

.max-w-\[340px\] {
  max-width: 340px;
}

.max-w-\[400px\] {
  max-width: 400px;
}

.max-w-\[420px\] {
  max-width: 420px;
}

.max-w-\[430px\] {
  max-width: 430px;
}

.max-w-\[500px\] {
  max-width: 500px;
}

.max-w-\[520px\] {
  max-width: 520px;
}

.max-w-\[536px\] {
  max-width: 536px;
}

.max-w-\[560px\] {
  max-width: 560px;
}

.max-w-\[580px\] {
  max-width: 580px;
}

.max-w-\[620px\] {
  max-width: 620px;
}

.max-w-\[680px\] {
  max-width: 680px;
}

.max-w-\[690px\] {
  max-width: 690px;
}

.max-w-\[800px\] {
  max-width: 800px;
}

.max-w-full {
  max-width: 100%;
}

.max-w-none {
  max-width: none;
}

.flex-1 {
  flex: 1 1 0%;
}

.shrink {
  flex-shrink: 1;
}

.shrink-0 {
  flex-shrink: 0;
}

.grow {
  flex-grow: 1;
}

.origin-center {
  transform-origin: center;
}

.origin-top {
  transform-origin: top;
}

.-translate-x-1\/2 {
  --tw-translate-x: -50%;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.-translate-y-1\/2 {
  --tw-translate-y: -50%;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.scale-y-\[-1\] {
  --tw-scale-y: -1;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.transform {
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.cursor-pointer {
  cursor: pointer;
}

.select-none {
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}

.resize {
  resize: both;
}

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

.flex-col {
  flex-direction: column;
}

.flex-wrap {
  flex-wrap: wrap;
}

.place-items-center {
  place-items: center;
}

.items-start {
  align-items: flex-start;
}

.items-end {
  align-items: flex-end;
}

.items-center {
  align-items: center;
}

.justify-center {
  justify-content: center;
}

.justify-between {
  justify-content: space-between;
}

.gap-10 {
  gap: 2.5rem;
}

.gap-12 {
  gap: 3rem;
}

.gap-2 {
  gap: 0.5rem;
}

.gap-3 {
  gap: 0.75rem;
}

.gap-4 {
  gap: 1rem;
}

.gap-5 {
  gap: 1.25rem;
}

.gap-6 {
  gap: 1.5rem;
}

.gap-8 {
  gap: 2rem;
}

.gap-\[10px\] {
  gap: 10px;
}

.gap-\[14px\] {
  gap: 14px;
}

.gap-\[180px\] {
  gap: 180px;
}

.gap-\[18px\] {
  gap: 18px;
}

.gap-\[20px\] {
  gap: 20px;
}

.gap-\[2px\] {
  gap: 2px;
}

.gap-\[30px\] {
  gap: 30px;
}

.gap-\[4px\] {
  gap: 4px;
}

.gap-\[6px\] {
  gap: 6px;
}

.gap-x-1 {
  -moz-column-gap: 0.25rem;
       column-gap: 0.25rem;
}

.gap-x-2 {
  -moz-column-gap: 0.5rem;
       column-gap: 0.5rem;
}

.gap-x-4 {
  -moz-column-gap: 1rem;
       column-gap: 1rem;
}

.gap-y-1 {
  row-gap: 0.25rem;
}

.gap-y-2 {
  row-gap: 0.5rem;
}

.gap-y-3 {
  row-gap: 0.75rem;
}

.-space-x-3 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-x-reverse: 0;
  margin-right: calc(-0.75rem * var(--tw-space-x-reverse));
  margin-left: calc(-0.75rem * calc(1 - var(--tw-space-x-reverse)));
}

.space-y-4 > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(1rem * var(--tw-space-y-reverse));
}

.space-y-\[10px\] > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(10px * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(10px * var(--tw-space-y-reverse));
}

.space-y-\[14px\] > :not([hidden]) ~ :not([hidden]) {
  --tw-space-y-reverse: 0;
  margin-top: calc(14px * calc(1 - var(--tw-space-y-reverse)));
  margin-bottom: calc(14px * var(--tw-space-y-reverse));
}

.overflow-hidden {
  overflow: hidden;
}

.overflow-x-clip {
  overflow-x: clip;
}

.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.whitespace-nowrap {
  white-space: nowrap;
}

.\!rounded-\[20px\] {
  border-radius: 20px !important;
}

.\!rounded-\[24px\] {
  border-radius: 24px !important;
}

.\!rounded-card-lg {
  border-radius: 30px !important;
}

.rounded {
  border-radius: 0.25rem;
}

.rounded-\[10px\] {
  border-radius: 10px;
}

.rounded-\[12px\] {
  border-radius: 12px;
}

.rounded-\[16px\] {
  border-radius: 16px;
}

.rounded-\[18px\] {
  border-radius: 18px;
}

.rounded-\[26px\] {
  border-radius: 26px;
}

.rounded-\[8px\] {
  border-radius: 8px;
}

.rounded-\[9px\] {
  border-radius: 9px;
}

.rounded-card-lg {
  border-radius: 30px;
}

.rounded-full {
  border-radius: 9999px;
}

.rounded-pill {
  border-radius: 100px;
}

.rounded-t-\[20px\] {
  border-top-left-radius: 20px;
  border-top-right-radius: 20px;
}

.border {
  border-width: 1px;
}

.border-y {
  border-top-width: 1px;
  border-bottom-width: 1px;
}

.border-l {
  border-left-width: 1px;
}

.border-t {
  border-top-width: 1px;
}

.border-line {
  --tw-border-opacity: 1;
  border-color: rgb(221 229 237 / var(--tw-border-opacity, 1));
}

.\!bg-\[\#E9F3FB\] {
  --tw-bg-opacity: 1 !important;
  background-color: rgb(233 243 251 / var(--tw-bg-opacity, 1)) !important;
}

.\!bg-ink {
  --tw-bg-opacity: 1 !important;
  background-color: rgb(29 29 29 / var(--tw-bg-opacity, 1)) !important;
}

.\!bg-surface {
  --tw-bg-opacity: 1 !important;
  background-color: rgb(237 241 244 / var(--tw-bg-opacity, 1)) !important;
}

.\!bg-white {
  --tw-bg-opacity: 1 !important;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1)) !important;
}

.bg-\[\#3B82F6\] {
  --tw-bg-opacity: 1;
  background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));
}

.bg-\[\#FBE9E9\] {
  --tw-bg-opacity: 1;
  background-color: rgb(251 233 233 / var(--tw-bg-opacity, 1));
}

.bg-ink {
  --tw-bg-opacity: 1;
  background-color: rgb(29 29 29 / var(--tw-bg-opacity, 1));
}

.bg-ink\/15 {
  background-color: rgb(29 29 29 / 0.15);
}

.bg-line {
  --tw-bg-opacity: 1;
  background-color: rgb(221 229 237 / var(--tw-bg-opacity, 1));
}

.bg-primary {
  --tw-bg-opacity: 1;
  background-color: rgb(0 153 255 / var(--tw-bg-opacity, 1));
}

.bg-success\/10 {
  background-color: rgb(16 185 129 / 0.1);
}

.bg-success\/15 {
  background-color: rgb(16 185 129 / 0.15);
}

.bg-surface {
  --tw-bg-opacity: 1;
  background-color: rgb(237 241 244 / var(--tw-bg-opacity, 1));
}

.bg-surface\/70 {
  background-color: rgb(237 241 244 / 0.7);
}

.bg-white {
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}

.bg-white\/35 {
  background-color: rgb(255 255 255 / 0.35);
}

.bg-white\/75 {
  background-color: rgb(255 255 255 / 0.75);
}

.bg-gradient-to-b {
  background-image: linear-gradient(to bottom, var(--tw-gradient-stops));
}

.bg-gradient-to-t {
  background-image: linear-gradient(to top, var(--tw-gradient-stops));
}

.from-ink {
  --tw-gradient-from: #1D1D1D var(--tw-gradient-from-position);
  --tw-gradient-to: rgb(29 29 29 / 0) var(--tw-gradient-to-position);
  --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}

.from-success\/45 {
  --tw-gradient-from: rgb(16 185 129 / 0.45) var(--tw-gradient-from-position);
  --tw-gradient-to: rgb(16 185 129 / 0) var(--tw-gradient-to-position);
  --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}

.via-ink\/90 {
  --tw-gradient-to: rgb(29 29 29 / 0)  var(--tw-gradient-to-position);
  --tw-gradient-stops: var(--tw-gradient-from), rgb(29 29 29 / 0.9) var(--tw-gradient-via-position), var(--tw-gradient-to);
}

.to-ink\/70 {
  --tw-gradient-to: rgb(29 29 29 / 0.7) var(--tw-gradient-to-position);
}

.to-transparent {
  --tw-gradient-to: transparent var(--tw-gradient-to-position);
}

.bg-clip-text {
  -webkit-background-clip: text;
          background-clip: text;
}

.object-contain {
  -o-object-fit: contain;
     object-fit: contain;
}

.object-cover {
  -o-object-fit: cover;
     object-fit: cover;
}

.object-center {
  -o-object-position: center;
     object-position: center;
}

.object-top {
  -o-object-position: top;
     object-position: top;
}

.p-10 {
  padding: 2.5rem;
}

.p-4 {
  padding: 1rem;
}

.p-6 {
  padding: 1.5rem;
}

.p-7 {
  padding: 1.75rem;
}

.p-8 {
  padding: 2rem;
}

.p-\[10px\] {
  padding: 10px;
}

.p-\[6px\] {
  padding: 6px;
}

.\!py-\[17px\] {
  padding-top: 17px !important;
  padding-bottom: 17px !important;
}

.\!py-\[18px\] {
  padding-top: 18px !important;
  padding-bottom: 18px !important;
}

.px-1 {
  padding-left: 0.25rem;
  padding-right: 0.25rem;
}

.px-2 {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}

.px-3 {
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

.px-4 {
  padding-left: 1rem;
  padding-right: 1rem;
}

.px-5 {
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}

.px-6 {
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}

.px-7 {
  padding-left: 1.75rem;
  padding-right: 1.75rem;
}

.px-8 {
  padding-left: 2rem;
  padding-right: 2rem;
}

.px-\[10px\] {
  padding-left: 10px;
  padding-right: 10px;
}

.py-1 {
  padding-top: 0.25rem;
  padding-bottom: 0.25rem;
}

.py-4 {
  padding-top: 1rem;
  padding-bottom: 1rem;
}

.py-6 {
  padding-top: 1.5rem;
  padding-bottom: 1.5rem;
}

.py-\[10px\] {
  padding-top: 10px;
  padding-bottom: 10px;
}

.py-\[13px\] {
  padding-top: 13px;
  padding-bottom: 13px;
}

.py-\[19px\] {
  padding-top: 19px;
  padding-bottom: 19px;
}

.py-\[22px\] {
  padding-top: 22px;
  padding-bottom: 22px;
}

.py-\[30px\] {
  padding-top: 30px;
  padding-bottom: 30px;
}

.py-\[3px\] {
  padding-top: 3px;
  padding-bottom: 3px;
}

.py-\[6px\] {
  padding-top: 6px;
  padding-bottom: 6px;
}

.py-\[70px\] {
  padding-top: 70px;
  padding-bottom: 70px;
}

.py-\[7px\] {
  padding-top: 7px;
  padding-bottom: 7px;
}

.py-\[80px\] {
  padding-top: 80px;
  padding-bottom: 80px;
}

.py-\[9px\] {
  padding-top: 9px;
  padding-bottom: 9px;
}

.pb-1 {
  padding-bottom: 0.25rem;
}

.pb-10 {
  padding-bottom: 2.5rem;
}

.pb-6 {
  padding-bottom: 1.5rem;
}

.pb-7 {
  padding-bottom: 1.75rem;
}

.pb-8 {
  padding-bottom: 2rem;
}

.pb-9 {
  padding-bottom: 2.25rem;
}

.pb-\[6px\] {
  padding-bottom: 6px;
}

.pl-3 {
  padding-left: 0.75rem;
}

.pl-6 {
  padding-left: 1.5rem;
}

.pr-6 {
  padding-right: 1.5rem;
}

.pt-3 {
  padding-top: 0.75rem;
}

.pt-8 {
  padding-top: 2rem;
}

.pt-9 {
  padding-top: 2.25rem;
}

.pt-\[130px\] {
  padding-top: 130px;
}

.pt-\[70px\] {
  padding-top: 70px;
}

.pt-\[80px\] {
  padding-top: 80px;
}

.text-left {
  text-align: left;
}

.text-center {
  text-align: center;
}

.text-right {
  text-align: right;
}

.font-display {
  font-family: "Bricolage Grotesque", system-ui, sans-serif;
}

.font-sans {
  font-family: Inter, system-ui, -apple-system, sans-serif;
}

.\!text-body-md {
  font-size: 18px !important;
  line-height: 1.3 !important;
}

.\!text-body-sm {
  font-size: 16px !important;
  line-height: 1.3 !important;
}

.text-\[10px\] {
  font-size: 10px;
}

.text-\[11px\] {
  font-size: 11px;
}

.text-\[13px\] {
  font-size: 13px;
}

.text-\[15px\] {
  font-size: 15px;
}

.text-\[19px\] {
  font-size: 19px;
}

.text-\[20px\] {
  font-size: 20px;
}

.text-\[22px\] {
  font-size: 22px;
}

.text-\[24px\] {
  font-size: 24px;
}

.text-\[28px\] {
  font-size: 28px;
}

.text-\[44px\] {
  font-size: 44px;
}

.text-\[52px\] {
  font-size: 52px;
}

.text-\[76px\] {
  font-size: 76px;
}

.text-body-lg {
  font-size: 20px;
  line-height: 1.3;
}

.text-body-md {
  font-size: 18px;
  line-height: 1.3;
}

.text-body-sm {
  font-size: 16px;
  line-height: 1.3;
}

.text-body-xs {
  font-size: 14px;
  line-height: 1.3;
}

.text-display-md {
  font-size: 40px;
  line-height: 1.2;
  letter-spacing: -1px;
}

.text-display-xs {
  font-size: 28px;
  line-height: 1.2;
}

.font-bold {
  font-weight: 700;
}

.font-medium {
  font-weight: 500;
}

.font-normal {
  font-weight: 400;
}

.font-semibold {
  font-weight: 600;
}

.uppercase {
  text-transform: uppercase;
}

.leading-\[0\.72\] {
  line-height: 0.72;
}

.leading-\[1\.2\] {
  line-height: 1.2;
}

.leading-\[1\.45\] {
  line-height: 1.45;
}

.leading-\[1\.4\] {
  line-height: 1.4;
}

.leading-\[1\.55\] {
  line-height: 1.55;
}

.leading-\[1\.5\] {
  line-height: 1.5;
}

.leading-\[1\] {
  line-height: 1;
}

.leading-none {
  line-height: 1;
}

.leading-tight {
  line-height: 1.25;
}

.tracking-\[-0\.5px\] {
  letter-spacing: -0.5px;
}

.tracking-\[-1px\] {
  letter-spacing: -1px;
}

.text-\[\#D9414A\] {
  --tw-text-opacity: 1;
  color: rgb(217 65 74 / var(--tw-text-opacity, 1));
}

.text-ink {
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
}

.text-muted {
  --tw-text-opacity: 1;
  color: rgb(77 88 95 / var(--tw-text-opacity, 1));
}

.text-subtle {
  --tw-text-opacity: 1;
  color: rgb(186 186 186 / var(--tw-text-opacity, 1));
}

.text-success {
  --tw-text-opacity: 1;
  color: rgb(16 185 129 / var(--tw-text-opacity, 1));
}

.text-transparent {
  color: transparent;
}

.text-white {
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}

.text-white\/60 {
  color: rgb(255 255 255 / 0.6);
}

.text-white\/65 {
  color: rgb(255 255 255 / 0.65);
}

.text-white\/70 {
  color: rgb(255 255 255 / 0.7);
}

.text-white\/85 {
  color: rgb(255 255 255 / 0.85);
}

.\!opacity-100 {
  opacity: 1 !important;
}

.opacity-30 {
  opacity: 0.3;
}

.opacity-70 {
  opacity: 0.7;
}

.opacity-80 {
  opacity: 0.8;
}

.opacity-90 {
  opacity: 0.9;
}

.shadow {
  --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
  --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.shadow-\[0_0_0_1px_theme\(colors\.line\)\] {
  --tw-shadow: 0 0 0 1px #DDE5ED;
  --tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.shadow-\[0_10px_30px_-12px_rgba\(29\2c 29\2c 29\2c \.25\)\] {
  --tw-shadow: 0 10px 30px -12px rgba(29,29,29,.25);
  --tw-shadow-colored: 0 10px 30px -12px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.shadow-\[0_8px_22px_-12px_rgba\(29\2c 29\2c 29\2c \.3\)\] {
  --tw-shadow: 0 8px 22px -12px rgba(29,29,29,.3);
  --tw-shadow-colored: 0 8px 22px -12px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.shadow-card {
  --tw-shadow: 0 1px 2px rgba(29,29,29,.04);
  --tw-shadow-colored: 0 1px 2px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.shadow-dash {
  --tw-shadow: 0 24px 60px -20px rgba(29,29,29,.28);
  --tw-shadow-colored: 0 24px 60px -20px var(--tw-shadow-color);
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.ring {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}

.ring-1 {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}

.ring-\[3px\] {
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}

.ring-inset {
  --tw-ring-inset: inset;
}

.ring-\[\#F1C9C9\]\/70 {
  --tw-ring-color: rgb(241 201 201 / 0.7);
}

.ring-line {
  --tw-ring-opacity: 1;
  --tw-ring-color: rgb(221 229 237 / var(--tw-ring-opacity, 1));
}

.ring-success\/25 {
  --tw-ring-color: rgb(16 185 129 / 0.25);
}

.ring-surface {
  --tw-ring-opacity: 1;
  --tw-ring-color: rgb(237 241 244 / var(--tw-ring-opacity, 1));
}

.ring-white\/45 {
  --tw-ring-color: rgb(255 255 255 / 0.45);
}

.blur {
  --tw-blur: blur(8px);
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}

.brightness-0 {
  --tw-brightness: brightness(0);
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}

.drop-shadow {
  --tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) drop-shadow(0 1px 1px rgb(0 0 0 / 0.06));
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}

.invert {
  --tw-invert: invert(100%);
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}

.filter {
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}

.backdrop-blur {
  --tw-backdrop-blur: blur(8px);
  -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
  backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}

.backdrop-blur-\[14px\] {
  --tw-backdrop-blur: blur(14px);
  -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
  backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}

.transition {
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

.transition-all {
  transition-property: all;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

.transition-colors {
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

.transition-opacity {
  transition-property: opacity;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

.duration-300 {
  transition-duration: 300ms;
}

.ease-smooth {
  transition-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

.will-change-transform {
  will-change: transform;
}

/* ==========================================================================
   BASE
   ========================================================================== */

/* ==========================================================================
   LAYOUT PRIMITIVES
   ========================================================================== */

/* ==========================================================================
   1. PAGE-LOAD ENTRANCE
   Elements carry .load-in and a --d delay; the body gets .is-loaded on
   DOMContentLoaded which releases the whole staggered sequence.
   ========================================================================== */

.load-in {
  opacity: 0;
  transform: translate3d(0, var(--load-y, 24px), 0) scale(var(--load-s, 1));
  transition:
    opacity 700ms var(--ease-smooth) var(--d, 0ms),
    transform 900ms var(--ease-smooth) var(--d, 0ms);
  will-change: transform, opacity;
}

.is-loaded .load-in {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

/* Release will-change once the sequence is finished */

.is-loaded .load-in.load-done {
  will-change: auto;
}

/* ==========================================================================
   4/5. SCROLL REVEAL
   ========================================================================== */

.reveal {
  opacity: 0;
  transition:
    opacity 700ms var(--ease-smooth) var(--d, 0ms),
    transform 800ms var(--ease-smooth) var(--d, 0ms);
  will-change: transform, opacity;
}

.reveal-up      {
  transform: translate3d(0, 40px, 0);
}

.reveal-down    {
  transform: translate3d(0, -30px, 0);
}

.reveal-left    {
  transform: translate3d(-40px, 0, 0);
}

.reveal-right   {
  transform: translate3d(40px, 0, 0);
}

.reveal-scale   {
  transform: translate3d(0, 30px, 0) scale(0.96);
}

.reveal-fade    {
  transform: none;
}

/* Phones: the sideways reveals travel up instead.

   .reveal-right holds an element 40px right of where it lands, and an element
   that is nearly the full width of a phone then sticks out past the right
   edge — the FAQ items were 20px over on a 430px screen, which is a horizontal
   scrollbar on the whole document from load, because a block below the fold
   has not revealed yet and may never.

   .reveal-left has the mirror problem: it parks content under the left edge,
   where a reader cannot scroll to it at all. On a screen this narrow a
   sideways slide of 40px reads as a fade anyway, so both take the vertical
   travel .reveal-up already uses. .reveal.is-visible outweighs this and still
   lands everything at 0. */

@media (max-width: 767px) {
  .reveal-left,
  .reveal-right {
    transform: translate3d(0, 40px, 0);
  }
}

.reveal.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

.reveal.reveal-done {
  will-change: auto;
}

/* ==========================================================================
   3/7/10. CONTINUOUS FLOAT + DRIFT
   Duration/offset come from custom properties so no two elements sync up.
   ========================================================================== */

@keyframes fx-float {
  0%, 100% {
    transform: translate3d(0, 0, 0);
  }

  50%      {
    transform: translate3d(0, var(--float-y, -8px), 0);
  }
}

@keyframes fx-drift {
  0%, 100% {
    transform: translate3d(0, 0, 0);
  }

  33%      {
    transform: translate3d(var(--drift-x, 6px), calc(var(--float-y, -8px) * 0.6), 0);
  }

  66%      {
    transform: translate3d(calc(var(--drift-x, 6px) * -0.7), var(--float-y, -8px), 0);
  }
}

@keyframes fx-pulse {
  0%, 100% {
    opacity: var(--pulse-min, 0.55);
  }

  50%      {
    opacity: var(--pulse-max, 1);
  }
}

@keyframes fx-spin {
  from {
    transform: rotate(0deg);
  }

  to   {
    transform: rotate(360deg);
  }
}

.fx-float {
  animation: fx-float var(--dur, 6s) ease-in-out infinite;
  animation-delay: var(--delay, 0s);
}

.fx-drift {
  animation: fx-drift var(--dur, 10s) ease-in-out infinite;
  animation-delay: var(--delay, 0s);
}

.fx-pulse {
  animation: fx-pulse var(--dur, 8s) ease-in-out infinite;
  animation-delay: var(--delay, 0s);
}

.fx-spin {
  animation: fx-spin var(--dur, 40s) linear infinite;
}

/* Float only starts once the element has revealed, so the two never fight */

.fx-float, .fx-drift {
  animation-play-state: paused;
}

.is-visible .fx-float,
.is-visible .fx-drift,
.is-loaded .fx-float,
.is-loaded .fx-drift,
.fx-float.fx-run,
.fx-drift.fx-run {
  animation-play-state: running;
}

/* Nested float wrapper: entrance on the outer element, float on the inner */

.float-host {
  animation: fx-float var(--dur, 6s) ease-in-out infinite;
  animation-delay: var(--delay, 1.2s);
}

/* ==========================================================================
   8/12/13. MARQUEE
   The track holds two identical copies; translating by exactly -50% loops
   seamlessly. Pure CSS transform — no timers.
   ========================================================================== */

@keyframes marquee-x {
  from {
    transform: translate3d(0, 0, 0);
  }

  to   {
    transform: translate3d(-50%, 0, 0);
  }
}

@keyframes marquee-x-rev {
  from {
    transform: translate3d(-50%, 0, 0);
  }

  to   {
    transform: translate3d(0, 0, 0);
  }
}

.marquee {
  position: relative;
  display: flex;
  width: 100%;
  overflow: hidden;
}

/* One track holding exactly two identical groups; -50% lands the second
   group precisely where the first started, so the loop has no seam. */

.marquee__track {
  display: flex;
  width: -moz-max-content;
  width: max-content;
  align-items: stretch;
  animation: marquee-x var(--speed, 40s) linear infinite;
  will-change: transform;
}

.marquee__group {
  display: flex;
  flex-shrink: 0;
  align-items: stretch;
  gap: var(--gap, 40px);
  padding-right: var(--gap, 40px);
}

.marquee--reverse .marquee__track {
  animation-name: marquee-x-rev;
}

.marquee--pause-hover:hover .marquee__track,
.marquee__track:focus-within {
  animation-play-state: paused;
}

/* Edge fade */

.marquee--fade {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

/* The logo strip's own spacing. It used the py-[30px] utility, which put the
   same 30 above and below; the badge underneath the hero already carries the
   air above, so the top 30 was doubling it. A named class rather than editing
   that utility: a .py-[30px] that does not set 30 top and bottom is a trap for
   whoever uses it next, and there is no build step here to mint pt-0 or
   pb-[30px], so those would silently do nothing in the markup. */

.clients-sec {
  padding-top: 0;
  padding-bottom: 30px;
}

/* ==========================================================================
   14. PRICING TOGGLE
   ========================================================================== */

.toggle-track {
  position: relative;
  display: flex;
  height: 34px;
  width: 62px;
  flex-shrink: 0;
  cursor: pointer;
  align-items: center;
  border-radius: 100px;
  --tw-bg-opacity: 1;
  background-color: rgb(237 241 244 / var(--tw-bg-opacity, 1));
  padding: 3px;
  box-shadow: inset 0 0 0 1px rgba(221, 229, 237, 0.9);
  transition: background-color 320ms var(--ease-soft);
}

.toggle-knob {
  display: block;
  height: 28px;
  width: 28px;
  border-radius: 9999px;
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
  box-shadow: 0 1px 2px rgba(29, 29, 29, 0.18), 0 2px 6px rgba(29, 29, 29, 0.1);
  transform: translateX(0);
  transition: transform 420ms var(--ease-smooth);
}

.is-yearly .toggle-track {
  background-color: #1D1D1D;
}

.is-yearly .toggle-knob {
  transform: translateX(28px);
}

/* Price digits swap without a layout jump */

.price-swap {
  position: relative;
  display: inline-grid;
}

.price-swap > span {
  grid-area: 1 / 1;
  transition:
    opacity 300ms var(--ease-soft),
    transform 420ms var(--ease-smooth),
    filter 300ms var(--ease-soft);
}

.price-swap > .price-out {
  opacity: 0;
  transform: translateY(-14px);
  filter: blur(3px);
  pointer-events: none;
}

.price-swap > .price-in {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}

/* ==========================================================================
   10. HOW IT WORKS — step tabs
   ========================================================================== */

.step-tab {
  position: relative;
  z-index: 10;
  border-radius: 100px;
  padding-left: 18px;
  padding-right: 18px;
  padding-top: 9px;
  padding-bottom: 9px;
  font-size: 14px;
  line-height: 1.3;
  font-weight: 500;
  --tw-text-opacity: 1;
  color: rgb(77 88 95 / var(--tw-text-opacity, 1));
  transition: color 320ms var(--ease-soft);
}

.step-tab.is-active {
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}

.step-indicator {
  position: absolute;
  left: 0px;
  top: 0px;
  border-radius: 100px;
  --tw-bg-opacity: 1;
  background-color: rgb(29 29 29 / var(--tw-bg-opacity, 1));
  transition: transform 520ms var(--ease-smooth), width 520ms var(--ease-smooth);
  will-change: transform, width;
}

.step-panel {
  pointer-events: none;
  position: absolute;
  inset: 0px;
  opacity: 0;
  transform: translateY(16px) scale(0.985);
  transition: opacity 420ms var(--ease-soft), transform 620ms var(--ease-smooth);
}

.step-panel.is-active {
  pointer-events: auto;
  opacity: 1;
  transform: translateY(0) scale(1);
}

/* ==========================================================================
   FAQ ACCORDION
   ========================================================================== */

.faq-item {
  overflow: hidden;
  border-radius: 18px;
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
  box-shadow: inset 0 0 0 1px #DDE5ED;
  transition: background-color 380ms var(--ease-soft), box-shadow 380ms var(--ease-soft);
}

.faq-item.is-open {
  --tw-bg-opacity: 1;
  background-color: rgb(237 241 244 / var(--tw-bg-opacity, 1));
  box-shadow: inset 0 0 0 1px transparent;
}

.faq-body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 460ms var(--ease-smooth);
}

.faq-item.is-open .faq-body {
  grid-template-rows: 1fr;
}

.faq-body > div {
  overflow: hidden;
}

.faq-body p {
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 320ms var(--ease-soft) 80ms, transform 380ms var(--ease-smooth) 80ms;
}

.faq-item.is-open .faq-body p {
  opacity: 1;
  transform: translateY(0);
}

.faq-sign span {
  position: absolute;
  display: block;
  --tw-bg-opacity: 1;
  background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
  transition: transform 420ms var(--ease-smooth), opacity 260ms var(--ease-soft);
}

.faq-item.is-open .faq-sign span:last-child {
  transform: rotate(90deg) scaleX(0);
  opacity: 0;
}

/* ==========================================================================
   2. COMPARISON — scroll-driven Before → After
   ========================================================================== */

.cmp-face {
  transition: opacity 520ms var(--ease-soft), transform 700ms var(--ease-smooth);
  will-change: opacity, transform;
}

.cmp-face[data-state='out'] {
  opacity: 0;
  transform: scale(0.985);
  pointer-events: none;
}

.cmp-face[data-state='in'] {
  opacity: 1;
  transform: scale(1);
}

.cmp-dial {
  transition: transform 700ms var(--ease-smooth);
  will-change: transform;
}

.cmp-tab {
  transition: color 460ms var(--ease-soft), opacity 460ms var(--ease-soft);
}

/* Below the sticky breakpoint the two faces simply stack — no crossfade,
   so both states stay readable without any scroll choreography. */

@media (max-width: 1023px) {
  .cmp-stack .cmp-face {
    position: relative !important;
    inset: auto !important;
    opacity: 1 !important;
    transform: none !important;
    pointer-events: auto !important;
  }

  .cmp-stack .cmp-face + .cmp-face {
    margin-top: 24px;
  }
}

/* ==========================================================================
   17. BACKGROUND / AMBIENT
   ========================================================================== */

@keyframes bg-breathe {
  0%, 100% {
    transform: translate3d(0, 0, 0) scale(1);
  }

  50%      {
    transform: translate3d(0, -18px, 0) scale(1.04);
  }
}

.bg-breathe {
  animation: bg-breathe var(--dur, 18s) ease-in-out infinite;
}

.grain::after {
  content: '';
  pointer-events: none;
  position: absolute;
  inset: 0px;
  background-image: radial-gradient(rgba(29, 29, 29, 0.045) 1px, transparent 1px);
  background-size: 3px 3px;
  opacity: 0.6;
}

/* Scrollbar polish */

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: #dde5ed;
  border-radius: 8px;
}

::-webkit-scrollbar-thumb:hover {
  background: #c3cfdb;
}

/* ==========================================================================
   21. REDUCED MOTION
   ========================================================================== */

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

  .load-in,
  .reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .fx-float,
  .fx-drift,
  .fx-pulse,
  .fx-spin,
  .float-host,
  .bg-breathe,
  .marquee__track {
    animation: none !important;
  }

  /* Keep the marquee readable when its animation is off */

  .marquee {
    overflow-x: auto;
  }

  .btn,
  .card,
  .card-hover .card-art,
  .step-panel,
  .cmp-face,
  .cmp-dial,
  .st-stage,
  .st-w__in,
  .st-tint,
  .statement__key {
    transition-duration: 1ms !important;
  }

  /* No pin, so no stages to step through — the sentence carries it alone. */

  .statement__track {
    height: auto !important;
  }

  .statement__panel {
    position: static !important;
    height: auto !important;
    padding: 180px 0 !important;
  }

  .statement__stages {
    display: none !important;
  }

  .btn:hover,
  .card-hover.card-hover:hover,
  .card-hover:hover .card-art {
    transform: none !important;
  }

  /* Parallax elements are reset by JS as well */

  [data-parallax],
  [data-scroll-scale] {
    transform: none !important;
  }
}

/* ==========================================================================
   PRODUCT SHOWCASE — six panels stepped through while the stage is pinned
   --------------------------------------------------------------------------
   Written as plain CSS rather than @apply so the block can live identically in
   input.css and style.css; nothing here needs a Tailwind recompile.

   Mobile first: the panels are an ordinary stacked list, image above copy. The
   pin is added at 1024 px, where `.showcase__track` grows to one viewport per
   panel and `.showcase__stage` sticks below the 72 px navbar — exactly the
   arrangement the statement slab uses. The surplus track height is the travel
   showcase.js scrubs, so the crossfade is driven by real scroll position and
   never by a timer.
   ========================================================================== */

.showcase {
  position: relative;
  isolation: isolate;
  /* No `overflow` here on purpose: any value other than `visible` turns this
     into a scroll container, and `position: sticky` on `.showcase__stage`
     would silently stop pinning. The stage clips its own overflow instead. */
  /* Neutral near-black rather than the old navy: with a colour cast in the
     ground, six of the seven step accents read as variations on blue. */
  background-color: #08090D;
  padding-top: 70px;
  padding-bottom: 70px;
}

/* Depth under the washes — pure luminance, no hue of its own. */

.showcase::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -3;
  pointer-events: none;
  background: linear-gradient(180deg, #12141B 0%, #08090D 55%, #06070A 100%);
}

/* ------------------------------------------------------------------
   Per-step wash
   One layer per panel, each carrying that step's --tint. Stacked in the
   same box and cross-dissolved by showcase.js against the panel timeline,
   because a single layer changing colour cannot be transitioned — custom
   properties do not animate.
   ------------------------------------------------------------------ */

.showcase__tints {
  position: absolute;
  inset: 0;
  /* Behind the panels and the frame glow (-1) but above the section's
     luminance gradient (-3). `.showcase` is the stacking context — the stage
     is only a positioning one — so a negative index here still resolves
     against the section while the stage's overflow does the clipping. */
  z-index: -2;
  pointer-events: none;
}

/* Below the pin, the wash has to reach the section's own edges.

   inset: 0 is measured against .showcase__stage, and under 1024 the section
   carries 70px of padding the stage starts inside — so the top and bottom 70
   were bare #08090D and the colour began partway down, which read as a black
   band with the blue starting under it. At 1024 and up the section's padding
   is 0 and the stage already fills it, which is why this only shows on a
   phone.

   -70 is exactly that padding, so the wash lands flush on the section box and
   no further. Not applied under reduced motion: that block makes the stage
   position: static, so these resolve against .showcase instead and inset: 0 is
   already the whole section — pulling another 70 out would bleed the colour
   into the sections either side. */

@media (max-width: 1023px) and (prefers-reduced-motion: no-preference) {
  .showcase__tints {
    top: -70px;
    bottom: -70px;
  }
}

.sc-tint {
  position: absolute;
  inset: 0;
  opacity: 0;
  background:
    radial-gradient(115% 75% at 10% 6%, rgba(var(--tint), 0.40), rgba(var(--tint), 0) 58%),
    radial-gradient(95% 65% at 92% 92%, rgba(var(--tint), 0.22), rgba(var(--tint), 0) 60%),
    radial-gradient(70% 50% at 50% 50%, rgba(var(--tint), 0.10), rgba(var(--tint), 0) 70%);
  /* Longer than the panel handover and with no delay, so the ground has begun
     to move before the copy does and is still settling after it lands. Two
     washes over one another simply read as a third colour, so unlike the
     panels there is nothing here to keep apart — this one genuinely is a
     crossfade. */
  transition: opacity 900ms var(--ease-smooth);
}

/* Step 01 is the pre-script resting state, and the only one shown when the
   pin is off — below 1024 px or under prefers-reduced-motion.

   Scoped to `:not(.is-stepping)` because an attribute cannot be taken off the
   element the way a class can: once showcase.js is driving, this rule has to
   stop applying or tint 01 would never fade out. */

.showcase:not(.is-stepping) .sc-tint[data-sc-tint='0'] {
  opacity: 1;
}

.sc-tint.is-on {
  opacity: 1;
}

.showcase__track {
  position: relative;
}

.showcase__stage {
  position: relative;
}

.showcase__panels {
  display: grid;
  gap: 80px;
}

/* ------------------------------------------------------------------
   One panel
   ------------------------------------------------------------------ */

.sc-panel {
  display: grid;
  gap: 30px;
  align-items: center;
}

/* Media ---------------------------------------------------------- */

.sc-panel__media {
  position: relative;
  display: flex;
  justify-content: center;
}

/* Glow pooled under the frame; blurred and clipped well inside the box so it
   never reads as a hard edge. */

.sc-panel__media::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 10% 6%;
  border-radius: 50%;
  background: radial-gradient(60% 60% at 50% 55%, rgba(var(--tint, 59, 130, 246), 0.46), rgba(var(--tint, 59, 130, 246), 0) 70%);
  filter: blur(44px);
}

.sc-panel__frame {
  position: relative;
  width: 100%;
  /* 1324 × 1189 artwork — the vh cap keeps the frame inside a short viewport
     instead of pushing the copy off the bottom of the pinned stage. */
  max-width: min(560px, 69vh);
  overflow: hidden;
  /* The artwork no longer carries its own navy plate, so this radius does all
     the rounding — and clips the rounded-corner remnants a rectangular crop
     left behind on the two photographic panels. The fill is the artwork's own
     top-left gradient stop, so a subpixel seam at the edge is invisible
     rather than a dark hairline. */
  border-radius: 30px;
  background-color: #e4eaf9;
  box-shadow:
    0 34px 80px -30px rgba(0, 0, 0, 0.75),
    0 2px 10px rgba(0, 0, 0, 0.35);
}

.sc-panel__img {
  display: block;
  width: 100%;
  height: auto;
}

/* Sheen ---------------------------------------------------------------
   A band of light drawn diagonally across the frame and moved by the scroll,
   so the plate behind each panel's UI is lit rather than flat.

   OVER, NOT UNDER
   Every panel's artwork paints its own opaque plate over the full frame, so
   there is nothing behind it to light — the frame's own background-color is
   already invisible for that reason. This goes on top instead, which is only
   tolerable because of the blend below.

   SOFT-LIGHT, NOT A WHITE WASH
   At plain opacity a white gradient over a UI screenshot fogs the text under
   it. soft-light leaves anything already dark alone and lifts only what is
   light, which on these near-white plates is the plate itself — the effect
   lands where it was aimed and the type stays as legible as it was.

   The box is oversized and offset so the band's soft ends stay outside the
   frame through the whole travel: sized to the frame, the taper would drift
   into view and read as a rectangle passing over the artwork. The frame's
   `overflow: hidden` does the trimming.

   The resting position is the middle of the sweep, so with no JS — reduced
   motion, narrow screens, GSAP blocked — it is a static highlight rather than
   a band parked off one edge. */

.sc-panel__sheen {
  position: absolute;
  /* Twice the frame each way, centred on it, so translating by half its own
     size never brings an end into shot. */
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  pointer-events: none;
  mix-blend-mode: soft-light;
  background: linear-gradient(
    115deg,
    rgba(255, 255, 255, 0) 38%,
    rgba(255, 255, 255, 0.85) 50%,
    rgba(255, 255, 255, 0) 62%
  );
  will-change: transform;
}

/* Copy ----------------------------------------------------------- */

.sc-panel__body {
  max-width: 480px;
}

.sc-panel__num {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: #7cb0fc;
}

.sc-panel__num::after {
  content: '';
  width: 44px;
  height: 1.5px;
  background-color: rgba(124, 176, 252, 0.42);
}

.sc-panel__title {
  margin-top: 18px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(34px, 5vw, 56px);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -1px;
  color: #ffffff;
}

/* The clamp bottoms out at 34, which is the size the panel wears on a phone —
   nearly as large as it is on a laptop, because 5vw of a phone is nothing. At
   that size the product name is the loudest thing on a screen that also has to
   carry the artwork, the paragraph and the button. Held to 20 below 768, with
   the tracking relaxed: -1px is drawn for a 56px line and pinches letters
   together at a fifth of it. */

@media (max-width: 767px) {
  .sc-panel__title {
    font-size: 20px;
    letter-spacing: -0.3px;
  }
}

.sc-panel__text {
  margin-top: 20px;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.55;
  color: rgba(226, 235, 250, 0.74);
}

.sc-panel__cta {
  margin-top: 28px;
}

/* The shared .btn-dark is #1d1d1d on a near-black ground — invisible. Scoped
   to this section it becomes the inverse: white pill, dark icon disc, and the
   arrow artwork (a fixed #1D1D1D fill) inverted so it reads on that disc. */

.showcase .btn-dark {
  background-color: #ffffff;
  background-image: linear-gradient(180deg, #ffffff 0%, #e8eefb 100%);
  color: #0b1220;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 10px 28px -12px rgba(0, 0, 0, 0.75);
}

.showcase .btn-dark .btn__icon {
  background-color: #0b1220;
}

.showcase .btn-dark .btn__icon img {
  filter: invert(1);
}

.showcase .btn-dark:hover {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    0 18px 38px -14px rgba(0, 0, 0, 0.8);
}

/* ------------------------------------------------------------------
   THE PIN — desktop only, matching the statement slab's 1024 px threshold
   and its 72 px navbar offset.

   `--sc-step` is how far you scroll to advance one panel, and it is the one
   number to touch to change the pacing: lower feels snappier, higher gives
   the artwork longer on screen. The track is sized so the surplus over the
   sticky stage works out to (panels - 1 + --sc-tail) x --sc-step, which is
   the travel showcase.js divides into steps — so they stay evenly spaced
   whatever the value.

   Nothing is scrubbed against that travel: it decides which step is current
   and no more. The handover itself is a fixed CSS transition, further down
   under THE HANDOVER.
   ------------------------------------------------------------------ */

@media (min-width: 1024px) {
  .showcase {
    padding-top: 0;
    padding-bottom: 0;
  }

  .showcase__track {
    /* One step per two scroll gestures. At 50vh a step was gone in a single
       flick — the stage pinned and the next panel was already lifting, so the
       first one was never really seen. */
    --sc-step: 100vh;
    /* Extra travel past the last step, in steps, so the final panel is not
       thrown away the moment it arrives.

       Every other panel holds the screen for a full step: it becomes current
       half a step before its own mark and stays current until half a step
       after. The last one had no "after" — the track ended exactly where it
       became current plus half a step, so it landed and the stage immediately
       unstuck. It was on screen settled for a fraction of a gesture, which is
       why the sequence appeared to skip straight from 06 to the next section.

       This buys it the missing half back and a little over, so it holds for
       about as long as the others before the page moves on. It is dead travel
       — no step changes in it — which is exactly the point.

       showcase.js reads this value to keep its step arithmetic in agreement
       with the height below; it is the one number to change to lengthen the
       hold. */
    --sc-tail: 0.75;
    height: calc(
      (var(--sc-count, 6) - 1 + var(--sc-tail)) * var(--sc-step) + 100vh - var(--nav-h)
    );
  }

  .showcase__stage {
    position: sticky;
    top: var(--nav-h);
    display: flex;
    align-items: center;
    height: calc(100vh - var(--nav-h));
    overflow: hidden;
  }

  .showcase__stage > .shell {
    width: 100%;
  }

  /* Every panel occupies the same cell, so the stage never resizes between
     steps and the frame stays put while the artwork swaps. */

  .showcase__panels {
    grid-template-areas: 'stack';
    gap: 0;
  }

  .sc-panel {
    grid-area: stack;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 80px;
    /* Waiting, below its final position. */
    opacity: 0;
    visibility: hidden;
    transform: translate3d(0, 20px, 0) scale(0.98);
    transition:
      opacity 420ms var(--ease-smooth),
      transform 700ms var(--ease-smooth),
      visibility 0s linear 700ms;
    will-change: opacity, transform;
  }

  /* Gone: same fade, but lifted up and out rather than dropped back down.
     Only the transform differs from the waiting state, so a panel scrolled
     back to reverses into place along the path it left by. */

  .sc-panel.is-past {
    transform: translate3d(0, -20px, 0) scale(0.98);
  }

  /* Current. `is-active` is the pre-JS state — the first panel on show before
     showcase.js runs, and if it never does. */

  .sc-panel.is-active,
  .sc-panel.is-in {
    opacity: 1;
    visibility: visible;
    transform: translate3d(0, 0, 0) scale(1);
    transition:
      opacity 720ms var(--ease-smooth) 200ms,
      transform 820ms var(--ease-smooth) 200ms,
      visibility 0s;
  }

  /* The sheen crosses the plate as the step changes, on the same three
     positions and the same curve — light moving with the panel rather than a
     second effect with its own timing. Slightly longer than the panel so it
     is still travelling as everything else settles. */

  .sc-panel__sheen {
    transform: translate3d(-26%, -12%, 0);
    transition: transform 900ms var(--ease-smooth) 200ms;
  }

  .sc-panel.is-in .sc-panel__sheen {
    transform: translate3d(0, 0, 0);
  }

  .sc-panel.is-past .sc-panel__sheen {
    transform: translate3d(26%, 12%, 0);
  }

  .sc-panel__body {
    max-width: 520px;
  }

  .sc-panel__text {
    font-size: 18px;
  }

  .sc-panel__cta {
    margin-top: 34px;
  }
}

@media (min-width: 1280px) {
  .sc-panel {
    gap: 100px;
  }

  .sc-panel__frame {
    max-width: min(600px, 70vh);
  }
}

/* ------------------------------------------------------------------
   No pin, no stepping — every panel is simply on the page in order.
   ------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .showcase {
    padding-top: 70px !important;
    padding-bottom: 70px !important;
  }

  .showcase__track {
    height: auto !important;
  }

  .showcase__stage {
    position: static !important;
    height: auto !important;
    display: block !important;
    overflow: visible !important;
  }

  .showcase__panels {
    grid-template-areas: none !important;
    gap: 80px !important;
  }

  .sc-panel {
    grid-area: auto !important;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    opacity: 1 !important;
    visibility: visible !important;
    transform: none !important;
    will-change: auto !important;
  }

  .sc-panel__media,
  .sc-panel__body {
    transform: none !important;
  }
}

/* ==========================================================================
   TESTIMONIAL MONOGRAM AVATAR
   Stands in for a customer photo. Sized and shaped to match the 50 px round
   image it replaces, so a row that supplies `photo` swaps in without moving
   anything else in the card.
   ========================================================================== */

.t-avatar {
  display: grid;
  flex-shrink: 0;
  place-items: center;
  width: 50px;
  height: 50px;
  border-radius: 9999px;
  background-image: linear-gradient(140deg, var(--t-from, #6d46e8), var(--t-to, #4b27c9));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.24),
    0 1px 2px rgba(29, 29, 29, 0.12);
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1;
  color: #fff;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}

/* ==========================================================================
   IMPACT — photo tiles with a stat burned into the corner
   Plain CSS with its own class names, so no Tailwind recompile is needed.
   ========================================================================== */

.impact {
  position: relative;
  isolation: isolate;
  padding: 70px 0;
  background-color: #fff;
}

/* Pastel wash behind the row, cool on the left warming to the brand blue. */

.impact::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(70% 60% at 8% 0%, rgba(96, 165, 250, 0.16), rgba(96, 165, 250, 0) 62%),
    radial-gradient(70% 60% at 92% 4%, rgba(37, 99, 235, 0.10), rgba(37, 99, 235, 0) 60%);
}

.impact__title {
  max-width: 900px;
  margin: 0 auto;
  text-align: center;
}

/* The accent half of the headline. background-clip:text needs a transparent
   fill; the colour above it is the fallback for anything that cannot clip. */

.impact__accent {
  color: #2563eb;
  background-image: linear-gradient(95deg, #34d399 0%, #38bdf8 42%, #2563eb 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.impact__grid {
  display: grid;
  gap: 22px;
  margin-top: 48px;
  grid-template-columns: minmax(0, 1fr);
}

/* ------------------------------------------------------------------
   One tile
   ------------------------------------------------------------------ */

.impact-card {
  position: relative;
  overflow: hidden;
  border-radius: 26px;
  /* Fixed ratio so the row stays even whatever crop the photo arrives in. */
  aspect-ratio: 4 / 5;
  background-color: #0f1729;
  box-shadow: 0 18px 44px -22px rgba(10, 20, 36, 0.42);
  transition:
    transform 500ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 500ms cubic-bezier(0.22, 1, 0.36, 1);
}

.impact-card__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  /* Bias the crop upward. The card is 4:5; a taller portrait gets trimmed top
     and bottom, and centring that trim eats into faces near the top of frame.
     40% keeps heads clear and takes the difference out of the floor. */
  -o-object-position: 50% 40%;
     object-position: 50% 40%;
  /* Held slightly oversized until the card reveals, so the tile settles into
     place instead of simply appearing. Also covers the scrim's edges while the
     card is still translating in. */
  transform: scale(1.12);
  transition: transform 1200ms cubic-bezier(0.22, 1, 0.36, 1);
}

.impact-card.is-visible .impact-card__img {
  transform: scale(1);
}

/* The three lines rise in sequence under the counting number. Delays are
   relative to the card's own reveal, which the stagger has already offset. */

.impact-card__num,
.impact-card__label,
.impact-card__text {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 700ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
}

.impact-card.is-visible .impact-card__num,
.impact-card.is-visible .impact-card__label,
.impact-card.is-visible .impact-card__text {
  opacity: 1;
  transform: none;
}

.impact-card.is-visible .impact-card__num {
  transition-delay: 180ms;
}

.impact-card.is-visible .impact-card__label {
  transition-delay: 300ms;
}

.impact-card.is-visible .impact-card__text {
  transition-delay: 400ms;
}

/* Everything readable sits on this, never on bare photography. */

.impact-card__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(9, 14, 28, 0) 26%,
    rgba(9, 14, 28, 0.42) 56%,
    rgba(9, 14, 28, 0.88) 100%
  );
}

.impact-card__body {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  padding: 26px;
  color: #fff;
}

.impact-card__num {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(40px, 5.2vw, 58px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -1.6px;
}

.impact-card__label {
  margin-top: 12px;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
}

.impact-card__text {
  margin-top: 8px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.74);
}

@media (hover: hover) {
  .impact-card:hover {
    transform: translateY(-6px);
    box-shadow: 0 30px 60px -24px rgba(10, 20, 36, 0.5);
  }

  .impact-card:hover .impact-card__img {
    transform: scale(1.05);
  }
}

@media (min-width: 768px) {
  .impact {
    padding: 100px 0;
  }

  .impact__grid {
    gap: 26px;
    margin-top: 60px;
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .impact-card__body {
    padding: 30px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .impact-card,
  .impact-card__img,
  .impact-card__num,
  .impact-card__label,
  .impact-card__text {
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
  }

  /* Nothing is held back, so nothing needs releasing. */

  .impact-card__img {
    transform: none !important;
  }

  .impact-card__num,
  .impact-card__label,
  .impact-card__text {
    opacity: 1 !important;
    transform: none !important;
  }

  .impact-card:hover {
    transform: none !important;
  }

  .impact-card:hover .impact-card__img {
    transform: none !important;
  }
}

/* ==========================================================================
   HERO FOOT — the tail under the product shot, and the fade that dissolves
   the sky backdrop into the white page.

   These are one decision, not two. The fade is anchored to the section's
   bottom edge, so whenever the tail is shorter than the fade is tall the
   gradient climbs over the product shot and washes its lower edge out. Keep
   `padding-bottom` >= the fade height and that cannot happen.

   The tail used to be `min-height: 175vh`, which existed to position the
   meadow layer. That layer is hidden, so all the height did was leave ~280 px
   of empty white between the shot and the logo strip.
   ========================================================================== */

#hero .hero__stage {
  padding-bottom: 130px;
}

/* Wherever the scroll-grow actually runs — desktop, motion allowed; see the
   collect() guard in animations.js — the tail the reader SEES is assembled
   from three pieces rather than one, and they add up to the same 130 px:

     51 px  the shot stops growing at 0.92, so the bottom of its 643 px layout
            box is never filled
     65 px  the counter-translate that lifts it, stopping the growth reading
            as a stall
     14 px  this padding, which is simply the remainder

   Keep the SUM at 130 and the fade below still clears the artwork. Change the
   end scale in sections/hero.php and the first number moves, so this one has
   to move with it. Outside this query no transform applies, the first two
   pieces are zero, and the full 130 px is the real tail. */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  #hero .hero__stage {
    padding-bottom: 14px;
  }
}

#hero .bg-fade-bottom {
  height: 120px;
}

/* ==========================================================================
   NAV "BOOK A DEMO" — white pill
   Metrics match .btn-brand beside it so the pair reads as one control group.

   The bar is transparent over the hero and ~90% white once scrolled, so a
   plain white fill would disappear in the scrolled state. The hairline border
   is what keeps the edge readable there; the shadow does the work over the
   hero image.
   ========================================================================== */

.btn-nav-white {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-shrink: 0;
  border-radius: 100px;
  /* 12/25 not 13/26: the 1px border adds 2px to the box, and .btn-brand next
     to it is borderless at 13/26. Absorbing the border into the padding keeps
     the two pills exactly the same size. */
  padding: 12px 25px;
  font-size: 15px;
  line-height: 1.3;
  font-weight: 600;
  color: #1d1d1d;
  background-color: #ffffff;
  border: 1px solid rgba(29, 29, 29, 0.10);
  box-shadow:
    0 1px 2px rgba(29, 29, 29, 0.06),
    0 6px 18px -10px rgba(29, 29, 29, 0.28);
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  transition:
    transform 300ms var(--ease-smooth),
    box-shadow 300ms var(--ease-smooth),
    background-color 300ms var(--ease-soft),
    border-color 300ms var(--ease-soft);
}

.btn-nav-white:hover {
  transform: translateY(-2px);
  border-color: rgba(29, 29, 29, 0.16);
  box-shadow:
    0 1px 2px rgba(29, 29, 29, 0.08),
    0 14px 26px -12px rgba(29, 29, 29, 0.34);
}

.btn-nav-white:active {
  transform: translateY(-1px) scale(0.98);
  transition-duration: 90ms;
}

@media (prefers-reduced-motion: reduce) {
  .btn-nav-white {
    transition-duration: 1ms;
  }

  .btn-nav-white:hover,
  .btn-nav-white:active {
    transform: none;
  }
}

/* ==========================================================================
   HERO SHOT — LIVE OVERLAY
   --------------------------------------------------------------------------
   The hero product shot is flat artwork (hero-dashboard.webp, 2000 × 1214), so
   anything that has to move is drawn in HTML on top of it rather than baked
   into the pixels.

   Geometry is a percentage of the image box and type is sized in `cqw`, so the
   overlay rides the shot's 0.64 → 1 scroll-grow and its float with no JS
   syncing at all — both of those are transforms on ancestors, and a
   percentage-positioned child of a transformed box just comes along.

   Coordinates were measured off the artwork itself, in image pixels:
     Clock In card    x 423 → 917    y 317 → 800
     content gutter   x 452 → 885    (433 px wide)
     free band        y 377 → 496    (under the header, over the 06:06 ring)
   1 cqw = 1 % of the shot = 20 image px, which is how the type sizes below
   were derived — the card's own small text is ~21 image px, i.e. ~1.05 cqw.

   Plain CSS rather than @apply, so the block is identical in input.css and
   style.css and needs no Tailwind recompile (same reason as the showcase).
   ========================================================================== */

.shot-fx {
  position: absolute;
  inset: 0;
  /* Above the dashboard, which is now itself above the cast figures. Without
     an explicit index the shot-img's z-index: 1 would cover this overlay. */
  z-index: 2;
  container-type: inline-size;
  pointer-events: none;
}

/* left 452/2000, width 433/2000, top 393/1214 — the block is ~89 image px
   tall, so this sits it in the 119 px band with the header 28 px above and
   the ring 16 px below. */

.shot-bar {
  position: absolute;
  left: 22.6%;
  top: 32.4%;
  width: 21.65%;
  /* The artwork's own dark text, sampled off "06:06" and "Clocked in" in the
     same card: #20232B, a dark blue-grey. The previous #0e0c18 was both darker
     and purple-tinted, so the overlay's "64%" sat heavier than the real
     figures either side of it. Scoped here rather than changed globally —
     the showcase panels reuse that value against different artwork. */
  color: #20232B;
  line-height: 1.25;
}

.shot-bar__row,
.shot-bar__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.shot-bar__label {
  font-size: 0.9cqw;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #8a8894;
}

.shot-bar__value {
  font-size: 1.2cqw;
  font-weight: 700;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

.shot-bar__track {
  position: relative;
  height: 0.7cqw;
  margin-top: 0.55cqw;
  overflow: hidden;
  border-radius: 100px;
  /* The artwork's ring track, re-sampled: #D9E3F8. The old value here was a
     lavender #efedfd, taken from a mis-located sample — there is no purple
     anywhere in hero-dashboard.webp. Its accents are a blue ring, a rose
     Clock Out button and a green status dot. */
  background: #D9E3F8;
}

/* Swept with scaleX, not width, to stay on the compositor like every other
   animation on the page. The right cap squashes by the scale factor, which at
   ~7 CSS px tall is not perceptible. */

.shot-bar__fill {
  position: absolute;
  inset: 0;
  display: block;
  border-radius: inherit;
  /* The artwork's ring arc, re-sampled around its true centre: a flat #628FED
     across the whole arc — the start and end of it differ by one step, so there
     is no gradient in the artwork to copy. The slight sweep here is the bar's
     own, kept narrow so its mean lands back on #628FED and it still reads as
     the same blue as the ring beside it.

     This was #9b7bff → #7458f3, labelled "the ring purple". The ring is not
     purple; the earlier sample was taken 18px off centre and picked up
     something else entirely. */
  background: linear-gradient(90deg, #6E97F0 0%, #5A88EA 100%);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 1600ms var(--ease-smooth) var(--fill-d, 1400ms);
}

.shot-bar.is-visible .shot-bar__fill {
  transform: scaleX(var(--p, 0.64));
}

/* A slow sheen so the bar still reads as live once it has settled. Held off
   until the sweep has landed (--fill-d + its duration), then mostly idle. */

.shot-bar__fill::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    100deg,
    transparent 20%,
    rgba(255, 255, 255, 0.55) 50%,
    transparent 80%
  );
  opacity: 0;
}

.shot-bar.is-visible .shot-bar__fill::after {
  animation: shot-sheen 6s var(--ease-smooth) 3100ms infinite;
}

@keyframes shot-sheen {
  0%        {
    opacity: 0;
    transform: translate3d(-70%, 0, 0);
  }

  8%        {
    opacity: 1;
  }

  30%, 100% {
    opacity: 0;
    transform: translate3d(120%, 0, 0);
  }
}

.shot-bar__foot {
  margin-top: 0.5cqw;
  font-size: 0.9cqw;
  font-weight: 500;
  color: #8a8894;
  font-variant-numeric: tabular-nums;
}

/* Below md the whole shot is small enough that the widget would be a smudge —
   and the screenshot's own type is already past reading size. */

@media (max-width: 767px) {
  .shot-fx {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .shot-bar__fill {
    transform: scaleX(var(--p, 0.64));
    transition: none;
  }

  .shot-bar.is-visible .shot-bar__fill::after {
    animation: none;
  }
}

/* --- the 06:06 dial ------------------------------------------------------
   Geometry in image pixels: centre (814, 571) → the 156 px box that holds the
   ring spans x 736 → 892, y 493 → 649. 736/2000 = 36.8 %, 493/1214 = 40.61 %,
   156/2000 = 7.8 %; the box is square, so the height comes off the aspect
   ratio rather than a second percentage basis.

   This is the one place on the page that animates something other than
   transform/opacity — stroke-dashoffset repaints. It is a single 83 px
   element moving once, which is a fair price for not having to re-cut the
   artwork. */

.shot-ring {
  position: absolute;
  left: 36.8%;
  top: 40.61%;
  width: 7.8%;
  height: auto;
  aspect-ratio: 1;
  /* The mask has to be on screen from the very first paint, so this element
     borrows .reveal only for its is-visible flag, not its fade. */
  opacity: 1;
  transition: none;
}

.shot-ring__mask,
.shot-ring__feather {
  fill: none;
  stroke-linecap: butt;
  stroke-dasharray: 100 100;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1800ms var(--ease-smooth) 1700ms;
}

/* The track band, re-sampled around the gap: a flat #D9E3F8. 15 wide in the
   artwork; the extra 0.6 swallows the arc's antialiased outer edge.

   This stroke's whole job is to be invisible — it hides the baked-in arc so the
   overlay can wipe it back on. At the old lavender #ebe9f7 it was not hiding
   anything, it was drawing a wrong-coloured band over a blue-grey track. */

.shot-ring__mask {
  stroke: #D9E3F8;
  stroke-width: 15.6;
}

/* r 55.3 → 59.9, where the arc bleeds inward past the track band. The real
   track lightens across exactly this ring (#DDE7FA at its inner edge against
   #D9E3F8 in the flat band), so this is the falloff, not an extra band of
   track. Re-sampled with the mask above; it carried the same lavender error. */

.shot-ring__feather {
  stroke: #DDE7FA;
  stroke-width: 4.6;
}

/* Retracted to nothing — what is left is the artwork's own arc. */

.shot-ring.is-visible .shot-ring__mask,
.shot-ring.is-visible .shot-ring__feather {
  stroke-dashoffset: 100;
}

@media (prefers-reduced-motion: reduce) {
  .shot-ring__mask,
  .shot-ring__feather {
    stroke-dashoffset: 100;
    transition: none;
  }
}

/* ==========================================================================
   AI SOURCING ILLUSTRATION
   --------------------------------------------------------------------------
   A rebuild of assets/images/ai-sourcing.jpg (980 × 875) as live markup, so
   each part can be animated on its own instead of the whole thing fading in
   as one picture. See sections/security.php and js/ai-sourcing.js.

   Sizing: the root keeps the image's aspect ratio and max-width, so the card
   around it never changes size. Geometry is a percentage of that box and type
   is in `cqw` off the root container, which means the illustration scales as
   a single piece at any width — exactly how the screenshot behaved. 1 cqw =
   1 % of the box = 9.8 px in the reference artwork, which is how every size
   below was derived.

   Colours and coordinates are sampled from the artwork:
     heading card   x 140→841  y 136→340
     connector      x 490      y 340→419
     plus node      36 px      centred on (490, 437)
     panel          x 124→853  y 443→770,  padding 37
     rules          y 561 and y 674
   Plain CSS rather than @apply, so the block is identical in input.css and
   style.css and needs no Tailwind recompile.
   ========================================================================== */

/* The stage every rebuilt panel shares: the tinted ground, the type basis and
   the container the `cqw` sizing is measured against. Aspect ratio stays with
   each component, since each matches its own artwork. */

.liveui {
  container-type: inline-size;
  position: relative;
  /* A definite width, not width:100%. In the security card .card-art sits in a
     place-items-center grid, so it is content-sized: the <img> gave it a width
     via its intrinsic pixels clamped by max-w-[508px], and a plain div has
     none — width:100% against a content-sized parent collapses the box. */
  width: 508px;
  max-width: 100%;
  /* No rounding of its own: the artwork it replaces was a square bitmap, and
     each host does its own clipping — the showcase frame's 30 px radius, the
     security card's padding. */
  overflow: hidden;
  background:
    radial-gradient(115% 75% at 88% 0%, rgba(150, 188, 250, 0.55), transparent 62%),
    linear-gradient(172deg, #c1d0ee 0%, #ccd8ef 34%, #d9dfef 68%, #e3e7f2 100%);
  font-family: Inter, system-ui, -apple-system, sans-serif;
  line-height: 1.25;
}

.ais {
  aspect-ratio: 980 / 875;
}

/* In the showcase the frame has a definite width, so the illustration fills it
   the way the <img> did. The default keeps a definite 508 px for the security
   card, whose place-items-center grid hands down no width to inherit. */

.liveui--fill {
  width: 100%;
  max-width: none;
}

/* ---- 1. heading card --------------------------------------------------- */

.ais__card {
  position: absolute;
  left: 14.29%;
  top: 15.54%;
  width: 71.53%;
  height: 23.31%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.9cqw;
  border-radius: 2.86cqw;
  background: #f9fafc;
  box-shadow:
    0 0.2cqw 0.6cqw rgba(43, 68, 120, 0.05),
    0 1.6cqw 3.4cqw -1cqw rgba(43, 68, 120, 0.16);
}

.ais__title {
  font-size: 3.98cqw;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: #3569d9;
}

.ais__sub {
  font-size: 1.94cqw;
  font-weight: 400;
  color: #5c5f66;
}

/* ---- 4. dotted connector ----------------------------------------------- */

.ais__link {
  position: absolute;
  left: 50%;
  top: 38.86%;
  height: 9.03%;
  width: 0.21cqw;
  margin-left: -0.105cqw;
  /* drawn as a gradient rather than a dashed border so the dash and the gap
     are both measurable, and both scale with the box */
  background-image: repeating-linear-gradient(
    to bottom,
    #8ba4d4 0 0.62cqw,
    transparent 0.62cqw 1.28cqw
  );
}

/* ---- 5. plus node ------------------------------------------------------ */

.ais__plus {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 3.78cqw;
  height: 3.78cqw;
  margin: -1.89cqw 0 0 -1.89cqw;
  z-index: 2;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #0b2c5f;
  color: #fff;
  box-shadow: 0 0.5cqw 1.2cqw -0.3cqw rgba(11, 44, 95, 0.45);
}

.ais__plus svg {
  width: 55%;
  height: 55%;
}

/* ---- 6. search panel --------------------------------------------------- */

.ais__panel {
  position: absolute;
  left: 12.65%;
  top: 50.63%;
  width: 74.39%;
  height: 37.37%;
  padding: 3.78cqw;
  border-radius: 2.45cqw;
  border: 0.21cqw dashed #a9bcde;
  background: #f9fafc;
}

/* ---- 7. query line ----------------------------------------------------- */

.ais__query {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 2cqw;
}

/* The type sizing lives on the WRAPPER, not the inner span: as a flex item it
   builds its own strut, and inheriting the root's 16px/20px one made the line
   box 14 px taller than the text and pushed the whole panel down.

   The reveal is a clip-path rather than an animated width, so the box keeps
   its natural size throughout — the sparkle opposite it cannot be pushed, and
   descenders are never cropped. */

.ais__typedwrap {
  display: inline-block;
  width: -moz-fit-content;
  width: fit-content;
  font-size: 2.35cqw;
  line-height: 1.25;
  color: #a9adb9;
  white-space: nowrap;
}

.ais__typed {
  white-space: nowrap;
}

.ais__loc {
  color: #3f6fd0;
  /* max() because 0.16cqw is well under a pixel at this size and the rule
     simply drops out — the underline has to survive the small end */
  text-decoration: underline;
  text-decoration-thickness: max(1px, 0.16cqw);
  text-underline-offset: 0.3cqw;
}

.ais__spark {
  flex: none;
  width: 2.14cqw;
  height: 2.14cqw;
  color: #b9c4e4;
  overflow: visible;
}

/* ---- rules ------------------------------------------------------------- */

.ais__rule {
  display: block;
  height: 0.1cqw;
  background: #dfe1e5;
  transform-origin: left center;
}

.ais__query + .ais__rule {
  margin-top: 5.33cqw;
}

.ais__row  + .ais__rule  {
  margin-top: 1.94cqw;
}

/* ---- 8. focus chips + 9. analyze button -------------------------------- */

.ais__row {
  display: flex;
  align-items: center;
  gap: 1.8cqw;
  margin-top: 1.63cqw;
}

.ais__chips {
  flex: 1 1 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.22cqw 0.82cqw;
}

.ais__lab {
  font-size: 1.43cqw;
  color: #565b66;
}

.ais__lab--try {
  color: #9aa0a8;
}

.ais__chip {
  display: inline-flex;
  align-items: center;
  height: 3.37cqw;
  padding: 0 1.53cqw;
  border-radius: 100px;
  border: 0.1cqw solid #dcdee3;
  background: #fff;
  font-size: 1.48cqw;
  color: #3c4049;
  white-space: nowrap;
}

.ais__chip.is-on {
  border-color: #a9c4f2;
  background: #eaf1fe;
  color: #4a7ae0;
}

.ais__btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.85cqw;
  height: 5.41cqw;
  padding: 0 2.4cqw;
  border-radius: 100px;
  background: linear-gradient(105deg, #3b74e2 0%, #4b86ea 60%, #4f8bec 100%);
  margin-top: 0.6cqw;
  /* the artwork sits it just below the chips' centre */
  font-size: 1.63cqw;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
  box-shadow: 0 0.6cqw 1.6cqw -0.4cqw rgba(59, 116, 226, 0.5);
}

.ais__btn svg {
  width: 1.63cqw;
  height: 1.63cqw;
}

/* ---- 10. suggestion tags ----------------------------------------------- */

.ais__try {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.82cqw 0.95cqw;
  margin-top: 2.65cqw;
}

.ais__tag {
  display: inline-flex;
  align-items: center;
  height: 3.16cqw;
  padding: 0 1.15cqw;
  border-radius: 100px;
  border: 0.1cqw solid #e2e4e8;
  background: #fff;
  font-size: 1.38cqw;
  color: #6b7079;
  white-space: nowrap;
}

/* ==========================================================================
   AI SOURCING — SCROLL ENTRANCE
   --------------------------------------------------------------------------
   Two ways in, one set of from-states. js/ai-sourcing.js drives a GSAP
   timeline when GSAP + ScrollTrigger are on the page (they are — the footer
   loads them for the showcase). Without them it falls back to an
   IntersectionObserver that just adds .is-in, and the transitions below run
   the same sequence with delays instead of a timeline.

   Only transform and opacity are animated. Nothing here is in flow — the
   three blocks are absolutely positioned and the chips reserve their space —
   so no step can shift the layout.
   ========================================================================== */

.ais [data-ais] {
  opacity: 0;
}

.ais__card  {
  transform: translate3d(0, 4.1cqw, 0);
}

.ais__link  {
  transform: scaleY(0);
  transform-origin: top center;
}

.ais__plus  {
  transform: scale(0);
}

.ais__panel {
  transform: translate3d(0, 3.1cqw, 0) scale(0.98);
}

.ais__typedwrap {
  clip-path: inset(0 100% 0 0);
}

.ais__chip,
.ais__tag   {
  transform: translate3d(0, 0.9cqw, 0);
}

.ais__btn   {
  transform: scale(0.9);
}

.ais__spark {
  transform: scale(0.4);
}

.ais__title {
  transform: translate3d(0, 1.2cqw, 0);
}

.ais__sub   {
  transform: translate3d(0, 0.8cqw, 0);
}

/* ---- fallback path: IntersectionObserver adds .is-in ------------------- */

.ais.is-in [data-ais] {
  opacity: 1;
  transition:
    opacity 320ms var(--ease-smooth) var(--d, 0ms),
    transform 360ms var(--ease-smooth) var(--d, 0ms),
    clip-path 410ms var(--ease-smooth) var(--d, 0ms);
}

.ais.is-in .ais__card,
.ais.is-in .ais__title,
.ais.is-in .ais__sub,
.ais.is-in .ais__panel,
.ais.is-in .ais__chip,
.ais.is-in .ais__tag {
  transform: translate3d(0, 0, 0);
}

.ais.is-in .ais__link {
  transform: scaleY(1);
}

.ais.is-in .ais__plus,
.ais.is-in .ais__btn,
.ais.is-in .ais__spark {
  transform: scale(1);
}

.ais.is-in .ais__typedwrap {
  clip-path: inset(0 0 0 0);
}

.ais.is-in .ais__card  {
  --d: 0ms;
}

.ais.is-in .ais__title {
  --d: 100ms;
}

.ais.is-in .ais__sub   {
  --d: 160ms;
}

.ais.is-in .ais__link  {
  --d: 230ms;
}

.ais.is-in .ais__plus  {
  --d: 350ms;
}

.ais.is-in .ais__panel {
  --d: 410ms;
}

.ais.is-in .ais__typed-wrap,
.ais.is-in .ais__typedwrap {
  --d: 540ms;
}

.ais.is-in .ais__spark {
  --d: 590ms;
}

.ais.is-in .ais__chip  {
  --d: calc(650ms + var(--i, 0) * 40ms);
}

.ais.is-in .ais__btn   {
  --d: 900ms;
}

.ais.is-in .ais__tag   {
  --d: calc(960ms + var(--i, 0) * 40ms);
}

/* ---- the sparkle keeps drifting once it has landed --------------------- */

@keyframes ais-spark-float {
  0%, 100% {
    transform: translate3d(0, 0, 0);
  }

  50%      {
    transform: translate3d(0, -14%, 0);
  }
}

/* ---- no motion: render the finished illustration ----------------------- */

@media (prefers-reduced-motion: reduce) {
  .ais [data-ais] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    animation: none !important;
  }

  .ais__typedwrap {
    clip-path: none !important;
  }
}

/* ==========================================================================
   AI SOURCING — AMBIENT LAYER ("the system is thinking")
   --------------------------------------------------------------------------
   Continuous micro-motion, added on top of the one-shot entrance. It is gated
   behind `.is-live`, which js/ai-sourcing.js adds only once the entrance has
   finished, for a reason worth keeping in mind:

     a CSS animation outranks an inline style, so any ambient keyframe touching
     `transform` would silently override the transform GSAP is writing during
     the entrance. Card, plus, sparkle, chips and tags all animate transform in
     both phases — gating keeps the two from ever running at once.

   Everything below is transform, opacity, box-shadow or a pseudo-element, so
   nothing reflows. Timings are deliberately coprime-ish (3.4s / 4.6s / 5.2s /
   6.5s / 7.5s / 9s / 26s) so the parts never fall into step with each other,
   which is what makes the whole thing read as alive rather than as a loop.
   ========================================================================== */

/* ---- background: a slow travelling light, and near-invisible dust -------- */

.liveui::before,
.liveui::after {
  content: '';
  position: absolute;
  z-index: 0;
  pointer-events: none;
}

.liveui::before {
  inset: -25%;
  background: radial-gradient(38% 34% at 32% 26%, rgba(255, 255, 255, 0.75), transparent 62%);
  opacity: 0.5;
}

.liveui::after {
  inset: -12%;
  opacity: 0.55;
  background-image:
    radial-gradient(1.5px 1.5px at 12% 22%, rgba(255, 255, 255, 0.95), transparent 60%),
    radial-gradient(1.2px 1.2px at 27% 67%, rgba(255, 255, 255, 0.75), transparent 60%),
    radial-gradient(1.7px 1.7px at 46% 12%, rgba(255, 255, 255, 0.65), transparent 60%),
    radial-gradient(1.3px 1.3px at 62% 83%, rgba(255, 255, 255, 0.8), transparent 60%),
    radial-gradient(1.6px 1.6px at 80% 34%, rgba(255, 255, 255, 0.7), transparent 60%),
    radial-gradient(1.2px 1.2px at 91% 73%, rgba(255, 255, 255, 0.75), transparent 60%),
    radial-gradient(1.4px 1.4px at 37% 45%, rgba(255, 255, 255, 0.6), transparent 60%);
}

/* The three blocks ride above both layers. */

.ais__card,
.ais__link,
.ais__panel {
  z-index: 1;
}

@keyframes ais-lightdrift {
  0%, 100% {
    transform: translate3d(-3%, -2%, 0) scale(1);
    opacity: 0.42;
  }

  50%      {
    transform: translate3d(6%, 5%, 0)   scale(1.22);
    opacity: 0.78;
  }
}

@keyframes ais-dust {
  0%, 100% {
    transform: translate3d(0, 0, 0);
    opacity: 0.35;
  }

  50%      {
    transform: translate3d(-1.4%, -3.2%, 0);
    opacity: 0.7;
  }
}

.liveui.is-live::before {
  animation: ais-lightdrift 26s ease-in-out infinite;
}

.liveui.is-live::after  {
  animation: ais-dust 34s ease-in-out infinite;
}

/* ---- heading card: breathing, with the shadow shifting under it --------- */

@keyframes ais-breathe {
  0%, 100% {
    transform: scale(1);
    box-shadow:
      0 0.2cqw 0.6cqw rgba(43, 68, 120, 0.05),
      0 1.6cqw 3.4cqw -1cqw rgba(43, 68, 120, 0.16);
  }

  50% {
    transform: scale(1.006);
    box-shadow:
      0 0.3cqw 0.8cqw rgba(43, 68, 120, 0.06),
      0 2.1cqw 4.2cqw -1cqw rgba(43, 68, 120, 0.2);
  }
}

.ais.is-live .ais__card {
  animation: ais-breathe 7.5s ease-in-out infinite;
}

/* ---- connector: a light running down toward the plus -------------------- */

.ais__link::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 0;
  width: 0.72cqw;
  height: 0.72cqw;
  margin-left: -0.36cqw;
  border-radius: 50%;
  background: #5b8ae8;
  box-shadow: 0 0 0.9cqw 0.16cqw rgba(91, 138, 232, 0.65);
  opacity: 0;
}

/* travels the connector's own 9.03% of the box — 79 px in the artwork */

@keyframes ais-travel {
  0%       {
    transform: translateY(0);
    opacity: 0;
  }

  14%      {
    opacity: 1;
  }

  78%      {
    opacity: 1;
  }

  100%     {
    transform: translateY(8.06cqw);
    opacity: 0;
  }
}

.ais.is-live .ais__link::after {
  animation: ais-travel 3.8s ease-in-out infinite;
}

/* ---- plus node: slow pulse, with a ring breathing out of it ------------- */

@keyframes ais-plus {
  0%, 100% {
    transform: scale(1);
  }

  50%      {
    transform: scale(1.045);
  }
}

@keyframes ais-plusring {
  0%       {
    transform: scale(1);
    opacity: 0.5;
  }

  70%, 100% {
    transform: scale(1.9);
    opacity: 0;
  }
}

.ais__plus::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 0.16cqw solid rgba(59, 116, 226, 0.55);
  opacity: 0;
}

.ais.is-live .ais__plus         {
  animation: ais-plus 5.6s ease-in-out infinite;
}

.ais.is-live .ais__plus::before {
  animation: ais-plusring 5.6s ease-in-out infinite;
}

/* ---- query: blinking caret, and the underline breathing ----------------- */

.ais__caret {
  display: inline-block;
  width: 0.16cqw;
  height: 1.9cqw;
  margin-left: 0.3cqw;
  vertical-align: -0.32cqw;
  background: #8b90a0;
  opacity: 0;
}

@keyframes ais-caret {
  0%, 48%   {
    opacity: 1;
  }

  49%, 100% {
    opacity: 0;
  }
}

@keyframes ais-underline {
  0%, 100% {
    text-decoration-color: rgba(63, 111, 208, 0.4);
  }

  50%      {
    text-decoration-color: rgba(63, 111, 208, 1);
  }
}

.ais.is-live .ais__caret {
  animation: ais-caret 1.1s steps(1, end) infinite;
}

.ais.is-live .ais__loc   {
  animation: ais-underline 3.2s ease-in-out infinite;
}

/* ---- input area: a scan passing over the prompt ------------------------- */

.ais__panel {
  overflow: hidden;
}

/* the panel's own children have to out-rank the scan */

.ais__query,
.ais__rule,
.ais__row,
.ais__try {
  position: relative;
  z-index: 1;
}

.ais__panel::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 11cqw;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent 24%,
    rgba(255, 255, 255, 0.9) 46%,
    rgba(203, 222, 252, 0.55) 56%,
    transparent 78%
  );
  transform: translateX(-100%);
  opacity: 0;
}

@keyframes ais-scan {
  0%        {
    transform: translateX(-100%);
    opacity: 0;
  }

  10%       {
    opacity: 1;
  }

  58%       {
    opacity: 1;
  }

  72%, 100% {
    transform: translateX(100%);
    opacity: 0;
  }
}

.ais.is-live .ais__panel::before {
  animation: ais-scan 9s ease-in-out infinite 1.4s;
}

/* ---- sparkle: twinkle, a little rotation, an occasional glow ------------ */

@keyframes ais-twinkle {
  0%, 100% {
    transform: translateY(0) rotate(0deg) scale(1);
    opacity: 0.85;
    filter: none;
  }

  30%      {
    transform: translateY(-4%) rotate(4deg) scale(1.05);
    opacity: 1;
  }

  50%      {
    transform: translateY(-8%) rotate(9deg) scale(1.12);
    opacity: 1;
    filter: drop-shadow(0 0 0.55cqw rgba(116, 156, 232, 0.9));
  }

  74%      {
    transform: translateY(-3%) rotate(3deg) scale(1.03);
    opacity: 0.9;
  }
}

.ais.is-live .ais__spark {
  animation: ais-twinkle 5.2s ease-in-out infinite;
}

/* ---- focus pills: a wave passing along them ---------------------------- */

@keyframes ais-pill {
  0%, 80%, 100% {
    transform: translateY(0);
  }

  88%           {
    transform: translateY(-0.38cqw);
  }
}

@keyframes ais-loc {
  0%, 100% {
    border-color: #a9c4f2;
    box-shadow: 0 0 0 0 rgba(74, 122, 224, 0);
  }

  50%      {
    border-color: #7ba4ee;
    box-shadow: 0 0 0.95cqw 0.1cqw rgba(74, 122, 224, 0.38);
  }
}

.ais.is-live .ais__chip {
  animation: ais-pill 8s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.55s);
}

/* Two animations, deliberately on different properties — ais-pill owns the
   transform, ais-loc owns border and shadow — so neither cancels the other. */

.ais.is-live .ais__chip.is-on {
  animation:
    ais-pill 8s ease-in-out infinite calc(var(--i, 0) * 0.55s),
    ais-loc 4.6s ease-in-out infinite;
}

/* ---- analyze button: light sweep, breathing glow, pulsing icon ---------- */

.ais__btn {
  position: relative;
  overflow: hidden;
}

.ais__btn::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    105deg,
    transparent 32%,
    rgba(255, 255, 255, 0.42) 50%,
    transparent 68%
  );
  transform: translateX(-130%);
}

@keyframes ais-sweep {
  0%        {
    transform: translateX(-130%);
  }

  42%, 100% {
    transform: translateX(130%);
  }
}

@keyframes ais-btnglow {
  0%, 100% {
    box-shadow: 0 0.6cqw 1.6cqw -0.4cqw rgba(59, 116, 226, 0.5);
  }

  50%      {
    box-shadow: 0 0.8cqw 2.2cqw -0.4cqw rgba(59, 116, 226, 0.78);
  }
}

@keyframes ais-iconpulse {
  0%, 100% {
    transform: scale(1);
  }

  50%      {
    transform: scale(1.14);
  }
}

.ais.is-live .ais__btn        {
  animation: ais-btnglow 5s ease-in-out infinite;
}

.ais.is-live .ais__btn::after {
  animation: ais-sweep 6.5s ease-in-out infinite 1.2s;
}

.ais.is-live .ais__btn svg    {
  animation: ais-iconpulse 3.4s ease-in-out infinite;
}

/* ---- suggestion tags: barely-there float ------------------------------- */

@keyframes ais-float {
  0%, 100% {
    transform: translateY(0);
  }

  50%      {
    transform: translateY(-0.32cqw);
  }
}

.ais.is-live .ais__tag {
  animation: ais-float 6s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.9s);
}

/* ---- hold everything while the showcase has this step crossfaded out -----
   `is-showing` rather than `is-active`: showcase.js strips is-active the
   moment the pin starts and drives visibility with autoAlpha instead, so
   :not(.is-active) would match every panel and freeze the lot. Scoped to the
   query the pin runs under, since below it the panels are a stacked list and
   all of them are on screen. */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .sc-panel:not(.is-showing) .liveui,
.sc-panel:not(.is-showing) .liveui::before,
.sc-panel:not(.is-showing) .liveui::after,
.sc-panel:not(.is-showing) .ais__card,
.sc-panel:not(.is-showing) .ais__link::after,
.sc-panel:not(.is-showing) .ais__plus,
.sc-panel:not(.is-showing) .ais__plus::before,
.sc-panel:not(.is-showing) .ais__caret,
.sc-panel:not(.is-showing) .ais__loc,
.sc-panel:not(.is-showing) .ais__panel::before,
.sc-panel:not(.is-showing) .ais__spark,
.sc-panel:not(.is-showing) .ais__chip,
.sc-panel:not(.is-showing) .ais__btn,
.sc-panel:not(.is-showing) .ais__btn::after,
.sc-panel:not(.is-showing) .ais__btn svg,
.sc-panel:not(.is-showing) .ais__tag,
/* The Location pill re-declares the `animation` shorthand at a higher
   specificity, which resets play-state back to running — so it needs its own
   entry that outranks that rule rather than the plain .ais__chip one. */
.sc-panel:not(.is-showing) .ais.is-live .ais__chip.is-on {
    animation-play-state: paused;
  }
}

/* ---- no motion: a still, finished illustration ------------------------- */

@media (prefers-reduced-motion: reduce) {
  .liveui::before,
  .liveui::after,
  .ais__card,
  .ais__link::after,
  .ais__plus,
  .ais__plus::before,
  .ais__caret,
  .ais__loc,
  .ais__panel::before,
  .ais__spark,
  .ais__chip,
  .ais__btn,
  .ais__btn::after,
  .ais__btn svg,
  .ais__tag {
    animation: none !important;
  }

  .ais__caret {
    opacity: 0;
  }
}

/* ==========================================================================
   AI ASSESSMENT ILLUSTRATION  (showcase panel 02 — "See past the CV")
   --------------------------------------------------------------------------
   A rebuild of assets/images/showcase-ai-assessment.jpg (984 × 880) as live
   markup. Sits on the shared `.liveui` stage, so the tinted ground, the
   drifting light and the dust come from there; everything below is this
   panel's own furniture.

   1 cqw = 1 % of the box = 9.84 px in the reference artwork, which is how the
   sizes were derived. Coordinates measured off the artwork:
     cards       x 104→882            (all three share the column)
     header      y 67→256   radius 22
     link A      y 256→312   node 37 px centred on (493, 330)
     meta        y 338→464   dividers at x 358 and 613
     link B      y 464→526   node centred on (493, 544)
     summary     y 551→790   dashed
   ========================================================================== */

.aia {
  aspect-ratio: 984 / 880;
}

.aia__card,
.aia__summary {
  position: absolute;
  left: 10.57%;
  width: 79.07%;
  z-index: 1;
}

.aia__card {
  border-radius: 2.24cqw;
  background: #f9fafd;
  box-shadow:
    0 0.2cqw 0.6cqw rgba(43, 68, 120, 0.05),
    0 1.5cqw 3.2cqw -1cqw rgba(43, 68, 120, 0.15);
}

/* ---- 1. candidate header ----------------------------------------------- */

.aia__head {
  top: 7.61%;
  height: 21.48%;
  padding: 2.44cqw 2.54cqw 0 3.96cqw;
}

.aia__headtop {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}

.aia__name {
  font-size: 2.92cqw;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: #0e0c18;
}

.aia__loc {
  display: flex;
  align-items: center;
  gap: 0.7cqw;
  margin-top: 0.75cqw;
  font-size: 1.87cqw;
  color: #8f95a5;
}

.aia__loc svg {
  width: 1.73cqw;
  height: 1.73cqw;
  flex: none;
}

.aia__scorebox {
  text-align: right;
}

.aia__overall {
  font-size: 1.38cqw;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #959ba9;
}

.aia__scoreline {
  margin-top: 0.5cqw;
  line-height: 1;
  white-space: nowrap;
}

.aia__scorenum {
  font-size: 5.82cqw;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: #3b74e2;
}

.aia__scoremax {
  font-size: 2.16cqw;
  font-weight: 600;
  color: #8fa6cf;
}

/* The pill's left edge sits ~11 px outside the name's, as in the artwork —
   optical alignment, so its label rather than its box lines up. */

.aia__tabs {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* right inset pulls Q&A in to x 798, where the artwork ends the row */
  margin: 1.32cqw 6cqw 0 -1.12cqw;
}

.aia__tab {
  font-size: 1.86cqw;
  color: #9298a8;
  white-space: nowrap;
}

.aia__tab.is-on {
  padding: 1.42cqw 3.2cqw;
  border-radius: 1.02cqw;
  background: #3b76da;
  color: #fff;
  font-weight: 500;
}

/* ---- connectors and nodes ---------------------------------------------- */

.aia__link {
  position: absolute;
  left: 50.1%;
  width: 0.21cqw;
  margin-left: -0.105cqw;
  z-index: 1;
  background-image: repeating-linear-gradient(
    to bottom,
    #8ba4d4 0 0.62cqw,
    transparent 0.62cqw 1.28cqw
  );
}

.aia__link--a {
  top: 29.09%;
  height: 6.36%;
}

.aia__link--b {
  top: 52.73%;
  height: 7.05%;
}

.aia__plus {
  position: absolute;
  left: 50.1%;
  width: 3.76cqw;
  height: 3.76cqw;
  margin-left: -1.88cqw;
  z-index: 2;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #0b2c5f;
  color: #fff;
  box-shadow: 0 0.5cqw 1.2cqw -0.3cqw rgba(11, 44, 95, 0.45);
}

.aia__plus--a {
  top: 37.5%;
  margin-top: -1.88cqw;
}

.aia__plus--b {
  top: 61.82%;
  margin-top: -1.88cqw;
}

.aia__plus svg {
  width: 55%;
  height: 55%;
}

/* ---- 3. interview metadata --------------------------------------------- */

.aia__meta {
  top: 38.41%;
  height: 14.32%;
  display: grid;
  grid-template-columns: 32.7% 32.8% 34.5%;
  /* dividers at x 358 and 613 */
  align-content: center;
}

.aia__col + .aia__col {
  border-left: 0.1cqw solid #e6e8ec;
}

/* The artwork insets each column differently — reproduced rather than
   normalised, so the three read exactly where they do in the original. */

.aia__col:nth-child(1) {
  padding-left: 4.07cqw;
}

.aia__col:nth-child(2) {
  padding-left: 6.2cqw;
}

.aia__col:nth-child(3) {
  padding-left: 5.9cqw;
}

.aia__mlabel {
  font-size: 1.47cqw;
  font-weight: 500;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: #747a88;
}

.aia__mval {
  display: flex;
  align-items: center;
  gap: 0.85cqw;
  margin-top: 1.1cqw;
  font-size: 1.9cqw;
  font-weight: 600;
  color: #0e0c18;
  white-space: nowrap;
}

.aia__mval svg {
  width: 1.93cqw;
  height: 1.93cqw;
  flex: none;
  color: #4a7ad0;
}

/* ---- 5. AI summary ------------------------------------------------------ */

.aia__summary {
  top: 62.61%;
  height: 27.16%;
  padding: 3.46cqw;
  border-radius: 2.24cqw;
  border: 0.2cqw dashed #a9bcde;
  background: #fafbfd;
  overflow: hidden;
}

.aia__stitle {
  display: flex;
  align-items: center;
  gap: 1.73cqw;
  font-size: 2.11cqw;
  font-weight: 600;
  color: #0e0c18;
}

.aia__dot {
  width: 1.42cqw;
  height: 1.42cqw;
  flex: none;
  border-radius: 50%;
  background: #3b74e2;
}

.aia__row {
  display: flex;
  align-items: flex-start;
  gap: 2.13cqw;
  margin-top: 2.83cqw;
  /* Sized so each finding sets on one line inside the 667 px the artwork
     allows — Inter runs ~24 % wider than the reference face, so matching its
     apparent size rather than its measured cap height is what keeps the
     three rows from wrapping and overflowing the card. */
  font-size: 1.68cqw;
  color: #72717f;
}

.aia__row:first-of-type {
  margin-top: 2.75cqw;
}

.aia__row svg {
  width: 2.03cqw;
  height: 2.03cqw;
  flex: none;
  margin-top: 0.25cqw;
  color: #4a7ad0;
}

/* ==========================================================================
   AI ASSESSMENT — SCROLL ENTRANCE
   Same arrangement as the sourcing panel: these are the from-states, shared by
   the GSAP timeline and the no-GSAP fallback. Nothing here is in normal flow,
   so no step can shift the layout.
   ========================================================================== */

.aia [data-aia] {
  opacity: 0;
}

.aia__head    {
  transform: translate3d(0, 4.1cqw, 0);
}

.aia__name    {
  transform: translate3d(0, 1.2cqw, 0);
}

.aia__loc     {
  transform: translate3d(0, 0.8cqw, 0);
}

.aia__scorebox {
  transform: translate3d(0, 1.1cqw, 0);
}

.aia__tab     {
  transform: translate3d(0, 0.9cqw, 0);
}

.aia__link    {
  transform: scaleY(0);
  transform-origin: top center;
}

.aia__plus    {
  transform: scale(0);
}

.aia__meta    {
  transform: translate3d(0, 3.1cqw, 0) scale(0.98);
}

.aia__col     {
  transform: translate3d(0, 0.9cqw, 0);
}

.aia__summary {
  transform: translate3d(0, 3.1cqw, 0) scale(0.98);
}

.aia__row     {
  transform: translate3d(0, 0.9cqw, 0);
}

/* ---- fallback path: IntersectionObserver adds .is-in ------------------- */

.aia.is-in [data-aia] {
  opacity: 1;
  transition:
    opacity 320ms var(--ease-smooth) var(--d, 0ms),
    transform 360ms var(--ease-smooth) var(--d, 0ms);
}

.aia.is-in .aia__head,
.aia.is-in .aia__name,
.aia.is-in .aia__loc,
.aia.is-in .aia__scorebox,
.aia.is-in .aia__tab,
.aia.is-in .aia__meta,
.aia.is-in .aia__col,
.aia.is-in .aia__summary,
.aia.is-in .aia__row {
  transform: translate3d(0, 0, 0);
}

.aia.is-in .aia__link {
  transform: scaleY(1);
}

.aia.is-in .aia__plus {
  transform: scale(1);
}

.aia.is-in .aia__head     {
  --d: 0ms;
}

.aia.is-in .aia__name     {
  --d: 90ms;
}

.aia.is-in .aia__loc      {
  --d: 150ms;
}

.aia.is-in .aia__scorebox {
  --d: 200ms;
}

.aia.is-in .aia__tab      {
  --d: calc(250ms + var(--i, 0) * 40ms);
}

.aia.is-in .aia__link--a  {
  --d: 410ms;
}

.aia.is-in .aia__plus--a  {
  --d: 510ms;
}

.aia.is-in .aia__meta     {
  --d: 560ms;
}

.aia.is-in .aia__col      {
  --d: calc(650ms + var(--i, 0) * 40ms);
}

.aia.is-in .aia__link--b  {
  --d: 770ms;
}

.aia.is-in .aia__plus--b  {
  --d: 860ms;
}

.aia.is-in .aia__summary  {
  --d: 920ms;
}

.aia.is-in .aia__row      {
  --d: calc(1020ms + var(--i, 0) * 50ms);
}

/* ==========================================================================
   AI ASSESSMENT — AMBIENT LAYER
   Gated behind .is-live for the same reason as the sourcing panel: a CSS
   animation outranks an inline style, so an ambient keyframe on `transform`
   would override what GSAP writes during the entrance. Timings are staggered
   against each other so nothing falls into step.
   ========================================================================== */

/* header and metadata breathe, out of phase with one another */

@keyframes aia-breathe {
  0%, 100% {
    transform: scale(1);
    box-shadow:
      0 0.2cqw 0.6cqw rgba(43, 68, 120, 0.05),
      0 1.5cqw 3.2cqw -1cqw rgba(43, 68, 120, 0.15);
  }

  50% {
    transform: scale(1.005);
    box-shadow:
      0 0.3cqw 0.8cqw rgba(43, 68, 120, 0.06),
      0 2cqw 4cqw -1cqw rgba(43, 68, 120, 0.19);
  }
}

.aia.is-live .aia__head {
  animation: aia-breathe 7.5s ease-in-out infinite;
}

.aia.is-live .aia__meta {
  animation: aia-breathe 9.2s ease-in-out infinite 1.6s;
}

/* the score is the focal number — a slow, quiet glow rather than movement */

@keyframes aia-score {
  0%, 100% {
    color: #3b74e2;
    text-shadow: none;
  }

  50%      {
    color: #2f68dc;
    text-shadow: 0 0 1.6cqw rgba(59, 116, 226, 0.45);
  }
}

.aia.is-live .aia__scorenum {
  animation: aia-score 6.4s ease-in-out infinite;
}

/* active tab holds a soft glow */

@keyframes aia-tab {
  0%, 100% {
    box-shadow: 0 0.3cqw 0.9cqw -0.3cqw rgba(59, 118, 218, 0.5);
  }

  50%      {
    box-shadow: 0 0.5cqw 1.5cqw -0.3cqw rgba(59, 118, 218, 0.8);
  }
}

.aia.is-live .aia__tab.is-on {
  animation: aia-tab 5s ease-in-out infinite;
}

/* a light runs down each connector, the second trailing the first */

.aia__link::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 0;
  width: 0.72cqw;
  height: 0.72cqw;
  margin-left: -0.36cqw;
  border-radius: 50%;
  background: #5b8ae8;
  box-shadow: 0 0 0.9cqw 0.16cqw rgba(91, 138, 232, 0.65);
  opacity: 0;
}

@keyframes aia-travel-a {
  0%   {
    transform: translateY(0);
    opacity: 0;
  }

  14%  {
    opacity: 1;
  }

  78%  {
    opacity: 1;
  }

  100% {
    transform: translateY(5.69cqw);
    opacity: 0;
  }

  /* 56 px */
}

@keyframes aia-travel-b {
  0%   {
    transform: translateY(0);
    opacity: 0;
  }

  14%  {
    opacity: 1;
  }

  78%  {
    opacity: 1;
  }

  100% {
    transform: translateY(6.3cqw);
    opacity: 0;
  }

  /* 62 px */
}

.aia.is-live .aia__link--a::after {
  animation: aia-travel-a 4.2s ease-in-out infinite;
}

.aia.is-live .aia__link--b::after {
  animation: aia-travel-b 4.2s ease-in-out infinite 1.5s;
}

/* nodes pulse, each with a ring breathing out of it */

@keyframes aia-plus {
  0%, 100% {
    transform: scale(1);
  }

  50%      {
    transform: scale(1.045);
  }
}

@keyframes aia-plusring {
  0%        {
    transform: scale(1);
    opacity: 0.5;
  }

  70%, 100% {
    transform: scale(1.9);
    opacity: 0;
  }
}

.aia__plus::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 0.16cqw solid rgba(59, 116, 226, 0.55);
  opacity: 0;
}

.aia.is-live .aia__plus--a         {
  animation: aia-plus 5.6s ease-in-out infinite;
}

.aia.is-live .aia__plus--a::before {
  animation: aia-plusring 5.6s ease-in-out infinite;
}

.aia.is-live .aia__plus--b         {
  animation: aia-plus 5.6s ease-in-out infinite 1.9s;
}

.aia.is-live .aia__plus--b::before {
  animation: aia-plusring 5.6s ease-in-out infinite 1.9s;
}

/* metadata icons tick over, one after another */

@keyframes aia-micon {
  0%, 72%, 100% {
    transform: scale(1);
    color: #4a7ad0;
  }

  80%           {
    transform: scale(1.16);
    color: #2f68dc;
  }
}

.aia.is-live .aia__mval svg {
  animation: aia-micon 7s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.7s);
}

/* the summary is what the model is "writing" — a scan crosses it, the status
   dot breathes, and each finding lights briefly in turn */

.aia__summary::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent 26%,
    rgba(255, 255, 255, 0.85) 47%,
    rgba(205, 223, 252, 0.5) 57%,
    transparent 78%
  );
  transform: translateX(-100%);
  opacity: 0;
}

.aia__stitle,
.aia__row {
  position: relative;
  z-index: 1;
}

@keyframes aia-scan {
  0%        {
    transform: translateX(-100%);
    opacity: 0;
  }

  10%       {
    opacity: 1;
  }

  58%       {
    opacity: 1;
  }

  72%, 100% {
    transform: translateX(100%);
    opacity: 0;
  }
}

@keyframes aia-dot {
  0%, 100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(59, 116, 226, 0.5);
  }

  50%      {
    transform: scale(1.15);
    box-shadow: 0 0 0.9cqw 0.14cqw rgba(59, 116, 226, 0.55);
  }
}

@keyframes aia-rowlight {
  0%, 74%, 100% {
    color: #72717f;
  }

  84%           {
    color: #4a4e5c;
  }
}

@keyframes aia-checklight {
  0%, 74%, 100% {
    transform: scale(1);
    color: #4a7ad0;
  }

  84%           {
    transform: scale(1.12);
    color: #2f68dc;
  }
}

.aia.is-live .aia__summary::before {
  animation: aia-scan 9.5s ease-in-out infinite 1.4s;
}

.aia.is-live .aia__dot             {
  animation: aia-dot 3.6s ease-in-out infinite;
}

.aia.is-live .aia__row {
  animation: aia-rowlight 8s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.85s);
}

.aia.is-live .aia__row svg {
  animation: aia-checklight 8s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.85s);
}

/* ---- hold everything while the showcase has this step crossfaded out -----
   `is-showing` rather than `is-active`: showcase.js strips is-active the
   moment the pin starts and drives visibility with autoAlpha instead, so
   :not(.is-active) would match every panel and freeze the lot. Scoped to the
   query the pin runs under, since below it the panels are a stacked list and
   all of them are on screen. */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .sc-panel:not(.is-showing) .aia__head,
.sc-panel:not(.is-showing) .aia__meta,
.sc-panel:not(.is-showing) .aia__scorenum,
.sc-panel:not(.is-showing) .aia__tab.is-on,
.sc-panel:not(.is-showing) .aia__link::after,
.sc-panel:not(.is-showing) .aia__plus,
.sc-panel:not(.is-showing) .aia__plus::before,
.sc-panel:not(.is-showing) .aia__mval svg,
.sc-panel:not(.is-showing) .aia__summary::before,
.sc-panel:not(.is-showing) .aia__dot,
.sc-panel:not(.is-showing) .aia__row,
.sc-panel:not(.is-showing) .aia__row svg {
    animation-play-state: paused;
  }
}

/* ---- no motion: a still, finished illustration ------------------------- */

@media (prefers-reduced-motion: reduce) {
  .aia [data-aia] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .aia__head,
  .aia__meta,
  .aia__scorenum,
  .aia__tab.is-on,
  .aia__link::after,
  .aia__plus,
  .aia__plus::before,
  .aia__mval svg,
  .aia__summary::before,
  .aia__dot,
  .aia__row,
  .aia__row svg {
    animation: none !important;
  }
}

/* ==========================================================================
   HERO PIN — the section holds on screen for a beat before it scrolls away
   --------------------------------------------------------------------------
   `.hero__stage` is sticky inside a taller `.hero__track`. CSS does the
   pinning; js/hero-pin.js only supplies the two numbers CSS cannot work out —
   the track's height, and the negative `top` that sticks a stage taller than
   the viewport by its bottom edge instead of its top. It also publishes
   `--hero-p`, 0 → 1 across the pin, which drives everything below.

   Careful with `overflow` on the section or the track: any value other than
   visible makes them a scroll container and sticky quietly stops working. The
   clip belongs to the stage, which is where the markup puts it.

   Off this query the hero is exactly the section it was — no track height, no
   sticky top, `--hero-p` unset and every layer at its 0 state.
   ========================================================================== */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .hero__stage {
    position: sticky;
    /* top comes from js/hero-pin.js — it is a measurement, not a constant */
  }

  /* Depth. The sky swells and drifts up a little; the clouds move about twice
     as far, which is what separates them from it. Both are transforms, so the
     layout underneath never moves. */

  #hero .hero__bg {
    transform: scale(calc(1 + 0.05 * var(--hero-p, 0)))
               translate3d(0, calc(var(--hero-p, 0) * -20px), 0);
    transform-origin: 50% 30%;
    will-change: transform;
  }

  #hero .hero__clouds {
    transform: translate3d(0, calc(var(--hero-p, 0) * -44px), 0);
    will-change: transform;
  }

  /* Light gathering behind the shot as it settles. Sized off the stage rather
     than the shot so it reads as the scene lifting, not as a halo stuck to the
     artwork. */

  #hero .hero__glow {
    background: radial-gradient(
      46% 34% at 50% 62%,
      rgba(255, 255, 255, 0.85),
      rgba(214, 231, 255, 0.35) 45%,
      transparent 72%
    );
    opacity: calc(0.18 + 0.52 * var(--hero-p, 0));
    transform: scale(calc(0.92 + 0.16 * var(--hero-p, 0)));
    will-change: opacity, transform;
  }
}

/* The glow is a pin effect only: with no pin there is no --hero-p to move it,
   so it would sit at a fixed 0.18 over a section that never holds still. */

@media (max-width: 1023px), (prefers-reduced-motion: reduce) {
  #hero .hero__glow {
    display: none;
  }
}

/* ==========================================================================
   AI INTERVIEW  (showcase panel 03 — "Screen at scale")
   --------------------------------------------------------------------------
   The artwork is the project's own hand-authored SVG, inlined by
   includes/ai-interview-ui.php so CSS can reach inside it. Nothing in the
   interface is restyled here — every rule below is either an entrance
   from-state or a continuous effect. The SVG scales through its viewBox, so
   there is no `cqw` sizing to keep in step.

   SVG note: `transform` on an SVG child is resolved in the user coordinate
   space, and `transform-origin` defaults to the origin of that space rather
   than the element. `transform-box: fill-box` scopes it back to the shape, and
   is what makes "scale this bar from its left edge" or "pulse this dot about
   its middle" mean what it says.
   ========================================================================== */

.aiv {
  position: relative;
  width: 508px;
  max-width: 100%;
  aspect-ratio: 1272 / 1137;
}

.aiv--fill {
  width: 100%;
  max-width: none;
}

.aiv__svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ---- entrance from-states, shared by the timeline and the fallback ------ */

.aiv [data-aiv] {
  opacity: 0;
}

.aiv__card    {
  transform: translate3d(0, 22px, 0);
}

.aiv__avatar,
.aiv__plus    {
  transform: scale(0.9);
  transform-box: fill-box;
  transform-origin: center;
}

.aiv__mfill,
.aiv__rubfill {
  transform: scaleX(0);
  transform-box: fill-box;
  transform-origin: left center;
}

.aiv [data-aiv="name"],
.aiv [data-aiv="role"],
.aiv [data-aiv="qlabel"],
.aiv [data-aiv="qline"],
.aiv [data-aiv="evaltitle"],
.aiv [data-aiv="rubtitle"],
.aiv [data-aiv="rubcopy"],
.aiv [data-aiv="foot"],
.aiv [data-aiv="step"] {
  transform: translate3d(0, 8px, 0);
}

.aiv [data-aiv="rule"] {
  transform: scaleX(0);
  transform-box: fill-box;
  transform-origin: left center;
}

.aiv [data-aiv="badge"],
.aiv [data-aiv="chip"] {
  transform: scale(0.94);
  transform-box: fill-box;
  transform-origin: center;
}

/* ---- fallback path: IntersectionObserver adds .is-in ------------------- */

.aiv.is-in [data-aiv] {
  opacity: 1;
  transition:
    opacity 320ms var(--ease-smooth) var(--d, 0ms),
    transform 410ms var(--ease-smooth) var(--d, 0ms);
  transform: none;
}

.aiv.is-in [data-aiv="card"]      {
  --d: 0ms;
}

.aiv.is-in [data-aiv="live"]      {
  --d: 130ms;
}

.aiv.is-in [data-aiv="avatar"]    {
  --d: 90ms;
}

.aiv.is-in [data-aiv="name"]      {
  --d: 170ms;
}

.aiv.is-in [data-aiv="role"]      {
  --d: 210ms;
}

.aiv.is-in [data-aiv="wave"]      {
  --d: 250ms;
}

.aiv.is-in [data-aiv="qlabel"]    {
  --d: 180ms;
}

.aiv.is-in [data-aiv="qline"]     {
  --d: 240ms;
}

.aiv.is-in [data-aiv="rule"]      {
  --d: 300ms;
}

.aiv.is-in [data-aiv="step"]      {
  --d: calc(330ms + var(--i, 0) * 50ms);
}

.aiv.is-in [data-aiv="chip"]      {
  --d: 490ms;
}

.aiv.is-in [data-aiv="evaltitle"] {
  --d: 530ms;
}

.aiv.is-in [data-aiv="badge"]     {
  --d: 570ms;
}

.aiv.is-in [data-aiv="meter"]     {
  --d: calc(600ms + var(--i, 0) * 60ms);
}

.aiv.is-in [data-aiv="foot"]      {
  --d: calc(780ms + var(--i, 0) * 40ms);
}

.aiv.is-in [data-aiv="rubtitle"]  {
  --d: 910ms;
}

.aiv.is-in [data-aiv="rubcopy"]   {
  --d: 950ms;
}

.aiv.is-in [data-aiv="rubfill"]   {
  --d: 990ms;
}

.aiv.is-in [data-aiv="plus"]      {
  --d: 1140ms;
}

/* the bars are the point of the panel — give them their own, longer sweep */

.aiv.is-in .aiv__mfill,
.aiv.is-in .aiv__rubfill {
  transform: scaleX(1);
  transition:
    opacity 230ms var(--ease-smooth) var(--d, 0ms),
    transform 640ms var(--ease-smooth) var(--d, 0ms);
}

/* ==========================================================================
   AI INTERVIEW — LIVE LAYER
   Gated behind .is-live, which js/showcase-live.js adds once the entrance has
   finished: a CSS animation outranks an inline style, so any keyframe on
   `transform` would otherwise override what GSAP writes mid-entrance.
   Timings are deliberately out of step with one another.
   ========================================================================== */

/* recording dot */

@keyframes aiv-rec {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }

  50%      {
    opacity: 0.45;
    transform: scale(0.86);
  }
}

.aiv.is-live .aiv__rec {
  transform-box: fill-box;
  transform-origin: center;
  animation: aiv-rec 1.9s ease-in-out infinite;
}

/* the candidate is speaking — nine bars, each on its own clock so the group
   never reads as one shape breathing */

@keyframes aiv-wave {
  0%, 100% {
    transform: scaleY(0.35);
  }

  50%      {
    transform: scaleY(1.15);
  }
}

.aiv.is-live .aiv__wave rect {
  transform-box: fill-box;
  /* every bar is centred on y 453 in the artwork, so scaling about the middle
     keeps the waveform on its axis */
  transform-origin: center;
  animation: aiv-wave 900ms ease-in-out infinite;
  /* prime numbers of milliseconds, so the nine never resynchronise */
  animation-duration: calc(760ms + var(--i, 0) * 97ms);
  animation-delay: calc(var(--i, 0) * -137ms);
}

/* breath around the candidate */

@keyframes aiv-breathe {
  0%, 100% {
    transform: scale(1);
    opacity: 0.95;
  }

  50%      {
    transform: scale(1.025);
    opacity: 1;
  }
}

.aiv.is-live .aiv__avatar {
  transform-box: fill-box;
  transform-origin: center;
  animation: aiv-breathe 6.4s ease-in-out infinite;
}

/* the three question dots light in turn */

@keyframes aiv-stepdot {
  0%, 76%, 100% {
    transform: scale(1);
    opacity: 1;
  }

  86%           {
    transform: scale(1.35);
    opacity: 0.75;
  }
}

.aiv.is-live .aiv__stepdot {
  transform-box: fill-box;
  transform-origin: center;
  animation: aiv-stepdot 5.4s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.5s);
}

/* the idle "up next" dot only breathes, it does not report progress */

.aiv.is-live .aiv__stepdot--idle {
  animation-duration: 7.2s;
}

/* "AI analysing…" — the chip's fill lifts while a highlight crosses it */

@keyframes aiv-chip {
  0%, 100% {
    fill: #E7EFFE;
  }

  50%      {
    fill: #DCE9FE;
  }
}

@keyframes aiv-chiptext {
  0%, 100% {
    opacity: 1;
  }

  50%      {
    opacity: 0.62;
  }
}

.aiv.is-live .aiv__chip     {
  animation: aiv-chip 2.8s ease-in-out infinite;
}

.aiv.is-live .aiv__chiptext {
  animation: aiv-chiptext 2.8s ease-in-out infinite;
}

/* Travelling highlight. Each one is clipped to its own bar, and carries its
   own --from/--to so the sweep covers that bar's width and no more. */

@keyframes aiv-shine {
  0%        {
    transform: translateX(var(--from, -110px));
  }

  55%, 100% {
    transform: translateX(var(--to, 300px));
  }
}

.aiv__shine {
  opacity: 0;
}

.aiv.is-live .aiv__shine {
  opacity: 1;
  animation: aiv-shine 5.2s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.6s);
}

/* the chip and the rubric line run on their own clocks */

.aiv.is-live [data-aiv="chip"] .aiv__shine {
  animation-duration: 2.8s;
}

.aiv.is-live .aiv__rubfill ~ g .aiv__shine {
  animation-duration: 7.5s;
}

/* Fair · bias-free keeps a soft glow */

@keyframes aiv-badge {
  0%, 100% {
    fill: #E7F7F0;
  }

  50%      {
    fill: #DBF3E8;
  }
}

.aiv.is-live .aiv__badge {
  animation: aiv-badge 4.3s ease-in-out infinite;
}

/* the rubric node */

@keyframes aiv-plus {
  0%, 100% {
    transform: scale(1);
  }

  50%      {
    transform: scale(1.08);
  }
}

.aiv.is-live .aiv__plus {
  transform-box: fill-box;
  transform-origin: center;
  animation: aiv-plus 4.8s ease-in-out infinite;
}

/* ---- hold everything while the showcase has this step crossfaded out --- */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .sc-panel:not(.is-showing) .aiv__rec,
.sc-panel:not(.is-showing) .aiv__wave rect,
.sc-panel:not(.is-showing) .aiv__avatar,
.sc-panel:not(.is-showing) .aiv__stepdot,
.sc-panel:not(.is-showing) .aiv__chip,
.sc-panel:not(.is-showing) .aiv__chiptext,
.sc-panel:not(.is-showing) .aiv__shine,
.sc-panel:not(.is-showing) .aiv__badge,
.sc-panel:not(.is-showing) .aiv__plus {
    animation-play-state: paused;
  }
}

/* ---- no motion: the finished interface, holding still ------------------ */

@media (prefers-reduced-motion: reduce) {
  .aiv [data-aiv] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .aiv__rec,
  .aiv__wave rect,
  .aiv__avatar,
  .aiv__stepdot,
  .aiv__chip,
  .aiv__chiptext,
  .aiv__shine,
  .aiv__badge,
  .aiv__plus {
    animation: none !important;
  }

  .aiv__shine {
    opacity: 0;
  }
}

/* ==========================================================================
   PAYROLL  (showcase panel 04 — "Payroll on autopilot")
   --------------------------------------------------------------------------
   The artwork is the project's own hand-authored SVG, inlined by
   includes/payroll-ui.php so CSS can reach inside it. Nothing in the interface
   is restyled here — every rule below is either an entrance from-state or a
   continuous effect, and no value, label or colour is touched. The SVG scales
   through its viewBox, so there is no `cqw` sizing to keep in step.

   SVG note: `transform` on an SVG child resolves in the user coordinate space,
   and `transform-origin` defaults to the origin of that space rather than the
   element. `transform-box: fill-box` scopes it back to the shape, which is
   what makes "grow this bar from its own base" or "pulse this dot about its
   middle" mean what it says.
   ========================================================================== */

.pay {
  position: relative;
  width: 508px;
  max-width: 100%;
  aspect-ratio: 1272 / 1137;
}

.pay--fill {
  width: 100%;
  max-width: none;
}

.pay__svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ---- entrance from-states, shared by the timeline and the fallback ------ */

.pay [data-pay] {
  opacity: 0;
}

.pay__card {
  transform: translate3d(0, 22px, 0);
}

.pay [data-pay="tile"],
.pay [data-pay="row"] {
  transform: translate3d(0, 14px, 0);
}

.pay [data-pay="runlabel"],
.pay [data-pay="total"],
.pay [data-pay="meta"],
.pay [data-pay="regtitle"],
.pay [data-pay="viewall"],
.pay [data-pay="more"],
.pay [data-pay="comptitle"],
.pay [data-pay="check"],
.pay [data-pay="trendtitle"],
.pay [data-pay="trendfoot"] {
  transform: translate3d(0, 8px, 0);
}

.pay [data-pay="badge"],
.pay [data-pay="cta"] {
  transform: scale(0.94);
  transform-box: fill-box;
  transform-origin: center;
}

.pay [data-pay="rule"] {
  transform: scaleX(0);
  transform-box: fill-box;
  transform-origin: left center;
}

/* Bars grow out of the baseline they already share (all six end at y 1004),
   so the row of them rises rather than each one sliding. */

.pay__bar {
  transform: scaleY(0);
  transform-box: fill-box;
  transform-origin: center bottom;
}

/* The ticks land after their row, so the compliance list reads as three checks
   completing in turn rather than one block appearing. */

.pay__tick {
  transform: scale(0);
  transform-box: fill-box;
  transform-origin: center;
}

/* ---- fallback path: IntersectionObserver adds .is-in ------------------- */

.pay.is-in [data-pay] {
  opacity: 1;
  transform: none;
  transition:
    opacity 320ms var(--ease-smooth) var(--d, 0ms),
    transform 410ms var(--ease-smooth) var(--d, 0ms);
}

.pay.is-in [data-pay="card"]       {
  --d: 0ms;
}

.pay.is-in [data-pay="runlabel"]   {
  --d: 100ms;
}

.pay.is-in [data-pay="total"]      {
  --d: 150ms;
}

.pay.is-in [data-pay="meta"]       {
  --d: 250ms;
}

.pay.is-in [data-pay="badge"]      {
  --d: 300ms;
}

.pay.is-in [data-pay="cta"]        {
  --d: 350ms;
}

.pay.is-in [data-pay="tile"]       {
  --d: calc(400ms + var(--i, 0) * 60ms);
}

.pay.is-in [data-pay="regtitle"]   {
  --d: 600ms;
}

.pay.is-in [data-pay="viewall"]    {
  --d: 640ms;
}

.pay.is-in [data-pay="row"]        {
  --d: calc(680ms + var(--i, 0) * 60ms);
}

.pay.is-in [data-pay="rule"]       {
  --d: calc(660ms + var(--i, 0) * 60ms);
}

.pay.is-in [data-pay="more"]       {
  --d: 980ms;
}

.pay.is-in [data-pay="comptitle"]  {
  --d: 640ms;
}

.pay.is-in [data-pay="check"]      {
  --d: calc(710ms + var(--i, 0) * 90ms);
}

.pay.is-in [data-pay="trendtitle"] {
  --d: 1000ms;
}

.pay.is-in [data-pay="bar"]        {
  --d: calc(1050ms + var(--i, 0) * 50ms);
}

.pay.is-in [data-pay="trendfoot"]  {
  --d: 1360ms;
}

/* A tick scales in a beat behind the line it belongs to, and the bars get a
   longer, softer climb than the generic 900ms — they are the one thing on the
   panel whose movement is the content. */

.pay.is-in .pay__tick {
  transform: scale(1);
  transition: transform 280ms var(--ease-smooth) calc(750ms + var(--i, 0) * 200ms);
}

.pay.is-in .pay__bar {
  transform: scaleY(1);
  transition:
    opacity 230ms var(--ease-smooth) var(--d, 0ms),
    transform 500ms var(--ease-smooth) var(--d, 0ms);
}

/* ==========================================================================
   PAYROLL — LIVE LAYER
   Gated behind .is-live, which js/showcase-live.js adds once the entrance has
   finished: a CSS animation outranks an inline style, so a keyframe on
   `transform` would otherwise override what GSAP writes mid-entrance.
   Timings are deliberately out of step with one another, so the panel never
   reads as one thing ticking.
   ========================================================================== */

/* run approved — the pill holds a soft glow and its dot breathes */

@keyframes pay-badge {
  0%, 100% {
    fill: #E7F7F0;
  }

  50%      {
    fill: #DBF3E8;
  }
}

@keyframes pay-appdot {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }

  50%      {
    opacity: 0.55;
    transform: scale(0.84);
  }
}

.pay.is-live .pay__badge {
  animation: pay-badge 4.3s ease-in-out infinite;
}

.pay.is-live .pay__appdot {
  transform-box: fill-box;
  transform-origin: center;
  animation: pay-appdot 2.6s ease-in-out infinite;
}

/* payment status — green reads as settled, amber as still waiting, so the
   amber one runs quicker and travels further */

@keyframes pay-dot {
  0%, 72%, 100% {
    transform: scale(1);
    opacity: 1;
  }

  84%           {
    transform: scale(1.28);
    opacity: 0.7;
  }
}

@keyframes pay-dot-warn {
  0%, 100% {
    transform: scale(1);
    opacity: 1;
  }

  50%      {
    transform: scale(1.22);
    opacity: 0.62;
  }
}

.pay.is-live .pay__dot {
  transform-box: fill-box;
  transform-origin: center;
  animation: pay-dot 5.6s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.55s);
}

.pay.is-live .pay__dot--warn {
  animation: pay-dot-warn 2.2s ease-in-out infinite;
}

/* compliance ticks keep the faintest afterglow of having just landed */

@keyframes pay-tick {
  0%, 82%, 100% {
    transform: scale(1);
  }

  90%           {
    transform: scale(1.09);
  }
}

.pay.is-live .pay__tick {
  animation: pay-tick 6.2s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.7s);
}

/* Travelling highlights. Each is clipped to its own surface and carries its
   own --from/--to, so a sweep covers that surface and no more. */

@keyframes pay-shine {
  0%        {
    transform: translateX(var(--from, -180px));
  }

  55%, 100% {
    transform: translateX(var(--to, 400px));
  }
}

.pay__shine {
  opacity: 0;
}

.pay.is-live .pay__shine {
  opacity: 1;
  animation: pay-shine 5.4s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.5s);
}

/* the CTA is the one thing waiting on the reader, so it sweeps oftenest */

.pay.is-live [data-pay="cta"] .pay__shine {
  animation-duration: 3.2s;
}

/* the register's sweep is the "occasionally" one — long cycle, faint gradient */

.pay.is-live .pay__shine--soft {
  animation-duration: 9.5s;
}

/* the three tiles sweep in the order they filled */

.pay.is-live [data-pay="tile"] .pay__shine {
  animation-duration: 6.4s;
  animation-delay: calc(var(--i, 0) * 0.45s);
}

/* ---- hold everything while the showcase has this step crossfaded out --- */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .sc-panel:not(.is-showing) .pay__badge,
.sc-panel:not(.is-showing) .pay__appdot,
.sc-panel:not(.is-showing) .pay__dot,
.sc-panel:not(.is-showing) .pay__tick,
.sc-panel:not(.is-showing) .pay__shine {
    animation-play-state: paused;
  }
}

/* ---- no motion: the finished dashboard, holding still ------------------ */

@media (prefers-reduced-motion: reduce) {
  .pay [data-pay] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .pay__tick {
    transform: scale(1) !important;
  }

  .pay__bar  {
    transform: scaleY(1) !important;
  }

  .pay__badge,
  .pay__appdot,
  .pay__dot,
  .pay__tick,
  .pay__shine {
    animation: none !important;
  }

  .pay__shine {
    opacity: 0;
  }
}

/* ==========================================================================
   PERFORMANCE  (showcase panel 05 — "Growth, measured")
   --------------------------------------------------------------------------
   The artwork is the project's own hand-authored SVG, inlined by
   includes/performance-ui.php so CSS can reach inside it. Nothing in the
   interface is restyled here — every rule below is either an entrance
   from-state or a continuous effect, and no value, label or colour is touched.
   The SVG scales through its viewBox, so there is no `cqw` sizing to keep in
   step.

   SVG note: `transform` on an SVG child resolves in the user coordinate space,
   and `transform-origin` defaults to the origin of that space rather than the
   element. `transform-box: fill-box` scopes it back to the shape — which is
   also why the ring sheen can spin about the ring's centre without knowing the
   centre: a circle's fill box is centred on it.
   ========================================================================== */

.prf {
  position: relative;
  width: 508px;
  max-width: 100%;
  aspect-ratio: 1272 / 1137;
}

.prf--fill {
  width: 100%;
  max-width: none;
}

.prf__svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ---- entrance from-states, shared by the timeline and the fallback ------ */

.prf [data-prf] {
  opacity: 0;
}

.prf__card {
  transform: translate3d(0, 22px, 0);
}

.prf [data-prf="kpi"] {
  transform: translate3d(0, 18px, 0);
}

.prf [data-prf="obj"],
.prf [data-prf="objtitle"],
.prf [data-prf="objq2"],
.prf [data-prf="charttitle"],
.prf [data-prf="chartmeta"],
.prf [data-prf="revtitle"],
.prf [data-prf="revsub"],
.prf [data-prf="achtitle"],
.prf [data-prf="kpisub"],
.prf [data-prf="ringnum"],
.prf [data-prf="ringlabel"] {
  transform: translate3d(0, 8px, 0);
}

/* the achievements slide in from their own side of the card */

.prf [data-prf="ach"] {
  transform: translate3d(14px, 0, 0);
}

.prf [data-prf="badge"] {
  transform: translate3d(0, 10px, 0);
}

.prf [data-prf="rule"] {
  transform: scaleX(0);
  transform-box: fill-box;
  transform-origin: left center;
}

.prf [data-prf="ringtrack"] {
  transform: scale(0.92);
  transform-box: fill-box;
  transform-origin: center;
}

.prf__fill {
  transform: scaleX(0);
  transform-box: fill-box;
  transform-origin: left center;
}

.prf__icon {
  transform: scale(0);
  transform-box: fill-box;
  transform-origin: center;
}

/* The line is drawn rather than faded. pathLength="1" in the markup normalises
   it, so one dash the length of the whole path retracts to nothing without
   anyone having to measure the geometry. */

.prf__line {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

/* The area is revealed through a clip that opens left to right, in step with
   the line, so the fill never runs ahead of the stroke drawing it. */

.prf__reveal {
  transform: scaleX(0);
  transform-box: fill-box;
  transform-origin: left center;
}

.prf__dot {
  opacity: 0;
  transform: scale(0);
  transform-box: fill-box;
  transform-origin: center;
}

/* 477.5 is the ring's dash — its true circumference, 2π × 76 — so offsetting
   by the whole of it genuinely leaves nothing drawn. It did not use to: the
   dash was 439, which is 2πr for the wrong radius, and the shortfall stayed
   painted as a stub at the top of the ring. See the note on the circle in
   includes/performance-ui.php. */

.prf__ring {
  stroke-dashoffset: 477.5;
}

/* ---- fallback path: IntersectionObserver adds .is-in ------------------- */

.prf.is-in [data-prf] {
  opacity: 1;
  transform: none;
  transition:
    opacity 320ms var(--ease-smooth) var(--d, 0ms),
    transform 410ms var(--ease-smooth) var(--d, 0ms);
}

.prf.is-in [data-prf="card"]       {
  --d: 0ms;
}

.prf.is-in [data-prf="kpi"]        {
  --d: calc(80ms + var(--i, 0) * 50ms);
}

.prf.is-in [data-prf="kpisub"]     {
  --d: calc(280ms + var(--i, 0) * 50ms);
}

.prf.is-in [data-prf="badge"]      {
  --d: 290ms;
}

.prf.is-in [data-prf="objtitle"]   {
  --d: 330ms;
}

.prf.is-in [data-prf="objq2"]      {
  --d: 350ms;
}

.prf.is-in [data-prf="rule"]       {
  --d: 370ms;
}

.prf.is-in [data-prf="obj"]        {
  --d: calc(430ms + var(--i, 0) * 60ms);
}

.prf.is-in [data-prf="revtitle"]   {
  --d: 380ms;
}

.prf.is-in [data-prf="ringtrack"]  {
  --d: 440ms;
}

.prf.is-in [data-prf="ringnum"]    {
  --d: 500ms;
}

.prf.is-in [data-prf="ringlabel"]  {
  --d: 1250ms;
}

.prf.is-in [data-prf="revsub"]     {
  --d: 1340ms;
}

.prf.is-in [data-prf="charttitle"] {
  --d: 770ms;
}

.prf.is-in [data-prf="chartmeta"]  {
  --d: 800ms;
}

.prf.is-in [data-prf="achtitle"]   {
  --d: 980ms;
}

.prf.is-in [data-prf="ach"]        {
  --d: calc(1040ms + var(--i, 0) * 70ms);
}

/* A bar sweeps out over its own, longer climb, on the beat its row arrives. */

.prf.is-in .prf__fill {
  transform: scaleX(1);
  transition: transform 550ms var(--ease-smooth) calc(430ms + var(--i, 0) * 130ms);
}

/* An icon lands a beat behind the row it belongs to. */

.prf.is-in .prf__icon {
  transform: scale(1);
  transition: transform 250ms var(--ease-smooth) calc(1090ms + var(--i, 0) * 150ms);
}

/* Ring, line and area all run long — they are the panel's content, not its
   packaging, and the numbers are counted against these same timings. */

.prf.is-in .prf__ring {
  stroke-dashoffset: 57.3;
  /* 12 % of 477.5 — the 88 % the label counts to */
  transition: stroke-dashoffset 730ms var(--ease-smooth) 500ms;
}

.prf.is-in .prf__line {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 590ms cubic-bezier(0.4, 0, 0.2, 1) 1800ms;
}

.prf.is-in .prf__reveal {
  transform: scaleX(1);
  transition: transform 590ms cubic-bezier(0.4, 0, 0.2, 1) 1800ms;
}

.prf.is-in .prf__dot {
  opacity: 1;
  transform: scale(1);
  transition:
    opacity 180ms var(--ease-smooth) 1390ms,
    transform 240ms var(--ease-smooth) 1390ms;
}

/* ==========================================================================
   PERFORMANCE — LIVE LAYER
   Gated behind .is-live, which js/showcase-live.js adds once the entrance has
   finished: a CSS animation outranks an inline style, so a keyframe on
   `transform` would otherwise override what GSAP writes mid-entrance. Timings
   are deliberately out of step, so the panel never reads as one thing ticking.
   ========================================================================== */

/* ▲ 12% — the one figure that is a claim about direction, so it breathes */

@keyframes prf-badge {
  0%, 100% {
    fill: #E7F7F0;
  }

  50%      {
    fill: #DBF3E8;
  }
}

.prf.is-live .prf__badge {
  animation: prf-badge 4.6s ease-in-out infinite;
}

/* the head of the growth line */

@keyframes prf-dot {
  0%, 100% {
    transform: scale(1);
  }

  50%      {
    transform: scale(1.14);
  }
}

.prf.is-live .prf__dot {
  animation: prf-dot 3.4s ease-in-out infinite;
}

/* One short dash of white going round the finished ring. It rides the same
   circle as the progress arc, so it can only ever trace the shape already
   there — and it turns about its own centre, which is the ring's. */

@keyframes prf-ringsheen {
  0%   {
    transform: rotate(-90deg);
  }

  100% {
    transform: rotate(270deg);
  }
}

.prf__ringsheen {
  opacity: 0;
}

.prf.is-live .prf__ringsheen {
  opacity: 1;
  transform-box: fill-box;
  transform-origin: center;
  animation: prf-ringsheen 7.5s linear infinite;
  transition: opacity 270ms var(--ease-smooth) 180ms;
}

/* Travelling highlights across the finished blue bars, and one slow pass over
   the achievements card. Each is clipped to its own surface and carries its
   own --from/--to, so a sweep covers that surface and no more. The amber bar
   has none — it is meant to read differently. */

@keyframes prf-shine {
  0%        {
    transform: translateX(var(--from, -140px));
  }

  55%, 100% {
    transform: translateX(var(--to, 640px));
  }
}

.prf__shine {
  opacity: 0;
}

.prf.is-live .prf__shine {
  opacity: 1;
  animation: prf-shine 6.2s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.55s);
}

.prf.is-live .prf__shine--card {
  animation-duration: 9s;
}

/* ---- hold everything while the showcase has this step crossfaded out --- */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .sc-panel:not(.is-showing) .prf__badge,
.sc-panel:not(.is-showing) .prf__dot,
.sc-panel:not(.is-showing) .prf__ringsheen,
.sc-panel:not(.is-showing) .prf__shine {
    animation-play-state: paused;
  }
}

/* ---- no motion: the finished dashboard, holding still ------------------ */

@media (prefers-reduced-motion: reduce) {
  .prf [data-prf] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .prf__fill   {
    transform: scaleX(1) !important;
  }

  .prf__reveal {
    transform: scaleX(1) !important;
  }

  .prf__icon   {
    transform: scale(1) !important;
  }

  .prf__dot    {
    opacity: 1 !important;
    transform: scale(1) !important;
  }

  .prf__line   {
    stroke-dashoffset: 0 !important;
  }

  .prf__ring   {
    stroke-dashoffset: 57.3 !important;
  }

  .prf__badge,
  .prf__dot,
  .prf__ringsheen,
  .prf__shine {
    animation: none !important;
  }

  .prf__shine,
  .prf__ringsheen {
    opacity: 0;
  }
}

/* ==========================================================================
   SITE FOOTER  (sections/site-footer.php)
   --------------------------------------------------------------------------
   Four zones stacked on a near-black ground, each separated by a hairline: the
   sitemap grid, the download routes, the ways to reach us, and the closing
   bar. Nothing is boxed and nothing is a rail — the width belongs to whichever
   zone is using it.

   Hand-authored rather than composed from Tailwind utilities: css/style.css is
   committed as generated output and this repo has no build step, so a utility
   class not already used elsewhere would simply be absent from the file.
   ========================================================================== */

.sf {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background-color: #0A0713;
  padding-top: 64px;
  /* Zero, so the wordmark below the closing bar reaches the true foot of the
     document and its cut edge IS the last pixel of the page. This used to be
     84px — 42px cluster + 20px inset + breathing room — to stop the floating
     contact cluster covering "Cancellation Policy". The legal row is no longer
     the last thing down here, so the cluster now floats over the wordmark,
     which is decorative and does not mind. See .fab. */
  padding-bottom: 0;
}

/* A single soft wash across the top, so the footer lifts off the section above
   it without needing a border to say where it starts. */

.sf::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 0;
  z-index: -1;
  height: 420px;
  background:
    radial-gradient(80% 100% at 22% 0%, rgba(37, 99, 235, 0.22), transparent 70%),
    radial-gradient(70% 100% at 78% 0%, rgba(59, 130, 246, 0.12), transparent 70%);
}

@media (min-width: 768px) {
  .sf {
    padding-top: 84px;
    /* Zero for the same reason as the base rule: the wordmark is the last thing
       on the page now and its cut edge should be the last pixel. This was 104px
       to clear the floating contact cluster. */
    padding-bottom: 0;
  }
}

/* ---- 1 · sitemap ------------------------------------------------------- */

.sf__groups {
  display: grid;
  align-items: start;
  gap: 44px 28px;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 640px) {
  .sf__groups {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Three tracks for three columns, deliberately uneven, and the ratios come from
   the widest label each one has to carry rather than from taste. Measured at
   16px: the two-up Niyuk HR list needs 211px a side ("Visitor Management
   System"), column two needs 181px ("Recruitment Automation") and column three
   needs 256px ("Niyuk Recruit Vs Ceipal TalentHire"). Add the 56px fold and the
   32px that separates a column from its rule and the floor is 512 / 213 / 256,
   against a budget of 1133 at a 1261px viewport — so these shares clear every
   label on one line and put most of the slack where the fold is. */

@media (min-width: 1024px) {
  .sf__groups {
    grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr) minmax(0, 1.15fr);
    align-items: stretch;
    gap: 52px 32px;
  }
}

/* A column stacks its groups, which is what puts Alternatives under Niyuk
   Recruit rather than wrapping it onto a row of its own. $FOOTER_COLS has
   always been shaped this way — one entry per column, holding its groups in
   order — so what sits under what is decided in the config, not here. */

.sf__col {
  display: flex;
  flex-direction: column;
  gap: 44px;
}

@media (min-width: 1024px) {
  .sf__col {
    gap: 52px;
  }
}

/* The column carrying the long list takes the extra track and sets that list
   in two — below the breakpoint it is an ordinary column, single file. */

@media (min-width: 640px) {
  .sf__col--wide {
    grid-column: span 2;
  }

  .sf__list--split {
    -moz-columns: 2;
         columns: 2;
  }

  /* A link must not be torn across the fold. */

  .sf__list--split li {
    -moz-column-break-inside: avoid;
         break-inside: avoid;
  }

  /* …and the fold itself goes where the data says, not where balancing puts
     it. See split_after in $FOOTER_COLS. */

  .sf__list--split .sf__break {
    -moz-column-break-before: column;
         break-before: column;
  }
}

/* Three hairline-separated columns, and the divider runs the full height of the
   row rather than stopping at the foot of a short column — which is why the
   grid stretches its items here instead of the `align-items: start` the
   narrower layouts use. A .sf__col is a flex column, so its groups still sit at
   the top of the track it has been given.

   The border goes on the track's trailing edge with matching padding, so there
   is the same 32px of air on either side of every rule.

   AFTER the 640px block above on purpose. A media query adds no specificity, so
   between two rules that both match it is source order that decides, and
   `grid-column: span 2` there would otherwise beat the reset here and give the
   Niyuk HR column two of the four tracks. */
@media (min-width: 1024px) {
  .sf__col--wide {
    grid-column: auto;
  }

  .sf__col:not(:last-child) {
    border-inline-end: 1px solid rgba(255, 255, 255, 0.09);
    padding-inline-end: 32px;
  }
}

/* A hairline over a group that does not follow on from the one above it. See
   'rule' in $FOOTER_COLS — opt-in, because a second group in a column usually
   reads as a continuation and wants only the gap. It spans the column's content
   box, so it stops short of the vertical divider rather than running into it. */
.sf__group--rule {
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  padding-top: 44px;
}

@media (min-width: 1024px) {
  .sf__group--rule {
    padding-top: 52px;
  }
}

.sf__head {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #3B82F6;
}

.sf__list {
  margin-top: 22px;
  display: flex;
  flex-direction: column;
  gap: 15px;
}

/* Multi-column needs block flow, not flex, to break at all.

   The column gap lives here rather than up in the 640px block with `columns: 2`
   where it belongs, because `.sf__list` below sets `gap: 15px` — a shorthand,
   so it writes column-gap too — and both selectors are one class. A media query
   adds no specificity, so the later rule won and the fold was 15px however wide
   the declaration up there said it was. This rule comes after `.sf__list`, so
   this is the value that lands. */

.sf__list--split {
  display: block;
  -moz-column-gap: 56px;
       column-gap: 56px;
}

.sf__list--split li + li {
  margin-top: 15px;
}

/* Hover and keyboard focus draw an underline as well as lifting the colour.
   Asked for on 2026-09-02: #DEDAE6 to #FFFFFF on its own is a change of about
   8% lightness, which is not enough to tell a reader the row is a link at all.

   The rule is always underlined and the colour of the underline is what
   changes, so nothing reflows on hover — an underline that appears on hover
   moves the line it is under by its own thickness, and in a column of fifteen
   that reads as a twitch.

   :focus-visible, not :focus, so a mouse click does not leave the underline
   stuck on after the pointer has gone. */

.sf__list a {
  font-size: 16px;
  line-height: 1.35;
  color: #DEDAE6;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: color 300ms var(--ease-soft), text-decoration-color 300ms var(--ease-soft);
}

.sf__list a:hover,
.sf__list a:focus-visible {
  color: #FFFFFF;
  text-decoration-color: currentColor;
}

.sf__more,
.sf__solo {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #FFFFFF;
  transition: gap 300ms var(--ease-smooth);
}

.sf__more {
  margin-top: 20px;
  font-size: 15px;
  font-weight: 500;
}

.sf__solo {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.sf__more:hover,
.sf__solo:hover {
  gap: 14px;
}

.sf__more-arrow {
  height: 15px;
  width: 15px;
}

.sf__solo-arrow {
  height: 16px;
  width: 16px;
}

/* ---- 2 · downloads ----------------------------------------------------- */

.sf__strip {
  margin-top: 56px;
  display: grid;
  gap: 32px;
  grid-template-columns: minmax(0, 1fr);
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  padding-top: 40px;
}

@media (min-width: 900px) {
  .sf__strip {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.sf__cell .sf__head {
  margin-bottom: 16px;
}

.sf__row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.sf__store,
.sf__chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background-color: rgba(255, 255, 255, 0.04);
  color: #FFFFFF;
  transition:
    transform 300ms var(--ease-smooth),
    border-color 300ms var(--ease-soft),
    background-color 300ms var(--ease-soft);
}

.sf__store:hover,
.sf__chip:hover {
  transform: translateY(-2px);
  border-color: rgba(255, 255, 255, 0.28);
  background-color: rgba(255, 255, 255, 0.09);
}

.sf__store {
  padding: 8px 14px 8px 11px;
}

.sf__chip {
  padding: 11px 16px;
  font-size: 15px;
  font-weight: 500;
}

/* The Launchpad is the one thing here that is an offer rather than a download,
   so it keeps the brand edge it had. */

.sf__chip--brand {
  border-color: rgba(143, 125, 228, 0.55);
  background-color: rgba(37, 99, 235, 0.16);
}

.sf__chip--brand:hover {
  border-color: rgba(143, 125, 228, 0.9);
  background-color: rgba(37, 99, 235, 0.26);
}

.sf__store-mark {
  height: 24px;
  width: 24px;
  flex: none;
}

/* Google's mark keeps its own four colours — flattening it to currentColor
   would make it unreadable. */

.sf__store-mark--play path:nth-child(1) {
  fill: #00D0FF;
}

.sf__store-mark--play path:nth-child(2) {
  fill: #FFC900;
}

.sf__store-mark--play path:nth-child(3) {
  fill: #FF3A44;
}

.sf__store-mark--play path:nth-child(4) {
  fill: #00E5A0;
}

.sf__store-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.sf__store-kicker {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.72);
}

.sf__store-name {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.sf__chip-arrow {
  height: 14px;
  width: 14px;
  color: rgba(255, 255, 255, 0.6);
}

.sf__chip-mark {
  height: 18px;
  width: 18px;
  flex: none;
  color: #4285F4;
}

.sf__chip-mark--bulb {
  color: #34D399;
}

/* ---- 3 · reach us ------------------------------------------------------ */

.sf__reach {
  margin-top: 40px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  padding-top: 32px;
}

@media (min-width: 900px) {
  .sf__reach {
    flex-direction: row;
    align-items: center;
  }
}

.sf__chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 22px;
}

.sf__iconset {
  display: flex;
  align-items: center;
  gap: 10px;
}

.sf__iconset a {
  display: grid;
  height: 40px;
  width: 40px;
  place-items: center;
  border-radius: 11px;
  background-color: rgba(255, 255, 255, 0.07);
  color: #FFFFFF;
  transition:
    transform 300ms var(--ease-smooth),
    background-color 300ms var(--ease-soft);
}

.sf__iconset a:hover {
  transform: translateY(-2px);
  background-color: rgba(255, 255, 255, 0.16);
}

.sf__icon {
  height: 17px;
  width: 17px;
}

.sf__contact {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 28px;
}

.sf__contact-item {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 15px;
  color: #DEDAE6;
  transition: color 300ms var(--ease-soft);
}

a.sf__contact-item:hover {
  color: #FFFFFF;
}

.sf__contact-i {
  height: 17px;
  width: 17px;
  flex: none;
  color: #8B8399;
}

/* ---- 4 · closing bar --------------------------------------------------- */

.sf__bar {
  margin-top: 32px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  padding-top: 26px;
}

@media (min-width: 768px) {
  .sf__bar {
    flex-direction: row;
    align-items: center;
  }
}

.sf__mark {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 18px;
}

.sf__logo {
  width: auto;
  height: 26px;
  /* The wordmark is authored in near-black for the light navbar; this is the
     same file inverted rather than a second copy to keep in step. */
  filter: brightness(0) invert(1);
}

.sf__copy {
  font-size: 14px;
  color: rgba(222, 218, 230, 0.55);
}

.sf__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 22px;
}

.sf__legal a {
  font-size: 14px;
  color: rgba(222, 218, 230, 0.72);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: color 300ms var(--ease-soft), text-decoration-color 300ms var(--ease-soft);
}

.sf__legal a:hover,
.sf__legal a:focus-visible {
  color: #FFFFFF;
  text-decoration-color: currentColor;
}

@media (prefers-reduced-motion: reduce) {
  .sf__store,
  .sf__chip,
  .sf__iconset a,
  .sf__more,
  .sf__solo,
  .sf__list a,
  .sf__legal a {
    transition: none;
  }

  .sf__store:hover,
  .sf__chip:hover,
  .sf__iconset a:hover {
    transform: none;
  }
}

/* ==========================================================================
   CRM / ATS  (showcase panel 06 — "Pipeline, end to end")
   --------------------------------------------------------------------------
   The artwork is the project's own hand-authored SVG, inlined by
   includes/crm-ui.php so CSS can reach inside it. Nothing in the interface is
   restyled here — every rule below is either an entrance from-state or a
   continuous effect, and no name, count, label or colour is touched. The SVG
   scales through its viewBox, so there is no `cqw` sizing to keep in step.

   SVG note: `transform` on an SVG child resolves in the user coordinate space,
   and `transform-origin` defaults to the origin of that space rather than the
   element. `transform-box: fill-box` scopes it back to the shape.
   ========================================================================== */

.crm {
  position: relative;
  width: 508px;
  max-width: 100%;
  aspect-ratio: 1272 / 1137;
}

.crm--fill {
  width: 100%;
  max-width: none;
}

.crm__svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ---- entrance from-states, shared by the timeline and the fallback ------ */

.crm [data-crm] {
  opacity: 0;
}

.crm [data-crm="title"],
.crm [data-crm="sub"],
.crm [data-crm="clienttitle"],
.crm [data-crm="crmlink"],
.crm [data-crm="colhead"],
.crm [data-crm="hiredlabel"],
.crm [data-crm="clientsub"] {
  transform: translate3d(0, 8px, 0);
}

.crm [data-crm="cta"] {
  transform: scale(0.94);
  transform-box: fill-box;
  transform-origin: center;
}

/* The columns rise as boards; the chips inside them arrive after, so the board
   is built before it is filled. */

.crm [data-crm="col"] {
  transform: translate3d(0, 20px, 0);
}

.crm [data-crm="card"] {
  transform: translate3d(0, 20px, 0);
}

.crm [data-crm="chip"] {
  transform: translate3d(0, 12px, 0);
}

.crm [data-crm="client"] {
  transform: translate3d(0, 12px, 0);
}

.crm [data-crm="colrule"],
.crm [data-crm="clientrule"] {
  transform: scaleX(0);
  transform-box: fill-box;
  transform-origin: left center;
}

/* The card in motion, its badge and its arrow are the panel's subject, so they
   land last and from further away than anything around them. */

.crm [data-crm="live"] {
  transform: translate3d(0, 16px, 0) scale(0.96);
  transform-box: fill-box;
  transform-origin: center;
}

.crm [data-crm="score"] {
  transform: scale(0.7);
  transform-box: fill-box;
  transform-origin: center;
}

.crm [data-crm="arrow"] {
  transform: translate3d(-10px, 0, 0);
}

.crm__tick {
  transform: scale(0);
  transform-box: fill-box;
  transform-origin: center;
}

.crm__init {
  transform: scale(0.6);
  transform-box: fill-box;
  transform-origin: center;
}

/* ---- fallback path: IntersectionObserver adds .is-in ------------------- */

.crm.is-in [data-crm] {
  opacity: 1;
  transform: none;
  transition:
    opacity 320ms var(--ease-smooth) var(--d, 0ms),
    transform 410ms var(--ease-smooth) var(--d, 0ms);
}

.crm.is-in [data-crm="title"]       {
  --d: 80ms;
}

.crm.is-in [data-crm="sub"]         {
  --d: 130ms;
}

.crm.is-in [data-crm="cta"]         {
  --d: 190ms;
}

.crm.is-in [data-crm="col"]         {
  --d: calc(250ms + var(--i, 0) * 40ms);
}

.crm.is-in [data-crm="colhead"]     {
  --d: calc(320ms + var(--i, 0) * 40ms);
}

.crm.is-in [data-crm="colrule"]     {
  --d: calc(350ms + var(--i, 0) * 40ms);
}

/* Column then row, so the board fills the way it is read. */

.crm.is-in [data-crm="chip"]        {
  --d: calc(410ms + var(--c, 0) * 90ms + var(--r, 0) * 110ms);
}

.crm.is-in [data-crm="live"]        {
  --d: 690ms;
}

.crm.is-in [data-crm="score"]       {
  --d: 800ms;
}

.crm.is-in [data-crm="arrow"]       {
  --d: 850ms;
}

.crm.is-in [data-crm="hiredlabel"]  {
  --d: calc(710ms + var(--i, 0) * 100ms);
}

.crm.is-in [data-crm="card"]        {
  --d: 930ms;
}

.crm.is-in [data-crm="clienttitle"] {
  --d: 970ms;
}

.crm.is-in [data-crm="clientrule"]  {
  --d: 1000ms;
}

.crm.is-in [data-crm="crmlink"]     {
  --d: 1030ms;
}

.crm.is-in [data-crm="client"]      {
  --d: calc(1050ms + var(--i, 0) * 70ms);
}

.crm.is-in [data-crm="clientsub"]   {
  --d: calc(1120ms + var(--i, 0) * 70ms);
}

/* The badge lands with a little more spring than anything else on the panel —
   it is the one number a recruiter is looking for. */

.crm.is-in [data-crm="score"] {
  transition:
    opacity 180ms var(--ease-smooth) 800ms,
    transform 280ms cubic-bezier(0.34, 1.56, 0.64, 1) 1760ms;
}

.crm.is-in .crm__tick {
  transform: scale(1);
  transition: transform 250ms cubic-bezier(0.34, 1.56, 0.64, 1)
              calc(1420ms + var(--i, 0) * 220ms);
}

.crm.is-in .crm__init {
  transform: scale(1);
  transition: transform 240ms var(--ease-smooth)
              calc(1090ms + var(--i, 0) * 150ms);
}

/* ==========================================================================
   CRM / ATS — LIVE LAYER
   Gated behind .is-live, which js/showcase-live.js adds once the entrance has
   finished: a CSS animation outranks an inline style, so a keyframe on
   `transform` would otherwise override what GSAP writes mid-entrance. Nothing
   here loops on the same clock as anything beside it — a board where every
   chip breathed together would read as a screensaver, not a system.
   ========================================================================== */

/* the card in motion keeps a soft glow under it */

@keyframes crm-glow {
  0%, 100% {
    opacity: 0.16;
  }

  50%      {
    opacity: 0.34;
  }
}

.crm__glow {
  opacity: 0;
}

.crm.is-live .crm__glow {
  animation: crm-glow 4.2s ease-in-out infinite;
}

/* Score 82 */

@keyframes crm-score {
  0%, 100% {
    transform: scale(1);
  }

  50%      {
    transform: scale(1.06);
  }
}

.crm.is-live [data-crm="score"] {
  transform-box: fill-box;
  transform-origin: center;
  animation: crm-score 2.9s ease-in-out infinite;
}

/* The arrow nudges forward and the dashed run flows under it, so the candidate
   reads as moving on without the card ever leaving the Interview column. */

@keyframes crm-arrow {
  0%, 100% {
    transform: translateX(0);
  }

  50%      {
    transform: translateX(4px);
  }
}

@keyframes crm-dash {
  0%   {
    stroke-dashoffset: 0;
  }

  100% {
    stroke-dashoffset: -24;
  }
}

.crm.is-live [data-crm="arrow"] {
  animation: crm-arrow 2.4s ease-in-out infinite;
}

.crm.is-live .crm__dash {
  animation: crm-dash 1.6s linear infinite;
}

/* Avatars breathe in turn rather than together, and only every few seconds. */

@keyframes crm-av {
  0%, 84%, 100% {
    transform: scale(1);
    opacity: 1;
  }

  92%           {
    transform: scale(1.12);
    opacity: 0.82;
  }
}

.crm.is-live .crm__av {
  transform-box: fill-box;
  transform-origin: center;
  animation: crm-av 7.4s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.85s);
}

/* the one on the live card is on its own, quicker clock */

.crm.is-live .crm__av--live {
  animation-duration: 4.6s;
  animation-delay: 0s;
}

/* hired cards hold a slow success glow, and their ticks settle */

@keyframes crm-hired {
  0%, 100% {
    opacity: 1;
  }

  50%      {
    opacity: 0.9;
  }
}

@keyframes crm-tick {
  0%, 86%, 100% {
    transform: scale(1);
  }

  93%           {
    transform: scale(1.1);
  }
}

.crm.is-live .crm__hired {
  animation: crm-hired 6.6s ease-in-out infinite;
  animation-delay: calc(var(--r, 0) * 0.8s);
}

.crm.is-live .crm__tick {
  animation: crm-tick 6.8s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.9s);
}

/* Open CRM reads as the one thing on the strip you can press */

@keyframes crm-link {
  0%, 100% {
    opacity: 1;
  }

  50%      {
    opacity: 0.68;
  }
}

.crm.is-live .crm__crmlink {
  animation: crm-link 3.8s ease-in-out infinite;
}

/* Travelling highlights. Each is clipped to its own surface and carries its
   own --from/--to, so a sweep covers that surface and no more. */

@keyframes crm-shine {
  0%        {
    transform: translateX(var(--from, -160px));
  }

  55%, 100% {
    transform: translateX(var(--to, 200px));
  }
}

.crm__shine {
  opacity: 0;
}

.crm.is-live .crm__shine {
  opacity: 1;
  animation: crm-shine 5.6s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.7s);
}

/* the card in motion sweeps oftenest; the placeholder chips are the "long
   intervals" ones and must never coincide with each other */

.crm.is-live .crm__shine--live {
  animation-duration: 3.4s;
}

.crm.is-live .crm__shine--slow {
  animation-duration: 11s;
  animation-delay: calc(2s + var(--i, 0) * 4.5s);
}

.crm.is-live .crm__shine--green {
  animation-duration: 8.5s;
  animation-delay: calc(1.5s + var(--i, 0) * 2.2s);
}

/* ---- hold everything while the showcase has this step crossfaded out --- */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .sc-panel:not(.is-showing) .crm__glow,
.sc-panel:not(.is-showing) [data-crm="score"],
.sc-panel:not(.is-showing) [data-crm="arrow"],
.sc-panel:not(.is-showing) .crm__dash,
.sc-panel:not(.is-showing) .crm__av,
.sc-panel:not(.is-showing) .crm__hired,
.sc-panel:not(.is-showing) .crm__tick,
.sc-panel:not(.is-showing) .crm__crmlink,
.sc-panel:not(.is-showing) .crm__shine {
    animation-play-state: paused;
  }
}

/* ---- no motion: the finished board, holding still ---------------------- */

@media (prefers-reduced-motion: reduce) {
  .crm [data-crm] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .crm__tick {
    transform: scale(1) !important;
  }

  .crm__init {
    transform: scale(1) !important;
  }

  .crm__glow,
  .crm [data-crm="score"],
  .crm [data-crm="arrow"],
  .crm__dash,
  .crm__av,
  .crm__hired,
  .crm__tick,
  .crm__crmlink,
  .crm__shine {
    animation: none !important;
  }

  .crm__shine,
  .crm__glow {
    opacity: 0;
  }
}

/* ==========================================================================
   HRMS  (showcase panel 07 — "All of HR, one place")
   --------------------------------------------------------------------------
   The artwork is the project's own hand-authored SVG, inlined by
   includes/hrms-ui.php so CSS can reach inside it. Nothing in the interface is
   restyled here — every rule below is either an entrance from-state or a
   continuous effect, and no name, figure, label or colour is touched. The SVG
   scales through its viewBox, so there is no `cqw` sizing to keep in step.

   SVG note: `transform` on an SVG child resolves in the user coordinate space,
   and `transform-origin` defaults to the origin of that space rather than the
   element. `transform-box: fill-box` scopes it back to the shape — which is
   also why the ring sheen can spin about the ring's centre without knowing the
   centre: a circle's fill box is centred on it.
   ========================================================================== */

.hrm {
  position: relative;
  width: 508px;
  max-width: 100%;
  aspect-ratio: 1272 / 1137;
}

.hrm--fill {
  width: 100%;
  max-width: none;
}

/* The same opt-in for the helpdesk queue, so it can fill a showcase frame. */
.hdk--fill {
  width: 100%;
  max-width: none;
}

.hrm__svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* ---- entrance from-states, shared by the timeline and the fallback ------ */

.hrm [data-hrm] {
  opacity: 0;
}

.hrm__card {
  transform: translate3d(0, 20px, 0);
}

.hrm [data-hrm="name"],
.hrm [data-hrm="meta"],
.hrm [data-hrm="stat"],
.hrm [data-hrm="atttitle"],
.hrm [data-hrm="attmonth"],
.hrm [data-hrm="daylabel"],
.hrm [data-hrm="legend"],
.hrm [data-hrm="leavetitle"],
.hrm [data-hrm="leaverow"],
.hrm [data-hrm="ringnum"],
.hrm [data-hrm="ringlabel"],
.hrm [data-hrm="teamtitle"],
.hrm [data-hrm="teamcount"],
.hrm [data-hrm="member"],
.hrm [data-hrm="anatitle"],
.hrm [data-hrm="anafoot"] {
  transform: translate3d(0, 8px, 0);
}

.hrm [data-hrm="avatar"],
.hrm [data-hrm="badge"],
.hrm [data-hrm="status"],
.hrm [data-hrm="ringtrack"] {
  transform: scale(0.86);
  transform-box: fill-box;
  transform-origin: center;
}

.hrm [data-hrm="rule"] {
  transform: scaleX(0);
  transform-box: fill-box;
  transform-origin: left center;
}

.hrm__face {
  transform: scale(0.7);
  transform-box: fill-box;
  transform-origin: center;
}

/* A day fills in rather than sliding: it belongs to its square on the
   calendar, and a square that arrives from somewhere else reads as a card. */

.hrm__day {
  transform: scale(0.7);
  transform-box: fill-box;
  transform-origin: center;
}

/* The bars grow out of the baseline they already share (all five end at
   y 1008), so the row of them rises rather than each one sliding. */

.hrm__bar {
  transform: scaleY(0);
  transform-box: fill-box;
  transform-origin: center bottom;
}

/* 465 is the dash the artwork already carries, and 163 the offset it rests at.
   Offsetting by the whole dash puts the ring at zero without touching either
   number, so the arc it finishes on is the authored one to the unit. */

.hrm__ring {
  stroke-dashoffset: 465;
}

/* ---- fallback path: IntersectionObserver adds .is-in ------------------- */

.hrm.is-in [data-hrm] {
  opacity: 1;
  transform: none;
  transition:
    opacity 320ms var(--ease-smooth) var(--d, 0ms),
    transform 410ms var(--ease-smooth) var(--d, 0ms);
}

.hrm.is-in [data-hrm="card"]       {
  --d: calc(var(--i, 0) * 30ms);
}

.hrm.is-in [data-hrm="avatar"]     {
  --d: 90ms;
}

.hrm.is-in [data-hrm="name"]       {
  --d: 140ms;
}

.hrm.is-in [data-hrm="meta"]       {
  --d: 170ms;
}

.hrm.is-in [data-hrm="badge"]      {
  --d: calc(220ms + var(--i, 0) * 50ms);
}

.hrm.is-in [data-hrm="stat"]       {
  --d: calc(210ms + var(--i, 0) * 40ms);
}

.hrm.is-in [data-hrm="atttitle"]   {
  --d: 330ms;
}

.hrm.is-in [data-hrm="attmonth"]   {
  --d: 350ms;
}

.hrm.is-in [data-hrm="rule"]       {
  --d: calc(370ms + var(--i, 0) * 50ms);
}

.hrm.is-in [data-hrm="daylabel"]   {
  --d: calc(400ms + var(--i, 0) * 30ms);
}

/* Column then row, so the calendar fills the way it is read. */

.hrm.is-in [data-hrm="day"]        {
  --d: calc(450ms + var(--c, 0) * 45ms + var(--r, 0) * 90ms);
}

.hrm.is-in [data-hrm="legend"]     {
  --d: calc(770ms + var(--i, 0) * 30ms);
}

.hrm.is-in [data-hrm="leavetitle"] {
  --d: 350ms;
}

.hrm.is-in [data-hrm="ringtrack"]  {
  --d: 410ms;
}

.hrm.is-in [data-hrm="ringnum"]    {
  --d: 450ms;
}

.hrm.is-in [data-hrm="ringlabel"]  {
  --d: 1160ms;
}

.hrm.is-in [data-hrm="leaverow"]   {
  --d: calc(910ms + var(--i, 0) * 60ms);
}

.hrm.is-in [data-hrm="teamtitle"]  {
  --d: 640ms;
}

.hrm.is-in [data-hrm="teamcount"]  {
  --d: 660ms;
}

.hrm.is-in [data-hrm="member"]     {
  --d: calc(730ms + var(--i, 0) * 120ms);
}

.hrm.is-in [data-hrm="status"]     {
  --d: calc(810ms + var(--i, 0) * 120ms);
}

.hrm.is-in [data-hrm="anatitle"]   {
  --d: 650ms;
}

.hrm.is-in [data-hrm="bar"]        {
  --d: calc(710ms + var(--i, 0) * 50ms);
}

.hrm.is-in [data-hrm="anafoot"]    {
  --d: 1450ms;
}

/* A face lands with its row; a day pops rather than eases, which is what makes
   28 of them read as filling in instead of drifting in. */

.hrm.is-in .hrm__face {
  transform: scale(1);
  transition: transform 240ms var(--ease-smooth) calc(730ms + var(--i, 0) * 260ms);
}

.hrm.is-in .hrm__day {
  transform: scale(1);
  transition: transform 210ms cubic-bezier(0.34, 1.4, 0.64, 1)
              calc(1000ms + var(--c, 0) * 45ms + var(--r, 0) * 90ms);
}

/* Ring and bars run long — they are the panel's content, not its packaging,
   and the leave figure is counted against these same timings. */

.hrm.is-in .hrm__ring {
  stroke-dashoffset: 163;
  transition: stroke-dashoffset 680ms var(--ease-smooth) 450ms;
}

.hrm.is-in .hrm__bar {
  transform: scaleY(1);
  transition:
    opacity 230ms var(--ease-smooth) var(--d, 0ms),
    transform 500ms var(--ease-smooth) var(--d, 0ms);
}

/* ==========================================================================
   HRMS — LIVE LAYER
   Gated behind .is-live, which js/showcase-live.js adds once the entrance has
   finished: a CSS animation outranks an inline style, so a keyframe on
   `transform` would otherwise override what GSAP writes mid-entrance. Nothing
   here loops on the same clock as anything beside it.
   ========================================================================== */

/* the one day off — it is the exception on the calendar, so it is the one
   square that keeps moving */

@keyframes hrm-leave {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }

  50%      {
    opacity: 0.86;
    transform: scale(1.05);
  }
}

.hrm.is-live .hrm__day--leave {
  transform-box: fill-box;
  transform-origin: center;
  animation: hrm-leave 3.6s ease-in-out infinite;
}

/* the two remote days breathe together, softly and slowly */

@keyframes hrm-remote {
  0%, 100% {
    opacity: 1;
  }

  50%      {
    opacity: 0.72;
  }
}

.hrm.is-live .hrm__day--remote {
  animation: hrm-remote 5.2s ease-in-out infinite;
}

/* availability badges */

@keyframes hrm-status {
  0%, 100% {
    opacity: 1;
  }

  50%      {
    opacity: 0.72;
  }
}

.hrm.is-live .hrm__status {
  animation: hrm-status 4.4s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 1.1s);
}

/* the profile badges hold the faintest glow */

@keyframes hrm-badge {
  0%, 100% {
    opacity: 1;
  }

  50%      {
    opacity: 0.84;
  }
}

.hrm.is-live .hrm__badge {
  animation: hrm-badge 6.2s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.9s);
}

/* One dash of white going round the finished ring. It rides the same circle as
   the progress arc, so it can only ever trace the shape already there — and it
   turns about its own centre, which is the ring's. Slow enough at twelve
   seconds to read as an occasional pass rather than a spinner. */

@keyframes hrm-ringsheen {
  0%   {
    transform: rotate(-90deg);
  }

  100% {
    transform: rotate(270deg);
  }
}

.hrm__ringsheen {
  opacity: 0;
}

.hrm.is-live .hrm__ringsheen {
  opacity: 1;
  transform-box: fill-box;
  transform-origin: center;
  animation: hrm-ringsheen 12s linear infinite;
  transition: opacity 270ms var(--ease-smooth) 180ms;
}

/* the lead bar stays the focus of the chart */

@keyframes hrm-lead {
  0%, 100% {
    opacity: 1;
  }

  50%      {
    opacity: 0.88;
  }
}

.hrm.is-live .hrm__bar--lead {
  animation: hrm-lead 4.8s ease-in-out infinite;
}

/* Travelling highlights, each clipped to its own surface and carrying its own
   --from/--to so a sweep covers that surface and no more. */

@keyframes hrm-shine {
  0%        {
    transform: translateX(var(--from, -160px));
  }

  55%, 100% {
    transform: translateX(var(--to, 300px));
  }
}

.hrm__shine {
  opacity: 0;
}

.hrm.is-live .hrm__shine {
  opacity: 1;
  animation: hrm-shine 6.4s ease-in-out infinite;
}

/* the calendar's pass is the "very subtle occasional" one */

.hrm.is-live .hrm__shine--grid {
  animation-duration: 10.5s;
  animation-delay: 2.5s;
}

/* ---- hold everything while the showcase has this step crossfaded out --- */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .sc-panel:not(.is-showing) .hrm__day--leave,
.sc-panel:not(.is-showing) .hrm__day--remote,
.sc-panel:not(.is-showing) .hrm__status,
.sc-panel:not(.is-showing) .hrm__badge,
.sc-panel:not(.is-showing) .hrm__ringsheen,
.sc-panel:not(.is-showing) .hrm__bar--lead,
.sc-panel:not(.is-showing) .hrm__shine {
    animation-play-state: paused;
  }
}

/* ---- no motion: the finished dashboard, holding still ------------------ */

@media (prefers-reduced-motion: reduce) {
  .hrm [data-hrm] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .hrm__day  {
    transform: scale(1) !important;
  }

  .hrm__face {
    transform: scale(1) !important;
  }

  .hrm__bar  {
    transform: scaleY(1) !important;
  }

  .hrm__ring {
    stroke-dashoffset: 163 !important;
  }

  .hrm__day--leave,
  .hrm__day--remote,
  .hrm__status,
  .hrm__badge,
  .hrm__ringsheen,
  .hrm__bar--lead,
  .hrm__shine {
    animation: none !important;
  }

  .hrm__shine,
  .hrm__ringsheen {
    opacity: 0;
  }
}

/* ==========================================================================
   HERO SHOT — ADDITIVE LAYER  (sections/hero.php)
   --------------------------------------------------------------------------
   A second live layer over hero-dashboard.webp, alongside the "Today's hours"
   widget and the 06:06 dial above.

   Everything here is ADDITIVE: a translucent sheen, or a soft glow, painted on
   top of the artwork. Nothing has to match a local background, so the shot is
   the untouched screenshot at rest and stays pixel-identical if the artwork is
   ever re-exported. That is the whole reason this layer does sweeps and glows
   and not entrance reveals — the sidebar, the task rows, the checkboxes and
   the avatars are baked pixels, and revealing one would mean covering it in
   its own background colour first, which only works where that background is
   flat (as it is for the dial).

   Geometry is a percentage of the image box, so the layer rides the shot's
   0.64 → 1 scroll-grow and its float with no JS syncing — both are transforms
   on ancestors. Radii are in `cqw` off .shot-fx for the same reason.
   1 cqw = 1 % of the shot = 20 image px.

   Measured off the artwork itself, in its own 2000 × 1214 pixels:
     search bar      x  502..1812  y   29.. 88
     reward points   x 1592..1962  y  118..206
     Clock Out       x  451.. 651  y  600..666
     holiday card 1  x 1494..1930  y  390..488
     holiday card 2  x 1494..1930  y  498..588
     quick actions   x  454.. 673 / 697.. 919 / 943..1162 / 1186..1405
                     y  906..1072  (all four)
     clocked-in dot  centre (621, 526)   r  6.5
     inbox tick      centre (1190, 550)  r 31
     inbox badge     x  309.. 342  y  234..259

   Plain CSS rather than @apply, so the block is identical in input.css and
   style.css and needs no Tailwind recompile.
   ========================================================================== */

/* ---- sheens ------------------------------------------------------------ */

.shot-sheen {
  position: absolute;
  left: var(--l);
  top: var(--t);
  width: var(--w);
  height: var(--h);
  border-radius: var(--r, 0.8cqw);
  overflow: hidden;
  /* .reveal owns the fade in; this only has to not fight it. */
  will-change: opacity;
}

.shot-sheen::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    transparent 34%,
    rgba(255, 255, 255, 0.62) 50%,
    transparent 66%
  );
  transform: translate3d(-130%, 0, 0);
}

/* One pass, then a long wait — 9s with the sweep over in the first fifth, so
   any given card catches the light about as often as a real one would. The
   per-element --dly in the markup keeps them off each other's clock. */

.shot-sheen.is-visible::after {
  animation: shot-pass 9s var(--ease-smooth) var(--dly, 0s) infinite;
}

@keyframes shot-pass {
  0%        {
    transform: translate3d(-130%, 0, 0);
  }

  20%, 100% {
    transform: translate3d(130%, 0, 0);
  }
}

/* The Clock Out button is the one control on the card that is waiting on the
   reader, so it catches the light oftener and a little brighter. */

.shot-sheen--cta::after {
  background: linear-gradient(
    100deg,
    transparent 34%,
    rgba(255, 255, 255, 0.5) 50%,
    transparent 66%
  );
}

.shot-sheen--cta.is-visible::after {
  animation-duration: 5.5s;
}

/* ---- glows ------------------------------------------------------------- */

.shot-glow {
  position: absolute;
  left: var(--l);
  top: var(--t);
  width: var(--w);
  height: var(--h);
  border-radius: 100px;
  will-change: opacity;
}

/* Inbox cleared — a soft ring of the tick's own green, breathing. */

.shot-glow--tick {
  background: radial-gradient(
    closest-side,
    rgba(16, 185, 129, 0.28),
    rgba(16, 185, 129, 0.08) 62%,
    transparent 78%
  );
}

.shot-glow--tick.is-visible {
  animation: shot-breathe 4.6s var(--ease-smooth) 400ms infinite;
}

/* The clocked-in dot. Small and quick — it is a heartbeat, not a halo. */

.shot-glow--dot {
  background: radial-gradient(
    closest-side,
    rgba(34, 197, 94, 0.55),
    rgba(34, 197, 94, 0.12) 55%,
    transparent 74%
  );
}

.shot-glow--dot.is-visible {
  animation: shot-breathe 2.6s ease-in-out infinite;
}

/* The sidebar's unread count. It sits on the near-black rail, so the glow is
   the badge's own pink and only shows for a beat — "pulse once at intervals"
   rather than a steady throb. */

.shot-glow--badge {
  border-radius: 100px;
  background: radial-gradient(
    closest-side,
    rgba(244, 63, 94, 0.5),
    rgba(244, 63, 94, 0.14) 60%,
    transparent 78%
  );
}

.shot-glow--badge.is-visible {
  animation: shot-blip 6.4s ease-in-out 1s infinite;
}

@keyframes shot-breathe {
  0%, 100% {
    opacity: 0.35;
    transform: scale(0.94);
  }

  50%      {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes shot-blip {
  0%, 74%, 100% {
    opacity: 0;
    transform: scale(0.9);
  }

  82%           {
    opacity: 0.95;
    transform: scale(1.06);
  }

  90%           {
    opacity: 0.2;
    transform: scale(1);
  }
}

/* Below md the whole shot is small enough that any of this would be a smudge —
   .shot-fx is already display:none there, so this is only a note that the
   breakpoint above governs this layer too. */

@media (prefers-reduced-motion: reduce) {
  .shot-sheen.is-visible::after,
  .shot-glow.is-visible {
    animation: none;
  }

  /* Left at rest rather than hidden: the glows are part of how the card reads
     when it is finished, they just stop moving. */

  .shot-sheen::after {
    opacity: 0;
  }

  .shot-glow {
    opacity: 0.55;
  }
}

/* ==========================================================================
   FOUNDER'S NOTE  (sections/founder-note.php)
   --------------------------------------------------------------------------
   A letter on a pale card, with the hero's meadow rising into its bottom-right
   corner. Palette is the site's own — surface for the card, ink for the
   headings, muted for the prose — so it belongs to this page.

   The card clips: the photograph is sized past the corner and the card's
   overflow trims it to the radius, which is what gives the meadow its
   curved edge instead of a rectangle sitting on top.

   Hand-authored rather than composed from Tailwind utilities: css/style.css is
   committed as generated output and this repo has no build step, so a utility
   class not already used elsewhere would simply be absent from the file.
   ========================================================================== */

/* The section's own 70 above and below, met by the neighbouring section's 70,
   put about 140px of white on each side of a card that is one short letter.
   50 on phones, where that white is a bigger share of the screen than it is on
   a laptop. The id beats .section on specificity, so this holds wherever it
   sits in the file. */

@media (max-width: 767px) {
  #founder-note {
    padding-top: 50px;
    padding-bottom: 50px;
  }
}

.fn {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: 30px;
  background-color: #EDF1F4;
  padding: 30px 24px 32px;
}

@media (min-width: 768px) {
  .fn {
    padding: 44px 48px 44px;
  }
}

@media (min-width: 1024px) {
  .fn {
    padding: 52px 72px 52px;
  }
}

/* ---- head -------------------------------------------------------------- */

.fn__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
}

.fn__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 28px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: #1D1D1D;
}

@media (min-width: 768px) {
  .fn__title {
    font-size: 36px;
  }
}

.fn__kicker {
  margin-top: 8px;
  font-size: 17px;
  font-weight: 500;
  color: #4D585F;
}

@media (min-width: 768px) {
  .fn__kicker {
    font-size: 19px;
  }
}

/* The dashed frame with the thumbnail inset — the border is the frame, the
   padding is the mount, so the picture never touches the dashes. */

.fn__frame {
  display: grid;
  flex: none;
  place-items: center;
  width: 84px;
  height: 84px;
  padding: 6px;
  border: 1.5px dashed #B7C2CE;
  border-radius: 18px;
}

@media (min-width: 768px) {
  .fn__frame {
    width: 108px;
    height: 108px;
    padding: 7px;
    border-radius: 22px;
  }
}

.fn__frame img {
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  border-radius: 13px;
}

/* The mark is a logo, not a photograph: it is contained on white rather than
   cropped to fill, or it would be cut off at its own edges. */

.fn__frame--mark {
  /* The dashed mount is the reference's own detail and is kept — only what
     sits in it changes. */
  background-color: #FFFFFF;
}

.fn__frame--mark img {
  width: 62%;
  height: 62%;
  -o-object-fit: contain;
     object-fit: contain;
  border-radius: 0;
}

/* ---- letter ------------------------------------------------------------ */

.fn__body {
  /* Narrow enough that the prose clears the meadow rather than relying on
     the paragraph happening to be short. The photograph is 50 % wide with a
     2 % overhang, so on a 1200 card its left edge is at x 624; 520 puts the
     text column's right edge at 592. */
  max-width: 520px;
  margin-top: 26px;
}

@media (min-width: 1024px) {
  .fn__body {
    margin-top: 34px;
  }
}

.fn__body p {
  font-size: 17px;
  line-height: 1.62;
  color: #3F4A55;
}

@media (min-width: 768px) {
  .fn__body p {
    font-size: 19px;
    line-height: 1.65;
  }
}

.fn__body p + p {
  margin-top: 18px;
}

/* Phone sizes for the card. The heading ran at 28 and everything under it at
   17, which on a 390px screen put "Why We Built Niyuk" on two lines and left
   the note nearly the same weight as its own title.

   Black rather than the greys they carry on desktop. The meadow crosses the
   foot of the card at this width, and #3F4A55 over it was the part of this
   that was actually hard to read. */

@media (max-width: 767px) {
  .fn__title {
    font-size: 20px;
  }

  .fn__kicker {
    font-size: 15px;
    color: #1D1D1D;
  }

  .fn__body p {
    font-size: 15px;
    color: #1D1D1D;
  }
}

/* ---- the meadow -------------------------------------------------------- */

.fn__grass {
  position: absolute;
  right: -2%;
  bottom: -1px;
  /* kills the hairline the browser can leave under a
                        scaled image sitting exactly on the card's edge */
  z-index: -1;
  width: 46%;
  height: auto;
  pointer-events: none;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  /* The PNG has a straight left edge. In the hero that edge is off-screen, but
     here it falls inside the card and reads as a seam, so it is dissolved into
     the ground over the first fifth of the image. */
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 20%);
  mask-image: linear-gradient(to right, transparent 0%, #000 20%);
}

/* No meadow on a phone. It ran as a band along the foot of the card at 55%
   opacity, on the reasoning that a narrow card leaves it nowhere to sit but
   under the letter. That is the problem rather than the solution: .fn__body is
   capped at 520px so the prose clears the picture on a wide card, and there is
   no width left to clear it in at this size, so the band crossed both
   paragraphs. Hidden below 768, which is where the card's type steps down too.

   display: none rather than opacity: 0 — the image is decorative and
   aria-hidden, so there is nothing to keep in the layout for. */

@media (max-width: 767px) {
  .fn__grass {
    display: none;
  }
}

/* ---- ambient ------------------------------------------------------------
   Both effects are gated on .reveal-done, which animations.js adds 900ms after
   an element has revealed. That matters: .reveal.is-visible sets `transform`,
   and an animation on the same property would override it mid-fade and the
   entrance would jump. Waiting until the entrance is over means the two never
   touch the same frame.
   ------------------------------------------------------------------------ */

/* The meadow drifts, the way the hero's shot does — same fx-float keyframes,
   just slower and shorter, so it reads as a breeze rather than a bob. */

.fn__grass.reveal-done {
  --float-y: -7px;
  animation: fx-float 9s ease-in-out infinite;
}

/* And light crosses the card every so often. It sits at z-index -1, so it
   passes over the ground and the meadow but never over the type — a sheen
   washing across the prose would be a readability bug, not an effect. */

.fn::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent 38%,
    rgba(255, 255, 255, 0.5) 50%,
    transparent 62%
  );
  transform: translate3d(-130%, 0, 0);
}

/* Long cycle, and the pass itself is over in the first sixth of it. No class
   gate on this one: unlike the meadow, the card is not a .reveal, so there is
   no transform of its own for the animation to fight. */

.fn::after {
  animation: fn-sheen 12s var(--ease-smooth) 1.2s infinite;
}

@keyframes fn-sheen {
  0%        {
    transform: translate3d(-130%, 0, 0);
  }

  16%, 100% {
    transform: translate3d(130%, 0, 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .fn__grass.reveal-done {
    animation: none;
  }

  .fn::after {
    animation: none;
    opacity: 0;
  }
}

/* ==========================================================================
   FLOATING CONTACT SHORTCUTS  (includes/footer.php)
   --------------------------------------------------------------------------
   The three shortcuts that used to sit in the footer's "reach us" row, pinned
   to the bottom-right corner instead so they are reachable from anywhere on
   the page.

   Dark chips rather than the translucent ones they were in the footer: there
   they sat on a near-black ground and could borrow it, but floating they pass
   over whatever the page happens to be — mostly white sections — and a
   translucent white chip would disappear against them.

   z-index 40 puts them under the navbar (50) and the skip link (100), so
   neither can be covered by something that is on screen permanently.
   ========================================================================== */

.fab {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 40;
}

@media (min-width: 768px) {
  .fab {
    right: 28px;
    bottom: 28px;
  }
}

.fab ul {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Two element types wear this chip. The calendar shortcut is a <button>: it
   opens the booking panel on this page rather than navigating, and a link that
   does not navigate is a lie told to the keyboard and to a middle click. The
   other two are real links and stay links. */

.fab a,
.fab button {
  display: grid;
  height: 46px;
  width: 46px;
  place-items: center;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background-color: #16161E;
  color: #FFFFFF;
  box-shadow:
    0 2px 6px rgba(10, 12, 24, 0.18),
    0 12px 28px -8px rgba(10, 12, 24, 0.32);
  transition:
    transform 300ms var(--ease-smooth),
    background-color 300ms var(--ease-soft);
}

.fab a:hover,
.fab button:hover {
  transform: translateY(-3px);
  background-color: #22222E;
}

.fab__icon {
  height: 20px;
  width: 20px;
}

/* ---- a colour per shortcut ----

   The glyphs are single-colour and inherit currentColor, so this is `color` on
   the chip rather than a fill on the SVG. The tile stays #16161E for all three
   — three coloured tiles in a row would read as a toolbar of buttons rather
   than as three quiet shortcuts.

   Checked against the tile and its hover, both: WhatsApp green is 9.1:1,
   Niyuk's blue 3.5:1 and the violet 5.3:1, so all three clear 3:1 for a
   graphic against its ground. #4632B4 was the other candidate for the
   calendar and is 2.0:1 on this tile, which is why it is not used.

   The class is named for the icon, not the position, so reordering
   $FOOTER_ACTIONS cannot mis-colour them. */

/* ---- the label on hover ----

   Drawn from data-tip rather than the browser's own `title`, which waits about
   a second, cannot be styled, and never appears for a keyboard. This shows on
   focus as well as hover, so tabbing to a chip says what it is.

   Above the chip, and anchored by its RIGHT edge rather than centred: the
   cluster is fixed 20px from the right of the screen, and "Schedule a meeting"
   is about three times the width of the 46px chip it belongs to — centred, it
   would run off the edge of the page. Extending leftward it crosses only the
   empty space above the neighbouring chips.

   pointer-events: none so the label can never sit between the pointer and the
   chip it is describing. */

.fab [data-tip] {
  position: relative;
}

.fab [data-tip]::after {
  content: attr(data-tip);
  position: absolute;

  /* Centred over the chip. The 50% is of the chip's PADDING box, which the 1px
     border keeps half a pixel off true; translateX(-50%) is of the label's own
     width, so the pair lands it centred to within that half pixel. */
  left: 50%;

  bottom: calc(100% + 10px);
  z-index: 1;

  padding: 7px 11px;
  border-radius: 9px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background-color: #16161E;
  box-shadow: 0 10px 24px -12px rgba(10, 12, 24, 0.55);

  font-size: 12.5px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  color: #FFFFFF;

  opacity: 0;
  transform: translate(-50%, 4px);
  pointer-events: none;
  transition:
    opacity 200ms var(--ease-soft),
    transform 200ms var(--ease-smooth);
}

.fab [data-tip]:hover::after,
.fab [data-tip]:focus-visible::after {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* ---- the last chip is the exception ----

   Centred, "Schedule a meeting" would hang 21px past the right of the screen
   on a desktop and 29px on a phone: the label is 143px wide and its chip's
   centre sits only 51px from the edge. So this one hangs from its right edge
   instead. The other two clear the edge by a wide margin and stay centred. */

.fab li:last-child [data-tip]::after {
  left: auto;
  right: -1px;
  transform: translateY(4px);
}

.fab li:last-child [data-tip]:hover::after,
.fab li:last-child [data-tip]:focus-visible::after {
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .fab [data-tip]::after { transition: none; }
}

/* WhatsApp's own green. The one mark here that belongs to somebody else and
   is recognised by its colour. */
.fab .fab--whatsapp { color: #25D366; }

/* A lighter blue than the buttons' #2563EB, asked for on 2026-09-03. These
   three marks sit on a near-black tile, and the button blue is dark enough
   against it that the envelope read as the dimmest of the three next to
   WhatsApp's green and the booking violet. */
.fab .fab--mail     { color: #7FA7FF; }

/* The booking shortcut. Violet from the brand's own set, so the three are
   three hues rather than two blues and a green. */
.fab .fab--calendar { color: #8F7DE4; }

/* Tighter on phones, where the cluster is competing with the content for a
   narrow screen rather than sitting in a wide margin. */

@media (max-width: 639px) {
  .fab ul {
    gap: 8px;
  }

  .fab a {
    height: 42px;
    width: 42px;
    border-radius: 12px;
  }

  .fab__icon {
    height: 18px;
    width: 18px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .fab a {
    transition: none;
  }

  .fab a:hover {
    transform: none;
  }
}

/* ==========================================================================
   INTEGRATIONS CARD  (sections/integrations.php)
   --------------------------------------------------------------------------
   The scenic artwork fills the card instead of sitting in flow as a band along
   its foot. Being out of flow it no longer sets the card's height, so the card
   sets its own — that is all .integ-card is for.

   The art is 2422 x 638 (3.8:1) against a card nearer 1.9:1, so covering it
   crops the sides. Anchored to the bottom so the hills stay grounded and the
   crop comes out of the sky, where there is nothing to lose.

   Hand-authored rather than utilities: `object-bottom` and the arbitrary
   min-heights are not in the built stylesheet, and this repo has no build step.
   ========================================================================== */

.integ-card {
  min-height: 200px;
  padding-top: 53px;
  padding-bottom: 50px;
}

.integ-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  height: 100%;
  width: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  /* Anchored to the TOP of the artwork, so the scene starts from its top edge
     rather than its foot.

     Worth knowing when tuning: this only bites while the card is WIDER in
     proportion than the artwork (2422 x 638, so 3.8:1). Above that the cover
     fit matches the card's height exactly and the crop is entirely horizontal,
     which leaves nothing for a vertical anchor to move. Take the card down to
     a shallow band and the crop flips to vertical — and then `top` is what
     shows the misty top of the scene instead of the grass. */
  -o-object-position: center top;
     object-position: center top;
  pointer-events: none;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}

/* The hills rise behind the copy once the artwork fills the frame, so the top
   of the card keeps its own ground and the scene fades up into it. Same colour
   as the card, so it reads as the card rather than as a wash laid over it. */

.integ-card::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 0;
  z-index: 1;
  height: 62%;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    #EDF1F4 0%,
    #EDF1F4 42%,
    rgba(237, 241, 244, 0.86) 62%,
    rgba(237, 241, 244, 0) 100%
  );
}

/* ==========================================================================
   SOLUTIONS  (sections/solutions.php)
   --------------------------------------------------------------------------
   Six cards scattered around a centred heading. The scatter is a grid with
   per-card offsets rather than absolute positioning, so the block reflows to
   two columns and then one without any of it having to be re-placed.

   Three colourways. The icon's circle inverts against its card so a glyph is
   never dark-on-dark, and the marks themselves are flattened to one colour —
   they ship multi-coloured, and a red bolt beside a pink heart beside a green
   shield would read as clip art rather than a set.

   Hand-authored rather than utilities: css/style.css is committed as generated
   output and this repo has no build step, so a utility class not already used
   elsewhere would simply be absent from the file.
   ========================================================================== */

/* Kept after the grid was returned to the content column: card 1 carries a
   negative top margin, and the scatter scales and rotates the cards, so this
   is the guard against a stray pixel becoming horizontal scroll. */

/* clip, not hidden. Both stop a stray pixel of the scatter becoming horizontal
   scroll, but `hidden` makes this a scroll container and position: sticky on
   .sol__stage would silently stop pinning. `clip` does not, and leaves the
   y axis visible so the pin still works. */

#solutions {
  overflow-x: clip;
  /* A soft white gradient rather than a flat slab: pure white through the top
     two thirds, easing into a cool tint at the foot. It gives the section a
     lit-from-above feel and softens the join with the flat-white integrations
     section below.

     One-directional, and that is forced rather than chosen. The pale cards
     (#EDF1F4, cards 1 and 3) carry no border, so the background is the only
     thing separating them from the page, and against white that edge is
     already just a 1.136 contrast ratio. Measured, those cards span 2% to 19%
     of the section — there is no clear band above them to tint. A top stop of
     #F6F9FC took them to 1.075, halving an edge that was faint to begin with,
     so the top stays white.

     Downward there is real room: every card ends by 54% in the three-column
     layout, and the ramp is gentle enough that a card as low as 65% — where
     the two-column layout puts card 3 — still sits on #FDFEFF, a 1.13 ratio.

     background-color from .bg-white stays as the fallback beneath this. */
  background-image: linear-gradient(
    180deg,
    #FFFFFF 0%,
    #FFFFFF 58%,
    #FAFCFE 76%,
    #EDF3F9 100%
  );
}

@media (min-width: 768px) {
  /* .section pays 100px here; the block has to fit a screen, so it does not. */

  #solutions {
    padding-top: 54px;
    padding-bottom: 54px;
  }
}

/* --------------------------------------------------------------------------
   SOLUTIONS — PIN
   The stage sticks under the navbar while the track scrolls past it, holding
   the assembled block for the surplus height.

   Two guards, both necessary:

   min-width  below 1024 the grid is one or two columns, the scatter is off,
              and there is nothing composed to hold.
   min-height the block is ~650px. Pinned under a 72px navbar it needs a
              viewport of about 760px to show in full; on anything shorter the
              bottom row would sit below the fold for the whole pin, which is
              worse than not pinning at all.
   -------------------------------------------------------------------------- */

@media (min-width: 1024px) and (min-height: 760px) {
  .sol__track {
    /* One stage plus the travel. The surplus IS the hold. */
    height: calc(100vh - var(--nav-h) + 70vh);
  }

  .sol__stage {
    position: sticky;
    top: var(--nav-h);
    display: flex;
    align-items: center;
    min-height: calc(100vh - var(--nav-h));
  }

  /* The stage is doing the vertical centring now, so the section's own padding
     would only push the block off centre. */

  #solutions {
    padding-top: 0;
    padding-bottom: 0;
  }
}

.sol__grid {
  display: grid;
  gap: 20px;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 640px) {
  .sol__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .sol__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    /* Split: the columns still want air, the rows do not — the row gap is
       what pushes the cards away from the heading. */
    -moz-column-gap: 28px;
         column-gap: 28px;
    row-gap: 10px;
  }

  /* The copy is first in the source, for reading order on a phone. Here it
     goes back to the middle row, between the two halves of the set. */

  .sol__copy      {
    grid-column: 1 / -1;
    grid-row: 2;
  }

  .sol__card:nth-of-type(1) {
    grid-column: 1;
    grid-row: 1;
  }

  .sol__card:nth-of-type(2) {
    grid-column: 2;
    grid-row: 1;
  }

  .sol__card:nth-of-type(3) {
    grid-column: 3;
    grid-row: 1;
  }

  .sol__card:nth-of-type(4) {
    grid-column: 1;
    grid-row: 3;
  }

  .sol__card:nth-of-type(5) {
    grid-column: 2;
    grid-row: 3;
  }

  .sol__card:nth-of-type(6) {
    grid-column: 3;
    grid-row: 3;
  }

  /* The scatter: the middle of each row sits lower, the outer two higher, so
     the set reads as placed rather than tabulated. Margin, not transform —
     transform is what .reveal animates and what the drift below uses. */

  /* Every card on its own line, none of them level with a neighbour. The
     outer two of each row ride high and low respectively so the middle of the
     block stays open for the heading. */

  .sol__card:nth-of-type(1) {
    margin-top: -14px;
  }

  .sol__card:nth-of-type(2) {
    margin-top: 16px;
  }

  .sol__card:nth-of-type(3) {
    margin-top: -6px;
  }

  .sol__card:nth-of-type(4) {
    margin-top: 12px;
  }

  .sol__card:nth-of-type(5) {
    margin-top: 18px;
  }

  .sol__card:nth-of-type(6) {
    margin-top: 2px;
  }
}

/* ---- centre copy ------------------------------------------------------- */

.sol__copy {
  padding: 12px 0;
  text-align: center;
}

@media (min-width: 1024px) {
  /* Top and bottom are different numbers because they are not measuring the
     same thing: below, the headline's line box already ends well short of its
     descenders, so it needs less padding to sit the same distance off the
     lower row. Tuned until the measured gaps above and below match. */

  .sol__copy {
    padding: 26px 0 40px;
  }
}

.sol__title {
  margin-top: 16px;
  margin-inline: auto;
  max-width: 620px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 32px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: #1D1D1D;
}

@media (min-width: 768px) {
  .sol__title {
    font-size: 44px;
  }
}

/* 60px is the target size; the two steps below it exist so the line does not
   arrive at full size on a screen too narrow to hold it. */

@media (min-width: 1024px) {
  .sol__title {
    font-size: 60px;
    /* Widened with the size so the line breaks in two, not three. At 620px the
       60px setting put "HR" alone on a third line. 780px is the smallest that
       gives "A Complete AI powered / Solution for HR"; the override is scoped
       to this breakpoint so the 44px and 32px steps keep their own measure. */
    max-width: 780px;
  }
}

/* ---- cards ------------------------------------------------------------- */

.sol__card {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-radius: 24px;
  padding: 22px;
}

@media (min-width: 768px) {
  .sol__card {
    min-height: 184px;
    padding: 20px 22px;
  }
}

.sol__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.sol__name {
  /* The stylesheet sets a colour on h1-h5 directly, and a direct rule always
     beats an inherited one — so without this the card's white never reaches
     its own heading and the dark tones render near-black on near-black. */
  color: inherit;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 20px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

/* The description sits at the foot of the card, the way the reference puts its
   figure there — so the cards agree along a line even when the titles run to
   different lengths. */

.sol__text {
  margin-top: auto;
  padding-top: 16px;
  font-size: 15px;
  line-height: 1.5;
}

.sol__mark {
  display: grid;
  height: 44px;
  width: 44px;
  flex: none;
  place-items: center;
  border-radius: 999px;
}

.sol__mark img {
  height: 20px;
  width: 20px;
}

/* ---- colourways -------------------------------------------------------- */

.sol__card--pale {
  background-color: #EDF1F4;
  color: #1D1D1D;
}

.sol__card--pale .sol__text  {
  color: #4D585F;
}

.sol__card--pale .sol__mark  {
  background-color: #3B82F6;
}

/* brightness(0) crushes the mark to black, invert(1) lifts it to white —
   between them any source colour ends up as one flat tone. */

.sol__card--pale .sol__mark img {
  filter: brightness(0) invert(1);
}

.sol__card--dark {
  background-color: #16161E;
  color: #FFFFFF;
}

.sol__card--dark .sol__text  {
  color: rgba(255, 255, 255, 0.68);
}

.sol__card--dark .sol__mark  {
  background-color: #FFFFFF;
}

.sol__card--dark .sol__mark img {
  filter: brightness(0);
}

.sol__card--blue {
  background-color: #3B82F6;
  color: #FFFFFF;
}

.sol__card--blue .sol__text  {
  color: rgba(255, 255, 255, 0.78);
}

.sol__card--blue .sol__mark  {
  background-color: #16161E;
}

.sol__card--blue .sol__mark img {
  filter: brightness(0) invert(1);
}

/* ---- after the entrance -------------------------------------------------
   Nothing. Measured off the reference: its cards animate in once and then
   hold — sampling their transforms across 1200px of scroll returns `none`
   at every position, so there is no drift and no scroll parallax to match.
   An earlier pass here had them floating on independent clocks; it looked
   pleasant but it was not what the design does, so it came out.
   ------------------------------------------------------------------------ */

/* ---- scroll-driven scatter ----------------------------------------------
   The cards assemble themselves out of the middle of the block as the section
   rises up the viewport. js/solutions-scatter.js measures how far each card
   sits from the centre and writes it on as --dx/--dy plus a --tilt; per frame
   it updates one number, --p, on the grid. Everything below interpolates off
   those, so a frame costs one custom-property write rather than six transform
   strings, and the transform never leaves the compositor.

   Scoped to .is-scatter, which the script only adds at >=1024px with motion
   allowed — so with JS off, on a phone, or under reduced motion this whole
   block is inert and the cards keep the ordinary staggered reveal.

   Three classes deep on purpose: it has to outrank .reveal.is-visible, which
   would otherwise pin transform and opacity at their finished values.
   ------------------------------------------------------------------------ */

.sol__grid.is-scatter .sol__card {
  transform:
    translate3d(
      calc(var(--dx, 0px) * (1 - var(--lp, 0))),
      calc(var(--dy, 0px) * (1 - var(--lp, 0))),
      0
    )
    rotate(calc(var(--tilt, 0deg) * (1 - var(--lp, 0))))
    scale(calc(0.88 + 0.12 * var(--lp, 0)));
  opacity: calc(0.45 + 0.55 * var(--lp, 0));
  /* .reveal carries a 700/800ms transition. Against a value that is already
     changing every frame it would smear the motion a beat behind the scroll,
     so scroll-driven means no transition. */
  transition: none;
  will-change: transform, opacity;
}

/* Stacked in reading order while they overlap, so the pile has a front and a
   back instead of whatever the paint order happens to be. */

.sol__grid.is-scatter .sol__card:nth-of-type(1) {
  z-index: 1;
}

.sol__grid.is-scatter .sol__card:nth-of-type(2) {
  z-index: 2;
}

.sol__grid.is-scatter .sol__card:nth-of-type(3) {
  z-index: 3;
}

.sol__grid.is-scatter .sol__card:nth-of-type(4) {
  z-index: 4;
}

.sol__grid.is-scatter .sol__card:nth-of-type(5) {
  z-index: 5;
}

.sol__grid.is-scatter .sol__card:nth-of-type(6) {
  z-index: 6;
}

/* The heading sits over the pile while the cards are still gathered on it. */

.sol__grid.is-scatter .sol__copy {
  position: relative;
  z-index: 7;
}

/* ==========================================================================
   HERO BACKDROP VIDEO
   Sits over the still inside .hero__bg, filling the same box. The still is
   never removed — it is the poster and the fallback, and it is what shows
   under reduced motion.
   ========================================================================== */

.hero__bg-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  /* Matches the still's object-top: both are anchored to the sky so the
     horizon lands in the same place whichever one is on screen. */
  -o-object-position: top center;
     object-position: top center;
  pointer-events: none;
}

/* iOS Safari paints its own grey start-playback button over an inline video
   whenever it refuses to autoplay — Low Power Mode and Low Data Mode both do
   that, and no amount of `muted`/`playsinline` overrides them. This video is
   pure decoration sitting behind the hero copy, so that button is never
   something to press: it lands mid-headline and reads as a broken embed. Hide
   the control and the still underneath stays on screen instead, which is the
   fallback this layer was built around. */
.hero__bg-video::-webkit-media-controls-start-playback-button,
.hero__bg-video::-webkit-media-controls {
  display: none !important;
  -webkit-appearance: none;
}

/* Phones get the still and nothing else. The loop is scene-setting rather
   than information, and on a phone it costs a video download on a mobile
   connection, decoding on the weakest CPUs, and — whenever iOS declines to
   autoplay — that grey start-playback button sitting on top of the headline.
   hero-bg.webp is already the poster, so dropping the video here changes
   nothing about what the hero looks like. Matches Tailwind's md breakpoint,
   which is where the hero switches to its two-column layout.
   js/animations.js quiets it as well, for the same reason it does under
   reduced motion: display: none does not stop a video downloading. */
@media (max-width: 767.98px) {
  .hero__bg-video {
    display: none;
  }
}

/* Motion the reader has asked not to see. Hiding it also stops it being
   composited; js/animations.js pauses playback and drops the buffer so it is
   not being decoded behind a hidden element either. */

@media (prefers-reduced-motion: reduce) {
  .hero__bg-video {
    display: none;
  }
}

/* ==========================================================================
   HERO HEADING
   A three-beat entrance for the h1, then two quiet loops that keep it alive.

   The entrance is the site's own .load-in — rise, fade, and the cube's slight
   scale-up — with a blur laid over the top, so each word resolves INTO focus
   instead of only sliding into place. That is the whole trick; there is no new
   timeline and no JavaScript, because .load-in is already released by
   .is-loaded at DOMContentLoaded, which for an above-the-fold hero is the same
   instant the section first appears.

   Timing: words at 160 / 260 / 360 ms, transform 820 ms. The last word lands
   at ~1.18 s, so the line is complete inside the 1–1.5 s budget. The glow and
   the float both start after that and never announce themselves.

   Ordering note: these rules must stay AFTER the .load-in block they extend —
   `.hero-word` and `.load-in` have identical specificity, so this only wins on
   source order.
   ========================================================================== */

.hero-word {
  filter: blur(var(--load-blur, 10px));
  /* Restated in full rather than adding a filter leg, because a second
     `transition` declaration replaces the first outright. Slightly quicker
     than the shared .load-in curve: the heading is the first thing read, and
     at 100 px a long travel reads as sluggish rather than considered. */
  transition:
    opacity 620ms var(--ease-smooth) var(--d, 0ms),
    transform 820ms var(--ease-smooth) var(--d, 0ms),
    filter 700ms var(--ease-smooth) var(--d, 0ms);
  will-change: transform, opacity, filter;
}

.is-loaded .hero-word {
  filter: blur(0);
}

/* Drop the filter once the word has arrived. `blur(0)` is not free: it keeps
   the span on its own layer and renders the glyphs through the filter path,
   which softens 100 px type against the same text painted normally. animations.js
   adds .load-done at --d + 1000 ms, comfortably past the 820 ms travel. */

.is-loaded .hero-word.load-done {
  filter: none;
  will-change: auto;
}

/* Phones carry the smallest GPUs and the largest relative type; a lighter
   blur costs less to composite and, at 52 px, reads the same. */

@media (max-width: 639px) {
  .hero-word {
    --load-blur: 7px;
  }
}

/* --------------------------------------------------------------------------
   The cube — the line's one highlighted element, so it gets the accent.

   A soft pool of light behind it, in the cube's own colour (sampled off the
   artwork: its lit faces sit around #7A98CD). It fades up only after the words
   have landed, then breathes on a slow off-beat clock.

   Fade-in is a transition on opacity; the breathe is an animation on transform.
   Deliberately two different properties — an animation always beats a
   transition on the same property, so sharing one would silently drop the
   fade.
   -------------------------------------------------------------------------- */

.hero-mark {
  position: relative;
  isolation: isolate;
}

.hero-mark::before {
  content: '';
  position: absolute;
  inset: -34%;
  z-index: 0;
  border-radius: 50%;
  background: radial-gradient(
    closest-side,
    rgba(122, 152, 205, 0.5),
    rgba(122, 152, 205, 0.16) 55%,
    rgba(122, 152, 205, 0) 76%
  );
  opacity: 0;
  transition: opacity 900ms var(--ease-soft) 1s;
  animation: hero-mark-breathe 5.5s ease-in-out 1.6s infinite alternate;
  pointer-events: none;
}

.is-loaded .hero-mark::before {
  opacity: 1;
}

/* Explicit stacking: the glow is a sibling of nothing, so without this the
   image and the pseudo-element are ordered by paint rules rather than intent. */

.hero-mark img {
  position: relative;
  z-index: 1;
}

@keyframes hero-mark-breathe {
  from {
    transform: scale(0.88);
  }

  to {
    transform: scale(1.1);
  }
}

/* --------------------------------------------------------------------------
   Ambient float on the finished line.

   4 px over 8 s — about a 25th of the cap height, and slow enough that it is
   felt rather than watched. The period is deliberately not the cube's 7 s, so
   the two never lock into a single visible bob.

   Paused until .is-loaded for the same reason .fx-float is: the animation
   clock starts at element creation, and an unpaused float would be part-way
   through its curve before the words had finished arriving.
   -------------------------------------------------------------------------- */

.hero-title {
  font-size: clamp(28px, 5.5vw, 70px);
  line-height: clamp(34px, 6vw, 75px);
  margin-top: clamp(30px, 6vw, 80px);
  animation: hero-title-float 8s ease-in-out 1.5s infinite;
  animation-play-state: paused;
}

.is-loaded .hero-title {
  animation-play-state: running;
}

@keyframes hero-title-float {
  0%,
  100% {
    transform: translate3d(0, 0, 0);
  }

  50% {
    transform: translate3d(0, -4px, 0);
  }
}

/* --------------------------------------------------------------------------
   HERO TITLE TEXT ROTATOR
   -------------------------------------------------------------------------- */
/* An inline grid with one cell. Every phrase is placed in that same cell, so
   the wrapper takes the width and height of the longest one and holds it
   whichever is on screen: the line below the heading never moves, and adding a
   fourth phrase needs no measuring. */
.hero-rotator-wrapper {
  display: inline-grid;
  place-items: center;
  vertical-align: baseline;
  text-align: center;
}

/* The resting state is also the entrance state: an item waits below the line,
   transparent and slightly blurred, and rises into place. Blur is what makes
   the change read as motion rather than as a crossfade, and 3px is enough to
   feel without the type ever looking out of focus.

   600ms matches TRANSITION_TIME in js/hero-rotator.js. The two have to agree:
   the script strips .is-exiting on that timer, and if it fired first the
   outgoing phrase would snap back into place mid-flight. */
.hero-rotator-item {
  grid-area: 1 / 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  white-space: nowrap;
  opacity: 0;
  transform: translate3d(0, 38px, 0);
  filter: blur(3px);
  transition: opacity 600ms var(--ease-smooth),
              transform 600ms var(--ease-smooth),
              filter 600ms var(--ease-smooth);
  pointer-events: none;
  will-change: transform, opacity, filter;
  z-index: 1;
}

.hero-rotator-item.is-active {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  filter: blur(0);
  pointer-events: auto;
  z-index: 2;
}

/* Leaves upward, the way the next one arrives, so the pair reads as one line
   moving rather than two lines swapping. */
.hero-rotator-item.is-exiting {
  opacity: 0;
  transform: translate3d(0, -38px, 0);
  filter: blur(3px);
  pointer-events: none;
  z-index: 1;
}

/* Reduced motion: the first phrase is simply the heading. js/hero-rotator.js
   stops rotating as well, so this is belt and braces rather than a lone rule
   fighting a running timer. */
@media (prefers-reduced-motion: reduce) {
  .hero-rotator-item {
    transition: none;
    filter: none;
    transform: none;
  }
}

.hero-accent-gradient {
  background: linear-gradient(135deg, #2563eb 0%, #3b82f6 50%, #60a5fa 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* --------------------------------------------------------------------------
   Reduced motion.

   The shared block earlier in the file kills .load-in's transition, which on
   its own would strand these words at their initial blur forever — the
   entrance never runs, so nothing ever clears it. Reset the filter here
   instead of relying on that block.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .hero-word {
    filter: none !important;
    transition: none !important;
  }

  .hero-title,
  .hero-mark::before {
    animation: none !important;
  }

  .hero-mark::before {
    opacity: 1;
    transition: none;
    transform: scale(1);
  }
}

/* ==========================================================================
   HEADING REVEAL
   The shared entrance for every heading — see js/heading-reveal.js for which
   ones are taken and which already own theirs.

   The span carries no type of its own: no size, weight, colour, spacing or
   line-height. inline-block is the only layout it adds, and the whitespace
   between words is still real text, so the heading wraps exactly where it did.
   ========================================================================== */

.rt-word {
  display: inline-block;
  opacity: 0;
  /* em, not px: the rise scales with the heading it belongs to, so a 100px
     hero and a 22px card heading travel proportionally rather than the small
     one barely moving and the large one lurching. */
  transform: translate3d(0, 0.36em, 0);
  filter: blur(7px);
  transition:
    opacity 760ms cubic-bezier(0.22, 1, 0.36, 1) var(--rt-d, 0ms),
    transform 760ms cubic-bezier(0.22, 1, 0.36, 1) var(--rt-d, 0ms),
    filter 760ms cubic-bezier(0.22, 1, 0.36, 1) var(--rt-d, 0ms);
  will-change: opacity, transform, filter;
}

.rt-h.is-revealed .rt-word {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  filter: blur(0);
}

/* Landed. Holding a compositor layer per word for the rest of the session
   costs memory on long pages for no further benefit. */

.rt-h.rt-done .rt-word {
  transition: none;
  will-change: auto;
}

/* A .reveal sitting on the heading itself would fade and lift the whole block
   underneath the word cascade — two entrances on one element. The words are
   the entrance now, so the block is released immediately. Ancestors that carry
   .reveal are left alone: those bring in a whole card or column, which is a
   different move and reads fine underneath this one. */

.rt-h.reveal {
  opacity: 1;
  transform: none;
  filter: none;
  transition: none;
}

@media (prefers-reduced-motion: reduce) {
  /* The script leaves the DOM untouched under this preference, so there are no
     .rt-word spans to style. This is belt and braces for a preference switched
     on after the split has already happened. */

  .rt-word {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }
}

/* ==========================================================================
   SHOWCASE — STEP TITLE CASCADE
   The seven step headings use the site's ordinary word-by-word entrance — same
   .rt-word spans, same 0.36em rise, same 7px blur, same 760ms curve, same 60ms
   per-word stagger. Only the trigger is different.

   js/heading-reveal.js splits them but deliberately does not observe them (see
   GATED there). An IntersectionObserver cannot answer "is this step on show"
   in a pinned stage where all seven panels occupy one grid cell and are
   therefore all intersecting at once. `is-showing` can: showcase.js sets it on
   whichever step is settled, and clears it the moment that step starts leaving.

   The upshot is that these are the only headings on the site that replay. The
   observer is once-only by design, but a step the reader scrolls back up to is
   genuinely arriving again, and the artwork beside it (js/showcase-live.js)
   replays off this same class — a heading that stayed put while its
   illustration re-animated would look broken.
   ========================================================================== */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .sc-panel.is-showing .sc-panel__title .rt-word {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    filter: blur(0);
  }

  /* Reset instantly on the way out rather than playing the cascade backwards.
     The outgoing panel is already fading and lifting away on the scrubbed
     timeline; a second, time-based 760ms retreat underneath it would be
     visible as the words sliding one way while their panel slides the other.
     The jump is invisible because it happens inside a panel on its way to
     opacity 0.

     Dropping will-change here matters more than usual: seven headings' worth
     of words would otherwise hold a compositor layer each for the whole
     session. The normal headings shed theirs via .rt-done, which these never
     get. This way only the step actually on screen is promoted. */

  .sc-panel:not(.is-showing) .sc-panel__title .rt-word {
    transition: none;
    will-change: auto;
  }

  /* Panel 01 before showcase.js has built its timeline — and permanently if
     GSAP never loads, in which case `is-active` is all there is and no step
     will ever be marked `is-showing`. Without this the section's one visible
     panel renders with an invisible heading. */

  .sc-panel.is-active:not(.is-showing) .sc-panel__title .rt-word {
    opacity: 1;
    transform: none;
    filter: none;
  }
}

/* Below the pin there is no stepping and nothing ever sets `is-showing`, so a
   gated heading would sit at opacity 0 forever. The panels are an ordinary
   stacked list at this width; the titles simply render, exactly as they did
   before they were split. */

@media (max-width: 1023px) {
  .sc-panel__title .rt-word {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
    will-change: auto;
  }
}

/* ==========================================================================
   SOLUTIONS — DELAYED ENTRANCE GATE
   The section holds still until it is properly on screen, waits half a second
   more, and only then starts. js/solutions-scatter.js decides when that is and
   publishes it as `.is-armed`; everything below simply reads the class.

   Three separate things animate in this section and each used to start on its
   own trigger — the cards on scroll position, the copy block on animations.js's
   observer, the heading on heading-reveal.js's. Gating all three on one class
   is what makes them one entrance rather than three overlapping ones.

   The cards are not listed here: their hold is in the module, which simply
   keeps --lp at 0 until the gate opens. Doing it there rather than in CSS
   means the scroll progress is REBASED at that moment, so the cards start from
   zero instead of jumping to wherever the scroll had already reached.
   ========================================================================== */

/* Heading — split into .rt-word spans by heading-reveal.js, which deliberately
   does not observe it (see GATED there). This is the only thing that releases
   it, so a section that never arms leaves the words hidden — the module adds
   the class on every width and under reduced motion for exactly that reason. */

#solutions.is-armed .sol__title .rt-word,
#solutions.is-armed .sol__name .rt-word {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  filter: blur(0);
}

/* Copy block. animations.js has already added .is-visible by now — its
   observer fires the moment the block clips the viewport, well before the gate
   opens — so this holds the released state back rather than the resting one.
   Specificity beats plain `.reveal.is-visible`, and `transition: none` keeps
   the hold from being a slow fade in reverse. */

#solutions:not(.is-armed) .sol__copy.reveal.is-visible {
  opacity: 0;
  transform: translate3d(0, 40px, 0);
  transition: none;
}

/* Reset instantly when the section disarms on its way out of view, so the
   replay starts from a clean slate rather than reverse-animating behind the
   reader. */

#solutions:not(.is-armed) .sol__title .rt-word,
#solutions:not(.is-armed) .sol__name .rt-word {
  transition: none;
}

@media (prefers-reduced-motion: reduce) {
  /* heading-reveal.js leaves the DOM alone under this preference, so there are
     no .rt-word spans to release — but the copy block's .reveal is still real,
     and the shared reduced-motion rule that forces it visible sits earlier in
     this file. Undo the hold so the gate can never withhold content from a
     reader who asked for less motion. */

  #solutions:not(.is-armed) .sol__copy.reveal.is-visible {
    opacity: 1;
    transform: none;
  }
}

/* ==========================================================================
   SHOWCASE — STEP COPY
   Everything in a step's copy column arrives as one movement as that step
   settles, on the same `is-showing` gate the heading cascade uses.

   The order is eyebrow, heading, paragraph, button, and the overlaps matter
   more than the delays: each one starts partway through the one before it, so
   the block reads as a single gesture with a lead and a follow rather than four
   things taking turns. End to end it is about 1.1s, inside the 0.58-of-a-step
   the reader dwells on a panel.

   The eyebrow and the button used to be excluded, and that was the bug: while
   the heading and paragraph waited on the gate, those two sat there fully
   opaque. A step caught before its gate opened showed a floating "01" and a
   floating button with a void between them, which read as broken rather than
   as anticipation.

   Gated, not observed, for exactly the reason given in "SHOWCASE — STEP TITLE
   CASCADE": all seven panels share one grid cell in a pinned stage, so they
   are all intersecting at once and an IntersectionObserver cannot tell which
   step is actually on show. It replays for the same reason too — a step
   scrolled back up to is genuinely arriving again.

   One block, not word by word. The heading above it is already cascading; a
   second cascade under it would read as fussy rather than composed, and a
   three-line paragraph split into words takes long enough that the step is
   half over before it has finished arriving.
   ========================================================================== */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  /* The 260ms delay starts the paragraph partway THROUGH the heading's
     cascade, not after it. The two then read as one movement — the paragraph
     is already on its way up as the last word of the heading lands. */

  .sc-panel__text {
    opacity: 0;
    transform: translate3d(0, 14px, 0);
    filter: blur(5px);
    transition:
      opacity 700ms cubic-bezier(0.22, 1, 0.36, 1) 260ms,
      transform 700ms cubic-bezier(0.22, 1, 0.36, 1) 260ms,
      filter 700ms cubic-bezier(0.22, 1, 0.36, 1) 260ms;
  }

  .sc-panel.is-showing .sc-panel__text {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    filter: blur(0);
  }

  /* Reset instantly on the way out rather than playing it backwards. The
     outgoing panel is already fading and lifting on the scrubbed timeline, and
     a second 700ms retreat underneath it would show as the paragraph sliding
     one way while its panel slides the other. The jump is invisible: it
     happens inside a panel already on its way to opacity 0. */

  .sc-panel:not(.is-showing) .sc-panel__text {
    transition: none;
  }

  /* Panel 01 before showcase.js has built its timeline — and permanently if
     GSAP never loads, in which case `is-active` is all there is and no step is
     ever marked `is-showing`. Without this the one visible panel would render
     with an invisible paragraph. */

  .sc-panel.is-active:not(.is-showing) .sc-panel__text {
    opacity: 1;
    transform: none;
    filter: none;
  }

  /* ---- eyebrow ("01" and its rule) --------------------------------------
     Leads with no delay. It is the smallest thing in the column and its job is
     to set the heading up, so it wants to be there first — but only just: at
     520ms it is still arriving as the heading's first word starts. */

  .sc-panel__num {
    opacity: 0;
    transform: translate3d(0, 10px, 0);
    transition:
      opacity 520ms cubic-bezier(0.22, 1, 0.36, 1),
      transform 620ms cubic-bezier(0.22, 1, 0.36, 1);
  }

  .sc-panel.is-showing .sc-panel__num {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }

  /* The 44px rule draws out from the number instead of fading in with it —
     scaleX from its left edge, so it reads as being extended by the number
     rather than as a separate mark appearing beside it. Delayed just enough
     that the number is legible before the line starts moving. */

  .sc-panel__num::after {
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 620ms cubic-bezier(0.22, 1, 0.36, 1) 160ms;
  }

  .sc-panel.is-showing .sc-panel__num::after {
    transform: scaleX(1);
  }

  /* ---- button -----------------------------------------------------------
     Lands last, at 420ms: there should be something worth acting on before the
     thing to act with turns up. Travels furthest of the four, because it is the
     heaviest element and a short rise on a solid white pill barely registers. */

  .sc-panel__cta {
    opacity: 0;
    transform: translate3d(0, 18px, 0);
    transition:
      opacity 700ms cubic-bezier(0.22, 1, 0.36, 1) 420ms,
      transform 700ms cubic-bezier(0.22, 1, 0.36, 1) 420ms;
  }

  .sc-panel.is-showing .sc-panel__cta {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }

  /* Same two guards the paragraph above carries, for the same two reasons:
     an instant reset on the way out so nothing plays backwards underneath the
     scrubbed panel exit, and a visible resting state for panel 01 before
     showcase.js runs — or forever, if GSAP fails to load and `is-showing` is
     never set on anything. */

  .sc-panel:not(.is-showing) .sc-panel__num,
  .sc-panel:not(.is-showing) .sc-panel__num::after,
  .sc-panel:not(.is-showing) .sc-panel__cta {
    transition: none;
  }

  .sc-panel.is-active:not(.is-showing) .sc-panel__num,
  .sc-panel.is-active:not(.is-showing) .sc-panel__cta {
    opacity: 1;
    transform: none;
  }

  .sc-panel.is-active:not(.is-showing) .sc-panel__num::after {
    transform: scaleX(1);
  }
}

/* ==========================================================================
   HERO SHOT — CORNER CLIP
   hero-dashboard.webp has no alpha channel (lossy VP8), so its rounded corners
   are painted into an opaque rectangle and the dark blue it was composited
   against survives as a wedge outside each one. Nothing used to clip it, on the
   belief that the artwork carried real transparency.

   It only became visible when the shot stopped growing to full size: at scale 1
   the top edge sat tucked under the fixed navbar, and the corners went with it.

   The radius is measured off the artwork, not guessed. Scanning in from each
   corner for the first non-blue pixel gives an inset of 24 px at 2 px depth,
   10 px at 10 px, 5 px at 16 px, reaching zero by about 20 px — a circle of
   r ≈ 36 in the 2000 x 1214 original. 38 is used instead of 36 so the clip
   lands just outside the artwork's own curve and takes the antialiased blue
   fringe with it; the 2 px it costs the dashboard is below anything visible.

   Expressed as a percentage pair rather than pixels so it survives every size
   the shot is drawn at — the load-in, the 0.64 → 0.92 scroll-grow, and every
   breakpoint down to a phone. 38/2000 = 1.9% across, 38/1214 = 3.13% down, so
   the two resolve to the same 38 px and the corner stays circular at any width
   as long as the aspect ratio holds, which for an <img> it does.

   The four straight edges are deliberately not touched: measured, they carry
   0 px of blue, so there is nothing there to hide.
   ========================================================================== */

.shot-img {
  border-radius: 1.9% / 3.13%;
  /* Positioned so it can sit above the hero-cast figures — see "HERO CAST". */
  position: relative;
  z-index: 1;
}

/* ==========================================================================
   SHOWCASE — STEP INDICATOR
   Seven marks down the right-hand gutter: how far through the seven steps the
   reader is, and how many are left.

   The active mark stretches into a pill rather than only brightening. Length
   carries at a glance in a way opacity does not — you can see which one is
   current from the corner of your eye, without having to compare seven dots
   for brightness.

   Hidden wherever the pin is not running. Below 1024 px, and under reduced
   motion, the panels are an ordinary stacked list in normal flow: there are no
   steps to be on, so a step indicator would be describing something that is
   not happening. showcase.js is scoped to the same query, so the two cannot
   disagree about whether the sequence exists.
   ========================================================================== */

.sc-dots {
  display: none;
}

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .sc-dots {
    position: absolute;
    top: 50%;
    /* Parked in the gutter beside the text column, not against the viewport
       edge. The shell is 1260 wide at most, so `50% - 630px` IS its outer edge;
       on a wide monitor that keeps the marks next to the copy instead of
       stranding them 600 px away from it.

       The 8px floor takes over below about 1280px, where the shell fills the
       viewport and there is no gutter left — the marks then have to live in the
       shell's own 20px padding. 8, not something rounder, because the copy
       column reaches the content edge at these widths and the padding is all
       the clearance there is: at 8px the marks clear the text by 6px from
       1024px up, where 18px would have overlapped it by 4. */
    right: max(8px, calc(50% - 630px));
    transform: translateY(-50%);
    z-index: 30;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
    /* The column itself stays transparent to the pointer: it is a 6px-wide
       strip standing over the artwork for the full height of the stage, and
       anything it swallowed would be a click the reader aimed at the panel.
       The marks take it back for themselves below. */
    pointer-events: none;
  }

  .sc-dot {
    /* A <button>, so the UA's own border, padding, background and font have to
       come off before the pill below is what is actually drawn. */
    appearance: none;
    display: block;
    padding: 0;
    border: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;

    /* Undoes the list's pointer-events: none. Without this the click handler
       in js/showcase.js never fires and the marks read as decoration. */
    pointer-events: auto;

    /* The hit area is bigger than the mark. 6px is a fair target for the eye
       and an unfair one for the hand, so ::before pads it out to 24px without
       moving or resizing anything that is drawn. Related, so the pad is
       positioned against the mark rather than the stage. */
    position: relative;

    width: 6px;
    height: 6px;
    border-radius: 100px;
    background-color: rgba(255, 255, 255, 0.24);
    /* Height and colour on the same curve, so the pill grows as it brightens
       rather than the two arriving separately.

       Lengthened from 420ms to sit with the panel handover rather than finish
       ahead of it: the indicator arriving first is what made the change read
       as two events. The mark growing is also a position change — the marks
       below it are pushed down the gutter by the same transition, so the
       column reflows on the curve instead of jumping. */
    transition:
      height 720ms var(--ease-smooth),
      background-color 720ms var(--ease-smooth);
  }

  .sc-dot::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 24px;
    height: 24px;
    transform: translate(-50%, -50%);
  }

  /* The mark is 6px of white at 24%, so the ring a browser draws by default
     lands somewhere between invisible and enormous. Drawn against the hit area
     instead, which is the shape the keyboard is actually selecting. */
  .sc-dot:focus-visible { outline: none; }

  .sc-dot:focus-visible::before {
    border-radius: 100px;
    outline: 2px solid #ffffff;
    outline-offset: 2px;
  }

  .sc-dot:hover { background-color: rgba(255, 255, 255, 0.55); }

  .sc-dot.is-on {
    height: 24px;
    background-color: #ffffff;
  }

  /* The one on show is where the reader already is, so it does not offer
     itself as somewhere to go. */
  .sc-dot.is-on { cursor: default; }
}

/* The marks sit over the near-black ground, which is what makes white at 24 %
   legible as "not yet" without competing with the copy. */

/* ==========================================================================
   OVERVIEW CAST
   Two figures flanking the platform dashboard in the "Platform overview"
   section, one either side, standing on its baseline.

   BEHIND THE PLATE
   `.ov-dash__plate` carries the only z-index that matters: the dashboard is in
   front, the figures behind it. So the brief's "do not cover dashboard
   content" is not something the offsets below have to be solved for — a figure
   that reaches too far is clipped by an opaque white plate, at every width,
   including ones nobody measured. The offsets only decide how much of each
   person clears the plate and shows in the gutter.

   This is the opposite of the hero, where the figures deliberately stand in
   FRONT of the shot. There the overlap is part of the composition and the
   offsets are solved for a fixed 70px of it; here the dashboard is the subject
   and the people are staging around it.

   SIZED AGAINST THE DASHBOARD
   Heights and offsets are percentages of `.ov-dash`, so the figures keep their
   proportional relationship to the dashboard at every width rather than
   drifting as it grows. The pair is the wider of the two at a given height, so
   it needs the larger outward offset to clear the plate by the same amount as
   the single figure.

   WHY 1280px
   Below that the shell fills the viewport and there is no gutter to stand in —
   at 1024px it is 0, and the figures would be entirely behind the plate. The
   two honest options at those widths are to cover the dashboard or to shrink
   it, and the brief rules out both. They are dropped instead, and because
   `loading="lazy"` on a `display: none` image is never fetched, a phone does
   not pay for artwork it will not see. This is the one number to change if the
   dashboard ever gets narrower on tablet.

   THE ENTRANCE
   Not scripted here. The markup carries `.reveal .reveal-left` /
   `.reveal-right`, so animations.js runs it: opacity 0 until the first time
   the element is genuinely on screen, then `io.unobserve()` — once, never
   replayed. All this block adds is the duration, since the brief asks for
   0.8-1.2s where the shared default is 0.7/0.8.
   ========================================================================== */

.ov-dash {
  position: relative;
}

/* The dashboard, in front. Nothing else about it changes. */

.ov-dash__plate {
  position: relative;
  z-index: 2;
}

.ov-cast {
  display: none;
  position: absolute;
  bottom: 0;
  z-index: 1;
  width: auto;
  max-width: none;
  pointer-events: none;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}

/* Slower than the shared .reveal default, which is 700/800ms. Doubled class so
   it beats `.reveal` on specificity rather than on source order — this block
   sits far below the reveal system in the file, and that should not be what
   the rule depends on. The travel (40px, from .reveal-left / .reveal-right)
   and the curve are the shared ones. */

.reveal.ov-cast {
  transition:
    opacity 1000ms var(--ease-smooth) var(--d, 0ms),
    transform 1100ms var(--ease-smooth) var(--d, 0ms);
}

@media (min-width: 1280px) {
  .ov-cast {
    display: block;
    height: 52%;
  }

  .ov-cast--left  {
    left:  -13%;
  }

  /* the pair  — wider, reaches further */

  .ov-cast--right {
    right:  -9%;
  }

  /* the woman — narrower at the same height */
}

@media (min-width: 1536px) {
  /* A real gutter at last: a taller figure, further out, without either one
     bleeding off the edge of the section. */

  .ov-cast {
    height: 58%;
  }

  .ov-cast--left  {
    left:  -17%;
  }

  .ov-cast--right {
    right: -12%;
  }
}

/* ==========================================================================
   HERO CAST
   Two figures standing at the left and right edges of the product shot.

   COMES AND GOES
   The one entrance on the site that is not once-only. js/hero-cast.js toggles
   .is-in as each figure enters and leaves the viewport, so scrolling back up to
   the hero looks the same as arriving at it — rather than finding them already
   landed, which is what the shared .reveal system would give (it unobserves on
   first fire).

   The two directions carry different timing, and they get it without any
   scripting: a transition is started from the after-change style, so adding
   .is-in uses the slow, delayed values on that rule and removing it falls back
   to the quicker undelayed ones on the base. The 400ms beat is therefore paid
   only on the way in.

   SIZED AGAINST THE SHOT, IN PERCENTAGES
   Every number here is a percentage of the shot's own box, so the figures keep
   the same proportional relationship to it at every stage of the 0.64 -> 0.92
   scroll-grow and never drift as it expands.

   Viewport units were the obvious alternative and they are wrong here. Pinning
   each figure's outer edge to the screen edge with `calc(530px - 50vw)` reads
   correctly on paper, but it is viewport-space arithmetic evaluated INSIDE a
   scaled coordinate space: at the 0.64 start of the grow the whole offset is
   multiplied by 0.64 too, which drags both figures inward until only a 25px
   sliver of each clears the dashboard. Percentages scale with the box they
   belong to, which is the entire point.

   The trade is that the outward reach no longer adapts to the gutter, so the
   breakpoints below do it instead: 24%/-15% while the gutter is 150-230px,
   opening to 30%/-22% past 1500 where there is room for a larger figure and a
   wider reach. Measured against the real gutter at each width neither band
   bleeds off the screen edge, and in both the handshake — the thing that makes
   the right-hand image read — stays clear of the shot's edge rather than
   disappearing behind it.

   IN FRONT OF THE SHOT
   The three layers inside .float-host are ordered explicitly — the dashboard 1,
   its live overlay 2, the figures 3 — so the figures stand in front of the
   whole shot, including the animated bar and ring.

   They were behind it originally, which meant the overlap was hidden and could
   not cover anything. In front, the overlap is real: whatever the figures reach
   over IS obscured. That is the reason the offsets below are solved for a fixed
   70px overlap rather than left to fall where they may — see the note on the
   breakpoints.

   z-index: -1 was the first attempt at putting them behind and it does not
   work: a negative index takes them below the ancestors between here and the
   hero backdrop, several of which carry their own transforms, so they end up
   painted underneath the sky instead of between it and the shot. Keeping every
   layer on a positive index keeps them all in one stacking context. The
   dashboard still needs `position: relative` for its own index to apply.

   Widths step up with the viewport so the visible portion stays a readable
   slice of a person rather than a sliver — the narrower the gutter, the
   smaller the figure that fits it.

   Below 1280px the gutter is too narrow to hold a readable slice of a person
   — at 1100 it is 20px. They are dropped rather than shrunk, and
   `loading="lazy"` on a display:none image means neither file is fetched.
   ========================================================================== */

/* ---- the cut-outs stand on something ----

   The three places the cast appears: the hero, the overview dashboard and the
   contact form. All three are the same two PNGs and all three had them floating
   — a cut-out with no shadow reads as a sticker laid on the page rather than a
   person standing in it.

   drop-shadow, not an ellipse behind them. These are <img> elements, so they
   take no ::after, and the alternative is wrapping each of the six in a span —
   which would mean moving `position: absolute`, the entrance transforms and
   the .is-in timing off the image and onto a new wrapper, refactoring an
   animated component to add a shadow. The filter follows the PNG's own alpha,
   so it needs none of that.

   Two shadows, not one: a short dark one is the contact where the shoes meet
   the ground, and a wide soft one is the ambient falloff around it. One alone
   reads either as a hard outline or as a smudge. Offset straight down with no
   x, because the hero's light comes from above.

   Applied to the images and not to a container, so nothing else in these
   sections is filtered — a filter on an ancestor would also make it the
   containing block for anything positioned inside it. */

.hero-cast,
.ov-cast,
.ct-cast {
  filter:
    drop-shadow(0 6px 5px rgba(11, 27, 51, 0.26))
    drop-shadow(0 18px 22px rgba(11, 27, 51, 0.16));
}

.hero-cast {
  display: none;
  position: absolute;
  bottom: 0;
  z-index: 3;
  height: auto;
  max-width: none;
  pointer-events: none;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  /* Resting state: hidden, and offset toward the edge they come in from. The
     direction lives on the modifiers below.

     This transition is the EXIT — quicker, and with no delay. The entrance is
     on the .is-in rule, which is how the two get different timing without any
     scripting: a transition is started from the after-change style, so adding
     the class uses the slow, delayed values and removing it uses these. The
     beat before they arrive is therefore only paid on the way in; on the way
     out they simply go. */
  opacity: 0;
  transition:
    opacity 500ms var(--ease-smooth),
    transform 600ms var(--ease-smooth);
}

.hero-cast--left  {
  transform: translate3d(-40px, 0, 0);
}

.hero-cast--right {
  transform: translate3d(40px, 0, 0);
}

/* Entrance: 40px of travel, a 400ms beat first, ~1s to land. Same expo-out
   curve as the rest of the site, so it decelerates in with no overshoot. */

.hero-cast.is-in {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity 900ms var(--ease-smooth) 400ms,
    transform 1000ms var(--ease-smooth) 400ms;
}

/* Sized by HEIGHT so the two figures stand the same height as each other,
   with width following from each image's own aspect ratio. The pair is the
   wider of the two at any given height — 0.90 against the single figure's
   0.67 — so its outward offset is the one the gutter constrains, and the
   single figure's is then solved backwards from it to land on the same 70px
   overlap. Equal overlap is what makes them read as standing at the same
   distance; equal offsets would push the pair 100px further over the shot. */

@media (min-width: 1280px) {
  .hero-cast {
    display: block;
    width: auto;
    height: 41%;
  }

  .hero-cast--left  {
    left:  -16%;
  }

  /* the pair  — wider, reaches further */

  .hero-cast--right {
    right: -10%;
  }

  /* the woman — narrower at the same height */
}

/* Past 1500 the gutter is wide enough to take a figure half again as tall
   without either of them reaching any further over the shot. */

@media (min-width: 1500px) {
  .hero-cast {
    height: 61%;
  }

  .hero-cast--left  {
    left:  -27%;
  }

  .hero-cast--right {
    right: -18%;
  }
}

/* The pair sits left and the single figure right; the files are named for who
   is in them rather than for a side, so swapping is the two offsets above and
   the two class names in hero.php, with no misleading filenames left behind. */

/* ==========================================================================
   SITE FOOTER — OVERSIZED WORDMARK
   The brand mark set very large across the foot of the page, fading downward
   into the background, sliding up into place as the footer arrives.

   A CSS MASK, NOT AN IMAGE
   The mark has to carry a vertical gradient, and an <img> cannot be filled with
   one. The usual answer is to inline the SVG and point its paths at a
   <linearGradient>, but that means keeping a second copy of the artwork in the
   markup, in step with assets/images/niyuk-logo.svg by hand. Using the same
   file as a mask instead leaves one copy of the artwork: the element paints a
   plain CSS gradient and the mask cuts the letterforms out of it. The file's
   paths are opaque on a transparent ground, so its own alpha is exactly the
   shape needed.

   SIZED BY HEIGHT
   The mark is 113 x 46, about 2.46:1. The Sphinx wordmark it is modelled on is
   nearer 4.4:1, which is why theirs can run the full width of the page at a
   sensible height and this one cannot — matched edge to edge it would stand
   almost 500px tall. So the height is capped and `contain` centres the mark
   within it, which keeps it large without the footer growing a storey.

   THE SLIDE
   The clip carries .reveal so animations.js's observer marks it on arrival;
   the travel itself is on the inner span, a full 100% of its own height, so it
   climbs out from behind the clip's lower edge rather than merely shifting.
   .reveal-fade rather than .reveal-up: the wrapper should not move, only the
   mark inside it.
   ========================================================================== */

.sf__wordclip {
  margin-top: 44px;
  overflow: hidden;
  /* Capped and centred rather than edge to edge. At full shell width the mark
     stands nearly 500px tall — a storey of its own, and far louder than the
     closing bar it is meant to sit under. The clamp keeps it a quiet sign-off:
     it still scales with the viewport, but stops well short of the shell. The
     cap is on the clip, not the mark, so the ratios below are untouched and the
     cut still lands in the same place on the letterforms. */
  max-width: clamp(340px, 52vw, 700px);
  margin-inline: auto;
  /* The cut. The mark is 113 x 46; this box is 113 x 38, so about 83% of the
     mark's height is on the page and the last 17% runs off the bottom. Both are
     ratios rather than pixels, so the proportion holds at every width without a
     single breakpoint.

     38, not the 32 this ran at. At 32 only 70% showed and the cut fell through
     the feet of the letters, which is what made the "n" read as a broken shape
     rather than a letter fading out. 38 clears the feet and leaves the tail of
     the "y" to run off, which is the effect the block is for.

     Where the cut lands matters: it has to arrive where the gradient has
     already faded to nothing, or the edge reads as a hard chop through solid
     white rather than a dissolve. So the stops move whenever this does — see
     .sf__word. The two are one decision and cannot be changed independently.
     38 is also the ceiling for that: past about 85% visible the last stop
     computes beyond 100% and the fade can no longer finish before the cut. */
  aspect-ratio: 113 / 38;
}

.sf__word {
  display: block;
  width: 100%;
  /* The mark's own ratio, so `contain` fits it to the full width rather than
     letterboxing it — this is what makes it run edge to edge instead of sitting
     centred at half the width. Taller than the clip above, by design. */
  aspect-ratio: 113 / 46;
  /* Bright at the top, gone by the bottom — the mark reads as emerging from
     the page rather than sitting on it.

     10 / 60 / 96 again, because the cut is back at 83% visible: the rule is to
     scale 10 / 60 / 96 by (visible % / 83), and at 83 that factor is 1. They
     were 8 / 51 / 81 while the clip showed 70%. At the cut the mark is down to
     about alpha 0.05, so the edge dissolves rather than shearing through solid
     white. This is the arithmetic to redo if the cut moves again. */
  background-image: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.92) 10%,
    rgba(255, 255, 255, 0.34) 60%,
    rgba(255, 255, 255, 0.05) 96%
  );
  /* Relative to the stylesheet, so css/../assets/... resolves correctly. */
  -webkit-mask-image: url(../assets/images/niyuk-logo.svg);
  mask-image: url(../assets/images/niyuk-logo.svg);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center top;
  mask-position: center top;
  transform: translate3d(0, 100%, 0);
  transition: transform 1100ms var(--ease-smooth);
  will-change: transform;
}

.sf__wordclip.is-visible .sf__word {
  transform: translate3d(0, 0, 0);
}

/* Nothing to slide out from behind, so the clip would simply hide it. */

@media (prefers-reduced-motion: reduce) {
  .sf__word {
    transform: none !important;
    transition: none !important;
  }
}

/* ==========================================================================
   HRMS SOFTWARE PAGE
   Hand-authored, like the site footer and for the same reason: css/style.css
   is committed as generated output and there is no build step in this repo, so
   a Tailwind utility that is not already used somewhere on the site would not
   exist in the file and would silently do nothing. Everything below is written
   out, and the only classes borrowed from elsewhere are ones the home page
   already renders — .badge, .card, .btn-*, .section-title, .section-lead,
   .faq-item, .reveal.

   Namespaced hs-. Nothing in here is loaded conditionally, so the prefix is
   what keeps a page-specific arrangement from reaching the home page.
   ========================================================================== */

.hs-i {
  width: 22px;
  height: 22px;
}

.hs-i--sm {
  width: 15px;
  height: 15px;
}

/* Break only where there is room to. The headings are written with a <br> at
   the point they read best on a wide screen; below 640px the line lengths are
   short enough that an enforced break leaves an orphan. */

.hs-br {
  display: none;
}

@media (min-width: 640px) {
  .hs-br {
    display: inline;
  }
}

/* The HRMS-vs-spreadsheets section's own phone spacing. It carries the generic
   .section, whose 70 top and bottom is tuned for a block that opens on a badge
   and a heading with room around them; this one is mostly a wide table the
   reader has scrolled to on purpose. A named class rather than editing
   .section, which eleven other sections use, and rather than pt/pb utilities,
   which are not in the generated CSS and would silently do nothing with no
   build step here. */

@media (max-width: 767px) {
  .hs-vs-sec {
    padding-top: 30px;
    padding-bottom: 30px;
  }
}

/* ------------------------------------------------------------------
   Section heading block — badge, title, optional lead, centred
   ------------------------------------------------------------------ */

.hs-head {
  margin-left: auto;
  margin-right: auto;
  max-width: 720px;
  text-align: center;
}

.hs-head__title {
  margin-top: 22px;
}

/* A heading the shared 720px measure is 22px too narrow for: "Manual payroll
   vs payroll software" runs to 742px at the desktop size, so the shared
   measure broke it over two lines by a hair. Widened here, and held on one
   line from 1024px up where the shell has room for it. Below that the line
   cannot fit at a readable size, so it wraps as any other heading does. */

.hs-head--wide {
  max-width: 820px;
}

@media (min-width: 1024px) {
  .hs-head--wide .hs-head__title {
    white-space: nowrap;
  }
}

/* The other long heading: a full question rather than a phrase, which cannot
   be held on one line at any width. It gets the room to break over two lines
   instead of the 720px measure, which would make three. */

.hs-head--long {
  max-width: 900px;
}

.hs-head__lead {
  margin-top: 18px;
}

/* ------------------------------------------------------------------
   Hero
   ------------------------------------------------------------------ */

.hs-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* Clears the fixed navbar, which is --nav-h tall and overlays the page. */
  padding-top: calc(var(--nav-h) + 58px);
  padding-bottom: 70px;
}

/* 46 above the navbar's own clearance, not 88. The heroes carry a badge, a
   heading, a line and a button in the copy column and a picture beside it, and
   at 88 the pair started well down the screen with the button below the fold
   on a laptop. The clearance itself is untouched: --nav-h still comes off the
   top before this is counted. */

@media (min-width: 768px) {
  .hs-hero {
    padding-top: calc(var(--nav-h) + 46px);
    padding-bottom: 100px;
  }
}

.hs-hero__sky {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

.hs-hero__sky img {
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  -o-object-position: center top;
     object-position: center top;
}

/* Phones: the top of the photograph, not all of it.

   hero-bg.webp is 1374x1145 and a phone hero is about 430x619, so `cover`
   scales it by height and the WHOLE picture is squeezed into the hero — sky in
   the top half, meadow in the bottom. The meadow is the detailed half, and it
   was landing exactly where the lead paragraph and the buttons are.

   Making the image box 180% of the hero and keeping it anchored top means the
   hero shows the top 56% of the picture instead: sky behind all the copy, and
   the horizon arriving around 90% of the way down, so a strip of meadow still
   sits under the buttons. .hs-hero clips the overflow, and .hs-hero__fade still
   dissolves the foot into the white below.

   No upscaling: at 180% of a 530-620px hero the image renders 1150-1340px wide
   against its own 1374, so the crop is the only thing that changes. */

/* Desktop and tablet: the same crop, for the same reason.
   
   The horizon sits at about 52% of hero-bg.webp. `cover` on a 1440-wide hero
   is driven by the width, so the hero showed the top 69% of the picture and
   the meadow's top edge landed across the lead paragraph — legible against the
   pale sky above it and not against flowers. Anchored top at 200% the hero
   shows the top 50% instead, which is sky the whole way across.
   
   It costs about 1.45x of upscaling at a typical hero height. The visible half
   is sky and soft cloud, which carries that; the detailed half is what is now
   out of frame. A wider screen needs no help — at 1920 `cover` already crops
   to 52% and at 2560 to 39% — and this rule changes nothing there. */

@media (min-width: 768px) {
  .hs-hero__sky img {
    height: 200%;
  }
}

@media (max-width: 767px) {
  .hs-hero__sky img {
    height: 180%;
  }
}

/* The photograph has to end somewhere, and a hard edge across the page reads
   as a seam. This dissolves it into the white the next section starts on. */

.hs-hero__fade {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 220px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #ffffff 92%);
}

.hs-hero__grid {
  display: grid;
  gap: 44px;
  align-items: center;
}

@media (min-width: 1024px) {
  .hs-hero__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    gap: 60px;
  }
}

.hs-hero__title {
  margin-top: 22px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(34px, 5.4vw, 56px);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -1.2px;
  color: #0B0D12;
}

.hs-hero__lead {
  margin-top: 20px;
  max-width: 520px;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.55;
  /* Black, not the grey the rest of the site's body copy takes. A hero lead is
     the one paragraph every visitor reads, and it sits over sky or beside
     artwork rather than on flat white, where a mid grey goes soft. Five pages
     had already overridden this to a near-black of their own; those are gone
     and they inherit this. */
  color: #000000;
}

.hs-hero__cta {
  display: flex;
  flex-direction: row;
  /* The wrap is the small-phone fallback. Below roughly 375 the pair no longer
     fits on one line even at the tightened paddings below, and wrapping puts
     them back one per row, full width, which is what they used to do at every
     width under 480. */
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-top: 32px;
}

/* Phones: the two stay side by side rather than stacking, "Book a demo" then
   "Explore features".

   At their desktop paddings the pair measures 364 (30 + 93 + 14 + 33 + 10 for
   the primary, 26 + 118 + 26 for the solid, 14 between), which clears a 430px
   phone and nothing narrower. Bringing the paddings and both gaps in takes it
   to 326, which clears a 375. The buttons also grow to share whatever is left,
   so the pair reads as two halves of one row rather than two pills with a tail
   of empty space after them. */

@media (max-width: 479px) {
  .hs-hero__cta {
    gap: 10px;
  }

  .hs-hero__cta > * {
    flex: 1 1 auto;
  }

  /* Growing to share the row is what makes a PAIR read as two halves of one
     row. A hero with one button has nothing to share it with, so the same rule
     stretched it the full width of the screen — a pill the width of the page
     with three words in the middle of it. Back to its own width there, which
     lands at roughly half the row and sits under the copy's left edge like
     every other button on a left-set hero. */
  .hs-hero__cta > :only-child {
    flex: 0 0 auto;
  }

  .hs-hero__cta .btn-primary {
    gap: 10px;
    padding-left: 20px;
    padding-right: 6px;
  }

  .hs-hero__cta .btn-solid {
    padding-left: 18px;
    padding-right: 18px;
  }
}

/* The artwork sits on a plate of its own so it reads as a product surface
   rather than as loose vector art floating on the sky. */

.hs-hero__frame {
  /* The positioning context for the play button centred on the artwork —
     .shot-play is absolute, and without this it would resolve against the
     page. */
  position: relative;
  overflow: hidden;
  border-radius: 22px;
  background-color: #e4eaf9;
  box-shadow:
    0 34px 80px -30px rgba(16, 24, 48, 0.45),
    0 2px 10px rgba(16, 24, 48, 0.12);
}

/* ------------------------------------------------------------------
   Scenic sections — the feature grid and the closing CTA
   ------------------------------------------------------------------ */

.hs-scenic {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-top: 90px;
  padding-bottom: 90px;
}

@media (min-width: 768px) {
  .hs-scenic {
    padding-top: 130px;
    padding-bottom: 130px;
  }
}

.hs-scenic__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

.hs-scenic__bg img {
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  -o-object-position: center;
     object-position: center;
}

/* Both edges dissolve into the white sections either side, so the photograph
   reads as a band the page passes through rather than a panel dropped on it. */

.hs-scenic__top,
.hs-scenic__bottom {
  position: absolute;
  inset-inline: 0;
  height: 180px;
}

.hs-scenic__top {
  top: 0;
  background: linear-gradient(180deg, #ffffff 0%, rgba(255, 255, 255, 0) 100%);
}

.hs-scenic__bottom {
  bottom: 0;
  background: linear-gradient(0deg, #ffffff 0%, rgba(255, 255, 255, 0) 100%);
}

/* ------------------------------------------------------------------
   Key features — header row, then a slider
   ------------------------------------------------------------------ */

.hs-feat__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 26px;
  margin-bottom: 40px;
}

@media (min-width: 900px) {
  .hs-feat__head {
    /* Heading left, the single call to action opposite it. flex-end on the
       button so it sits on the heading's last line rather than floating level
       with the badge above it. */
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
    gap: 40px;
  }
}

.hs-feat__title {
  margin-top: 20px;
}

.hs-feat__cta {
  flex: none;
}

/* One arrow at each end of the rail, sitting on the marquee's own faded edges
   rather than beside the button above: that is where the mask has already
   taken the cards down to nothing, so an arrow covers no readable text.

   The wrapper is the positioning context. It cannot be .marquee itself, which
   clips its overflow — an arrow inside it would be cut off the moment it sat
   past the edge. */

.rail-wrap {
  position: relative;
}

/* Same near-white-over-photograph treatment as the cards below, at button
   size, so the pair reads as belonging to the rail rather than to the page. */

.rail-nav__btn {
  position: absolute;
  /* Level with the middle of the cards: the rail's own 10px top and 24px
     bottom padding sit inside this box, so centring on the box would leave the
     arrows riding low. */
  top: calc(50% - 7px);
  transform: translate3d(0, -50%, 0);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: 999px;
  color: #1D1D1D;
  background: rgba(255, 255, 255, 0.94);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  box-shadow:
    inset 0 0 0 1px rgba(16, 24, 48, 0.08),
    0 1px 2px rgba(16, 24, 48, 0.06),
    0 18px 40px -26px rgba(16, 24, 48, 0.45);
  cursor: pointer;
  transition:
    transform 260ms var(--ease-smooth),
    box-shadow 260ms var(--ease-smooth),
    background-color 260ms var(--ease-smooth);
}

.rail-nav__btn svg {
  width: 20px;
  height: 20px;
}

.rail-nav__btn:hover {
  background: #ffffff;
  transform: translate3d(0, calc(-50% - 2px), 0);
  box-shadow:
    inset 0 0 0 1px rgba(16, 24, 48, 0.1),
    0 1px 2px rgba(16, 24, 48, 0.06),
    0 24px 48px -24px rgba(16, 24, 48, 0.5);
}

.rail-nav__btn:active {
  transform: translate3d(0, -50%, 0);
}

.rail-nav__btn:focus-visible {
  outline: 2px solid #1D1D1D;
  outline-offset: 3px;
}

.rail-nav__btn--prev {
  left: -4px;
}

.rail-nav__btn--next {
  right: -4px;
}

/* Clear of the shell's gutters once there is room outside the content column;
   below that they sit just inside the rail, over the faded edge. */

@media (min-width: 1320px) {
  .rail-nav__btn--prev {
    left: -30px;
  }

  .rail-nav__btn--next {
    right: -30px;
  }
}

@media (max-width: 639px) {
  .rail-nav__btn {
    width: 40px;
    height: 40px;
  }

  .rail-nav__btn svg {
    width: 18px;
    height: 18px;
  }
}

/* ---- the rail ---- */

/* The site's marquee component. Vertical padding rather than margin because
   .marquee clips its own overflow — the cards' shadows need to fall inside the
   box or they are cut off along a straight line top and bottom. */

.hs-feat__rail {
  padding: 10px 0 24px;
}

/* How many cards are on screen at once. The width is derived from it rather
   than set directly, so "four across" stays four across at every width above
   the breakpoint instead of drifting as the column grows.

   `min(1200px, 100vw - 40px)` is the content column: capped by .content, and
   by the shell's 20px gutters below that. A percentage cannot be used — the
   card sits inside .marquee__group, which is `width: max-content`, so a
   percentage would resolve against a width the cards themselves define. */

.hs-feat__rail {
  --cards: 1.15;
}

@media (min-width: 640px)  {
  .hs-feat__rail {
    --cards: 2;
  }
}

@media (min-width: 900px)  {
  .hs-feat__rail {
    --cards: 3;
  }
}

@media (min-width: 1200px) {
  .hs-feat__rail {
    --cards: 4;
  }
}

.hs-feat__rail .hs-feat__card {
  flex: 0 0 auto;
  width: calc(
    (min(1200px, 100vw - 40px) - (var(--cards) - 1) * var(--gap, 20px)) / var(--cards)
  );
  /* The 200px on .hs-feat__card is a floor here, not a height. A card whose
     description runs to four lines was overflowing its own sheet, and every
     rail on the site was one long sentence away from doing it. The group is a
     flex row with the default stretch, so dropping the fixed height lets all
     the cards in a rail take the height of the tallest one: they still match,
     they simply match at whatever the copy needs. */
  height: auto;
  min-height: 200px;
  /* Was a grid item ending against the bottom of its row; in a marquee track
     there is no row to end against. */
  align-self: auto;
}

/* ---- a card ---- */

/* Near-white rather than white, over a blur: the photograph behind stays
   faintly present at the edges, which is what stops six opaque rectangles from
   reading as a table dropped onto a landscape. It stops at 0.94 because the
   body copy has to survive whatever the picture is doing underneath — the same
   limit the hero's card ran into. */

.hs-feat__card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* A fixed height, so all six match without depending on which row they are
     in or how long their description runs. The content is centred inside it,
     which is what lets a one-line card and a three-line one look like the same
     card rather than one of them sitting high in its box. */
  height: 200px;
  /* The text block is taller than 200px, so the first row's track is taller
     than the cards in it. Ending them against the bottom of the track lines
     their feet up with the foot of the text block instead of leaving them
     floating in the middle of a row that is not their size. */
  align-self: end;
  gap: 18px;
  padding: 26px 24px 28px;
  border-radius: 26px;
  background: linear-gradient(
    160deg,
    rgba(255, 255, 255, 0.97) 0%,
    rgba(255, 255, 255, 0.94) 100%
  );
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  box-shadow:
    0 1px 2px rgba(16, 24, 48, 0.06),
    0 22px 50px -30px rgba(16, 24, 48, 0.45);
  transition: transform 320ms var(--ease-smooth), box-shadow 320ms var(--ease-smooth);
}

.hs-feat__card:hover {
  transform: translate3d(0, -4px, 0);
  box-shadow:
    0 1px 2px rgba(16, 24, 48, 0.06),
    0 30px 60px -28px rgba(16, 24, 48, 0.5);
}

/* Mark first, then the name, both on one line and both starting from the left
   edge of the card. Pushed to opposite ends the two read as unrelated — a
   label on one side and a badge on the other; side by side the mark belongs to
   the words next to it.

   Centred rather than top-aligned so a name that wraps to two lines still sits
   level with the disc instead of hanging below it. */

.hs-feat__top {
  display: flex;
  align-items: center;
  gap: 14px;
}

.hs-feat__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.2px;
  color: #0B0D12;
}

/* A circle, not the rounded square the rest of the page uses: on a card with
   no border of its own it is the one hard shape, and a disc reads as a mark
   where a square reads as a second, smaller card. */

.hs-feat__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: 100px;
  background-color: #0B0D12;
  color: #ffffff;
}

.hs-feat__icon .hs-i {
  width: 20px;
  height: 20px;
}

.hs-feat__text {
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
  color: #5A6070;
}

/* ------------------------------------------------------------------
   Split — artwork one side, copy and reasons the other
   ------------------------------------------------------------------ */

.hs-split {
  display: grid;
  gap: 44px;
  align-items: center;
}

@media (min-width: 1024px) {
  .hs-split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 80px;
  }
}

.hs-split__frame {
  overflow: hidden;
  border-radius: 24px;
  background-color: #e4eaf9;
  box-shadow:
    0 30px 70px -34px rgba(16, 24, 48, 0.42),
    0 2px 10px rgba(16, 24, 48, 0.1);
}

.hs-split__title {
  margin-top: 22px;
}

/* The payroll page's pay-runs heading, held at 30px where the shared
   .section-title scale runs 34px up to 48px. Two classes deep on purpose: a
   single class ties with the Tailwind size utility it has to beat, and which
   of the two won would then depend on where they landed in the file. The HRMS
   page's split heading is untouched and keeps the scale. */

.hs-split .hs-split__title--sm {
  font-size: 30px;
}

.hs-split__lead {
  margin-top: 18px;
  max-width: 460px;
}

.hs-reasons {
  display: grid;
  gap: 12px;
  margin-top: 32px;
  padding: 0;
  list-style: none;
}

/* The skills-matrix benefits section runs its head across the content instead
   of inside the right-hand column, so the split below holds only the artwork
   and the list. The list is the whole column now and has nothing above it to
   clear. */

.sk-ben__split {
  margin-top: 48px;
}

.sk-ben__split .hs-reasons {
  margin-top: 0;
}

@media (min-width: 560px) {
  .hs-reasons {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.hs-reason {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-radius: 14px;
  background-color: #F4F6FB;
  font-size: 15px;
  font-weight: 500;
  color: #22262F;
}

.hs-reason__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  background-color: #ffffff;
  color: #2563EB;
  box-shadow: 0 1px 3px rgba(16, 24, 48, 0.12);
}

/* ------------------------------------------------------------------
   Comparison tables
   Shared by both comparisons on the page — see sections/hrms/_table.php.

   An ordinary continuous table: one bordered block, collapsed borders, rules
   running the full width. The recommended column is marked by its ground
   rather than by being cut away from the others.
   ------------------------------------------------------------------ */

.hs-tinted {
  background-color: #F7F9FD;
}

.hs-table-wrap {
  margin-top: 46px;
  overflow: hidden;
  border-radius: 18px;
  border: 1px solid rgba(16, 24, 48, 0.1);
  background-color: #ffffff;
  box-shadow: 0 24px 60px -40px rgba(16, 24, 48, 0.45);
}

/* The table scrolls inside this box; the page never does. `tabindex` is on the
   element in the markup so a keyboard can reach the scroll area — a region
   only a mouse or a wheel can pan is unreachable for anyone else. */

.hs-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.hs-table-scroll:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: -2px;
}

.hs-table {
  width: 100%;
  min-width: 700px;
  border-collapse: collapse;
  text-align: left;
}

/* Compressed: six rows of two or three words do not need 20px of air above
   and below each one. */

.hs-table th,
.hs-table td {
  padding: 13px 20px;
  vertical-align: middle;
}

.hs-table thead th {
  background-color: #1A1F35;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -0.1px;
  color: #ffffff;
  white-space: nowrap;
}

/* The two verdict headers are centred over their columns; only the row-label
   column reads as a left-aligned heading. */

.hs-table thead th:not(.hs-table__rowhead) {
  text-align: center;
}

.hs-table tbody tr + tr {
  border-top: 1px solid rgba(16, 24, 48, 0.07);
}

/* Banded rows, very lightly — the recommended column carries a stronger tint
   of its own, and two competing stripes make the table look like a
   spreadsheet. */

.hs-table tbody tr:nth-child(even) {
  background-color: #F8FAFC;
}

/* The row label. Sticky so it stays put while the two verdict columns pan
   underneath on a narrow screen — scrolled away, a row of two answers with no
   question is unreadable. Opaque background because a sticky cell paints over
   what passes beneath it. */

.hs-table__rowhead {
  position: sticky;
  left: 0;
  z-index: 1;
  min-width: 180px;
  font-size: 14.5px;
  font-weight: 500;
  color: #22262F;
  background-color: #ffffff;
}

.hs-table thead .hs-table__rowhead {
  background-color: #1A1F35;
  color: #ffffff;
  font-weight: 600;
}

.hs-table tbody tr:nth-child(even) .hs-table__rowhead {
  background-color: #F8FAFC;
}

/* The recommendation column, tinted the whole way down so the answer reads as
   a column rather than as six separate cells. */

.hs-table__win {
  background-color: rgba(37, 99, 235, 0.045);
}

.hs-table tbody tr:nth-child(even) .hs-table__win {
  background-color: rgba(37, 99, 235, 0.08);
}

/* The site's primary, and the same gradient .btn-primary uses rather than a
   flat sample of it — the header of the column being recommended should be
   the brand, not a colour that merely resembles it. */

.hs-table thead .hs-table__win {
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
}

.hs-table__winlabel {
  display: inline-block;
  vertical-align: middle;
}

.hs-table__pill {
  display: inline-block;
  vertical-align: middle;
  margin-left: 10px;
  padding: 4px 11px;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.24);
  font-size: 12px;
  font-weight: 500;
  color: #ffffff;
}

/* ---- a verdict ---- */

.hs-verdict {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.35;
  color: #22262F;
}

.hs-verdict__mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 100px;
}

/* Amber, not red. The left-hand column is not wrong — it is the harder way
   round — and a red cross states something the row does not. */

.hs-verdict__mark--warn {
  background-color: #FDF0D9;
  color: #E9A23B;
}

.hs-verdict__mark--yes {
  background-color: #DCF5EA;
  color: #17A673;
}

/* Verdicts sit against the left edge of their column, not centred in it.
   Centred, every row started at a different x — the mark for "Separate Tools"
   sat well left of the one for "Basic" — so the two columns of icons read as
   ragged rather than as a column. Left-aligned they stack.

   The headers stay centred: they label the whole column rather than belonging
   to any row. */

.hs-table td {
  text-align: left;
}

/* ------------------------------------------------------------------
   The verdict callout under the second table
   ------------------------------------------------------------------ */

.hs-verdictbox {
  margin-top: 30px;
  margin-left: auto;
  margin-right: auto;
  max-width: 880px;
  padding: 30px;
  border-radius: 22px;
  border: 1px solid rgba(236, 72, 153, 0.16);
  background: linear-gradient(180deg, rgba(253, 242, 248, 0.9) 0%, rgba(253, 246, 250, 0.7) 100%);
  text-align: center;
}

@media (min-width: 768px) {
  .hs-verdictbox {
    padding: 36px 44px;
  }
}

.hs-verdictbox__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(20px, 2.4vw, 26px);
  font-weight: 600;
  letter-spacing: -0.4px;
  color: #0B0D12;
}

.hs-verdictbox__text {
  margin-top: 14px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.6;
  color: #5A6070;
}

/* The line above the stack. */

.hs-steps__kicker {
  margin-top: 40px;
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #8A90A0;
}

/* ------------------------------------------------------------------
   Workflow — the sticky stack

   Six full-width cards, each `position: sticky` at the same offset and laid
   out one after another in flow. Card 02 travels up from below and lands
   exactly on card 01; 03 lands on 02; and so on. The scrollbar drives it by
   definition — there is no script following the scroll and no pin-spacer.

   It releases itself, too: the last card is the last thing in the container,
   so once it lands there is nothing holding the container open. The tail below
   is the only thing that keeps it there a moment longer.

   Nothing in the ancestry may become a scroll container or the sticky stops
   sticking. `overflow-x: clip` on <body> is safe — clip does not create one,
   which is why the showcase's pinned stage works too — but an `overflow:
   hidden` added to .section or .content later would silently kill this.
   ------------------------------------------------------------------ */

.hs-stack {
  /* Clears the fixed navbar with room to breathe. One number, used by every
     card, so they land on the same line. */
  --stack-top: calc(var(--nav-h) + 24px);
  margin-top: 30px;
}

@media (min-width: 768px) {
  .hs-stack {
    --stack-top: calc(var(--nav-h) + 32px);
    margin-top: 44px;
  }
}

/* The hold after card 06, and it is load-bearing.

   A sticky element is constrained to its containing block's CONTENT box, so
   padding on .hs-stack does not extend its range — that was tried, and card 06
   still landed and was carried off in the same gesture. An actual child does
   extend it, so this is an empty div rather than a padding value.

   It is what "release the stack after the last card, not before" means in CSS:
   for as long as this is tall, 06 stays on the sticky line; the moment it runs
   out, the stack scrolls away with the page and the next section takes over.

   A fraction of the viewport rather than a fixed height — a comfortable hold on
   a laptop is an interminable one on a tall monitor. */

.hs-stack__tail {
  height: 38vh;
}

@media (min-width: 768px) {
  .hs-stack__tail {
    height: 46vh;
  }
}

.hs-stack__card {
  position: sticky;
  top: var(--stack-top);
  overflow: hidden;
  border-radius: 24px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #ffffff;
  /* Deeper than a card sitting on a page would need, because it is doing a
     second job: with every card the same white, the only thing marking where
     one ends and the card covering it begins is the shadow the arriving card
     casts onto it. Two layers — a tight one for the edge itself, a wide soft
     one for the lift. */
  box-shadow:
    0 2px 6px -2px rgba(16, 24, 48, 0.16),
    0 30px 70px -34px rgba(16, 24, 48, 0.7);
  /* Scaled about its top edge, not its middle. js/steps-stack.js eases the
     covered card back to 0.97, and from the centre that lifts its top edge
     away from the sticky line — the card appears to shrink upward out of the
     stack instead of settling into it. */
  transform-origin: 50% 0%;
  /* The card underneath is only ever seen through the gap above the card
     covering it, so the transition is on the whole card and nothing inside it
     needs its own. easeOutQuint — the same curve as --ease-smooth,
     cubic-bezier(0.22, 1, 0.36, 1) — decelerating to a stop with nothing past
     1 to overshoot with. */
  transition: transform 700ms var(--ease-smooth);
  will-change: transform;
}

/* Cards meet edge to edge: the travel a card needs to reach the sticky line is
   the height of the one before it, and a gap would only add empty scroll
   between two things that are meant to overlap. */

.hs-stack__card + .hs-stack__card {
  margin-top: 26px;
}

.hs-stack__inner {
  display: grid;
  gap: 26px;
  padding: 34px 26px 38px;
  /* Generous, and tall enough that a card reads as a panel rather than a strip
     — but capped against the viewport so a short laptop screen still shows a
     whole card between the navbar and the fold. */
  min-height: min(420px, 58vh);
  align-content: center;
}

@media (min-width: 768px) {
  .hs-stack__inner {
    grid-template-columns: 150px minmax(0, 1fr);
    gap: 48px;
    padding: 56px 56px 60px;
    min-height: min(460px, 60vh);
    align-items: center;
  }
}

@media (min-width: 1024px) {
  .hs-stack__inner {
    grid-template-columns: 190px minmax(0, 1fr);
    gap: 70px;
    padding: 64px 72px 68px;
  }
}

/* ---- the number ---- */

/* Holds the numeral alone since the mark moved in beside the title, so there
   is nothing left here to lay out. */

.hs-stack__aside {
  display: block;
}

.hs-stack__num {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(40px, 7vw, 68px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  color: #2563EB;
}

/* Above the title now rather than under the number: it reads as the mark for
   the step's name, which is what it is, instead of as a second badge competing
   with the numeral. */

.hs-stack__icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-bottom: 22px;
  border-radius: 15px;
  background-color: #F1F4FA;
  color: #0B0D12;
}

.hs-stack__icon .hs-i {
  width: 25px;
  height: 25px;
}

/* ---- the copy ---- */

.hs-stack__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(23px, 3.2vw, 34px);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.5px;
  color: #0B0D12;
}


.hs-stack__text {
  margin-top: 14px;
  max-width: 640px;
  font-size: clamp(15px, 1.5vw, 18px);
  font-weight: 500;
  line-height: 1.6;
  color: #5A6070;
}

/* The stack is the animation, and it is scroll position rather than motion —
   it cannot be "turned off" without turning the layout off with it. What can
   go is the recede, so the cards simply cover one another. */

@media (prefers-reduced-motion: reduce) {
  .hs-stack__card {
    transition: none !important;
    transform: none !important;
  }
}

/* ------------------------------------------------------------------
   Industries — the pinned rail

   A tall track holds a sticky stage; the surplus track height is the
   horizontal travel. The pin is CSS, so no pin-spacer is injected and the
   sections either side keep their normal flow.
   ------------------------------------------------------------------ */

.hs-rail {
  /* Height of the fixed navbar the stage tucks under — matches the showcase. */
  --rail-top: var(--nav-h);
  /* The gutter the row is inset by at both ends, which is what lines the first
     card up with the heading above it and keeps the last card off the right
     edge when it arrives. Tracks the shell's own edge on a wide screen and
     falls back to its 20px padding once the shell fills the viewport. */
  --rail-inset: max(20px, calc((100vw - 1220px) / 2));
  /* The stage owns the vertical spacing; the section's own padding would be
     added to the track and paid for in scroll distance. */
  padding-top: 0;
  padding-bottom: 0;
}

/* One stage-height plus the travel. --rail-travel is measured and set by
   js/industries-pan.js — it cannot be written here, because the travel is the
   row's width less the viewport's and the row's width follows the card size,
   which follows the viewport height. With no JS it stays 0 and the section is
   simply a stage tall, with the row scrollable by hand. */

.hs-rail__track {
  position: relative;
  height: calc(100vh - var(--rail-top) + var(--rail-travel, 0px));
}

.hs-rail__stage {
  position: sticky;
  top: var(--rail-top);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(24px, 4vh, 52px);
  height: calc(100vh - var(--rail-top));
}

/* Full bleed: the row runs to both screen edges rather than stopping at the
   1200px column. A rail that ends in white gutters reads as a widget sitting
   on the page rather than as the page.

   It is a real scroll container, not just a mask — without JS, and under
   prefers-reduced-motion, that is the whole feature. `is-panning` locks the
   native scroll when the script takes over so the two cannot fight over the
   same axis. */

.hs-rail__clip {
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
}

.hs-rail__clip.is-panning {
  overflow: hidden;
}

.hs-rail__clip:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: 4px;
}

/* ==========================================================================
   PHONES — a rail that stops being a rail

   A rail marked data-rail-stack gives up the pin below 768 and goes back to
   ordinary flow: no sticky stage, no travel, no horizontal scroll. The same
   attribute tells js/industries-pan.js to leave it alone, so the row keeps its
   own transform and the cards keep their own opacity.

   Only the scaffolding is here. What the row becomes once it is free of the
   rail — one column for the lifecycle cards, two for the industry tiles — is
   each section's own business and sits with its own rules.

   Specificity, not order: [data-rail-stack] .hs-rail__stage outweighs the bare
   .hs-rail__stage above whatever the file does afterwards.
   ========================================================================== */

@media (max-width: 767px) {
  /* .hs-rail zeroes the section's padding on the grounds that the stage owns
     the vertical spacing — true while the stage is a viewport tall and centres
     what is in it, and false the moment it is not. Without this the tinted
     ground starts on the badge's top edge. Later in the file than .hs-rail and
     .section, which is what settles it: all three weigh the same.

     .lfx sets its own 24/40 further down and keeps it. */
  [data-rail-stack] {
    padding-top: 40px;
    padding-bottom: 40px;
  }

  /* Was one stage-height plus the travel. With no travel there is nothing for
     it to be but the height of what is in it. */
  [data-rail-stack] .hs-rail__track {
    height: auto;
  }

  /* Unstuck and unsized, so the centring that used to drop the heading a third
     of the way down the screen has nothing left to centre. */
  [data-rail-stack] .hs-rail__stage {
    position: static;
    height: auto;
  }

  /* The clip was a real horizontal scroll container, which is what a rail
     degrades to without JS. Nothing left to scroll, and a hidden overflow
     would only clip the card shadows. */
  [data-rail-stack] .hs-rail__clip {
    overflow: visible;
  }
}

.hs-inds {
  display: flex;
  flex-wrap: nowrap;
  width: -moz-max-content;
  width: max-content;
  gap: clamp(14px, 1.6vw, 22px);
  padding: 10px var(--rail-inset) 30px;
  margin: 0;
  list-style: none;
}

/* Sized by HEIGHT, with the width following from the 4:5 ratio. The stage is
   one viewport tall and has a heading in it, so the cards have to be measured
   against the viewport's height rather than its width — set by width they
   would be too tall to fit on a laptop in landscape. */

.hs-ind {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  flex: 0 0 auto;
  height: clamp(230px, 46vh, 380px);
  aspect-ratio: 4 / 5;
  border-radius: 20px;
  background-color: #EDF1F4;
  box-shadow: 0 18px 44px -30px rgba(16, 24, 48, 0.6);
  /* The focus effect: cards away from the middle of the rail sit back a
     little. js/industries-pan.js writes the values, this curve carries them —
     and it is short, because the values change every frame the reader scrolls
     and a long transition would lag behind the scroll rather than smooth it. */
  transition: opacity 260ms var(--ease-smooth), transform 260ms var(--ease-smooth);
}

.hs-ind__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
}

/* Everything readable sits inside this, never on bare photography — the same
   rule the impact cards follow. Two stops rather than a flat wash: solid where
   the label is, gone by halfway, so the picture is still a picture. */

/* A card whose photograph has not arrived. The icon and the label are both
   white, so the pale tile they normally sit on top of a picture over would
   swallow them; this puts a dark ground under them instead. It is a tile that
   looks deliberate rather than one that looks broken, and it disappears the
   moment the file lands. */

.hs-ind--bare {
  background-image: linear-gradient(150deg, #2B3446 0%, #151A24 100%);
}

.hs-ind__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    0deg,
    rgba(8, 9, 13, 0.88) 0%,
    rgba(8, 9, 13, 0.45) 28%,
    rgba(8, 9, 13, 0) 58%
  );
}

.hs-ind__icon {
  position: absolute;
  top: 14px;
  left: 14px;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 11px;
  background-color: rgba(255, 255, 255, 0.16);
  color: #ffffff;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.hs-ind__icon .hs-i {
  width: 18px;
  height: 18px;
}

.hs-ind__label {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: 0 16px 16px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: #ffffff;
}

@media (min-width: 768px) {
  .hs-ind__label {
    padding: 0 18px 18px;
    font-size: 17px;
  }
}

/* ---- phones: two columns, not a rail ------------------------------------

   The pin is already off by here (data-rail-stack on the section, handled up
   by .hs-rail); this is what the row becomes without it. Two across rather
   than one, because these tiles are a photograph and a word — a full-width
   one is a banner, and ten banners is a longer scroll than the rail it
   replaced.

   The cards were sized by HEIGHT, which is what a rail on a viewport-tall
   stage needs: height first, width from the 4:5. In a grid the column decides
   the width, so the ratio is read the other way round and the height follows.

   After .hs-ind rather than inside the block above: a media query carries no
   specificity of its own, and .hs-ind's own height would otherwise outlast
   this by sitting later in the file. */

@media (max-width: 767px) {
  .hs-inds {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    width: auto;
    gap: 14px;
    padding: 0 var(--rail-inset) 4px;
  }

  .hs-ind {
    width: auto;
    height: auto;
    aspect-ratio: 4 / 5;
  }
}

/* No pin and no travel: the stage sits in normal flow and the row is an
   ordinary horizontal scroller the reader moves themselves. The rail is a
   scroll position rather than a motion, but converting one axis into the other
   is not something to do to somebody who has asked for less of it. */

@media (prefers-reduced-motion: reduce) {
  .hs-rail__track {
    height: auto !important;
  }

  .hs-rail__stage {
    position: static;
    height: auto;
    padding-top: 70px;
    padding-bottom: 70px;
  }

  .hs-ind {
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ------------------------------------------------------------------
   Testimonial
   The founder's note treatment, deliberately: same pale ground, same head
   with a framed thumbnail opposite, same left-aligned measure. It replaced
   a dark gradient panel with a centred pull-quote and an oversized quote
   mark, which was the only place on the page raising its voice. A quote is
   more credible set quietly.
   ------------------------------------------------------------------ */

.hs-note {
  position: relative;
  /* isolation, as on .fn: it makes this card its own stacking context, which
     is what lets the meadow below sit at z-index -1 — above the card's own
     ground, behind everything that has to be read. Without it the -1 would
     put the image behind the background colour and it would never be seen. */
  isolation: isolate;
  overflow: hidden;
  margin-left: auto;
  margin-right: auto;
  max-width: 940px;
  padding: 30px 24px 32px;
  border-radius: 30px;
  /* White at the top where the quote is read, deepening to indigo at the foot.
     A gradient rather than an image: it is a colour ramp, so a file would be
     kilobytes to say what two stops say, and it would have to be resized for
     every width this card is used at. The meadow still sits over it in the
     bottom-right corner, at z-index -1. */
  background-color: #EDF1F4;
  /* The brand blue, tinted: #2563EB at low saturation across four stops, pale
     at the top where the quote is read and deepest at the foot. Light enough
     that the name and the role under it stay in ink rather than needing to be
     reversed out. */
  background-image: linear-gradient(180deg,
      #F7F9FD 0%,
      #EDF2FE 38%,
      #DAE5FC 72%,
      #C2D4F8 100%);
}

/* A quotation mark, set large and faint in the corner the meadow used to
   occupy. It is what the card is: somebody said something. Drawn as a glyph in
   the display face rather than as an image, at z-index -1 so it sits over the
   gradient and under everything that has to be read.

   aria-hidden is not needed: generated content is not in the accessibility
   tree, and the real quote marks are in the copy itself. */

.hs-note::after {
  content: '\201C';
  position: absolute;
  right: 3%;
  bottom: -14%;
  z-index: -1;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 300px;
  font-weight: 700;
  line-height: 1;
  color: rgba(37, 99, 235, 0.10);
  pointer-events: none;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}

@media (max-width: 700px) {
  .hs-note::after {
    font-size: 190px;
    right: 2%;
    bottom: -10%;
  }
}

/* ---- the meadow ----
   The founder's note's own .fn__grass, on the card that borrows that note's
   treatment. Same image, same corner, same masked left edge and the same
   drift, so the two read as one component used twice rather than two cards
   that happen to be a similar colour. */

.hs-note__grass {
  position: absolute;
  right: -2%;
  bottom: -1px;
  /* kills the hairline the browser can leave under a
                        scaled image sitting exactly on the card's edge */
  z-index: -1;
  width: 42%;
  height: auto;
  pointer-events: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  /* TWO MASKS, INTERSECTED.
     Horizontal, because the PNG has a straight left edge: off-screen in the
     hero, but inside the card here, where it reads as a seam — so it is
     dissolved into the ground over the first fifth of the image.

     Vertical, because this card is shorter than the founder's note's and the
     quote runs across the meadow's crest. Fading the top means the hilltop
     thins out to nothing exactly where type can reach it, whatever the card's
     height or the quote's length — rather than the meadow being kept small
     enough to miss one particular sentence.

     Where mask-composite is not supported the layers add instead of
     intersecting, which lands back on roughly the horizontal-only behaviour.
     That is the right way for this to fail. */
  -webkit-mask-image:
      linear-gradient(to right, transparent 0%, #000 20%),
      linear-gradient(to bottom, transparent 0%, #000 62%);
  mask-image:
      linear-gradient(to right, transparent 0%, #000 20%),
      linear-gradient(to bottom, transparent 0%, #000 62%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

/* On phones the card is narrow and the quote fills it, so the meadow is a band
   along the foot rather than a corner it would otherwise sit on top of. */

@media (max-width: 639px) {
  .hs-note__grass {
    right: -8%;
    width: 108%;
    opacity: 0.55;
  }
}

/* It drifts once the entrance is over. Gated on .reveal-done, which
   animations.js adds 900ms after an element has revealed — .reveal.is-visible
   sets `transform`, and an animation on the same property would override it
   mid-fade and make the entrance jump. */

.hs-note__grass.reveal-done {
  --float-y: -7px;
  animation: fx-float 9s ease-in-out infinite;
}

@media (min-width: 768px) {
  .hs-note {
    padding: 44px 48px;
  }
}

@media (min-width: 1024px) {
  .hs-note {
    padding: 52px 64px;
  }
}

.hs-note__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
}

.hs-note__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 28px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: #0B0D12;
}

.hs-note__kicker {
  margin-top: 6px;
  font-size: 15px;
  font-weight: 500;
  color: #5A6070;
}

/* No portrait on file, so the frame holds the mark rather than a stock face,
   which would be claiming something about a real person. Dashed, so it reads
   as a placeholder instead of pretending to be a photograph. */

.hs-note__frame {
  display: grid;
  flex: none;
  place-items: center;
  width: 84px;
  height: 84px;
  padding: 6px;
  border: 1.5px dashed #B7C2CE;
  border-radius: 18px;
  /* White inside the dashed mount, as the founder's note does for the same
     fallback. Against the card's pale grey the mark floated as a dark tile
     with nothing under it; on white it reads as something mounted in the
     frame, which is what the dashes are drawing. */
  background-color: #ffffff;
}

@media (min-width: 768px) {
  .hs-note__frame {
    width: 100px;
    height: 100px;
    padding: 7px;
    border-radius: 22px;
  }
}

/* The mark is a logo, not a photograph: contained rather than cropped to
   fill, or it would be cut off at its own edges. */

.hs-note__frame img {
  width: 62%;
  height: 62%;
  -o-object-fit: contain;
     object-fit: contain;
}

/* The monogram that stands in until a photograph exists. Same idea as
   .t-avatar on the home page: initials on the brand gradient, sized to the
   mount it fills. */

.hs-note__mono {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  border-radius: 14px;
  background-image: linear-gradient(140deg, #4F8DFB 0%, #2F6FE8 55%, #2657D6 100%);
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 26px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #ffffff;
}

@media (min-width: 768px) {
  .hs-note__mono {
    border-radius: 17px;
    font-size: 31px;
  }
}

/* A real portrait is the opposite case — it fills the mount and is cropped to
   it, and the dashed border goes solid because there is nothing placeholder
   about it any more. */

.hs-note__frame--photo {
  padding: 0;
  border-style: solid;
  border-color: rgba(16, 24, 48, 0.1);
  overflow: hidden;
}

.hs-note__frame--photo img {
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  border-radius: 16px;
}

@media (min-width: 768px) {
  .hs-note__frame--photo img {
    border-radius: 20px;
  }
}

.hs-note__quote {
  margin-top: 34px;
  max-width: 620px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(21px, 2.6vw, 27px);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.4px;
  color: #0B0D12;
}

/* The quote is one sentence and should read as one. From 768px up the 620px
   measure comes off so a short quote holds its line inside the card's own
   width, rather than being broken over two by a cap narrower than the card.

   It used to be `white-space: nowrap`, which held the line by refusing to wrap
   at all — fine for the one sentence it was tuned against, and a clipped
   overflow for the longer quote on the payroll page. text-wrap: balance does
   the job the nowrap was there for without that failure mode: a quote that
   fits stays on one line, and one that does not breaks into even lines instead
   of running off the card. */

@media (min-width: 768px) {
  .hs-note__quote {
    max-width: none;
    text-wrap: balance;
  }
}

.hs-note__by {
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid rgba(16, 24, 48, 0.12);
}

.hs-note__name {
  display: block;
  font-size: 15px;
  font-weight: 600;
  color: #0B0D12;
}

.hs-note__role {
  display: block;
  margin-top: 3px;
  font-size: 14px;
  font-weight: 500;
  color: #1D1D1D;
}

/* ------------------------------------------------------------------
   Closing CTA
   ------------------------------------------------------------------ */

/* The closing CTA sets dark type over a sunset photograph, which is the one
   place on the page where the scenic treatment and the type collide: the
   picture is busy edge to edge and has no quiet corner for a heading to sit
   in. This lifts a bright pool under the copy — brightest where the text is,
   thinning to nothing at the edges so the photograph is still a photograph.
   Cheaper than a second image and it survives the file being swapped. */

.hs-cta .hs-scenic__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    62% 58% at 50% 50%,
    rgba(255, 255, 255, 0.72) 0%,
    rgba(255, 255, 255, 0.4) 42%,
    rgba(255, 255, 255, 0.1) 74%,
    rgba(255, 255, 255, 0) 100%
  );
}

.hs-cta__body {
  margin-left: auto;
  margin-right: auto;
  max-width: 720px;
  text-align: center;
}

/* The marketplace CTA is one sentence and is set on one line. It needs about
   810px at the 48px display size, so this page's block gets its own measure
   rather than the shared 720px, which broke it after "Marketplace". Scoped to
   the section so every other closing CTA keeps the narrower measure. */

#vm-demo .hs-cta__body {
  max-width: 880px;
}

/* Near-black, not the .section-lead grey it would otherwise inherit. That grey
   is chosen for body copy on white; here the paragraph sits on a photograph,
   and even over the bright pool above it the grey reads as washed out against
   the heading right on top of it. The heading and the sentence under it are
   one block of copy, so they are one colour. */

.hs-cta__lead {
  margin-top: 18px;
  color: #0B0D12;
}

.hs-cta__row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin-top: 34px;
}

@media (min-width: 480px) {
  .hs-cta__row {
    flex-direction: row;
    justify-content: center;
  }
}

/* ------------------------------------------------------------------
   FAQ
   ------------------------------------------------------------------ */

.hs-faq {
  display: grid;
  gap: 44px;
}

@media (min-width: 1024px) {
  .hs-faq {
    grid-template-columns: minmax(0, 420px) minmax(0, 1fr);
    gap: 70px;
  }
}

.hs-faq__lead {
  margin-top: 20px;
  max-width: 340px;
}

.hs-faq__card.card {
  margin-top: 40px;
  padding: 30px;
  border-radius: 24px;
}

.hs-faq__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 14px;
  background-color: #0B0D12;
  color: #ffffff;
}

.hs-faq__cardtitle {
  margin-top: 22px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.3px;
  color: #0B0D12;
}

.hs-faq__cardtext {
  margin-top: 8px;
  margin-bottom: 24px;
  font-size: 15px;
  font-weight: 500;
  color: #5A6070;
}

.hs-faq__list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.hs-faq__q {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 24px 28px;
  text-align: left;
}

.hs-faq__qtext {
  font-size: 16px;
  font-weight: 500;
  color: #0B0D12;
}

/* The +/− sign. .faq-sign positions and colours the two bars and animates
   them; their size comes from utility classes in the home page's markup, so
   this page states it instead — the shared rule has no dimensions of its own. */

.hs-faq__sign {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 100px;
  background-color: #0B0D12;
}

.hs-faq__sign span:first-child {
  width: 11px;
  height: 2px;
  border-radius: 100px;
}

.hs-faq__sign span:last-child {
  width: 2px;
  height: 11px;
  border-radius: 100px;
}

.hs-faq__a {
  padding: 0 28px 28px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.55;
  color: #5A6070;
}

/* =====================================================================
 * DEMO VIDEO MODAL — includes/video-modal.php + js/video-modal.js
 * ================================================================== */

/* The play badge inside a "View demo" button. Solid ink on the white
   button, so it reads as the one thing to press even at a glance. */

.btn-play {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 100px;
  background-color: #0B0D12;
  color: #ffffff;
}

.btn-play svg {
  width: 9px;
  height: 11px;
  margin-left: 1px;
  /* optical centring: a triangle's mass sits left of centre */
}

/* The dialog is only a positioning box — the UA's border, padding and white
   ground all come off so the panel inside is the whole of what shows. */

.vmodal {
  margin: auto;
  padding: 0;
  border: 0;
  max-width: none;
  max-height: none;
  background: transparent;
  overflow: visible;
}

.vmodal::backdrop {
  background-color: rgba(6, 8, 14, 0.72);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}

/* 16:9 held by aspect-ratio, and the third term of the min() caps the width
   by the height the viewport can actually give it — so on a short window the
   panel shrinks rather than running off the top and bottom. */

.vmodal__frame {
  position: relative;
  width: min(1120px, 92vw, (100vh - 120px) * 16 / 9);
  aspect-ratio: 16 / 9;
  border-radius: 22px;
  overflow: hidden;
  background-color: #000000;
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.7);
}

.vmodal__video {
  display: block;
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
}

/* Inside the frame rather than floating above it: at 92vw on a phone there is
   no room above the panel for a control, and one position that works
   everywhere beats two that each work in one place. Top-right, clear of the
   player's own controls along the bottom. */

.vmodal__close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 100px;
  color: #ffffff;
  background-color: rgba(11, 13, 18, 0.55);
  -webkit-backdrop-filter: blur(4px);
          backdrop-filter: blur(4px);
  transition:
    background-color 200ms var(--ease-soft),
    transform 200ms var(--ease-smooth);
}

.vmodal__close:hover {
  background-color: rgba(11, 13, 18, 0.85);
  transform: scale(1.06);
}

.vmodal__close svg {
  width: 14px;
  height: 14px;
}

.vmodal__fallback {
  padding: 24px;
  font-size: 15px;
  color: #ffffff;
}

.vmodal__fallback a {
  text-decoration: underline;
}

@media (min-width: 768px) {
  .vmodal__close {
    top: 18px;
    right: 18px;
  }
}

/* Open only — a dialog animates in and is dismissed flat, which is the usual
   asymmetry: arriving wants a beat, leaving wants to be gone. */

@media (prefers-reduced-motion: no-preference) {
  .vmodal[open] {
    animation: vmodal-rise 300ms var(--ease-smooth) both;
  }

  .vmodal[open]::backdrop {
    animation: vmodal-fade 300ms ease both;
  }
}

@keyframes vmodal-rise {
  from {
    opacity: 0;
    transform: translateY(16px) scale(0.97);
  }

  to   {
    opacity: 1;
    transform: none;
  }
}

@keyframes vmodal-fade {
  from {
    opacity: 0;
  }

  to   {
    opacity: 1;
  }
}

/* ==========================================================================
   BOOKING MODAL
   The scheduler in a panel rather than a page the reader is sent to. Shares
   the video modal's dialog treatment above — same backdrop, same close chip,
   same open-only animation — because they are the same object at two sizes,
   and the panel itself is white rather than black: this one holds an
   interface, not a film.
   ========================================================================== */

.bkmodal {
  margin: auto;
  padding: 0;
  border: 0;
  max-width: none;
  max-height: none;
  background: transparent;
  overflow: visible;
}

.bkmodal::backdrop {
  background-color: rgba(6, 8, 14, 0.72);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}

/* Portrait rather than the film's 16:9: a booking flow is a column of a month,
   a day and a form. Both terms of each min() are caps, so the panel shrinks to
   fit a short window or a narrow one instead of running off the edge of it. */

.bkmodal__frame {
  display: flex;
  flex-direction: column;
  width: min(880px, 94vw);
  height: min(760px, 88vh);
  border-radius: 22px;
  overflow: hidden;
  background-color: #FFFFFF;
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.55);
}

/* A real header, not a close button floating over somebody else's interface.
   The frame below belongs to another origin and we cannot know what is under
   the top-right corner of it, so the control gets a strip of its own. */

.bkmodal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex: none;
  padding: 16px 16px 14px 22px;
  border-bottom: 1px solid rgba(221, 229, 237, 0.9);
}

.bkmodal__title {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
  color: #22262F;
}

.bkmodal__close {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 100px;
  color: #5B6472;
  background-color: #F1F4F9;
  transition:
    background-color 200ms var(--ease-soft),
    color 200ms var(--ease-soft),
    transform 200ms var(--ease-smooth);
}

.bkmodal__close:hover {
  background-color: #E4E9F2;
  color: #22262F;
  transform: scale(1.06);
}

.bkmodal__close svg {
  width: 13px;
  height: 13px;
}

/* position: relative so the spinner and the failure message can sit over the
   frame's own box rather than pushing it around. */

.bkmodal__body {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  background-color: #FAFBFD;
}

.bkmodal__frameel {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  opacity: 0;
  transition: opacity 300ms var(--ease-soft);
}

/* Added by js/book-modal.js on the frame's load event. Without it the panel
   shows a white rectangle for as long as the third-party app takes to paint,
   and a blank sheet reads as broken where a spinner reads as loading. */

.bkmodal__frameel.is-in {
  opacity: 1;
}

.bkmodal__wait {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}

/* `display: grid` above outranks the browser's own [hidden] rule, so without
   this the script's `wait.hidden = true` does nothing and the spinner turns
   round behind the loaded scheduler for the rest of the session. Same guard as
   .bkmodal__fail[hidden] below, for the same reason. */

.bkmodal__wait[hidden] {
  display: none;
}

.bkmodal__spin {
  width: 34px;
  height: 34px;
  border: 3px solid rgba(37, 99, 235, 0.18);
  border-top-color: #2563EB;
  border-radius: 50%;
  animation: bkmodal-spin 700ms linear infinite;
}

@keyframes bkmodal-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Reduced motion still needs to say "working". A pulse carries that without
   anything travelling across the screen. */

@media (prefers-reduced-motion: reduce) {
  .bkmodal__spin {
    animation: bkmodal-pulse 1.4s ease-in-out infinite;
  }
}

@keyframes bkmodal-pulse {
  0%, 100% {
    opacity: 0.35;
  }

  50%      {
    opacity: 1;
  }
}

.bkmodal__fail {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 16px;
  padding: 24px;
  text-align: center;
  background-color: #FAFBFD;
}

.bkmodal__fail p {
  font-size: 15px;
  line-height: 1.5;
  color: #5B6472;
}

.bkmodal__fail[hidden] {
  display: none;
}

.bkmodal__foot {
  flex: none;
  padding: 12px 22px 14px;
  border-top: 1px solid rgba(221, 229, 237, 0.9);
  font-size: 13px;
  line-height: 1.4;
  color: #8A93A3;
}

.bkmodal__foot a {
  color: #2563EB;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Open only, matching the video modal: arriving wants a beat, leaving wants to
   be gone. */

@media (prefers-reduced-motion: no-preference) {
  .bkmodal[open] {
    animation: vmodal-rise 300ms var(--ease-smooth) both;
  }

  .bkmodal[open]::backdrop {
    animation: vmodal-fade 300ms ease both;
  }
}

/* ==========================================================================
   ENTRY MODAL

   The panel that arrives on a timer. Same native <dialog> as the booking and
   video panels, and the same dark blurred backdrop, so the three read as one
   family. What differs is the shape: this one is landscape, copy on the left
   and a product still on the right, because it is an invitation rather than an
   interface.
   ========================================================================== */

.entry {
  margin: auto;
  padding: 0;
  border: 0;
  max-width: none;
  max-height: none;
  background: transparent;
  overflow: visible;
}

.entry::backdrop {
  background-color: rgba(6, 8, 14, 0.72);
  backdrop-filter: blur(6px);
}

.entry__frame {
  position: relative;
  display: grid;
  width: min(880px, 94vw);
  max-height: 90vh;
  overflow: hidden;
  border-radius: 26px;
  background-color: #FFFFFF;
  box-shadow: 0 40px 90px -40px rgba(6, 8, 14, 0.6);
}

/* The still is hidden below the breakpoint rather than stacked above the copy.
   On a phone the panel has room for a heading, a line and two buttons, and a
   picture pushes at least one button off the bottom of a short window. */
@media (min-width: 768px) {
  .entry__frame {
    grid-template-columns: 1.12fr 1fr;
  }
}

.entry__copy {
  padding: 34px 26px 30px;
}

@media (min-width: 768px) {
  .entry__copy {
    padding: 46px 40px 44px;
  }
}

.entry__badge {
  margin-bottom: 16px;
}

.entry__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 28px;
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.8px;
  color: #0B1B33;
}

@media (min-width: 768px) {
  .entry__title { font-size: 34px; }
}

.entry__lead {
  margin-top: 12px;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6;
  color: #4D585F;
}

.entry__acts {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 26px;
}

/* The site's own primary action, stated rather than shared: .btn-primary is a
   Tailwind composite and css/style.css is generated output with no build step
   behind it, so a class that is not already in the file would do nothing. */
.entry__go {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 12px 14px 26px;
  border-radius: 100px;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  box-shadow: 0 8px 20px -8px rgba(37, 99, 235, 0.55);
  font-size: 15px;
  font-weight: 600;
  color: #FFFFFF;
  transition:
    transform 260ms var(--ease-soft),
    filter 260ms var(--ease-soft),
    box-shadow 260ms var(--ease-soft);
}

.entry__go:hover {
  transform: translateY(-2px);
  filter: saturate(1.08) brightness(1.03);
  box-shadow: 0 16px 30px -10px rgba(37, 99, 235, 0.6);
}

.entry__alt {
  display: inline-flex;
  align-items: center;
  padding: 14px 24px;
  border-radius: 100px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1.5px #D8E3F7;
  font-size: 15px;
  font-weight: 600;
  color: #2563EB;
  transition:
    background-color 260ms var(--ease-soft),
    box-shadow 260ms var(--ease-soft),
    color 260ms var(--ease-soft);
}

.entry__alt:hover {
  background-color: #EEF4FE;
  box-shadow: inset 0 0 0 1.5px #A9C9FA;
}

/* Over the artwork on a wide panel and over the copy on a narrow one, so it is
   in the same corner either way and never lands on a line of text. */
.entry__close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.92);
  box-shadow: 0 4px 14px -6px rgba(6, 8, 14, 0.4);
  color: #5B6472;
  transition:
    background-color 200ms var(--ease-soft),
    color 200ms var(--ease-soft),
    transform 200ms var(--ease-smooth);
}

.entry__close svg { width: 13px; height: 13px; }

.entry__close:hover {
  background-color: #FFFFFF;
  color: #22262F;
  transform: scale(1.06);
}

.entry__art {
  display: none;
  position: relative;
  background-image: linear-gradient(160deg, #EDF1FA 0%, #F4F7FD 55%, #FFFFFF 100%);
}

@media (min-width: 768px) {
  .entry__art { display: block; }
}

/* Cropped by its half of the panel and pushed off the right edge, so it reads
   as a window into a product that carries on rather than a screenshot sitting
   in a box. */
.entry__art img {
  position: absolute;
  top: 50%;
  left: 26px;
  width: 132%;
  border-radius: 14px 0 0 14px;
  box-shadow: 0 30px 60px -30px rgba(16, 24, 48, 0.45);
  transform: translateY(-50%);
}

/* The arrival, and only the arrival. Under reduced motion the panel still
   opens — it is content, and only the way it gets there is decoration. */
.entry[open] .entry__frame {
  animation: entry-in 420ms var(--ease-smooth) both;
}

@keyframes entry-in {
  from { opacity: 0; transform: translateY(14px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .entry[open] .entry__frame { animation: none; }
  .entry__go:hover { transform: none; }
  .entry__close:hover { transform: none; }
}

/* ==========================================================================
   PRODUCTS MEGA MENU
   A full-width panel under the bar: product selector down the left, that
   product's grid on the right.

   IT IS AN ORDINARY .nav-item
   Open and close are the existing dropdown rules — `:hover`, `.is-open` and
   `:focus-within` — so the keyboard, touch, Escape and click-outside handling
   already in js/main.js drives this with no changes. js/mega-menu.js only
   switches which product is showing inside an already-open panel.

   WHY IT IS NOT `relative`
   The panel runs the full width of the bar, so it resolves against the
   header's own positioned wrapper rather than the ~90px list item. That is the
   one thing .nav-item--mega changes.
   ========================================================================== */

/* THE BRIDGE
   The panel's top edge sits at the foot of the 72px bar, but the Products link
   is only ~36px tall and centred in it — so between the bottom of the link and
   the top of the panel there was an 18px strip belonging to neither. Measured
   with elementFromPoint, it returned the nav shell. :hover follows the DOM, so
   crossing that strip on the way down dropped the hover and shut the menu
   before the pointer arrived.

   The padding extends the item's own hit area down to meet the panel; the
   negative margin takes it back out of the flex layout, so the link does not
   move and the bar's centring is untouched. Scoped to this item rather than
   done by stretching the panel upward — the panel is full width, and a
   transparent strip of it lying across the bar would swallow hover and clicks
   on Industries, Pricing and the buttons opposite. */

.nav-item--mega {
  padding-bottom: 22px;
  margin-bottom: -22px;
}

.mega {
  pointer-events: none;
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  z-index: 50;
  /* A transparent bridge over the bar's bottom edge, and the reason it is here
     again.

     `top: 100%` resolves against the containing block, and that is the
     full-width wrapper rather than .nav-item — it has to be, or `left: 0;
     right: 0` would size the panel to the item instead of the viewport. So the
     panel's top lands on the WRAPPER's bottom, which is not the same line as
     the item's: the item is the pill's height and the wrapper is the bar's.
     The few pixels between them belong to neither, :hover goes false as the
     pointer crosses them, and the panel closes on its way to being used.

     The padding extends the panel's hit area up over that band and the
     negative margin puts the visible card back where it was, so nothing moves
     and there is no gap to fall through. It is sized well over the current
     shortfall on purpose: the shortfall is a function of --nav-h and the
     pill's inset, and this should not need revisiting when either changes. */
  margin-top: -10px;
  padding: 10px 0 0;
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, -8px, 0);
  transition:
    opacity 240ms var(--ease-soft),
    transform 380ms var(--ease-smooth),
    visibility 0s linear 380ms;
}

.nav-item:hover .mega,
.nav-item.is-open .mega,
.mega:focus-within {
  pointer-events: auto;
  opacity: 1;
  visibility: visible;
  transform: translate3d(0, 0, 0);
  transition:
    opacity 240ms var(--ease-soft),
    transform 380ms var(--ease-smooth),
    visibility 0s;
}

.mega__inner {
  display: grid;
  overflow: hidden;
  /* Edge to edge. No max-width, no radius on the top corners and no ring:
     the panel is a continuation of the bar above it rather than a card
     floating under it, so the only edge it needs is the one along its foot. */
  background-color: #ffffff;
  border-bottom-left-radius: 20px;
  border-bottom-right-radius: 20px;
  box-shadow:
    inset 0 1px 0 rgba(221, 229, 237, 0.9),
    0 30px 70px -30px rgba(16, 24, 48, 0.4);
}

@media (min-width: 1024px) {
  .mega__inner {
    /* A fixed rail rather than the old 1fr/3fr ratio. Full bleed, a quarter of
       a 2000px screen is a 500px column holding two short rows, so the rail
       takes what it needs and the panel takes the rest. */
    grid-template-columns: 340px minmax(0, 1fr);
  }

  /* The bar's own gutter, so the rail's label and the feature panel line up
     with the logo and the Signup button above them rather than running to the
     screen edge. */

  .mega__rail {
    padding: 24px 24px 24px 40px;
  }

  .mega__body {
    padding: 24px 40px 28px 30px;
  }
}

/* ------------------------------------------------------------------
   Left — the product selector
   ------------------------------------------------------------------ */

.mega__rail {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px 16px;
  /* A tinted ground with no divider. The rule used to draw the boundary; now
     the current product's white card does, by being the one thing in the
     column that is the same colour as the panel it points at. */
  background-color: #F4F6FA;
}

.mega__tab {
  position: relative;
  display: block;
  width: 100%;
  padding: 14px 38px 14px 16px;
  border-radius: 14px;
  text-align: left;
  cursor: pointer;
  transition: background-color 260ms var(--ease-soft);
}

.mega__tab:hover {
  background-color: rgba(255, 255, 255, 0.7);
}

/* The current product. A tint rather than a solid fill, so the rail stays
   quieter than the grid it is pointing at. */

/* The current product is a white card lifted off the grey, the same white as
   the panel beside it. That is what makes the rail read as a selector rather
   than a second list. */

.mega__tab.is-on {
  background-color: #ffffff;
  box-shadow: 0 12px 30px -18px rgba(16, 24, 48, 0.45);
}

/* The notch. A rotated square half outside the card, so the white carries on
   into the gutter and points at the panel it opened. Drawn rather than an
   image: it has to be exactly the card's white, whatever that becomes. */

@media (min-width: 1024px) {
  .mega__tab.is-on::after {
    content: '';
    position: absolute;
    top: 50%;
    right: -6px;
    width: 12px;
    height: 12px;
    border-radius: 2px;
    background-color: #ffffff;
    transform: translateY(-50%) rotate(45deg);
  }
}

.mega__tab-name {
  display: block;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: #0B0D12;
}

.mega__tab-blurb {
  display: block;
  margin-top: 3px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  color: #6B7280;
}

.mega__tab-arrow {
  position: absolute;
  top: 50%;
  right: 14px;
  display: grid;
  place-items: center;
  opacity: 0;
  transform: translate3d(-6px, -50%, 0);
  transition: opacity 260ms var(--ease-soft), transform 300ms var(--ease-smooth);
}

.mega__tab.is-on .mega__tab-arrow,
.mega__tab:hover .mega__tab-arrow {
  opacity: 0.55;
  transform: translate3d(0, -50%, 0);
}

/* ------------------------------------------------------------------
   Right — the product's grid
   ------------------------------------------------------------------ */

/* Faintly tinted, not white: it is what a row's white hover card reads
   against. The rail beside it is a step further into the same grey. */

.mega__body {
  position: relative;
  padding: 20px;
  background-color: #FAFBFD;
}

@media (min-width: 1024px) {
  .mega__body {
    padding: 24px 26px 26px;
  }
}

/* ALL PANELS OCCUPY ONE CELL

   Stacked rather than swapped, so the body is always as tall as the TALLEST
   product's grid and the card stops resizing under the pointer when you move
   between the rail's two products. Niyuk HR runs eight rows and Recruit six;
   with only the current panel in flow the whole menu jumped 80px on hover,
   which reads as the menu flinching away from you.

   It also makes .mega__foot's `margin-top: auto` mean something: the footer
   line now pins to the bottom of a shared height rather than to the bottom of
   whatever the current panel happens to measure, so the two products' footers
   sit on the same line.

   Hidden panels stay `hidden` in the markup — a panel nobody can see should not
   be somewhere the keyboard can land — but the attribute's `display: none`
   would take them out of layout and the height would collapse again. So they
   are laid out and hidden with `visibility` instead, which keeps them out of
   the accessibility tree and out of tab order just as `display: none` does, and
   unlike `opacity: 0` alone leaves nothing for the pointer to hit. */

.mega__body {
  display: grid;
}

.mega__panel[hidden] {
  display: block;
  visibility: hidden;
}

.mega__panel {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translate3d(0, 8px, 0);
}

/* The chain that carries the shared height down to the footer: the panel is
   stretched by the grid above, and each of these has to pass that height on or
   `margin-top: auto` has no room to push into. */

.mega__panel > .mega__cols {
  height: 100%;
}

/* Added a frame after the panel is un-hidden, so the transition has a
   from-state to run from — set in the same frame, the browser resolves both
   values at once and there is nothing to animate. js/mega-menu.js does the
   waiting. */

.mega__panel.is-on {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity 260ms var(--ease-soft),
    transform 420ms var(--ease-smooth);
}

.mega__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding-bottom: 14px;
  margin-bottom: 16px;
  border-bottom: 1px solid rgba(221, 229, 237, 0.9);
}

/* The product's own page. It used to be the banner at the top of the panel;
   with the banner gone it lives here, still one click from the menu. */

.mega__heading {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: #5A6070;
  transition: color 260ms var(--ease-soft);
}

.mega__heading:hover {
  color: #2563EB;
}

.mega__heading > span {
  display: grid;
  place-items: center;
  transition: transform 300ms var(--ease-smooth);
}

.mega__heading:hover > span {
  transform: translate3d(3px, 0, 0);
}

.mega__pricing {
  flex: none;
  padding: 8px 16px;
  border-radius: 100px;
  background-color: #0B0D12;
  font-size: 13px;
  font-weight: 600;
  color: #ffffff;
  transition: background-color 260ms var(--ease-soft), transform 260ms var(--ease-smooth);
}

.mega__pricing:hover {
  background-color: #2b2f3a;
  transform: translate3d(0, -1px, 0);
}

/* Names what the grid is, where a filled banner used to sit. */

.mega__label {
  margin: 2px 0 14px;
  padding-left: 12px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.mega__grid {
  display: grid;
  gap: 2px;
}

@media (min-width: 640px) {
  .mega__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px 12px;
  }
}

/* ---- one menu row, in either panel ---- */

.mega__item {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 11px 12px;
  border-radius: 12px;
  transition:
    background-color 220ms var(--ease-soft),
    box-shadow 260ms var(--ease-soft);
}

/* The whole row lifts as a white card. It reads because the panel behind it is
   faintly tinted rather than white, which is also why the hover is the row and
   not the mark inside it: a tile that inverts under the pointer draws the eye
   to the icon when the thing being chosen is the row. */

.mega__item:hover {
  background-color: #ffffff;
  box-shadow: 0 10px 26px -18px rgba(16, 24, 48, 0.45);
}

/* The tile, on both panels. It went bare on the products grid at one point,
   on the argument that fourteen tiles compete with their labels; with the rows
   lifting on hover instead of the marks inverting, the tile is quiet enough to
   keep, and the two panels now match. */

.mega__item-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: linear-gradient(
    140deg,
    rgba(37, 99, 235, 0.14) 0%,
    rgba(37, 99, 235, 0.07) 100%
  );
  color: #2563EB;
}

.mega-i {
  width: 20px;
  height: 20px;
}

.mega__item-label {
  min-width: 0;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.3;
  color: #22262F;
}

/* The mobile accordion still runs two lines, so it keeps the tile and the
   description the desktop grid dropped. */

.mega-acc__item .mega__item-icon {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background-color: rgba(37, 99, 235, 0.1);
}

.mega__item-text {
  display: block;
  min-width: 0;
}

.mega-acc__item .mega__item-label {
  display: block;
  font-size: 14.5px;
  font-weight: 600;
  color: #0B0D12;
}

.mega__item-desc {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.4;
  color: #6B7280;
}

/* ------------------------------------------------------------------
   Below the desktop breakpoint the bar collapses into the sheet, so the panel
   has no bar to hang from. It is hidden outright rather than restyled — the
   sheet carries its own accordion.
   ------------------------------------------------------------------ */

@media (max-width: 1023px) {
  .mega {
    display: none;
  }
}

/* ==========================================================================
   MOBILE SHEET — VERTICAL RHYTHM

   The sheet is one scroll on a phone and it was running long: "Resource" and
   the two buttons under it sat below the fold on a 390x844 screen, so the
   reader had to scroll a menu to find out what was in it.

   Only vertical values change. The horizontal padding, the type sizes, the
   rules down the child lists and the hit targets are all left alone — the
   rows still clear 40px, which is what they have to do on a touch screen.

   Scoped to .mobile-menu throughout, so the desktop bar and the mega panel
   keep the spacing they were tuned with.
   ========================================================================== */

@media (max-width: 1023px) {
  /* The sheet's own frame. The bottom clears the home indicator on a phone
     that has one, so the last row is not sitting under it; env() resolves to
     0 everywhere else, which leaves the plain 10. */
  .mobile-menu {
    padding-top: 10px;
    padding-bottom: calc(10px + env(safe-area-inset-bottom));
  }

  /* Top-level rows: Solutions, Pricing, Resource and the two products.

     14px, down from the shared 18: these are group labels in a sheet, not
     headings on a page, and at 18 they were the largest type on a screen whose
     whole problem is length. The row still clears 36px, so it is no harder to
     hit. */
  .mobile-menu > ul > li > a {
    padding-top: 9px;
    padding-bottom: 9px;
    font-size: 14px;
  }

  /* The child lists under Solutions, Pricing and Resource. */
  .mobile-menu > ul > li > ul {
    margin-bottom: 0;
  }

  /* 7, not less. The label is 16px on 1.3, so this row comes to about 35px
     tall; at 6 it drops under 34 and the list stops being comfortable to hit
     on a phone, which is a worse trade than the 10px it would save. */
  .mobile-menu > ul > li > ul > li > a {
    padding-top: 7px;
    padding-bottom: 7px;
  }

  /* The products and region accordions. */
  .mobile-menu .mega-acc {
    margin: 0 0 4px;
  }

  .mobile-menu .mega-acc__summary {
    padding-top: 9px;
    padding-bottom: 9px;
  }

  .mobile-menu .mega-acc__list {
    margin: 2px 0 4px;
  }

  .mobile-menu .mega-acc__item {
    padding-top: 7px;
    padding-bottom: 7px;
  }
}

/* ==========================================================================
   PRODUCTS — MOBILE ACCORDION
   The same fourteen items in the sheet. <details>/<summary>, so it opens with
   no JS and announces itself as a disclosure widget without any ARIA of ours.
   ========================================================================== */

.mega-acc {
  margin: 2px 0 6px;
  padding-left: 4px;
}

.mega-acc__group + .mega-acc__group {
  margin-top: 4px;
}

.mega-acc__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 11px 14px;
  border-radius: 10px;
  background-color: #F5F6FB;
  font-size: 14px;
  font-weight: 600;
  color: #0B0D12;
  cursor: pointer;
  list-style: none;
}

/* Safari draws its own triangle through ::-webkit-details-marker, and Firefox
   through the summary's own list-style — both have to go, or the row carries
   two arrows. */

.mega-acc__summary::-webkit-details-marker {
  display: none;
}

.mega-acc__chev {
  width: 9px;
  height: 9px;
  border-right: 1.8px solid #6B7280;
  border-bottom: 1.8px solid #6B7280;
  transform: rotate(45deg) translate3d(-2px, -2px, 0);
  transition: transform 300ms var(--ease-smooth);
}

.mega-acc__group[open] .mega-acc__chev {
  transform: rotate(225deg) translate3d(-2px, -2px, 0);
}

.mega-acc__list {
  margin: 4px 0 8px;
  padding: 0;
  list-style: none;
}

.mega-acc__item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 9px 10px;
  border-radius: 11px;
  transition: background-color 220ms var(--ease-soft);
}

.mega-acc__item:hover {
  background-color: #F5F6FB;
}

/* ==========================================================================
   BLOG
   Three cards, the whole of each one a link.
   ========================================================================== */

.blog {
  /* Its own ground, so the section separates from the white either side of it
     without needing a rule across the page. */
  background-color: #F7F9FD;
}

.blog__head {
  margin-left: auto;
  margin-right: auto;
  max-width: 640px;
  text-align: center;
}

.blog__title {
  margin-top: 22px;
}

.blog__lead {
  margin-top: 18px;
}

.blog__grid {
  display: grid;
  gap: 22px;
  margin-top: 48px;
}

@media (min-width: 640px) {
  .blog__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .blog__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 26px;
  }
}

/* ---- a card ---- */

/* display: flex so the meta row can be pushed to the foot — three titles of
   different lengths otherwise leave their categories at three different
   heights across the row. */

.blog-card {
  display: flex;
  flex-direction: column;
  padding: 10px 10px 4px;
  border-radius: 22px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
  box-shadow: 0 18px 44px -34px rgba(16, 24, 48, 0.5);
  transition: transform 320ms var(--ease-smooth), box-shadow 320ms var(--ease-smooth);
}

.blog-card:hover {
  transform: translate3d(0, -4px, 0);
  box-shadow: 0 28px 56px -30px rgba(16, 24, 48, 0.5);
}

/* Inset rather than bleeding to the card's edge, so the photograph keeps the
   white frame the site's other cards have instead of turning the card into a
   tile. */

.blog-card__shot {
  display: block;
  overflow: hidden;
  border-radius: 15px;
  background-color: #EDF1F4;
  aspect-ratio: 4 / 3;
}

.blog-card__shot img {
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  /* Held slightly large and eased back on hover, so the card settles rather
     than the frame simply lifting. */
  transform: scale(1.04);
  transition: transform 600ms var(--ease-smooth);
}

.blog-card:hover .blog-card__shot img {
  transform: scale(1);
}

.blog-card__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: 20px 12px 18px;
}

.blog-card__title {
  display: block;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.2px;
  color: #0B0D12;
}

/* margin-top: auto is what levels the three meta rows regardless of how many
   lines the title above them runs to. */

.blog-card__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: auto;
  padding-top: 22px;
  font-size: 14px;
  font-weight: 500;
}

.blog-card__cat {
  color: #0B0D12;
}

.blog-card__go {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: #6B7280;
  transition: color 260ms var(--ease-soft);
}

.blog-card:hover .blog-card__go {
  color: #2563EB;
}

.blog-card__arrow {
  width: 13px;
  height: 13px;
  transition: transform 320ms var(--ease-smooth);
}

.blog-card:hover .blog-card__arrow {
  transform: translate3d(3px, 0, 0);
}

.blog__all {
  display: flex;
  justify-content: center;
  margin-top: 42px;
}

/* ==========================================================================
   SOLUTION BENTO
   Five capabilities, five card treatments, an uneven grid. Every dashboard
   preview inside a card is markup rather than a screenshot — they recolour per
   ground, stay sharp at any density, and animate on arrival.
   ========================================================================== */

.solution {
  /* Off-white rather than white, so the light card in the grid still reads as
     a card and the dark ones are not sitting on paper.

     The flat tone read as a slab of white between two brighter sections, so it
     is now a gradient: a cool blue tint at the top, warming through the
     off-white in the middle to a faint lavender at the foot. Kept very low in
     saturation on purpose — the dark cards are the contrast in this section,
     and a ground with any real colour in it would start competing with them.
     background-color stays as the fallback for anything that cannot paint the
     gradient. */
  background-color: #F6F7F9;
  background-image: linear-gradient(
    180deg,
    #EEF3FB 0%,
    #F6F7F9 42%,
    #F5F4FA 78%,
    #F1EFF8 100%
  );
}

.sol {
  display: grid;
  gap: 14px;
}

@media (min-width: 700px) {
  .sol {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
  }
}

@media (min-width: 1024px) {
  .sol {
    /* Named areas rather than spans: the shape is the point, and reading it
       off six lines of ASCII beats deriving it from fourteen span values
       scattered across the cards.

       Three cards down the left, four on the right as two over two. Six rows
       because that is the smallest number both halves divide into: the left
       cards take two rows each and the right cards three, so the two columns
       finish level even though they hold a different number of cards.

       WHICH CARD SITS WHERE IS DECIDED BY HOW MUCH IT HAS TO SHOW
       A left slot is two rows and a right slot is three, so the left column is
       the short one. The photograph and the two short cards go there, because
       a picture reads at any height and those two are a heading, a line and a
       row of live detail. The four with a full interface inside them — the
       people panel, the blue card's stack and button, the assessment inset,
       the talent tiles — take the taller right-hand slots. */
    grid-template-columns: 1fr 1.15fr 1.15fr;
    grid-template-areas:
      'c a b'
      'c a b'
      'f a b'
      'f d e'
      'g d e'
      'g d e';
    gap: 18px;
  }

  .sol-a {
    grid-area: a;
  }

  .sol-b {
    grid-area: b;
  }

  .sol-c {
    grid-area: c;
  }

  .sol-d {
    grid-area: d;
  }

  .sol-e {
    grid-area: e;
  }

  .sol-f {
    grid-area: f;
  }

  .sol-g {
    grid-area: g;
  }

  /* The talent strip ran four tiles across the full width of the section. In a
     right-hand slot they would be about 100px each, so it folds to two by
     two instead. */

  .sol-e .sol-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ---- the two short cards in the left column ----

   One live detail each, sitting at the foot of the card. rgba white rather
   than a hex, so both read correctly on the dark ground without either of them
   carrying its own copy of that ground's colour. */

/* .sol-card carries no padding of its own — every child brings the 26px
   gutter with it, the way .sol-card__head and .sol-card__text do. Without the
   same gutter here the pills sat flush against the card's rounded corner. */

.sol-mini {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding: 22px 26px 26px;
}

.sol-mini__pill {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 7px 12px;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.06);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
  font-size: 12px;
  font-weight: 600;
  color: #C7CCD8;
}

.sol-mini__pill b {
  font-size: 13px;
  font-weight: 700;
  color: #FFFFFF;
  font-variant-numeric: tabular-nums;
}

/* The stage actually being worked. One of the three, so the row reads as a
   funnel with a live position in it rather than three equal numbers. */

.sol-mini__pill.is-on {
  background-color: rgba(37, 99, 235, 0.24);
  box-shadow: inset 0 0 0 1px rgba(96, 150, 255, 0.45);
  color: #BBD3FF;
}

.sol-mini__points {
  padding: 7px 12px;
  border-radius: 100px;
  background-color: rgba(52, 199, 145, 0.16);
  box-shadow: inset 0 0 0 1px rgba(52, 199, 145, 0.32);
  font-size: 12px;
  font-weight: 700;
  color: #6FE0B4;
}

/* The funnel, as three bars. Widths are the counts as a percentage of the top
   of the funnel, so the shape is the data rather than a decoration sized by
   eye. They grow on arrival, staggered, which is the one thing on the card
   that says the pipeline is moving. */

.sol-funnel {
  display: flex;
  flex-direction: column;
  gap: 5px;
  width: 100%;
}

.sol-funnel i {
  display: block;
  width: var(--w);
  height: 6px;
  border-radius: 100px;
  background-image: linear-gradient(90deg, #6FA0FF, #2563EB);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 900ms var(--ease-smooth);
  transition-delay: var(--d, 0ms);
}

.is-revealed .sol-funnel i,
.reveal-done .sol-funnel i {
  transform: scaleX(1);
}

/* No JS class to wait for under reduced motion, and none needed: the bars are
   simply already their width. */

@media (prefers-reduced-motion: reduce) {
  .sol-funnel i {
    transform: scaleX(1);
    transition: none;
  }
}

/* The line that closes each of the two short cards. Quiet on purpose — it is
   the caption under the live row, not a second claim. */

.sol-mini__foot {
  width: 100%;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.5);
}

.sol-lede {
  padding: 0 0 40px;
  text-align: center;
}

@media (min-width: 1024px) {
  .sol-lede {
    padding-bottom: 56px;
  }
}

/* Named .sol-lede, not .sol__mid/.sol__title. The double-underscore sol__
   namespace already belongs to the scatter section in sections/solutions.php,
   and .sol__title is in heading-reveal.js's GATED list — a heading matching it
   is deliberately kept out of the observer and released by a rule scoped to
   #solutions.is-armed instead. Borrowing the name meant this heading was gated
   out and then never released by anything: it sat at opacity 0 forever, which
   read as a large empty gap above the cards.

   No top margin — the badge that used to sit above it is gone. */

.sol-lede__title {
  margin-top: 0;
}

/* ------------------------------------------------------------------
   The card shell
   ------------------------------------------------------------------ */

.sol-card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 28px;
  min-height: 260px;
  /* Lift and a touch of scale on hover. Kept to 0.4% — at anything more the
     card's own contents visibly resample, which on a card full of small type
     reads as a wobble rather than a lift. */
  transition: transform 420ms var(--ease-smooth), box-shadow 420ms var(--ease-smooth);
}

.sol-card:hover {
  transform: translate3d(0, -5px, 0) scale(1.004);
}

.sol-card--dark {
  background-color: #0B0D12;
  color: #ffffff;
  box-shadow: 0 18px 44px -30px rgba(11, 13, 18, 0.7);
}

.sol-card--dark:hover {
  box-shadow: 0 34px 70px -32px rgba(11, 13, 18, 0.8);
}

.sol-card--light {
  background-color: #ffffff;
  color: #0B0D12;
  box-shadow: 0 1px 2px rgba(16, 24, 48, 0.05), 0 18px 44px -34px rgba(16, 24, 48, 0.5);
}

.sol-card--light:hover {
  box-shadow: 0 1px 2px rgba(16, 24, 48, 0.05), 0 34px 66px -34px rgba(16, 24, 48, 0.55);
}

.sol-card--brand {
  /* A gradient rather than a flat fill: the one card carrying the brand should
     have some depth in it, or it reads as a swatch. */
  background: linear-gradient(150deg, #4F8DFB 0%, #2F6FE8 55%, #2657D6 100%);
  color: #ffffff;
  box-shadow: 0 18px 44px -28px rgba(37, 99, 235, 0.75);
}

.sol-card--brand:hover {
  box-shadow: 0 34px 70px -30px rgba(37, 99, 235, 0.8);
}

.sol-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 26px 26px 0;
}

.sol-card__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 20px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.3px;
  color: inherit;
}

.sol-card__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 100px;
}

.sol-card--dark .sol-card__icon {
  background-color: rgba(255, 255, 255, 0.1);
  color: #ffffff;
}

.sol-card--light .sol-card__icon {
  background-color: #3B82F6;
  color: #ffffff;
}

.sol-card--brand .sol-card__icon {
  background-color: #0B0D12;
  color: #ffffff;
}

.sol-i {
  width: 18px;
  height: 18px;
}

.sol-i--sm {
  width: 15px;
  height: 15px;
}

.sol-card__text {
  padding: 14px 26px 0;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.55;
}

.sol-card--dark .sol-card__text {
  color: rgba(255, 255, 255, 0.62);
}

.sol-card--light .sol-card__text {
  color: #5A6070;
}

/* ------------------------------------------------------------------
   The animated meter
   Shared by the assessment bar and the goals tile. Fills from nothing when
   its card arrives rather than sitting full, which is the whole difference
   between a screenshot and something running.
   ------------------------------------------------------------------ */

.sol-meter {
  display: block;
  flex: 1;
  min-width: 20px;
  height: 3px;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.14);
  overflow: hidden;
}

.sol-meter b {
  display: block;
  width: 0;
  height: 100%;
  border-radius: 100px;
  background-color: #5EEAD4;
  transition: width 1500ms var(--ease-smooth) 500ms;
}

/* The card is the .reveal, so its arrival is what starts the fill. */

.reveal.is-visible .sol-meter b {
  width: var(--to, 100%);
}

/* ------------------------------------------------------------------
   1 · the cropped product surface
   ------------------------------------------------------------------ */

.sol-panel {
  position: relative;
  margin: 26px 0 0 26px;
  padding: 20px 20px 0;
  border-radius: 18px 0 0 0;
  background-color: rgba(255, 255, 255, 0.05);
  box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.07);
  /* The overflow: 64px of the panel is outside the card, and .sol-card's
     overflow: hidden does the cutting. */
  width: calc(100% + 64px);
  flex: 1;
  min-height: 0;
}

/* The list has to stop somewhere and a hard cut looks like a bug. This fades
   it into the card instead, so the panel reads as continuing. */

.sol-panel::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 92px;
  background: linear-gradient(180deg, rgba(11, 13, 18, 0) 0%, #0B0D12 88%);
  pointer-events: none;
}

.sol-panel__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: #ffffff;
  white-space: nowrap;
}

.sol-panel__sub {
  margin-top: 7px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.5);
}

.sol-panel__chips {
  display: flex;
  gap: 8px;
  margin-top: 16px;
}

.sol-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  padding: 6px 12px 6px 6px;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.07);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09);
  font-size: 13px;
  font-weight: 500;
  color: #ffffff;
  white-space: nowrap;
}

.sol-chip img {
  width: 22px;
  height: 22px;
  border-radius: 100px;
  -o-object-fit: cover;
     object-fit: cover;
}

.sol-chip i {
  font-style: normal;
  color: rgba(255, 255, 255, 0.4);
}

/* Held to the card's own width, unlike the heading and chips above it. The
   panel overflows by 64px, and the permission pill sits at the end of each
   row — left to overflow with everything else it fell entirely outside the
   card, which meant the one control the panel exists to show was the one
   thing you could not see. The crop still reads: the subtitle above is cut
   mid-word, which is what tells you the panel carries on. */

.sol-people {
  display: grid;
  gap: 13px;
  margin: 20px 0 0;
  padding: 0;
  /* 90px, not 64: the panel overflows the card by 64 AND is inset from its
     left edge by another 26, so trimming only the overflow still left the row
     ending past the card. */
  max-width: calc(100% - 90px);
  list-style: none;
}

.sol-people li {
  display: flex;
  align-items: center;
  gap: 12px;
}

.sol-people img {
  width: 36px;
  height: 36px;
  border-radius: 100px;
  -o-object-fit: cover;
     object-fit: cover;
  flex: none;
}

.sol-people__who {
  flex: 1;
  min-width: 0;
}

.sol-people b {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}

.sol-people i {
  display: block;
  margin-top: 2px;
  font-style: normal;
  font-size: 12.5px;
  font-weight: 500;
  color: #5EEAD4;
}

/* The permission. Three states told apart by colour as well as by word, so the
   column scans without being read. */

.sol-perm {
  flex: none;
  padding: 5px 11px;
  border-radius: 100px;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}

.sol-perm--full {
  background-color: rgba(94, 234, 212, 0.16);
  color: #5EEAD4;
}

.sol-perm--edit {
  background-color: rgba(124, 176, 252, 0.16);
  color: #7CB0FC;
}

.sol-perm--view {
  background-color: rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 0.55);
}

/* ------------------------------------------------------------------
   2 · the accent card
   ------------------------------------------------------------------ */

.sol-b {
  padding: 26px;
  justify-content: flex-start;
}

.sol-faces {
  display: flex;
  padding: 0;
  margin: 0 0 22px;
  list-style: none;
}

.sol-faces li + li {
  margin-left: -12px;
}

.sol-faces img {
  display: block;
  width: 42px;
  height: 42px;
  border-radius: 100px;
  -o-object-fit: cover;
     object-fit: cover;
  box-shadow: 0 0 0 3px #3F7BEF;
  transition: transform 420ms var(--ease-smooth);
}

/* The stack opens out under the pointer — the small motion that makes the card
   feel like a live surface rather than a picture of one. */

.sol-b:hover .sol-faces li + li img {
  transform: translate3d(5px, 0, 0);
}

.sol-b:hover .sol-faces li:nth-child(3) img {
  transform: translate3d(10px, 0, 0);
}

.sol-b:hover .sol-faces li:nth-child(4) img {
  transform: translate3d(15px, 0, 0);
}

.sol-kicker {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
}

.sol-b__title {
  margin-top: 12px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(22px, 2.4vw, 28px);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.5px;
  color: #ffffff;
}

/* The bottom margin is what keeps the button off this paragraph. The button
   below is pushed down with `margin-top: auto`, which collapses to nothing the
   moment the copy is long enough to fill the card — and then the two touch.
   A margin here is the floor that auto cannot take away. */

.sol-b__meta {
  margin-top: 14px;
  margin-bottom: 24px;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.82);
}

/* Outlined, not filled: on a card that is already solid brand, a filled button
   has nothing to sit against. */


/* The two figures on the accent card. A hairline above rather than a box
   around them: the card is already a solid colour, and a panel on top of it
   would be a second surface where the design only wants a rule. */

.sol-b__stats {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 28px;
  margin: 26px 0 0;
  padding: 20px 0 0;
  border-top: 1px solid rgba(255, 255, 255, 0.22);
  list-style: none;
}

.sol-b__stats li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.72);
}

.sol-b__stats b {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.5px;
  color: #FFFFFF;
}

.sol-b__btn {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  margin-top: auto;
  padding: 13px 22px;
  border-radius: 100px;
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.55);
  font-size: 15px;
  font-weight: 600;
  color: #ffffff;
  transition: background-color 260ms var(--ease-soft), box-shadow 260ms var(--ease-soft), color 260ms var(--ease-soft);
}

.sol-b__btn:hover {
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1.5px #ffffff;
  color: #1D4ED8;
}

/* ------------------------------------------------------------------
   3 · photography
   ------------------------------------------------------------------ */

.sol-shot {
  justify-content: flex-end;
  min-height: 300px;
}

.sol-shot__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  z-index: -2;
  /* Held slightly large and eased back under the pointer, so the card settles
     rather than the frame merely lifting. */
  transform: scale(1.05);
  transition: transform 900ms var(--ease-smooth);
}

.sol-shot:hover .sol-shot__img {
  transform: scale(1);
}

/* Everything readable sits inside this, never on bare photography — the same
   rule the impact cards and the industry rail follow. */

.sol-shot__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    0deg,
    rgba(8, 9, 13, 0.9) 0%,
    rgba(8, 9, 13, 0.45) 38%,
    rgba(8, 9, 13, 0.05) 72%
  );
}

.sol-shot__body {
  position: relative;
  padding: 26px;
}

.sol-shot__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(22px, 2.3vw, 28px);
  font-weight: 600;
  letter-spacing: -0.5px;
  color: #ffffff;
}

.sol-shot__sub {
  margin-top: 8px;
  max-width: 420px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.78);
}

/* ------------------------------------------------------------------
   4 · copy beside a card-within-the-card
   ------------------------------------------------------------------ */

.sol-d {
  padding-bottom: 26px;
}

/* The copy sits ABOVE the inset, always. This card used to span two columns of
   the grid and put the two side by side; in the seven-card layout it holds one
   column at any viewport, and the card's width no longer follows the window's.
   A media query cannot express that — the breakpoint that mattered was the
   card's width, not the screen's — so the side-by-side is gone rather than
   guarded. Stacked is the arrangement it already used on a phone. */

.sol-inset {
  margin: 22px 26px 0;
  border-radius: 18px;
  background-color: rgba(255, 255, 255, 0.05);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
}


.sol-inset__top {
  padding: 20px 20px 18px;
}

.sol-inset__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.3px;
  color: #ffffff;
}

.sol-inset__sub {
  margin-top: 6px;
  font-size: 13.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.5);
}

.sol-inset__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 18px;
}

/* Overlapped, each face ringed in the panel's own colour so the stack reads as
   one object rather than four circles that happen to touch. */

.sol-stack {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px 4px 4px;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.07);
}

.sol-stack img {
  width: 26px;
  height: 26px;
  border-radius: 100px;
  -o-object-fit: cover;
     object-fit: cover;
  box-shadow: 0 0 0 2px #14161C;
}

.sol-stack img + img {
  margin-left: -9px;
}

.sol-stack b {
  margin-left: 8px;
  font-size: 12px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.75);
}

.sol-stack--light {
  background-color: #F1F3F7;
}

.sol-stack--light img {
  box-shadow: 0 0 0 2px #F1F3F7;
}

.sol-stack--light b {
  color: #5A6070;
}

.sol-inset__act {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 100px;
  font-size: 13.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.78);
  transition: background-color 260ms var(--ease-soft);
}

.sol-inset__act:hover {
  background-color: rgba(255, 255, 255, 0.07);
}

.sol-inset__act--sq {
  padding: 8px 10px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
}

/* The toolbar. One item lit with the meter running out of it — the reference's
   way of showing which view is open without a tab bar. */

.sol-inset__bar {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 14px 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  overflow: hidden;
}

.sol-inset__bar span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  font-size: 13.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.45);
}

.sol-inset__bar span.is-on {
  flex: 1;
  min-width: 0;
  color: #ffffff;
}

/* ------------------------------------------------------------------
   5 · copy above a row of small live panels
   ------------------------------------------------------------------ */

.sol-strip {
  display: grid;
  gap: 12px;
  padding: 22px 26px 26px;
}

@media (min-width: 560px) {
  .sol-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .sol-strip {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 14px;
  }
}

.sol-tile {
  display: flex;
  flex-direction: column;
  padding: 16px 16px 15px;
  border-radius: 16px;
  background-color: #F4F6FA;
}

.sol-tile__label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #6B7280;
}

.sol-tile__val {
  margin-top: 10px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 26px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.6px;
  color: #0B0D12;
}

.sol-tile__val--sm {
  font-size: 19px;
}

.sol-tile__val em {
  font-style: normal;
  font-size: 14px;
  color: #9AA1AE;
}

/* margin-top: auto levels the four footnotes whatever sits above them. */

.sol-tile__foot {
  margin-top: auto;
  padding-top: 12px;
  font-size: 11.5px;
  font-weight: 500;
  color: #8A90A0;
}

/* The wide variant of the shared meter, on a light ground. */

.sol-meter--wide {
  width: 100%;
  flex: none;
  height: 6px;
  margin-top: 12px;
  background-color: rgba(16, 24, 48, 0.1);
}

.sol-meter--wide b {
  background-color: #2563EB;
}

.sol-dots {
  display: flex;
  gap: 5px;
  margin-top: 12px;
}

.sol-dots i {
  width: 100%;
  height: 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.1);
}

.sol-dots i.is-on {
  background-color: #F59E0B;
}

.sol-tile .sol-stack--light {
  align-self: flex-start;
  margin-top: 12px;
  padding-left: 4px;
}

.sol-step {
  display: flex;
  gap: 5px;
  margin-top: 12px;
}

.sol-step i {
  width: 100%;
  height: 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.1);
}

.sol-step i.is-on {
  background-color: #16A34A;
}

/* Nothing moves for a reader who has asked for less of it. The meters simply
   start full, which is the state they were animating towards anyway. */

@media (prefers-reduced-motion: reduce) {
  .sol-card,
  .sol-shot__img,
  .sol-faces img,
  .sol-meter b {
    transition: none !important;
  }

  .sol-meter b {
    width: var(--to, 100%);
  }
}

/* ==========================================================================
   HRMS SOLUTION WALL
   Six cards in two bands of three with the section heading spanning the row
   between them.

   Prefixed hs-wall, not sol-: the sol__ namespace belongs to the home page's
   scatter section, and `.sol__title` is in heading-reveal.js's GATED list — a
   heading matching it is kept out of the reveal observer and released only by
   a rule scoped to #solutions, so borrowing the name leaves a heading that can
   never appear.
   ========================================================================== */

.hs-wall-sec {
  background-color: #ffffff;
}

.hs-wall {
  display: grid;
  gap: 18px;
}

@media (min-width: 700px) {
  .hs-wall {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 20px;
  }
}

@media (min-width: 1024px) {
  .hs-wall {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 22px;
  }
}

/* The heading's own row, first in the grid and full width, so it reads as the
   section's head with the cards under it.

   It stays a grid child rather than moving out to a sibling above the wall:
   js/wall-burst.js measures each card's distance to this element with
   offsetLeft/offsetTop, and that subtraction is only meaningful while the two
   resolve against the same offsetParent. Lifting it out of the grid would send
   every card to the wrong origin. */

.hs-wall__lede {
  grid-column: 1 / -1;
  padding: 0 0 6px;
  text-align: center;
}

@media (min-width: 1024px) {
  .hs-wall__lede {
    padding: 0 0 14px;
  }
}

.hs-wall__title {
  margin: 0 auto;
  max-width: 760px;
}

/* ------------------------------------------------------------------
   A card
   ------------------------------------------------------------------ */

.hs-wall__card {
  display: flex;
  flex-direction: column;
  padding: 24px 24px 26px;
  border-radius: 24px;
  /* No min-height. It was 236px, which was 74px taller than the tallest card's
     own content — every card carried that as empty space under its last line.
     The cards still match: they are grid items in a single row, so the row
     sizes to the tallest and stretches the rest to meet it. The equal height
     was never the min-height's doing. */
  transition: transform 380ms var(--ease-smooth), box-shadow 380ms var(--ease-smooth);
}

.hs-wall__card:hover {
  transform: translate3d(0, -4px, 0);
}

/* ---- the four cards arriving from behind the heading ----
   js/wall-burst.js adds .is-burst and animates --bx / --by / --bs; this is
   where those become a transform. The card's own transform lives here rather
   than being written inline by the script for one reason: the hover lift below
   is also a transform, and an inline one would beat it permanently. Composed
   from the same three variables, the animation and the lift coexist.

   The class is doubled on purpose. `.reveal.is-visible` sets `transform` at
   two classes as well, and a tie is settled by source order — which is not
   something this rule should depend on.

   The defaults are the identity transform, so the rule is inert until the
   script writes a value, and harmless if it never does. */

.hs-wall.is-burst .hs-wall__card.hs-wall__card {
  transform: translate3d(var(--bx, 0px), var(--by, 0px), 0) scale(var(--bs, 1));
  /* The transform transition above has to go while the scrub owns the
     transform. Left on, every step of the scroll would be eased over 380ms on
     top of the scrub's own smoothing, and the cards would lag the gesture and
     drift on after it stops — exactly the rubbery feel this is meant not to
     have. box-shadow keeps its transition: nothing is animating that. */
  transition: box-shadow 380ms var(--ease-smooth);
}

/* Added by js/wall-burst.js once the last card has landed, and taken off again
   if the reader scrolls back up into the run. It gives the transform its
   transition back, so the hover lift eases as it does everywhere else rather
   than snapping — the one thing the rule above costs. */

.hs-wall.is-burst.is-settled .hs-wall__card.hs-wall__card {
  transition:
    transform 380ms var(--ease-smooth),
    box-shadow 380ms var(--ease-smooth);
}

.hs-wall.is-burst .hs-wall__card.hs-wall__card:hover {
  transform: translate3d(var(--bx, 0px), calc(var(--by, 0px) - 4px), 0) scale(var(--bs, 1));
}

/* ---- the six grounds ----
   One quiet ground per card, assigned in order by hs_wall_tones() in
   includes/hrms-content.php. A four-card wall takes the first four, so the
   first card is the same colour on a wall of four and a wall of six.

   THEY REPLACED light / dark / brand
   Near-white, near-black and brand blue is an emphasis device: the dark and
   blue cards read as "these ones matter more", which is true of a hierarchy
   and false of a wall, where the cards are equal parts of one answer. Six
   grounds of the same weight say six different things without ranking them.

   Each pair is one hue: a pale ground at roughly 6% saturation-on-white for
   the card, and the same hue at full strength for the icon chip, so the chip
   reads as belonging to the card rather than as a sticker on it. Type stays
   the site's own near-black and grey on every one, which is what keeps six
   colours from becoming six designs.

   --tint is the hover shadow's hue, so a card's lift is coloured by its own
   ground rather than by one grey borrowed from the old light card. */

.hs-wall__card--sky   {
  --tint: 37 99 235;
  background-color: #E7EFFD;
}

.hs-wall__card--lilac {
  --tint: 109 91 246;
  background-color: #EFEAFD;
}

.hs-wall__card--mint  {
  --tint: 21 128 61;
  background-color: #E3F4EC;
}

.hs-wall__card--sand  {
  --tint: 194 116 11;
  background-color: #FBF0DE;
}

.hs-wall__card--rose  {
  --tint: 220 38 38;
  background-color: #FCEAEC;
}

.hs-wall__card--aqua  {
  --tint: 14 116 144;
  background-color: #E2F1F6;
}

.hs-wall__card--sky,
.hs-wall__card--lilac,
.hs-wall__card--mint,
.hs-wall__card--sand,
.hs-wall__card--rose,
.hs-wall__card--aqua {
  color: #0B0D12;
}

.hs-wall__card--sky:hover,
.hs-wall__card--lilac:hover,
.hs-wall__card--mint:hover,
.hs-wall__card--sand:hover,
.hs-wall__card--rose:hover,
.hs-wall__card--aqua:hover {
  box-shadow: 0 26px 54px -32px rgb(var(--tint) / 0.42);
}

.hs-wall__card--sky   .hs-wall__icon {
  background-color: #2563EB;
  color: #ffffff;
}

.hs-wall__card--lilac .hs-wall__icon {
  background-color: #6D5BF6;
  color: #ffffff;
}

.hs-wall__card--mint  .hs-wall__icon {
  background-color: #15803D;
  color: #ffffff;
}

.hs-wall__card--sand  .hs-wall__icon {
  background-color: #C2740B;
  color: #ffffff;
}

.hs-wall__card--rose  .hs-wall__icon {
  background-color: #DC2626;
  color: #ffffff;
}

.hs-wall__card--aqua  .hs-wall__icon {
  background-color: #0E7490;
  color: #ffffff;
}

.hs-wall__card--sky   .hs-wall__text,
.hs-wall__card--lilac .hs-wall__text,
.hs-wall__card--mint  .hs-wall__text,
.hs-wall__card--sand  .hs-wall__text,
.hs-wall__card--rose  .hs-wall__text,
.hs-wall__card--aqua  .hs-wall__text {
  color: #5A6070;
}

/* ---- kept, unused by the walls ----
   Nothing on the site assigns these any more. They stay because .hs-wall__card
   is a public class and a page could still ask for the old three; removing
   them would turn that into a card with no background at all. */

.hs-wall__card--light {
  background-color: #EDF1F4;
  color: #0B0D12;
}

.hs-wall__card--light:hover {
  box-shadow: 0 26px 54px -32px rgba(16, 24, 48, 0.5);
}

.hs-wall__card--dark {
  background-color: #0B0D12;
  color: #ffffff;
  box-shadow: 0 16px 40px -32px rgba(11, 13, 18, 0.7);
}

.hs-wall__card--dark:hover {
  box-shadow: 0 30px 62px -32px rgba(11, 13, 18, 0.8);
}

.hs-wall__card--brand {
  background-color: #3B82F6;
  color: #ffffff;
  box-shadow: 0 16px 40px -30px rgba(37, 99, 235, 0.75);
}

.hs-wall__card--brand:hover {
  box-shadow: 0 30px 62px -30px rgba(37, 99, 235, 0.8);
}

.hs-wall__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.hs-wall__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 19px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.3px;
  color: inherit;
}

/* The mark inverts against its card: brand on light, white on dark, dark on
   brand. Three rules rather than one with opacity — a knocked-back white on
   the blue reads as a mistake rather than a choice. */

.hs-wall__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 100px;
}

.hs-wall__icon .hs-i {
  width: 19px;
  height: 19px;
}

.hs-wall__card--light .hs-wall__icon {
  background-color: #3B82F6;
  color: #ffffff;
}

.hs-wall__card--dark .hs-wall__icon  {
  background-color: #ffffff;
  color: #0B0D12;
}

.hs-wall__card--brand .hs-wall__icon {
  background-color: #0B0D12;
  color: #ffffff;
}

.hs-wall__text {
  margin-top: 26px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.55;
}

.hs-wall__card--light .hs-wall__text {
  color: #5A6070;
}

.hs-wall__card--dark .hs-wall__text  {
  color: rgba(255, 255, 255, 0.64);
}

.hs-wall__card--brand .hs-wall__text {
  color: rgba(255, 255, 255, 0.88);
}

@media (prefers-reduced-motion: reduce) {
  .hs-wall__card {
    transition: none !important;
    transform: none !important;
  }
}

/* ==========================================================================
   HERO — PLAY BUTTON
   Centred on the product shot, opening the same panel the "View demo" button
   does. It lives inside .float-host, so it rides the shot's scroll-grow and
   float and stays on its centre at every scale.

   Above everything in that box: the dashboard is 1, its live overlay 2, the
   cast figures 3.
   ========================================================================== */

.shot-play {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 4;
  display: grid;
  place-items: center;
  width: 88px;
  height: 88px;
  border-radius: 100px;
  background-color: #ffffff;
  color: #0B0D12;
  cursor: pointer;
  transform: translate3d(-50%, -50%, 0);
  box-shadow:
    0 2px 6px rgba(16, 24, 48, 0.18),
    0 24px 50px -18px rgba(16, 24, 48, 0.55);
  transition: transform 380ms var(--ease-smooth), box-shadow 380ms var(--ease-smooth);
}

/* Scaled about the same point it is translated to, so the hover growth does
   not shunt it off centre. */

.shot-play:hover {
  transform: translate3d(-50%, -50%, 0) scale(1.06);
  box-shadow:
    0 2px 6px rgba(16, 24, 48, 0.2),
    0 30px 60px -18px rgba(16, 24, 48, 0.6);
}

.shot-play:focus-visible {
  outline: 3px solid #2563EB;
  outline-offset: 4px;
}

/* Optically centred, not geometrically: a triangle's visual centre of mass
   sits left of its bounding box, so a play mark centred by its box always
   looks a couple of pixels too far left. */

.shot-play__tri {
  width: 26px;
  height: 30px;
  margin-left: 5px;
}

/* One slow ring leaving the button. It is the only thing on the shot that
   says the artwork is a film rather than a picture — without it a white
   circle on a screenshot reads as part of the screenshot. */

.shot-play__pulse {
  position: absolute;
  inset: 0;
  border-radius: 100px;
  box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.6);
  animation: shot-play-pulse 2600ms var(--ease-smooth) infinite;
  pointer-events: none;
}

@keyframes shot-play-pulse {
  0%   {
    box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.55);
    opacity: 1;
  }

  70%  {
    box-shadow: 0 0 0 26px rgba(255, 255, 255, 0);
    opacity: 0;
  }

  100% {
    box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
    opacity: 0;
  }
}

/* Smaller where the shot itself is smaller, or an 88px disc covers a third of
   the dashboard on a phone. */

@media (max-width: 767px) {
  .shot-play {
    width: 62px;
    height: 62px;
  }

  .shot-play__tri {
    width: 19px;
    height: 22px;
    margin-left: 4px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .shot-play {
    transition: none !important;
  }

  .shot-play__pulse {
    animation: none;
  }
}

/* ==========================================================================
   PRICING PAGE — /pricing/niyuk-hr/
   Header and segmented billing switch, three tiers, a comparison panel, the
   FAQ column, and the closing band.
   ========================================================================== */

/* A ground for the cards to sit on. The old gradient resolved to white at 72%,
   which is exactly where the cards start, so four white cards met a white page
   and the whole band went flat. This holds a tint the length of the section and
   only lets go at the very bottom, where the disclosure below needs an edge to
   start against. Two faint brand washes over it, the same pair .sec-wash uses,
   so it reads as this site's ground and not a grey box. */
.pr-head {
  background:
    radial-gradient(78% 52% at 12% 4%, rgba(37, 99, 235, 0.10), rgba(37, 99, 235, 0) 62%),
    radial-gradient(62% 46% at 90% 74%, rgba(139, 92, 246, 0.07), rgba(139, 92, 246, 0) 66%),
    linear-gradient(180deg, #EDF1FA 0%, #F4F7FD 40%, #F1F4FB 84%, #FFFFFF 100%);
  /* Clears the fixed navbar — this is the first section on the page, so there
     is nothing above it to do that. */
  padding-top: calc(var(--nav-h) + 58px);
}

@media (min-width: 768px) {
  .pr-head {
    padding-top: calc(var(--nav-h) + 88px);
  }
}

/* The badge sits above the heading, and the heading needs a little air under
   it. .pr-head__title carries no top margin of its own (it used to open the
   section), so the gap goes here. */
.pr-head__intro .badge { margin-bottom: 20px; }

/* The 680px measure belongs to the lead, not to the block. On the title it
   forced "Choose Your Perfect Plan for Niyuk HR" onto two lines at every width
   the page is ever read at — the heading needs about 900px at its full size,
   and the measure exists to keep a paragraph readable, which a seven-word
   heading is not. So the title takes the content width and the lead keeps the
   measure. */
.pr-head__intro {
  margin: 0 auto;
  text-align: center;
}

.pr-head__intro .pr-head__lead {
  margin-left: auto;
  margin-right: auto;
  max-width: 680px;
}

/* Held on one line wherever there is room for it. Below that it wraps as any
   heading does — nowrap without the guard would push the page sideways on a
   phone, which is the one thing a centred heading must never do. */
@media (min-width: 1024px) {
  .pr-head__title { white-space: nowrap; }
}

.pr-head__title {
  margin-top: 22px;
}

.pr-head__lead  {
  margin-top: 18px;
}

/* ------------------------------------------------------------------
   "See all Plans Comparison" — the matrix behind a disclosure
   ------------------------------------------------------------------ */

/* The disclosure is a hinge between the plan cards and the table it opens, not
   a section in its own right. At a section's padding it sat in 100px of air
   above and 200px below (its own, plus the FAQ's), which read as three
   unrelated blocks rather than one control belonging to the cards. */
.pr-open-sec {
  padding-top: 0;
  padding-bottom: 30px;
}

.pr-head:has(+ .pr-open-sec) { padding-bottom: 34px; }

@media (min-width: 768px) {
  .pr-open-sec { padding-bottom: 40px; }
  .pr-head:has(+ .pr-open-sec) { padding-bottom: 44px; }
}

.pr-open { text-align: center; }

/* The marker is the browser's own triangle, and this control already says
   which way it is going in words. -webkit-details-marker is Safari's. */
.pr-open__btn { list-style: none; }
.pr-open__btn::-webkit-details-marker { display: none; }

.pr-open__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 17px 34px;
  border: 1.5px solid #2563EB;
  border-radius: 100px;
  background-color: #FFFFFF;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 600;
  color: #2563EB;
  cursor: pointer;
  transition:
    background-color 260ms var(--ease-soft),
    color 260ms var(--ease-soft),
    box-shadow 260ms var(--ease-soft);
}

.pr-open__btn:hover {
  background-color: #2563EB;
  color: #FFFFFF;
  box-shadow: 0 16px 34px -20px rgba(37, 99, 235, 0.7);
}

.pr-open__btn:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: 3px;
}

/* One label at a time: a control that still reads "See all Plans Comparison"
   with the table already open is describing what it did, not what it will do. */
.pr-open__open { display: none; }
.pr-open[open] .pr-open__shut { display: none; }
.pr-open[open] .pr-open__open { display: inline; }

/* The table reads left to right; the summary above it is centred. */
.pr-open[open] > .pr-panel { text-align: left; }

/* ---- the header ---- */

/* The title opens the section now, so it carries no top margin of its own —
   the section's own padding is the space above it. */

.pr-head__title {
  margin-top: 0;
}

.pr-head__lead  {
  margin-top: 16px;
}

/* ---- the plan cards ---- */

.pr-plans {
  display: grid;
  gap: 20px;
  margin-top: 46px;
}

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

@media (min-width: 1024px) {
  /* One column per plan, counted in the markup. Four cards on the 1200px
     measure is about 280px each, which is why the type steps down a little
     below. */
  .pr-plans {
    grid-template-columns: repeat(var(--pr-cols, 3), minmax(0, 1fr));
    gap: 22px;
  }
}

/* Four across is tighter than three, so the two largest sizes come back a
   step. Nothing else changes: the card is the same card. */
@media (min-width: 1024px) {
  .pr-plans:not([style*="--pr-cols: 3"]) .pr-plan { padding: 30px 22px 28px; }
  .pr-plans:not([style*="--pr-cols: 3"]) .pr-plan--popular { padding: 29px 21px 27px; }
  .pr-plans:not([style*="--pr-cols: 3"]) .pr-plan__name { font-size: 27px; }
  .pr-plans:not([style*="--pr-cols: 3"]) .pr-plan__price { font-size: 34px; }
  .pr-plans:not([style*="--pr-cols: 3"]) .pr-plan__badge { left: 22px; }
}

.pr-plan {
  display: flex;
  flex-direction: column;
  padding: 26px 24px 26px;
  border-radius: 20px;
  border: 1px solid rgba(16, 24, 48, 0.12);
  background-color: #ffffff;
  transition: transform 380ms var(--ease-smooth), box-shadow 380ms var(--ease-smooth);
}

.pr-plan:hover {
  transform: translate3d(0, -4px, 0);
  box-shadow: 0 26px 56px -34px rgba(16, 24, 48, 0.5);
}

.pr-plan--popular {
  border-color: #2563EB;
  box-shadow: 0 20px 50px -30px rgba(37, 99, 235, 0.55);
}

.pr-plan {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 34px 28px 32px;
  border-radius: 22px;
  border: 1px solid #E4E7EC;
  background-color: #FFFFFF;
  transition: box-shadow 320ms var(--ease-soft), border-color 320ms var(--ease-soft);
}

.pr-plan:hover { box-shadow: 0 26px 60px -40px rgba(16, 24, 48, 0.4); }

/* The recommendation: a brand border and a tinted ground, so the card is
   marked by what it is made of rather than by being made bigger. */
.pr-plan--popular {
  border-color: #2563EB;
  border-width: 2px;
  background-color: #F4F8FF;
  padding: 33px 27px 31px;
}

/* Both flags straddle the card's top edge. Inside the card they would read as
   a first line of content; on the edge they read as a label on the card. */
.pr-plan__flag,
.pr-plan__badge {
  position: absolute;
  top: 0;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  padding: 7px 16px;
  border-radius: 100px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.7px;
  text-transform: uppercase;
  white-space: nowrap;
}

.pr-plan__flag {
  left: 50%;
  transform: translate(-50%, -50%);
  border: 2px solid #2563EB;
  background-color: #FFFFFF;
  color: #2563EB;
}

.pr-plan__badge {
  left: 28px;
  border: 1.5px solid #86E0AC;
  background-color: #ECFCF2;
  color: #0B7A43;
}

.pr-plan__eyebrow {
  margin-bottom: 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 1px;
  line-height: 1.3;
  text-transform: uppercase;
  color: #6B7280;
}

/* A card with no eyebrow reserves the space one would take, so four cards line
   their names, prices and buttons up whether or not each has one. An empty <p>
   would do the same and is what this replaces: the row would then contain
   elements that exist only to be blank, which is the thing the blurb handling
   in js/pricing-live.js already refuses to do. */
@media (min-width: 1024px) {
  .pr-plan__name { margin-top: 26px; }
  .pr-plan__eyebrow + .pr-plan__name { margin-top: 0; }

  /* Three lines, which is the longest blurb in the set. Below this width the
     cards stack and there is nothing to line up with. */
  .pr-plan__blurb { min-height: 70px; }
}

.pr-plan__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 32px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.8px;
  color: #0B0D12;
}

.pr-plan__blurb {
  margin-top: 12px;
  font-size: 15px;
  line-height: 1.55;
  color: #4D585F;
}

.pr-plan__price {
  margin-top: 26px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 40px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -1.4px;
  color: #0B0D12;
}

.pr-plan__per {
  margin-left: 6px;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0;
  color: #6B7280;
}

.pr-plan__includes {
  margin-top: 14px;
  font-size: 15px;
  font-weight: 700;
  color: #1D1D1D;
}

/* Fine print under the headcount it qualifies, so it reads as part of the
   price rather than as a separate claim. */
.pr-plan__extra,
.pr-plan__note {
  margin-top: 6px;
  font-size: 13.5px;
  line-height: 1.5;
  color: #6B7280;
}

/* Directly under the price block. It cannot be pushed to the foot of the card:
   the feature list comes after it, so margin-top:auto drove the button of the
   shortest list all the way down past its own features. */
.pr-plan__acts { margin-top: 26px; }

.pr-plan__buy {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 54px;
  /* A pill, which is what every other button on the site is: .btn in
     css/input.css is rounded-pill, and the 12px this used to carry made the
     pricing cards the one place with square-ish actions. */
  border-radius: 100px;
  /* The Signup gradient, off .btn-brand. A flat blue next to a gradient one is
     two blues, and the reader has no way to know the difference is meaningless.
     Kept as a copy rather than @apply because this file's rules are plain CSS
     the generated stylesheet carries verbatim. */
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  box-shadow: 0 8px 20px -8px rgba(37, 99, 235, 0.55);
  font-size: 16px;
  font-weight: 600;
  color: #FFFFFF;
  transition:
    transform 260ms var(--ease-soft),
    filter 260ms var(--ease-soft),
    box-shadow 260ms var(--ease-soft);
}

.pr-plan__buy:hover {
  transform: translateY(-2px);
  filter: saturate(1.08) brightness(1.03);
  box-shadow: 0 16px 30px -10px rgba(37, 99, 235, 0.6);
}

/* The free card's action is a different one — starting, not buying — so it
   takes a different colour rather than competing with the paid plans' blue.
   Same gradient shape, so the two read as one family. */
.pr-plan--free .pr-plan__buy {
  background-image: linear-gradient(150deg, #FBC96B 0%, #F59E0B 45%, #D9880A 100%);
  box-shadow: 0 8px 20px -8px rgba(217, 136, 10, 0.55);
}

.pr-plan--free .pr-plan__buy:hover {
  box-shadow: 0 16px 30px -10px rgba(217, 136, 10, 0.6);
}

/* ---- What the plan comes with -------------------------------------- */

.pr-plan__feat {
  margin-top: 26px;
  padding-top: 24px;
  border-top: 1px solid #E4E7EC;
}

.pr-plan--popular .pr-plan__feat { border-top-color: #D3E1FB; }

.pr-plan__feathead {
  margin-bottom: 16px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.9px;
  text-transform: uppercase;
  color: #6B7280;
}

/* ------------------------------------------------------------------
   Plan features: three rows, and the rest in a panel
   ------------------------------------------------------------------
   The cards carry every feature in their markup; this is what shows three of
   them. Keyed off the data attribute the script removes when it clones the
   list into the dialog, so the panel gets the whole thing from the same nodes
   without the copy existing twice. See sections/pricing/plans.php. */

.pr-plan__list[data-plan-list] li:nth-child(n + 4) {
  display: none;
}

/* The fallback when there is no <dialog> to open: js/plan-modal.js sets this
   on <html> and gives up, and every row shows in the card instead of sitting
   behind a button that cannot do anything. */
.no-dialog .pr-plan__list[data-plan-list] li:nth-child(n + 4) {
  display: flex;
}

.no-dialog .pr-plan__more {
  display: none;
}

/* …and two of them on /pricing/niyuk-recruit/, asked for on 2026-09-02.

   Scoped to .pr-r-sec, which only that page's section carries, because the
   markup above is shared with /pricing/niyuk-hr/ and that page still shows
   three. Its twin is $prFlShown in sections/pricing/_featlist.php, which sets
   the number the "Read more" button counts down from; change one and change
   the other or the button offers "4 more" over a card showing a different
   number of rows.

   AFTER the two rules above on purpose: these carry one more class each, so
   they would win on specificity anyway, but the pair reads as an override of
   the pair it follows and belongs next to it. */

.pr-r-sec .pr-plan__list[data-plan-list] li:nth-child(n + 3) {
  display: none;
}

/* The same no-dialog fallback: with no panel to open, every row shows in the
   card rather than hiding behind a button that cannot do anything. */

.no-dialog .pr-r-sec .pr-plan__list[data-plan-list] li:nth-child(n + 3) {
  display: flex;
}


.pr-plan__more {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  padding: 0;
  border: 0;
  background: none;
  font-size: 14px;
  font-weight: 600;
  color: #2563EB;
  cursor: pointer;
  transition: color 220ms var(--ease-soft);
}

.pr-plan__more:hover {
  color: #1D4FD7;
}

.pr-plan__morecount {
  padding: 3px 9px;
  border-radius: 100px;
  background-color: #EEF3FF;
  font-size: 12px;
  font-weight: 600;
}

/* ---- the panel ----
   Same shell as the booking modal, sized for a column of text rather than a
   scheduler: it takes the height of its list up to a cap, then scrolls. */

.plmodal {
  margin: auto;
  padding: 0;
  border: 0;
  max-width: none;
  max-height: none;
  background: transparent;
  overflow: visible;
}

.plmodal::backdrop {
  background-color: rgba(6, 8, 14, 0.72);
  backdrop-filter: blur(6px);
}

.plmodal__frame {
  display: flex;
  flex-direction: column;
  width: min(460px, 92vw);
  max-height: min(680px, 86vh);
  border-radius: 24px;
  background-color: #ffffff;
  box-shadow: 0 40px 90px -40px rgba(9, 14, 28, 0.6);
  overflow: hidden;
}

.plmodal__head {
  position: relative;
  flex: none;
  padding: 26px 56px 18px 28px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.plmodal__eyebrow {
  display: block;
  margin-bottom: 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.9px;
  text-transform: uppercase;
  color: #6B7280;
}

.plmodal__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: #0B0D12;
}

.plmodal__close {
  position: absolute;
  top: 22px;
  right: 20px;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 50%;
  background-color: #F1F4F9;
  color: #4D585F;
  cursor: pointer;
  transition: background-color 220ms var(--ease-soft), color 220ms var(--ease-soft);
}

.plmodal__close:hover {
  background-color: #E4E9F2;
  color: #0B0D12;
}

.plmodal__close svg {
  width: 12px;
  height: 12px;
}

.plmodal__body {
  overflow-y: auto;
  padding: 22px 28px 28px;
  -webkit-overflow-scrolling: touch;
}


.pr-plan__list {
  display: grid;
  gap: 11px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pr-plan__list li {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  font-size: 15px;
  line-height: 1.45;
  color: #1D1D1D;
}

.pr-plan__tick {
  display: grid;
  place-items: center;
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  border-radius: 50%;
  background-color: #16A34A;
  color: #FFFFFF;
}

.pr-plan__tick .hs-i { width: 12px; height: 12px; }

/* ---- the matrix ---- */

.pr-compare-sec {
  background-color: #F6F8FD;
}

.pr-panel {
  padding: 36px 16px;
  border-radius: 28px;
  background-color: #ffffff;
  box-shadow: 0 24px 60px -44px rgba(16, 24, 48, 0.45);
}

@media (min-width: 768px) {
  .pr-panel {
    padding: 52px 40px;
  }
}

.pr-panel__head {
  text-align: center;
}

.pr-panel__title {
  margin-top: 20px;
}

/* The rows sit inside a bordered card rather than running loose on the page:
   thirty-six rows of ticks need an edge to be read against. */
.pr-grid-scroll {
  margin-top: 38px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid #E6E8EC;
  border-radius: 18px;
  background-color: #FFFFFF;
}

.pr-grid-scroll:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: 4px;
  border-radius: 16px;
}

.pr-grid {
  width: 100%;
  /* Five columns now: the feature label plus four plans. At 640 the plan
     columns crushed into two lines each rather than scrolling. */
  min-width: 780px;
  border-collapse: collapse;
}

.pr-grid th,
.pr-grid td {
  padding: 15px 16px;
  border-bottom: 1px solid #EFF1F4;
}

.pr-grid tbody tr:last-child th,
.pr-grid tbody tr:last-child td { border-bottom: 0; }

/* The group heading opens a section, so it takes the rule above it rather
   than one of its own underneath. The band is what separates one group of rows
   from the next at a glance — a reader skimming for "Add-Ons" finds the tint
   before they find the words. */
.pr-grid__grouprow th {
  border-bottom: 0;
  border-top: 1px solid #EFF1F4;
  background-color: #F7F9FF;
}

.pr-grid tbody:first-of-type .pr-grid__grouprow th { border-top: 0; }

/* Deliberately NOT sticky. The grid is 36 rows and a sticky header was the
   obvious answer, but the scroll container around it is `overflow-x: auto`,
   and a sticky offset resolves against the nearest scrolling ancestor — that
   container, which never scrolls vertically. The header therefore never
   sticks to the viewport, and what it does instead is paint over the first
   rows of the table.

   Orientation comes from the group bands every eight to twelve rows, and from
   the plan names being on the cards directly above. */

.pr-grid thead th {
  padding-top: 14px;
  padding-bottom: 14px;
  /* A band, so the head reads as the frame the table hangs in rather than as
     a first row of content. */
  background-color: #F7F8FA;
  box-shadow: inset 0 -1px 0 #E6E8EC;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 600;
  color: #0B0D12;
  text-align: center;
}

.pr-grid thead .pr-grid__feat {
  text-align: left;
}

.pr-grid thead th:not(.pr-grid__feat) {
  width: calc(70% / var(--pr-grid-cols, 3));
}

/* The group bands. A run of twelve rows with no break is a wall; these are
   what let the reader find "the AI things" without reading every label. */

/* A heading, set like one: the group is a section of the table, and a small
   coloured label reads as a tag on the row beneath rather than as the name of
   everything under it. */
.pr-grid__group {
  /* Even, now that it is a filled band rather than air above a heading. */
  padding-top: 16px;
  padding-bottom: 16px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  text-align: left;
  color: #0B0D12;
}

.pr-grid__feat {
  min-width: 240px;
  font-size: 14px;
  font-weight: 500;
  text-align: left;
  color: #22262F;
}


.pr-grid td {
  text-align: center;
}

/* The recommended column, tinted the full height so it reads as a column
   rather than as thirty-six separate cells. */

.pr-grid__win {
  background-color: rgba(37, 99, 235, 0.04);
}

/* ---- the plan header inside the grid --------------------------------
   Name, price, what it includes and the two actions, repeated from the cards.
   The table opens from a control well below them and runs to thirty-odd rows,
   so by the time a reader reaches the row that decides it, the cards are off
   screen — a column you cannot act on from where you are reading sends you
   back up to find the button. */

/* The head is one line of text now, so it stops reserving the height a price
   block and a button used to need. */
.pr-grid thead th { padding-top: 18px; padding-bottom: 18px; vertical-align: middle; }

.pr-grid__lead {
  vertical-align: bottom;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #6B7280;
}

.pr-grid__plan {
  display: block;
  font-size: 17px;
  font-weight: 700;
  color: #0B0D12;
}


/* ---- the three states ----
   Three shapes, not three colours: the difference has to survive being
   printed, being colour-blind, and being skimmed at speed. */

.pr-yes,
.pr-no {
  display: inline-grid;
  place-items: center;
}

/* The plan cards' tick, at the grid's size: .pr-plan__tick is the same filled
   disc with a white check, 20px there and 16 here. One mark for "included" on
   a page that says it in two places. */
.pr-yes {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background-color: #16A34A;
  color: #FFFFFF;
}

.pr-yes .hs-i {
  width: 10px;
  height: 10px;
  stroke-width: 3;
}

/* The cross stays bare. The disc is what marks the answer worth finding, and
   a filled red disc opposite it would give "not included" the same weight. */
.pr-no {
  width: 24px;
  height: 24px;
  color: #E5484D;
}

.pr-no .hs-i {
  width: 20px;
  height: 20px;
  stroke-width: 2.4;
}



/* Neither included nor unavailable: buyable. Amber because it is a cost, not
   a failure, and outlined because it is an offer rather than a state. */

.pr-add {
  display: inline-block;
  padding: 4px 11px;
  border-radius: 100px;
  border: 1px solid rgba(233, 162, 59, 0.4);
  background-color: #FDF6E9;
  font-size: 11.5px;
  font-weight: 600;
  color: #B4761B;
}

.pr-val {
  font-size: 13.5px;
  font-weight: 600;
  color: #22262F;
}

.pr-grid__ai {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 100px;
  background-color: rgba(109, 75, 224, 0.12);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #6D4BE0;
}

.pr-notes {
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
}

.pr-notes li {
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #8A90A0;
}

.pr-notes li + li {
  margin-top: 4px;
}

/* ---- merged with the cards above ----
   /pricing/niyuk-hr/ renders the matrix inside the pricing section instead of
   as its own grey band below it ($PR_COMPARE_MERGE, see plans.php). Two things
   change, and only from 1024px up — below that the cards stack, the table
   keeps its own horizontal scroll, and the two read as one block simply by
   sharing a background.

   1. The cards sit on the table's columns. The card row gains a leading column
      the width of the Module column and the first card starts in column two,
      so each card is the header of the column it prices, and a reader looking
      at "Shift planning · Add-on · Add-on · tick" is looking straight up a
      column at the price that buys it.

   2. The plan-name row sticks. It could not before: its scroll container is
      `overflow-x: auto`, a sticky offset resolves against the nearest
      scrolling ancestor, and that container never scrolls vertically — so the
      header painted over the first rows instead of pinning. Merged, the table
      is no wider than the card row, so the container goes back to
      `overflow: visible` and the header pins under the 72px navbar. */

/* Not a panel any more: the lower half of the pricing block. */

.pr-panel--flat {
  margin-top: 54px;
  padding: 0;
  border-radius: 0;
  background-color: transparent;
  box-shadow: none;
}

/* The head steps down from "new section" to "next part of this one": left
   aligned, and sized as a subheading rather than as a second page title. */

.pr-panel--flat .pr-panel__head {
  text-align: left;
}

.pr-panel--flat .pr-panel__title {
  margin-top: 14px;
  font-size: 24px;
  letter-spacing: -0.4px;
}

@media (min-width: 640px) {
  .pr-panel--flat .pr-panel__title {
    font-size: 27px;
  }
}

.pr-panel--flat .pr-grid-scroll {
  margin-top: 26px;
}

@media (min-width: 1024px) {
  .pr-merge {
    /* The Module column and the gutter the card row already uses. Everything
       below is laid out from these two numbers alone, which is what keeps the
       table and the cards on the same columns. */
    --prm-feat: 262px;
    --prm-gap: 22px;
  }

  /* No spacer element for the leading column: an empty grid cell is not
     content, and js/pricing-live.js clones .pr-plan nodes into this row when
     the feed carries a different number of plans. */

  .pr-merge .pr-plans {
    grid-template-columns: var(--prm-feat) repeat(3, minmax(0, 1fr));
    gap: var(--prm-gap);
  }

  .pr-merge .pr-plans > .pr-plan:first-child {
    grid-column: 2;
  }

  .pr-merge .pr-grid-scroll {
    overflow: visible;
  }

  /* Separated borders rather than collapsed, so the columns carry the same
     22px gutters the cards do. border-spacing also applies at the two outer
     edges, so the table is pulled one gutter wider on each side: that puts the
     Module column's left edge back on the content edge and every plan column
     exactly under its card. */

  .pr-merge .pr-grid {
    min-width: 0;
    width: calc(100% + (var(--prm-gap) * 2));
    margin-left: calc(var(--prm-gap) * -1);
    margin-right: calc(var(--prm-gap) * -1);
    table-layout: fixed;
    border-collapse: separate;
    border-spacing: var(--prm-gap) 0;
  }

  .pr-merge .pr-grid__feat {
    width: var(--prm-feat);
    min-width: 0;
  }

  /* The gutters are the spacing now. Zero side padding is also what makes the
     tinted column sit exactly under the recommended card rather than 16px
     inside it. */

  .pr-merge .pr-grid th,
  .pr-merge .pr-grid td {
    padding-left: 0;
    padding-right: 0;
  }

  /* The header row comes out of the merged layout: the plan cards sit directly
     above, on these exact columns, and name every one of them. Printing
     "Module | Essential | Growth | Enterprise" underneath them says it twice.

     Hidden, not deleted. The <thead> is what lets a screen reader announce
     which plan a tick belongs to, and it is still the only labelling below
     1024px, where the cards stack and stop heading anything. So it stays in
     the markup and only this layout hides it.

     clip rather than display:none, because a table row removed from the layout
     also takes its column widths with it. */

  .pr-merge .pr-grid thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* The head moves into the empty leading column, sat on top of the table so
     it reads as the label for the Module column rather than as a title
     floating in the gap between the cards and the grid. That column is blank
     for the whole height of the card row, which is the only reason there is
     room for it.

     Absolute rather than moved in the markup: it is the panel's own head, it
     is written once, and below 1024px it goes straight back to sitting above
     the table with nothing to undo. */

  .pr-merge .pr-panel--flat {
    position: relative;
  }

  .pr-merge .pr-panel--flat .pr-panel__head {
    position: absolute;
    left: 0;
    bottom: calc(100% + 14px);
    width: var(--prm-feat);
  }

  /* One step down from the standalone panel's title: it is a column label at
     262px now, and "Everything" has to fit on a line. */

  .pr-merge .pr-panel--flat .pr-panel__title {
    font-size: 25px;
  }

  /* The gap above the table is the head's room, so the scroller gives up its
     own margin and the panel carries the whole distance. */

  .pr-merge .pr-panel--flat {
    margin-top: 46px;
  }

  .pr-merge .pr-panel--flat .pr-grid-scroll {
    margin-top: 0;
  }
}

/* ---- the FAQ column ---- */

/* The same white wash .sec-wash--white lays down elsewhere: white at both
   ends lifting to a tint through the middle, so the section reads as its own
   band without a hard edge against the white above and below it. Written here
   rather than added as a class in the markup because this section is shared by
   both pricing pages and the contact page, and it should look the same on all
   three. */

/* Less foot than the shared .section rhythm gives it. The band below opens
   with its own 100px of air, so the two together left the "Help centre" button
   floating in about 200px of nothing. Trimmed here rather than on .section, and
   only at the bottom: the head of this section still wants its full space. */

.pr-faq-sec {
  padding-bottom: 44px;
  background-color: #ffffff;
  background-image:
    radial-gradient(70% 50% at 50% 0%, rgba(37, 99, 235, 0.055), rgba(37, 99, 235, 0) 70%),
    linear-gradient(180deg, #FFFFFF 0%, #F4F6FB 46%, #F7F9FC 62%, #FFFFFF 100%);
}

.pr-faq__head {
  margin: 0 auto;
  max-width: 620px;
  text-align: center;
}

.pr-faq__title {
  margin-top: 20px;
}

.pr-faq__lead  {
  margin-top: 16px;
}

.pr-faq__list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 44px auto 0;
  max-width: 720px;
}

/* Same +/× sign as the site's other accordions; only the size differs. */

.pr-faq__sign {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 100px;
  background-color: #0B0D12;
}

.pr-faq__sign span:first-child {
  width: 11px;
  height: 2px;
  border-radius: 100px;
}

.pr-faq__sign span:last-child {
  width: 2px;
  height: 11px;
  border-radius: 100px;
}

.pr-faq__more {
  display: flex;
  justify-content: center;
  margin-top: 40px;
}

/* ---- the closing band ---- */

.pr-band-sec {
  background-color: #ffffff;
}

.pr-band {
  display: grid;
  overflow: hidden;
  border-radius: 28px;
  background-color: #0B0D12;
  color: #ffffff;
}

@media (min-width: 1024px) {
  .pr-band {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    align-items: center;
  }
}

.pr-band__copy {
  padding: 40px 28px;
}

@media (min-width: 1024px) {
  .pr-band__copy {
    padding: 56px 20px 56px 52px;
  }
}

.pr-band__flag {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.1);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.82);
}

.pr-band__title {
  margin-top: 22px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -1px;
  color: #ffffff;
}

.pr-band__accent {
  color: #5EEAD4;
}

.pr-band__row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 28px;
}

.pr-band__go {
  padding: 14px 26px;
  border-radius: 100px;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  font-size: 15px;
  font-weight: 600;
  color: #ffffff;
  transition: transform 300ms var(--ease-smooth);
}

.pr-band__go:hover {
  transform: translate3d(0, -2px, 0);
}

.pr-band__ghost {
  padding: 14px 26px;
  border-radius: 100px;
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.3);
  font-size: 15px;
  font-weight: 600;
  color: #ffffff;
  transition: background-color 300ms var(--ease-soft);
}

.pr-band__ghost:hover {
  background-color: rgba(255, 255, 255, 0.1);
}

.pr-band__note {
  margin-top: 16px;
  font-size: 13.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.5);
}

.pr-band__stats {
  display: flex;
  flex-wrap: wrap;
  gap: 26px 40px;
  margin: 34px 0 0;
  padding-top: 28px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  list-style: none;
}

.pr-band__num {
  display: block;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 30px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.8px;
  color: #ffffff;
}

.pr-band__label {
  display: block;
  margin-top: 7px;
  max-width: 160px;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.55);
}

/* The artwork bleeds off the panel's right edge, so it reads as a product
   carrying on rather than a screenshot pasted into a box. */

.pr-band__art {
  display: none;
}

@media (min-width: 1024px) {
  .pr-band__art {
    display: block;
    padding: 40px 0 40px 20px;
  }

  .pr-band__frame {
    overflow: hidden;
    width: calc(100% + 60px);
    border-radius: 18px 0 0 18px;
    background-color: #e4eaf9;
    box-shadow: 0 30px 70px -30px rgba(0, 0, 0, 0.6);
  }
}

@media (prefers-reduced-motion: reduce) {
  .pr-plan,
  .pr-band__go {
    transition: none !important;
    transform: none !important;
  }
}

/* ==========================================================================
   PRICING PAGE — /pricing/niyuk-recruit/
   Everything below builds on the block above: the section, the cards, the
   notes and the closing band are the Niyuk HR page's, and these rules only
   add what this product's shape needs — a billing switch, a feature list
   inside the card, and a third card that is a conversation rather than a
   price.
   ========================================================================== */

/* ---- the header ----
   The title opens the section now that the product name and its tag line are
   gone, so it carries no top margin of its own: the section's own padding is
   the space above it. */

.pr-r-sec .pr-head__title {
  margin-top: 0;
}

/* ---- the billing switch ---- */

.pr-r-switch {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 30px;
}

.pr-r-switch__label {
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
  transition: color 300ms var(--ease-soft);
}

.pr-r-switch__right {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Green, not the brand blue: this is a saving, and it should not compete with
   the one filled brand button further down the page. */

.pr-r-switch__save {
  padding: 4px 11px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.12);
  font-size: 11.5px;
  font-weight: 700;
  color: #15803D;
}

/* ---- the cards ----
   Three across from 1024px like the HR page, but each one is much taller here
   because it carries its own feature list, so the gaps are a little wider and
   the padding a little tighter. */

.pr-r-plans {
  align-items: start;
  margin-top: 40px;
}

.pr-r-plan {
  padding: 26px 24px 28px;
}

.pr-r-price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 2px 8px;
  margin-top: 16px;
}

.pr-r-unit {
  margin-left: 0;
  font-size: 13.5px;
}

/* "Let's talk" is a sentence where the others are a figure, so it takes the
   figure's weight but not its tracking — set at -1.4px it reads as cramped. */

.pr-r-price--talk {
  letter-spacing: -0.8px;
}

/* The two period-dependent lines. Both are in the markup and one is hidden,
   rather than one line the script rewrites: it is right before the script
   runs, and `.is-yearly` is a class the existing toggle already sets. */

.pr-r-when--y {
  display: none;
}

[data-pricing].is-yearly .pr-r-when--m {
  display: none;
}

[data-pricing].is-yearly .pr-r-when--y {
  display: block;
}

.pr-r-save {
  margin-left: 6px;
  font-size: 12px;
  font-weight: 700;
  color: #15803D;
}

.pr-r-blurb {
  margin-top: 14px;
  min-height: 0;
}

/* Three lines' worth from the point the cards sit side by side. The blurbs
   run to two lines, three and two, and without this the three "Buy now"
   buttons step down the row — which reads as three different kinds of card
   rather than three prices for one product. */

@media (min-width: 1024px) {
  .pr-r-blurb {
    min-height: 60px;
  }
}

/* The HR cards push their buttons to the bottom with margin-top: auto so the
   three line up. Here the feature list sits below the button, so that would
   drive the button through the middle of the card instead. */

.pr-r-acts {
  margin-top: 20px;
  padding-top: 0;
}

.pr-r-inclhead {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid rgba(16, 24, 48, 0.1);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #6B7280;
}

/* ---- the feature list ---- */

.pr-r-list {
  margin: 16px 0 0;
  padding: 0;
  list-style: none;
}

.pr-r-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.45;
  color: #3A4050;
}

.pr-r-item + .pr-r-item {
  margin-top: 11px;
}

.pr-r-tick {
  display: grid;
  place-items: center;
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.14);
  color: #16A34A;
}

/* What the upgrade actually buys. Both cards list every line they include, so
   a card still stands on its own — but on the live page the seven that only
   Business has sit unmarked in a list of sixteen, which is exactly the
   information a reader came to the page for, hidden in plain sight. */

.pr-r-item--more {
  font-weight: 600;
  color: #0B0D12;
}

.pr-r-item--more .pr-r-tick {
  background-color: rgba(37, 99, 235, 0.14);
  color: #2563EB;
}

/* The qualifier on a line, not a second line: "up to 1,000 records" is part of
   what "Integrated CRM" means here. */

.pr-r-note {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  font-weight: 500;
  color: #8A90A0;
}

/* ---- the enterprise card ---- */

.pr-r-ent {
  background-color: #F7F9FE;
}

.pr-r-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}

.pr-r-pills li {
  padding: 6px 12px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  font-size: 12px;
  font-weight: 600;
  color: #1D4ED8;
}

.pr-r-shot {
  overflow: hidden;
  margin-top: 22px;
  border-radius: 16px;
  background-color: #E4EAF9;
}

.pr-r-shot img {
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: 16 / 11;
  -o-object-fit: cover;
     object-fit: cover;
}

/* ---- the notes under the cards ---- */

.pr-r-notes {
  margin-top: 26px;
  text-align: center;
}

/* ==========================================================================
   PAYROLL SOFTWARE PAGE — /payroll-software.php
   The page is built from the HRMS block above: the hero, the scenic feature
   grid, the comparison table, the industries rail, the client story, the
   closing panel and the FAQ are all that block's, unchanged. What is here is
   only the three arrangements that content needs and the HRMS page has none
   of — the definition, the four connected systems, and the outcomes row.
   ========================================================================== */

/* One line under the feature heading, where the HRMS page has none. It has to
   clear the heading and stop short of the button beside it. */

.hs-feat__lead {
  margin-top: 14px;
  max-width: 460px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
  color: #5A6070;
}

/* ---- the "what is X?" definition, both inner pages ----
   Named hs- rather than py- because sections/hrms/_definition.php renders it
   for the HRMS page and the payroll page alike. Prose, centred, on a measure
   narrow enough to read. Not cards: two paragraphs cut into boxes stop being
   an explanation. */

.hs-what {
  margin: 0 auto;
  max-width: 760px;
  text-align: center;
}

/* Phones: the section's own 70 above and below, met by the next section's 70,
   put about 140px of white around two paragraphs. 40 here, on a class of its
   own because the section carries nothing else to aim at — .section and
   .bg-white are on half the site. Later in the file than .section, which is
   what settles it: the two weigh the same. */

@media (max-width: 767px) {
  .hs-what-sec {
    padding-top: 40px;
    padding-bottom: 40px;
  }
}

.hs-what__title {
  margin-top: 0;
}

/* The word the section is about, in the brand colour — the same device the
   home page's headings use. */

.hs-what__accent {
  color: #2563EB;
}

.hs-what__lead {
  margin-top: 22px;
}

/* Both paragraphs are set identically: same size, same measure, so the block
   reads as one passage rather than a lead with a footnote under it. The second
   one used to be smaller and on a narrower measure. */

.hs-what__body {
  margin-top: 18px;
}

/* text-wrap: pretty is what stops a centred paragraph ending on one stranded
   word. The browser reflows the last few lines to avoid it, which no amount of
   rewriting can guarantee across every width — a copy edit that fixes the
   orphan at 1512px puts one back at 1280.

   `pretty` rather than `balance`: balance evens every line and is meant for
   headings of a few words, where this is a full paragraph and only the last
   line needs the attention. Browsers without it wrap as they always did, so
   this costs nothing where it is not supported. */

.hs-what__lead,
.hs-what__body {
  text-wrap: pretty;
}

/* ---- from hiring to payroll ----
   The section is the HRMS solution wall, so its arrangement lives in that
   block above. All this adds is the four-card variant and the paragraph that
   rides with the heading in the middle cell. */

/* Two columns at every width above the stack, not three. Four cards in a
   three-column grid leave a hole beside the last one, and the hole reads as a
   missing step in a sequence that is explicitly four long.

   Narrower than the full column, too: two cards across the whole 1200px shell
   are 589px wide holding two lines of text, which letterboxes every one of
   them. Capped and centred, they land at roughly the width the six-card wall's
   cards have, so the two versions of this component look like the same
   component. */

@media (min-width: 1024px) {
  .hs-wall--four {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-left: auto;
    margin-right: auto;
    max-width: 1000px;
  }
}

/* The wall on the HRMS page carries a heading alone; here the paragraph under
   it is the sentence that makes the four cards one system, so it belongs in
   the same cell rather than above the section. */

.hs-wall__lead {
  margin: 16px auto 0;
  max-width: 660px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.6;
  color: #5A6070;
}

/* ---- what changes after Niyuk ----
   One shape for all four, because two of them are figures and two are words.
   Giving the words a different treatment would split the row into two claims
   and two adjectives; the label under the slot does the explaining either way. */

/* Two across from the smallest screen up, not one. Stacked, the four cards ran
   to most of a phone screen each and the row read as four sections rather than
   one set of outcomes. Half a 390px screen leaves 123px inside the card's own
   padding and the widest value, "Faster", sets 79px at the clamp's 28px floor,
   so nothing is squeezed by the pairing. The 600px step this replaces did the
   same thing later. */

.py-changes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin: 46px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 1024px) {
  .py-changes {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 20px;
  }
}

/* The outcomes row runs on its own ground. It used to take .hs-tinted, the flat
   #F7F9FD every other tinted section uses, which put it between an identically
   tinted comparison table above and an identically tinted industries rail
   below: three bands of one colour with no edge between them.

   Green because of what the row says. These are the gains after the switch,
   and the success colour is already in the palette carrying that meaning
   everywhere else on the site. Held very faint: the white cards and the blue
   icon discs sit on top of it and neither should pick up a cast. */

.py-outcomes {
  background:
    radial-gradient(80% 60% at 12% 0%, rgba(16, 185, 129, 0.13), rgba(16, 185, 129, 0) 62%),
    radial-gradient(70% 55% at 90% 100%, rgba(37, 99, 235, 0.07), rgba(37, 99, 235, 0) 64%),
    linear-gradient(180deg, #F1FAF5 0%, #F5FBF8 55%, #FFFFFF 100%);
}

.py-change {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 24px 22px 22px;
  border-radius: 20px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #ffffff;
  transition: transform 380ms var(--ease-smooth), box-shadow 380ms var(--ease-smooth);
}

.py-change:hover {
  transform: translate3d(0, -4px, 0);
  box-shadow: 0 26px 56px -34px rgba(16, 24, 48, 0.5);
}

.py-change__icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 12px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #2563EB;
}

/* clamp rather than a fixed size: "Faster" is six characters where "0" is one,
   and a size that suits the figure overflows the word on a narrow card. */

.py-change__value {
  margin-top: 18px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(28px, 3.2vw, 36px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -1px;
  color: #0B0D12;
}

.py-change__label {
  margin-top: 10px;
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #5A6070;
}

@media (prefers-reduced-motion: reduce) {
  .py-change {
    transition: none !important;
    transform: none !important;
  }
}

/* ==========================================================================
   ATS SOFTWARE PAGE — /ats-software.php
   The page is built from the HRMS block above: the hero, the scenic feature
   grid, the comparison table, the verdict box, the industries rail, the client
   story, the closing panel and the FAQ are all that block's. What is here is
   only what a fourth table column and a cited source need.
   ========================================================================== */

/* ---- the "why it matters" column ----
   Deliberately unmarked and quieter than the two verdicts beside it. It is not
   a third thing being compared — it is the reason the verdict counts — and a
   tick on it would read as a third contender. The table's min-width goes up
   with it, so four columns scroll sideways inside their own box rather than
   squeezing the row label to nothing. */

.hs-table--why .hs-table {
  min-width: 940px;
}

.hs-table__why {
  font-size: 13.5px;
  font-weight: 500;
  color: #5A6070;
}

/* White, like the three headers beside it. It was #0B0D12, which is
   near-black on a #1A1F35 header row: the label was there the whole time and
   could not be read. The body cells below stay grey; only the header is on a
   dark ground. */

.hs-table thead .hs-table__why {
  font-weight: 600;
  color: #ffffff;
}

/* ---- the citation under a comparison ----
   Rendered by sections/hrms/_table.php, so any table that carries a source
   gets this. A real link, not a line of grey text: a source you cannot open is
   decoration rather than evidence. */

.hs-source {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px 24px;
  margin-top: 18px;
  font-size: 12.5px;
  font-weight: 500;
  color: #8A90A0;
}

.hs-source a {
  color: #2563EB;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color 260ms var(--ease-soft);
}

.hs-source a:hover {
  color: #1D4ED8;
}

.hs-source__date {
  flex: none;
}

/* More than one report behind a table: the links group so the row still reads
   as sources on the left, date on the right. */

.hs-source__links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
}

/* The verdict runs to two paragraphs here where the HRMS page's version was
   one, so they need parting. */

.hs-verdictbox__text + .hs-verdictbox__text {
  margin-top: 14px;
}

/* ==========================================================================
   PAYROLL RUNS ILLUSTRATION — includes/payroll-runs-ui.php
   Markup and CSS rather than an inlined SVG like the showcase panels: this
   interface is drawn from scratch, so the rows reflow at any width instead of
   scaling a fixed viewBox down until the type is unreadable, and the figures
   stay real text. See the note at the top of that file.

   Everything here is sized in px against a container that is itself fluid, and
   the type steps down once below 480px — the frame gets narrow on a phone, and
   a row that wraps its payout under its month has stopped being a row.
   ========================================================================== */

/* ---- the bar ---- */

.pyr__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.pyr__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15px;
  font-weight: 600;
  color: #0B0D12;
}

.pyr__tools {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pyr__year,
.pyr__ghost,
.pyr__go {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-radius: 8px;
  font-size: 10.5px;
  font-weight: 600;
  white-space: nowrap;
}

.pyr__year {
  gap: 9px;
  color: #3A4050;
}

.pyr__chev {
  color: #A6ADBD;
}

.pyr__ghost {
  border: 1px solid rgba(37, 99, 235, 0.2);
  background-color: #ffffff;
  color: #3A4050;
}

.pyr__go {
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  color: #ffffff;
}

.pyr__filter {
  display: inline-flex;
  align-items: center;
  margin-top: 12px;
  padding: 6px 12px;
  border-radius: 8px;
  border: 1px solid rgba(16, 24, 48, 0.1);
  background-color: #ffffff;
  font-size: 10.5px;
  font-weight: 500;
  color: #5A6070;
}

/* ---- the runs ---- */

.pyr__list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.pyr__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 13px;
  border-radius: 12px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
  box-shadow: 0 6px 18px -14px rgba(16, 24, 48, 0.5);
}

.pyr__num {
  flex: none;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 12px;
  font-weight: 600;
  color: #6D4BE0;
}

.pyr__meta {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.pyr__month {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  font-size: 12px;
  font-weight: 600;
  color: #0B0D12;
}

.pyr__staff {
  font-size: 10px;
  font-weight: 500;
  color: #8A90A0;
}

/* The three states as three colours AND three words. The word is what carries
   it — at this size a 5px difference in hue is not a distinction anyone can
   rely on, and the pills are decoration inside an aria-hidden illustration. */

.pyr__pill {
  padding: 2px 7px;
  border-radius: 100px;
  font-size: 9px;
  font-weight: 600;
  white-space: nowrap;
}

.pyr__pill--finalized {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.pyr__pill--approved {
  background-color: rgba(37, 99, 235, 0.12);
  color: #1D4ED8;
}

.pyr__pill--draft {
  background-color: rgba(16, 24, 48, 0.07);
  color: #5A6070;
}

/* margin-left: auto rather than a spacer: the payout sits against the right
   edge whatever the month beside it runs to. */

.pyr__pay {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  margin-left: auto;
  text-align: right;
}

.pyr__paylabel {
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.pyr__amount {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: #0B0D12;
}

/* ---- the rows arriving ----
   Gated on the showcase panel rather than the site's .reveal observer: inside
   a pinned stage a step is shown and hidden repeatedly, and .reveal fires once
   and unobserves, so the rows would only ever arrive on the first pass. This
   replays every time the step comes round, in either direction, with no state
   to keep. --i is authored on each row. */

.pyr__row {
  opacity: 0;
  transform: translate3d(0, 12px, 0);
  transition:
    opacity 520ms var(--ease-smooth),
    transform 620ms var(--ease-smooth);
  transition-delay: calc(140ms + var(--i, 0) * 80ms);
}

.sc-panel.is-showing .pyr__row {
  opacity: 1;
  transform: none;
}

/* The one thing that moves on its own, and only while its step is the one on
   screen. A button pulsing inside a panel nobody is looking at is work the
   browser is doing for nothing. */

.pyr__go {
  transition: box-shadow 400ms var(--ease-soft);
}

.sc-panel.is-showing .pyr__go {
  animation: pyr-pulse 3.4s ease-in-out infinite;
  animation-delay: 700ms;
}

/* Pin off: no sequence to arrive with, so the rows are simply there. */

@media (max-width: 1023.98px) {
  .pyr__row {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

@keyframes pyr-pulse {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(37, 99, 235, 0);
  }

  45%      {
    box-shadow: 0 0 0 5px rgba(37, 99, 235, 0.16);
  }
}

/* The frame is half a column on a large screen and the full width on a phone,
   so the step is on the container, not the viewport. */

@container (max-width: 380px) {
  .pyr__ghost {
    display: none;
  }

  .pyr__row {
    padding: 9px 10px;
    gap: 9px;
  }

  .pyr__month {
    font-size: 11px;
  }

  .pyr__amount {
    font-size: 12px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pyr__row {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .sc-panel.is-showing .pyr__go {
    animation: none;
  }
}

/* ==========================================================================
   PAYROLL REGISTER ILLUSTRATION — includes/payroll-register-ui.php
   The pay-runs illustration's companion, and built the same way: markup and
   CSS, sized against its own container rather than the viewport, because the
   frame is half a column on a large screen and the full width on a phone.
   ========================================================================== */

/* ---- the three payroll interfaces inside a showcase panel ----
   They are HTML, not the fixed-viewBox SVGs the home page's panels use, so
   their natural heights differ: 432, 391 and 494 at this width. Stacked in one
   grid cell that difference would resize the pinned stage on every handover,
   which is the one thing a pinned stage must not do.

   min-height, not height: the tallest sets the figure, so nothing is clipped,
   and the flex is what makes the artwork fill the extra rather than leaving a
   strip of the frame's own background under it. */

.sc-panel__frame--pay {
  display: flex;
  /* 60px taller than it was: the blue box's padding takes that out of the
     sheet, and the sheet still has to hold the payslip's five factors. */
  min-height: 560px;
  background-color: #DCE4F6;
}

.sc-panel__frame--pay > * {
  flex: 1;
}

/* ---- the bar ---- */

.pyg__bar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.pyg__head {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.pyg__month {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #0B0D12;
}

.pyg__tags {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
}

.pyg__pill {
  padding: 2px 7px;
  border-radius: 100px;
  font-size: 9px;
  font-weight: 600;
  white-space: nowrap;
}

.pyg__pill--done {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.pyg__staff {
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.pyg__send {
  flex: none;
  padding: 6px 10px;
  border-radius: 8px;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  font-size: 10px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}

/* ---- the three totals ----
   auto-fit rather than three fixed columns: at the frame's narrowest the tiles
   drop to one per row instead of squeezing a lakh figure to four characters. */

.pyg__tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 8px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.pyg__tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 11px;
  border-radius: 10px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
}

.pyg__amount {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: #0B0D12;
}

/* Money in, money out, money paid. The tint is on the figure alone, so the
   three tiles stay one object rather than becoming a traffic light. */

.pyg__tile--out .pyg__amount {
  color: #C2410C;
}

.pyg__tile--net .pyg__amount {
  color: #1D4ED8;
}

.pyg__label {
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

/* ---- the register ---- */

.pyg__table {
  margin-top: 12px;
  border-radius: 10px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
  overflow: hidden;
}

.pyg__row {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr));
  align-items: center;
  gap: 8px;
  padding: 8px 11px;
}

.pyg__row + .pyg__row {
  border-top: 1px solid rgba(16, 24, 48, 0.06);
}

.pyg__row--head {
  background-color: #F4F6FB;
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #8A90A0;
}

.pyg__row--head > span:not(:first-child),
.pyg__num {
  text-align: right;
}

.pyg__who {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.pyg__name {
  font-size: 11px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pyg__code {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.pyg__num {
  font-size: 10.5px;
  font-weight: 500;
  color: #3A4050;
  white-space: nowrap;
}

.pyg__num--out {
  color: #C2410C;
}

.pyg__num--net {
  font-weight: 600;
  color: #0B0D12;
}

.pyg__more {
  padding: 8px 11px;
  border-top: 1px solid rgba(16, 24, 48, 0.06);
  background-color: #FBFBFE;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

/* Narrow frame: the deductions column goes first. Gross and net are the two
   figures the eye actually reconciles, and the difference between them is the
   deduction, so nothing is lost that cannot be worked out. */

@container (max-width: 380px) {
  .pyg__row {
    grid-template-columns: minmax(0, 1.5fr) repeat(2, minmax(0, 1fr));
  }

  .pyg__row > :nth-child(3) {
    display: none;
  }

  .pyg__send {
    display: none;
  }
}

/* ==========================================================================
   PAYSLIP ILLUSTRATION — includes/payroll-payslip-ui.php
   The third of the payroll page's drawn interfaces, built like the other two:
   markup and CSS, sized against its own container.

   Denser than they are on purpose. A payslip is a long document, and the
   length is half of what it communicates; compressing it to four lines would
   be a picture of something else.
   ========================================================================== */

/* ---- the bar ---- */

.pys__bar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.pys__who {
  display: flex;
  align-items: baseline;
  gap: 7px;
  min-width: 0;
}

.pys__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
}

.pys__code {
  font-size: 9px;
  font-weight: 500;
  color: #A6ADBD;
}

.pys__acts {
  display: flex;
  gap: 6px;
  flex: none;
}

.pys__act {
  padding: 5px 9px;
  border-radius: 7px;
  border: 1px solid rgba(16, 24, 48, 0.1);
  background-color: #ffffff;
  font-size: 9px;
  font-weight: 600;
  color: #3A4050;
  white-space: nowrap;
}

.pys__act--go {
  border-color: rgba(37, 99, 235, 0.22);
  color: #1D4ED8;
}

/* ---- the three facts ---- */

.pys__tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 7px;
  margin: 11px 0 0;
  padding: 0;
  list-style: none;
}

.pys__tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 9px;
  border-radius: 9px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
}

.pys__tlabel {
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

.pys__tval {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 12.5px;
  font-weight: 600;
  color: #0B0D12;
}

/* ---- the three lists ---- */

.pys__cap {
  display: block;
  margin: 12px 0 6px;
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.pys__box {
  border-radius: 9px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
  overflow: hidden;
}

.pys__line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 6px 10px;
  font-size: 10.5px;
  font-weight: 500;
  color: #3A4050;
}

.pys__line + .pys__line {
  border-top: 1px solid rgba(16, 24, 48, 0.05);
}

/* The total of the list above it: same row, tinted ground, heavier type. It is
   a sum, not another item, and the shading is what says so without a rule. */

.pys__line--sum {
  background-color: #F4F6FB;
  font-weight: 600;
  color: #0B0D12;
}

.pys__num {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.pys__num--out {
  color: #C2410C;
}

/* The dates behind the four lost days. Quiet, because it is evidence rather
   than a figure, but present, because "where did those four days go" is the
   question a payslip has to answer. */

.pys__note {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 10px;
  padding: 6px 10px;
  border-top: 1px solid rgba(16, 24, 48, 0.05);
  background-color: #FBFBFE;
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.pys__dates {
  color: #5A6070;
}

/* ---- net pay ----
   The one figure the employee opened the payslip for, so the one thing given a
   box of its own rather than another row in another list. */

.pys__net {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 12px;
  padding: 11px 12px;
  border-radius: 10px;
  border: 1px solid rgba(37, 99, 235, 0.22);
  background-color: rgba(37, 99, 235, 0.05);
  font-size: 12px;
  font-weight: 600;
  color: #0B0D12;
}

.pys__netnum {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: #1D4ED8;
}

/* Earnings beside deductions, so the panel is roughly as tall as the register
   illustration in the section above instead of half as tall again. The lists
   are different lengths and the shorter one just ends; stretching it to match
   would put a gap inside a box that is meant to be a complete list. */

.pys__cols {
  display: grid;
  gap: 10px;
  align-items: start;
}

@container (min-width: 420px) {
  .pys__cols {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}

/* The caption above each list already carries the top margin, so the first one
   in a column must not add the block's own. */

.pys__cols .pys__cap {
  margin-top: 12px;
}

/* Narrow frame: the two buttons go. They are the least of what this picture
   says, and they are the first thing to crowd the name out of its line. */

@container (max-width: 340px) {
  .pys__acts {
    display: none;
  }

  .pys__line {
    font-size: 10px;
  }
}

/* ==========================================================================
   MEGA MENU — the three-column arrangement
   Rail, panel, feature. The rail and the panel already existed; what is new is
   the label above the rail, the icon tile on each product, the banner across
   the top of the panel and the picture down the right.
   ========================================================================== */

/* ---- the rail ---- */

.mega__raillabel {
  margin: 2px 0 10px;
  padding-left: 16px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #A6ADBD;
}

/* The tab is a row now: tile, text, arrow. It was a block with the text
   stacked, so the padding that reserved room for the arrow moves onto the grid
   instead. */

/* position: relative for the notch on the current row. */

.mega__tab {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 16px;
}

/* The same badge the product rows beside this one wear: .mega__item-icon's
   tinted fill, no ring. The HRMS Software row is one of those rows, so a
   ringed white tile here made the same product read as two different marks
   depending on which half of the menu you were looking at. Radius is 12px
   against their 10px because this badge is 42px to their 34px and the corner
   has to scale with the box to look like the same corner. */

.mega__tab-icon {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: linear-gradient(
    140deg,
    rgba(37, 99, 235, 0.14) 0%,
    rgba(37, 99, 235, 0.07) 100%
  );
  color: #2563EB;
  transition: background 260ms var(--ease-soft), color 260ms var(--ease-soft);
}

/* The current product's badge deepens the same tint rather than gaining a
   ring, so the two states stay one mark at two strengths. */

.mega__tab.is-on .mega__tab-icon {
  background: linear-gradient(
    140deg,
    rgba(37, 99, 235, 0.22) 0%,
    rgba(37, 99, 235, 0.12) 100%
  );
}

.mega__tab-text {
  min-width: 0;
}

/* Static now that the grid holds a column for it, rather than absolutely
   placed against the old block layout. */

/* ---- panel and feature side by side ---- */

.mega__cols {
  display: grid;
  gap: 20px;
}

@media (min-width: 1024px) {
  .mega__cols {
    /* The panel gets the room; the picture is a companion to it, not a third
       equal column. */
    grid-template-columns: minmax(0, 1fr) 268px;
    gap: 24px;
  }
}

.mega__main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* ---- the line under the grid ----
   The product's full name and the pricing link. It used to sit above the grid
   as a heading row; the banner says what the panel is now, so this is a
   footnote rather than a title. margin-top: auto pins it to the bottom so the
   two panels' footers line up however many rows each grid runs to. */

.mega__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid rgba(221, 229, 237, 0.9);
}

/* The arrow used by mega_arrow(), on the panel's footer link and the feature
   panel's call to action. */

.mega-arrow {
  width: 15px;
  height: 15px;
}

/* ---- the feature panel ---- */

.mega__feature {
  position: relative;
  display: block;
  overflow: hidden;
  min-height: 240px;
  border-radius: 16px;
  background-color: #12141B;
}

/* Below the breakpoint the menu is already the full width of a phone, and a
   third column would push the grid off the screen. */

@media (max-width: 1023.98px) {
  .mega__feature {
    display: none;
  }
}

.mega__feature-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  transition: transform 700ms var(--ease-smooth);
}

.mega__feature:hover .mega__feature-img {
  transform: scale(1.04);
}

/* Two stops rather than one flat wash: the type sits in the bottom third, and
   a scrim heavy enough to carry it there would grey out the whole picture. */

.mega__feature-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(11, 13, 18, 0) 30%, rgba(11, 13, 18, 0.82) 100%);
}

.mega__feature-body {
  position: absolute;
  right: 16px;
  bottom: 16px;
  left: 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.mega__feature-kicker {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
}

.mega__feature-title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.2px;
  color: #ffffff;
}

.mega__feature-cta {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 2px;
  font-size: 12.5px;
  font-weight: 600;
  color: #ffffff;
}

.mega__feature-cta > span {
  display: grid;
  place-items: center;
  transition: transform 300ms var(--ease-smooth);
}

.mega__feature:hover .mega__feature-cta > span {
  transform: translate3d(3px, 0, 0);
}

/* ==========================================================================
   NAVBAR REGION CONTROL
   A support-contact switcher: one language, one set of pages, two phone
   numbers. See the note in includes/navbar.php.
   ========================================================================== */

.nav-region {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 12px;
  border-radius: 100px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  color: #22262F;
  transition: background-color 260ms var(--ease-soft);
}

.nav-region:hover {
  background-color: rgba(16, 24, 48, 0.05);
}

.nav-region__globe {
  display: grid;
  place-items: center;
  color: #6B7280;
}

.nav-region__globe .mega-i {
  width: 17px;
  height: 17px;
}

/* Wider than the plain nav dropdown, and taller: nine rows rather than one
   short label apiece. */

.nav-menu--country {
  width: 252px;
  max-height: min(70vh, 520px);
  overflow-y: auto;
  padding: 8px;
}

.nav-region__flag {
  font-size: 16px;
  line-height: 1;
}

.nav-country {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 500;
  color: #22262F;
  transition: background-color 240ms var(--ease-soft);
}

.nav-country:hover {
  background-color: #F4F6FB;
}

.nav-country__flag {
  flex: none;
  font-size: 17px;
  line-height: 1;
}

/* Where the reader already is. Weight and a tint rather than a tick: the row
   is a destination everywhere else in the list, and a tick would read as a
   checkbox. */

.nav-country.is-now {
  background-color: rgba(37, 99, 235, 0.07);
  font-weight: 600;
  color: #1D4ED8;
}

/* Not a country: no flag, and parted from the list by a rule. */

.nav-country--global {
  margin-top: 6px;
  padding-top: 13px;
  border-top: 1px solid rgba(221, 229, 237, 0.9);
  border-radius: 0 0 10px 10px;
  color: #5A6070;
}

/* The country list inside the mobile sheet, as a closed <details>: nine rows
   opened by default would push the two buttons under it off the bottom. */

.mob-region {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid rgba(221, 229, 237, 0.9);
}

.mob-region__now {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}

.mob-region__list {
  display: flex;
  flex-direction: column;
  padding: 4px 0 2px;
}

/* ==========================================================================
   ATS SHOWCASE — the two drawn interfaces inside a showcase panel
   The pipeline board and the score breakdown are markup and CSS, not the
   fixed-viewBox SVGs the home page's panels use, so their natural heights
   differ. Stacked in one grid cell that difference would resize the pinned
   stage on every handover, which is the one thing a pinned stage must not do.

   min-height, not height: the tallest sets the figure, so nothing is clipped;
   the flex is what makes the artwork fill the extra rather than leaving a
   strip of the frame's own background under it.
   ========================================================================== */

.sc-panel__frame--ats {
  display: flex;
  /* The same 560px the payroll frames use. Every drawn interface on the site
     is now this tall, so the pinned stage is the same size on every page it
     appears on. Getting the score breakdown's five factors into the shorter
     sheet is what the tightened metrics below are for. */
  min-height: 560px;
  background-color: #DCE4F6;
}

.sc-panel__frame--ats > * {
  flex: 1;
}

/* ==========================================================================
   HIRING PIPELINE ILLUSTRATION — includes/ats-pipeline-ui.php
   Markup and CSS, sized against its own container: the frame is half a column
   on a large screen and the full width on a phone.
   ========================================================================== */

/* The pipeline board bleeds to the sheet's right edge so its fourth column
   still runs off it. That overflow is the point of the picture: a board that
   ends neatly says there are three stages, and there are not. Only the right
   side, so the sheet keeps its inset everywhere the eye reads from. */

.atp .sc-sheet {
  padding-right: 0;
}

/* ---- the job ---- */

.atp__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding-right: 14px;
}

.atp__job {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.atp__title {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13.5px;
  font-weight: 600;
  color: #0B0D12;
}

.atp__pill {
  padding: 2px 7px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
  white-space: nowrap;
}

.atp__pill--live {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.atp__meta {
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.atp__view {
  flex: none;
  padding: 6px 10px;
  border-radius: 8px;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  font-size: 9.5px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}

/* ---- the toolbar ---- */

.atp__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 12px;
  padding: 8px 14px 8px 0;
  border-top: 1px solid rgba(16, 24, 48, 0.07);
}

.atp__all {
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.atp__count {
  display: inline-block;
  margin-left: 5px;
  padding: 1px 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.07);
  font-size: 9px;
  color: #5A6070;
}

.atp__add {
  padding: 5px 9px;
  border-radius: 7px;
  border: 1px solid rgba(37, 99, 235, 0.22);
  background-color: #ffffff;
  font-size: 9px;
  font-weight: 600;
  color: #1D4ED8;
  white-space: nowrap;
}

/* ---- the board ----
   Fixed column widths with no wrap, so the fourth runs off the right edge of
   the frame. That overflow is the point: a board that ends neatly says there
   are three stages, and there are not. */

.atp__board {
  display: flex;
  gap: 10px;
  margin-top: 10px;
  overflow: hidden;
  /* Faded at the right edge rather than relying on a sliver of the next column
     showing through. The blue box took 60px off the sheet, and at that width
     whether the fourth column peeks past the edge is a matter of a few pixels
     either way. A fade says "this continues" whatever the arithmetic does. */
  -webkit-mask-image: linear-gradient(to right, #000 86%, transparent 100%);
  mask-image: linear-gradient(to right, #000 86%, transparent 100%);
}

/* 168px, not the 154 this started at. The footer row inside a card carries the
   source, the date and the match score, and at 154 that row needed 134px in a
   118px box — the score pill hung off the right edge of every card, on this
   page and on the ATS one. The board is masked and clipped at the right
   regardless, so the extra 14px comes out of how much of the fourth column
   shows rather than out of anything the reader was reading. */

.atp__col {
  flex: none;
  width: 168px;
  padding: 9px;
  border-radius: 12px;
  background-color: rgba(16, 24, 48, 0.035);
}

.atp__colhead {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 0 2px 8px;
}

.atp__colname {
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.atp__colnum {
  padding: 1px 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.08);
  font-size: 8.5px;
  font-weight: 600;
  color: #5A6070;
}

.atp__empty {
  padding: 14px 4px;
  font-size: 9px;
  font-weight: 500;
  line-height: 1.4;
  text-align: center;
  color: #A6ADBD;
}

/* ---- a candidate ----
   Two columns and two rows: avatar and details up top with the score pinned
   right, the source line spanning underneath. */

.atp__card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 4px 8px;
  padding: 9px;
  border-radius: 10px;
  background-color: #ffffff;
  box-shadow: 0 4px 14px -10px rgba(16, 24, 48, 0.55);
}

.atp__card + .atp__card {
  margin-top: 8px;
}

.atp__avatar {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #1D4ED8;
}

.atp__who {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.atp__name {
  font-size: 10.5px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.atp__tag {
  align-self: flex-start;
  padding: 1px 6px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.1);
  font-size: 8px;
  font-weight: 600;
  color: #15803D;
  white-space: nowrap;
}

.atp__mail {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Three bands, not a ramp: a match score is a rough signal, and a per-point
   gradient would imply a precision it does not have. */

.atp__score {
  margin-left: auto;
  /* flex: none so the pill is never the thing that gets squeezed: a truncated
     percentage is a wrong number, where a truncated source label is still a
     readable one. */
  flex: none;
  padding: 2px 5px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 700;
  white-space: nowrap;
}

.atp__score--good {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.atp__score--fair {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

.atp__score--low  {
  background-color: rgba(233, 162, 59, 0.16);
  color: #B4761B;
}

.atp__foot {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 3px;
  padding-top: 7px;
  border-top: 1px solid rgba(16, 24, 48, 0.06);
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

.atp__src {
  /* min-width: 0 against the flex default of auto, which is what let a nowrap
     label refuse to shrink and push the score out of the card. With the wider
     column above nothing actually truncates at any real width; this is the
     valve, so a longer source name degrades to an ellipsis instead of spilling
     over the edge again. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 1px 5px;
  border-radius: 5px;
  background-color: rgba(16, 24, 48, 0.05);
  white-space: nowrap;
}

/* Never squeezed: it is four characters and a slash. */

.atp__date {
  flex: none;
}

/* Narrow frame: the toolbar's two ends crowd each other before anything else
   does, and neither is what the picture is about. */

@container (max-width: 380px) {
  .atp__add,
  .atp__view {
    display: none;
  }

  .atp__col {
    width: 150px;
  }

  /* Even at 150 the three-item row does not fit, and the date is the one with
     no label on it and the least to say. Source and score stay whole rather
     than both being truncated to keep a number nobody is reading. */

  .atp__date {
    display: none;
  }
}

/* ==========================================================================
   MATCH SCORE ILLUSTRATION — includes/ats-score-ui.php
   The pipeline board's companion, built the same way and sized against its own
   container. Denser than the board on purpose: the point of the picture is
   that a score has parts, and five parts is what that takes.
   ========================================================================== */

.ats__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.ats__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13.5px;
  font-weight: 600;
  color: #0B0D12;
}

.ats__for {
  font-size: 10px;
  font-weight: 600;
  color: #8A90A0;
}

/* ---- the total ---- */

/* The overall row is sized by the ring, so the ring is what decides how much
   air the row has. Tightened together: at 54px with 2px of border it left a
   visible band of empty white above and below the three lines of copy beside
   it. */

.ats__overall {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 9px;
  padding: 8px 10px;
  border-radius: 11px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
}

.ats__ocopy {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  flex: 1;
}

.ats__olabel {
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.ats__overdict {
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.35;
  color: #0B0D12;
}

/* The one figure the panel exists to explain, so the one thing given a shape
   of its own rather than another row in the list. */

/* Flex column, not grid. `display: grid` with two children made two implicit
   rows that split the ring's height between them and centred each item inside
   its own row, which put 11px of air between the score and its unit however
   the margins were set. Stacking them in flex leaves them touching. */

.ats__ring {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: none;
  /* 50px, not 54: tight enough that the row is no longer mostly white space,
     wide enough that "out of 100" is not touching the curve. At 46px the label
     ran to within 4px of the border on both sides. */
  width: 50px;
  height: 50px;
  border-radius: 100px;
  border: 1.5px solid rgba(22, 163, 74, 0.28);
  background-color: rgba(22, 163, 74, 0.08);
  text-align: center;
}

.ats__rnum {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 600;
  line-height: 1;
  color: #15803D;
}

/* line-height:1 is what closes the gap under the number. At the inherited 1.6
   this 7px label carried about 2px of leading above the glyphs, which read as
   a space between the score and its unit rather than as one block. */

.ats__rof {
  margin-top: 1px;
  font-size: 7px;
  font-weight: 500;
  line-height: 1;
  color: #15803D;
  opacity: 0.75;
}

/* ---- one factor ---- */

.ats__rows {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 7px;
}

.ats__row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 10px;
  border-radius: 10px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
}

.ats__rhead {
  display: flex;
  align-items: center;
  gap: 8px;
}

.ats__rname {
  font-size: 11px;
  font-weight: 600;
  color: #0B0D12;
}

/* How much this factor counts for. Quiet, because it qualifies the score
   beside it rather than competing with it. */

.ats__weight {
  padding: 1px 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.05);
  font-size: 8px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.ats__score {
  margin-left: auto;
  padding: 2px 7px;
  border-radius: 100px;
  font-size: 9px;
  font-weight: 700;
  white-space: nowrap;
}

.ats__score--good {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.ats__score--fair {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

.ats__score--low  {
  background-color: rgba(233, 162, 59, 0.16);
  color: #B4761B;
}

/* ---- the bars ----
   One rule for the track, one for the fill, with the width carried as --w on
   the element so the value lives with the data rather than in a class per
   percentage. */

.ats__bar {
  display: block;
  overflow: hidden;
  height: 5px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.08);
}

.ats__fill {
  display: block;
  width: var(--w, 0%);
  height: 100%;
  border-radius: 100px;
}

.ats__fill--good {
  background-color: #16A34A;
}

.ats__fill--fair {
  background-color: #3B82F6;
}

.ats__fill--low  {
  background-color: #E9A23B;
}

.ats__note {
  font-size: 8.5px;
  font-weight: 500;
  line-height: 1.4;
  color: #8A90A0;
}

/* The evidence behind a factor, where there is any: the tenure that produced a
   stability score, the gap that cost one. */

.ats__chip {
  align-self: flex-start;
  padding: 2px 7px;
  border-radius: 7px;
  font-size: 8.5px;
  font-weight: 500;
}

.ats__chiplabel {
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.ats__chip--good {
  background-color: rgba(22, 163, 74, 0.08);
  color: #15803D;
}

.ats__chip--warn {
  background-color: rgba(220, 38, 38, 0.07);
  color: #B91C1C;
}

.ats__foot {
  margin-top: 6px;
  font-size: 8px;
  font-weight: 500;
  line-height: 1.45;
  color: #A6ADBD;
}

/* Narrow frame: the candidate's name goes before anything that carries a
   number does. */

@container (max-width: 360px) {
  .ats__for {
    display: none;
  }

  .ats__ring {
    width: 50px;
    height: 50px;
  }

  .ats__rnum {
    font-size: 16px;
  }
}

/* ==========================================================================
   BUTTON HEIGHTS
   .btn-primary and .btn-dark carry a 38px circular icon badge with 10px of
   padding above and below it, which works out to 58px. .btn-solid has no
   badge, so its own 15px padding gave 50px, and the two sat side by side in
   the heroes at different heights.

   min-height on all three rather than more padding on one: the badge still
   sets the figure, the padding stays what it is, and any future pairing of
   these buttons lines up without anyone having to remember why.
   ========================================================================== */

.btn-primary,
.btn-dark,
.btn-solid,
.btn-white {
  min-height: 58px;
}

/* ==========================================================================
   CONTACT PAGE — /contact-us/
   Badge and title over one form card on the sky, three tiles under it, a
   centred FAQ and the dark closing panel. The FAQ and the panel are the
   pricing pages' own sections, so only what is here is new.
   ========================================================================== */

.ct-head {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* Clears the fixed navbar: first section on the page, nothing above it.
     The bottom padding is not decoration: with it at 0 the form's own top
     margin collapsed straight through .content and out of the section, so the
     card overflowed its parent by 40px and `overflow: hidden` above clipped
     it. Real padding gives the margin something to sit against. */
  padding-top: 130px;
  padding-bottom: 46px;
}

@media (min-width: 768px) {
  .ct-head {
    padding-top: 160px;
  }
}

/* The site's own sky, so the page opens on the ground the rest of it does. */

.ct-head__sky {
  position: absolute;
  inset: 0 0 auto;
  z-index: -1;
  height: 560px;
  pointer-events: none;
}

.ct-head__sky img {
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
}

.ct-head__fade {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0) 45%, #ffffff 100%);
}

.ct-head__intro {
  margin: 0 auto;
  max-width: 620px;
  text-align: center;
}

.ct-head__title {
  margin-top: 20px;
  font-size: clamp(40px, 6vw, 64px);
  letter-spacing: -1.8px;
}

.ct-head__lead {
  margin-top: 14px;
}

/* ---- the form ----
   Narrow and centred. Nothing sits beside it: it is the only thing anyone
   came to this page to do. */

.ct-form {
  display: grid;
  gap: 14px;
  margin: 40px auto 0;
  max-width: 620px;
  padding: 24px 22px 26px;
  border-radius: 20px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #ffffff;
  box-shadow: 0 30px 70px -34px rgba(16, 24, 48, 0.4);
}

@media (min-width: 560px) {
  .ct-form {
    /* Two fields to a row; everything else spans both. */
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
    padding: 30px 30px 32px;
  }

  .ct-field--wide,
  .ct-submit,
  .ct-said {
    grid-column: 1 / -1;
  }
}

.ct-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  min-width: 0;
  border: 0;
  padding: 0;
}

.ct-label {
  padding: 0;
  font-size: 13.5px;
  font-weight: 600;
  color: #22262F;
}

/* Only ever beside a field whose input also carries `required`: both come off
   the same flag in $CT_FIELDS. */

.ct-req {
  margin-left: 3px;
  color: #DC2626;
}

.ct-input {
  width: 100%;
  padding: 12px 14px;
  border-radius: 11px;
  border: 1px solid rgba(16, 24, 48, 0.13);
  background-color: #FBFBFE;
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 500;
  color: #0B0D12;
  transition: border-color 240ms var(--ease-soft), box-shadow 240ms var(--ease-soft);
}

.ct-input::-moz-placeholder {
  color: #A6ADBD;
}

.ct-input::placeholder {
  color: #A6ADBD;
}

.ct-input:focus {
  outline: none;
  border-color: #2563EB;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.14);
}

/* Vertical only: dragged wider it would break the grid it sits in, and there
   is nothing to gain from it. */

.ct-input--area {
  resize: vertical;
  min-height: 112px;
  line-height: 1.55;
}

/* ---- what it is about ---- */

.ct-purpose__row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin-top: 2px;
}

.ct-radio {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  color: #3A4050;
}

/* The real input, kept in the accessibility tree and in tab order rather than
   display:none, with the drawn dot beside it doing the showing. */

.ct-radio input,
.ct-consent input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.ct-radio__dot {
  display: grid;
  place-items: center;
  flex: none;
  width: 17px;
  height: 17px;
  border-radius: 100px;
  border: 1.5px solid rgba(16, 24, 48, 0.24);
  transition: border-color 200ms var(--ease-soft);
}

.ct-radio__dot::after {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 100px;
  background-color: #2563EB;
  transform: scale(0);
  transition: transform 220ms var(--ease-smooth);
}

.ct-radio input:checked + .ct-radio__dot {
  border-color: #2563EB;
}

.ct-radio input:checked + .ct-radio__dot::after {
  transform: scale(1);
}

/* Focus has to be visible on the drawn control, because the real one is
   clipped out of sight. */

.ct-radio input:focus-visible + .ct-radio__dot,
.ct-consent input:focus-visible + .ct-consent__box {
  outline: 2px solid #2563EB;
  outline-offset: 3px;
}

/* ---- consent ---- */

.ct-consent {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 2px;
  cursor: pointer;
  font-size: 13.5px;
  font-weight: 500;
  color: #3A4050;
}

.ct-consent__box {
  display: grid;
  place-items: center;
  flex: none;
  width: 18px;
  height: 18px;
  border-radius: 5px;
  border: 1.5px solid rgba(16, 24, 48, 0.24);
  transition: background-color 200ms var(--ease-soft), border-color 200ms var(--ease-soft);
}

.ct-consent__box::after {
  content: '';
  width: 9px;
  height: 5px;
  border-left: 2px solid #ffffff;
  border-bottom: 2px solid #ffffff;
  transform: rotate(-45deg) scale(0);
  transition: transform 220ms var(--ease-smooth);
}

.ct-consent input:checked + .ct-consent__box {
  border-color: #2563EB;
  background-color: #2563EB;
}

.ct-consent input:checked + .ct-consent__box::after {
  transform: rotate(-45deg) scale(1);
}

/* The one .btn-primary on the site with no arrow badge in it. That badge was
   doing structural work: .btn-primary is padded 30px on the left and 10px on
   the right because the disc fills the right side, so removing it left the
   label sitting off-centre. The padding is evened up here rather than in
   .btn-primary itself, which every other button on the site still relies on.
   The 58px min-height the badge used to set is inherited and still applies, so
   this button stays the same height as the ones beside it elsewhere. */

.ct-submit {
  justify-self: stretch;
  margin-top: 6px;
  padding-right: 30px;
}

/* Written by js/contact-form.js once it hands the message over, and empty
   until then, which is why it has no height of its own. */

.ct-said {
  margin: 0;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.5;
  color: #15803D;
}

/* ---- the three tiles ----
   The form's own shadow reaches down past its edge, so 26px of padding left
   the tiles looking pushed up against it while the section's default 100px
   below opened a hole before the FAQ. Hence the 80 above.

   Below it was 0, on the grounds that the FAQ's own top padding was already
   doing the separating. That holds for the FAQ's text and not for its ground:
   .pr-faq-sec paints a gradient whose blue is strongest at 50% 0%, its own top
   edge, so with nothing under the tiles the tint began on the cards' bottom
   border however much padding sat inside the section below. 48px of white is
   what puts the row back on the page it belongs to. */

.ct-tiles-sec {
  padding-top: 80px;
  padding-bottom: 48px;
}

/* The FAQ's own 100px top padding, trimmed where it follows the tiles, so the
   48 above and this together come to about the 86 the pair was tuned at rather
   than stacking into a hole. Scoped to this adjacency so the pricing pages keep
   the spacing they were tuned with. */

.ct-tiles-sec + .pr-faq-sec {
  padding-top: 44px;
}

.ct-tiles {
  display: grid;
  gap: 16px;
  margin: 0 auto;
  padding: 0;
  max-width: 940px;
  list-style: none;
}

@media (min-width: 760px) {
  .ct-tiles {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* The whole tile is the link, not a pill inside it. justify-content: center
   so the contents sit in the middle of the card: the three cards are the same
   height because the grid stretches them, and their copy runs to two lines,
   one line and three, so anything else leaves one of them looking hollow. */

.ct-tile > a {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  height: 100%;
  padding: 28px 20px;
  border-radius: 18px;
  border: 1px solid rgba(16, 24, 48, 0.09);
  background-color: #ffffff;
  text-align: center;
  transition: transform 380ms var(--ease-smooth), box-shadow 380ms var(--ease-smooth);
}

.ct-tile > a:hover {
  transform: translate3d(0, -4px, 0);
  box-shadow: 0 26px 56px -34px rgba(16, 24, 48, 0.5);
}

.ct-tile__icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: 10px;
  border-radius: 12px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #2563EB;
}

.ct-i {
  width: 19px;
  height: 19px;
}

.ct-tile__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 600;
  color: #0B0D12;
}

.ct-tile__text {
  font-size: 13px;
  font-weight: 500;
  line-height: 1.45;
  color: #6B7280;
}

.ct-tile__line {
  font-size: 13px;
  font-weight: 500;
  color: #5A6070;
}

/* The address and the phone as a bordered pill, as the reference has them:
   the one part of the tile that looks like something to press. */

.ct-tile__pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 14px;
  padding: 9px 16px;
  border-radius: 100px;
  border: 1px solid rgba(16, 24, 48, 0.12);
  font-size: 13.5px;
  font-weight: 600;
  color: #0B0D12;
  transition: border-color 240ms var(--ease-soft), color 240ms var(--ease-soft);
}

.ct-tile > a:hover .ct-tile__pill {
  border-color: rgba(37, 99, 235, 0.4);
  color: #1D4ED8;
}

.ct-tile__pill--go > span {
  display: grid;
  place-items: center;
  transition: transform 300ms var(--ease-smooth);
}

.ct-tile > a:hover .ct-tile__pill--go > span {
  transform: translate3d(3px, 0, 0);
}

/* ---- the tiles on the dark ground ----

   Asked for on 2026-09-02: a black band with a gradient, and bigger titles.

   The ground is .ind-ai's, the one the industries AI band, the case study's
   dark block and every audience page's .aud-who already stand on, rather than
   a fourth near-black invented here. The cards follow .ind-gcard--dark for the
   same reason: a lifted panel at 4% white with a 10% edge, not the white card
   they were, which on this ground would read as three lamps.

   AFTER the light rules above, all of them, because these override colours set
   there and both sides are a single class. A media query would not have helped:
   source order is what decides between two rules of equal weight. */

.ct-tiles-sec {
  background-color: #0B0D12;
  background-image:
    radial-gradient(70% 55% at 50% 0%, rgba(37, 99, 235, 0.22), rgba(37, 99, 235, 0) 68%);
  padding-bottom: 88px;
}

/* The band ends on its own colour now, so the FAQ below it starts on its own
   full padding rather than the 44px that was tuned for two light sections
   running together. */

.ct-tiles-sec + .pr-faq-sec {
  padding-top: 100px;
}

.ct-tiles-sec .ct-tile > a {
  border-color: rgba(255, 255, 255, 0.10);
  background-color: rgba(255, 255, 255, 0.04);
}

.ct-tiles-sec .ct-tile > a:hover {
  border-color: rgba(255, 255, 255, 0.22);
  box-shadow: none;
}

.ct-tiles-sec .ct-tile__icon {
  background-color: rgba(255, 255, 255, 0.07);
  color: #5D95F0;
}

/* Bigger, and on the display face the section titles use. 16px was a label; at
   20 it is the heading of the card it sits on. */

.ct-tiles-sec .ct-tile__title {
  font-size: 20px;
  line-height: 1.25;
  color: #FFFFFF;
}

.ct-tiles-sec .ct-tile__text,
.ct-tiles-sec .ct-tile__line {
  color: #A7B0C0;
}

.ct-tiles-sec .ct-tile__pill {
  border-color: rgba(255, 255, 255, 0.22);
  color: #FFFFFF;
}

.ct-tiles-sec .ct-tile > a:hover .ct-tile__pill {
  border-color: rgba(93, 149, 240, 0.55);
  color: #8FB6F6;
}


/* A fixed gap, not margin-top: auto. Pinning the pills to the foot lined them
   up with each other but left a gap above them that grew with every line the
   card did not have, which is what made two of the three look empty. */

.ct-tile__pill {
  margin-top: 18px;
}

@media (prefers-reduced-motion: reduce) {
  .ct-tile > a {
    transition: none !important;
    transform: none !important;
  }
}

/* ==========================================================================
   SUCCESSION PLANNING PAGE — /succession-planning/
   Everything this page shows is a shape from the blocks above, fed its own
   copy. What is here is the four things that had nowhere to come from: a
   centred hero, the breadcrumb over it, a numbered reason list, and a plain
   three-card row where the other pages run a marquee.
   ========================================================================== */

/* ---- centred hero ----
   The other inner heroes are copy left, artwork right. This one has no
   artwork, so the grid comes off and the column centres. */

.hs-hero--center .hs-hero__copy--center {
  margin: 0 auto;
  /* 960px, not 860: the title's first line runs to 863px at the top of the
     type scale, so the narrower measure broke it over three lines and left
     "Smart" stranded on its own. */
  max-width: 960px;
  text-align: center;
}

.hs-hero--center .hs-hero__lead {
  margin-left: auto;
  margin-right: auto;
  max-width: 720px;
}

.hs-hero--center .hs-hero__cta {
  justify-content: center;
}

/* …and the grid it sits in collapses to one track, or the centred copy is
   centred inside the left half of a two-column row with a hole beside it.
   sections/audience/hero.php sets .hs-hero--center when a page has no hero
   picture, which is the only way that class is reached today.

   AFTER the .hs-hero__grid media block above: a media query adds no
   specificity, and this rule carries one more class than the one it overrides,
   so it wins either way — but it belongs next to what it modifies. */

@media (min-width: 1024px) {
  .hs-hero--center .hs-hero__grid {
    grid-template-columns: minmax(0, 1fr);
  }
}


/* ---- breadcrumb ----
   Above the badge, quiet enough not to compete with it. A real ol, so a
   screen reader announces the trail as a list of two rather than as a run of
   text with a chevron in it. */

.sp-crumbs {
  margin-bottom: 26px;
  text-align: center;
}

.sp-crumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 500;
  color: #5A6070;
}

/* The separator is generated rather than typed into the markup: it is
   decoration, and a screen reader reading "greater than" between two links
   is noise. */

.sp-crumbs li + li::before {
  content: '';
  display: inline-block;
  width: 5px;
  height: 5px;
  margin-right: 8px;
  border-top: 1.4px solid #A6ABBA;
  border-right: 1.4px solid #A6ABBA;
  transform: rotate(45deg);
  vertical-align: middle;
}

.sp-crumbs a {
  color: #5A6070;
  transition: color 220ms var(--ease-soft);
}

.sp-crumbs a:hover {
  color: #2563EB;
}

.sp-crumbs [aria-current='page'] {
  color: #0B0D12;
}

/* ---- numbered reasons ----
   The HRMS list is ticked labels of six words. These three are claims with a
   condition attached, so each carries a title and a line under it, and the
   tick becomes a number: three reasons read as an argument in order where six
   read as a set. */

.hs-reasons--num {
  display: grid;
  gap: 14px;
  margin-top: 28px;
}

.hs-reason--num {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 18px 20px;
  border-radius: 18px;
  background-color: #F4F6FA;
}

.hs-reason__num {
  display: grid;
  place-items: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 100px;
  background-color: #FFFFFF;
  box-shadow: 0 1px 2px rgba(16, 24, 48, 0.08);
  font-size: 13px;
  font-weight: 600;
  color: #2563EB;
}

.hs-reason__body {
  display: block;
}

.hs-reason__title {
  display: block;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  color: #0B0D12;
}

.hs-reason__text {
  display: block;
  margin-top: 5px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.55;
  color: #5A6070;
}

/* ---- three cards on the scenic ground ----
   The feature rows elsewhere run five or six cards through a marquee. A rail
   exists to make a row longer than the screen readable, and three cards fit,
   so these sit in a plain grid. The cards themselves are .hs-feat__card,
   unchanged, except that they size to their content here rather than to the
   fixed height a marquee needs to keep its rhythm. */

.hs-cards3__head {
  margin: 0 auto 40px;
  max-width: 720px;
  text-align: center;
}

.hs-cards3__lead {
  margin-top: 14px;
}

.hs-cards3 {
  display: grid;
  gap: 20px;
}

.hs-cards3 .hs-feat__card {
  height: auto;
  min-height: 200px;
}

@media (min-width: 768px) {
  .hs-cards3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ==========================================================================
   SUCCESSION PANELS — the three drawn interfaces on the HRMS page
   Markup and CSS, sized against their own container. One shared frame height,
   for the reason given on the payroll and ATS frames: stacked in a single grid
   cell, three natural heights would resize the pinned stage on every handover.
   ========================================================================== */

/* The blue ground, the same one the hero artwork on this page sits on: the
   interface sits ON something rather than filling the frame edge to edge. */

.sc-panel__frame--succ {
  display: flex;
  /* 560px, the same as the payroll and ATS frames. Every drawn interface on
     the site is this tall, so the pinned stage is the same size wherever it
     appears. */
  min-height: 560px;
  background-color: #DCE4F6;
}

.sc-panel__frame--succ > * {
  flex: 1;
}

/* ---- a shorter frame, for the visitor sequence ----
   470px, not the 560 every other drawn interface here uses. Measured: the
   tallest of that page's four panels needs 453px of content, so a 560 frame
   was leaving between 107 and 208 pixels of empty sheet under each one. A
   panel that is mostly blank reads as a screenshot that failed to load.

   It is one value shared by all four, which is the property that actually
   matters: the pinned stage must not resize on the handover between panels.
   Matching the OTHER pages was never the requirement — those panels are taller
   because their artwork is. */

/* ---- the DeskTime sequence's frame ----
   Its own height, for the same reason --vis has one: five panels of five
   natural heights would resize the pinned stage on every handover, and the
   right shared value is the one measured against THESE five rather than
   inherited from a page whose artwork is a different size. */

.sc-panel__frame--dt {
  display: flex;
  /* 400, measured: the tallest of the five needs 337px of sheet plus the blue
     box's 60px of padding. Picked against these panels rather than guessed —
     at 450 the shortest was carrying 130px of empty sheet, which reads as a
     screenshot that failed to load. */
  min-height: 400px;
  background-color: #DCE4F6;
}

.sc-panel__frame--dt > * {
  flex: 1;
  min-height: 0;
}

.sc-panel__frame--vis {
  display: flex;
  /* 480, measured rather than picked: the tallest of the four panels needs
     418px of sheet plus the blue box's 60px of padding. At 470 the list panel
     grew the frame to 478 and the stage twitched on its handover. */
  min-height: 480px;
  background-color: #DCE4F6;
}

.sc-panel__frame--vis > * {
  flex: 1;
  min-height: 0;
}

/* The five facility screens. One shared height, for the reason given on the
   payroll and visitor frames: stacked in a single grid cell, the pinned stage
   must not resize when one panel hands over to the next. 540, measured rather
   than picked: the tallest of the five is the board, which needs 476px of
   sheet plus the blue box's 60px of padding. */

.sc-panel__frame--fb {
  display: flex;
  min-height: 540px;
  background-color: #DCE4F6;
}

.sc-panel__frame--fb > * {
  flex: 1;
  min-height: 0;
}

/* ---- the blue box, shared by every drawn interface on the site ----
   The root is the blue box; the sheet inside it is the interface. Splitting
   them this way is what lets every rule in these blocks keep assuming a
   near-white ground, which is what they were all written against.

   One selector for the succession, payroll and ATS artworks: they are the same
   object on three pages, and three copies of this would be three places for
   the padding to drift. */

.scp, .scr, .scg,
.pyr, .pyg, .pys,
.atp, .ats,
.cer, .cel, .cew, .cep, .egv,
.hdk, .hdl, .hdt,
.scn, .snp,
.vms, .vpz, .vrp, .vin, .vls,
.dtm, .dtd, .dta, .dtp, .dts, .dtt,
.fbk, .fbd, .fbn, .fbs, .fba, .fbt,
.skm, .skg, .skc,
.skl, .skr, .skn, .skd, .skp, .skv,
.tsw, .tsl, .tsp, .tsr, .tsu,
.fld, .fdd, .fdl, .fdv, .fdr,
.trv, .tvt, .tvn, .tvq, .tvd,
.cll, .cld, .clg, .clh,
.cro, .crl, .crc, .cra, .crd, .crs,
.pjd, .pjn, .pjt, .pjb, .pjm, .pjs,
.agd, .agl, .agc, .agp, .agt, .agb,
.sod, .soq, .sor, .som, .sop, .soo,
.pgo, .pck, .prv {
  display: flex;
  padding: 30px;
  background-color: #DCE4F6;
  container-type: inline-size;
}

/* The three performance screens take 20px rather than 30. They are the densest
   of the drawn interfaces: a goals board with nine rows, a two-column dialog
   and a six-column review table. The extra 20px of sheet is what keeps their
   columns readable at the same frame width everything else uses. */

.pgo, .pck, .prv {
  padding: 20px;
}

.sc-sheet {
  flex: 1;
  min-width: 0;
  padding: 14px;
  border-radius: 14px;
  background-color: #FBFBFE;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.6) inset,
    0 18px 40px -26px rgba(16, 24, 48, 0.55);
}

/* The tab bar the roles and grid panels share. */

.scr__tabs {
  display: flex;
  gap: 16px;
  padding-bottom: 9px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.scr__tab {
  position: relative;
  padding-bottom: 8px;
  font-size: 10px;
  font-weight: 600;
  color: #A6ADBD;
  white-space: nowrap;
}

.scr__tab.is-on {
  color: #2563EB;
}

.scr__tab.is-on::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -10px;
  height: 2px;
  border-radius: 100px;
  background-color: #2563EB;
}

/* ==========================================================================
   01 — the plan
   ========================================================================== */

.scp__title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #0B0D12;
}

.scp__pill {
  padding: 2px 7px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
}

.scp__pill--live {
  background-color: rgba(37, 99, 235, 0.12);
  color: #1D4ED8;
}

.scp__meta {
  display: block;
  margin-top: 4px;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.scp__overall {
  margin-top: 12px;
  padding: 11px 12px;
  border-radius: 11px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
}

.scp__orow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.scp__olabel {
  font-size: 10.5px;
  font-weight: 500;
  color: #5A6070;
}

.scp__onum {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #0B0D12;
}

.scp__bar {
  display: block;
  overflow: hidden;
  height: 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.08);
}

/* Set from --w, so the figure above and the length of the bar are the same
   number written once. */

.scp__fill {
  display: block;
  width: var(--w, 0%);
  height: 100%;
  border-radius: 100px;
  background-image: linear-gradient(90deg, #7CB0FC 0%, #2563EB 100%);
}

.scp__tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 8px;
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
}

.scp__tile {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 10px;
  border-radius: 10px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
}

/* A tinted square standing in for the reference's icon: at 22px an outlined
   mark is mush, and the three tiles are told apart by their labels anyway. */

.scp__ticon {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 7px;
}

.scp__ticon--aim  {
  background-color: rgba(37, 99, 235, 0.14);
}

.scp__ticon--done {
  background-color: rgba(22, 163, 74, 0.14);
}

.scp__ticon--up   {
  background-color: rgba(139, 92, 246, 0.16);
}

.scp__tcopy {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.scp__tlabel {
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.scp__tval {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #0B0D12;
}

.scp__cap {
  display: block;
  margin: 13px 0 7px;
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.scp__goals {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* A left border in the accent, as the reference has it: the goal rows are the
   one list on the panel that is a list of things you act on. */

.scp__goal {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  padding: 10px 11px;
  border-radius: 10px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  border-left: 3px solid #8B5CF6;
  background-color: #ffffff;
}

.scp__gname {
  font-size: 11px;
  font-weight: 600;
  color: #0B0D12;
}

.scp__tag {
  padding: 1px 6px;
  border-radius: 100px;
  background-color: rgba(139, 92, 246, 0.12);
  font-size: 8px;
  font-weight: 600;
  color: #6D28D9;
  white-space: nowrap;
}

.scp__tag--p1 {
  background-color: rgba(233, 162, 59, 0.16);
  color: #B4761B;
}

.scp__state {
  margin-left: auto;
  font-size: 9px;
  font-weight: 600;
  white-space: nowrap;
}

.scp__state--done {
  color: #15803D;
}

.scp__state--wip  {
  color: #1D4ED8;
}

/* The percentage as a ring, because it is a completion and a completion reads
   as a circle filling. */

.scp__ring {
  display: grid;
  place-items: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 100px;
  border: 2px solid rgba(16, 24, 48, 0.12);
  font-size: 8px;
  font-weight: 700;
  color: #5A6070;
}

.scp__ring--done {
  border-color: rgba(22, 163, 74, 0.5);
  color: #15803D;
}

/* ==========================================================================
   02 — critical positions
   ========================================================================== */

.scr__bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}

.scr__sel {
  padding: 6px 11px;
  border-radius: 8px;
  border: 1px solid rgba(16, 24, 48, 0.1);
  background-color: #ffffff;
  font-size: 9.5px;
  font-weight: 500;
  color: #5A6070;
  white-space: nowrap;
}

.scr__add {
  margin-left: auto;
  padding: 6px 11px;
  border-radius: 8px;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  font-size: 9.5px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}

.scr__table {
  margin-top: 11px;
  border-radius: 11px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #ffffff;
  overflow: hidden;
}

.scr__row {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 0.7fr) minmax(0, 1.2fr) minmax(0, 0.7fr);
  align-items: center;
  gap: 8px;
  padding: 9px 11px;
  font-size: 10.5px;
  color: #3A4050;
}

.scr__row--head {
  background-color: #F4F6FB;
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #8A90A0;
}

.scr__title {
  font-weight: 600;
  color: #0B0D12;
}

.scr__risk {
  padding: 2px 7px;
  border-radius: 100px;
  background-color: rgba(233, 162, 59, 0.16);
  font-size: 8.5px;
  font-weight: 600;
  color: #B4761B;
}

.scr__holder,
.scr__who {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.scr__av {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  font-size: 8px;
  font-weight: 700;
  color: #1D4ED8;
}

.scr__count {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 600;
  color: #0B0D12;
}

.scr__tick {
  color: #16A34A;
}

/* The open row's nominees, on a tinted ground with the accent down the left so
   they read as belonging to the row above rather than as more rows. */

.scr__nom {
  padding: 10px 11px 11px;
  border-top: 1px solid rgba(16, 24, 48, 0.06);
  border-left: 3px solid #8B5CF6;
  background-color: #FBFBFE;
}

.scr__nomcap {
  display: block;
  margin-bottom: 7px;
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.scr__nrow {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) auto auto auto;
  align-items: center;
  gap: 9px;
  padding: 8px 9px;
  border-radius: 9px;
  background-color: #ffffff;
  box-shadow: 0 3px 10px -8px rgba(16, 24, 48, 0.5);
}

.scr__nrow + .scr__nrow {
  margin-top: 7px;
}

.scr__wcopy {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.scr__nname {
  font-size: 10.5px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.scr__nrole {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.scr__ready {
  padding: 2px 7px;
  border-radius: 100px;
  background-color: rgba(233, 162, 59, 0.14);
  font-size: 8px;
  font-weight: 600;
  color: #B4761B;
  white-space: nowrap;
}

.scr__score {
  font-size: 11px;
  font-weight: 700;
  color: #0B0D12;
  white-space: nowrap;
}

.scr__of {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.scr__idp {
  font-size: 9px;
  font-weight: 600;
  color: #2563EB;
  white-space: nowrap;
}

/* ==========================================================================
   03 — the nine-box grid
   ========================================================================== */

.scg__wrap {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 8px;
  margin-top: 12px;
}

/* Rotated, because a vertical axis label written horizontally is not an axis
   label. writing-mode rather than a transform: it keeps its own box, so the
   grid beside it does not have to leave room for a rotated one. */

.scg__yaxis {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  align-self: center;
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.scg__xaxis {
  grid-column: 2;
  text-align: center;
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.scg__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 7px;
}

.scg__box {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 10px;
  min-height: 82px;
  padding: 8px 9px;
  border-radius: 9px;
  border: 1px solid rgba(16, 24, 48, 0.05);
}

/* Four tones, not nine: the grid's meaning is the axes, and nine colours would
   turn a scale into a mosaic. */

.scg__box--good  {
  background-color: rgba(22, 163, 74, 0.09);
}

.scg__box--cool  {
  background-color: rgba(37, 99, 235, 0.08);
}

.scg__box--warm  {
  background-color: rgba(233, 162, 59, 0.13);
}

.scg__box--weak  {
  background-color: rgba(220, 38, 38, 0.07);
}

.scg__box--plain {
  background-color: rgba(16, 24, 48, 0.04);
}

.scg__bhead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
}

.scg__blabel {
  font-size: 9px;
  font-weight: 600;
  line-height: 1.3;
  color: #22262F;
}

.scg__bnum {
  flex: none;
  font-size: 9px;
  font-weight: 700;
  color: #8A90A0;
}

.scg__people {
  display: flex;
  gap: 4px;
}

.scg__av {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.85);
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.08);
  font-size: 7.5px;
  font-weight: 700;
  color: #3A4050;
}

/* Narrow frame: the filter row's two selects go first. They are chrome, and
   the grid is the picture. */

@container (max-width: 380px) {
  .scr__sel {
    display: none;
  }

  .scg__box {
    min-height: 70px;
  }
}

/* ==========================================================================
   SUCCESSION PLANNING PAGE — /succession-planning/
   Every section on it is another page's, fed this page's data: the hero is the
   payroll page's, the "why" row is the ATS page's feature rail, the comparison
   table, industries, client story and FAQ are the HRMS page's. The one rule
   below is the only thing this page needs that no other page does.
   ========================================================================== */

/* This hero's headline carries the full subject for search, which is longer
   than the other heroes' and has no natural break point. balance splits it
   into even lines instead of leaving one word stranded on the last. Scoped to
   this page: the other heroes break where their copy tells them to. */

.hs-hero .sp-title {
  text-wrap: balance;
}

/* ==========================================================================
   MEGA MENU — the industries panel
   Three labelled columns instead of the products panel's rail. It shares the
   wrapper, so it inherits the full-width positioning and the hover bridge;
   everything below is what the columns need.
   ========================================================================== */

.mega__inner--cols {
  gap: 0;
  padding: 24px 20px 26px;
  background-color: #FAFBFD;
}

@media (min-width: 1024px) {
  .mega__inner--cols {
    /* The first column holds eleven items in two stacks, so it takes roughly
       half the panel; the other two hold three and four in one stack each.
       Split evenly, the industries would wrap two words to a line while the
       short columns ended in a lot of nothing. */
    grid-template-columns: 2.1fr 1fr 1.15fr;
    padding: 26px 40px 30px;
  }
}

/* Hairlines between the columns, as the reference has them. On the column
   rather than a separate element, and skipped on the first, so adding a fourth
   group needs no change here. */

.mega__col + .mega__col {
  padding-left: 26px;
}

/* The rule between columns, and the room either side of it.

   The 26px above sits entirely to the LEFT of the border, so a column's rows
   ran right up to the next column's border-left: on hover .mega__item paints
   itself white with a shadow, and that card landed flush against the line.

   Split 13/13 here rather than adding to one side, so the gutter is still 26
   and the panel's width is unchanged — the difference is only that the rows
   now stop short of the rule instead of touching it. padding-right on every
   column, including the last, where it costs nothing: the panel's own padding
   is outside it. */

@media (min-width: 1024px) {
  .mega__col {
    padding-right: 13px;
  }

  .mega__col + .mega__col {
    border-left: 1px solid rgba(221, 229, 237, 0.9);
    padding-left: 13px;
  }
}

.mega__col .mega__label {
  padding-left: 12px;
}

.mega__collist {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* A group long enough to run off the panel lays out in --cols stacks instead of
   one. Below 1024 the panel is a single column of its own, so the split only
   applies where there is width to split. */
@media (min-width: 1024px) {
  .mega__collist--split {
    display: grid;
    grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr));
    column-gap: 6px;
  }
}

/* Two lines, so the mark aligns to the top of the label rather than to the
   middle of both lines. The products grid is one line and centres its mark;
   this is the same row with a second line under it. */

.mega__item--two {
  align-items: flex-start;
  gap: 12px;
  padding: 9px 12px;
}

.mega__item--two .mega__item-label {
  display: block;
  font-size: 14.5px;
  font-weight: 600;
  color: #0B0D12;
}

/* ==========================================================================
   NAV DROPDOWN HOVER
   The same treatment the two mega panels use: a faintly tinted panel with the
   hovered row lifting to white. Applied here so Pricing, Resource and the
   country list behave like Products and Industries rather than being the two
   menus that highlight differently.
   ========================================================================== */

.nav-menu {
  background-color: #FAFBFD;
}

.nav-menu__item {
  transition:
    background-color 220ms var(--ease-soft),
    box-shadow 260ms var(--ease-soft),
    color 220ms var(--ease-soft);
}

.nav-menu__item:hover,
.nav-country:hover {
  background-color: #ffffff;
  box-shadow: 0 10px 26px -18px rgba(16, 24, 48, 0.45);
  color: #0B0D12;
}

.nav-country {
  transition:
    background-color 220ms var(--ease-soft),
    box-shadow 260ms var(--ease-soft);
}

/* The current country keeps its tint rather than going white: it is where the
   reader already is, not somewhere to go, and a white card would make it look
   like the hovered row. */

.nav-country.is-now,
.nav-country.is-now:hover {
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: none;
  color: #1D4ED8;
}

/* ==========================================================================
   CANDIDATE ENGAGEMENT (/candidate-engagement-1/)
   Four components this page introduces, plus the artwork in
   includes/engage-ai-ui.php. Everything else on that page is existing
   furniture: the hero, the four-card wall, the FAQ accordion, the scenic band.
   ========================================================================== */

/* ---- 1. the problem cards ------------------------------------------------
   A plain grid, not the marquee the feature rails use: these four are the
   argument the page is about to answer, and an argument that slides away while
   you are reading it is a worse argument. Tinted rather than white, and the
   mark is a muted red, so the one section describing what goes wrong does not
   look like the benefit sections either side of it. */

.en-probs {
  display: grid;
  gap: 14px;
  margin-top: 44px;
}

@media (min-width: 640px) {
  .en-probs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
  }
}

@media (min-width: 1024px) {
  .en-probs {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 18px;
  }
}

.en-prob {
  padding: 24px 22px 26px;
  border-radius: 20px;
  background-color: #F6F7FA;
  transition: transform 380ms var(--ease-smooth), background-color 380ms var(--ease-soft);
}

.en-prob:hover {
  transform: translate3d(0, -4px, 0);
  background-color: #F1F3F8;
}

.en-prob__icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: 16px;
  border-radius: 12px;
  background-color: rgba(220, 68, 68, 0.09);
  color: #C0392B;
}

.en-prob__icon .hs-i {
  width: 20px;
  height: 20px;
}

.en-prob__name {
  margin-bottom: 8px;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
  color: #22262F;
}

.en-prob__text {
  font-size: 14px;
  line-height: 1.6;
  color: #5A6070;
}

/* ---- 2. the journey line -------------------------------------------------
   A rule behind six markers and a second rule drawn over it. --jrn-draw is
   what js/journey-line.js scrubs, 0 to 1; the fill reads it as a scale on its
   own long axis, so nothing is being animated that costs a layout.

   THE DEFAULT IS THE FINISHED STATE
   The fill is full and every stage is lit unless the script adds .is-scrubbed.
   With no GSAP, under reduced motion, or if the file never loads, this section
   is complete rather than a row of grey markers behind an undrawn rule. */

.en-jrn {
  position: relative;
  display: grid;
  gap: 28px 18px;
  margin-top: 48px;
  padding: 0;
  list-style: none;
}

.en-jrn__rail {
  position: absolute;
  /* Vertical below the breakpoint: the rule runs down the left of the column
     rather than across a row that no longer exists. 19px is half the marker. */
  top: 20px;
  bottom: 20px;
  left: 19px;
  width: 2px;
  border-radius: 2px;
  background-color: rgba(16, 24, 48, 0.09);
}

.en-jrn__fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(180deg, #2563EB 0%, #60A5FA 100%);
  transform: scaleY(var(--jrn-draw, 1));
  transform-origin: top center;
}

.en-jrn__step {
  position: relative;
  padding-left: 56px;
}

.en-jrn__mark {
  position: absolute;
  top: 0;
  left: 0;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background-color: #EDF1F4;
  color: #8A90A0;
  transition: background-color 320ms var(--ease-soft), color 320ms var(--ease-soft);
}

.en-jrn__num {
  display: block;
  margin-bottom: 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.11em;
  color: #A6ADBD;
}

.en-jrn__name {
  margin-bottom: 6px;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
  color: #22262F;
}

.en-jrn__text {
  font-size: 14px;
  line-height: 1.6;
  color: #5A6070;
}

/* Six across once there is room for a stage name and a sentence without
   setting three words to a line. The rail turns with the layout: one rule,
   rotated by swapping which axis it spans and which way the fill scales. */

@media (min-width: 900px) {
  .en-jrn {
    grid-template-columns: repeat(var(--jrn-count, 6), minmax(0, 1fr));
    gap: 0 16px;
  }

  .en-jrn__rail {
    top: 19px;
    bottom: auto;
    /* Ends at the centre of the first and last markers rather than running to
       the edges of the row, so the line joins the stages instead of pointing
       off the section. Half a column in from each side. */
    left: calc(50% / var(--jrn-count, 6));
    right: calc(50% / var(--jrn-count, 6));
    width: auto;
    height: 2px;
  }

  .en-jrn__fill {
    background: linear-gradient(90deg, #2563EB 0%, #60A5FA 100%);
    transform: scaleX(var(--jrn-draw, 1));
    transform-origin: left center;
  }

  .en-jrn__step {
    padding-left: 0;
    padding-right: 12px;
    text-align: left;
  }

  .en-jrn__mark {
    position: static;
    margin-bottom: 18px;
  }

  .en-jrn__num {
    margin-bottom: 3px;
  }
}

/* Lit, in step with the line arriving. Only while the script is driving: at
   rest every marker is already in its lit state, which is what the fallback
   above depends on. */

.en-jrn.is-scrubbed .en-jrn__fill {
  transform-origin: left center;
}

.en-jrn.is-scrubbed .en-jrn__mark {
  background-color: #EDF1F4;
  color: #8A90A0;
}

.en-jrn.is-scrubbed .en-jrn__step.is-lit .en-jrn__mark,
.en-jrn:not(.is-scrubbed) .en-jrn__mark {
  background-color: rgba(37, 99, 235, 0.12);
  color: #2563EB;
}

@media (max-width: 899px) {
  .en-jrn.is-scrubbed .en-jrn__fill {
    transform-origin: top center;
  }
}

/* ---- 3. the bento --------------------------------------------------------
   Six columns; --span on each tile is how many it takes, set from the content
   file, and the eight are ordered so every row adds to six. The size is the
   emphasis: that is what makes this a bento rather than a grid of identical
   boxes. Tones are the wall's three, so a tile here and a card three sections
   up read as the same object at two sizes. */

.en-bento {
  display: grid;
  gap: 14px;
  margin-top: 44px;
}

@media (min-width: 640px) {
  .en-bento {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
  }
}

@media (min-width: 1024px) {
  .en-bento {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 18px;
  }

  .en-tile {
    grid-column: span var(--span, 2);
  }
}

/* ---- four across ----
   A row of four equal tiles rather than the six-column span system above. Four
   does not divide six, so this variant drops out of that system entirely and
   every tile takes a quarter: the set reads as one row seen at once instead of
   as two pairs. --span is ignored here, and the sections using it set none.

   Below 1024px it inherits the base grid: two across, then one. A quarter of
   the shell is about 286px, which is as narrow as one of these tiles should
   ever get on a desktop. */

@media (min-width: 1024px) {
  .en-bento--four {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .en-bento--four .en-tile {
    grid-column: auto;
  }
}

.en-tile {
  display: flex;
  flex-direction: column;
  padding: 24px 22px 26px;
  border-radius: 20px;
  transition: transform 380ms var(--ease-smooth), box-shadow 380ms var(--ease-smooth);
}

.en-tile:hover {
  transform: translate3d(0, -4px, 0);
}

.en-tile--light {
  background-color: #EDF1F4;
  color: #0B0D12;
}

.en-tile--dark  {
  background-color: #0B0D12;
  color: #ffffff;
}

.en-tile--brand {
  background-color: #2563EB;
  color: #ffffff;
}

.en-tile__icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin-bottom: 16px;
  border-radius: 12px;
}

.en-tile__icon .hs-i {
  width: 19px;
  height: 19px;
}

.en-tile--light .en-tile__icon {
  background-color: #3B82F6;
  color: #ffffff;
}

.en-tile--dark  .en-tile__icon {
  background-color: #ffffff;
  color: #0B0D12;
}

.en-tile--brand .en-tile__icon {
  background-color: #0B0D12;
  color: #ffffff;
}

.en-tile__name {
  margin-bottom: 8px;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
}

/* Every tone names its own colour rather than inheriting the tile's.
   The base stylesheet sets `h1, h2, h3, h4, h5 { color: #1d1d1d }`, and a type
   selector on the element itself beats a colour inherited from .en-tile--dark,
   so the title on a dark or brand tile came out near-black on near-black. The
   text under it was already doing this per tone; the heading was the one part
   that was not. */

.en-tile--light .en-tile__name {
  color: #0B0D12;
}

.en-tile--dark  .en-tile__name {
  color: #ffffff;
}

.en-tile--brand .en-tile__name {
  color: #ffffff;
}

.en-tile__text {
  font-size: 14px;
  line-height: 1.6;
}

.en-tile--light .en-tile__text {
  color: #5A6070;
}

.en-tile--dark  .en-tile__text {
  color: rgba(255, 255, 255, 0.64);
}

.en-tile--brand .en-tile__text {
  color: rgba(255, 255, 255, 0.88);
}

/* ---- 4. the AI split -----------------------------------------------------
   Copy left, the dashboard right, in the hero's own frame so it is the same
   object on the same ground as the artwork at the top of the page. */

.en-ai {
  display: grid;
  gap: 36px;
  align-items: center;
}

@media (min-width: 1024px) {
  .en-ai {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    gap: 56px;
  }
}

.en-ai__title {
  margin: 16px 0 0;
  text-align: left;
}

.en-ai__lead  {
  margin: 16px 0 0;
  text-align: left;
}

.en-ai__list {
  display: grid;
  gap: 12px;
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
}

.en-ai__list li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 15px;
  line-height: 1.5;
  color: #22262F;
}

.en-ai__tick {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 1px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.en-ai__tick .hs-i {
  width: 13px;
  height: 13px;
}

/* ---- 5. without and with -------------------------------------------------
   Two panels, not the comparison table: the two lists are not paired, and
   forcing them into rows would mean inventing a fifth failure to sit opposite
   the AI line. Marks are shapes rather than only colours. */

.en-vs {
  display: grid;
  gap: 18px;
  margin-top: 44px;
}

@media (min-width: 860px) {
  .en-vs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 22px;
  }
}

.en-vs__panel {
  padding: 28px 26px 30px;
  border-radius: 22px;
}

.en-vs__panel--before {
  background-color: #F6F7FA;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.05);
}

.en-vs__panel--after {
  background-color: #0B0D12;
  color: #ffffff;
}

.en-vs__label {
  margin-bottom: 20px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}

.en-vs__panel--before .en-vs__label {
  color: #8A90A0;
}

.en-vs__panel--after  .en-vs__label {
  color: rgba(255, 255, 255, 0.55);
}

.en-vs__list {
  display: grid;
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.en-vs__list li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 15px;
  line-height: 1.5;
}

.en-vs__panel--before .en-vs__list li {
  color: #5A6070;
}

.en-vs__panel--after  .en-vs__list li {
  color: rgba(255, 255, 255, 0.88);
}

.en-vs__mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 1px;
  border-radius: 100px;
}

/* A dash, not a cross: what is on the left is missing rather than wrong. */

.en-vs__mark--no {
  background-color: rgba(16, 24, 48, 0.06);
}

.en-vs__mark--no::before {
  content: '';
  width: 9px;
  height: 2px;
  border-radius: 2px;
  background-color: #A6ADBD;
}

.en-vs__mark--yes {
  background-color: rgba(96, 165, 250, 0.22);
  color: #93C5FD;
}

.en-vs__mark--yes .hs-i {
  width: 13px;
  height: 13px;
}

/* ==========================================================================
   ENGAGEMENT AI PANEL  (includes/engage-ai-ui.php)
   The artwork beside the AI copy. Markup and CSS rather than an SVG, so the
   figures stay real text and the tiles reflow inside whatever box they get.
   ========================================================================== */

.eai {
  display: flex;
  padding: 26px;
  background-color: #E4EAF9;
  container-type: inline-size;
}

.eai .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: 100%;
  padding: 16px;
  border-radius: 16px;
  background-color: #ffffff;
  box-shadow: 0 18px 40px -26px rgba(16, 24, 48, 0.5);
}

.eai__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.eai__title {
  font-size: 13px;
  font-weight: 600;
  color: #22262F;
}

.eai__chip {
  padding: 2px 9px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.eai__top {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: 10px;
}

.eai__score {
  display: flex;
  flex-direction: column;
  padding: 14px;
  border-radius: 12px;
  background: linear-gradient(150deg, #2563EB 0%, #1D4ED8 100%);
  color: #ffffff;
}

.eai__scorenum {
  font-size: 30px;
  font-weight: 700;
  line-height: 1;
}

.eai__scorelab {
  margin-top: 6px;
  font-size: 10px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.78);
}

.eai__scoredelta {
  margin-top: 10px;
  align-self: flex-start;
  padding: 2px 7px;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.18);
  font-size: 9.5px;
  font-weight: 700;
}

.eai__stats {
  display: grid;
  gap: 10px;
}

.eai__stat {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 10px 12px;
  border-radius: 12px;
  background-color: #F4F6FB;
}

.eai__statnum {
  font-size: 18px;
  font-weight: 700;
  line-height: 1.1;
  color: #22262F;
}

.eai__statnum--warn {
  color: #B4761B;
}

.eai__statlab {
  margin-top: 2px;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.eai__caplabel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.eai__caplabel em {
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: #8A90A0;
}

.eai__act {
  display: grid;
  gap: 9px;
}

.eai__bars {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
  align-items: end;
  height: 66px;
}

/* A grid, not a flex column. As flex the bar's percentage height resolved
   against the whole 66px including the day label under it, so anything over
   about 70% hit the ceiling and Wednesday's 100 and Thursday's 71 drew the
   same height — a chart with the shape flattened out of it. The 1fr row is the
   track, the auto row is the label, and the percentage now means what it says. */

.eai__bar {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 5px;
  height: 100%;
}

.eai__barfill {
  align-self: end;
  height: var(--h, 50%);
  border-radius: 4px 4px 2px 2px;
  background: linear-gradient(180deg, rgba(37, 99, 235, 0.9) 0%, rgba(96, 165, 250, 0.65) 100%);
}

.eai__barday {
  text-align: center;
  font-size: 8.5px;
  font-weight: 600;
  color: #A6ADBD;
}

.eai__list {
  display: grid;
  gap: 7px;
}

.eai__row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: 10px;
  background-color: #F8F9FC;
}

.eai__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-size: 8.5px;
  font-weight: 700;
}

.eai__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}

.eai__name {
  font-size: 11px;
  font-weight: 600;
  color: #22262F;
}

.eai__since {
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.eai__dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 100px;
}

.eai__dot--cold {
  background-color: #E9A23B;
}

.eai__dot--warm {
  background-color: #60A5FA;
}

.eai__next {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 12px;
  border-radius: 12px;
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.14);
}

.eai__nexticon {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 9px;
  background-color: #2563EB;
  color: #ffffff;
}

.eai__nexticon .hs-i {
  width: 14px;
  height: 14px;
}

.eai__nexttext {
  min-width: 0;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.35;
  color: #22262F;
}

.eai__nextlab {
  display: block;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #2563EB;
}

/* Narrow frame: the score and the two readings stop fitting side by side
   before anything else does. */

@container (max-width: 380px) {
  .eai {
    padding: 18px;
  }

  .eai__top {
    grid-template-columns: minmax(0, 1fr);
  }

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

/* ==========================================================================
   ENGAGEMENT PANELS — the four screens in /candidate-engagement/'s sequence
   Recognition and rewards: the wall, the earning rules, the leaderboard and
   the store. Markup and CSS, sized against their own container, on the shared
   blue box registered above. They sit in .sc-panel__frame--succ, so all four
   are the same 560px every drawn interface on the site is.

   The sheet inside each is scrolled from the top and clipped: these are taller
   interfaces than the frame, and cropping one is honest where squeezing eight
   rows into six would be drawing a product that does not exist.
   ========================================================================== */

/* min-height: 0 against the flex default of auto, on the root and the sheet
   alike. It does not set the height — the frame's own min-height does that —
   it stops a panel that outgrows the frame from silently pushing it taller,
   which would resize the pinned stage on the handover to that one panel. The
   panels are sized to fit; this is the guard for the next time one is edited. */

.cer, .cel, .cew, .cep {
  min-height: 0;
}

.cer .sc-sheet,
.cel .sc-sheet,
.cew .sc-sheet,
.cep .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
  min-height: 0;
}

/* ---- 1. the company wall ---- */

.cew__tabs {
  display: flex;
  gap: 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.cew__tab {
  position: relative;
  font-size: 10.5px;
  font-weight: 600;
  color: #8A90A0;
}

.cew__tab--on {
  color: #2563EB;
}

.cew__tab--on::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -9px;
  height: 2px;
  border-radius: 2px;
  background-color: #2563EB;
}

.cew__composer {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px;
  border-radius: 10px;
  background-color: #F6F7FB;
}

.cew__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-size: 10px;
  font-weight: 700;
}

.cew__avatar--sm {
  width: 22px;
  height: 22px;
  font-size: 9px;
}

.cew__ph {
  font-size: 11px;
  font-weight: 500;
  color: #A6ADBD;
}

.cew__actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.cew__act {
  font-size: 9.5px;
  font-weight: 600;
  color: #8A90A0;
}

.cew__post {
  margin-left: auto;
  padding: 4px 12px;
  border-radius: 100px;
  background-color: #2563EB;
  color: #ffffff;
  font-size: 9.5px;
  font-weight: 700;
}

.cew__post-card {
  display: grid;
  gap: 7px;
  padding: 11px;
  border-radius: 12px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.cew__kind {
  justify-self: start;
  padding: 2px 8px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.cew__kind--poll {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

.cew__kind--rec  {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.cew__by {
  display: flex;
  align-items: center;
  gap: 8px;
}

.cew__meta {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.cew__name {
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.cew__role {
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.cew__role b {
  font-weight: 700;
  color: #22262F;
}

.cew__q {
  font-size: 11px;
  font-weight: 600;
  color: #22262F;
}

.cew__opt {
  padding: 7px 10px;
  border-radius: 8px;
  background-color: #F6F7FB;
  font-size: 10px;
  font-weight: 500;
  color: #5A6070;
}

.cew__praise {
  align-self: start;
  padding: 5px 10px;
  border-radius: 8px;
  background-color: rgba(22, 163, 74, 0.09);
  color: #15803D;
  font-size: 10px;
  font-weight: 600;
}

/* ---- 2. how points are earned ---- */

.cep__head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.cep__mark {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 9px;
  background: linear-gradient(150deg, #F6C453 0%, #E9A23B 100%);
}

.cep__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.cep__title {
  font-size: 12.5px;
  font-weight: 700;
  color: #22262F;
}

.cep__sub {
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.cep__tabs {
  display: flex;
  gap: 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.cep__tab {
  position: relative;
  font-size: 10.5px;
  font-weight: 600;
  color: #8A90A0;
}

.cep__tab--on {
  color: #2563EB;
}

.cep__tab--on::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -9px;
  height: 2px;
  border-radius: 2px;
  background-color: #2563EB;
}

.cep__groups {
  display: grid;
  gap: 6px;
}

.cep__glabel {
  margin-top: 4px;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.cep__glabel:first-child {
  margin-top: 0;
}

/* 6px of vertical padding, not 7. Six rows at 7 put this panel's content at
   563px against the 560 every drawn interface on the site shares, and three
   pixels is enough to resize the pinned stage on the handover. The row is the
   thing there are six of, so it is the thing that gives. */

.cep__row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 9px;
  border-radius: 9px;
  background-color: #F8F9FC;
}

.cep__icon {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background-color: rgba(233, 162, 59, 0.18);
}

.cep__copy {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}

.cep__name {
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.cep__note {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.cep__pts {
  flex: none;
  font-size: 10.5px;
  font-weight: 700;
  color: #15803D;
}

.cep__pts em {
  font-style: normal;
  font-size: 8.5px;
  font-weight: 600;
}

.cep__cta {
  margin-top: auto;
  padding: 9px;
  border-radius: 9px;
  background-color: #5B4BE3;
  color: #ffffff;
  text-align: center;
  font-size: 10.5px;
  font-weight: 700;
}

/* ---- 3. the leaderboard ---- */

.cel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.cel__title {
  font-size: 12.5px;
  font-weight: 700;
  color: #22262F;
}

.cel__view {
  padding: 3px 10px;
  border-radius: 7px;
  background-color: #F1F4F9;
  font-size: 9.5px;
  font-weight: 600;
  color: #5A6070;
}

.cel__filters {
  display: flex;
  gap: 7px;
}

.cel__sel {
  padding: 4px 10px;
  border-radius: 7px;
  background-color: #F6F7FB;
  font-size: 9.5px;
  font-weight: 600;
  color: #8A90A0;
}

.cel__sel--on {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

/* One grid template for the header and every row, declared once so a column
   cannot drift out of line with its own label. */

.cel__cols,
.cel__row {
  display: grid;
  grid-template-columns: 26px minmax(0, 1.5fr) minmax(0, 1.2fr) 42px minmax(0, 0.9fr);
  align-items: center;
  gap: 8px;
}

.cel__cols {
  padding: 0 8px 7px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.cel__num {
  text-align: right;
}

.cel__rows {
  display: grid;
  gap: 4px;
}

.cel__row {
  padding: 7px 8px;
  border-radius: 9px;
}

.cel__row--you {
  background-color: rgba(233, 162, 59, 0.1);
}

.cel__rank {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 100px;
  background-color: #F1F4F9;
  color: #8A90A0;
  font-size: 9.5px;
  font-weight: 700;
}

.cel__rank--m1 {
  background-color: #E9A23B;
  color: #ffffff;
}

.cel__rank--m2 {
  background-color: #B9C0CC;
  color: #ffffff;
}

.cel__rank--m3 {
  background-color: #C88B4E;
  color: #ffffff;
}

.cel__who {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.cel__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-size: 8.5px;
  font-weight: 700;
}

.cel__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.cel__you {
  margin-left: 5px;
  padding: 1px 6px;
  border-radius: 100px;
  background-color: rgba(233, 162, 59, 0.22);
  color: #B4761B;
  font-style: normal;
  font-size: 8px;
  font-weight: 700;
}

.cel__dept {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.cel__pts {
  text-align: right;
  font-size: 10.5px;
  font-weight: 700;
  color: #22262F;
}

.cel__badge {
  min-width: 0;
  text-align: right;
}

.cel__badge i {
  display: inline-block;
  overflow: hidden;
  max-width: 100%;
  padding: 2px 7px;
  border-radius: 100px;
  background-color: #F1F4F9;
  color: #5A6070;
  font-style: normal;
  font-size: 8.5px;
  font-weight: 600;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* ---- 4. the reward store ---- */

.cer__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.cer__title {
  display: flex;
  flex-direction: column;
  font-size: 12.5px;
  font-weight: 700;
  color: #22262F;
}

.cer__sub {
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.cer__pts {
  flex: none;
  padding: 4px 10px;
  border-radius: 100px;
  background-color: rgba(233, 162, 59, 0.16);
  color: #B4761B;
  font-size: 11px;
  font-weight: 700;
}

.cer__pts em,
.cer__price em,
.cer__balnum em {
  font-style: normal;
  font-size: 8.5px;
  font-weight: 600;
}

.cer__filters {
  display: flex;
  align-items: center;
  gap: 7px;
  padding-bottom: 9px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.cer__chip {
  padding: 4px 11px;
  border-radius: 100px;
  background-color: #F6F7FB;
  font-size: 9.5px;
  font-weight: 600;
  color: #8A90A0;
}

.cer__chip--on {
  background-color: #5B4BE3;
  color: #ffffff;
}

.cer__count {
  margin-left: auto;
  font-size: 9px;
  font-weight: 500;
  color: #A6ADBD;
}

.cer__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.cer__card {
  display: flex;
  flex-direction: column;
  padding: 8px;
  border-radius: 11px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

/* A coloured plate, not a logo. See the note at the top of
   includes/engage-rewards-ui.php on why the real brands are not drawn. */

/* 16:10, not 8:5, and a tighter margin: at six cards the grid runs two rows
   inside the same 560px frame every panel on this site shares, so the plate
   gives back the height the second row needs. */

.cer__plate {
  position: relative;
  display: block;
  aspect-ratio: 16 / 10;
  margin-bottom: 7px;
  border-radius: 7px;
  overflow: hidden;
}

/* One plate per brand, in that brand's own colour and nothing else of theirs.
   See the note at the top of includes/engage-rewards-ui.php on why the logos
   are not drawn. */

.cer__plate--amz {
  background: linear-gradient(140deg, #232F3E 0%, #37475A 100%);
}

.cer__plate--flk {
  background: linear-gradient(140deg, #2874F0 0%, #1B5BC4 100%);
}

.cer__plate--dom {
  background: linear-gradient(140deg, #006491 0%, #C8102E 100%);
}

.cer__plate--pvr {
  background: linear-gradient(140deg, #14110E 0%, #C8A24A 100%);
}

.cer__plate--myn {
  background: linear-gradient(140deg, #E9418C 0%, #F26A2E 100%);
}

.cer__plate--swg {
  background: linear-gradient(140deg, #FC8019 0%, #E0670C 100%);
}

.cer__platebar {
  position: absolute;
  left: 14%;
  right: 14%;
  bottom: 24%;
  height: 12%;
  border-radius: 3px;
  background-color: rgba(255, 255, 255, 0.55);
}

.cer__platedot {
  position: absolute;
  left: 14%;
  top: 22%;
  width: 22%;
  aspect-ratio: 1;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.35);
}

.cer__cat {
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #8A90A0;
}

.cer__name {
  margin: 2px 0 5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.cer__price {
  font-size: 10.5px;
  font-weight: 700;
  color: #B4761B;
}

.cer__bal {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: auto;
  padding: 10px 12px;
  border-radius: 11px;
  background: linear-gradient(140deg, #F6C453 0%, #E9A23B 100%);
  color: #4A3208;
}

.cer__ballab {
  font-size: 9.5px;
  font-weight: 600;
}

.cer__balnum {
  font-size: 15px;
  font-weight: 700;
}

/* Narrow frame: three reward cards across stop working before anything else
   does, and the leaderboard's two quietest columns are the ones to lose. */

@container (max-width: 380px) {
  .cer, .cel, .cew, .cep {
    padding: 18px;
  }

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

  .cel__cols,
  .cel__row {
    grid-template-columns: 24px minmax(0, 1fr) 40px;
  }

  .cel__dept,
  .cel__badge {
    display: none;
  }
}

/* ==========================================================================
   EMPLOYEE HELPDESK  (/employee-helpdesk/)
   The request queue in includes/helpdesk-ui.php, and the three service-level
   points beside it. The queue sits in .hs-hero__frame in both places it
   appears, so it needs no frame modifier of its own.
   ========================================================================== */

.hdk .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.hdk__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.hdk__title {
  font-size: 13px;
  font-weight: 600;
  color: #22262F;
}

.hdk__chip {
  padding: 2px 9px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.hdk__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 9px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.hdk__stat {
  display: flex;
  flex-direction: column;
  padding: 10px 12px;
  border-radius: 11px;
  background-color: #F4F6FB;
}

.hdk__statnum {
  font-size: 19px;
  font-weight: 700;
  line-height: 1.1;
  color: #22262F;
}

.hdk__statnum--warn {
  color: #B4761B;
}

.hdk__statnum--good {
  color: #15803D;
}

.hdk__statlab {
  margin-top: 2px;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.hdk__caplabel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.hdk__caplabel em {
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: #8A90A0;
}

.hdk__rows {
  display: grid;
  gap: 7px;
}

/* One template, so a row's owner and its clock always land under the same
   place they do on the row above. */

.hdk__row {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr) 24px 52px;
  align-items: center;
  gap: 9px;
  padding: 9px 10px;
  border-radius: 11px;
  background-color: #F8F9FC;
}

.hdk__id {
  font-size: 9.5px;
  font-weight: 700;
  color: #8A90A0;
}

.hdk__copy {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.hdk__subj {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11px;
  font-weight: 600;
  color: #22262F;
}

.hdk__cat {
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.hdk__owner {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-size: 8.5px;
  font-weight: 700;
}

/* The clock. Red is the only red in the panel, so an overdue ticket is the
   first thing found when the eye lands on the queue. */

.hdk__sla {
  padding: 3px 0;
  border-radius: 7px;
  text-align: center;
  font-size: 9px;
  font-weight: 700;
  white-space: nowrap;
}

.hdk__sla--ok   {
  background-color: rgba(16, 24, 48, 0.05);
  color: #5A6070;
}

.hdk__sla--late {
  background-color: rgba(220, 68, 68, 0.12);
  color: #C0392B;
}

.hdk__kb {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: auto;
  padding: 11px 12px;
  border-radius: 12px;
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.14);
}

.hdk__kbicon {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 9px;
  background-color: #2563EB;
  color: #ffffff;
}

.hdk__kbicon .hs-i {
  width: 14px;
  height: 14px;
}

.hdk__kbtext {
  min-width: 0;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.35;
  color: #22262F;
}

.hdk__kblab {
  display: block;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #2563EB;
}

/* Narrow frame: the queue's four columns are three before anything else
   breaks, and the ticket number is the one nobody reads. */

@container (max-width: 380px) {
  .hdk {
    padding: 18px;
  }

  .hdk__row {
    grid-template-columns: minmax(0, 1fr) 24px 52px;
  }

  .hdk__id {
    display: none;
  }
}

/* ==========================================================================
   HELPDESK SEQUENCE PANELS — the two screens in /employee-helpdesk/
   The queue, and one ticket opened out of it. Markup and CSS, sized against
   their own container, on the shared blue box registered above. Both sit in
   .sc-panel__frame--succ, so both are the 560px every drawn interface here is.
   ========================================================================== */

.hdl .sc-sheet,
.hdt .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
  /* Same guard as the engagement panels: stops a panel that outgrows the frame
     from pushing it taller, which would resize the pinned stage. */
  min-height: 0;
}

.hdl, .hdt {
  min-height: 0;
}

/* ---- 1. the queue ---- */

.hdl__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.hdl__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.hdl__title {
  font-size: 12.5px;
  font-weight: 700;
  color: #22262F;
}

.hdl__sub {
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.hdl__new {
  flex: none;
  padding: 5px 11px;
  border-radius: 8px;
  background-color: #5B4BE3;
  color: #ffffff;
  font-size: 9.5px;
  font-weight: 700;
}

.hdl__tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.hdl__tile {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 10px;
  border-radius: 10px;
  background-color: #F4F6FB;
}

.hdl__tdot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 100px;
}

.hdl__tdot--open {
  background-color: #DC4444;
}

.hdl__tdot--wip  {
  background-color: #3B82F6;
}

.hdl__tdot--done {
  background-color: #16A34A;
}

.hdl__tdot--shut {
  background-color: #A6ADBD;
}

.hdl__tcopy {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.hdl__tnum {
  font-size: 15px;
  font-weight: 700;
  line-height: 1.1;
  color: #22262F;
}

.hdl__tlab {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

.hdl__bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.hdl__tab {
  position: relative;
  font-size: 10px;
  font-weight: 600;
  color: #8A90A0;
}

.hdl__tab em {
  margin-left: 4px;
  padding: 1px 5px;
  border-radius: 100px;
  background-color: #F1F4F9;
  font-style: normal;
  font-size: 8px;
  font-weight: 700;
}

.hdl__tab--on {
  color: #5B4BE3;
}

.hdl__tab--on::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -9px;
  height: 2px;
  border-radius: 2px;
  background-color: #5B4BE3;
}

.hdl__filter {
  margin-left: auto;
  padding: 3px 9px;
  border-radius: 7px;
  background-color: #F6F7FB;
  font-size: 9.5px;
  font-weight: 600;
  color: #5A6070;
}

.hdl__filter em {
  margin-left: 4px;
  font-style: normal;
  font-weight: 700;
  color: #8A90A0;
}

/* One template for the header and every row, so a cell can never drift out of
   line with its own label. */

.hdl__cols,
.hdl__row {
  display: grid;
  grid-template-columns: 62px minmax(0, 1.6fr) 46px minmax(0, 0.9fr) 68px;
  align-items: center;
  gap: 8px;
}

.hdl__cols {
  padding: 0 8px;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.hdl__rows {
  display: grid;
  gap: 4px;
}

.hdl__row {
  padding: 8px;
  border-radius: 9px;
  background-color: #F8F9FC;
}

.hdl__id {
  font-size: 9px;
  font-weight: 700;
  color: #8A90A0;
}

.hdl__subj,
.hdl__asg {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hdl__subj {
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.hdl__asg {
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.hdl__pri {
  padding: 2px 0;
  border-radius: 100px;
  text-align: center;
  font-size: 8.5px;
  font-weight: 700;
}

.hdl__pri--high   {
  background-color: rgba(233, 162, 59, 0.18);
  color: #B4761B;
}

.hdl__pri--medium {
  background-color: rgba(59, 130, 246, 0.14);
  color: #1D4ED8;
}

/* Red is the only red on the panel, so the one overdue row is the first thing
   found when the eye lands on the queue. */

.hdl__due {
  text-align: right;
  font-size: 9px;
  font-weight: 700;
  white-space: nowrap;
}

.hdl__due--ok   {
  color: #8A90A0;
}

.hdl__due--due  {
  color: #B4761B;
}

.hdl__due--late {
  color: #C0392B;
}

.hdl__foot {
  margin-top: auto;
  font-size: 9px;
  font-weight: 500;
  color: #A6ADBD;
}

/* ---- 2. one ticket ---- */

.hdt__head {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.hdt__back {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 7px;
  background-color: #F1F4F9;
}

.hdt__titles {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.hdt__title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  font-weight: 700;
  color: #22262F;
}

.hdt__tags {
  display: flex;
  align-items: center;
  gap: 6px;
}

.hdt__id {
  padding: 2px 7px;
  border-radius: 6px;
  background-color: #F1F4F9;
  font-size: 8.5px;
  font-weight: 700;
  color: #8A90A0;
}

.hdt__tag {
  padding: 2px 8px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 700;
}

.hdt__tag--open {
  box-shadow: inset 0 0 0 1px rgba(220, 68, 68, 0.35);
  color: #C0392B;
}

.hdt__tag--high {
  box-shadow: inset 0 0 0 1px rgba(233, 162, 59, 0.45);
  color: #B4761B;
}

.hdt__cols {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: 10px;
  min-height: 0;
}

.hdt__main {
  display: flex;
  flex-direction: column;
  gap: 9px;
  min-width: 0;
}

.hdt__card {
  display: grid;
  gap: 7px;
  padding: 10px;
  border-radius: 11px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.hdt__card--act {
  background-color: #F8F9FC;
  box-shadow: none;
}

.hdt__by {
  display: flex;
  align-items: center;
  gap: 8px;
}

.hdt__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-size: 8.5px;
  font-weight: 700;
}

.hdt__avatar--alt {
  background-color: rgba(139, 92, 246, 0.12);
  color: #6D28D9;
}

.hdt__meta {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.hdt__name {
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.hdt__name em {
  margin-left: 4px;
  font-style: normal;
  font-size: 8.5px;
  font-weight: 600;
  color: #A6ADBD;
}

.hdt__when {
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.hdt__desc {
  margin: 0;
  font-size: 10px;
  line-height: 1.5;
  color: #5A6070;
}

.hdt__desc b {
  font-weight: 700;
  color: #5B4BE3;
}

.hdt__caplabel {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.hdt__caplabel em {
  font-style: normal;
  letter-spacing: 0;
  color: #8A90A0;
}

.hdt__composer {
  margin-top: auto;
  padding: 9px 11px;
  border-radius: 9px;
  background-color: #F4F6FB;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.06);
  font-size: 10px;
  font-weight: 500;
  color: #A6ADBD;
}

.hdt__side {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 11px;
  border-radius: 12px;
  background-color: #F8F9FC;
}

.hdt__sidelab {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.hdt__field {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.06);
}

.hdt__field:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.hdt__flab {
  font-size: 8.5px;
  font-weight: 600;
  color: #A6ADBD;
}

.hdt__fval {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.hdt__fval--open {
  color: #C0392B;
}

.hdt__fval--high {
  color: #B4761B;
}

.hdt__fval--due  {
  color: #1D4ED8;
}

/* Narrow frame: the queue loses its two quietest columns and the ticket goes
   to one column, because a details panel squeezed to a third of 340px is a
   column of ellipses. */

@container (max-width: 380px) {
  .hdl, .hdt {
    padding: 18px;
  }

  .hdl__cols,
  .hdl__row {
    grid-template-columns: minmax(0, 1fr) 46px 68px;
  }

  .hdl__id,
  .hdl__asg {
    display: none;
  }

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

  .hdt__cols {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ==========================================================================
   CANDIDATE SCREENING  (/candidate-screening/)
   The sorted pile in includes/screening-ui.php: what arrived, what was screened
   without a person, and the three that came out ranked. It sits in
   .hs-hero__frame, so it needs no frame modifier of its own.
   ========================================================================== */

.scn .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  min-height: 0;
}

.scn {
  min-height: 0;
}

.scn__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.scn__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.scn__title {
  font-size: 13px;
  font-weight: 600;
  color: #22262F;
}

.scn__sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.scn__chip {
  flex: none;
  padding: 2px 9px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.scn__tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.scn__tile {
  display: flex;
  flex-direction: column;
  padding: 9px 10px;
  border-radius: 10px;
  background-color: #F4F6FB;
}

.scn__tnum {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.1;
  color: #22262F;
}

.scn__tnum--good {
  color: #15803D;
}

.scn__tnum--warn {
  color: #B4761B;
}

.scn__tlab {
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

.scn__caplabel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.scn__caplabel em {
  font-style: normal;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: #15803D;
}

.scn__trend {
  display: grid;
  gap: 7px;
}

/* The line is drawn on a 100 × 34 viewBox with preserveAspectRatio="none", so
   it stretches to the panel's width and keeps its height. That is the right
   trade for a sparkline: the shape of the week matters, the aspect does not. */

.scn__spark {
  display: block;
  width: 100%;
  height: 34px;
  color: #2563EB;
}

.scn__rows {
  display: grid;
  gap: 6px;
}

.scn__row {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) 54px 22px;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: 10px;
  background-color: #F8F9FC;
}

.scn__avatar {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-size: 8.5px;
  font-weight: 700;
}

.scn__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.scn__name {
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

/* The reason under the name is what stops the score being a black box, so it
   truncates rather than being dropped at narrow widths. */

.scn__why {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.scn__bar {
  position: relative;
  height: 5px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.08);
  overflow: hidden;
}

.scn__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w, 50%);
  border-radius: inherit;
  background: linear-gradient(90deg, #2563EB 0%, #60A5FA 100%);
}

.scn__score {
  text-align: right;
  font-size: 10.5px;
  font-weight: 700;
  color: #1D4ED8;
}

.scn__note {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: auto;
  padding: 11px 12px;
  border-radius: 12px;
  background-color: rgba(22, 163, 74, 0.08);
  box-shadow: inset 0 0 0 1px rgba(22, 163, 74, 0.16);
}

.scn__noteicon {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 9px;
  background-color: #16A34A;
  color: #ffffff;
}

.scn__noteicon .hs-i {
  width: 14px;
  height: 14px;
}

.scn__notetext {
  min-width: 0;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.35;
  color: #22262F;
}

.scn__notelab {
  display: block;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #15803D;
}

/* Narrow frame: four tiles across is two, and the score bar is the first thing
   that stops being readable. */

@container (max-width: 380px) {
  .scn {
    padding: 18px;
  }

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

  .scn__row {
    grid-template-columns: 24px minmax(0, 1fr) 22px;
  }

  .scn__bar {
    display: none;
  }
}

/* ==========================================================================
   CANDIDATE PROFILE  (includes/screening-profile-ui.php)
   Panel 02 of /candidate-screening/'s sequence: one applicant opened out of the
   board. Sits in .sc-panel__frame--succ, so it is the 560px every drawn
   interface here is.
   ========================================================================== */

.snp .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
  min-height: 0;
}

.snp {
  min-height: 0;
}

.snp__head {
  display: flex;
  align-items: center;
  gap: 10px;
}

.snp__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-size: 11px;
  font-weight: 700;
}

.snp__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.snp__name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 700;
  color: #22262F;
}

.snp__match {
  padding: 2px 8px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-style: normal;
  font-size: 9px;
  font-weight: 700;
}

.snp__mail {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.snp__acts {
  display: flex;
  align-items: center;
  gap: 7px;
}

.snp__stage {
  margin-right: auto;
  padding: 4px 10px;
  border-radius: 7px;
  background-color: #F4F6FB;
  font-size: 9.5px;
  font-weight: 600;
  color: #5A6070;
}

.snp__btn {
  padding: 4px 11px;
  border-radius: 7px;
  background-color: #5B4BE3;
  color: #ffffff;
  font-size: 9.5px;
  font-weight: 700;
}

.snp__btn--ghost {
  background-color: transparent;
  color: #5B4BE3;
  box-shadow: inset 0 0 0 1px rgba(91, 75, 227, 0.3);
}

.snp__tabs {
  display: flex;
  gap: 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.snp__tab {
  position: relative;
  font-size: 10px;
  font-weight: 600;
  color: #8A90A0;
}

.snp__tab--on {
  color: #5B4BE3;
}

.snp__tab--on::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -9px;
  height: 2px;
  border-radius: 2px;
  background-color: #5B4BE3;
}

.snp__cols {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 10px;
  min-height: 0;
}

/* ---- the document, as a shape ----
   Headings over rules rather than a fabricated career history. See the note at
   the top of includes/screening-profile-ui.php. */

.snp__doc {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px;
  border-radius: 11px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
  overflow: hidden;
}

.snp__docbar {
  width: 52%;
  height: 9px;
  border-radius: 3px;
  background-color: rgba(16, 24, 48, 0.16);
}

.snp__docsub {
  width: 74%;
  height: 5px;
  margin-bottom: 4px;
  border-radius: 3px;
  background-color: rgba(16, 24, 48, 0.08);
}

.snp__seclab {
  margin-top: 4px;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.snp__line {
  width: var(--w, 100%);
  height: 4px;
  border-radius: 3px;
  background-color: rgba(16, 24, 48, 0.07);
}

.snp__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.snp__chip {
  width: 42px;
  height: 12px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.12);
}

.snp__chip--w2 {
  width: 58px;
}

.snp__side {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 11px;
  border-radius: 12px;
  background-color: #F8F9FC;
  overflow: hidden;
}

.snp__sidelab {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.snp__field {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-bottom: 7px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.06);
}

.snp__field:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.snp__flab {
  font-size: 8.5px;
  font-weight: 600;
  color: #A6ADBD;
}

.snp__fval {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

/* Narrow frame: the info column squeezed to a third of 340px is a column of
   ellipses, so it goes under the document instead. */

@container (max-width: 380px) {
  .snp {
    padding: 18px;
  }

  .snp__cols {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ==========================================================================
   VISITOR MANAGEMENT  (includes/visitor-ui.php)
   The front desk: who is on the premises, who is expected, and the digital
   pass that replaced the logbook. Sits in .hs-hero__frame, so it needs no
   frame modifier of its own.
   ========================================================================== */

.vms .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  min-height: 0;
}

.vms {
  min-height: 0;
}

.vms__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.vms__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.vms__title {
  font-size: 13px;
  font-weight: 600;
  color: #22262F;
}

.vms__sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.vms__chip {
  flex: none;
  padding: 2px 9px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.vms__tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.vms__tile {
  display: flex;
  flex-direction: column;
  padding: 9px 10px;
  border-radius: 10px;
  background-color: #F4F6FB;
}

.vms__tnum {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.1;
  color: #22262F;
}

/* The count that matters during an evacuation, so it is the one in colour. */

.vms__tnum--on   {
  color: #1D4ED8;
}

.vms__tnum--good {
  color: #15803D;
}

.vms__tlab {
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

.vms__caplabel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.vms__caplabel em {
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: #8A90A0;
}

.vms__rows {
  display: grid;
  gap: 6px;
}

.vms__row {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) 34px 8px;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: 10px;
  background-color: #F8F9FC;
}

.vms__avatar {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-size: 8.5px;
  font-weight: 700;
}

.vms__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.vms__name {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.vms__type {
  flex: none;
  padding: 1px 6px;
  border-radius: 100px;
  background-color: rgba(139, 92, 246, 0.12);
  color: #6D28D9;
  font-style: normal;
  font-size: 8px;
  font-weight: 700;
}

.vms__host {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.vms__time {
  text-align: right;
  font-size: 9.5px;
  font-weight: 700;
  color: #5A6070;
}

/* On site, still. Green rather than a label, because three of them in a column
   is three words nobody reads. */

.vms__dot {
  width: 7px;
  height: 7px;
  border-radius: 100px;
  background-color: #16A34A;
}

.vms__pass {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-top: auto;
  padding: 11px 12px;
  border-radius: 12px;
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.14);
}

/* A QR code as a shape: nine squares on a 3 × 3 grid with two corners solid.
   Not a scannable code, and deliberately not — a real one on a marketing page
   is a link somebody will point a phone at. */

.vms__qr {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
  flex: none;
  width: 28px;
  height: 28px;
  padding: 3px;
  border-radius: 7px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.18);
}

.vms__qr span {
  border-radius: 1px;
  background-color: rgba(37, 99, 235, 0.22);
}

.vms__qr span:nth-child(1),
.vms__qr span:nth-child(3),
.vms__qr span:nth-child(5),
.vms__qr span:nth-child(9) {
  background-color: #2563EB;
}

.vms__passtext {
  min-width: 0;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.35;
  color: #22262F;
}

.vms__passlab {
  display: block;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #2563EB;
}

/* Narrow frame: four tiles across is two, and the host line under each name is
   the first thing that stops fitting. */

@container (max-width: 380px) {
  .vms {
    padding: 18px;
  }

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

  .vms__host {
    display: none;
  }
}

/* ==========================================================================
   VISITOR SEQUENCE PANELS — the three screens in /visitor-management-system/
   The pass and its timeline, the report over a range, and the breakdown under
   it. All three sit in .sc-panel__frame--succ, so all three are the 560px
   every drawn interface here is.
   ========================================================================== */

.vpz .sc-sheet,
.vrp .sc-sheet,
.vin .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 11px;
  overflow: hidden;
  min-height: 0;
}

.vpz, .vrp, .vin {
  min-height: 0;
}

.vpz__caplabel,
.vrp__caplabel,
.vin__caplabel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.vpz__caplabel em,
.vrp__caplabel em,
.vin__caplabel em {
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: #8A90A0;
}

/* ---- 1. the pass ---- */

.vpz__head {
  display: flex;
  align-items: center;
  gap: 10px;
}

.vpz__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.14);
  color: #15803D;
  font-size: 10.5px;
  font-weight: 700;
}

.vpz__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}

.vpz__name {
  font-size: 12.5px;
  font-weight: 700;
  color: #22262F;
}

.vpz__org {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.vpz__tags {
  flex: none;
}

.vpz__tag {
  padding: 2px 8px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 700;
}

.vpz__tag--on {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.vpz__cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  min-height: 0;
}

.vpz__left,
.vpz__right {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.vpz__field {
  padding: 7px 10px;
  border-radius: 8px;
  background-color: #F4F6FB;
  font-size: 10px;
  font-weight: 600;
  color: #5A6070;
  letter-spacing: 0.04em;
}

.vpz__win {
  display: grid;
  gap: 5px;
  padding: 8px 10px;
  border-radius: 9px;
  background-color: #F8F9FC;
}

.vpz__winrow {
  display: flex;
  flex-direction: column;
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
}

.vpz__winrow em {
  font-style: normal;
  font-size: 8.5px;
  font-weight: 600;
  color: #A6ADBD;
}

.vpz__winrow--ok {
  color: #15803D;
}

.vpz__pass {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 10px;
  border-radius: 11px;
  background-color: #F8F9FC;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.06);
}

/* Sixteen cells with three corner markers. Not a scannable code, deliberately:
   see the note at the top of includes/visitor-pass-ui.php. */

.vpz__qr {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2px;
  width: 62px;
  height: 62px;
  padding: 5px;
  border-radius: 8px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.1);
}

.vpz__qr span {
  border-radius: 1px;
  background-color: rgba(16, 24, 48, 0.14);
}

.vpz__qr span:nth-child(1),
.vpz__qr span:nth-child(4),
.vpz__qr span:nth-child(6),
.vpz__qr span:nth-child(11),
.vpz__qr span:nth-child(13),
.vpz__qr span:nth-child(16) {
  background-color: #22262F;
}

.vpz__passnote {
  text-align: center;
  font-size: 8.5px;
  font-weight: 500;
  line-height: 1.35;
  color: #A6ADBD;
}

.vpz__time {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.vpz__step {
  display: grid;
  grid-template-columns: 9px minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
}

.vpz__dot {
  width: 8px;
  height: 8px;
  border-radius: 100px;
}

.vpz__dot--sent {
  background-color: #3B82F6;
}

.vpz__dot--in   {
  background-color: #16A34A;
}

.vpz__dot--out  {
  background-color: #A6ADBD;
}

.vpz__steplab {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
}

.vpz__steptime {
  font-size: 9px;
  font-weight: 600;
  color: #8A90A0;
}

/* ---- 2. the report ---- */

.vrp__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.vrp__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.vrp__title {
  font-size: 13px;
  font-weight: 700;
  color: #22262F;
}

.vrp__sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.vrp__range {
  flex: none;
  padding: 4px 10px;
  border-radius: 7px;
  background-color: #F1F4F9;
  font-size: 9.5px;
  font-weight: 600;
  color: #5A6070;
}

.vrp__tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.vrp__tile {
  display: flex;
  flex-direction: column;
  padding: 9px 10px;
  border-radius: 10px;
  background-color: #F4F6FB;
}

.vrp__tnum {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.1;
  color: #22262F;
}

.vrp__tnum--brand {
  color: #1D4ED8;
}

.vrp__tnum--good  {
  color: #15803D;
}

.vrp__tnum--warn  {
  color: #B4761B;
}

.vrp__tlab {
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

.vrp__chart {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: auto;
  padding: 11px;
  border-radius: 11px;
  background-color: #F8F9FC;
}

.vrp__svg {
  display: block;
  width: 100%;
  height: 92px;
}

.vrp__l {
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.vrp__l--tot {
  stroke: #2563EB;
}

.vrp__l--in  {
  stroke: #16A34A;
}

.vrp__l--no  {
  stroke: #E9A23B;
}

.vrp__legend {
  display: flex;
  gap: 12px;
}

.vrp__key {
  display: flex;
  align-items: center;
  gap: 5px;
  font-style: normal;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
}

.vrp__key::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 100px;
}

.vrp__key--tot::before {
  background-color: #2563EB;
}

.vrp__key--in::before  {
  background-color: #16A34A;
}

.vrp__key--no::before  {
  background-color: #E9A23B;
}

/* ---- 3. the insights ---- */

.vin__panel {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 11px;
  border-radius: 11px;
  background-color: #F8F9FC;
}

.vin__bars {
  display: grid;
  grid-template-columns: repeat(9, minmax(0, 1fr));
  gap: 6px;
  align-items: end;
  height: 74px;
}

/* A grid, not a flex column: the percentage has to resolve against the track
   alone, or the hour label under it eats the top of the scale and the tallest
   bars all draw the same height. */

.vin__bar {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 5px;
  height: 100%;
}

.vin__fill {
  align-self: end;
  height: var(--h, 50%);
  border-radius: 3px 3px 2px 2px;
  background: linear-gradient(180deg, #5B4BE3 0%, #8B7CF0 100%);
}

.vin__hour {
  text-align: center;
  font-size: 8px;
  font-weight: 600;
  color: #A6ADBD;
}

.vin__types {
  display: grid;
  gap: 7px;
}

.vin__type {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 84px 16px;
  align-items: center;
  gap: 9px;
}

.vin__tname {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
}

.vin__track {
  position: relative;
  height: 7px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.07);
  overflow: hidden;
}

.vin__trackfill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w, 50%);
  border-radius: inherit;
}

.vin__trackfill--a {
  background-color: #16A34A;
}

.vin__trackfill--b {
  background-color: #2563EB;
}

.vin__trackfill--c {
  background-color: #E9A23B;
}

.vin__trackfill--d {
  background-color: #8B5CF6;
}

.vin__tcount {
  text-align: right;
  font-size: 10px;
  font-weight: 700;
  color: #5A6070;
}

.vin__hosts {
  display: grid;
  gap: 7px;
}

.vin__host {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr) 22px;
  align-items: center;
  gap: 9px;
}

.vin__rank {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 100px;
  background-color: #EDF1F4;
  font-size: 8.5px;
  font-weight: 700;
  color: #8A90A0;
}

.vin__hwho {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.vin__hname {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.vin__hteam {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.vin__hnum {
  text-align: right;
  font-size: 10.5px;
  font-weight: 700;
  color: #22262F;
}

/* Narrow frame: the pass goes to one column and the report's tiles to two. */

@container (max-width: 380px) {
  .vpz, .vrp, .vin {
    padding: 18px;
  }

  .vpz__cols {
    grid-template-columns: minmax(0, 1fr);
  }

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

  .vin__type {
    grid-template-columns: minmax(0, 1fr) 54px 16px;
  }
}

/* ---- the visitors list (includes/visitor-list-ui.php) ----
   Panel 01 of the visitor sequence. A different screen from the hero's summary:
   a row per visitor with the columns reception reads. */

.vls .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
  min-height: 0;
}

.vls {
  min-height: 0;
}

.vls__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.vls__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.vls__title {
  font-size: 13px;
  font-weight: 700;
  color: #22262F;
}

.vls__sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.vls__invite {
  flex: none;
  padding: 5px 12px;
  border-radius: 8px;
  background-color: #5B4BE3;
  color: #ffffff;
  font-size: 9.5px;
  font-weight: 700;
}

.vls__tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.vls__tile {
  display: flex;
  flex-direction: column;
  padding: 8px 10px;
  border-radius: 10px;
  background-color: #F4F6FB;
}

.vls__tnum {
  font-size: 16px;
  font-weight: 700;
  line-height: 1.1;
  color: #22262F;
}

.vls__tnum--on   {
  color: #1D4ED8;
}

.vls__tnum--warn {
  color: #B4761B;
}

.vls__tnum--bad  {
  color: #C0392B;
}

.vls__tlab {
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 8px;
  font-weight: 500;
  color: #8A90A0;
}

.vls__bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.vls__tab {
  position: relative;
  font-size: 10px;
  font-weight: 600;
  color: #8A90A0;
}

.vls__tab em {
  margin-left: 4px;
  padding: 1px 5px;
  border-radius: 100px;
  background-color: rgba(91, 75, 227, 0.12);
  font-style: normal;
  font-size: 8px;
  font-weight: 700;
}

.vls__tab--on {
  color: #5B4BE3;
}

.vls__tab--on::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -9px;
  height: 2px;
  border-radius: 2px;
  background-color: #5B4BE3;
}

.vls__export {
  margin-left: auto;
  padding: 3px 10px;
  border-radius: 7px;
  background-color: #F1F4F9;
  font-size: 9.5px;
  font-weight: 600;
  color: #5A6070;
}

/* One template for the header and every row. */

.vls__cols,
.vls__row {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) 68px minmax(0, 0.9fr) 84px;
  align-items: center;
  gap: 9px;
}

.vls__cols {
  padding: 0 8px;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.vls__rows {
  display: grid;
  gap: 4px;
}

.vls__row {
  padding: 7px 8px;
  border-radius: 9px;
  background-color: #F8F9FC;
}

.vls__who {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.vls__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-size: 8.5px;
  font-weight: 700;
}

.vls__names {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.vls__name,
.vls__org,
.vls__host,
.vls__win {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.vls__name {
  font-size: 10.5px;
  font-weight: 600;
  color: #22262F;
}

.vls__org {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.vls__type {
  padding: 2px 0;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
  text-align: center;
  font-size: 8px;
  font-weight: 700;
}

.vls__host {
  font-size: 9.5px;
  font-weight: 500;
  color: #5A6070;
}

.vls__win {
  text-align: right;
  font-size: 9px;
  font-weight: 600;
  color: #8A90A0;
}

/* Narrow frame: the host and the employer line are the first two to go. */

@container (max-width: 380px) {
  .vls {
    padding: 18px;
  }

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

  .vls__cols,
  .vls__row {
    grid-template-columns: minmax(0, 1fr) 68px 84px;
  }

  .vls__host, .vls__org {
    display: none;
  }
}

/* ==========================================================================
   THE PROBLEM  (sections/automation/problem.php)

   A photograph on the left, the five failures on the right, and the result
   they add up to on a card over the picture.

   The list is a list, not a grid of cards: it is one argument in five parts,
   and it is read down. The marks are a muted red, the only warm colour on the
   page, because this is the one section describing what goes wrong.
   ========================================================================== */

.rap {
  display: grid;
  gap: 34px;
  align-items: center;
}

@media (min-width: 900px) {
  .rap {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
    gap: 56px;
  }

  /* The solution runs the other way: copy left, photograph right. Two
     identical layouts back to back would read as one long section, and it is
     the turn that makes the second one the reply to the first. The markup
     order does the swapping, so the columns only need their widths exchanged. */

  .rap--flip {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  }
}

.rap__art {
  position: relative;
  isolation: isolate;
}

.rap__photo {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 4.4;
  -o-object-fit: cover;
     object-fit: cover;
  border-radius: 24px;
  box-shadow: 0 30px 60px -34px rgba(16, 24, 48, 0.55);
}

/* The result, over the foot of the picture. Inset from the edge rather than
   flush to it, so the card reads as sitting on the photograph rather than as
   a caption bar cut into it. */

.rap__result {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 16px;
  display: block;
  padding: 16px 18px;
  border-radius: 16px;
  background-color: rgba(255, 255, 255, 0.94);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: 0 16px 34px -22px rgba(16, 24, 48, 0.6);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.45;
  color: #14161D;
}

.rap__result em {
  display: block;
  margin-bottom: 4px;
  font-style: normal;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #C2410C;
}

.rap__title {
  margin-top: 16px;
  text-align: left;
}

.rap__lead {
  margin-top: 12px;
  font-size: 17px;
  font-weight: 500;
  line-height: 1.6;
  color: #4D585F;
}

.rap__list {
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 10px;
}

.rap__point {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 15px 18px;
  border-radius: 14px;
  background-color: #F6F7FA;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.45;
  color: #22262F;
}

/* A dot rather than a cross. Five crosses down a column reads as a scorecard
   somebody failed; these are conditions, not marks against anyone. */

.rap__mark {
  flex: none;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background-color: #E56B4E;
  box-shadow: 0 0 0 4px rgba(229, 107, 78, 0.14);
}

/* Green on the solution side. Same shape, so the two lists read as one pair
   rather than as two unrelated blocks; only the colour says which is which. */

.rap__mark--ok {
  background-color: #10B981;
  box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.16);
}

.rap__result--ok em {
  color: #047857;
}

/* ==========================================================================
   AI INTERVIEW EXTRAS  (sections/interview/*)

   Two additions to the .rap block above, and one small section of its own.
   Everything else on that page is a component that already existed.
   ========================================================================== */

/* The hero frame on this page, in a pale blue-tinted border rather than the
   flat grey every other hero uses. The interview screen is mostly white cards
   and one dark video tile; on the default ground the two washed into each
   other and the whole thing read as a screenshot lying flat. The tint puts a
   box around it without competing with the artwork it holds.

   The padding is what makes it a box rather than a tint: the artwork floats
   inside the colour instead of running to its edges. */

.hs-hero__frame--ai {
  padding: 20px;
  border-radius: 26px;
  background-color: #E8EEFC;
  background-image: linear-gradient(150deg, #F2F5FE 0%, #E8EEFC 45%, #DFE7FA 100%);
  box-shadow:
    0 34px 80px -34px rgba(21, 82, 199, 0.28),
    0 2px 10px rgba(16, 24, 48, 0.07);
}

/* The artwork column holding a drawn screen rather than a photograph. The
   photo variant carries its own rounding and shadow; a screen brings its own
   frame, so this only gives it the ground to sit on. */

.rap__art--frame {
  padding: 22px;
  border-radius: 24px;
  background-image: linear-gradient(150deg, #EEF3FE 0%, #E4EBFA 100%);
  box-shadow: 0 30px 60px -38px rgba(16, 24, 48, 0.5);
}

/* A point with a title and a line under it, rather than the single line the
   problem list uses. Same chip, more inside it. */

.rap__point--rich {
  align-items: flex-start;
  gap: 14px;
  padding: 18px 20px;
}

.rap__picon {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 11px;
  background-color: #FFFFFF;
  color: #1D6BF3;
  box-shadow: 0 1px 2px rgba(16, 24, 48, 0.06);
}

.rap__picon .hs-i {
  width: 18px;
  height: 18px;
}

.rap__ptext {
  display: block;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.55;
  color: #4D585F;
}

.rap__ptitle {
  display: block;
  margin-bottom: 3px;
  font-size: 15px;
  font-weight: 600;
  color: #14161D;
}

/* The eight integrity checks, two across. One column would run the list past
   the photograph beside it and leave the picture stranded at the top. */

.ai-checks {
  display: grid;
  gap: 10px;
  margin: 28px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 620px) {
  .ai-checks {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
  }
}

.ai-check {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 15px 16px;
  border-radius: 16px;
  background-color: #F4F6FB;
}

.ai-check__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 11px;
  background-color: #FFFFFF;
  color: #1D6BF3;
  box-shadow: 0 1px 2px rgba(16, 24, 48, 0.06);
}

.ai-check__icon .hs-i {
  width: 17px;
  height: 17px;
}

.ai-check__body {
  display: block;
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #5A6070;
}

.ai-check__name {
  display: block;
  margin-bottom: 2px;
  font-size: 14.5px;
  font-weight: 600;
  color: #22262F;
}

/* ---- the hub and its eight spokes  (sections/interview/hub.php) ----

   The box is locked to the wires' own 1000 x 560 so the SVG and the HTML chips
   share one coordinate space: the SVG scales uniformly inside it, and a chip
   placed at 38% of the height sits exactly where the path drawn at y=213 ends.
   Break that ratio and every wire misses its chip.
   -------------------------------------------------------------------- */

.aih {
  position: relative;
  display: grid;
  gap: 12px;
  margin: 44px auto 0;
  max-width: 1000px;
}

.aih__wires {
  display: none;
}

.aih__side {
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 560px) {
  .aih__side {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.aih__chip {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-radius: 100px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #E6EFFC, 0 10px 24px -18px rgba(21, 82, 199, 0.5);
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.3;
  color: #14161D;
}

.aih__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background-color: #EEF4FE;
  color: #1D6BF3;
}

.aih__icon .hs-i {
  width: 17px;
  height: 17px;
}

.aih__hub {
  position: relative;
  display: grid;
  place-items: center;
  justify-self: center;
  width: 92px;
  height: 92px;
  border-radius: 50%;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  box-shadow: 0 14px 30px -8px rgba(37, 99, 235, 0.55);
}

.aih__hub img {
  width: 54px;
  max-width: 60%;
  height: auto;
  filter: brightness(0) invert(1);
}

/* The rings leaving the hub. Two of them, half a cycle apart, so there is
   always one on its way out. */

.aih__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.35);
  animation: aih-ring 3.2s ease-out infinite;
}

.aih__ring--late {
  animation-delay: 1.6s;
}

@keyframes aih-ring {
  0%   {
    transform: scale(1);
    opacity: 0.65;
  }

  100% {
    transform: scale(1.85);
    opacity: 0;
  }
}

@media (min-width: 900px) {
  .aih {
    display: block;
    aspect-ratio: 1000 / 560;
  }

  .aih__wires {
    display: block;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
  }

  .aih__side {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 23%;
    display: block;
  }

  .aih__side--in  {
    left: 0;
  }

  .aih__side--out {
    right: 0;
  }

  /* --y is the row, set from PHP beside the path endpoints it has to match. */

  .aih__chip {
    position: absolute;
    top: var(--y);
    left: 0;
    right: 0;
    transform: translateY(-50%);
    padding: 11px 15px;
    font-size: 13.5px;
  }

  .aih__side--out .aih__chip {
    flex-direction: row-reverse;
    text-align: right;
  }

  .aih__hub {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 13%;
    height: auto;
    aspect-ratio: 1;
  }

  .aih__hub img {
    width: 54%;
    max-width: 65%;
  }
}

/* ---- the wires ---- */

.aih__halo {
  fill: none;
  stroke: #E7EEFB;
  stroke-width: 1.5;
}

.aih__wire {
  stroke: #DCE6F6;
  stroke-width: 2;
  stroke-linecap: round;
}

/* One short dash travelling the length of the path. pathLength="1000" is what
   lets the same numbers work on eight curves of different real lengths. */

.aih__pulse {
  stroke: #2563EB;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-dasharray: 70 930;
  animation: aih-run 3.4s linear infinite;
  animation-delay: var(--d, 0ms);
}

/* Every path is drawn chip to hub, so both sides reverse: the dash leaves the
   hub and runs out to its chip, left and right alike. */

.aih__pulse--in,
.aih__pulse--out {
  animation-name: aih-run;
  animation-direction: reverse;
}

@keyframes aih-run {
  from {
    stroke-dashoffset: 1000;
  }

  to   {
    stroke-dashoffset: 0;
  }
}

/* Nothing here carries meaning that the copy above does not, so under reduced
   motion it simply stops. The wires and the hub stay. */

@media (prefers-reduced-motion: reduce) {
  .aih__ring {
    animation: none;
    opacity: 0;
  }

  .aih__pulse {
    animation: none;
    stroke-dasharray: none;
    opacity: 0.35;
  }
}

/* ---- the three figures ---- */

.aik-sec {
  background-image: linear-gradient(180deg, #FFFFFF 0%, #F3F6FD 45%, #FFFFFF 100%);
}

.aik {
  display: grid;
  gap: 16px;
  margin: 44px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 760px) {
  .aik {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 22px;
  }
}

.aik__item {
  padding: 34px 28px 32px;
  border-radius: 22px;
  text-align: center;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #E6EFFC, 0 16px 36px -26px rgba(21, 82, 199, 0.5);
}

.aik__fig {
  display: block;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 46px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -1.5px;
  color: #1D6BF3;
}

.aik__label {
  display: block;
  margin-top: 12px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 600;
  color: #14161D;
}

/* The caption says what the figure counts. A number with a label and nothing
   else invites the reader to decide for themselves what it was measured
   against, which is how marketing figures stop being believed. */

.aik__note {
  display: block;
  margin-top: 8px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.55;
  color: #5A6070;
}

/* ==========================================================================
   VISITOR SOLUTION BAND  (sections/visitor/solution.php)

   The mid-page ask. A contained panel in the brand blue rather than the
   full-bleed scenic ground the closing band uses, because two bands of the
   same construction on one page read as one band shown twice.

   The blue is the one .btn-primary carries, run down into near-black at the
   far corner. It was this page's violet accent first; brand blue makes the
   band read as the site asking rather than as one more panel belonging to
   the visitor screens above it.

   Everything is centred and the panel has no artwork in it: it interrupts a
   run of dense sections, and its job is to be the one place on the page with
   nothing to read but the offer.
   ========================================================================== */

.vsol {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: 64px 32px 68px;
  border-radius: 28px;
  text-align: center;
  background-image: linear-gradient(
    135deg,
    #7CB0FC 0%,
    #3B82F6 30%,
    #2563EB 56%,
    #112C74 80%,
    #0C111E 100%
  );
  box-shadow: 0 30px 60px -34px rgba(37, 99, 235, 0.6);
}

/* A soft light behind the heading, off to one side so the panel is not a flat
   rectangle of one colour. Under the content, over the gradient. */

.vsol__glow {
  position: absolute;
  z-index: -1;
  top: -40%;
  right: -12%;
  width: 520px;
  height: 520px;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.28) 0%,
    rgba(255, 255, 255, 0) 62%
  );
}

.vsol__title {
  max-width: 18ch;
  margin: 0 auto;
  color: #FFFFFF;
}

.vsol__lead {
  max-width: 56ch;
  margin: 16px auto 0;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.86);
}

.vsol__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  margin-top: 32px;
}

/* .btn-white is written for a text-only pill and pads 18px top and bottom.
   Put the 38px icon capsule inside one and it stands 74px tall, half a head
   above every other button on the site. These are the numbers .btn-primary
   and .btn-dark use, which is what an arrow button measures everywhere else:
   58px, and this one now matches them. */

.vsol__btn {
  padding: 10px 10px 10px 30px;
}

/* The capsule is white on a dark button. Here the button is the white thing,
   so the capsule takes the panel's own blue instead and the arrow keeps its
   dark against it. */

.vsol__btn .btn__icon {
  background-color: #E3EDFD;
}

@media (max-width: 640px) {
  .vsol {
    padding: 46px 22px 50px;
  }

  .vsol__row {
    flex-direction: column;
    align-items: center;
  }
}

/* ==========================================================================
   VISITOR LIFECYCLE ACCORDION  (sections/visitor/lifecycle.php)
   Five titles on screen at once, one open, numbered down a single rail. Dark,
   because the section is a change of register between two white ones and the
   showcase that follows it is dark too.
   ========================================================================== */

.vlc-sec {
  position: relative;
  isolation: isolate;
  background-color: #0B0D12;
  color: #ffffff;
}

/* Flat black over a section this tall reads as a hole in the page. Two soft
   brand washes and a top-to-bottom lift give it somewhere to come from: the
   ground is lightest where the heading is and settles to near-black by the
   last step, which is also the direction the eye is already travelling.

   Kept faint on purpose. Anything stronger and the accordion's greys start
   picking up a colour cast they were not chosen for. */

.vlc-sec::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(95% 70% at 6% 0%, rgba(37, 99, 235, 0.20), rgba(37, 99, 235, 0) 60%),
    radial-gradient(80% 65% at 100% 96%, rgba(70, 50, 180, 0.18), rgba(70, 50, 180, 0) 64%),
    linear-gradient(180deg, #151A27 0%, #0B0D12 58%, #08090D 100%);
}

/* The head is one column: badge, heading, then the lead directly under it.
   It ran as two columns with the lead opposite the heading and right-aligned,
   which put the sentence a reader needs first at the far side of the page. */

.vlc__head {
  display: grid;
  justify-items: start;
  gap: 14px;
  margin-bottom: 56px;
}

/* Size, weight and tracking come from .section-title, the same heading rule
   every other section heading on the site uses — the two classes sit together
   on the <h2>. All that is left here is the colour, because .section-title is
   written for a light ground and this section is dark. */

.vlc__title {
  margin: 0;
  color: #ffffff;
}

.vlc__lead {
  margin: 6px 0 0;
  max-width: 640px;
  font-size: 15px;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.6);
}

/* ---- the rail and the numbers ---- */

.vlc {
  position: relative;
  padding-left: 74px;
}

@media (max-width: 639px) {
  .vlc {
    padding-left: 54px;
  }
}

/* One rule, inset by half a marker at each end so it joins the first and last
   circle rather than running past them. */

.vlc__rail {
  position: absolute;
  top: 30px;
  bottom: 30px;
  left: 23px;
  width: 1px;
  background-color: rgba(255, 255, 255, 0.16);
}

@media (max-width: 639px) {
  .vlc__rail {
    left: 15px;
  }
}

.vlc__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.vlc__item {
  position: relative;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.vlc__item:last-child {
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

.vlc__num {
  position: absolute;
  top: 18px;
  left: -74px;
  display: grid;
  place-items: center;
  width: 47px;
  height: 47px;
  border-radius: 100px;
  background-color: #0B0D12;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
  font-size: 12px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.5);
  transition:
    background-color 320ms var(--ease-soft),
    color 320ms var(--ease-soft),
    box-shadow 320ms var(--ease-soft);
}

@media (max-width: 639px) {
  .vlc__num {
    left: -54px;
    width: 31px;
    height: 31px;
    font-size: 10px;
  }
}

/* The open step's marker fills. It is the only solid thing in the section, so
   it reads as the position indicator the rail is drawn for. */

.vlc__item:has(.vlc__d[open]) .vlc__num {
  background-color: #ffffff;
  box-shadow: none;
  color: #0B0D12;
}

/* ---- one step ---- */

.vlc__sum {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 22px 0;
  cursor: pointer;
  list-style: none;
}

/* The UA marker, removed in both dialects. */

.vlc__sum::-webkit-details-marker {
  display: none;
}

.vlc__sum::marker {
  content: '';
}

.vlc__name {
  margin: 0;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(22px, 3.2vw, 34px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: rgba(255, 255, 255, 0.45);
  transition: color 320ms var(--ease-soft);
}

.vlc__meta {
  flex: 1 1 auto;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.32);
}

.vlc__arrow {
  flex: none;
  align-self: center;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  color: rgba(255, 255, 255, 0.45);
  /* Down when closed, up when open. One glyph, rotated. */
  transform: rotate(180deg);
  transition: transform 380ms var(--ease-smooth), color 320ms var(--ease-soft);
}

.vlc__arrow svg {
  width: 16px;
  height: 16px;
}

.vlc__d[open] .vlc__name  {
  color: #ffffff;
}

.vlc__d[open] .vlc__arrow {
  transform: rotate(0deg);
  color: #ffffff;
}

.vlc__text {
  max-width: 620px;
  margin: 0;
  padding: 0 0 26px;
  font-size: 15px;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.6);
}

/* The panel slides rather than appearing. Only the open state animates: a
   disclosure that eases shut makes the next one wait for it. */

@media (prefers-reduced-motion: no-preference) {
  .vlc__d[open] .vlc__text {
    animation: vlc-open 420ms var(--ease-smooth) both;
  }
}

@keyframes vlc-open {
  from {
    opacity: 0;
    transform: translate3d(0, -8px, 0);
  }

  to   {
    opacity: 1;
    transform: none;
  }
}

/* Hover on a closed step lifts it towards the open one, so the row reads as
   something that can be opened before anyone clicks it. */

@media (hover: hover) {
  .vlc__d:not([open]) .vlc__sum:hover .vlc__name,
  .vlc__d:not([open]) .vlc__sum:hover .vlc__arrow {
    color: rgba(255, 255, 255, 0.8);
  }
}

/* ==========================================================================
   DESKTIME  (includes/desktime-ui.php)
   The productivity dashboard: monitored headcount, the hours, the productive
   ring, and where the day actually went. Sits in .hs-hero__frame, so it needs
   no frame modifier of its own.
   ========================================================================== */

.dtm .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  min-height: 0;
}

.dtm {
  min-height: 0;
}

.dtm__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.dtm__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.dtm__title {
  font-size: 13px;
  font-weight: 600;
  color: #22262F;
}

.dtm__sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.dtm__chip {
  flex: none;
  padding: 2px 9px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.dtm__top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 108px;
  gap: 10px;
  align-items: stretch;
}

.dtm__tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.dtm__tile {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 8px 10px;
  border-radius: 10px;
  background-color: #F4F6FB;
}

.dtm__tnum {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.15;
  color: #22262F;
}

.dtm__tlab {
  margin-top: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

/* ---- the ring ----
   A track and an arc. pathLength="100" on the arc normalises its circumference,
   so stroke-dasharray "61 39" is literally the percentage printed inside it —
   the number and the drawing cannot disagree. */

.dtm__ring {
  position: relative;
  display: grid;
  place-items: center;
  padding: 8px;
  border-radius: 12px;
  background-color: #F4F6FB;
}

.dtm__ring svg {
  width: 100%;
  height: auto;
  max-height: 92px;
  transform: rotate(-90deg);
}

.dtm__track {
  fill: none;
  stroke: rgba(16, 24, 48, 0.09);
  stroke-width: 4;
}

.dtm__arc {
  fill: none;
  stroke: #2563EB;
  stroke-width: 4;
  stroke-linecap: round;
}

.dtm__ringnum {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-60%);
  text-align: center;
  font-size: 17px;
  font-weight: 700;
  color: #22262F;
}

.dtm__ringlab {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(46%);
  text-align: center;
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: #8A90A0;
}

.dtm__caplabel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.dtm__caplabel em {
  font-style: normal;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: #1D4ED8;
}

.dtm__trend {
  display: grid;
  gap: 7px;
}

.dtm__spark {
  display: block;
  width: 100%;
  height: 42px;
  color: #2563EB;
}

.dtm__apps {
  display: grid;
  gap: 7px;
}

.dtm__app {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr) 34px;
  align-items: center;
  gap: 10px;
}

.dtm__aname {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
}

.dtm__abar {
  position: relative;
  height: 7px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.07);
  overflow: hidden;
}

.dtm__afill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w, 50%);
  border-radius: inherit;
  background: linear-gradient(90deg, #2563EB 0%, #60A5FA 100%);
}

/* The one unproductive row, in the one warm colour on the panel. */

.dtm__afill--no {
  background: linear-gradient(90deg, #E9A23B 0%, #F6C453 100%);
}

.dtm__apct {
  text-align: right;
  font-size: 10px;
  font-weight: 700;
  color: #5A6070;
}

/* Narrow frame: the ring drops under the tiles rather than being squeezed into
   a column too thin to read the percentage in. */

@container (max-width: 380px) {
  .dtm {
    padding: 18px;
  }

  .dtm__top {
    grid-template-columns: minmax(0, 1fr);
  }

  .dtm__ring svg {
    max-height: 76px;
  }

  .dtm__app {
    grid-template-columns: 60px minmax(0, 1fr) 30px;
  }
}

/* ==========================================================================
   DESKTIME SEQUENCE PANELS — the five screens in /employee-monitoring-software/
   Dashboard, apps and people, teams and policy, desktop activity, timesheet.
   All five sit in .sc-panel__frame--dt, one shared height so the pinned stage
   does not resize on the handover between them.
   ========================================================================== */

.dtd .sc-sheet, .dta .sc-sheet, .dtp .sc-sheet,
.dts .sc-sheet, .dtt .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
  min-height: 0;
}

.dtd, .dta, .dtp, .dts, .dtt {
  min-height: 0;
}

.dtd__caplabel, .dta__caplabel, .dtp__caplabel, .dtt__caplabel {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

/* ---- 01 the dashboard ---- */

.dtd__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.dtd__title {
  font-size: 13px;
  font-weight: 700;
  color: #22262F;
}

.dtd__sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.dtd__filters {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
}

.dtd__filter {
  padding: 4px 10px;
  border-radius: 7px;
  background-color: #F4F6FB;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.06);
  font-size: 9px;
  font-weight: 600;
  color: #5A6070;
}

.dtd__tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 7px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.dtd__tile {
  display: flex;
  flex-direction: column;
  padding: 8px 9px;
  border-radius: 9px;
  background-color: #F4F6FB;
}

.dtd__tnum {
  font-size: 13px;
  font-weight: 700;
  line-height: 1.15;
  color: #22262F;
}

.dtd__tlab {
  margin-top: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 8px;
  font-weight: 500;
  color: #8A90A0;
}

.dtd__cols {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  gap: 10px;
  min-height: 0;
}

.dtd__ringbox, .dtd__trend {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  border-radius: 11px;
  background-color: #F8F9FC;
  min-width: 0;
}

.dtd__ring {
  position: relative;
  display: grid;
  place-items: center;
}

.dtd__ring svg {
  width: 84px;
  height: 84px;
  transform: rotate(-90deg);
}

.dtd__track {
  fill: none;
  stroke: rgba(16, 24, 48, 0.08);
  stroke-width: 5;
}

.dtd__arc   {
  fill: none;
  stroke: #16A34A;
  stroke-width: 5;
  stroke-linecap: round;
}

.dtd__ringnum {
  position: absolute;
  font-size: 15px;
  font-weight: 700;
  color: #22262F;
}

.dtd__legend {
  display: grid;
  gap: 5px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.dtd__legend li {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 8.5px;
  font-weight: 600;
  color: #5A6070;
}

.dtd__legend em {
  margin-left: auto;
  font-style: normal;
  font-weight: 700;
  color: #22262F;
}

.dtd__key {
  width: 7px;
  height: 7px;
  border-radius: 100px;
}

.dtd__key--a {
  background-color: #16A34A;
}

.dtd__key--b {
  background-color: #DC4444;
}

.dtd__key--c {
  background-color: #A6ADBD;
}

.dtd__svg {
  display: block;
  width: 100%;
  height: 108px;
}

.dtd__grid {
  stroke: rgba(16, 24, 48, 0.07);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.dtd__line {
  fill: none;
  stroke: #16A34A;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.dtd__axis {
  display: flex;
  justify-content: space-between;
}

.dtd__axis em {
  font-style: normal;
  font-size: 8px;
  font-weight: 600;
  color: #A6ADBD;
}

/* ---- 02 apps and people ---- */

.dta__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px;
  min-height: 0;
}

.dta__panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 11px;
  border-radius: 11px;
  background-color: #F8F9FC;
  min-width: 0;
}

.dta__panel--wide {
  grid-column: 1 / -1;
}

.dta__row {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) 62px;
  align-items: center;
  gap: 8px;
}

.dta__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
}

.dta__bar {
  position: relative;
  height: 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.07);
  overflow: hidden;
}

.dta__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w, 50%);
  border-radius: inherit;
}

.dta__fill--good {
  background-color: #16A34A;
}

.dta__fill--bad  {
  background-color: #DC4444;
}

.dta__val {
  text-align: right;
  font-size: 9px;
  font-weight: 700;
  color: #5A6070;
}

.dta__person {
  display: grid;
  grid-template-columns: 14px 22px minmax(0, 1fr) 62px;
  align-items: center;
  gap: 8px;
}

.dta__rank {
  font-size: 9px;
  font-weight: 700;
  color: #A6ADBD;
}

.dta__avatar {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.14);
  color: #15803D;
  font-size: 8px;
  font-weight: 700;
}

.dta__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.dta__pname {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
}

.dta__pid {
  font-size: 8px;
  font-weight: 500;
  color: #A6ADBD;
}

.dta__ptime {
  text-align: right;
  font-size: 9.5px;
  font-weight: 700;
  color: #22262F;
}

/* ---- 03 teams and policy ---- */

.dtp__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 9px;
  min-height: 0;
}

.dtp__panel {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 11px;
  border-radius: 11px;
  background-color: #F8F9FC;
  min-width: 0;
}

.dtp__row {
  display: grid;
  gap: 4px;
}

.dtp__rowtop {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.dtp__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
}

.dtp__val {
  flex: none;
  font-size: 8.5px;
  font-weight: 700;
  color: #8A90A0;
}

.dtp__bar {
  position: relative;
  height: 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.07);
  overflow: hidden;
}

.dtp__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w, 50%);
  border-radius: inherit;
  background-color: #16A34A;
}

.dtp__panel--side {
  align-items: flex-start;
}

.dtp__big {
  font-size: 34px;
  font-weight: 700;
  line-height: 1;
  color: #DC4444;
}

.dtp__biglab {
  margin-top: -4px;
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

.dtp__caplabel--tight {
  margin-top: 4px;
}

.dtp__block {
  display: grid;
  grid-template-columns: 8px minmax(0, 1fr) 18px;
  align-items: center;
  gap: 8px;
  width: 100%;
}

.dtp__bdot {
  width: 8px;
  height: 8px;
  border-radius: 100px;
  background-color: rgba(220, 68, 68, 0.55);
}

.dtp__bname {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
}

.dtp__bnum {
  text-align: right;
  font-size: 9.5px;
  font-weight: 700;
  color: #5A6070;
}

/* ---- 04 desktop activity ---- */

.dts__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.dts__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.dts__title {
  font-size: 13px;
  font-weight: 700;
  color: #22262F;
}

.dts__sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.dts__date {
  flex: none;
  padding: 4px 10px;
  border-radius: 7px;
  background-color: #F1F4F9;
  font-size: 9px;
  font-weight: 600;
  color: #5A6070;
}

.dts__tabs {
  display: flex;
  gap: 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.dts__tab {
  position: relative;
  font-size: 10px;
  font-weight: 600;
  color: #8A90A0;
}

.dts__tab--on {
  color: #5B4BE3;
}

.dts__tab--on::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -9px;
  height: 2px;
  border-radius: 2px;
  background-color: #5B4BE3;
}

.dts__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.dts__stat {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 9px;
  background-color: #F4F6FB;
}

.dts__dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 100px;
}

.dts__dot--on  {
  background-color: #16A34A;
}

.dts__dot--off {
  background-color: #A6ADBD;
}

.dts__scopy {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.dts__snum {
  font-size: 13px;
  font-weight: 700;
  line-height: 1.15;
  color: #22262F;
}

.dts__slab {
  font-size: 8px;
  font-weight: 500;
  color: #8A90A0;
}

.dts__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
}

.dts__shot {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

/* A drawn window, not a capture. See the note at the top of
   includes/dt-shots-ui.php on why no real screen is shown. */

.dts__frame {
  position: relative;
  display: block;
  aspect-ratio: 16 / 10;
  border-radius: 6px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.08);
}

.dts__frame--light {
  background-color: #EFF3F9;
}

.dts__frame--dark  {
  background-color: #1E2430;
}

.dts__bar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 18%;
  background-color: rgba(16, 24, 48, 0.10);
}

.dts__frame--dark .dts__bar {
  background-color: rgba(255, 255, 255, 0.10);
}

.dts__side {
  position: absolute;
  top: 18%;
  bottom: 0;
  left: 0;
  width: 22%;
  background-color: rgba(16, 24, 48, 0.06);
}

.dts__frame--dark .dts__side {
  background-color: rgba(255, 255, 255, 0.06);
}

.dts__lines {
  position: absolute;
  top: 30%;
  left: 30%;
  right: 10%;
  display: grid;
  gap: 12%;
}

.dts__lines i {
  display: block;
  height: 3px;
  border-radius: 2px;
  background-color: rgba(16, 24, 48, 0.13);
}

.dts__lines i:nth-child(2) {
  width: 76%;
}

.dts__lines i:nth-child(3) {
  width: 52%;
}

.dts__frame--dark .dts__lines i {
  background-color: rgba(120, 200, 160, 0.42);
}

.dts__stamp {
  position: absolute;
  left: 3px;
  bottom: 3px;
  padding: 1px 4px;
  border-radius: 3px;
  background-color: rgba(11, 13, 18, 0.72);
  color: #ffffff;
  font-size: 6.5px;
  font-weight: 700;
}

.dts__cap {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 8.5px;
  font-weight: 600;
  color: #5A6070;
}

/* ---- 05 the timesheet ---- */

.dtt__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.dtt__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.dtt__title {
  font-size: 13px;
  font-weight: 700;
  color: #22262F;
}

.dtt__title em {
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 100px;
  background-color: #F1F4F9;
  font-style: normal;
  font-size: 8px;
  font-weight: 700;
  color: #8A90A0;
}

.dtt__sub {
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.dtt__view {
  flex: none;
  padding: 4px 10px;
  border-radius: 7px;
  background-color: #5B4BE3;
  color: #ffffff;
  font-size: 9px;
  font-weight: 700;
}

.dtt__cap {
  display: grid;
  gap: 6px;
  padding: 10px 11px;
  border-radius: 11px;
  background-color: #F8F9FC;
}

.dtt__caprow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.dtt__capnum {
  font-size: 9.5px;
  font-weight: 700;
  color: #22262F;
}

.dtt__bar {
  position: relative;
  height: 7px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.08);
  overflow: hidden;
}

.dtt__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w, 50%);
  border-radius: inherit;
  background: linear-gradient(90deg, #5B4BE3 0%, #8B7CF0 100%);
}

.dtt__capnote {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.dtt__table {
  display: grid;
  gap: 5px;
}

.dtt__cols, .dtt__row {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(5, minmax(0, 1fr)) 42px;
  align-items: center;
  gap: 6px;
}

.dtt__cols {
  padding: 0 9px;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.dtt__cols span:not(:first-child) {
  text-align: center;
}

.dtt__cols .dtt__tot {
  text-align: right;
}

.dtt__row {
  padding: 8px 9px;
  border-radius: 9px;
  background-color: #F8F9FC;
}

.dtt__proj {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
}

.dtt__tag {
  flex: none;
  padding: 1px 6px;
  border-radius: 100px;
  background-color: #EDF1F4;
  font-style: normal;
  font-size: 7.5px;
  font-weight: 700;
  color: #8A90A0;
}

.dtt__cell {
  text-align: center;
  font-size: 9.5px;
  font-weight: 600;
  color: #5A6070;
}

.dtt__cell.dtt__tot {
  text-align: right;
  font-weight: 700;
  color: #22262F;
}

.dtt__foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
}

.dtt__unsaved {
  margin-right: auto;
  font-size: 8.5px;
  font-weight: 600;
  color: #B4761B;
}

.dtt__btn {
  padding: 5px 12px;
  border-radius: 8px;
  background-color: #5B4BE3;
  color: #ffffff;
  font-size: 9.5px;
  font-weight: 700;
}

.dtt__btn--ghost {
  background-color: transparent;
  color: #5A6070;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
}

/* Narrow frame: the two-column panels stack and the screenshot grid halves. */

@container (max-width: 380px) {
  .dtd, .dta, .dtp, .dts, .dtt {
    padding: 18px;
  }

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

  .dtd__cols, .dta__grid, .dtp__grid {
    grid-template-columns: minmax(0, 1fr);
  }

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

  .dtt__cols, .dtt__row {
    grid-template-columns: minmax(0, 1fr) repeat(3, minmax(0, 1fr)) 42px;
  }

  .dtt__cols span:nth-child(6), .dtt__cols span:nth-child(7),
  .dtt__row .dtt__cell:nth-of-type(4), .dtt__row .dtt__cell:nth-of-type(5) {
    display: none;
  }
}

/* ---- give recognition (includes/engage-give-ui.php) ----
   The fifth engagement panel: the act itself, rather than the feed it lands in
   or the points it awards. Same 560px frame as its four siblings. */

.egv .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
  min-height: 0;
}

.egv {
  min-height: 0;
}

.egv__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.egv__title {
  font-size: 13px;
  font-weight: 700;
  color: #22262F;
}

.egv__step {
  padding: 2px 9px;
  border-radius: 100px;
  background-color: #F1F4F9;
  font-size: 8.5px;
  font-weight: 700;
  color: #8A90A0;
}

.egv__caplabel {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.egv__person {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 10px;
  border-radius: 10px;
  background-color: #F8F9FC;
  box-shadow: inset 0 0 0 1px rgba(22, 163, 74, 0.22);
}

.egv__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
  font-size: 9.5px;
  font-weight: 700;
}

.egv__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}

.egv__name {
  font-size: 11px;
  font-weight: 600;
  color: #22262F;
}

.egv__role {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

/* The tick that says this one is chosen. Drawn from two borders rather than an
   icon: at 14px an SVG check is a smudge and a corner is not. */

.egv__picked {
  flex: none;
  width: 14px;
  height: 14px;
  border-radius: 100px;
  background-color: #16A34A;
  position: relative;
}

.egv__picked::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 5px;
  width: 3px;
  height: 6px;
  border: solid #ffffff;
  border-width: 0 1.6px 1.6px 0;
  transform: rotate(45deg);
}

.egv__badges {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

.egv__badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border-radius: 100px;
  background-color: #F4F6FB;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.06);
  font-size: 9.5px;
  font-weight: 600;
  color: #5A6070;
}

.egv__bmark {
  width: 9px;
  height: 9px;
  border-radius: 100px;
}

.egv__badge--a .egv__bmark {
  background-color: #16A34A;
}

.egv__badge--b .egv__bmark {
  background-color: #8B5CF6;
}

.egv__badge--c .egv__bmark {
  background-color: #E9A23B;
}

.egv__badge.is-on {
  background-color: rgba(22, 163, 74, 0.1);
  box-shadow: inset 0 0 0 1.5px rgba(22, 163, 74, 0.4);
  color: #15803D;
}

.egv__note {
  padding: 11px 12px;
  border-radius: 10px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.08);
  font-size: 10.5px;
  line-height: 1.5;
  color: #5A6070;
}

.egv__foot {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: auto;
}

.egv__award {
  margin-right: auto;
  font-size: 9.5px;
  font-weight: 700;
  color: #15803D;
}

.egv__btn {
  padding: 6px 14px;
  border-radius: 8px;
  background-color: #5B4BE3;
  color: #ffffff;
  font-size: 10px;
  font-weight: 700;
}

@container (max-width: 380px) {
  .egv {
    padding: 18px;
  }

  .egv__foot {
    flex-wrap: wrap;
  }
}

/* ==========================================================================
   AI RESUME SCREENING  (/ai-resume-screening/)
   Two small blocks this page introduces. Everything else on it is existing
   furniture, and both sequence artworks are the ATS page's.
   ========================================================================== */

/* ---- 1. quick recommendations ----
   Not the comparison table. That partial renders paired verdicts with a tick
   on the recommended column, and one of these rows recommends reading the
   applications yourself — a "recommended" pill above it would be marking the
   wrong thing. Scenario, arrow, approach. The tone says which of the three
   kinds of answer it is, so the row that says "manual review" reads as advice
   rather than as the losing half of a comparison. */

.qrec {
  display: grid;
  gap: 10px;
  max-width: 780px;
  margin: 44px auto 0;
  padding: 0;
  list-style: none;
}

.qrec__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 22px minmax(0, 1fr);
  align-items: center;
  gap: 16px;
  padding: 16px 20px;
  border-radius: 16px;
  background-color: #F6F7FA;
  transition: background-color 320ms var(--ease-soft);
}

.qrec__row:hover {
  background-color: #F1F3F8;
}

@media (max-width: 599px) {
  .qrec__row {
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
    text-align: left;
  }

  /* The arrow points across, and across is not where the next line is once
     the row has stacked. */

  .qrec__arrow {
    display: none;
  }
}

.qrec__case {
  font-size: 15px;
  font-weight: 600;
  color: #22262F;
}

.qrec__arrow {
  display: grid;
  place-items: center;
  color: #A6ADBD;
}

.qrec__arrow svg {
  width: 15px;
  height: 15px;
}

.qrec__pick {
  justify-self: start;
  padding: 5px 13px;
  border-radius: 100px;
  font-size: 14px;
  font-weight: 600;
}

/* Three answers, three tones. Manual is the quiet one on purpose: it is real
   advice rather than a lesser option. */

.qrec__pick--manual {
  background-color: #EDF1F4;
  color: #5A6070;
}

.qrec__pick--mixed  {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

.qrec__pick--ai     {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

/* ---- 2. what to look for ----
   A plain three-up grid rather than the marquee: these are the things to check
   before buying anything, including something that is not this, and a set of
   criteria that slides away while you are reading it is a worse set. */

.rsx {
  display: grid;
  gap: 16px;
  margin-top: 44px;
}

@media (min-width: 760px) {
  .rsx {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 18px;
  }
}

/* A white gradient: white at both ends, lifting to the faintest neutral in the
   middle, with one brand glow behind the heading. It is the quiet member of
   the pair — the section reads as its own block without changing colour, which
   is what suits a passage of prose sitting between two white sections.

   Both ends are white on purpose. The joins above and below stay invisible and
   only the middle of the section carries the tone. */

.sec-wash--white {
  background:
    radial-gradient(70% 50% at 50% 0%, rgba(37, 99, 235, 0.055), rgba(37, 99, 235, 0) 70%),
    linear-gradient(180deg, #FFFFFF 0%, #F4F6FB 46%, #F7F9FC 62%, #FFFFFF 100%);
}

/* A tinted ground for one section in a run of white ones. Two faint brand
   washes over a vertical lift that ends in white, so whatever follows still
   has an edge to start against rather than dissolving into the tint.

   Section-agnostic on purpose: it is a ground, not a component, and the next
   section that needs lifting off the white should reuse it rather than grow a
   second one of its own. */

.sec-wash {
  background:
    radial-gradient(85% 60% at 10% 0%, rgba(37, 99, 235, 0.10), rgba(37, 99, 235, 0) 62%),
    radial-gradient(70% 55% at 92% 100%, rgba(139, 92, 246, 0.09), rgba(139, 92, 246, 0) 64%),
    linear-gradient(180deg, #EDF2FE 0%, #F6F9FF 58%, #FFFFFF 100%);
}

.rsx__card {
  padding: 26px 24px 28px;
  border-radius: 20px;
  background-color: #F6F7FA;
  transition: transform 380ms var(--ease-smooth), background-color 380ms var(--ease-soft);
}

.rsx__card:hover {
  transform: translate3d(0, -4px, 0);
  background-color: #F1F3F8;
}

.rsx__icon {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  margin-bottom: 18px;
  border-radius: 13px;
  background-color: rgba(37, 99, 235, 0.1);
  color: #2563EB;
}

.rsx__icon .hs-i {
  width: 21px;
  height: 21px;
}

.rsx__name {
  margin-bottom: 9px;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
  color: #22262F;
}

.rsx__text {
  font-size: 14px;
  line-height: 1.65;
  color: #5A6070;
}

/* The caveat under the three. It is set as an aside rather than a fourth card
   because it is about the choice, not one of the criteria — which is where the
   live page had it, appended to the third card's text. */

.rsx__note {
  max-width: 720px;
  margin: 34px auto 0;
  padding-top: 26px;
  border-top: 1px solid rgba(221, 229, 237, 0.9);
  text-align: center;
  text-wrap: pretty;
  font-size: 14px;
  line-height: 1.7;
  color: #8A90A0;
}

/* ==========================================================================
   FACILITY BOOKING  (/facility-booking-software/)
   The day's timeline in includes/facility-ui.php: four spaces, their bookings
   laid along a 9am to 6pm track, and the utilisation each one adds up to. It
   sits in .hs-hero__frame, so it needs no frame modifier of its own.
   ========================================================================== */

.fbk .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.fbk__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.fbk__title {
  font-size: 13px;
  font-weight: 600;
  color: #22262F;
}

.fbk__chip {
  padding: 2px 9px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.fbk__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 9px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fbk__stat {
  display: flex;
  flex-direction: column;
  padding: 10px 12px;
  border-radius: 11px;
  background-color: #F4F6FB;
}

.fbk__statnum {
  font-size: 19px;
  font-weight: 700;
  line-height: 1.1;
  color: #22262F;
}

.fbk__statnum--good {
  color: #15803D;
}

.fbk__statlab {
  margin-top: 2px;
  font-size: 9.5px;
  font-weight: 500;
  color: #8A90A0;
}

.fbk__caplabel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.fbk__caplabel em {
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: #8A90A0;
}

.fbk__rows {
  display: grid;
  gap: 7px;
}

/* One template, so every space's track starts at the same x and a booking at
   eleven o'clock sits under the one above it. */

.fbk__row {
  display: grid;
  grid-template-columns: 124px minmax(0, 1fr) 30px;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 11px;
  background-color: #F8F9FC;
}

.fbk__copy {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.fbk__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11px;
  font-weight: 600;
  color: #22262F;
}

.fbk__type {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

/* The empty track is the free time, which is the point of the picture: the
   gaps are what an employee is looking for. */

.fbk__track {
  position: relative;
  height: 16px;
  border-radius: 6px;
  background-color: rgba(16, 24, 48, 0.05);
}

.fbk__block {
  position: absolute;
  top: 3px;
  bottom: 3px;
  border-radius: 4px;
  background-color: #2563EB;
}

/* The last row is nearly full, so its blocks read as one bar unless the gap
   between them is drawn. A hairline of sheet does that at any width. */

.fbk__block + .fbk__block {
  box-shadow: -2px 0 0 0 #F8F9FC;
}

.fbk__use {
  text-align: right;
  font-size: 9.5px;
  font-weight: 700;
  color: #5A6070;
}

.fbk__sync {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: auto;
  padding: 11px 12px;
  border-radius: 12px;
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.14);
}

.fbk__syncicon {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 9px;
  background-color: #2563EB;
  color: #ffffff;
}

.fbk__syncicon .hs-i {
  width: 14px;
  height: 14px;
}

.fbk__synctext {
  min-width: 0;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.35;
  color: #22262F;
}

.fbk__synclab {
  display: block;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #2563EB;
}

/* Narrow frame: the space column gives up its width first, since the track is
   the row and the name only has to be identifiable. */

@container (max-width: 380px) {
  .fbk {
    padding: 18px;
  }

  .fbk__row {
    grid-template-columns: 66px minmax(0, 1fr) 28px;
  }

  .fbk__type {
    display: none;
  }
}

/* ==========================================================================
   FACILITY BOOKING PANELS — the five screens in /facility-booking-software/
   The board, the booking form, the rooms table, the add-room form and the
   notification tab. Markup and CSS, sized against their own container, on the
   shared blue box registered above.

   ONE BLOCK, FIVE PANELS
   .fbx is the chrome all five share: the search bar, the tabs, the filter
   pills, the fields, the chips, the toggles and the buttons. Each panel then
   adds only what is its own — the room cards, the table, the notification
   card. Five copies of a search bar would be five places for it to drift.

   All five sit in .sc-panel__frame--fb, so the pinned stage never resizes on a
   handover.
   ========================================================================== */

.fbx .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  min-height: 0;
}

/* ---- the app chrome (includes/facility-chrome-ui.php) ---- */

.fbx__top {
  display: flex;
  align-items: center;
  gap: 10px;
}

.fbx__search {
  display: flex;
  flex: 1;
  align-items: center;
  gap: 7px;
  min-width: 0;
  padding: 6px 8px;
  border-radius: 100px;
  background-color: #F1F4F9;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 9.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.fbx__search svg {
  flex: none;
  width: 12px;
  height: 12px;
}

.fbx__kbd {
  flex: none;
  margin-left: auto;
  padding: 1px 5px;
  border-radius: 5px;
  background-color: #ffffff;
  font-style: normal;
  font-size: 8px;
  font-weight: 700;
  color: #8A90A0;
}

.fbx__me {
  display: flex;
  align-items: center;
  gap: 8px;
}

.fbx__bell {
  position: relative;
  display: grid;
  place-items: center;
  color: #8A90A0;
}

.fbx__bell svg {
  width: 14px;
  height: 14px;
}

.fbx__dot {
  position: absolute;
  top: -1px;
  right: -1px;
  width: 5px;
  height: 5px;
  border-radius: 100px;
  background-color: #DC4444;
}

.fbx__avatar {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 100px;
  background-color: #4F46E5;
  color: #ffffff;
  font-size: 9px;
  font-weight: 700;
}

/* ---- titles ---- */

.fbx__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.fbx__copy {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.fbx__h {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.25;
  color: #22262F;
}

.fbx__sub {
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 9px;
  font-weight: 500;
  line-height: 1.4;
  color: #8A90A0;
}

.fbx__acts {
  display: flex;
  flex: none;
  align-items: center;
  gap: 7px;
}

/* ---- buttons ---- */

.fbx__btn {
  padding: 6px 11px;
  border-radius: 8px;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 700;
}

.fbx__btn--primary {
  background-color: #4F46E5;
  color: #ffffff;
}

.fbx__btn--ghost {
  background-color: #ffffff;
  color: #5A6070;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
}

/* ---- tabs ---- */

.fbx__tabs {
  display: flex;
  gap: 16px;
  padding-bottom: 2px;
  box-shadow: inset 0 -1px 0 0 rgba(16, 24, 48, 0.08);
}

.fbx__tab {
  padding-bottom: 6px;
  font-size: 10px;
  font-weight: 600;
  color: #8A90A0;
}

.fbx__tab.is-on {
  color: #4F46E5;
  box-shadow: inset 0 -2px 0 0 #4F46E5;
}

/* ---- filter pills ---- */

.fbx__filters {
  display: flex;
  align-items: center;
  gap: 6px;
}

.fbx__pill {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 9px;
  border-radius: 8px;
  white-space: nowrap;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.1);
  font-size: 9px;
  font-weight: 600;
  color: #5A6070;
}

.fbx__pill em {
  font-style: normal;
  color: #A6ADBD;
}

.fbx__pill--date {
  font-weight: 700;
  color: #22262F;
}

.fbx__pill--wide {
  flex: 1;
  min-width: 0;
  color: #A6ADBD;
  font-weight: 500;
}

/* The view switch. One of the two is lit, which is how the panel says the
   board is showing a list rather than the timeline the hero draws. */

.fbx__seg {
  display: flex;
  gap: 2px;
  margin-left: auto;
  padding: 2px;
  border-radius: 8px;
  background-color: #F1F4F9;
}

.fbx__segbtn {
  padding: 4px 8px;
  border-radius: 6px;
  font-size: 9px;
  font-weight: 600;
  color: #8A90A0;
}

.fbx__segbtn.is-on {
  background-color: #4F46E5;
  color: #ffffff;
}

/* ---- modal head ---- */

.fbx__modalhead {
  display: flex;
  align-items: center;
  gap: 9px;
  padding-bottom: 10px;
  box-shadow: inset 0 -1px 0 0 rgba(16, 24, 48, 0.08);
}

.fbx__modalicon {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 9px;
  background-color: rgba(79, 70, 229, 0.1);
  color: #4F46E5;
}

.fbx__modalicon svg {
  width: 14px;
  height: 14px;
}

.fbx__modalicon--soft {
  background-color: rgba(79, 70, 229, 0.1);
}

.fbx__x {
  margin-left: auto;
  font-size: 14px;
  color: #A6ADBD;
}

/* ---- fields ---- */

.fbx__grid2,
.fbx__grid3 {
  display: grid;
  gap: 8px;
}

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

.fbx__grid3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.fbx__field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.fbx__lab {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #8A90A0;
}

.fbx__lab em {
  font-style: normal;
  color: #DC4444;
}

.fbx__lab--loose {
  margin-top: 2px;
}

.fbx__input {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 9px;
  border-radius: 8px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
}

/* An empty field, drawn as empty: the placeholder is lighter and lighter
   weight, so a form nobody has filled in does not read as one that is. */

.fbx__input--ghost {
  font-weight: 500;
  color: #A6ADBD;
}

.fbx__input--tall {
  align-items: flex-start;
  min-height: 34px;
}

.fbx__caret {
  margin-left: auto;
  font-style: normal;
  color: #A6ADBD;
}

.fbx__box {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 10px;
  border-radius: 11px;
  background-color: #F6F8FC;
}

.fbx__boxlab {
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #8A90A0;
}

/* ---- chips, checks, toggles ---- */

.fbx__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.fbx__chip {
  padding: 4px 9px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.1);
  font-size: 9px;
  font-weight: 600;
  color: #5A6070;
}

.fbx__chip.is-on {
  background-color: #4F46E5;
  box-shadow: none;
  color: #ffffff;
}

.fbx__checks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 10px;
}

.fbx__checks--wide {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.fbx__check {
  display: flex;
  align-items: center;
  gap: 6px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 9px;
  font-weight: 600;
  color: #5A6070;
}

.fbx__box2 {
  flex: none;
  width: 12px;
  height: 12px;
  border-radius: 4px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.18);
}

/* The tick is drawn rather than typed: a check glyph would pick up the page
   font and sit off-centre in a 12px box. */

.fbx__check.is-on .fbx__box2 {
  position: relative;
  background-color: #4F46E5;
  box-shadow: none;
}

.fbx__check.is-on .fbx__box2::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 4px;
  width: 3px;
  height: 5.5px;
  border: solid #ffffff;
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(42deg);
}

.fbx__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 10px;
  background-color: #F6F8FC;
}

.fbx__rowlab {
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
}

.fbx__toggle {
  position: relative;
  flex: none;
  width: 24px;
  height: 13px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.16);
}

.fbx__toggle::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 9px;
  height: 9px;
  border-radius: 100px;
  background-color: #ffffff;
  transition: left 200ms var(--ease-smooth);
}

.fbx__toggle.is-on {
  background-color: #4F46E5;
}

.fbx__toggle.is-on::after {
  left: 13px;
}

.fbx__foot {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: auto;
  padding-top: 10px;
  box-shadow: inset 0 1px 0 0 rgba(16, 24, 48, 0.08);
}

/* ---- panel 01: the board (includes/facility-board-ui.php) ---- */

.fbd__count {
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.fbd__rooms {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 9px;
  margin-top: 2px;
}

.fbd__room {
  display: flex;
  flex-direction: column;
  padding: 9px;
  border-radius: 12px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.08);
}

/* The tile is drawn, not photographed: a product screenshot's tile is a
   picture of somebody's actual office. */

.fbd__thumb {
  position: relative;
  display: grid;
  place-items: center;
  height: 62px;
  margin-bottom: 8px;
  border-radius: 9px;
  background-color: #EEF0FE;
  color: #6D5BF6;
}

.fbd__glyph {
  width: 26px;
  height: 26px;
}

.fbd__free {
  position: absolute;
  top: 6px;
  left: 6px;
  padding: 2px 6px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.14);
  color: #15803D;
  font-size: 7.5px;
  font-weight: 700;
}

.fbd__name {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 10.5px;
  font-weight: 700;
  color: #22262F;
}

.fbd__type,
.fbd__meta {
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

.fbd__when {
  margin: 4px 0 8px;
  font-size: 8.5px;
  font-weight: 700;
  color: #15803D;
}

.fbd__book {
  margin-top: auto;
  text-align: center;
}

.fbd__count--loose {
  margin-top: 2px;
}

.fbd__mine {
  display: grid;
  gap: 5px;
}

.fbd__bk {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 9px;
  padding: 7px 9px;
  border-radius: 9px;
  background-color: #F8F9FC;
}

.fbd__bkroom {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 9.5px;
  font-weight: 700;
  color: #22262F;
}

.fbd__bkwhen {
  font-size: 9px;
  font-weight: 500;
  color: #5A6070;
}

.fbd__bkstate {
  padding: 2px 7px;
  border-radius: 100px;
  white-space: nowrap;
  font-size: 8px;
  font-weight: 700;
}

.fbd__bkstate--ok   {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.fbd__bkstate--wait {
  background-color: rgba(180, 118, 27, 0.14);
  color: #B4761B;
}

/* ---- panel 03: the rooms table (includes/facility-rooms-ui.php) ---- */

.fbs__table {
  display: grid;
  gap: 5px;
}

.fbs__cols,
.fbs__row {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) 34px minmax(0, 1fr) 34px minmax(0, 0.9fr) 26px;
  align-items: center;
  gap: 8px;
}

.fbs__cols {
  padding: 0 9px;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.fbs__row {
  padding: 8px 9px;
  border-radius: 9px;
  background-color: #F8F9FC;
}

.fbs__name {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 9.5px;
  font-weight: 700;
  color: #22262F;
}

.fbs__code {
  padding: 2px 0;
  border-radius: 5px;
  background-color: rgba(79, 70, 229, 0.1);
  text-align: center;
  font-size: 8px;
  font-weight: 700;
  color: #4F46E5;
}

.fbs__cell {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 9px;
  font-weight: 500;
  color: #5A6070;
}

.fbs__tag {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 100px;
  background-color: #F1F4F9;
  font-style: normal;
  font-size: 8px;
  font-weight: 600;
  color: #5A6070;
}

.fbs__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: auto;
  padding-top: 9px;
  box-shadow: inset 0 1px 0 0 rgba(16, 24, 48, 0.08);
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.fbs__pages {
  padding: 3px 8px;
  border-radius: 100px;
  background-color: #F1F4F9;
  letter-spacing: 0;
  text-transform: none;
  color: #5A6070;
}

/* ---- panel 05: notifications (includes/facility-notify-ui.php) ---- */

.fbt__intro {
  margin: 0;
  font-size: 9.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #5A6070;
}

.fbt__intro em {
  font-style: normal;
  font-weight: 700;
  color: #4F46E5;
}

.fbt__card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 11px;
  border-radius: 12px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.08);
}

.fbt__cardhead {
  display: flex;
  align-items: center;
  gap: 9px;
  padding-bottom: 9px;
  box-shadow: inset 0 -1px 0 0 rgba(16, 24, 48, 0.08);
}

.fbt__name {
  font-size: 10.5px;
  font-weight: 700;
  color: #22262F;
}

.fbt__on {
  margin-left: auto;
  font-size: 9px;
  font-weight: 700;
  color: #15803D;
}

.fbt__pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.fbt__who {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 8px;
  border-radius: 100px;
  background-color: rgba(79, 70, 229, 0.09);
  font-size: 9px;
  font-weight: 600;
  color: #4F46E5;
}

.fbt__who em {
  font-style: normal;
  color: rgba(79, 70, 229, 0.5);
}

.fbt__add {
  padding: 4px 9px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  font-size: 9px;
  font-weight: 600;
  color: #8A90A0;
}

/* Narrow frame: the board's three room cards go to one column and the rooms
   table gives up the columns an admin reads last. */

@container (max-width: 380px) {
  .fbd__rooms {
    grid-template-columns: minmax(0, 1fr);
  }

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

  .fbs__cols,
  .fbs__row {
    grid-template-columns: minmax(0, 1.2fr) 34px minmax(0, 1fr) 26px;
  }

  .fbs__cols span:nth-child(4),
  .fbs__cols span:nth-child(5),
  .fbs__row .fbs__cell:nth-of-type(2),
  .fbs__row .fbs__cell:nth-of-type(3) {
    display: none;
  }
}

/* ==========================================================================
   SKILL MATRIX ARTWORKS — /skill-matrix/

   Three drawn interfaces: the grid itself in the hero (.skm), one employee
   against the levels their role requires (.skg), and the Skills Catalog beside
   the benefits list (.skc). All three sit in the blue box registered above, so
   every rule here assumes the near-white sheet .sc-sheet paints.

   ONE PALETTE ACROSS ALL THREE
   Green means the required level is met, amber means one level short, red
   means further than that. Nothing else on these three uses those hues, so a
   colour never means two things. The tones are the nine-box grid's, held at
   the same alphas, because a green cell here and a green box on the succession
   page are the same verdict.

   Sizes are the small end of the type scale on purpose. These are pictures of
   an interface at a distance, not an interface: at reading size the grid would
   need a horizontal scrollbar inside the hero frame, and a screenshot with a
   scrollbar in it reads as broken rather than as wide.
   ========================================================================== */

/* ==========================================================================
   01 — the matrix, in the hero
   ========================================================================== */

.skm__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
}

.skm__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
}

.skm__chips {
  display: flex;
  gap: 6px;
  margin-left: auto;
}

.skm__chip {
  padding: 3px 9px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.skm__chip--on {
  background-color: rgba(37, 99, 235, 0.1);
  box-shadow: none;
  color: #2563EB;
}

/* The grid is one CSS grid rather than a row of rows: the columns have to line
   up across every employee, and a per-row flexbox lines them up only as long
   as no two names are different lengths. --skm-cols is set on the element from
   the number of skills, so adding a sixth column in the PHP needs no CSS. */

.skm__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(var(--skm-cols, 5), minmax(0, 1fr));
  gap: 5px;
  margin-top: 12px;
}

.skm__corner {
  display: flex;
  align-items: flex-end;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.skm__col {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: center;
  padding-bottom: 4px;
  text-align: center;
}

.skm__colname {
  font-size: 9px;
  font-weight: 700;
  color: #22262F;
  line-height: 1.2;
  /* A skill name is one word and one word does not wrap. At the hero's own
     width every column head fits; in the narrow container below it, "Communication"
     is wider than its cell and would run over the neighbouring column. Breaking
     inside the word is the only thing that keeps the grid's columns aligned,
     and the required level under it stays on its own line either way. */
  overflow-wrap: anywhere;
}

/* The required level, printed under every column head. Without it the grid is
   a list of ratings with nothing to compare them against. */

.skm__need {
  font-size: 8px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.skm__who {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  padding: 5px 0;
}

.skm__av {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  font-size: 8px;
  font-weight: 700;
  color: #2563EB;
}

.skm__whotext {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.skm__name {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.skm__team {
  font-size: 8px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.skm__cell {
  display: grid;
  place-items: center;
  min-height: 30px;
  border-radius: 8px;
  font-size: 9.5px;
  font-weight: 700;
}

.skm__cell--ok   {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.skm__cell--near {
  background-color: rgba(233, 162, 59, 0.18);
  color: #B45309;
}

.skm__cell--gap  {
  background-color: rgba(220, 38, 38, 0.1);
  color: #B91C1C;
}

.skm__foot {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid rgba(16, 24, 48, 0.08);
}

.skm__key {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
}

.skm__dot {
  width: 7px;
  height: 7px;
  border-radius: 100px;
}

/* Every dot but the first one needs air in front of it, because the label it
   belongs to sits after it and the label before it sits in front. */

.skm__dot + .skm__dot,
.skm__key .skm__dot ~ .skm__dot {
  margin-left: 6px;
}

.skm__dot--ok   {
  background-color: #16A34A;
}

.skm__dot--near {
  background-color: #E9A23B;
}

.skm__dot--gap  {
  background-color: #DC2626;
}

.skm__count {
  margin-left: auto;
  padding: 3px 9px;
  border-radius: 100px;
  background-color: rgba(220, 38, 38, 0.09);
  font-size: 8.5px;
  font-weight: 700;
  color: #B91C1C;
  white-space: nowrap;
}

/* ==========================================================================
   02 — one employee's gaps
   ========================================================================== */

.skg__head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding-bottom: 11px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.skg__av {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  font-size: 10px;
  font-weight: 700;
  color: #2563EB;
}

.skg__id {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.skg__name {
  font-size: 12px;
  font-weight: 700;
  color: #0B0D12;
}

.skg__role {
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.skg__badge {
  margin-left: auto;
  padding: 4px 10px;
  border-radius: 100px;
  background-color: rgba(220, 38, 38, 0.09);
  font-size: 9px;
  font-weight: 700;
  color: #B91C1C;
  white-space: nowrap;
}

.skg__row {
  display: grid;
  grid-template-columns: minmax(0, 78px) minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  margin-top: 13px;
}

.skg__skill {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.skg__track {
  position: relative;
  height: 9px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.06);
}

.skg__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w);
  border-radius: 100px;
}

.skg__fill--ok   {
  background-color: #16A34A;
}

.skg__fill--near {
  background-color: #E9A23B;
}

.skg__fill--gap  {
  background-color: #DC2626;
}

/* The required level, as a mark across the track. A bar that stops before its
   notch is a gap the reader sees without reading either number. */

.skg__notch {
  position: absolute;
  top: -3px;
  bottom: -3px;
  left: var(--x);
  width: 2px;
  margin-left: -1px;
  border-radius: 100px;
  background-color: #0B0D12;
}

.skg__nums {
  display: flex;
  align-items: baseline;
  gap: 2px;
  font-size: 9px;
  font-weight: 700;
}

.skg__have--ok   {
  color: #15803D;
}

.skg__have--near {
  color: #B45309;
}

.skg__have--gap  {
  color: #B91C1C;
}

.skg__sep {
  color: #C7CCD8;
  font-weight: 500;
}

.skg__req {
  color: #8A90A0;
}

.skg__foot {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 16px;
  padding-top: 11px;
  border-top: 1px solid rgba(16, 24, 48, 0.08);
}

.skg__note {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.skg__cta {
  margin-left: auto;
  padding: 5px 11px;
  border-radius: 100px;
  background-color: #2563EB;
  font-size: 9px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}

/* ==========================================================================
   03 — the Skills Catalog
   ========================================================================== */

.skc__head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.skc__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
}

.skc__search {
  margin-left: auto;
  padding: 5px 12px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  font-size: 9px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
}

.skc__add {
  padding: 5px 11px;
  border-radius: 100px;
  background-color: #2563EB;
  font-size: 9px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}

.skc__cats {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 11px;
}

.skc__cat {
  padding: 3px 10px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.05);
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
}

.skc__cat.is-on {
  background-color: rgba(37, 99, 235, 0.1);
  color: #2563EB;
}

.skc__cols,
.skc__row {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 0.9fr) 30px;
  align-items: center;
  gap: 8px;
}

.skc__cols {
  margin-top: 13px;
  padding-bottom: 7px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.skc__row {
  padding: 9px 0;
  border-bottom: 1px solid rgba(16, 24, 48, 0.05);
}

/* A retired skill is still on the list, dimmed rather than deleted, which is
   the behaviour the copy beside this claims. */

.skc__row--off {
  opacity: 0.5;
}

.skc__name {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.skc__tag {
  justify-self: start;
  padding: 3px 8px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
  white-space: nowrap;
}

.skc__tag--technical   {
  background-color: rgba(37, 99, 235, 0.1);
  color: #2563EB;
}

.skc__tag--functional  {
  background-color: rgba(20, 184, 166, 0.13);
  color: #0F766E;
}

.skc__tag--behavioural {
  background-color: rgba(139, 92, 246, 0.12);
  color: #6D28D9;
}

.skc__use {
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
  white-space: nowrap;
}

.skc__sw {
  position: relative;
  justify-self: end;
  width: 26px;
  height: 14px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.15);
}

.skc__sw.is-on {
  background-color: #16A34A;
}

.skc__knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 10px;
  height: 10px;
  border-radius: 100px;
  background-color: #ffffff;
}

.skc__sw.is-on .skc__knob {
  left: auto;
  right: 2px;
}

/* Narrow frame: the matrix gives up the department under each name and the
   catalog gives up the column an admin reads last. The grid itself keeps every
   skill column — dropping one would be dropping the point of the picture. */

@container (max-width: 380px) {
  .skm__team {
    display: none;
  }

  /* "needs L3" is wider than a column once the frame narrows. Let it stack
     onto two lines rather than dropping it: the required level is the reason
     the column head is there. */

  .skm__need {
    white-space: normal;
    text-align: center;
  }

  .skm__chips {
    display: none;
  }

  .skm__grid {
    gap: 4px;
  }

  .skm__cell {
    min-height: 26px;
  }

  .skc__cols,
  .skc__row {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) 30px;
  }

  .skc__cols span:nth-child(3),
  .skc__use {
    display: none;
  }

  .skg__row {
    grid-template-columns: minmax(0, 66px) minmax(0, 1fr) auto;
  }
}

/* ==========================================================================
   THE SKILL MATRIX SEQUENCE — six drawn screens, /skill-matrix/

   .skl the matrix list, .skr that matrix opened, .skn the create form, .skd
   the Skills Catalog drawer, .skp the competency matrix form, .skv the
   proficiency descriptors. All six sit in the blue box registered above, so
   every rule here assumes the near-white sheet .sc-sheet paints.

   ONE SHARED HEIGHT
   Stacked in a single grid cell, six natural heights would resize the pinned
   stage on every handover. .sc-panel__frame--sk sets the floor; see the note
   beside it.

   INDIGO, NOT THE BLUE THE OTHER SEQUENCES USE
   This product's own chrome is indigo and violet, and the drawings follow it
   so the sequence reads as one application rather than six. The verdict
   colours are the exception: green, amber and red mean met, one short and gap
   here exactly as they do in the hero grid at the top of the page.
   ========================================================================== */

/* The frame the six share. No background of its own beyond the blue box each
   root already paints — the min-height is the whole job, and it is measured
   against the tallest of the six (the opened grid) rather than inherited from
   a page whose artwork is a different size. */

.sc-panel__frame--sk {
  display: flex;
  min-height: 470px;
  background-color: #DCE4F6;
}

.sc-panel__frame--sk > * {
  flex: 1;
  min-height: 0;
}

/* ==========================================================================
   01 — the matrix list
   ========================================================================== */

.skl__head {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.skl__h1 {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #0B0D12;
}

.skl__sub {
  font-size: 9px;
  font-weight: 500;
  line-height: 1.45;
  color: #8A90A0;
}

/* The tab bar is .scr__tabs, the one the succession panels introduced, so a
   tab here and a tab there are the same object. Only the indigo is this
   page's. */

.skl__tabs {
  margin-top: 11px;
}

.skl .scr__tab.is-on {
  color: #5B4BE0;
}

.skl .scr__tab.is-on::after {
  background-color: #5B4BE0;
}

.skl__bar {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-top: 13px;
}

.skl__barcopy {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.skl__h2 {
  font-size: 12px;
  font-weight: 700;
  color: #22262F;
}

.skl__note {
  font-size: 9px;
  font-weight: 500;
  color: #A6ADBD;
}

.skl__tools {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-left: auto;
}

.skl__ghost,
.skl__go {
  padding: 6px 11px;
  border-radius: 100px;
  font-size: 9.5px;
  font-weight: 600;
  white-space: nowrap;
}

.skl__ghost {
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(91, 75, 224, 0.25);
  color: #5B4BE0;
}

.skl__go {
  background-image: linear-gradient(150deg, #7C6BF8 0%, #5B4BE0 100%);
  color: #ffffff;
}

.skl__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-top: 13px;
}

.skl__card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 12px 13px;
  border-radius: 12px;
  background-color: #ffffff;
  box-shadow:
    inset 0 0 0 1px rgba(16, 24, 48, 0.07),
    0 6px 18px -14px rgba(16, 24, 48, 0.5);
}

.skl__name {
  padding-right: 18px;
  font-size: 11px;
  font-weight: 700;
  color: #5B4BE0;
}

.skl__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
}

.skl__stat {
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
  white-space: nowrap;
}

.skl__stat--date {
  color: #A6ADBD;
}

.skl__bin {
  position: absolute;
  top: 11px;
  right: 11px;
  width: 12px;
  height: 12px;
  color: #C7CCD8;
}

.skl__bin svg {
  width: 100%;
  height: 100%;
}

/* ==========================================================================
   02 — that matrix, opened
   ========================================================================== */

.skr__top {
  display: flex;
  align-items: center;
  gap: 9px;
}

.skr__brand {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.skr__search {
  flex: 1;
  min-width: 0;
  padding: 5px 11px;
  border-radius: 100px;
  background-color: #F4F5FA;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.skr__acts {
  display: flex;
  align-items: center;
  gap: 6px;
}

.skr__ghost,
.skr__go {
  padding: 5px 10px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
  white-space: nowrap;
}

.skr__ghost {
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  color: #5A6070;
}

.skr__go {
  background-image: linear-gradient(150deg, #7C6BF8 0%, #5B4BE0 100%);
  color: #ffffff;
}

.skr__filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 11px;
}

.skr__filter {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  border-radius: 7px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.1);
  font-size: 8.5px;
  font-weight: 600;
  color: #5A6070;
  white-space: nowrap;
}

.skr__caret {
  color: #A6ADBD;
  font-size: 7px;
}

/* ---- the legend ----
   The scale it describes is the cell shading below, so the swatches ARE those
   five backgrounds rather than five values written twice. */

.skr__key {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 11px;
  margin-top: 11px;
}

.skr__keyitem {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 8px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.skr__swatch {
  width: 9px;
  height: 9px;
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.06);
}

/* ---- the grid ----
   A real CSS grid rather than a row of rows: the columns have to line up
   across every employee, and a per-row flexbox lines them up only as long as
   no two names are the same length. --skr-cols is set on the element from the
   number of skills, so a fifth column needs no CSS. */

.skr__table {
  display: grid;
  /* Widths measured against the widest label in each column at the frame's
     own width, not guessed: "Communication" needs 60px of skill column at
     8.5px, and it is the one that decides the layout. */
  grid-template-columns:
    minmax(0, 1.15fr)
    repeat(var(--skr-cols, 4), minmax(0, 1fr))
    minmax(0, 0.72fr) minmax(0, 0.78fr);
  gap: 5px;
  margin-top: 12px;
}

.skr__th {
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
  overflow-wrap: anywhere;
}

.skr__th--mid {
  text-align: center;
  /* A skill name, not a column label. In caps with tracking "Communication"
     is wider than its cell and breaks mid-word; sentence case reads as the
     thing it names.

     8px, measured: the column is 64.7px at the frame width and the word wants
     65.8px at 8.5. It is the longest label in the set, so it is the one that
     decides the size. */
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: #5A6070;
}

.skr__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 4px 0;
}

.skr__name {
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.skr__code {
  font-size: 7.5px;
  font-weight: 500;
  color: #C0C5D2;
}

/* One scale in five steps, palest to solid. Written as a ramp rather than five
   picked tints so a column reads as a gradient — which is the only reason to
   shade a number at all. */

.skr__cell {
  display: grid;
  place-items: center;
  min-height: 31px;
  border-radius: 7px;
  font-size: 9.5px;
  font-weight: 700;
  color: #3A4050;
}

.skr__cell--0 {
  background-color: rgba(91, 75, 224, 0.04);
  color: #B0B5C2;
}

.skr__cell--1 {
  background-color: rgba(91, 75, 224, 0.10);
}

.skr__cell--2 {
  background-color: rgba(91, 75, 224, 0.22);
}

.skr__cell--3 {
  background-color: rgba(91, 75, 224, 0.48);
  color: #ffffff;
}

.skr__cell--4 {
  background-color: rgba(91, 75, 224, 0.90);
  color: #ffffff;
}

.skr__min {
  display: grid;
  place-items: center;
}

/* The verdict colours, the hero legend's exactly: met, one short, gap. */

.skr__chip {
  display: grid;
  place-items: center;
  min-width: 19px;
  padding: 3px 5px;
  border-radius: 6px;
  font-size: 9px;
  font-weight: 700;
}

.skr__chip--ok   {
  background-color: rgba(22, 163, 74, 0.14);
  color: #15803D;
}

.skr__chip--near {
  background-color: rgba(233, 162, 59, 0.22);
  color: #B45309;
}

.skr__chip--gap  {
  background-color: rgba(220, 38, 38, 0.12);
  color: #B91C1C;
}

.skr__req {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 3px 6px;
  border-radius: 6px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  font-size: 9px;
  font-weight: 600;
  color: #3A4050;
}

/* ==========================================================================
   03, 04, 05 — the drawer over the dimmed page
   ========================================================================== */

.skf__sheet {
  position: relative;
  display: flex;
  overflow: hidden;
  padding: 0;
}

/* The page underneath. Bars, not text: it is out of focus in the product and
   it is out of focus here. */

.skf__back {
  display: flex;
  flex-direction: column;
  gap: 9px;
  width: 38%;
  padding: 16px 14px;
  background-color: #E7E8EE;
}

.skf__bar {
  height: 8px;
  border-radius: 100px;
  background-color: #C6C9D4;
}

.skf__bar--dark  {
  background-color: #A8ACBB;
}

.skf__bar--brand {
  background-color: #A9A0EE;
}

.skf__bar--w25 {
  width: 25%;
}

.skf__bar--w30 {
  width: 30%;
}

.skf__bar--w35 {
  width: 35%;
}

.skf__bar--w40 {
  width: 40%;
}

.skf__bar--w45 {
  width: 45%;
}

.skf__bar--w60 {
  width: 60%;
}

.skf__bar--w70 {
  width: 70%;
}

.skf__bar--w80 {
  width: 80%;
}

.skf__bar--w85 {
  width: 85%;
}

.skf__row {
  display: flex;
  gap: 8px;
  width: 100%;
}

.skf__row .skf__bar {
  flex: none;
}

.skf__card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
  padding: 11px;
  border-radius: 10px;
  background-color: #D3D6DE;
}

/* The panel itself. Slides in from the right when its step comes round; see
   the entrance block at the foot of this section. */

.skf__panel {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  padding: 16px 15px;
  background-color: #FFFFFF;
  box-shadow: -14px 0 34px -22px rgba(16, 24, 48, 0.5);
}

.skf__head {
  display: flex;
  align-items: center;
  gap: 10px;
}

.skf__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
}

.skf__x {
  width: 12px;
  height: 12px;
  margin-left: auto;
  color: #A6ADBD;
}

.skf__x svg {
  width: 100%;
  height: 100%;
}

.skf__note {
  margin: 6px 0 0;
  font-size: 8.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #8A90A0;
}

.skf__body {
  display: flex;
  flex-direction: column;
  gap: 11px;
  margin-top: 13px;
}

.skf__field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.skf__field--split {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

.skf__field--split .skf__input {
  flex: 1;
  min-width: 0;
}

.skf__label {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 8.5px;
  font-weight: 600;
  color: #3A4050;
}

.skf__label--flat {
  flex: 1;
  min-width: 0;
}

.skf__label em {
  font-style: normal;
  color: #DC2626;
}

/* Two classes deep on purpose: .skf__label em above is the red asterisk on a
   required field, and a single class ties with it. The count is not a
   requirement marker and must not be red. */

.skf__label em.skf__count {
  margin-left: auto;
  font-style: normal;
  font-weight: 500;
  color: #A6ADBD;
}

.skf__input {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 10px;
  border-radius: 8px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.13);
  font-size: 9px;
  font-weight: 500;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.skf__input--ghost {
  color: #A6ADBD;
}

.skf__input--area {
  align-items: flex-start;
  min-height: 42px;
}

.skf__input--select {
  justify-content: space-between;
}

/* The one focused field on the page, which is where a form opens. */

.skf__input--focus {
  box-shadow: inset 0 0 0 1.5px #5B4BE0;
}

.skf__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.skf__chip {
  padding: 4px 9px;
  border-radius: 100px;
  background-color: #F4F5FA;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.08);
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.skf__chip.is-on {
  background-color: rgba(91, 75, 224, 0.1);
  box-shadow: none;
  color: #5B4BE0;
}

.skf__add {
  flex: none;
  padding: 7px 12px;
  border-radius: 8px;
  background-color: #5B4BE0;
  font-size: 9px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}

.skf__add--ghost {
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(91, 75, 224, 0.25);
  color: #5B4BE0;
}

.skf__sw {
  position: relative;
  flex: none;
  width: 26px;
  height: 14px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.15);
}

.skf__sw.is-on {
  background-color: #5B4BE0;
}

.skf__knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 10px;
  height: 10px;
  border-radius: 100px;
  background-color: #ffffff;
}

.skf__sw.is-on .skf__knob {
  left: auto;
  right: 2px;
}

.skf__search {
  display: flex;
  align-items: center;
  padding: 7px 11px;
  border-radius: 100px;
  background-color: #F4F5FA;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.08);
  font-size: 9px;
  font-weight: 500;
  color: #A6ADBD;
}

/* Pushed to the bottom of the panel by the auto margin, so the three drawers
   put their buttons on the same line whatever their fields add up to. */

.skf__foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin-top: auto;
  padding-top: 14px;
}

.skf__cancel {
  padding: 7px 14px;
  border-radius: 8px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.13);
  font-size: 9px;
  font-weight: 600;
  color: #5A6070;
}

.skf__go {
  padding: 7px 16px;
  border-radius: 8px;
  background-image: linear-gradient(150deg, #7C6BF8 0%, #5B4BE0 100%);
  font-size: 9px;
  font-weight: 600;
  color: #ffffff;
}

/* ---- 04, the catalog rows inside that drawer ---- */

.skd__cols,
.skd__row {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 0.9fr) minmax(0, 1.3fr) minmax(0, 0.6fr);
  align-items: center;
  gap: 8px;
}

.skd__cols {
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.skd__row {
  padding: 8px 0;
  border-bottom: 1px solid rgba(16, 24, 48, 0.05);
}

/* Dimmed rather than dropped: the line above this table promises that an
   inactive skill stays, and a table that hid it would contradict it. */

.skd__row--off {
  opacity: 0.5;
}

.skd__name {
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.skd__tag {
  justify-self: start;
  padding: 3px 8px;
  border-radius: 100px;
  font-size: 8px;
  font-weight: 600;
  white-space: nowrap;
}

.skd__tag--technical   {
  background-color: rgba(91, 75, 224, 0.1);
  color: #5B4BE0;
}

.skd__tag--behavioural {
  background-color: rgba(20, 184, 166, 0.13);
  color: #0F766E;
}

.skd__desc {
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.skd__state {
  justify-self: start;
  font-size: 8.5px;
  font-weight: 700;
  white-space: nowrap;
}

.skd__state--on  {
  color: #15803D;
}

.skd__state--off {
  color: #A6ADBD;
}

/* ==========================================================================
   06 — the proficiency descriptors

   A centred modal rather than a side drawer, because that is what adding a
   competency is in the product: it happens on top of the catalog, not beside
   it. Its own composition, so it shares .skf__ parts but not .skf__sheet.
   ========================================================================== */

.skv__sheet {
  position: relative;
  overflow: hidden;
  padding: 0;
}

.skv__back {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: 100%;
  padding: 18px 16px;
  background-color: #E7E8EE;
}

.skv__modal {
  position: absolute;
  inset: 16px 14px;
  display: flex;
  flex-direction: column;
  padding: 15px 15px 0;
  border-radius: 14px;
  background-color: #ffffff;
  box-shadow: 0 26px 60px -26px rgba(16, 24, 48, 0.6);
}

.skv__pair {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  gap: 10px;
  margin-top: 13px;
}

.skv__legend {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 13px;
}

.skv__legendtitle {
  font-size: 9.5px;
  font-weight: 700;
  color: #22262F;
}

.skv__legendnote {
  font-size: 8px;
  font-weight: 500;
  line-height: 1.45;
  color: #A6ADBD;
}

/* The list runs under the footer and is masked rather than cut. A list ending
   flush at the last visible row reads as a list with four levels rather than
   one that carries on. */

.skv__levels {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
  /* Takes the rest of the modal, so the fade lands where the footer starts
     rather than partway up a short list with empty sheet under it. */
  flex: 1;
  min-height: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 74%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0%, #000 74%, transparent 100%);
}

.skv__level {
  display: grid;
  grid-template-columns: 74px minmax(0, 1fr);
  align-items: center;
  gap: 9px;
}

.skv__num {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.skv__dot {
  flex: none;
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  border-radius: 100px;
  background-color: #5B4BE0;
  font-size: 8.5px;
  font-weight: 700;
  color: #ffffff;
}

.skv__tier {
  font-size: 7.5px;
  font-weight: 600;
  line-height: 1.25;
  color: #8A90A0;
}

/* Over the mask, so the buttons stay solid while the list fades under them. */

.skv__foot {
  position: relative;
  z-index: 1;
  padding-bottom: 15px;
  background-color: #ffffff;
}

/* ==========================================================================
   ENTRANCE

   Gated on `.sc-panel.is-showing`, not on the site's .reveal observer: inside
   a pinned stage a panel is shown and hidden repeatedly as the reader scrolls
   back and forth, and .reveal fires once and unobserves. This replays every
   time the step comes round, in either direction, with no state to keep. --i
   is authored on each row.
   ========================================================================== */

.skl__card,
.skr__who,
.skr__cell,
.skr__min,
.skr__req,
.skf__body > *,
.skv__pair,
.skv__legend,
.skv__level {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition:
    opacity 460ms var(--ease-smooth),
    transform 560ms var(--ease-smooth);
  transition-delay: calc(180ms + var(--i, 0) * 65ms);
}

/* The grid's cells arrive with their row rather than one by one: twenty-four
   separately delayed cells is a wave, not an entrance. */

.skr__cell,
.skr__min,
.skr__req {
  transition-delay: calc(220ms + var(--i, 0) * 65ms);
}

.sc-panel.is-showing .skl__card,
.sc-panel.is-showing .skr__who,
.sc-panel.is-showing .skr__cell,
.sc-panel.is-showing .skr__min,
.sc-panel.is-showing .skr__req,
.sc-panel.is-showing .skf__body > *,
.sc-panel.is-showing .skv__pair,
.sc-panel.is-showing .skv__legend,
.sc-panel.is-showing .skv__level {
  opacity: 1;
  transform: none;
}

/* The drawer slides in over the page it covers, which is the one movement
   these three panels are actually about. */

.skf__panel,
.skv__modal {
  opacity: 0;
  transform: translate3d(14px, 0, 0);
  transition:
    opacity 420ms var(--ease-smooth),
    transform 520ms var(--ease-smooth);
}

.skv__modal {
  transform: translate3d(0, 12px, 0);
}

.sc-panel.is-showing .skf__panel,
.sc-panel.is-showing .skv__modal {
  opacity: 1;
  transform: none;
}

/* Pin off: no sequence to arrive with, so everything is simply there. */

@media (max-width: 1023.98px) {
  .skl__card,
  .skr__who,
  .skr__cell,
  .skr__min,
  .skr__req,
  .skf__body > *,
  .skf__panel,
  .skv__pair,
  .skv__legend,
  .skv__level,
  .skv__modal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Narrow frame: the two columns a reader checks last come out, and the list
   cards go to one column. The skill columns stay — dropping one would be
   dropping the point of the picture. */

@container (max-width: 380px) {
  .skl__grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .skl__tools {
    flex-direction: column;
    align-items: flex-end;
  }

  .skr__code,
  .skr__acts .skr__ghost {
    display: none;
  }

  /* The required column goes, not a skill column: dropping a skill would be
     dropping the point of the picture. */

  .skr__table {
    grid-template-columns:
      minmax(0, 1.08fr)
      repeat(var(--skr-cols, 4), minmax(0, 0.9fr))
      minmax(0, 0.66fr);
  }

  .skr__th:last-child,
  .skr__req {
    display: none;
  }

  .skf__back {
    display: none;
  }

  .skd__cols,
  .skd__row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr) minmax(0, 0.7fr);
  }

  .skd__cols span:nth-child(3),
  .skd__desc {
    display: none;
  }

  .skv__pair {
    grid-template-columns: minmax(0, 1fr);
  }

  .skv__level {
    grid-template-columns: 62px minmax(0, 1fr);
  }
}

/* ==========================================================================
   THE TIMESHEET ARTWORKS — /employee-timesheet-software/

   .tsw the condensed week in the hero, .tsl that week in full, .tsp the
   projects table, .tsr the summary report, .tsu the utilisation report. All
   five sit in the blue box registered above, so every rule here assumes the
   near-white sheet .sc-sheet paints.

   .tsl, .tsp, .tsr and .tsu share .tsw__ parts wherever they draw the same
   object — the title, the status pills, the stat tiles, the billable flag, the
   week grid. Five copies of a stat tile would be five places for its padding
   to drift, and these five sit within one screen of each other.

   ONE MEANING PER COLOUR
   Blue is logged time, green is billable, amber is overtime or over-capacity,
   grey is a nil value. Nothing else on these five uses those hues, so a colour
   never means two things across the sequence.
   ========================================================================== */

/* The frame the four sequence panels share. Measured against the tallest of
   them, which is the summary report at five roster rows plus its tiles. */

.sc-panel__frame--ts {
  display: flex;
  min-height: 440px;
  background-color: #DCE4F6;
}

.sc-panel__frame--ts > * {
  flex: 1;
  min-height: 0;
}

/* ==========================================================================
   Shared chrome
   ========================================================================== */

.tsw__bar,
.tsp__bar {
  display: flex;
  align-items: center;
  gap: 10px;
}

.tsw__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.tsw__week {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px;
  border-radius: 100px;
  background-color: #F4F6FB;
  font-size: 9px;
  font-weight: 600;
  color: #3A4050;
  white-space: nowrap;
}

.tsw__chev {
  color: #A6ADBD;
}

.tsw__pill {
  margin-left: auto;
  padding: 3px 9px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 700;
  white-space: nowrap;
}

/* Three states, three colours AND three words. The word carries it: at this
   size a small difference in hue is not a distinction anyone can rely on, and
   the pills are decoration inside an aria-hidden illustration. */

.tsw__pill--draft    {
  background-color: rgba(16, 24, 48, 0.07);
  color: #5A6070;
}

.tsw__pill--pending  {
  background-color: rgba(233, 162, 59, 0.18);
  color: #B45309;
}

.tsw__pill--approved {
  background-color: rgba(22, 163, 74, 0.13);
  color: #15803D;
}

/* ---- the stat tiles ---- */

.tsw__tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.tsl__tiles {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.tsw__tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 11px;
  border-radius: 10px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.tsw__amount {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.tsw__label {
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  white-space: nowrap;
}

.tsw__tile--logged {
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: none;
}

.tsw__tile--logged .tsw__amount {
  color: #1D4ED8;
}

.tsw__tile--bill {
  background-color: rgba(22, 163, 74, 0.09);
  box-shadow: none;
}

.tsw__tile--bill .tsw__amount {
  color: #15803D;
}

.tsw__tile--ot {
  background-color: rgba(233, 162, 59, 0.14);
  box-shadow: none;
}

.tsw__tile--ot .tsw__amount {
  color: #B45309;
}

/* ---- the billable flag ---- */

.tsw__flag {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 100px;
  font-style: normal;
  font-size: 7.5px;
  font-weight: 700;
  white-space: nowrap;
}

.tsw__flag--bill {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.tsw__flag--non  {
  background-color: rgba(16, 24, 48, 0.06);
  color: #8A90A0;
}

/* ==========================================================================
   01 — the week grid, hero and panel 01

   A real CSS grid rather than a row of rows: the day columns have to line up
   across every project, and a per-row flexbox lines them up only as long as no
   two project names are the same length.
   ========================================================================== */

.tsw__grid {
  display: grid;
  grid-template-columns:
    minmax(0, 1.75fr)
    repeat(5, minmax(0, 0.62fr))
    minmax(0, 0.82fr);
  gap: 5px;
  align-items: center;
  margin-top: 13px;
}

.tsw__th {
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  text-align: center;
  white-space: nowrap;
}

.tsw__th--proj {
  text-align: left;
}

.tsw__proj {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  padding: 5px 0;
}

.tsw__name {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tsw__act {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 8px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
}

/* The hours cell reads as an input, because in the product it is one. */

.tsw__cell {
  display: grid;
  place-items: center;
  min-height: 28px;
  border-radius: 7px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.1);
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
}

.tsw__cell--nil {
  background-color: rgba(16, 24, 48, 0.03);
  box-shadow: none;
  color: #C7CCD8;
}

.tsw__tot {
  text-align: center;
  font-size: 9.5px;
  font-weight: 700;
  color: #1D4ED8;
  white-space: nowrap;
}

/* ---- panel 01 only ---- */

.tsl__views {
  display: flex;
  gap: 4px;
  margin-left: auto;
  padding: 3px;
  border-radius: 100px;
  background-color: #F4F6FB;
}

.tsl__view {
  padding: 3px 9px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.tsl__view.is-on {
  background-color: #ffffff;
  color: #1D4ED8;
}

/* The totals line under the grid. Spans the whole row set by living in the
   same grid, so its columns are the day columns by construction. */

.tsl__sumlabel {
  padding-top: 8px;
  border-top: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.tsl__sum {
  padding-top: 8px;
  border-top: 1px solid rgba(16, 24, 48, 0.08);
  text-align: center;
  font-size: 9.5px;
  font-weight: 700;
  color: #3A4050;
}

/* A day past the eight hours a forty-hour week implies. Marked rather than
   corrected: it is a real state, and hiding it would make the picture a
   picture of a week nobody works. */

.tsl__sum--over  {
  color: #B45309;
}

.tsl__sum--grand {
  color: #1D4ED8;
}

.tsl__foot {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 14px;
  padding-top: 11px;
  border-top: 1px solid rgba(16, 24, 48, 0.08);
}

.tsl__ghost {
  padding: 6px 11px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  font-size: 9px;
  font-weight: 600;
  color: #5A6070;
  white-space: nowrap;
}

.tsl__go {
  margin-left: auto;
  padding: 6px 13px;
  border-radius: 100px;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  font-size: 9px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}

/* ==========================================================================
   02 — projects and activities
   ========================================================================== */

.tsp__search {
  flex: 1;
  min-width: 0;
  padding: 5px 11px;
  border-radius: 100px;
  background-color: #F4F6FB;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
  font-size: 9px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tsp__go {
  margin-left: 0;
}

.tsp__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.25fr) minmax(0, 1.1fr) minmax(0, 1fr)
    minmax(0, 0.95fr) minmax(0, 0.95fr);
  gap: 6px 8px;
  align-items: center;
  margin-top: 14px;
}

.tsp__th {
  padding-bottom: 7px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  white-space: nowrap;
}

.tsp__th--num {
  text-align: right;
}

.tsp__name,
.tsp__cell,
.tsp__flagcell {
  min-width: 0;
  padding: 7px 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tsp__name {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
}

.tsp__cell {
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

/* An inactive project is dimmed rather than dropped, which is the behaviour
   the copy beside this claims. */

.tsp__name.is-off,
.tsp__cell.is-off,
.tsp__flagcell.is-off {
  opacity: 0.5;
}

.tsp__state {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 0;
}

.tsp__sw {
  position: relative;
  flex: none;
  width: 24px;
  height: 13px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.15);
}

.tsp__sw.is-on {
  background-color: #16A34A;
}

.tsp__knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 9px;
  height: 9px;
  border-radius: 100px;
  background-color: #ffffff;
}

.tsp__sw.is-on .tsp__knob {
  left: auto;
  right: 2px;
}

.tsp__word {
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.tsp__sw.is-on + .tsp__word {
  color: #15803D;
}

/* ==========================================================================
   03 — the summary report
   ========================================================================== */

.tsr__range {
  padding: 4px 10px;
  border-radius: 100px;
  background-color: #F4F6FB;
  font-size: 9px;
  font-weight: 600;
  color: #3A4050;
  white-space: nowrap;
}

.tsr__exports {
  display: flex;
  gap: 6px;
  margin-left: auto;
}

.tsr__exports .tsl__ghost {
  padding: 5px 10px;
  font-size: 8.5px;
}

.tsr__tiles {
  margin-top: 13px;
}

.tsr__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.35fr) minmax(0, 0.85fr) minmax(0, 0.85fr)
    minmax(0, 0.85fr) minmax(0, 0.85fr);
  gap: 4px 8px;
  align-items: center;
  margin-top: 14px;
}

.tsr__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 6px 0;
}

.tsr__code {
  font-size: 7.5px;
  font-weight: 500;
  color: #C0C5D2;
}

.tsr__num {
  text-align: right;
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
}

.tsr__num--bill {
  color: #15803D;
}

.tsr__num--ot   {
  color: #B45309;
  font-weight: 700;
}

.tsr__num--nil  {
  color: #C7CCD8;
  font-weight: 500;
}

.tsr__state {
  display: flex;
  justify-content: flex-start;
}

/* The pill takes its margin from .tsw__pill for the header case; inside a
   table cell it must not be pushed to the right. */

.tsr__state .tsw__pill {
  margin-left: 0;
}

/* ==========================================================================
   04 — the utilisation report
   ========================================================================== */

.tsu__group {
  display: flex;
  gap: 4px;
  margin-left: auto;
  padding: 3px;
  border-radius: 100px;
  background-color: #F4F6FB;
}

.tsu__by {
  padding: 3px 9px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.tsu__by.is-on {
  background-color: #ffffff;
  color: #5B4BE0;
}

.tsu__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.2fr) minmax(0, 0.8fr) minmax(0, 1.9fr) minmax(0, 0.75fr);
  gap: 5px 9px;
  align-items: center;
  margin-top: 14px;
}

.tsu__meter {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* The track is 125% of capacity, so the 100% mark sits four fifths along and
   an over-capacity bar has somewhere to go without leaving the row. */

.tsu__track {
  position: relative;
  flex: 1;
  min-width: 0;
  height: 9px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.06);
}

.tsu__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w);
  border-radius: 100px;
}

.tsu__fill--good  {
  background-color: #2563EB;
}

.tsu__fill--under {
  background-color: #93B4F8;
}

.tsu__fill--over  {
  background-color: #E9A23B;
}

/* Capacity, drawn across the track at the 100% point. A bar past this mark is
   the finding the panel exists for. */

.tsu__mark {
  position: absolute;
  top: -3px;
  bottom: -3px;
  left: 80%;
  width: 2px;
  margin-left: -1px;
  border-radius: 100px;
  background-color: #0B0D12;
}

.tsu__pct {
  flex: none;
  min-width: 30px;
  text-align: right;
  font-size: 9.5px;
  font-weight: 700;
  white-space: nowrap;
}

.tsu__pct--good  {
  color: #1D4ED8;
}

.tsu__pct--under {
  color: #8A90A0;
}

.tsu__pct--over  {
  color: #B45309;
}

.tsu__foot {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
  padding-top: 11px;
  border-top: 1px solid rgba(16, 24, 48, 0.08);
}

.tsu__note {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

/* ==========================================================================
   The why section's list

   .hs-reasons is the HRMS split section's ticked list, which is two columns
   inside a half-width column. Under a centred passage it gets three, and the
   same measure as the prose above it.
   ========================================================================== */

.hs-reasons--wide {
  max-width: 900px;
  margin-left: auto;
  margin-right: auto;
  margin-top: 40px;
}

@media (min-width: 900px) {
  .hs-reasons--wide {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ==========================================================================
   ENTRANCE

   Gated on `.sc-panel.is-showing`, not on the site's .reveal observer: inside
   a pinned stage a panel is shown and hidden repeatedly as the reader scrolls
   back and forth, and .reveal fires once and unobserves. This replays every
   time the step comes round, in either direction, with no state to keep. --i
   is authored on each row.

   The hero's own week is left out of this: it is not in a pinned panel, and
   .hs-hero__art already carries it in on the page's reveal.
   ========================================================================== */

.sc-panel .tsw__proj,
.sc-panel .tsw__cell,
.sc-panel .tsw__tot,
.sc-panel .tsl__sumlabel,
.sc-panel .tsl__sum,
.sc-panel .tsp__name,
.sc-panel .tsp__cell,
.sc-panel .tsp__flagcell,
.sc-panel .tsp__state,
.sc-panel .tsr__who,
.sc-panel .tsr__num,
.sc-panel .tsr__state,
.sc-panel .tsu__meter {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition:
    opacity 460ms var(--ease-smooth),
    transform 560ms var(--ease-smooth);
  transition-delay: calc(180ms + var(--i, 0) * 70ms);
}

.sc-panel.is-showing .tsw__proj,
.sc-panel.is-showing .tsw__cell,
.sc-panel.is-showing .tsw__tot,
.sc-panel.is-showing .tsl__sumlabel,
.sc-panel.is-showing .tsl__sum,
.sc-panel.is-showing .tsp__name,
.sc-panel.is-showing .tsp__cell,
.sc-panel.is-showing .tsp__flagcell,
.sc-panel.is-showing .tsp__state,
.sc-panel.is-showing .tsr__who,
.sc-panel.is-showing .tsr__num,
.sc-panel.is-showing .tsr__state,
.sc-panel.is-showing .tsu__meter {
  opacity: 1;
  transform: none;
}

/* The bars grow from nothing rather than sliding in with their row: a
   utilisation bar arriving at full width says nothing, and one filling to its
   figure is the only movement on that panel worth having. */

.sc-panel .tsu__fill {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 720ms var(--ease-smooth);
  transition-delay: calc(320ms + var(--i, 0) * 70ms);
}

.sc-panel.is-showing .tsu__fill {
  transform: scaleX(1);
}

/* Pin off: no sequence to arrive with, so everything is simply there. */

@media (max-width: 1023.98px) {
  .sc-panel .tsw__proj,
  .sc-panel .tsw__cell,
  .sc-panel .tsw__tot,
  .sc-panel .tsl__sumlabel,
  .sc-panel .tsl__sum,
  .sc-panel .tsp__name,
  .sc-panel .tsp__cell,
  .sc-panel .tsp__flagcell,
  .sc-panel .tsp__state,
  .sc-panel .tsr__who,
  .sc-panel .tsr__num,
  .sc-panel .tsr__state,
  .sc-panel .tsu__meter,
  .sc-panel .tsu__fill {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Narrow frame: the columns a reader checks last come out. The day columns and
   the utilisation bar stay, because they are what the pictures are about.

   Every header row here is a flex row of controls that does not wrap at the
   width these get on a phone, so they are all told to. Measured rather than
   assumed: at a 340px frame the timesheet bar overran its sheet by 87px and
   the footer by 28 before this block existed. */

@container (max-width: 380px) {
  .tsw__bar,
  .tsp__bar,
  .tsl__foot,
  .tsu__foot {
    flex-wrap: wrap;
  }

  .tsw__pill,
  .tsl__views,
  .tsl__go,
  .tsr__exports,
  .tsu__group {
    margin-left: 0;
  }

  .tsw__act .tsw__flag {
    display: none;
  }

  .tsw__date {
    display: none;
  }

  /* The total column goes, not a day column: the week total is already on the
     Logged tile above and on the day-total row below, and a day column is what
     the picture is about. */

  .tsw__grid {
    grid-template-columns:
      minmax(0, 1.5fr)
      repeat(5, minmax(0, 0.8fr));
    gap: 4px;
  }

  .tsw__th:last-child,
  .tsw__tot,
  .tsl__sum--grand {
    display: none;
  }

  .tsw__cell {
    min-height: 24px;
    font-size: 9px;
  }

  .tsw__th {
    font-size: 7.5px;
  }

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

  .tsp__search {
    display: none;
  }

  .tsp__table {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 0.95fr);
  }

  .tsp__th:nth-child(3),
  .tsp__th:nth-child(4),
  .tsp__cell:nth-of-type(2n),
  .tsp__flagcell {
    display: none;
  }

  .tsr__table {
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.9fr) minmax(0, 0.9fr) minmax(0, 0.9fr);
  }

  .tsr__code {
    display: none;
  }

  .tsr__table .tsp__th:nth-child(4) {
    display: none;
  }

  .tsr__num--ot,
  .tsr__num--nil {
    display: none;
  }

  .tsu__table {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.9fr) minmax(0, 0.75fr);
  }

  .tsu__table .tsp__th:nth-child(2) {
    display: none;
  }

  .tsu__table .tsr__num:not(.tsr__num--bill) {
    display: none;
  }
}

/* ==========================================================================
   THE FIELD TRACKING ARTWORKS — /field-employee-tracking-software/

   .fld the field force condensed in the hero, .fdd the dashboard, .fdl live
   tracking, .fdv the visit schedule, .fdr the visit report. All five sit in
   the blue box registered above, so every rule here assumes the near-white
   sheet .sc-sheet paints.

   .fdd, .fdl, .fdv and .fdr share .fld__ parts wherever they draw the same
   object — the title bar, the live badge, the stat tiles, the avatar, the
   status chip. Five copies of a status chip would be five places for its
   colour to drift, and these five sit within one screen of each other.

   ONE MEANING PER COLOUR
   The four statuses own their hues and nothing else uses them: blue on visit,
   teal travelling, amber idle, grey off duty. Green, amber and red keep the
   met / close / short meaning they carry everywhere else on the site, which is
   why the completion bars use them and the status chips do not.
   ========================================================================== */

/* The frame the four sequence panels share. Measured against the tallest of
   them, which is the dashboard with its four tiles over the two panels. */

.sc-panel__frame--fe {
  display: flex;
  min-height: 450px;
  background-color: #DCE4F6;
}

.sc-panel__frame--fe > * {
  flex: 1;
  min-height: 0;
}

/* ==========================================================================
   Shared chrome
   ========================================================================== */

.fld__bar {
  display: flex;
  align-items: center;
  gap: 9px;
}

.fld__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.fld__day {
  padding: 4px 10px;
  border-radius: 100px;
  background-color: #F4F6FB;
  font-size: 9px;
  font-weight: 600;
  color: #3A4050;
  white-space: nowrap;
}

/* The one thing on these panels that says the data is live rather than a
   report. It is the claim the copy makes, so it is drawn rather than written. */

.fld__live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  padding: 4px 10px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.1);
  font-size: 8.5px;
  font-weight: 700;
  color: #15803D;
  white-space: nowrap;
}

.fld__blip {
  width: 6px;
  height: 6px;
  border-radius: 100px;
  background-color: #16A34A;
}

.sc-panel.is-showing .fld__blip {
  animation: fld-blip 2.2s ease-in-out infinite;
}

@keyframes fld-blip {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(22, 163, 74, 0);
  }

  45%      {
    box-shadow: 0 0 0 4px rgba(22, 163, 74, 0.22);
  }
}

/* ---- the stat tiles ---- */

.fld__tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.fdd__tiles {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.fld__tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 11px;
  border-radius: 10px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.fld__amount {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.fld__label {
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  white-space: nowrap;
}

.fld__tile--on     {
  background-color: rgba(22, 163, 74, 0.09);
  box-shadow: none;
}

.fld__tile--on .fld__amount {
  color: #15803D;
}

.fld__tile--visits {
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: none;
}

.fld__tile--visits .fld__amount {
  color: #1D4ED8;
}

.fld__tile--km     {
  background-color: rgba(20, 184, 166, 0.1);
  box-shadow: none;
}

.fld__tile--km .fld__amount {
  color: #0F766E;
}

.fld__tile--time   {
  background-color: rgba(139, 92, 246, 0.1);
  box-shadow: none;
}

.fld__tile--time .fld__amount {
  color: #6D28D9;
}

/* ---- person, status ---- */

.fld__av {
  flex: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  font-size: 8.5px;
  font-weight: 700;
  color: #2563EB;
}

.fld__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.fld__name {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fld__zone {
  font-size: 8px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Four states, four colours AND four words. The word carries it: at this size
   a small difference in hue is not a distinction anyone can rely on, and these
   are decoration inside an aria-hidden illustration. */

.fld__state {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: 100px;
  font-size: 8px;
  font-weight: 700;
  white-space: nowrap;
}

.fld__dot {
  width: 6px;
  height: 6px;
  border-radius: 100px;
  background-color: currentColor;
}

.fld__state--visit  {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

.fld__state--travel {
  background-color: rgba(20, 184, 166, 0.13);
  color: #0F766E;
}

.fld__state--idle   {
  background-color: rgba(233, 162, 59, 0.16);
  color: #B45309;
}

.fld__state--off    {
  background-color: rgba(16, 24, 48, 0.06);
  color: #8A90A0;
}

/* Standalone dots, for the dashboard legend. */

.fld__dot--visit  {
  background-color: #1D4ED8;
}

.fld__dot--travel {
  background-color: #0F766E;
}

.fld__dot--idle   {
  background-color: #E9A23B;
}

.fld__dot--off    {
  background-color: #C0C5D2;
}

/* ==========================================================================
   01 — the hero list
   ========================================================================== */

.fld__list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.fld__row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: 10px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.06);
}

.fld__row .fld__who {
  flex: 1;
}

.fld__count {
  flex: none;
  font-size: 9.5px;
  font-weight: 700;
  color: #1D4ED8;
  white-space: nowrap;
}

/* ==========================================================================
   02 — the dashboard
   ========================================================================== */

.fdd__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 10px;
  margin-top: 12px;
}

.fdd__panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 11px 12px;
  border-radius: 12px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.fdd__caplabel {
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.fdd__caplabel--tight {
  margin-top: 4px;
}

.fdd__zone {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.fdd__zonetop {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.fdd__zonename {
  font-size: 9px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fdd__zoneval {
  margin-left: auto;
  font-size: 9px;
  font-weight: 700;
  color: #0F766E;
  white-space: nowrap;
}

.fdd__track {
  height: 7px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.06);
}

/* Scaled to the busiest zone, not to a round number: the bars are a ranking,
   and a ranking whose longest bar stops short reads as missing data. */

.fdd__fill {
  display: block;
  width: var(--w);
  height: 100%;
  border-radius: 100px;
  background-image: linear-gradient(90deg, #5EEAD4 0%, #14B8A6 100%);
}

.fdd__legend {
  display: flex;
  align-items: center;
  gap: 7px;
}

.fdd__legname {
  font-size: 9px;
  font-weight: 500;
  color: #5A6070;
  white-space: nowrap;
}

.fdd__legnum {
  margin-left: auto;
  font-size: 9.5px;
  font-weight: 700;
  color: #22262F;
}

.fdd__best {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 9px;
  border-radius: 10px;
  background-color: rgba(37, 99, 235, 0.06);
}

/* ==========================================================================
   03 — live tracking
   ========================================================================== */

.fdl__views {
  display: flex;
  gap: 4px;
  padding: 3px;
  border-radius: 100px;
  background-color: #F4F6FB;
}

.fdl__view {
  padding: 3px 9px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.fdl__view.is-on {
  background-color: #ffffff;
  color: #1D4ED8;
}

.fdl__split {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.15fr);
  gap: 10px;
  margin-top: 12px;
}

/* Pins on a plain field, not a street map. Drawing real streets would be
   drawing a picture of a map rather than of the product, and it would have to
   be a real place. What the panel claims is that the system knows where five
   people are, and five pins spread over a field is that claim. */

.fdl__map {
  position: relative;
  overflow: hidden;
  /* Sized to fill the frame the four panels share rather than to the pins:
     the dashboard sets that height, and a map floating above a band of empty
     sheet reads as a panel that failed to load. */
  min-height: 250px;
  border-radius: 12px;
  /* The ground between the blocks: the pale warm grey a street map leaves
     where there is nothing but road. */
  background-color: #EDEFF2;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

/* The city blocks. Two layered gradients cut the field into rectangles with
   pale streets between them, which is what a map reads as at this size: the
   white lines are the minor roads, the fill is everything they enclose. */

.fdl__grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(90deg, #FFFFFF 3px, transparent 3px),
    linear-gradient(#FFFFFF 3px, transparent 3px),
    linear-gradient(90deg, #F7F8FA 1px, transparent 1px),
    linear-gradient(#F7F8FA 1px, transparent 1px);
  background-size: 62px 62px, 62px 62px, 31px 31px, 31px 31px;
  background-position: -8px -6px, -8px -6px, -8px -6px, -8px -6px;
}

/* The two roads that carry traffic. Wider, and warmer than the minor streets,
   the way a map ranks a road by width before it ranks it by colour. */

.fdl__road {
  position: absolute;
  background-color: #FDFDFE;
  box-shadow: 0 0 0 1px rgba(16, 24, 48, 0.05);
}

.fdl__road--h {
  left: 0;
  right: 0;
  top: 41%;
  height: 9px;
}

.fdl__road--v {
  top: 0;
  bottom: 0;
  left: 57%;
  width: 9px;
}

/* Green space and water, the two things that stop a grid of rectangles
   reading as graph paper. */

.fdl__park {
  position: absolute;
  left: 8%;
  top: 55%;
  width: 34%;
  height: 30%;
  border-radius: 10px;
  background-color: #DFEEDF;
}

.fdl__river {
  position: absolute;
  right: 4%;
  top: -20%;
  /* Narrow: at 46% it read as half the map being water rather than as a river
     running through a city. */
  width: 16%;
  height: 150%;
  transform: rotate(20deg);
  border-radius: 40px;
  background-color: #CFE0F0;
}

/* A map marker, drawn as a path: it points straight down at the coordinate,
   which a disc floating over a street does not. The box hangs above its
   position so the tip, not the middle, sits on the point it means. */

.fdl__pin {
  position: absolute;
  left: var(--x);
  top: var(--y);
  display: block;
  width: 21px;
  height: 28px;
  margin: -28px 0 0 -10.5px;
  filter: drop-shadow(0 3px 5px rgba(16, 24, 48, 0.4));
  font-size: 8.5px;
  font-weight: 700;
}

.fdl__pin--visit  {
  color: #2563EB;
}

.fdl__pin--travel {
  color: #14B8A6;
}

.fdl__pin--idle   {
  color: #E9A23B;
}

.fdl__pulse {
  position: absolute;
  inset: -6px;
  border-radius: 100px;
  background-color: currentColor;
  opacity: 0.16;
}

.sc-panel.is-showing .fdl__pin .fdl__pulse {
  animation: fdl-pulse 2.6s ease-out infinite;
  animation-delay: calc(var(--i, 0) * 420ms);
}

@keyframes fdl-pulse {
  0%   {
    transform: scale(0.7);
    opacity: 0.28;
  }

  70%  {
    transform: scale(1.5);
    opacity: 0;
  }

  100% {
    transform: scale(1.5);
    opacity: 0;
  }
}

.fdl__scale {
  position: absolute;
  left: 10px;
  bottom: 9px;
  padding: 2px 7px;
  border-radius: 100px;
  background-color: rgba(255, 255, 255, 0.85);
  font-size: 7.5px;
  font-weight: 700;
  color: #8A90A0;
}

.fdl__list {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fdl__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 8px;
  padding: 7px 9px;
  border-radius: 9px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.06);
}

/* Clocked out, so dimmed and with no pin on the map beside it. A live view
   showing somebody who has finished would be showing a system that cannot
   tell the difference. */

.fdl__row--off {
  opacity: 0.55;
}

.fdl__meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
}

.fdl__seen {
  font-size: 7.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
}

.fdl__km {
  font-size: 9px;
  font-weight: 700;
  color: #0F766E;
  white-space: nowrap;
}

/* ==========================================================================
   04 — the visit schedule
   ========================================================================== */

.fdv__who {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 9.5px;
  font-weight: 600;
  color: #3A4050;
  white-space: nowrap;
}

.fdv__who .fld__av {
  width: 20px;
  height: 20px;
  font-size: 7.5px;
}

.fdv__count {
  margin-left: auto;
  padding: 4px 10px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.09);
  font-size: 8.5px;
  font-weight: 700;
  color: #1D4ED8;
  white-space: nowrap;
}

.fdv__filters {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
}

.fdv__filter {
  padding: 4px 10px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.1);
  font-size: 8.5px;
  font-weight: 600;
  color: #5A6070;
  white-space: nowrap;
}

.fdv__filter.is-on {
  background-color: rgba(37, 99, 235, 0.1);
  box-shadow: none;
  color: #1D4ED8;
}

.fdv__search {
  flex: 1;
  min-width: 0;
  padding: 5px 11px;
  border-radius: 100px;
  background-color: #F4F6FB;
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fdv__go {
  padding: 5px 11px;
  border-radius: 100px;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  font-size: 8.5px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}

.fdv__list {
  margin: 13px 0 0;
  padding: 0;
  list-style: none;
}

/* A timeline, because a schedule is one. The rail runs through the node on
   every row and stops at the last, which is what makes the day read as a
   sequence rather than as five unrelated records. */

.fdv__item {
  display: grid;
  grid-template-columns: 34px 14px minmax(0, 1fr) auto;
  align-items: center;
  gap: 9px;
  padding: 7px 0;
}

.fdv__time {
  font-size: 9px;
  font-weight: 700;
  color: #8A90A0;
  white-space: nowrap;
}

.fdv__rail {
  position: relative;
  align-self: stretch;
  display: grid;
  place-items: center;
}

.fdv__rail::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1.5px;
  background-color: rgba(16, 24, 48, 0.08);
}

.fdv__item:first-child .fdv__rail::before {
  top: 50%;
}

.fdv__item:last-child  .fdv__rail::before {
  bottom: 50%;
}

.fdv__node {
  position: relative;
  width: 9px;
  height: 9px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: 0 0 0 1.5px rgba(16, 24, 48, 0.15);
}

.fdv__item--done .fdv__node   {
  background-color: #16A34A;
  box-shadow: 0 0 0 1.5px #16A34A;
}

.fdv__item--active .fdv__node {
  background-color: #2563EB;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.22);
}

.fdv__body {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.fdv__name {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fdv__area {
  font-size: 8px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fdv__state {
  padding: 3px 9px;
  border-radius: 100px;
  font-size: 8px;
  font-weight: 700;
  white-space: nowrap;
}

.fdv__state--done   {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.fdv__state--active {
  background-color: rgba(37, 99, 235, 0.11);
  color: #1D4ED8;
}

.fdv__state--next   {
  background-color: rgba(16, 24, 48, 0.06);
  color: #8A90A0;
}

/* ==========================================================================
   05 — the visit report
   ========================================================================== */

.fdr__exports {
  display: flex;
  gap: 6px;
  margin-left: auto;
}

.fdr__ghost {
  padding: 5px 10px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  font-size: 8.5px;
  font-weight: 600;
  color: #5A6070;
  white-space: nowrap;
}

.fdr__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.2fr) minmax(0, 0.62fr) minmax(0, 1.5fr)
    minmax(0, 0.66fr) minmax(0, 0.72fr) minmax(0, 0.6fr);
  gap: 5px 8px;
  align-items: center;
  margin-top: 14px;
}

.fdr__th {
  padding-bottom: 7px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  overflow-wrap: anywhere;
}

.fdr__th--num {
  text-align: right;
}

.fdr__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 5px 0;
}

.fdr__code {
  font-size: 7.5px;
  font-weight: 500;
  color: #C0C5D2;
}

.fdr__num {
  text-align: right;
  font-size: 9px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
}

.fdr__num--time   {
  color: #6D28D9;
}

.fdr__num--ontime {
  color: #8A90A0;
}

.fdr__meter {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.fdr__track {
  position: relative;
  flex: 1;
  min-width: 0;
  height: 8px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.06);
}

.fdr__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w);
  border-radius: 100px;
}

/* The met / close / short verdict the rest of the site uses. Ninety per cent
   is the bar here, not a hundred: a field day with one visit rescheduled is
   not a failure, and colouring it red would say it was. */

.fdr__fill--ok   {
  background-color: #16A34A;
}

.fdr__fill--near {
  background-color: #E9A23B;
}

.fdr__fill--gap  {
  background-color: #DC2626;
}

.fdr__pct {
  flex: none;
  min-width: 26px;
  text-align: right;
  font-size: 9px;
  font-weight: 700;
  white-space: nowrap;
}

.fdr__pct--ok   {
  color: #15803D;
}

.fdr__pct--near {
  color: #B45309;
}

.fdr__pct--gap  {
  color: #B91C1C;
}

.fdr__foot {
  display: flex;
  align-items: center;
  margin-top: 14px;
  padding-top: 11px;
  border-top: 1px solid rgba(16, 24, 48, 0.08);
}

.fdr__note {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

/* ==========================================================================
   ENTRANCE

   Gated on `.sc-panel.is-showing`, not on the site's .reveal observer: inside
   a pinned stage a panel is shown and hidden repeatedly as the reader scrolls
   back and forth, and .reveal fires once and unobserves. This replays every
   time the step comes round, in either direction, with no state to keep. --i
   is authored on each row.

   The hero's own list is left out: it is not in a pinned panel, and
   .hs-hero__art already carries it in on the page's reveal.
   ========================================================================== */

.sc-panel .fdd__zone,
.sc-panel .fdl__row,
.sc-panel .fdv__item,
.sc-panel .fdr__who,
.sc-panel .fdr__num,
.sc-panel .fdr__meter {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition:
    opacity 460ms var(--ease-smooth),
    transform 560ms var(--ease-smooth);
  transition-delay: calc(180ms + var(--i, 0) * 70ms);
}

.sc-panel.is-showing .fdd__zone,
.sc-panel.is-showing .fdl__row,
.sc-panel.is-showing .fdv__item,
.sc-panel.is-showing .fdr__who,
.sc-panel.is-showing .fdr__num,
.sc-panel.is-showing .fdr__meter {
  opacity: 1;
  transform: none;
}

/* The pins drop onto the map rather than fading in, which is the only movement
   on that panel worth having. */

.sc-panel .fdl__pin {
  opacity: 0;
  transform: translate3d(0, -10px, 0) scale(0.7);
  transition:
    opacity 380ms var(--ease-smooth),
    transform 480ms var(--ease-soft);
  transition-delay: calc(260ms + var(--i, 0) * 110ms);
}

.sc-panel.is-showing .fdl__pin {
  opacity: 1;
  transform: none;
}

/* Bars grow from nothing rather than sliding in with their row. */

.sc-panel .fdd__fill,
.sc-panel .fdr__fill {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 700ms var(--ease-smooth);
  transition-delay: calc(320ms + var(--i, 0) * 70ms);
}

.sc-panel.is-showing .fdd__fill,
.sc-panel.is-showing .fdr__fill {
  transform: scaleX(1);
}

/* Pin off: no sequence to arrive with, so everything is simply there. */

@media (max-width: 1023.98px) {
  .sc-panel .fdd__zone,
  .sc-panel .fdl__row,
  .sc-panel .fdl__pin,
  .sc-panel .fdv__item,
  .sc-panel .fdr__who,
  .sc-panel .fdr__num,
  .sc-panel .fdr__meter,
  .sc-panel .fdd__fill,
  .sc-panel .fdr__fill {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Narrow frame: the header rows wrap, the map and the dashboard's side panel
   go under rather than beside, and the columns a reader checks last come out.
   The completion bar stays: it is what the report is about. */

@container (max-width: 380px) {
  .fld__bar,
  .fdv__filters,
  .fdr__exports {
    flex-wrap: wrap;
  }

  .fld__live,
  .fdv__count,
  .fdr__exports {
    margin-left: 0;
  }

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

  .fdd__grid,
  .fdl__split {
    grid-template-columns: minmax(0, 1fr);
  }

  .fdl__map {
    min-height: 150px;
  }

  .fdv__search {
    display: none;
  }

  .fdv__item {
    grid-template-columns: 30px 14px minmax(0, 1fr) auto;
  }

  .fdr__table {
    grid-template-columns:
      minmax(0, 1.1fr) minmax(0, 0.6fr) minmax(0, 1.3fr) minmax(0, 0.62fr);
  }

  .fdr__code,
  .fdr__th:nth-child(5),
  .fdr__th:nth-child(6),
  .fdr__num--time,
  .fdr__num--ontime {
    display: none;
  }
}

/* ==========================================================================
   THE TRAVEL DESK ARTWORKS — /travel-desk/

   .trv the trip board condensed in the hero, .tvt that board in full, .tvn the
   new request form, .tvq the desk queue, .tvd the trip detail and approval
   screen. All five sit in the blue box registered above, so every rule here
   assumes the near-white sheet .sc-sheet paints.

   .tvt, .tvn, .tvq and .tvd share .trv__ parts wherever they draw the same
   object — the title bar, the search field, the status pill, the primary
   button. Five copies of a status pill would be five places for its colour to
   drift, and these five sit within one screen of each other.

   ONE MEANING PER COLOUR
   The five trip states own their hues and nothing else uses them: grey draft,
   amber pending, blue approved, indigo booked, green completed. That is the
   order a trip moves through, and the ramp goes with it, so a board can be
   read as a progression rather than as five unrelated labels.
   ========================================================================== */

/* The frame the four sequence panels share. Measured against the tallest of
   them, which is the board with its three tiles over five rows. */

.sc-panel__frame--td {
  display: flex;
  min-height: 455px;
  background-color: #DCE4F6;
}

.sc-panel__frame--td > * {
  flex: 1;
  min-height: 0;
}

/* ==========================================================================
   Shared chrome
   ========================================================================== */

.trv__bar {
  display: flex;
  align-items: center;
  gap: 9px;
}

.trv__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.trv__search {
  flex: 1;
  min-width: 0;
  padding: 5px 11px;
  border-radius: 100px;
  background-color: #F4F6FB;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.trv__go {
  flex: none;
  padding: 6px 12px;
  border-radius: 100px;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  font-size: 9px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}

/* ---- the status tabs ----
   Every tab carries its count, which is what makes the strip a summary rather
   than a row of filters. The counts are tallied in PHP from the board below. */

.trv__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.trv__tab {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.trv__tab em {
  font-style: normal;
  font-weight: 700;
  color: #C0C5D2;
}

.trv__tab.is-on {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

.trv__tab.is-on em {
  color: #1D4ED8;
}

/* ---- the state pill ----
   Five states as five colours AND five words. The word carries it: at this
   size a small difference in hue is not a distinction anyone can rely on, and
   the pills are decoration inside an aria-hidden illustration. */

.trv__pill {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 100px;
  font-size: 8px;
  font-weight: 700;
  white-space: nowrap;
}

.trv__pill--draft     {
  background-color: rgba(16, 24, 48, 0.06);
  color: #8A90A0;
}

.trv__pill--pending   {
  background-color: rgba(233, 162, 59, 0.17);
  color: #B45309;
}

.trv__pill--approved  {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

.trv__pill--booked    {
  background-color: rgba(109, 91, 246, 0.13);
  color: #5B4BE0;
}

.trv__pill--completed {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

/* ==========================================================================
   01 — the hero board
   ========================================================================== */

.trv__list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 11px 0 0;
  padding: 0;
  list-style: none;
}

.trv__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border-radius: 11px;
  background-color: #ffffff;
  box-shadow:
    inset 0 0 0 1px rgba(16, 24, 48, 0.06),
    0 6px 18px -14px rgba(16, 24, 48, 0.5);
}

.trv__meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.trv__purpose {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.trv__route {
  font-size: 8px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.trv__sep {
  padding: 0 3px;
  color: #D3D7E0;
}

.trv__cost {
  flex: none;
  font-size: 9.5px;
  font-weight: 700;
  color: #22262F;
  white-space: nowrap;
}

.trv__more {
  margin-top: 9px;
  text-align: center;
  font-size: 8.5px;
  font-weight: 600;
  color: #A6ADBD;
}

/* ==========================================================================
   02 — the board in full
   ========================================================================== */

.tvt__tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.tvt__tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 11px;
  border-radius: 10px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.tvt__amount {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.tvt__label {
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  white-space: nowrap;
}

.tvt__tile--trips {
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: none;
}

.tvt__tile--trips .tvt__amount {
  color: #1D4ED8;
}

.tvt__tile--open  {
  background-color: rgba(233, 162, 59, 0.14);
  box-shadow: none;
}

.tvt__tile--open .tvt__amount {
  color: #B45309;
}

.tvt__tile--spend {
  background-color: rgba(109, 91, 246, 0.1);
  box-shadow: none;
}

.tvt__tile--spend .tvt__amount {
  color: #5B4BE0;
}

/* A real grid rather than a row of rows: the columns have to line up across
   every trip, and a per-row flexbox lines them up only as long as no two
   purposes are the same length. */

.tvt__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.15fr) minmax(0, 1.1fr) minmax(0, 0.95fr)
    minmax(0, 0.95fr) minmax(0, 0.72fr);
  gap: 5px 8px;
  align-items: center;
  margin-top: 12px;
}

.tvt__th {
  padding-bottom: 7px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  white-space: nowrap;
}

.tvt__th--num {
  text-align: right;
}

.tvt__trip {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 5px 0;
}

.tvt__code {
  font-size: 7.5px;
  font-weight: 500;
  color: #C0C5D2;
}

.tvt__cell {
  min-width: 0;
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tvt__state {
  justify-self: start;
}

.tvt__num {
  text-align: right;
  font-size: 9px;
  font-weight: 700;
  color: #22262F;
  white-space: nowrap;
}

/* ==========================================================================
   03 — the request form
   ========================================================================== */

.tvn__step {
  margin-left: auto;
  padding: 4px 10px;
  border-radius: 100px;
  background-color: #F4F6FB;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.tvn__form {
  display: flex;
  flex-direction: column;
  gap: 11px;
  margin-top: 14px;
}

.tvn__field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.tvn__pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.tvn__label {
  display: flex;
  align-items: baseline;
  gap: 5px;
  font-size: 8.5px;
  font-weight: 600;
  color: #3A4050;
}

.tvn__label em {
  font-style: normal;
  color: #DC2626;
}

.tvn__input {
  display: flex;
  align-items: center;
  padding: 7px 10px;
  border-radius: 8px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.13);
  font-size: 9px;
  font-weight: 500;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tvn__input--ghost {
  color: #A6ADBD;
}

.tvn__input--area {
  align-items: flex-start;
  min-height: 38px;
  white-space: normal;
  line-height: 1.45;
}

/* The one focused field, which is where a form opens. */

.tvn__input--focus {
  box-shadow: inset 0 0 0 1.5px #2563EB;
}

.tvn__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.tvn__chip {
  padding: 4px 9px;
  border-radius: 100px;
  background-color: #F4F5FA;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.08);
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.tvn__chip.is-on {
  background-color: rgba(37, 99, 235, 0.1);
  box-shadow: none;
  color: #1D4ED8;
}

.tvn__foot,
.tvd__foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding-top: 14px;
}

/* The policy check reads as a verdict, not a label: it is the thing the copy
   claims happens before the request is submitted rather than at the claim. */

.tvn__policy {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-right: auto;
  font-size: 8.5px;
  font-weight: 600;
  color: #15803D;
}

.tvn__tick {
  display: grid;
  place-items: center;
  width: 14px;
  height: 14px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.14);
}

.tvn__tick svg {
  width: 9px;
  height: 9px;
}

.tvn__ghost {
  padding: 6px 12px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  font-size: 9px;
  font-weight: 600;
  color: #5A6070;
  white-space: nowrap;
}

/* The form's own sheet is a column so its footer can sit at the bottom. */

.tvn .sc-sheet,
.tvd .sc-sheet {
  display: flex;
  flex-direction: column;
}

/* ==========================================================================
   04 — the desk queue
   ========================================================================== */

.tvq__count {
  padding: 4px 10px;
  border-radius: 100px;
  background-color: rgba(233, 162, 59, 0.14);
  font-size: 8.5px;
  font-weight: 700;
  color: #B45309;
  white-space: nowrap;
}

.tvq__filters {
  display: flex;
  gap: 6px;
  margin-left: auto;
}

.tvq__filter {
  padding: 4px 10px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.1);
  font-size: 8.5px;
  font-weight: 600;
  color: #5A6070;
  white-space: nowrap;
}

.tvq__filter.is-on {
  background-color: rgba(37, 99, 235, 0.1);
  box-shadow: none;
  color: #1D4ED8;
}

.tvq__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.05fr) minmax(0, 0.9fr) minmax(0, 0.95fr)
    minmax(0, 0.95fr) minmax(0, 0.7fr) minmax(0, 0.95fr);
  gap: 5px 8px;
  align-items: center;
  margin-top: 14px;
}

.tvq__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 5px 0;
}

/* What the desk does next, not the status again. Three weights, because a
   thing to do now and a thing already done should not look the same. */

.tvq__act {
  justify-self: start;
  padding: 3px 9px;
  border-radius: 7px;
  font-size: 8px;
  font-weight: 700;
  white-space: nowrap;
}

.tvq__act--now  {
  background-color: rgba(37, 99, 235, 0.11);
  color: #1D4ED8;
}

.tvq__act--soon {
  background-color: rgba(16, 24, 48, 0.05);
  color: #5A6070;
}

.tvq__act--done {
  background-color: transparent;
  color: #C0C5D2;
}

/* ==========================================================================
   05 — the trip detail and approval screen
   ========================================================================== */

.tvd__code {
  margin-left: 0;
  font-size: 8.5px;
}

.tvd__pill {
  margin-left: auto;
}

.tvd__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-top: 13px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.tvd__leg {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
}

.tvd__city {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #0B0D12;
}

.tvd__arrow {
  font-size: 12px;
  color: #A6ADBD;
}

.tvd__when {
  font-size: 9.5px;
  font-weight: 600;
  color: #3A4050;
}

.tvd__by {
  margin-left: auto;
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
}

.tvd__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: 10px;
  margin-top: 12px;
}

.tvd__panel {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 11px 12px;
  border-radius: 12px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.tvd__caplabel {
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.tvd__line,
.tvd__total {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.tvd__total {
  margin-top: 3px;
  padding-top: 8px;
  border-top: 1px solid rgba(16, 24, 48, 0.08);
}

.tvd__linename {
  font-size: 9px;
  font-weight: 500;
  color: #5A6070;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tvd__total .tvd__linename {
  font-weight: 700;
  color: #22262F;
}

.tvd__lineval {
  margin-left: auto;
  font-size: 9px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
}

.tvd__lineval--sum {
  font-size: 11px;
  font-weight: 700;
  color: #5B4BE0;
}

/* ---- the approval chain ----
   A rail down the left with one node per stage. Exactly one stage is live,
   because the pill at the top of this panel says the trip is pending. */

.tvd__step {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding-bottom: 11px;
}

.tvd__step:last-child {
  padding-bottom: 0;
}

.tvd__step::before {
  content: '';
  position: absolute;
  left: 4.5px;
  top: 12px;
  bottom: 0;
  width: 1.5px;
  background-color: rgba(16, 24, 48, 0.1);
}

.tvd__step:last-child::before {
  display: none;
}

.tvd__node {
  flex: none;
  width: 10px;
  height: 10px;
  margin-top: 2px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: 0 0 0 1.5px rgba(16, 24, 48, 0.15);
}

.tvd__step--done .tvd__node {
  background-color: #16A34A;
  box-shadow: 0 0 0 1.5px #16A34A;
}

.tvd__step--now .tvd__node  {
  background-color: #E9A23B;
  box-shadow: 0 0 0 3px rgba(233, 162, 59, 0.25);
}

.tvd__stepbody {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.tvd__stepname {
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
}

.tvd__step--next .tvd__stepname {
  color: #A6ADBD;
}

.tvd__stepmeta {
  font-size: 8px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tvd__attach {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-right: auto;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.tvd__clip {
  width: 12px;
  height: 12px;
}

.tvd__clip svg {
  width: 100%;
  height: 100%;
}

/* Reject is a real action on this screen, so it is drawn rather than implied,
   and it is the only red thing on the panel. */

.tvd__reject {
  padding: 6px 12px;
  border-radius: 100px;
  background-color: rgba(220, 38, 38, 0.08);
  font-size: 9px;
  font-weight: 600;
  color: #B91C1C;
  white-space: nowrap;
}

/* ==========================================================================
   ENTRANCE

   Gated on `.sc-panel.is-showing`, not on the site's .reveal observer: inside
   a pinned stage a panel is shown and hidden repeatedly as the reader scrolls
   back and forth, and .reveal fires once and unobserves. This replays every
   time the step comes round, in either direction, with no state to keep. --i
   is authored on each row.

   The hero's own board is left out: it is not in a pinned panel, and
   .hs-hero__art already carries it in on the page's reveal.
   ========================================================================== */

.sc-panel .tvt__trip,
.sc-panel .tvt__cell,
.sc-panel .tvt__state,
.sc-panel .tvt__num,
.sc-panel .tvq__who,
.sc-panel .tvq__act,
.sc-panel .tvn__field,
.sc-panel .tvn__pair,
.sc-panel .tvd__line,
.sc-panel .tvd__step {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition:
    opacity 460ms var(--ease-smooth),
    transform 560ms var(--ease-smooth);
  transition-delay: calc(180ms + var(--i, 0) * 70ms);
}

.sc-panel.is-showing .tvt__trip,
.sc-panel.is-showing .tvt__cell,
.sc-panel.is-showing .tvt__state,
.sc-panel.is-showing .tvt__num,
.sc-panel.is-showing .tvq__who,
.sc-panel.is-showing .tvq__act,
.sc-panel.is-showing .tvn__field,
.sc-panel.is-showing .tvn__pair,
.sc-panel.is-showing .tvd__line,
.sc-panel.is-showing .tvd__step {
  opacity: 1;
  transform: none;
}

/* The one control that moves on its own, and only while its step is on screen.
   A button pulsing inside a panel nobody is looking at is work the browser is
   doing for nothing. */

.sc-panel.is-showing .tvd__foot .trv__go {
  animation: trv-pulse 3.4s ease-in-out infinite;
  animation-delay: 900ms;
}

@keyframes trv-pulse {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(37, 99, 235, 0);
  }

  45%      {
    box-shadow: 0 0 0 5px rgba(37, 99, 235, 0.16);
  }
}

/* Pin off: no sequence to arrive with, so everything is simply there. */

@media (max-width: 1023.98px) {
  .sc-panel .tvt__trip,
  .sc-panel .tvt__cell,
  .sc-panel .tvt__state,
  .sc-panel .tvt__num,
  .sc-panel .tvq__who,
  .sc-panel .tvq__act,
  .sc-panel .tvn__field,
  .sc-panel .tvn__pair,
  .sc-panel .tvd__line,
  .sc-panel .tvd__step {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Narrow frame: the header rows wrap, the paired fields and the two detail
   panels go one above the other, and the columns a reader checks last come
   out. The status column stays on every table: it is what the boards are for.
   ========================================================================== */

@container (max-width: 380px) {
  .trv__bar,
  .tvn__foot,
  .tvd__foot,
  .tvd__head {
    flex-wrap: wrap;
  }

  .trv__search,
  .tvn__step,
  .tvq__filters,
  .tvd__by,
  .tvd__pill {
    margin-left: 0;
  }

  .trv__search {
    display: none;
  }

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

  .tvt__table {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 0.95fr);
  }

  .tvt__table .tvt__th:nth-child(3),
  .tvt__table .tvt__th:nth-child(5),
  .tvt__table .tvt__cell:nth-of-type(2n),
  .tvt__num {
    display: none;
  }

  .tvn__pair {
    grid-template-columns: minmax(0, 1fr);
  }

  .tvq__table {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.95fr) minmax(0, 1fr);
  }

  .tvq__table .tvt__th:nth-child(3),
  .tvq__table .tvt__th:nth-child(5),
  .tvq__table .tvt__th:nth-child(6),
  .tvq__table .tvt__cell,
  .tvq__table .tvt__num,
  .tvq__act {
    display: none;
  }

  .tvd__grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .tvd__attach {
    display: none;
  }
}

/* ==========================================================================
   THE CALL MONITORING ARTWORKS — /call-monitoring-software/

   .cll the dashboard condensed in the hero, .cld the full dashboard, .clg the
   employee call log, .clh one person's call history. All four sit in the blue
   box registered above, so every rule here assumes the near-white sheet
   .sc-sheet paints.

   .cld, .clg and .clh share .cll__ parts wherever they draw the same object —
   the title bar, the range chip, the stat tiles, the chart line. Four copies
   of a stat tile would be four places for its padding to drift, and these four
   sit within one screen of each other.

   ONE MEANING PER COLOUR
   Indigo is outgoing, teal incoming, violet talk time, red missed. Green means
   a call connected and grey means it did not. Nothing else on these four uses
   those hues, so a colour never means two things across the sequence.
   ========================================================================== */

/* The frame the two sequence panels share. Re-measured once the dashboard
   moved to the hero: the tallest of what is left is the six-row call log,
   which needs 410px of sheet. At the 470 the dashboard used to set, both
   panels were carrying sixty pixels of empty sheet, which reads as a
   screenshot that failed to load. */

.sc-panel__frame--cm {
  display: flex;
  min-height: 425px;
  background-color: #DCE4F6;
}

.sc-panel__frame--cm > * {
  flex: 1;
  min-height: 0;
}

/* ==========================================================================
   Shared chrome
   ========================================================================== */

.cll__bar {
  display: flex;
  align-items: center;
  gap: 9px;
}

.cll__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.cll__range {
  margin-left: auto;
  padding: 4px 10px;
  border-radius: 100px;
  background-color: #F4F6FB;
  font-size: 8.5px;
  font-weight: 600;
  color: #3A4050;
  white-space: nowrap;
}

/* The badge that says the count is live rather than a report. It is the claim
   the copy makes, so it is drawn rather than written. */

.cll__live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.1);
  font-size: 8.5px;
  font-weight: 700;
  color: #15803D;
  white-space: nowrap;
}

.cll__blip {
  width: 6px;
  height: 6px;
  border-radius: 100px;
  background-color: #16A34A;
}

/* ---- the stat tiles ---- */

.cll__tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.cll__tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 11px;
  border-radius: 10px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.cll__amount {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.cll__label {
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  white-space: nowrap;
}

.cll__tile--duty  {
  background-color: rgba(22, 163, 74, 0.09);
  box-shadow: none;
}

.cll__tile--duty .cll__amount {
  color: #15803D;
}

.cll__tile--calls {
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: none;
}

.cll__tile--calls .cll__amount {
  color: #1D4ED8;
}

.cll__tile--out   {
  background-color: rgba(109, 91, 246, 0.1);
  box-shadow: none;
}

.cll__tile--out .cll__amount {
  color: #5B4BE0;
}

.cll__tile--in    {
  background-color: rgba(20, 184, 166, 0.11);
  box-shadow: none;
}

.cll__tile--in .cll__amount {
  color: #0F766E;
}

.cll__tile--talk  {
  background-color: rgba(139, 92, 246, 0.1);
  box-shadow: none;
}

.cll__tile--talk .cll__amount {
  color: #6D28D9;
}

.cll__tile--miss  {
  background-color: rgba(220, 38, 38, 0.08);
  box-shadow: none;
}

.cll__tile--miss .cll__amount {
  color: #B91C1C;
}

/* ---- the charts ----
   Plotted from the same array the tiles total; see cm_points() in
   includes/call-content.php. preserveAspectRatio is none on purpose: the
   viewBox is a coordinate space, not a picture, and the line should stretch to
   whatever width the panel gives it. */

.cll__caplabel {
  display: block;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.cll__plot,
.cld__plot {
  display: block;
  width: 100%;
  height: 56px;
  margin-top: 7px;
  overflow: visible;
}

.cld__plot {
  height: 74px;
}

.cll__line {
  fill: none;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.cll__line--total {
  stroke: #2563EB;
}

.cll__line--out   {
  stroke: #5B4BE0;
}

.cll__line--in    {
  stroke: #14B8A6;
}

.cll__line--talk  {
  stroke: #8B5CF6;
}

/* ==========================================================================
   01 — the hero dashboard
   ========================================================================== */

.cll__chart {
  margin-top: 13px;
  padding: 11px 12px 9px;
  border-radius: 12px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

/* ==========================================================================
   02 — the full dashboard
   ========================================================================== */

.cld__tabs {
  display: flex;
  gap: 4px;
  padding: 3px;
  border-radius: 100px;
  background-color: #F4F6FB;
}

.cld__tab {
  padding: 3px 10px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.cld__tab.is-on {
  background-color: #ffffff;
  color: #5B4BE0;
}

/* Consent is a state the dashboard has to surface, so it gets a strip of its
   own rather than a badge tucked into a corner. */

.cld__consent {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 10px;
  padding: 7px 11px;
  border-radius: 9px;
  background-color: rgba(233, 162, 59, 0.12);
  font-size: 8.5px;
  font-weight: 600;
  color: #B45309;
}

.cld__warn {
  display: grid;
  place-items: center;
  color: #E9A23B;
}

.cld__warn svg {
  width: 12px;
  height: 12px;
}

.cld__charts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin-top: 11px;
}

.cld__chart {
  padding: 11px 12px 9px;
  border-radius: 12px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.cld__key {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  margin-top: 8px;
}

/* The key is a dot and a word, and the dot is the line's own colour. A legend
   whose swatch is a different tint from the line it names is a legend that
   makes the reader check. */

.cld__keyitem {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 8px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.cld__keyitem::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 100px;
  background-color: currentColor;
}

.cld__keyitem--out::before  {
  background-color: #5B4BE0;
}

.cld__keyitem--in::before   {
  background-color: #14B8A6;
}

.cld__keyitem--talk::before {
  background-color: #8B5CF6;
}

/* ==========================================================================
   03 — the employee call log
   ========================================================================== */

.clg__tools {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}

.clg__search {
  flex: 1;
  min-width: 0;
  padding: 6px 12px;
  border-radius: 100px;
  background-color: #F4F6FB;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
  font-size: 9px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.clg__filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  font-size: 9px;
  font-weight: 600;
  color: #5A6070;
  white-space: nowrap;
}

.clg__funnel {
  display: grid;
  place-items: center;
  color: #8A90A0;
}

.clg__funnel svg {
  width: 11px;
  height: 11px;
}

.clg__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.35fr) minmax(0, 1fr) minmax(0, 0.95fr)
    minmax(0, 0.7fr) minmax(0, 0.7fr) minmax(0, 0.85fr);
  gap: 5px 8px;
  align-items: center;
  margin-top: 13px;
}

.clg__th {
  padding-bottom: 7px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  overflow-wrap: anywhere;
}

.clg__th--num {
  text-align: right;
}

.clg__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 5px 0;
}

.clg__name {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.clg__sub {
  font-size: 7.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.clg__cell {
  min-width: 0;
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.clg__cell--last {
  color: #A6ADBD;
}

.clg__policy {
  justify-self: start;
  min-width: 0;
}

.clg__chip {
  display: inline-block;
  padding: 3px 8px;
  border-radius: 100px;
  background-color: rgba(109, 91, 246, 0.1);
  font-size: 8px;
  font-weight: 600;
  color: #5B4BE0;
  white-space: nowrap;
}

.clg__num {
  text-align: right;
  font-size: 9px;
  font-weight: 700;
  color: #22262F;
  white-space: nowrap;
}

/* A rep with no calls today keeps their row. The dash is the finding, so it is
   quiet rather than absent. */

.clg__num--nil {
  color: #C7CCD8;
  font-weight: 500;
}

.clg__foot {
  margin-top: auto;
  padding-top: 12px;
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

/* Both tables push their footer to the bottom of the sheet. */

.clg .sc-sheet,
.clh .sc-sheet {
  display: flex;
  flex-direction: column;
}

/* ==========================================================================
   04 — one employee's call history
   ========================================================================== */

.clh__back {
  font-size: 15px;
  line-height: 1;
  color: #A6ADBD;
}

.clh__role {
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
}

.clh__today {
  margin-left: auto;
  padding: 4px 10px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.09);
  font-size: 8.5px;
  font-weight: 700;
  color: #1D4ED8;
  white-space: nowrap;
}

.clh__list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 13px;
}

.clh__row {
  display: grid;
  grid-template-columns: 22px 34px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: 10px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.06);
}

/* Direction is an arrow as well as a colour: at this size a hue difference on
   a 10px icon is not something a reader should have to rely on. */

.clh__dir {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 100px;
}

.clh__dir svg {
  width: 12px;
  height: 12px;
}

.clh__dir--out {
  background-color: rgba(109, 91, 246, 0.1);
  color: #5B4BE0;
}

.clh__dir--in  {
  background-color: rgba(20, 184, 166, 0.12);
  color: #0F766E;
}

.clh__time {
  font-size: 9px;
  font-weight: 700;
  color: #8A90A0;
  white-space: nowrap;
}

.clh__body {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.clh__dur {
  font-size: 9px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
}

.clh__out {
  padding: 3px 8px;
  border-radius: 100px;
  font-size: 8px;
  font-weight: 700;
  white-space: nowrap;
}

.clh__out--connected {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.clh__out--voicemail {
  background-color: rgba(233, 162, 59, 0.15);
  color: #B45309;
}

.clh__out--no-answer {
  background-color: rgba(16, 24, 48, 0.06);
  color: #8A90A0;
}

/* ==========================================================================
   ENTRANCE

   Gated on `.sc-panel.is-showing`, not on the site's .reveal observer: inside
   a pinned stage a panel is shown and hidden repeatedly as the reader scrolls
   back and forth, and .reveal fires once and unobserves. This replays every
   time the step comes round, in either direction, with no state to keep. --i
   is authored on each row.

   The hero's own dashboard is left out: it is not in a pinned panel, and
   .hs-hero__art already carries it in on the page's reveal.
   ========================================================================== */

.sc-panel .cll__tile,
.sc-panel .clg__who,
.sc-panel .clg__cell,
.sc-panel .clg__policy,
.sc-panel .clg__num,
.sc-panel .clh__row {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition:
    opacity 460ms var(--ease-smooth),
    transform 560ms var(--ease-smooth);
  transition-delay: calc(180ms + var(--i, 0) * 60ms);
}

.sc-panel.is-showing .cll__tile,
.sc-panel.is-showing .clg__who,
.sc-panel.is-showing .clg__cell,
.sc-panel.is-showing .clg__policy,
.sc-panel.is-showing .clg__num,
.sc-panel.is-showing .clh__row {
  opacity: 1;
  transform: none;
}

/* The lines draw themselves rather than fading in, which is the movement a
   trend chart is actually about. The dash length is the longest a fourteen
   point polyline gets at this viewBox; anything shorter would leave a gap that
   never closes. */

.sc-panel .cld__plot .cll__line {
  stroke-dasharray: 900;
  stroke-dashoffset: 900;
  transition: stroke-dashoffset 1200ms var(--ease-smooth);
  transition-delay: 460ms;
}

.sc-panel.is-showing .cld__plot .cll__line {
  stroke-dashoffset: 0;
}

/* The live blip only pulses while its step is on screen. A badge animating
   inside a panel nobody is looking at is work the browser is doing for
   nothing. */

.sc-panel.is-showing .cll__blip {
  animation: cll-blip 2.2s ease-in-out infinite;
}

@keyframes cll-blip {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(22, 163, 74, 0);
  }

  45%      {
    box-shadow: 0 0 0 4px rgba(22, 163, 74, 0.22);
  }
}

/* Pin off: no sequence to arrive with, so everything is simply there. */

@media (max-width: 1023.98px) {
  .sc-panel .cll__tile,
  .sc-panel .clg__who,
  .sc-panel .clg__cell,
  .sc-panel .clg__policy,
  .sc-panel .clg__num,
  .sc-panel .clh__row {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .sc-panel .cld__plot .cll__line {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
    transition: none;
  }
}

/* Narrow frame: the header rows wrap, the tiles and the charts go two-up and
   then one, and the columns a reader checks last come out. The charts stay:
   they are what the dashboard is for.
   ========================================================================== */

@container (max-width: 380px) {
  .cll__bar,
  .clg__tools {
    flex-wrap: wrap;
  }

  .cll__range,
  .clh__today {
    margin-left: 0;
  }

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

  .cld__charts {
    grid-template-columns: minmax(0, 1fr);
  }

  .clg__search {
    display: none;
  }

  .clg__table {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.95fr) minmax(0, 0.7fr);
  }

  .clg__th:nth-child(2),
  .clg__th:nth-child(5),
  .clg__th:nth-child(6),
  .clg__cell {
    display: none;
  }

  .clg__table .clg__num:nth-of-type(2n) {
    display: none;
  }

  .clh__role {
    display: none;
  }

  .clh__row {
    grid-template-columns: 22px minmax(0, 1fr) auto;
  }

  .clh__time,
  .clh__dur {
    display: none;
  }
}

/* ==========================================================================
   THE HERO DASHBOARD — /call-monitoring-software/

   The hero on this page carries the whole screen rather than a summary of it,
   which is the exception on this site; see the note at the top of
   includes/call-ui.php. These rules are what the condensed version did not
   need: the application chrome, the icon on each tile, and the axes on the
   two charts.

   Everything else it uses is already defined above — .cll__tiles, the tile
   tones, .cld__tabs, .cld__consent, .cld__charts and the chart lines — so the
   hero and the two panels below it cannot drift into looking like two
   products.
   ========================================================================== */

/* The sheet is a column: the charts take the space the tiles leave rather than
   the sheet ending wherever the content happens to stop. */

.cll__sheet {
  display: flex;
  flex-direction: column;
}

/* ---- the application chrome ----
   It is what tells a reader this is a screen inside a product rather than a
   widget on a marketing page, which is the claim the copy beside it makes
   about not needing a second app. */

.cll__chrome {
  display: flex;
  align-items: center;
  gap: 9px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.07);
}

.cll__omni {
  display: flex;
  align-items: center;
  gap: 7px;
  flex: 1;
  min-width: 0;
  padding: 5px 6px 5px 11px;
  border-radius: 100px;
  background-color: #F4F6FB;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
}

.cll__mag {
  display: grid;
  place-items: center;
  flex: none;
  color: #A6ADBD;
}

.cll__mag svg {
  width: 11px;
  height: 11px;
}

.cll__kbd {
  flex: none;
  margin-left: auto;
  padding: 2px 7px;
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.1);
  font-style: normal;
  font-size: 7.5px;
  font-weight: 700;
  color: #8A90A0;
}

.cll__bell {
  position: relative;
  flex: none;
  width: 18px;
  height: 18px;
  border-radius: 100px;
  background-color: #F4F6FB;
}

.cll__count {
  position: absolute;
  top: -5px;
  right: -7px;
  padding: 1px 4px;
  border-radius: 100px;
  background-color: #DC2626;
  font-size: 6.5px;
  font-weight: 700;
  color: #ffffff;
  line-height: 1.4;
}

.cll__me {
  flex: none;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 100px;
  background-image: linear-gradient(150deg, #7C6BF8 0%, #5B4BE0 100%);
  font-size: 8.5px;
  font-weight: 700;
  color: #ffffff;
}

/* ---- the page heading ---- */

.cll__head {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: 11px;
}

.cll__h1 {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15px;
  font-weight: 600;
  color: #0B0D12;
}

.cll__phone {
  display: grid;
  place-items: center;
  color: #5B4BE0;
}

.cll__phone svg {
  width: 14px;
  height: 14px;
}

.cll__sub {
  font-size: 8.5px;
  font-weight: 500;
  color: #8A90A0;
}

/* The tab strip and the range sit on one line under the heading. */

.cll .cll__bar {
  margin-top: 11px;
}

/* ---- the tiles, with an icon ----
   The grid, the tones and the type are the ones already defined above; this
   adds the icon square and the second line the on-duty and missed tiles have.
   Seven tiles on a four-column track: four, then three with the last taking
   the width the fourth would have. */

.cll__tiles > li:nth-child(7) {
  grid-column: span 2;
}

.cll__tile {
  flex-direction: row;
  align-items: flex-start;
  gap: 9px;
}

.cll__ico {
  flex: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 8px;
  background-color: rgba(255, 255, 255, 0.75);
  color: #5B4BE0;
}

.cll__figs {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.cll__note {
  font-size: 7.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
}

/* Each tile's icon takes its own tone, so the colour on the square and the
   colour on the figure beside it are the same statement. */

.cll__tile--plain .cll__ico {
  background-color: rgba(16, 24, 48, 0.05);
  color: #5A6070;
}

.cll__tile--duty  .cll__ico {
  background-color: rgba(22, 163, 74, 0.14);
  color: #15803D;
}

.cll__tile--calls .cll__ico {
  background-color: rgba(37, 99, 235, 0.12);
  color: #1D4ED8;
}

.cll__tile--out   .cll__ico {
  background-color: rgba(109, 91, 246, 0.15);
  color: #5B4BE0;
}

.cll__tile--in    .cll__ico {
  background-color: rgba(20, 184, 166, 0.16);
  color: #0F766E;
}

.cll__tile--talk  .cll__ico {
  background-color: rgba(139, 92, 246, 0.15);
  color: #6D28D9;
}

.cll__tile--miss  .cll__ico {
  background-color: rgba(220, 38, 38, 0.12);
  color: #B91C1C;
}

/* ---- the chart axes ----
   The condensed version had none: a sparkline is read as a shape. A full chart
   is read as values, and values with no scale beside them are decoration. */

.cll__plotwrap {
  display: flex;
  align-items: stretch;
  gap: 7px;
  margin-top: 7px;
}

/* Five ticks, spread down the plot's own height so each one lands on its
   gridline rather than near it. */

.cll__yaxis {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  flex: none;
  padding: 4px 0;
  text-align: right;
}

.cll__yaxis em {
  font-style: normal;
  font-size: 7px;
  font-weight: 600;
  color: #C0C5D2;
  line-height: 1;
}

.cll__plotwrap .cld__plot {
  margin-top: 0;
}

/* Gridlines inside the plot, not behind it: they scale with the viewBox, so
   they stay on the tick values at any width. */

.cll__grid {
  stroke: rgba(16, 24, 48, 0.07);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* The plot and its date row are one column beside the y-axis, so the labels
   line up with the points rather than with a padding somebody guessed. The
   stroke is clipped here: a round line cap at x=240 otherwise hangs over the
   edge of the card. */

.cll__plotcol {
  flex: 1;
  min-width: 0;
  overflow: hidden;
}

/* Fourteen cells so every label sits under its own point; the empty ones are
   the days between the labelled ones. */

.cll__xaxis {
  display: grid;
  grid-template-columns: repeat(14, minmax(0, 1fr));
  margin-top: 5px;
}

.cll__xaxis em {
  font-style: normal;
  font-size: 6.5px;
  font-weight: 600;
  color: #C0C5D2;
  white-space: nowrap;
}

/* Narrow frame: the chrome, the axes and the second chart are the first things
   to go. The tiles and the calls chart are what the hero is showing. */

@container (max-width: 380px) {
  .cll__chrome,
  .cll__xaxis,
  .cll__sub {
    display: none;
  }

  .cll__tiles > li:nth-child(7) {
    grid-column: span 2;
  }

  .cll__tile {
    gap: 7px;
  }

  .cll__ico {
    width: 20px;
    height: 20px;
  }
}

/* ==========================================================================
   THE SWITCH — /call-monitoring-software/

   Two states of the same thing in one container, rather than two cards with a
   gap between them. The join is the argument: pale on the left is what a team
   has, dark on the right is what replaces it, and the badge sitting on the
   seam is the word "becomes" without anybody writing it.

   Deliberately NOT an edit to .en-vs. The candidate engagement page runs that
   block and has no reason to change, so this is its own.
   ========================================================================== */

.cmvs {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  margin-top: 48px;
  border-radius: 26px;
  /* The two grounds meet with no gap and no rule between them, so the corners
     have to be clipped by the container rather than by each half. */
  overflow: hidden;
  box-shadow:
    0 34px 80px -42px rgba(16, 24, 48, 0.5),
    0 2px 10px rgba(16, 24, 48, 0.06);
}

@media (min-width: 900px) {
  .cmvs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.cmvs__side {
  padding: 34px 30px 36px;
}

@media (min-width: 768px) {
  .cmvs__side {
    padding: 40px 38px 44px;
  }
}

.cmvs__side--before {
  background-color: #EEF0F5;
}

/* The dark half carries a brand wash from its top-left corner, which is the
   corner the seam is on. It is what stops the panel reading as a black
   rectangle and it points the eye back at the join. */

.cmvs__side--after {
  position: relative;
  background-color: #0B0D12;
  background-image:
    radial-gradient(120% 100% at 8% 0%, rgba(37, 99, 235, 0.3) 0%, rgba(37, 99, 235, 0) 62%);
}

.cmvs__tag {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.cmvs__side--before .cmvs__tag {
  color: #8A90A0;
}

.cmvs__side--after .cmvs__tag  {
  color: rgba(255, 255, 255, 0.5);
}

.cmvs__list {
  display: grid;
  gap: 15px;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}

.cmvs__item {
  display: flex;
  align-items: flex-start;
  gap: 13px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.45;
}

.cmvs__side--before .cmvs__item {
  color: #5A6070;
}

.cmvs__side--after .cmvs__item  {
  color: #ffffff;
}

.cmvs__mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  /* The optical centre of a 22px disc against a 15px line at 1.45 leading. */
  margin-top: 1px;
  border-radius: 100px;
}

/* A dash, not a cross. The left column is not wrong, it is what a team has
   before it buys anything, and a red X would be calling their current
   arrangement a mistake. */

.cmvs__mark--no {
  background-color: rgba(16, 24, 48, 0.06);
}

.cmvs__mark--no::before {
  content: '';
  width: 9px;
  height: 1.5px;
  border-radius: 100px;
  background-color: #A6ADBD;
}

/* Brand blue on the dark ground, not the near-navy this used to be: a tick the
   same value as the panel behind it is a tick nobody can see. */

.cmvs__mark--yes {
  background-color: #2563EB;
  color: #ffffff;
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.16);
}

.cmvs__mark--yes svg {
  width: 12px;
  height: 12px;
  stroke-width: 2.4;
}

/* ---- the badge on the seam ----
   Positioned against the dark half rather than the container, so it lands on
   the join at both layouts without anything having to measure where the
   boundary fell: centred on that half's top edge while the two are stacked,
   and on its left edge once they sit side by side. */

.cmvs__step {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 50%;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  transform: translate(-50%, -50%) rotate(90deg);
  border-radius: 100px;
  background-color: #ffffff;
  box-shadow:
    0 0 0 1px rgba(16, 24, 48, 0.08),
    0 10px 24px -10px rgba(16, 24, 48, 0.45);
  color: #0B0D12;
}

.cmvs__step svg {
  width: 18px;
  height: 18px;
}

@media (min-width: 900px) {
  .cmvs__step {
    top: 50%;
    left: 0;
    transform: translate(-50%, -50%);
  }
}

/* The badge overlaps the pale half, so that half needs room for it to sit in
   rather than landing on a line of text. */

@media (min-width: 900px) {
  .cmvs__side--before {
    padding-right: 46px;
  }

  .cmvs__side--after  {
    padding-left: 46px;
  }
}

/* ==========================================================================
   THE CRM ARTWORKS — /crm-software/

   .cro the overview dashboard in the hero, .crl leads, .crc contacts, .cra
   accounts, .crd the deal board, .crs settings. All six sit in the blue box
   registered above, so every rule here assumes the near-white sheet .sc-sheet
   paints.

   NOT .crm__
   That namespace belongs to includes/crm-ui.php, the artwork the home page's
   showcase uses. Borrowing it would restyle that panel from this page.

   The five sequence panels share .cro__ parts wherever they draw the same
   object: the title, the count beside it, the table head, the person cell, the
   status pill, the pager. Six copies of a status pill would be six places for
   its colour to drift, and these six sit within one screen of each other.

   ONE COLOUR PER STATUS, DEFINED ONCE
   Every pill, avatar and donut segment takes its colour from --c, which comes
   from $CR_STATUSES in PHP. The settings panel that configures those statuses
   therefore cannot show a different colour from the screens it configures.
   ========================================================================== */

/* The frame the five sequence panels share. Measured against the tallest,
   which is the deal board with its four columns. */

.sc-panel__frame--cr {
  display: flex;
  min-height: 440px;
  background-color: #DCE4F6;
}

.sc-panel__frame--cr > * {
  flex: 1;
  min-height: 0;
}

.cro__sheet,
.crl__sheet {
  display: flex;
  flex-direction: column;
}

/* ==========================================================================
   Shared chrome
   ========================================================================== */

.cro__title {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.cro__count {
  font-family: system-ui, sans-serif;
  font-style: normal;
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.cro__group {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 13px;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.cro__groupnote {
  font-style: normal;
  letter-spacing: 0;
  text-transform: none;
  font-size: 8px;
  font-weight: 500;
  color: #C0C5D2;
}

.cro__ghost,
.cro__go {
  padding: 5px 11px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
  white-space: nowrap;
}

.cro__ghost {
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
  color: #5A6070;
}

.cro__go {
  background-image: linear-gradient(150deg, #7C6BF8 0%, #5B4BE0 100%);
  color: #ffffff;
}

.cro__search {
  flex: 1;
  min-width: 0;
  padding: 5px 11px;
  border-radius: 100px;
  background-color: #F4F6FB;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- the tiles ---- */

.cro__tiles {
  display: grid;
  gap: 7px;
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}

.cro__tiles--six  {
  grid-template-columns: repeat(6, minmax(0, 1fr));
}

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

@media (min-width: 640px) {
  .cro__tiles--four {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.cro__tile {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 8px 9px;
  border-radius: 9px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.cro__amount {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: #0B0D12;
  white-space: nowrap;
}

.cro__label {
  font-size: 7.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  line-height: 1.25;
}

.cro__note {
  margin-top: 2px;
  font-size: 7.5px;
  font-weight: 500;
  color: #C0C5D2;
  line-height: 1.3;
}

.cro__tile--lead {
  background-color: rgba(109, 91, 246, 0.08);
  box-shadow: none;
}

.cro__tile--lead .cro__amount {
  color: #5B4BE0;
}

.cro__tile--good {
  background-color: rgba(22, 163, 74, 0.09);
  box-shadow: none;
}

.cro__tile--good .cro__amount {
  color: #15803D;
}

.cro__tile--pipe {
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: none;
}

.cro__tile--pipe .cro__amount {
  color: #1D4ED8;
}

.cro__tile--won  {
  background-color: rgba(22, 163, 74, 0.09);
  box-shadow: none;
}

.cro__tile--won .cro__amount {
  color: #15803D;
}

.cro__tile--rate {
  background-color: rgba(233, 162, 59, 0.13);
  box-shadow: none;
}

.cro__tile--rate .cro__amount {
  color: #B45309;
}

.cro__tile--open {
  background-color: rgba(20, 184, 166, 0.11);
  box-shadow: none;
}

.cro__tile--open .cro__amount {
  color: #0F766E;
}

/* ==========================================================================
   01 — the overview charts
   ========================================================================== */

.cro__charts {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: 9px;
  margin-top: 11px;
}

.cro__card {
  padding: 10px 11px 9px;
  border-radius: 11px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.07);
}

.cro__donutwrap {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-top: 9px;
}

/* One conic-gradient built in PHP from the status counts, so the ring is the
   data rather than a picture of it. The segments meet with no seam because
   each one starts where the last ended, at the exact share rather than the
   rounded percentage printed in the legend. */

.cro__donut {
  position: relative;
  flex: none;
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  border-radius: 100px;
  background-image: conic-gradient(var(--stops));
}

.cro__hole {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 100px;
  background-color: #ffffff;
  text-align: center;
}

.cro__holenum {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-style: normal;
  font-size: 15px;
  font-weight: 600;
  color: #0B0D12;
  line-height: 1;
}

.cro__holelab {
  font-style: normal;
  font-size: 7px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.cro__legend {
  display: grid;
  gap: 4px;
  flex: 1;
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.cro__legend li {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 8.5px;
  font-weight: 500;
  color: #5A6070;
}

.cro__swatch {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background-color: var(--c);
}

.cro__legname {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cro__legnum {
  margin-left: auto;
  font-weight: 700;
  color: #22262F;
  white-space: nowrap;
}

.cro__legnum em {
  font-style: normal;
  font-weight: 500;
  color: #A6ADBD;
}

/* ---- the revenue bars ---- */

.cro__barwrap {
  display: flex;
  gap: 7px;
  margin-top: 9px;
}

.cro__yaxis {
  padding: 0 0 12px;
}

.cro__bars {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: end;
  gap: 3px;
  flex: 1;
  min-width: 0;
  height: 86px;
}

.cro__bar {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  height: 100%;
  min-width: 0;
}

/* Scaled to the biggest month, not to a round number: the bars are a ranking,
   and a ranking whose tallest bar stops short reads as missing data. */

.cro__fill {
  height: var(--h);
  border-radius: 3px 3px 0 0;
  background-image: linear-gradient(180deg, #34D399 0%, #16A34A 100%);
}

.cro__month {
  margin-top: 4px;
  font-style: normal;
  font-size: 6.5px;
  font-weight: 600;
  color: #C0C5D2;
  text-align: center;
  white-space: nowrap;
}

/* ==========================================================================
   The four tables — leads, contacts, accounts, and the shared parts
   ========================================================================== */

.crl__acts {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
}

.crl__quick {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 12px;
}

.crl__qlabel {
  margin-right: 3px;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.crl__chip {
  padding: 4px 9px;
  border-radius: 100px;
  background-color: #F4F6FB;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.crl__chip.is-on {
  background-image: linear-gradient(150deg, #7C6BF8 0%, #5B4BE0 100%);
  color: #ffffff;
}

.crl__table,
.crc__table,
.cra__table {
  display: grid;
  gap: 5px 8px;
  align-items: center;
  margin-top: 13px;
}

.crl__table {
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 0.8fr) minmax(0, 0.7fr) minmax(0, 0.85fr);
}

.crc__table {
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 0.85fr) minmax(0, 0.9fr);
}

.cra__table {
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 0.9fr) minmax(0, 0.7fr) minmax(0, 1fr) minmax(0, 0.85fr);
}

.cro__th {
  padding-bottom: 7px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
  overflow-wrap: anywhere;
}

.cro__th--num {
  text-align: right;
}

.cro__who {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 5px 0;
}

/* The avatar takes the same --c the row's status pill does, so a glance down
   the first column reads as the same information as a glance down the last. */

.cro__av {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 100px;
  background-color: color-mix(in srgb, var(--c) 14%, transparent);
  font-size: 8px;
  font-weight: 700;
  color: var(--c);
}

.cra__logo {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background-color: rgba(109, 91, 246, 0.1);
  color: #5B4BE0;
}

.cra__logo svg {
  width: 13px;
  height: 13px;
}

.cro__whotext {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.cro__name {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cro__sub {
  font-size: 7.5px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cro__cell {
  min-width: 0;
  font-size: 8.5px;
  font-weight: 500;
  color: #5A6070;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A record that is incomplete says so quietly rather than being hidden. */

.cro__cell--nil {
  color: #C7CCD8;
}

.cro__cell--dim {
  color: #A6ADBD;
}

.cro__num {
  text-align: right;
  font-size: 8.5px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
}

.crl__due {
  display: inline-block;
  padding: 2px 7px;
  border-radius: 100px;
  background-color: rgba(220, 38, 38, 0.09);
  font-style: normal;
  font-size: 8px;
  font-weight: 700;
  color: #B91C1C;
}

.cro__state {
  justify-self: start;
  min-width: 0;
}

/* One pill, coloured from the status it prints. --c comes from PHP, so the
   settings panel and every screen it configures cannot disagree. */

.cro__pill {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 100px;
  background-color: color-mix(in srgb, var(--c) 13%, transparent);
  font-size: 8px;
  font-weight: 700;
  color: var(--c);
  white-space: nowrap;
}

.cro__foot {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: auto;
  padding-top: 12px;
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.cro__pager {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
}

.cro__pager em {
  padding: 3px 8px;
  border-radius: 6px;
  font-style: normal;
  font-size: 8px;
  font-weight: 600;
  color: #8A90A0;
}

.cro__pager em.is-on {
  background-color: rgba(109, 91, 246, 0.12);
  color: #5B4BE0;
}

/* ==========================================================================
   04 — the deal board
   ========================================================================== */

.crd__views {
  display: flex;
  gap: 3px;
  padding: 3px;
  border-radius: 100px;
  background-color: #F4F6FB;
}

.crd__view {
  padding: 3px 9px;
  border-radius: 100px;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.crd__view.is-on {
  background-color: #ffffff;
  color: #5B4BE0;
}

.crd__board {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin-top: 13px;
}

.crd__col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 9px 8px 8px;
  border-radius: 11px;
  background-color: #F4F6FB;
  min-width: 0;
}

.crd__colhead {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.crd__dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 100px;
  background-color: var(--c);
}

.crd__colname {
  font-size: 8.5px;
  font-weight: 700;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.crd__coln {
  flex: none;
  margin-left: auto;
  padding: 1px 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.07);
  font-size: 7.5px;
  font-weight: 700;
  color: #5A6070;
}

/* Each column totals its own cards, so the board header and the four column
   figures are five sums of the same array rather than five typed numbers. */

.crd__coltotal {
  font-size: 8px;
  font-weight: 600;
  color: #A6ADBD;
}

.crd__card {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 8px 9px;
  border-radius: 9px;
  background-color: #ffffff;
  box-shadow:
    inset 0 0 0 1px rgba(16, 24, 48, 0.06),
    0 4px 12px -8px rgba(16, 24, 48, 0.5);
}

.crd__cardname {
  font-size: 9px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.crd__cardval {
  font-size: 9px;
  font-weight: 700;
  color: #1D4ED8;
  white-space: nowrap;
}

/* A stage with nothing in it keeps its column. The drop zone is what tells a
   reader the stage exists at all. */

.crd__empty {
  display: grid;
  place-items: center;
  padding: 14px 6px;
  border-radius: 9px;
  border: 1px dashed rgba(16, 24, 48, 0.14);
  font-size: 8px;
  font-weight: 600;
  color: #C0C5D2;
  text-align: center;
}

.crd__add {
  margin-top: auto;
  padding-top: 4px;
  font-size: 8px;
  font-weight: 600;
  color: #A6ADBD;
}

/* ==========================================================================
   05 — the settings screen
   ========================================================================== */

.crs__tabs {
  margin-bottom: 13px;
}

.crs .scr__tab.is-on {
  color: #5B4BE0;
}

.crs .scr__tab.is-on::after {
  background-color: #5B4BE0;
}

.crs__bar {
  align-items: flex-start;
}

.crs__head {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.crs__bar .cro__go {
  margin-left: auto;
  flex: none;
}

.crs__list {
  display: flex;
  flex-direction: column;
  margin-top: 13px;
}

.crs__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 2px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.06);
}

.crs__row:last-child {
  border-bottom: none;
}

.crs__grab {
  flex: none;
  display: grid;
  place-items: center;
  width: 12px;
  height: 12px;
  color: #C7CCD8;
}

.crs__grab svg {
  width: 100%;
  height: 100%;
}

.crs__pill {
  font-size: 9px;
  padding: 4px 11px;
}

.crs__system {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.05);
  font-size: 7.5px;
  font-weight: 700;
  color: #8A90A0;
  white-space: nowrap;
}

.crs__lock {
  display: grid;
  place-items: center;
  width: 9px;
  height: 9px;
}

.crs__lock svg {
  width: 100%;
  height: 100%;
}

.crs__acts {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-left: auto;
}

.crs__act {
  display: grid;
  place-items: center;
  width: 13px;
  height: 13px;
  color: #A6ADBD;
}

.crs__act svg {
  width: 100%;
  height: 100%;
}

/* ==========================================================================
   ENTRANCE

   Gated on `.sc-panel.is-showing`, not on the site's .reveal observer: inside
   a pinned stage a panel is shown and hidden repeatedly as the reader scrolls
   back and forth, and .reveal fires once and unobserves. This replays every
   time the step comes round, in either direction, with no state to keep. --i
   is authored on each row.

   The hero's own dashboard is left out: it is not in a pinned panel, and
   .hs-hero__art already carries it in on the page's reveal.
   ========================================================================== */

.sc-panel .cro__who,
.sc-panel .cro__cell,
.sc-panel .cro__num,
.sc-panel .cro__state,
.sc-panel .crd__col,
.sc-panel .crs__row {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition:
    opacity 460ms var(--ease-smooth),
    transform 560ms var(--ease-smooth);
  transition-delay: calc(180ms + var(--i, 0) * 70ms);
}

.sc-panel.is-showing .cro__who,
.sc-panel.is-showing .cro__cell,
.sc-panel.is-showing .cro__num,
.sc-panel.is-showing .cro__state,
.sc-panel.is-showing .crd__col,
.sc-panel.is-showing .crs__row {
  opacity: 1;
  transform: none;
}

/* Pin off: no sequence to arrive with, so everything is simply there. */

@media (max-width: 1023.98px) {
  .sc-panel .cro__who,
  .sc-panel .cro__cell,
  .sc-panel .cro__num,
  .sc-panel .cro__state,
  .sc-panel .crd__col,
  .sc-panel .crs__row {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Narrow frame: the header rows wrap, the six-tile row halves, the charts and
   the board stack, and the columns a reader checks last come out. The donut,
   the bars and the deal cards stay: they are what the screens are for.
   ========================================================================== */

@container (max-width: 380px) {
  .cll__bar,
  .crl__quick,
  .crl__acts {
    flex-wrap: wrap;
  }

  .crl__acts,
  .cro__pager,
  .crs__bar .cro__go {
    margin-left: 0;
  }

  .cro__tiles--six {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .cro__charts {
    grid-template-columns: minmax(0, 1fr);
  }

  .cro__month {
    display: none;
  }

  .cro__search {
    display: none;
  }

  .crl__table {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 0.9fr);
  }

  .crl__table .cro__th:nth-child(3),
  .crl__table .cro__th:nth-child(4),
  .crl__table .cro__cell:nth-of-type(3n + 2),
  .crl__table .cro__cell:nth-of-type(3n) {
    display: none;
  }

  .crc__table {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 0.9fr);
  }

  .crc__table .cro__th:nth-child(3),
  .crc__table .cro__th:nth-child(5),
  .crc__table .cro__cell--dim {
    display: none;
  }

  .cra__table {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 0.9fr);
  }

  .cra__table .cro__th:nth-child(3),
  .cra__table .cro__th:nth-child(4),
  .cra__table .cro__num {
    display: none;
  }

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

  /* The four settings tabs are one nowrap flex row and overran the sheet by
     14px at this width. They wrap rather than scroll: a tab strip that has to
     be dragged sideways hides the tab a reader is looking for. */

  .crs__tabs {
    flex-wrap: wrap;
    gap: 6px 12px;
  }

  .crs__head .cll__sub {
    display: none;
  }
}

/* ==========================================================================
   THE PROJECT ARTWORKS — /project-management-software/

   .pjd the project dashboard in the hero, .pjn create project, .pjt create
   task, .pjb the board, .pjm members, .pjs settings. All six sit in the blue
   box registered above, so every rule here assumes the near-white sheet
   .sc-sheet paints.

   NOT .pr*
   That prefix is taken by the pricing blocks and the performance artwork.

   The six share the CRM page's .cro__ table and tile parts and the travel
   desk's .tvn__ form parts, because those are the same objects. A seventh copy
   of a form field would be a seventh place for its padding to drift.

   ONE COLOUR PER PROJECT
   Every card, key badge and avatar takes --c, which comes from $PJ_PROJECTS in
   PHP. The board panel and the members panel therefore carry the same colour
   the hero card gave that project.
   ========================================================================== */

/* The frame the five sequence panels share. Measured against the tallest,
   which is the create-task form. */

.sc-panel__frame--pj {
  display: flex;
  min-height: 455px;
  background-color: #DCE4F6;
}

.sc-panel__frame--pj > * {
  flex: 1;
  min-height: 0;
}

/* ==========================================================================
   01 — the project dashboard
   ========================================================================== */

.pjd__bar {
  margin-top: 12px;
}

.pjd__toggle {
  display: flex;
  gap: 3px;
  padding: 3px;
  border-radius: 8px;
  background-color: #F4F6FB;
}

.pjd__tog {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 6px;
  color: #A6ADBD;
}

.pjd__tog svg {
  width: 12px;
  height: 12px;
}

.pjd__tog.is-on {
  background-color: #ffffff;
  color: #5B4BE0;
}

.pjd__tabs {
  margin-top: 12px;
}

.pjd .scr__tab.is-on,
.pjm .scr__tab.is-on,
.pjs .scr__tab.is-on {
  color: #5B4BE0;
}

.pjd .scr__tab.is-on::after,
.pjm .scr__tab.is-on::after,
.pjs .scr__tab.is-on::after {
  background-color: #5B4BE0;
}

/* The count beside a tab, so the strip is a summary rather than a row of
   filters. */

.scr__tab em {
  margin-left: 5px;
  padding: 1px 5px;
  border-radius: 100px;
  background-color: rgba(109, 91, 246, 0.12);
  font-style: normal;
  font-size: 7.5px;
  font-weight: 700;
}

.pjd__tiles {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 12px;
}

.cro__tile--proj {
  background-color: rgba(109, 91, 246, 0.08);
  box-shadow: none;
}

.cro__tile--proj .cro__amount {
  color: #5B4BE0;
}

.cro__tile--done {
  background-color: rgba(22, 163, 74, 0.09);
  box-shadow: none;
}

.cro__tile--done .cro__amount {
  color: #15803D;
}

.cro__tile--team {
  background-color: rgba(37, 99, 235, 0.07);
  box-shadow: none;
}

.cro__tile--team .cro__amount {
  color: #1D4ED8;
}

.pjd__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-top: 10px;
}

/* The project's own colour runs down the left edge of its card, which is what
   ties it to the same colour on the board and the members panel. */

.pjd__card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 11px 11px;
  border-radius: 11px;
  border-left: 3px solid var(--c);
  background-color: #ffffff;
  box-shadow:
    inset 0 0 0 1px rgba(16, 24, 48, 0.06),
    0 5px 16px -12px rgba(16, 24, 48, 0.5);
}

.pjd__top {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.pjd__key {
  flex: none;
  padding: 2px 6px;
  border-radius: 5px;
  background-color: color-mix(in srgb, var(--c) 14%, transparent);
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--c);
}

.pjd__name {
  font-size: 10px;
  font-weight: 600;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pjd__track {
  height: 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.07);
}

/* The bar is the card's own done-over-total, worked out in PHP. */

.pjd__fill {
  display: block;
  width: var(--w);
  height: 100%;
  border-radius: 100px;
  background-color: var(--c);
}

.pjd__meta {
  display: flex;
  align-items: baseline;
  gap: 9px;
}

.pjd__pct {
  font-size: 9.5px;
  font-weight: 700;
  color: var(--c);
}

.pjd__stat {
  font-size: 8px;
  font-weight: 500;
  color: #A6ADBD;
  white-space: nowrap;
}

/* ==========================================================================
   02, 03 — the two forms

   They use the travel desk's .tvn__ field, input, pair and footer parts. These
   are the pieces those forms do not have.
   ========================================================================== */

.pjn__hint {
  font-size: 7.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.pjn__hint em {
  font-style: normal;
  font-weight: 700;
  color: #5B4BE0;
}

.pjn__swatches {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 0;
}

.pjn__swatch {
  width: 16px;
  height: 16px;
  border-radius: 100px;
  background-color: var(--c);
}

/* The chosen colour gets a ring rather than a tick: a tick inside a 16px disc
   is a smudge at this size. */

.pjn__swatch.is-on {
  box-shadow: 0 0 0 2px #ffffff, 0 0 0 3.5px var(--c);
}

.pjn__lead {
  gap: 7px;
}

.pjn__lead .cro__av {
  width: 18px;
  height: 18px;
  font-size: 7px;
}

.pjn__opts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.pjn__opt {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 10px;
  border-radius: 9px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.12);
}

.pjn__opt.is-on {
  background-color: rgba(109, 91, 246, 0.07);
  box-shadow: inset 0 0 0 1.5px #5B4BE0;
}

.pjn__optname {
  font-style: normal;
  font-size: 9px;
  font-weight: 700;
  color: #22262F;
}

.pjn__optnote {
  font-style: normal;
  font-size: 7.5px;
  font-weight: 500;
  line-height: 1.35;
  color: #A6ADBD;
}

/* ---- priority ----
   Three weights as three colours AND three words, and the same chip is used on
   the board so a priority reads the same on the form that set it. */

.pjt__prios {
  display: flex;
  gap: 5px;
}

.pjt__prio {
  padding: 4px 9px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.05);
  font-size: 8px;
  font-weight: 700;
  color: #8A90A0;
  white-space: nowrap;
}

.pjt__prio--high.is-on,
.pjb__card .pjt__prio--high {
  background-color: rgba(220, 38, 38, 0.1);
  color: #B91C1C;
}

.pjt__prio--med.is-on,
.pjb__card .pjt__prio--med  {
  background-color: rgba(233, 162, 59, 0.16);
  color: #B45309;
}

.pjt__prio--low.is-on,
.pjb__card .pjt__prio--low  {
  background-color: rgba(16, 24, 48, 0.06);
  color: #8A90A0;
}

.pjt__drop {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 10px;
  border-radius: 8px;
  border: 1px dashed rgba(16, 24, 48, 0.16);
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.pjt__clip {
  display: grid;
  place-items: center;
  width: 12px;
  height: 12px;
}

.pjt__clip svg {
  width: 100%;
  height: 100%;
}

/* The form's own claim, printed where the reader is about to act on it. */

.pjt__lands {
  margin-right: auto;
  font-size: 8.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.pjt__lands em {
  font-style: normal;
  font-weight: 700;
  color: #5A6070;
}

/* ==========================================================================
   04 — the board
   ========================================================================== */

.pjb__title {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.pjb__board {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 7px;
  margin-top: 13px;
}

.pjb__col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* 6px, not 7. "Content" was two pixels too long for its header and came out
     as "Cont…", which reads as a fault rather than as a long word. */
  padding: 8px 6px;
  border-radius: 10px;
  background-color: #F4F6FB;
  min-width: 0;
}

/* "Content" needed 33.3px of the 33.0px its header had left, which is why it
   came out as "Cont…". A pixel off each of the two gaps is the whole fix; the
   shared header keeps its 6px everywhere else. */

.pjb__col .crd__colhead {
  gap: 5px;
}

.pjb__card {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 8px;
  border-radius: 8px;
  background-color: #ffffff;
  box-shadow:
    inset 0 0 0 1px rgba(16, 24, 48, 0.06),
    0 4px 12px -9px rgba(16, 24, 48, 0.5);
}

.pjb__cardtop {
  display: flex;
  align-items: center;
  gap: 6px;
}

.pjb__id {
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: #A6ADBD;
  white-space: nowrap;
}

/* The pill on a board card, tighter than the one on the task screen. At five
   columns a card has 56px of content, and "WEB-27" plus a Medium pill at the
   task screen's size measured 74px: every pill on the board hung over the
   right edge of its own card, the Medium ones by 18px. Nothing about that was
   visible as an overflow; it just read as cards that did not line up. */

.pjb__card .pjt__prio {
  margin-left: auto;
  flex: none;
  padding: 2px 4px;
  font-size: 6.5px;
  line-height: 1.25;
  white-space: nowrap;
}

.pjb__cardtop {
  gap: 4px;
}

/* Two lines, always. The column is 56px wide, so a long title wrapped to
   three and made that one card taller than the four beside it, which read as
   a board that had gone wrong rather than as cards of different lengths. The
   height is reserved whether the title needs it or not, so every card in the
   row sits on the same baseline; the clamp is the backstop for a title
   somebody lengthens later. */

.pjb__cardname {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  min-height: calc(2 * 1.35 * 9px);
  font-size: 9px;
  font-weight: 600;
  line-height: 1.35;
  color: #22262F;
}

.pjb__cardfoot {
  display: flex;
  align-items: center;
  gap: 6px;
}

.pjb__due {
  font-size: 7.5px;
  font-weight: 600;
  color: #8A90A0;
  white-space: nowrap;
}

.pjb__av {
  margin-left: auto;
  width: 18px;
  height: 18px;
  font-size: 7px;
}

/* A column that cannot show all its cards says how many it is hiding, rather
   than letting the reader conclude the column is short. */

.pjb__more {
  margin-top: auto;
  padding-top: 2px;
  font-size: 7.5px;
  font-weight: 600;
  color: #A6ADBD;
  text-align: center;
}

/* ==========================================================================
   05 — members
   ========================================================================== */

.pjm__tabs {
  margin-top: 12px;
}

.pjm__table {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.8fr) minmax(0, 1fr);
  gap: 5px 10px;
  align-items: center;
  margin-top: 13px;
}

/* Three roles, three weights. Owner is the only one that reads as authority,
   which is the point of there being one of them. */

.pjm__role {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 100px;
  font-size: 8px;
  font-weight: 700;
  white-space: nowrap;
}

.pjm__role--owner  {
  background-color: rgba(109, 91, 246, 0.13);
  color: #5B4BE0;
}

.pjm__role--admin  {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

.pjm__role--member {
  background-color: rgba(16, 24, 48, 0.06);
  color: #5A6070;
}

/* ==========================================================================
   06 — notification settings

   A matrix, not a list of switches: the decision is this kind of alert on that
   channel, and a list would need four switches per row to say the same thing
   in four times the space.
   ========================================================================== */

.pjs__matrix {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) repeat(var(--pjs-cols, 4), minmax(0, 0.5fr));
  gap: 6px 8px;
  align-items: center;
  margin-top: 13px;
}

.pjs__chhead {
  text-align: center;
}

.pjs__event {
  font-size: 9px;
  font-weight: 500;
  color: #5A6070;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pjs__cell {
  display: grid;
  place-items: center;
}

.pjs__sw {
  position: relative;
  width: 24px;
  height: 13px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.14);
}

.pjs__sw.is-on {
  background-color: #5B4BE0;
}

.pjs__knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 9px;
  height: 9px;
  border-radius: 100px;
  background-color: #ffffff;
}

.pjs__sw.is-on .pjs__knob {
  left: auto;
  right: 2px;
}

/* The digest is the claim the panel is really making, so it sits under the
   matrix with what it contains rather than as one more switch inside it. */

.pjs__digest {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
  padding: 11px 12px;
  border-radius: 11px;
  background-color: rgba(109, 91, 246, 0.07);
}

.pjs__digestwrap {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.pjs__digestname {
  font-size: 9.5px;
  font-weight: 700;
  color: #22262F;
}

.pjs__digestnote {
  font-size: 8px;
  font-weight: 500;
  line-height: 1.4;
  color: #8A90A0;
}

.pjs__digest .pjs__sw {
  flex: none;
  margin-left: auto;
}

/* ==========================================================================
   ENTRANCE

   Gated on `.sc-panel.is-showing`, not on the site's .reveal observer: inside
   a pinned stage a panel is shown and hidden repeatedly as the reader scrolls
   back and forth, and .reveal fires once and unobserves. --i is authored on
   each row.

   The hero's own dashboard is left out: it is not in a pinned panel, and
   .hs-hero__art already carries it in on the page's reveal.
   ========================================================================== */

.sc-panel .pjb__col,
.sc-panel .pjs__event,
.sc-panel .pjs__cell {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition:
    opacity 460ms var(--ease-smooth),
    transform 560ms var(--ease-smooth);
  transition-delay: calc(180ms + var(--i, 0) * 70ms);
}

.sc-panel.is-showing .pjb__col,
.sc-panel.is-showing .pjs__event,
.sc-panel.is-showing .pjs__cell {
  opacity: 1;
  transform: none;
}

/* Pin off: no sequence to arrive with, so everything is simply there. */

@media (max-width: 1023.98px) {
  .sc-panel .pjb__col,
  .sc-panel .pjs__event,
  .sc-panel .pjs__cell {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Narrow frame: the dashboard cards and the board go to fewer columns, the
   forms stack their pairs, and the notification matrix drops the two channels
   fewest teams route to. The board keeps its cards: they are what it is for.
   ========================================================================== */

@container (max-width: 380px) {
  .pjd__grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .pjd__tiles {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .pjb__board {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .pjb__col:nth-child(n + 4) {
    display: none;
  }

  /* Three columns on a 340px frame leave a card about sixty pixels wide, and
     the id and the priority pill cannot both sit on that line. The id goes on
     being the thing a reader looks for, so the pill is what gives way. */

  .pjb__card .pjt__prio {
    display: none;
  }

  .pjn__opts {
    grid-template-columns: minmax(0, 1fr);
  }

  .pjm__table {
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.9fr);
  }

  .pjm__table .cro__th:nth-child(3),
  .pjm__table .cro__cell {
    display: none;
  }

  .pjs__matrix {
    grid-template-columns: minmax(0, 1.6fr) repeat(2, minmax(0, 0.5fr));
  }

  .pjs__matrix .pjs__chhead:nth-child(4),
  .pjs__matrix .pjs__chhead:nth-child(5),
  .pjs__matrix .pjs__cell:nth-of-type(4n + 3),
  .pjs__matrix .pjs__cell:nth-of-type(4n) {
    display: none;
  }
}

/* ==========================================================================
   THE AGENCY ARTWORKS — /recruitment-agency-crm/

   .agd the agency dashboard in the hero, .agl the talent database, .agc the
   client list, .agp one requirement's pipeline board, .agt team performance,
   .agb billing. All six sit in the blue box registered above, so every rule
   here assumes the near-white sheet .sc-sheet paints.

   NOT .cr*
   That prefix belongs to /crm-software/, which is the sales CRM. This is the
   staffing product. The two pages share the site's furniture and nothing else,
   and borrowing the namespace would restyle that page's panels from here.

   WHAT IS BORROWED RATHER THAN REDRAWN
   The chrome (.cll__), the tiles, table cells, avatars, pills and footers
   (.cro__), the action row and filter chips (.crl__) and the board column head
   (.crd__) are the CRM page's, because they are the same objects. A seventh
   copy of a table cell would be a seventh place for its padding to drift. What
   is new below is only the five shapes those blocks have no version of: the
   funnel, the nested requirement strip, the candidate card, the conversion
   bar and the billing chips.

   ONE COLOUR PER PERSON AND PER ACCOUNT
   Every avatar, swatch, pill and bar takes --c from PHP. A recruiter's colour
   on the team panel is their client's colour on the client panel and their
   slice of the placements donut in the hero, because it is one person.
   ========================================================================== */

/* The frame the five sequence panels share. Measured against the tallest,
   which is the team table with its totals row. */

.sc-panel__frame--ag {
  display: flex;
  min-height: 455px;
  background-color: #DCE4F6;
}

.sc-panel__frame--ag > * {
  flex: 1;
  min-height: 0;
}

.agd__sheet,
.agl__sheet {
  display: flex;
  flex-direction: column;
}

/* ==========================================================================
   01 — the agency dashboard (hero)

   The funnel is four stages of one quarter, each measured against the widest
   rather than against a fixed ceiling: submissions is always the top of the
   funnel, so it is the full track and the three under it are read against it.
   That is what makes the drop between two stages the thing the eye lands on.
   ========================================================================== */

.agd__funnel {
  display: grid;
  gap: 9px;
  margin: 9px 0 0;
  padding: 0;
  list-style: none;
}

.agd__stage {
  display: grid;
  gap: 3px;
}

.agd__stagetop {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.agd__stagename {
  font-size: 8.5px;
  font-weight: 600;
  font-style: normal;
  color: #5A6070;
}

/* The count sits at the right edge of the row rather than after the label, so
   the four numbers line up as a column a reader can compare down. */

.agd__stagenum {
  margin-left: auto;
  font-size: 10px;
  font-weight: 700;
  font-style: normal;
  color: #22262F;
}

.agd__track {
  display: block;
  height: 7px;
  border-radius: 100px;
  background-color: #EDF1F4;
}

.agd__bar {
  display: block;
  width: var(--w, 0%);
  height: 100%;
  border-radius: 100px;
  background-color: var(--c);
}

/* The conversion against the stage above, not against the top of the funnel.
   "36 of 60 got an interview" is the sentence a recruiter can act on. */

.agd__drop {
  font-size: 7.5px;
  font-weight: 500;
  font-style: normal;
  color: #A6ADBD;
}

/* ==========================================================================
   02 — the talent database
   ========================================================================== */

.agl__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.6fr) minmax(0, 1.05fr) minmax(0, 0.75fr)
    minmax(0, 0.42fr) minmax(0, 1.05fr);
  gap: 5px 8px;
  align-items: center;
  margin-top: 13px;
}

/* A profile that has already been placed is somebody's employee today. The row
   stays in the pool, which is the whole argument for keeping a database, but
   the last cell says so in the colour a reader reads as "not available". */

.agl__was {
  color: #B45309;
  font-weight: 600;
}

/* ==========================================================================
   03 — clients and their requirements

   One row is drawn open, with its requirements nested under it. That is where
   the open-positions figure on a client row is visible as the sum of the
   requirements below it, which no collapsed list can show.
   ========================================================================== */

.agc__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.9fr) minmax(0, 0.9fr) minmax(0, 0.55fr)
    minmax(0, 0.8fr) minmax(0, 0.65fr);
  gap: 5px 8px;
  align-items: center;
  margin-top: 13px;
}

/* A disclosure triangle, drawn rather than set in a font: at 5px an arrow
   glyph is a smudge, and the borders give a crisp one at any zoom. */

.agc__caret {
  flex: none;
  width: 0;
  height: 0;
  margin-right: -2px;
  border-top: 3.5px solid transparent;
  border-bottom: 3.5px solid transparent;
  border-left: 5px solid #C7CCD8;
  transition: transform 200ms var(--ease-smooth);
}

.agc__caret.is-open {
  transform: rotate(90deg) translate3d(0, 1px, 0);
  border-left-color: #5A6070;
}

.agc__won {
  color: #15803D;
  font-weight: 700;
}

/* The nested strip spans every column, so it reads as belonging to the row
   above rather than as a sixth cell in it. */

.agc__reqs {
  grid-column: 1 / -1;
  display: grid;
  gap: 4px;
  margin: 1px 0 4px 30px;
  padding: 7px 9px;
  border-radius: 9px;
  background-color: #F4F6FB;
}

.agc__req {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 3px 6px;
  border-radius: 6px;
  min-width: 0;
}

/* The requirement the next panel opens a board for. Marked here so the two
   screens are one click apart rather than two unrelated screenshots. */

.agc__req.is-on {
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.22);
}

.agc__reqname {
  font-size: 8.5px;
  font-weight: 600;
  font-style: normal;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.agc__reqmeta {
  flex: none;
  font-size: 7.5px;
  font-weight: 500;
  font-style: normal;
  color: #A6ADBD;
  white-space: nowrap;
}

.agc__reqpipe {
  flex: none;
  margin-left: auto;
  font-size: 7.5px;
  font-weight: 700;
  font-style: normal;
  color: #2563EB;
  white-space: nowrap;
}

/* ==========================================================================
   04 — one requirement's pipeline

   Five stages, so the columns are narrower than the CRM board's four and the
   cards carry a face rather than a value. A candidate is a person; a deal is
   an amount, and the two want different cards.
   ========================================================================== */

.agp__board {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 7px;
  margin-top: 13px;
}

.agp__col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 9px 7px 8px;
  border-radius: 11px;
  background-color: #F4F6FB;
  min-width: 0;
}

/* The stage name gets the whole head row. With the count badge beside it the
   name had about 36px in a 470px sheet and "Submitted" needs 43, so three of
   the five truncated. The count moves to its own line underneath, where it can
   also say what it is counting. */

.agp__colhead {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.agp__colname {
  min-width: 0;
  font-size: 8.5px;
  font-weight: 700;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.agp__coln {
  font-size: 7.5px;
  font-weight: 600;
  color: #A6ADBD;
}

.agp__card {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 8px 7px;
  border-radius: 9px;
  background-color: #ffffff;
  box-shadow:
    inset 0 0 0 1px rgba(16, 24, 48, 0.06),
    0 4px 12px -9px rgba(16, 24, 48, 0.5);
}

.agp__cardtop {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.agp__av {
  width: 17px;
  height: 17px;
  font-size: 6.5px;
}

.agp__cardname {
  min-width: 0;
  font-size: 8.5px;
  font-weight: 600;
  line-height: 1.25;
  color: #22262F;
}

.agp__cardnote {
  font-size: 7.5px;
  font-weight: 500;
  color: #8A90A0;
}

/* A column shows what fits and says how many it is hiding, rather than ending
   on a card and implying that was all of them. */

.agp__more {
  margin-top: auto;
  padding-top: 2px;
  font-size: 7.5px;
  font-weight: 600;
  color: #A6ADBD;
  text-align: center;
}

/* ==========================================================================
   05 — team performance

   Six columns: the recruiter, four stages of their quarter and the rate that
   comes out of the first and the last. The totals are a real row in the same
   grid, not a caption under it, because they are the same four columns.
   ========================================================================== */

.agt__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.7fr) minmax(0, 0.42fr) minmax(0, 0.42fr)
    minmax(0, 0.42fr) minmax(0, 0.55fr) minmax(0, 1.25fr);
  gap: 6px 8px;
  align-items: center;
  margin-top: 13px;
}

.agt__won {
  color: #15803D;
  font-weight: 700;
}

.agt__rate {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.agt__track {
  flex: 1;
  min-width: 0;
  height: 5px;
  border-radius: 100px;
  background-color: #EDF1F4;
}

/* Scaled against the best rate on the screen, not against 100%. Five bars all
   under a fifth of their track would be five bars nobody can tell apart, and
   the figure is printed beside every one either way. */

.agt__bar {
  display: block;
  width: var(--w, 0%);
  height: 100%;
  border-radius: 100px;
  background-color: var(--c);
}

.agt__pct {
  flex: none;
  font-size: 8px;
  font-weight: 700;
  font-style: normal;
  color: #5A6070;
  white-space: nowrap;
}

.agt__totlabel {
  padding-top: 8px;
  border-top: 1px solid rgba(16, 24, 48, 0.09);
  font-size: 8.5px;
  font-weight: 700;
  color: #22262F;
}

.agt__tot {
  padding-top: 8px;
  border-top: 1px solid rgba(16, 24, 48, 0.09);
  font-weight: 700;
}

.agt__pct--tot {
  font-size: 9px;
  color: #22262F;
}

.agt__totnote {
  font-size: 7.5px;
  font-weight: 500;
  font-style: normal;
  color: #A6ADBD;
  white-space: nowrap;
}

/* ==========================================================================
   06 — billing

   Three chips over the table, which are that table grouped by state and summed
   at render. Draft is its own chip rather than part of the billed figure: an
   invoice nobody has sent is not revenue.
   ========================================================================== */

.agb__chips {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 13px 0 0;
  padding: 0;
  list-style: none;
}

.agb__chip {
  display: grid;
  gap: 1px;
  padding: 9px 10px;
  border-radius: 10px;
  background-color: color-mix(in srgb, var(--c) 10%, transparent);
}

.agb__chipnum {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--c);
}

.agb__chiplab {
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #5A6070;
}

.agb__chipnote {
  font-size: 7.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.agb__table {
  display: grid;
  /* The fee column is wider than the widest amount rather than equal to it.
     At 0.7fr a right-aligned "₹2,70,000" filled its cell exactly and sat
     against the state pill, which read as one run-on column. */
  grid-template-columns:
    minmax(0, 0.9fr) minmax(0, 0.95fr) minmax(0, 1.3fr)
    minmax(0, 0.85fr) minmax(0, 0.65fr);
  gap: 5px 8px;
  align-items: center;
  margin-top: 13px;
}

/* Number over date, because the date is what tells a reader whether an
   outstanding invoice is late and it belongs with the number it qualifies. */

.agb__no {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  font-size: 8.5px;
  font-weight: 700;
  color: #22262F;
}

.agb__no em {
  font-size: 7.5px;
  font-weight: 500;
  font-style: normal;
  color: #A6ADBD;
}

/* ==========================================================================
   ENTRANCE

   Gated on `.sc-panel.is-showing`, not on the site's .reveal observer: inside
   a pinned stage a panel is shown and hidden repeatedly as the reader scrolls
   back and forth, and .reveal fires once and unobserves. --i is authored on
   each row.

   The .cro__ rows the four table panels use are already carried by the CRM
   block's own entrance rules, so what is listed here is only this page's own
   shapes. The hero's dashboard is left out: it is not in a pinned panel, and
   .hs-hero__art already carries it in on the page's reveal.
   ========================================================================== */

.sc-panel .agc__reqs,
.sc-panel .agp__col,
.sc-panel .agt__rate,
.sc-panel .agb__chip,
.sc-panel .agb__no {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition:
    opacity 460ms var(--ease-smooth),
    transform 560ms var(--ease-smooth);
  transition-delay: calc(180ms + var(--i, 0) * 70ms);
}

.sc-panel.is-showing .agc__reqs,
.sc-panel.is-showing .agp__col,
.sc-panel.is-showing .agt__rate,
.sc-panel.is-showing .agb__chip,
.sc-panel.is-showing .agb__no {
  opacity: 1;
  transform: none;
}

/* Pin off: no sequence to arrive with, so everything is simply there. */

@media (max-width: 1023.98px) {
  .sc-panel .agc__reqs,
  .sc-panel .agp__col,
  .sc-panel .agt__rate,
  .sc-panel .agb__chip,
  .sc-panel .agb__no {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Narrow frame: the tables drop the columns a reader checks last, the board
   halves its columns and the billing chips stack. The funnel, the donut and
   the candidate cards stay: they are what the screens are for.

   .cll__bar, .crl__acts, .crl__quick, .cro__tiles--six and .cro__charts are
   already handled by the CRM block's own narrow rules, which are global.
   ========================================================================== */

@container (max-width: 380px) {
  /* .cro__tiles--four is still four across here: its own two-column rule is a
     page-width media query, not a container query, and this artwork is 340px
     inside a 1512px page. Four money tiles in 250px leave 55 each and
     "₹13,14,000" needs 62. */

  .agd .cro__tiles--four {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .agl__table {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 0.95fr);
  }

  .agl__table .cro__th:nth-child(3),
  .agl__table .cro__th:nth-child(4),
  .agl__table .cro__cell:nth-of-type(2n),
  .agl__table .cro__num {
    display: none;
  }

  .agc__table {
    grid-template-columns: minmax(0, 1.8fr) minmax(0, 0.6fr) minmax(0, 0.6fr);
  }

  .agc__table .cro__th:nth-child(2),
  .agc__table .cro__th:nth-child(4),
  .agc__table .cro__cell {
    display: none;
  }

  .agc__reqs {
    margin-left: 0;
  }

  .agc__req {
    flex-wrap: wrap;
    gap: 3px 7px;
  }

  .agc__reqpipe {
    margin-left: 0;
  }

  .agp__board {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .agp__col:nth-child(n + 4) {
    display: none;
  }

  /* A candidate's name is the whole card at three columns, so it breaks rather
     than spills: "Farhan Qureshi" has nowhere to wrap otherwise. */

  .agp__cardname {
    overflow-wrap: anywhere;
  }

  /* The two middle stages come out, leaving what the row is for: who, how many
     they put forward, how many joined, and the rate between the two. They are
     dropped by class rather than by nth-of-type, which would be counting every
     span in the grid rather than every number in it. */

  .agt__table {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 0.5fr) minmax(0, 0.6fr) minmax(0, 1fr);
  }

  .agt__mid {
    display: none;
  }

  /* The totals cell holds two figures side by side and needs 107px of the 62
     the last column has here. It stacks rather than dropping one: the rate and
     the offer-to-join figure are the two numbers the panel exists to leave a
     reader with. */

  .agt__rate.agt__tot {
    flex-wrap: wrap;
    gap: 2px 7px;
  }

  .agt__totnote {
    white-space: normal;
  }

  .agb__chips {
    grid-template-columns: minmax(0, 1fr);
  }

  .agb__table {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) minmax(0, 0.85fr);
  }

  .agb__table .cro__th:nth-child(3),
  .agb__table .cro__th:nth-child(4),
  .agb__table .cro__cell:nth-of-type(2n),
  .agb__table .cro__num {
    display: none;
  }
}

/* ==========================================================================
   THE SOURCING ARTWORKS — /ai-sourcing/

   .sod the sourcing dashboard in the hero, .soq the multi-source search, .sor
   the resume intelligence engine, .som the ranked match list, .sop the talent
   pools, .soo the outreach sequence. All six sit in the blue box registered
   above, so every rule here assumes the near-white sheet .sc-sheet paints.

   NOT .so* ON THE HOME PAGE
   .sol belongs to the home page's scatter section. Nothing else in the .so
   space was taken.

   WHAT IS BORROWED RATHER THAN REDRAWN
   The chrome (.cll__), the tiles, table cells, avatars, pills and footers
   (.cro__), the action row (.crl__), the board column dot (.crd__) and the
   funnel (.agd__) are other pages' and are the same objects doing the same
   job. A second implementation of a funnel bar would be a second place for its
   height to drift. What is new below is only the six shapes no other page has:
   the source toggles, the parsed document, the score ring, the pool bar, the
   sequence step and the summary strip.

   ONE COLOUR PER SOURCE AND PER CANDIDATE
   Every swatch, toggle, ring and pool bar takes --c from PHP, so a source's
   colour in the hero donut is its colour on the search screen, and a
   candidate's avatar colour is the colour of their score ring.
   ========================================================================== */

/* The frame the five sequence panels share. Measured against the tallest,
   which is the parsed-resume split. */

.sc-panel__frame--so {
  display: flex;
  min-height: 460px;
  background-color: #DCE4F6;
}

.sc-panel__frame--so > * {
  flex: 1;
  min-height: 0;
}

.sod__sheet,
.soq__sheet {
  display: flex;
  flex-direction: column;
}

/* ==========================================================================
   02 — the multi-source search

   The role reads as a sentence, the fields under it as a form, and the sources
   as switches. That order is the argument: you say what you want in words, and
   the thing that makes it a sourcing tool rather than a filter is the list at
   the bottom.
   ========================================================================== */

.soq__query {
  display: grid;
  gap: 4px;
  margin-top: 14px;
}

.soq__qlabel {
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
}

/* The focused field, which is the one the reader's eye should land in. The
   brand ring is what says "this is where you type". */

.soq__qbox {
  display: flex;
  align-items: center;
  padding: 9px 11px;
  border-radius: 9px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1.5px #2563EB;
  font-size: 11px;
  font-weight: 600;
  color: #22262F;
}

/* A text caret, drawn rather than animated: a blinking bar on a marketing page
   asks a reader to wait for something. */

.soq__caret {
  width: 1.5px;
  height: 12px;
  margin-left: 2px;
  background-color: #2563EB;
}

.soq__fields {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 7px;
  margin-top: 8px;
}

.soq__field {
  display: grid;
  gap: 2px;
  padding: 7px 9px;
  border-radius: 8px;
  background-color: #F4F6FB;
  min-width: 0;
}

.soq__flabel {
  font-size: 7px;
  font-weight: 700;
  font-style: normal;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.soq__fvalue {
  font-size: 8.5px;
  font-weight: 600;
  font-style: normal;
  color: #22262F;
  overflow-wrap: anywhere;
}

.soq__skills {
  display: grid;
  gap: 6px;
  margin-top: 9px;
}

.soq__srow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 5px;
}

.soq__slabel {
  margin-right: 3px;
  font-size: 7.5px;
  font-weight: 700;
  font-style: normal;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.soq__chip {
  padding: 3px 8px;
  border-radius: 100px;
  background-color: #F4F6FB;
  font-size: 8px;
  font-weight: 600;
  font-style: normal;
  color: #5A6070;
  white-space: nowrap;
}

/* A must-have and a nice-to-have are not the same instruction, and a screen
   that set them identically would be showing a search that cannot tell them
   apart either. */

.soq__chip--must {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

.soq__sources {
  display: grid;
  gap: 5px;
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}

.soq__source {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 9px;
  border-radius: 8px;
  background-color: #F4F6FB;
}

/* The switch. Off is the resting state, so the on state is what is coloured,
   and it takes the source's own colour rather than a single brand blue: that
   is what ties a row here to its slice of the donut in the hero. */

.soq__sw {
  flex: none;
  display: block;
  width: 18px;
  height: 10px;
  padding: 1.5px;
  border-radius: 100px;
  background-color: #D5DAE5;
  transition: background-color 200ms var(--ease-smooth);
}

.soq__sw em {
  display: block;
  width: 7px;
  height: 7px;
  border-radius: 100px;
  background-color: #ffffff;
  transition: transform 200ms var(--ease-smooth);
}

.soq__source.is-on .soq__sw {
  background-color: var(--c);
}

.soq__source.is-on .soq__sw em {
  transform: translate3d(8px, 0, 0);
}

.soq__sname {
  flex: 1;
  min-width: 0;
  font-size: 9px;
  font-weight: 600;
  color: #5A6070;
}

.soq__source.is-on .soq__sname {
  color: #22262F;
}

.soq__scount {
  flex: none;
  padding: 1px 7px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.06);
  font-size: 7.5px;
  font-weight: 700;
  color: #8A90A0;
}

.soq__source.is-on .soq__scount {
  background-color: color-mix(in srgb, var(--c) 14%, transparent);
  color: var(--c);
}

/* ==========================================================================
   03 — the resume intelligence engine

   Document on the left, fields on the right. It is the only arrangement that
   shows what the engine did rather than asserting that it did something.
   ========================================================================== */

.sor__split {
  display: grid;
  grid-template-columns: minmax(0, 0.72fr) minmax(0, 1fr);
  gap: 10px;
  margin-top: 13px;
  min-height: 0;
}

.sor__doc {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 9px;
  border-radius: 10px;
  background-color: #F4F6FB;
  min-width: 0;
}

.sor__docname {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}

.sor__file {
  min-width: 0;
  font-size: 8px;
  font-weight: 700;
  font-style: normal;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sor__size {
  flex: none;
  font-size: 7px;
  font-weight: 500;
  font-style: normal;
  color: #A6ADBD;
}

/* Ruled lines, not lorem text. It is a picture of a CV: setting fake sentences
   on it would invite a reader to try to read them and find they cannot. */

.sor__page {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 5px;
  flex: 1;
  padding: 11px 10px;
  border-radius: 7px;
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 48, 0.06);
}

.sor__ln {
  height: 4px;
  border-radius: 100px;
  background-color: #E7EBF3;
}

.sor__ln--head {
  width: 55%;
  height: 7px;
  background-color: #C7CCD8;
}

.sor__ln--sub  {
  width: 38%;
  height: 5px;
  background-color: #D7DCE7;
}

.sor__ln--short {
  width: 62%;
}

.sor__gap {
  height: 5px;
}

/* The band that says the page is being read, sitting still rather than
   animating: a loop running forever on a marketing page reads as a page that
   never finishes. */

.sor__scan {
  position: absolute;
  left: 0;
  right: 0;
  top: 46%;
  height: 22px;
  background-image: linear-gradient(180deg,
    rgba(37, 99, 235, 0) 0%,
    rgba(37, 99, 235, 0.12) 45%,
    rgba(37, 99, 235, 0) 100%);
  border-top: 1px solid rgba(37, 99, 235, 0.35);
}

.sor__out {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.sor__whohead {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.sor__fields {
  display: grid;
  gap: 3px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sor__field {
  display: grid;
  grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.15fr) auto;
  align-items: baseline;
  gap: 7px;
  padding: 3px 6px;
  border-radius: 5px;
}

.sor__field:nth-child(odd) {
  background-color: #F7F8FC;
}

.sor__flabel {
  font-size: 7.5px;
  font-weight: 600;
  font-style: normal;
  color: #A6ADBD;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sor__fvalue {
  min-width: 0;
  font-size: 8px;
  font-weight: 600;
  font-style: normal;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Found and derived are marked apart on purpose. "7 years 4 months" was not
   written on the CV, it was worked out from the dates on it, and a screen that
   printed both the same way would be claiming the document said something it
   did not. */

.sor__ftag {
  flex: none;
  padding: 1px 5px;
  border-radius: 100px;
  font-size: 6.5px;
  font-weight: 700;
  font-style: normal;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.sor__ftag--found   {
  background-color: rgba(22, 163, 74, 0.12);
  color: #15803D;
}

.sor__ftag--derived {
  background-color: rgba(37, 99, 235, 0.1);
  color: #1D4ED8;
}

/* ==========================================================================
   04 — the ranked match list

   Five columns and a rule across the middle of them. The rule is the whole
   screen: auto-shortlisting has to cut somewhere and this says where.
   ========================================================================== */

.som__table {
  display: grid;
  grid-template-columns:
    minmax(0, 1.55fr) minmax(0, 1.1fr) minmax(0, 0.5fr)
    minmax(0, 1.15fr) minmax(0, 0.5fr);
  gap: 6px 8px;
  align-items: center;
  margin-top: 13px;
}

.som__why {
  font-weight: 600;
  color: #5A6070;
}

/* Drawn where the threshold actually falls rather than after a fixed number of
   rows, so moving the cut in PHP moves the line on the screen. */

.som__cut {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 2px 0;
  font-size: 7px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A6ADBD;
  white-space: nowrap;
}

.som__cut::after {
  content: '';
  flex: 1;
  height: 1px;
  background-image: repeating-linear-gradient(
    to right, #C7CCD8 0 4px, transparent 4px 8px);
}

.som__score {
  justify-self: end;
}

/* The score as a ring rather than a number in a pill: --p is the score itself,
   so the arc IS the figure printed inside it rather than a shape drawn near
   one. */

.som__ring {
  position: relative;
  display: grid;
  place-items: center;
  width: 27px;
  height: 27px;
  border-radius: 100px;
  background-image: conic-gradient(
    var(--c) 0 var(--p),
    rgba(16, 24, 48, 0.08) var(--p) 100%);
}

.som__ring::before {
  content: '';
  position: absolute;
  inset: 3px;
  border-radius: 100px;
  background-color: #FBFBFE;
}

.som__ring em {
  position: relative;
  font-size: 8.5px;
  font-weight: 700;
  font-style: normal;
  color: #22262F;
}

/* Above the line is in the shortlist. It is the only state change on the row,
   which is what keeps the rule readable as a threshold. */

.som__score.is-in .som__ring::before {
  background-color: #ffffff;
}

.som__score.is-in .som__ring em {
  color: var(--c);
}

/* ==========================================================================
   05 — the talent pools

   The bar is the matched share, not the pool size. How big a pool is, is the
   number beside its name; what a recruiter opens this to find out is how much
   of it is live.
   ========================================================================== */

.sop__list {
  display: grid;
  gap: 7px;
  margin-top: 13px;
}

.sop__pool {
  display: grid;
  gap: 5px;
  padding: 9px 10px;
  border-radius: 10px;
  background-color: #F4F6FB;
}

/* The pool the search on panel 01 is filtered to. */

.sop__pool.is-on {
  background-color: #ffffff;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c) 34%, transparent);
}

.sop__top {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.sop__name {
  min-width: 0;
  font-size: 9px;
  font-weight: 700;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sop__new {
  flex: none;
  padding: 1px 6px;
  border-radius: 100px;
  background-color: rgba(22, 163, 74, 0.12);
  font-size: 7px;
  font-weight: 700;
  color: #15803D;
  white-space: nowrap;
}

.sop__total {
  flex: none;
  margin-left: auto;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: #22262F;
}

.sop__track {
  display: block;
  height: 6px;
  border-radius: 100px;
  background-color: #E4E8F1;
}

.sop__fill {
  display: block;
  width: var(--w, 0%);
  height: 100%;
  border-radius: 100px;
  background-color: var(--c);
}

.sop__meta {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 7.5px;
  font-weight: 600;
  color: var(--c);
}

/* The rest of the pool is the point of keeping one, so it is printed rather
   than left as the empty part of a bar. */

.sop__rest {
  margin-left: auto;
  font-weight: 500;
  font-style: normal;
  color: #A6ADBD;
}

.sop__meta em {
  font-style: normal;
}

/* ==========================================================================
   06 — the outreach sequence

   Three steps, each with one bar carrying three widths: sent, opened, replied,
   drawn over each other rather than side by side, because they are three
   subsets of the same group and not three separate measures.
   ========================================================================== */

.soo__steps {
  display: grid;
  gap: 8px;
  margin: 13px 0 0;
  padding: 0;
  list-style: none;
}

.soo__step {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 9px 10px;
  border-radius: 10px;
  background-color: #F4F6FB;
}

.soo__num {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background-color: #ffffff;
  box-shadow: 0 1px 2px rgba(16, 24, 48, 0.1);
  font-size: 8px;
  font-weight: 700;
  color: #2563EB;
}

.soo__body {
  display: grid;
  gap: 5px;
  flex: 1;
  min-width: 0;
}

.soo__head {
  display: flex;
  align-items: baseline;
  gap: 7px;
  min-width: 0;
}

.soo__name {
  min-width: 0;
  font-size: 9px;
  font-weight: 700;
  font-style: normal;
  color: #22262F;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.soo__chan {
  flex: none;
  padding: 1px 6px;
  border-radius: 100px;
  background-color: rgba(16, 24, 48, 0.06);
  font-size: 7px;
  font-weight: 700;
  font-style: normal;
  color: #5A6070;
}

.soo__day {
  flex: none;
  margin-left: auto;
  font-size: 7.5px;
  font-weight: 600;
  font-style: normal;
  color: #A6ADBD;
}

/* Three bars in one track, each starting at the same left edge, so the reader
   sees replies as a fraction of opens as a fraction of sent rather than as
   three unrelated lengths. */

.soo__track {
  position: relative;
  display: block;
  height: 6px;
  border-radius: 100px;
  background-color: #E4E8F1;
  overflow: hidden;
}

.soo__track > span {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: var(--w, 0%);
  border-radius: 100px;
}

.soo__sent {
  background-color: #C3CBE8;
}

.soo__open {
  background-color: #6D5BF6;
}

.soo__rep  {
  background-color: #16A34A;
}

.soo__nums {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 7.5px;
  font-weight: 500;
  color: #8A90A0;
}

.soo__nums em {
  font-style: normal;
}

.soo__nums b {
  font-weight: 700;
  color: #5A6070;
}

.soo__replied {
  margin-left: auto;
}

.soo__replied b {
  color: #15803D;
}

/* What the sequence produced, and what it did not. A panel that printed only
   its replies would be selling the feature rather than reporting it. */

.soo__sum {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-top: 9px;
}

.soo__sumcell {
  display: grid;
  gap: 1px;
  padding: 8px 10px;
  border-radius: 9px;
  background-color: rgba(22, 163, 74, 0.09);
}

.soo__sumcell--quiet {
  background-color: #F4F6FB;
}

.soo__sumnum {
  font-size: 13px;
  font-weight: 700;
  font-style: normal;
  letter-spacing: -0.01em;
  color: #15803D;
}

.soo__sumcell--quiet .soo__sumnum {
  color: #8A90A0;
}

.soo__sumlab {
  font-size: 7.5px;
  font-weight: 700;
  font-style: normal;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #A6ADBD;
}

/* ==========================================================================
   ENTRANCE

   Gated on `.sc-panel.is-showing`, not on the site's .reveal observer: inside
   a pinned stage a panel is shown and hidden repeatedly as the reader scrolls
   back and forth, and .reveal fires once and unobserves. --i is authored on
   each row.

   The .cro__ rows the match panel uses are already carried by the CRM block's
   own entrance rules, so what is listed here is only this page's own shapes.
   The hero's dashboard is left out: it is not in a pinned panel, and
   .hs-hero__art already carries it in on the page's reveal.
   ========================================================================== */

.sc-panel .soq__field,
.sc-panel .soq__source,
.sc-panel .sor__field,
.sc-panel .sop__pool,
.sc-panel .soo__step,
.sc-panel .som__score {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  transition:
    opacity 460ms var(--ease-smooth),
    transform 560ms var(--ease-smooth);
  transition-delay: calc(180ms + var(--i, 0) * 70ms);
}

/* The parsed fields are twelve rows rather than five, so they arrive on a
   shorter step: a 70ms cascade would still be running after the reader has
   moved on. */

.sc-panel .sor__field {
  transition-delay: calc(220ms + var(--i, 0) * 34ms);
}

.sc-panel.is-showing .soq__field,
.sc-panel.is-showing .soq__source,
.sc-panel.is-showing .sor__field,
.sc-panel.is-showing .sop__pool,
.sc-panel.is-showing .soo__step,
.sc-panel.is-showing .som__score {
  opacity: 1;
  transform: none;
}

/* Pin off: no sequence to arrive with, so everything is simply there. */

@media (max-width: 1023.98px) {
  .sc-panel .soq__field,
  .sc-panel .soq__source,
  .sc-panel .sor__field,
  .sc-panel .sop__pool,
  .sc-panel .soo__step,
  .sc-panel .som__score {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Narrow frame: the search fields stack, the parsed document drops away, the
   match table loses the columns a reader checks last and the sequence summary
   goes to one column. The source toggles, the parsed fields, the score rings
   and the pool bars stay: they are what the screens are for.

   .cll__bar, .crl__acts, .cro__tiles--six and .cro__charts are already handled
   by the CRM block's own narrow rules, which are global.
   ========================================================================== */

@container (max-width: 380px) {
  /* Same reason as the agency dashboard: .cro__tiles--four is still four
     across here, because its two-column rule is a page-width media query
     rather than a container query. */

  .sod .cro__tiles--four {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

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

  .soq__field:nth-child(3) {
    display: none;
  }

  /* The document is a picture of a CV. The fields read off it are the content,
     so at this width the picture is what gives way. */

  .sor__split {
    grid-template-columns: minmax(0, 1fr);
  }

  .sor__doc {
    display: none;
  }

  .sor__field {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
  }

  .sor__ftag {
    display: none;
  }

  .som__table {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1.1fr) minmax(0, 0.5fr);
  }

  .som__table .cro__th:nth-child(2),
  .som__table .cro__th:nth-child(3),
  .som__table .cro__cell:not(.som__why),
  .som__table .cro__num {
    display: none;
  }

  .sop__meta {
    flex-wrap: wrap;
    gap: 1px 8px;
  }

  .sop__rest {
    margin-left: 0;
  }

  .soo__sum {
    grid-template-columns: minmax(0, 1fr);
  }

  .soo__nums {
    flex-wrap: wrap;
    gap: 2px 8px;
  }

  .soo__replied {
    margin-left: 0;
  }
}

/* ==========================================================================
   THE HIRING JOURNEY — /ats-software.php

   Eight stages, four across twice. Each is a white card with a numbered badge
   sitting on its top edge, and a dashed line runs between them with an arrow
   at every join. Rendered by sections/ats/journey.php; the artwork is eight
   SVGs in assets/images.

   ONE BLUE, AND THE NUMBERS DO THE TELLING APART
   Every stage takes the same blue. The eight used to have a hue each, which
   said they were eight different kinds of thing rather than eight parts of
   one hire.

   THE LINE IS GEOMETRY, NOT A PICTURE
   Everything between the cards is drawn with dashed borders on empty boxes,
   so it stays crisp at any zoom and takes the same blue as the rest. The
   measurements below all hang off --hjy-mid, the distance from the top of a
   step to the middle of its artwork, because that is the height every arrow
   and every turn in the line has to meet.
   ========================================================================== */

.hjy {
  --hjy-blue: #1D6BF3;
  --hjy-deep: #1552C7;
  --hjy-rule: #A9C7F7;
  /* Top of a step to the middle of its artwork: the badge's overhang, then
     the card's top padding, then half the artwork. Every join in the flow
     line meets this height. */
  --hjy-mid: 126px;
  --hjy-gap: 36px;
  position: relative;
  display: grid;
  /* Two columns from the smallest screen up. This was one below 620, and eight
     numbered cards one under the other is a very long scroll on a phone for
     what each card actually holds — a drawing, a name and a line. They carry
     at half width. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--hjy-gap) 22px;
  margin: 46px 0 0;
  padding: 0;
  list-style: none;
}

/* Phones. At two columns on a 375 the card is about 160 wide, and 22 of
   padding either side of a 14px line is most of what is left, so the padding
   and the gutter both come in. Nothing else changes: the badge still straddles
   the top edge and the artwork still stands on one line across the row. */

@media (max-width: 619px) {
  .hjy {
    --hjy-gap: 30px;
    gap: var(--hjy-gap) 14px;
  }
}

@media (min-width: 1024px) {
  .hjy {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    /* The column gap has to hold an arrow with dashes either side of it. */
    gap: var(--hjy-gap) 62px;
    /* Equal rows. The wrap-around line finds the middle of the second row by
       measuring from the middle of the grid, which only lands in the right
       place if the two rows are the same height. grid-auto-rows carries the
       same sizing to a third row, which a ten-card version of this grid has
       and an eight-card one does not. */
    grid-template-rows: repeat(2, 1fr);
    grid-auto-rows: 1fr;
  }

  /* Four or fewer cards are one row. The two-row sizing above exists so the
     wrap-around line lands in the middle of a second row; with no wrap there
     is no second row to size, and reserving one leaves a card's height of
     empty ground under the journey. */

  .hjy--row {
    grid-template-rows: auto;
  }
}

.hjy__step {
  position: relative;
  display: flex;
  min-width: 0;
}

/* ---- the card ---- */

.hjy__panel {
  position: relative;
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  /* 30px of the badge stands above the card, so the step is inset by that
     much and the card's own top padding clears the half that hangs into it. */
  margin-top: 30px;
  padding: 44px 22px 28px;
  text-align: center;
  border-radius: 20px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #E6EFFC, 0 12px 28px -20px rgba(21, 82, 199, 0.45);
}

/* ---- the number ----
   Straddling the top edge: solid disc, a white gap cut by the border, then a
   pale ring outside it. The ring is a shadow rather than a second element,
   which keeps it out of the box the layout measures. */

.hjy__num {
  position: absolute;
  top: -30px;
  left: 50%;
  transform: translateX(-50%);
  display: grid;
  place-items: center;
  width: 60px;
  height: 60px;
  border: 5px solid #FFFFFF;
  border-radius: 50%;
  /* Black rather than the section's blue. The stage names below the cards stay
     blue, so the numbers no longer compete with them for the same colour. The
     ring is neutral for the same reason. */
  background-color: #14161D;
  box-shadow: 0 0 0 2px #DDE1EC;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  color: #FFFFFF;
}

/* ---- the artwork ----
   A fixed height so eight drawings of different construction sit on one line
   across the row, which is the thing that would otherwise give them away as
   eight separate files. */

.hjy__card {
  position: relative;
  display: block;
  width: 100%;
  height: 104px;
}

/* Contained, not cropped. These are drawings on the card's own white rather
   than pictures filling a tile, so nothing may be cut off at the edges. */

.hjy__img {
  display: block;
  width: 100%;
  height: 100%;
  -o-object-fit: contain;
     object-fit: contain;
}

.hjy__name {
  margin-top: 20px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.2px;
  /* Black, not the section's blue. The numbered badges above the cards are the
     black now, and a blue stage name under a black badge read as two unrelated
     accents on one card. */
  color: #14161D;
}

.hjy__text {
  margin-top: 10px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.55;
  color: #4A5568;
}

/* The card's own padding on phones. Below 620 it is half of a 160px column,
   which leaves the copy a column of about six words. After .hjy__panel rather
   than beside the gap rule above: a media query carries no specificity, and
   the 44/22/28 would otherwise win by sitting later in the file. */

@media (max-width: 619px) {
  .hjy__panel {
    padding: 40px 14px 24px;
  }

  /* A point down from the 14 the card runs at elsewhere. The padding above
     leaves the copy about six words to a line at this width, and 13 buys back
     roughly one more rather than adding another line to every card. Only the
     size changes; the margin, weight, leading and colour are the card's own. */
  .hjy__text {
    font-size: 13px;
  }
}

/* ==========================================================================
   THE FLOW BETWEEN THE CARDS

   Two pieces. Between neighbours in a row, a dashed rule across the gap with
   an arrow on it, drawn by the step's own pseudo-elements so the last card in
   a row simply has none. Around the end of the first row, one empty element
   whose borders make the turn.

   Both only exist at four columns. Below that the cards stack and there is
   nothing left for a line to join.
   ========================================================================== */

.hjy__flow {
  display: none;
}

@media (min-width: 1024px) {
  /* The rule across the gap, at the height of the artwork. */

  .hjy__step::before {
    content: '';
    position: absolute;
    top: var(--hjy-mid);
    left: 100%;
    width: 62px;
    border-top: 2px dashed var(--hjy-rule);
  }

  /* The arrow sitting on it. A disc rather than a bare chevron: on a dashed
     line a lone arrowhead reads as one more dash. */

  .hjy__step::after {
    content: '';
    position: absolute;
    top: calc(var(--hjy-mid) - 15px);
    left: calc(100% + 16px);
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background-color: #FFFFFF;
    box-shadow: inset 0 0 0 1.5px #CFE0FB;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231D6BF3' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h13M13 7l5 5-5 5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 17px 17px;
  }

  /* Nothing to the right of the fourth card or the eighth. The last card gets
     the same treatment for a grid that does not divide by four: ten cards end
     two into a third row, and an arrow off the tenth would point at the empty
     half of the row. :last-child rather than :last-of-type on purpose, because
     the wrap element is the final <li> whenever it is drawn. */

  .hjy__step:nth-child(4n)::before,
  .hjy__step:nth-child(4n)::after,
  .hjy__step:last-child::before,
  .hjy__step:last-child::after {
    display: none;
  }

  /* ---- the wrap ----
     Out of the fourth card, down the right, back across under the row, down
     the left and into the fifth. Drawn as borders on two boxes: each corner
     is a border-radius on a box with the adjoining border missing, which the
     browser renders as the remaining border curving through the whole arc.

     The right-hand box runs from the artwork's height down to the middle of
     the grid. Because the two rows are equal, that middle is exactly the
     centre of the gap between them, which is the one measurement CSS can
     find here without knowing how tall a row came out. */

  .hjy__flow {
    display: block;
    position: absolute;
    top: var(--hjy-mid);
    right: -26px;
    left: 0;
    bottom: 50%;
    border-right: 2px dashed var(--hjy-rule);
    border-bottom: 2px dashed var(--hjy-rule);
    border-radius: 0 26px 26px 0;
  }

  /* And down into the second row. Its height is the half-gap plus the same
     distance into the step, so it lands on the fifth card's artwork at the
     height the fourth card's line left at. */

  .hjy__flow::after {
    content: '';
    position: absolute;
    top: 100%;
    left: -26px;
    width: 26px;
    height: calc(var(--hjy-gap) / 2 + var(--hjy-mid));
    border-left: 2px dashed var(--hjy-rule);
    border-bottom: 2px dashed var(--hjy-rule);
    border-radius: 26px 0 0 26px;
  }
}

/* ==========================================================================
   THE EIGHT SCENES

   Each one fills its card and is centred in it. They are thumbnails standing
   for a stage, not screens: no readable figures, because a number in a
   decoration is a number somebody will try to add up.

   Shared parts first, then the eight.
   ========================================================================== */

.hjs {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}

.hjs > * {
  position: absolute;
}

/* A ruled line of text, at three widths. */

.hjs__ln {
  position: static;
  display: block;
  height: 4px;
  margin-top: 5px;
  border-radius: 100px;
  background-color: #DEE3EF;
}

.hjs__ln--w80 {
  width: 80%;
}

.hjs__ln--w70 {
  width: 70%;
}

.hjs__ln--w60 {
  width: 60%;
}

.hjs__ln--w50 {
  width: 50%;
}

/* A face, as a disc with a shoulder under it. Enough to read as a person at
   this size, and it takes the stage's colour. */

.hjs__av,
.hjs__face,
.hjs__sit,
.hjs__person {
  border-radius: 100px;
  background-color: color-mix(in srgb, var(--c) 22%, #ffffff);
}

/* A checked row: a tick and the line it belongs to. */

.hjs__row {
  position: static;
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
}

.hjs__tick {
  flex: none;
  display: block;
  width: 11px;
  height: 11px;
  border-radius: 3px;
  background-color: color-mix(in srgb, var(--c) 78%, #ffffff);
}

.hjs__bar {
  display: block;
  flex: 1;
  height: 4px;
  border-radius: 100px;
  background-color: #DEE3EF;
}

.hjs__bar--short {
  flex: 0 0 55%;
}

/* A row of five rating pips, the first three filled. */

.hjs__stars {
  position: static;
  display: flex;
  gap: 3px;
  margin-top: 7px;
}

.hjs__stars::before,
.hjs__stars::after {
  content: none;
}

.hjs__stars {
  --pip: 5px;
  background-image:
    radial-gradient(circle, var(--c) 46%, transparent 47%),
    radial-gradient(circle, var(--c) 46%, transparent 47%),
    radial-gradient(circle, var(--c) 46%, transparent 47%),
    radial-gradient(circle, #D7DCE7 46%, transparent 47%),
    radial-gradient(circle, #D7DCE7 46%, transparent 47%);
  background-repeat: no-repeat;
  background-size: var(--pip) var(--pip);
  background-position: 0 50%, 8px 50%, 16px 50%, 24px 50%, 32px 50%;
  width: 37px;
  height: var(--pip);
}

.hjs__stars--lg {
  --pip: 8px;
  width: 60px;
  background-position: 0 50%, 13px 50%, 26px 50%, 39px 50%, 52px 50%;
}

/* A speech bubble with its tail. */

.hjs__bubble {
  width: 26px;
  height: 19px;
  border-radius: 7px;
  background-color: var(--c);
}

.hjs__bubble::after {
  content: '';
  position: absolute;
  left: 6px;
  bottom: -4px;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 3px solid transparent;
  border-top: 5px solid var(--c);
}

/* ---- 01 AI sourcing ---------------------------------------------------- */

/* One wire per person, drawn as a rotated bar between the tile and the face,
   with a node on the far end. The earlier version painted the wires as a
   background texture behind the scene, where they were invisible at this
   size and connected nothing to anything. */

.hjs__wire {
  left: 74px;
  top: 50%;
  width: 58px;
  height: 2px;
  border-radius: 100px;
  background-color: color-mix(in srgb, var(--c) 34%, #ffffff);
  transform-origin: left center;
}

.hjs__wire--a {
  transform: translateY(-1px) rotate(-24deg);
}

.hjs__wire--b {
  transform: translateY(-1px) rotate(24deg);
}

.hjs__wire::after {
  content: '';
  position: absolute;
  right: -2px;
  top: 50%;
  width: 6px;
  height: 6px;
  transform: translateY(-50%);
  border-radius: 100px;
  background-color: color-mix(in srgb, var(--c) 60%, #ffffff);
}

.hjs__ai {
  left: 32px;
  top: 50%;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  transform: translateY(-50%);
  border-radius: 12px;
  background-color: var(--c);
  color: #ffffff;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.2px;
}

.hjs__face {
  width: 32px;
  height: 32px;
}

.hjs__face--a {
  right: 28px;
  top: 38px;
}

.hjs__face--b {
  right: 28px;
  bottom: 38px;
  background-color: color-mix(in srgb, var(--c) 42%, #ffffff);
}

/* ---- 02 resume screening ------------------------------------------------ */

.hjs__doc {
  left: 24px;
  top: 50%;
  display: flex;
  flex-direction: column;
  width: 96px;
  padding: 13px 12px 15px;
  transform: translateY(-50%);
  border-radius: 10px;
  background-color: #ffffff;
  box-shadow: 0 8px 22px -14px rgba(16, 24, 48, 0.5);
}

.hjs__av {
  width: 22px;
  height: 22px;
  margin-bottom: 8px;
}

.hjs__marks {
  right: 30px;
  top: 50%;
  display: grid;
  gap: 12px;
  transform: translateY(-50%);
}

.hjs__mark {
  position: static;
  width: 18px;
  height: 18px;
  border-radius: 100px;
}

.hjs__mark--yes {
  background-color: #16A34A;
}

/* One rejection, drawn in the same weight as the passes rather than in a
   softer grey: a screen where the "no" is quieter than the "yes" is a screen
   arguing that nobody gets turned down. */

.hjs__mark--no {
  background-color: #DC2626;
}

/* ---- 03 assessment ------------------------------------------------------ */

.hjs__board {
  left: 50%;
  top: 50%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 104px;
  padding: 18px 13px 15px;
  transform: translate(-56%, -50%);
  border-radius: 10px;
  background-color: #ffffff;
  box-shadow: 0 8px 22px -14px rgba(16, 24, 48, 0.5);
}

/* The clip at the top of the board. */

.hjs__clip {
  left: 50%;
  top: -7px;
  width: 30px;
  height: 13px;
  transform: translateX(-50%);
  border-radius: 4px;
  background-color: color-mix(in srgb, var(--c) 55%, #ffffff);
}

/* --p is the arc. It is a decoration, so the figure inside it is small and
   the ring is not read as a chart. */

.hjs__ring {
  right: 20px;
  bottom: 28px;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 100px;
  background-image: conic-gradient(var(--c) 0 85%, #E4E8F1 85% 100%);
}

.hjs__ring::before {
  content: '';
  position: absolute;
  inset: 5px;
  border-radius: 100px;
  background-color: #F7F8FC;
}

.hjs__ring em {
  position: relative;
  font-size: 11px;
  font-weight: 700;
  font-style: normal;
  color: var(--c);
}

/* ---- 04 interview ------------------------------------------------------- */

.hjs__call {
  left: 50%;
  top: 44px;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  transform: translateX(-50%);
}

.hjs__tile {
  position: static;
  border-radius: 9px;
  background-color: color-mix(in srgb, var(--c) 26%, #ffffff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c) 34%, transparent);
}

.hjs__tile--big   {
  width: 62px;
  height: 48px;
}

.hjs__tile--small {
  width: 40px;
  height: 34px;
  background-color: color-mix(in srgb, var(--c) 46%, #ffffff);
}

.hjs--interview .hjs__bubble {
  right: 34px;
  top: 34px;
}

.hjs__ctrls {
  left: 50%;
  bottom: 34px;
  display: flex;
  gap: 8px;
  transform: translateX(-50%);
}

.hjs__ctrls i {
  display: block;
  width: 18px;
  height: 18px;
  border-radius: 100px;
  background-color: #C7CCD8;
}

.hjs__ctrls i.is-end {
  background-color: #DC2626;
}

/* ---- 05 face to face ---------------------------------------------------- */

.hjs__sit {
  width: 28px;
  height: 28px;
  top: 52px;
}

.hjs__sit--l {
  left: 38px;
}

.hjs__sit--r {
  right: 38px;
  background-color: color-mix(in srgb, var(--c) 42%, #ffffff);
}

/* The shoulder. A head on its own is a dot; a head with a body under it is a
   person, and that is the whole difference at 28px. */

.hjs__sit i {
  position: absolute;
  left: 50%;
  top: 32px;
  width: 44px;
  height: 26px;
  transform: translateX(-50%);
  border-radius: 16px 16px 4px 4px;
  background-color: inherit;
}

/* The table they are sitting at, which is what turns two discs into a
   meeting. */

.hjs__table {
  left: 50%;
  bottom: 34px;
  width: 116px;
  height: 9px;
  transform: translateX(-50%);
  border-radius: 100px;
  background-color: #D7DCE7;
}

.hjs__table::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 9px;
  width: 8px;
  height: 18px;
  transform: translateX(-50%);
  background-color: #E4E8F1;
}

.hjs__bubble--mid {
  left: 50%;
  top: 34px;
  transform: translateX(-50%);
}

/* ---- 06 final evaluation ------------------------------------------------ */

/* One card holding the rating and the two figures. Loose in the frame the
   three read as unrelated marks; together they read as the summary somebody
   makes the decision from. */

.hjs__report {
  left: 50%;
  top: 50%;
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: 122px;
  padding: 15px 14px 16px;
  transform: translate(-50%, -50%);
  border-radius: 11px;
  background-color: #ffffff;
  box-shadow: 0 8px 22px -14px rgba(16, 24, 48, 0.5);
}

.hjs__report .hjs__stars--lg {
  position: static;
  margin: 0;
}

.hjs__figs {
  position: static;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 10px;
}

.hjs__donut {
  position: static;
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: 100px;
  background-image: conic-gradient(var(--c) 0 62%, color-mix(in srgb, var(--c) 26%, #ffffff) 62% 100%);
  position: relative;
}

.hjs__donut::after {
  content: '';
  position: absolute;
  inset: 12px;
  border-radius: 100px;
  background-color: #ffffff;
}

.hjs__bars {
  position: static;
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 42px;
}

.hjs__bars i {
  display: block;
  width: 8px;
  height: var(--h);
  border-radius: 3px 3px 0 0;
  background-color: color-mix(in srgb, var(--c) 62%, #ffffff);
}

.hjs__bars i:last-child {
  background-color: var(--c);
}

/* ---- 07 e-sign offer ---------------------------------------------------- */

.hjs__letter {
  left: 50%;
  top: 50%;
  display: flex;
  flex-direction: column;
  width: 100px;
  padding: 14px 13px 16px;
  transform: translate(-58%, -50%);
  border-radius: 10px;
  background-color: #ffffff;
  box-shadow: 0 8px 22px -14px rgba(16, 24, 48, 0.5);
}

.hjs__lhead {
  position: static;
  width: 62%;
  height: 6px;
  margin-bottom: 9px;
  border-radius: 100px;
  background-color: #1B2233;
}

/* The signature. Two arcs of a border, rotated: enough to read as handwriting
   without becoming a drawing of somebody's actual name. */

.hjs__sign {
  position: static;
  width: 46px;
  height: 14px;
  margin-top: 11px;
  border-bottom: 2px solid var(--c);
  border-left: 2px solid var(--c);
  border-radius: 0 0 0 18px;
  transform: rotate(-6deg);
}

.hjs__seal {
  right: 22px;
  bottom: 30px;
  width: 32px;
  height: 32px;
  border-radius: 100px;
  background-color: #16A34A;
  box-shadow: 0 0 0 5px rgba(22, 163, 74, 0.14);
}

/* The tick inside the seal, drawn from two borders of a rotated box. A green
   disc on its own says a colour; a green disc with a tick in it says the thing
   came back signed. */

.hjs__seal::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 46%;
  width: 6px;
  height: 11px;
  transform: translate(-50%, -50%) rotate(45deg);
  border-right: 2.5px solid #ffffff;
  border-bottom: 2.5px solid #ffffff;
}

/* ---- 08 onboarding ------------------------------------------------------ */

.hjs__person {
  left: 34px;
  top: 34px;
  width: 28px;
  height: 28px;
}

.hjs__person i {
  position: absolute;
  left: 50%;
  top: 32px;
  width: 44px;
  height: 24px;
  transform: translateX(-50%);
  border-radius: 16px 16px 4px 4px;
  background-color: inherit;
}

/* The screen, with the base as its own element underneath. A single rounded
   rectangle read as a blob rather than as a machine somebody is sitting at. */

.hjs__desk {
  left: 28px;
  bottom: 44px;
  width: 40px;
  height: 26px;
  border-radius: 4px;
  background-color: color-mix(in srgb, var(--c) 34%, #ffffff);
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--c) 48%, #ffffff);
}

.hjs__desk i {
  position: absolute;
  left: 50%;
  bottom: -7px;
  width: 56px;
  height: 6px;
  transform: translateX(-50%);
  border-radius: 2px 2px 4px 4px;
  background-color: color-mix(in srgb, var(--c) 48%, #ffffff);
}

.hjs__list {
  right: 22px;
  top: 50%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 72px;
  padding: 13px 11px;
  transform: translateY(-50%);
  border-radius: 9px;
  background-color: #ffffff;
  box-shadow: 0 8px 22px -14px rgba(16, 24, 48, 0.5);
}

/* ==========================================================================
   Narrow cards

   Below the four-column grid each card is wider than it is on desktop, so the
   scenes need nothing. Below the two-column grid they are wider still. The one
   thing that does change is the badge row: with no line to draw, the number
   sits on its own.
   ========================================================================== */

@media (max-width: 1023.98px) {
  .hjy__top {
    margin-bottom: 12px;
  }
}

/* ==========================================================================
   PERFORMANCE SEQUENCE  (includes/perf-*-ui.php)
   Three drawn screens for sections/performance/showcase.php: the goals board,
   the check-in dialog and the review summary. Type is small on purpose, the
   way every other drawn interface on this site is: these are pictures of a
   product, read at a glance, not documents to be read word by word.
   ========================================================================== */

/* One shared height. Stacked in a single grid cell under a pinned stage, a
   frame that resized on handover would make the whole section jump. 500px is
   the review summary, which is the tallest of the three. */

.sc-panel__frame--prf {
  display: flex;
  /* 505 = the goals board's 464px of sheet, measured, plus the blue box's 20px
     top and bottom. It is the tallest of the three and all three share the
     value, so the pinned stage cannot resize on handover. */
  min-height: 505px;
  background-color: #DCE4F6;
}

.sc-panel__frame--prf > * {
  flex: 1;
  min-height: 0;
}

.pgo, .pck, .prv {
  min-height: 0;
}

.pgo .sc-sheet,
.pck .sc-sheet,
.prv .sc-sheet {
  display: flex;
  flex-direction: column;
  gap: 9px;
  overflow: hidden;
  min-height: 0;
}

/* ---- shared small parts ---- */

.pgo__title, .pck__title, .prv__title {
  font-size: 13px;
  font-weight: 700;
  color: #22262F;
}

/* ---- 01 the goals board ---- */

.pgo__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.pgo__titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.pgo__sub {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9px;
  font-weight: 500;
  color: #8A90A0;
}

.pgo__new {
  flex: none;
  padding: 5px 11px;
  border-radius: 8px;
  background-color: #5B4BE3;
  color: #ffffff;
  font-size: 9px;
  font-weight: 700;
}

.pgo__tabs {
  display: flex;
  gap: 14px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.pgo__tab {
  padding-bottom: 6px;
  font-size: 9.5px;
  font-weight: 600;
  color: #8A90A0;
}

.pgo__tab--on {
  color: #5B4BE3;
  box-shadow: inset 0 -1.5px 0 #5B4BE3;
}

.pgo__filters {
  display: flex;
  align-items: center;
  gap: 6px;
}

.pgo__year {
  padding: 4px 9px;
  border-radius: 7px;
  border: 1px solid rgba(16, 24, 48, 0.12);
  font-size: 9px;
  font-weight: 600;
  color: #4A5164;
}

.pgo__q {
  padding: 4px 9px;
  border-radius: 7px;
  font-size: 9px;
  font-weight: 600;
  color: #8A90A0;
}

.pgo__q--on {
  background-color: #5B4BE3;
  color: #ffffff;
}

.pgo__roll {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pgo__rlab {
  flex: none;
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
}

.pgo__rbar {
  flex: 1;
  height: 6px;
  border-radius: 100px;
  background-color: #ECEEF6;
}

.pgo__rfill {
  display: block;
  width: var(--w, 0%);
  height: 100%;
  border-radius: 100px;
  background-color: #5B4BE3;
}

.pgo__rpct {
  flex: none;
  font-size: 8.5px;
  font-weight: 700;
  color: #5B4BE3;
  font-variant-numeric: tabular-nums;
}

/* The four columns every row shares, including the header. */

.pgo__cols,
.pgo__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 84px 52px 96px;
  align-items: center;
  gap: 8px;
}

.pgo__cols {
  padding-bottom: 5px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
  font-size: 7.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.pgo__list {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
  min-height: 0;
}

.pgo__row {
  padding: 7px 0;
  border-bottom: 1px solid rgba(16, 24, 48, 0.05);
}

.pgo__row--kr {
  background-color: #FAFBFE;
}

.pgo__name {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

/* A caret rather than a chevron glyph: one triangle, rotated when open. */

.pgo__caret {
  flex: none;
  width: 0;
  height: 0;
  border-top: 3px solid transparent;
  border-bottom: 3px solid transparent;
  border-left: 4px solid #A6ADBD;
}

.pgo__caret.is-open {
  transform: rotate(90deg);
}

.pgo__dot {
  flex: none;
  width: 3px;
  height: 3px;
  margin-left: 12px;
  border-radius: 100px;
  background-color: #A6ADBD;
}

.pgo__nm {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
}

.pgo__row--kr .pgo__nm {
  font-weight: 500;
  color: #6B7285;
}

.pgo__state {
  flex: none;
  padding: 1.5px 6px;
  border-radius: 100px;
  font-size: 7px;
  font-weight: 700;
  font-style: normal;
}

.pgo__state--active {
  background-color: #E6F6EC;
  color: #167C3C;
}

.pgo__state--draft  {
  background-color: #EDEFF5;
  color: #6B7285;
}

.pgo__type {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.pgo__scope {
  font-size: 8.5px;
  font-weight: 600;
  color: #4A5164;
}

.pgo__unit {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 7.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.pgo__period {
  font-size: 8px;
  font-weight: 500;
  color: #8A90A0;
  font-variant-numeric: tabular-nums;
}

.pgo__prog {
  display: flex;
  align-items: center;
  gap: 6px;
}

.pgo__bar {
  flex: 1;
  height: 5px;
  border-radius: 100px;
  background-color: #ECEEF6;
}

.pgo__fill {
  display: block;
  width: var(--w, 0%);
  height: 100%;
  min-width: 5px;
  border-radius: 100px;
  background-color: #5B4BE3;
}

.pgo__pct {
  flex: none;
  font-size: 8px;
  font-weight: 700;
  font-style: normal;
  color: #4A5164;
  font-variant-numeric: tabular-nums;
}

/* ---- 02 the check-in dialog ---- */

.pck__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.pck__x {
  font-size: 13px;
  color: #A6ADBD;
}

.pck__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 14px;
  min-height: 0;
}

.pck__left, .pck__right {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.pck__goal {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 8px;
  border-radius: 9px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #FAFBFE;
}

.pck__glabel {
  font-size: 8.5px;
  font-weight: 600;
  color: #8A90A0;
}

.pck__select,
.pck__input {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 6px 8px;
  border-radius: 7px;
  border: 1px solid rgba(16, 24, 48, 0.12);
  background-color: #ffffff;
  font-size: 9.5px;
  font-weight: 600;
  color: #22262F;
}

.pck__select em, .pck__input em {
  margin-left: auto;
  font-style: normal;
  color: #A6ADBD;
}

.pck__range {
  font-size: 7.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.pck__range b {
  color: #4A5164;
}

.pck__fields {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.pck__field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.pck__flab {
  font-size: 8.5px;
  font-weight: 600;
  color: #4A5164;
}

.pck__flab--c {
  margin-top: 3px;
}

.pck__dot {
  width: 5px;
  height: 5px;
  border-radius: 100px;
}

.pck__dot--risk {
  background-color: #E9A23B;
}

.pck__hint {
  font-size: 7.5px;
  font-weight: 500;
  color: #A6ADBD;
}

.pck__hint--warn {
  color: #B4761B;
}

.pck__area {
  padding: 8px;
  border-radius: 7px;
  border: 1px solid rgba(16, 24, 48, 0.12);
  min-height: 42px;
  font-size: 8.5px;
  font-weight: 500;
  color: #C3C8D4;
}

.pck__actions {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
  margin-top: auto;
}

.pck__btn {
  padding: 5px 12px;
  border-radius: 7px;
  border: 1px solid rgba(16, 24, 48, 0.12);
  font-size: 9px;
  font-weight: 700;
  color: #4A5164;
}

.pck__btn--go {
  border-color: #5B4BE3;
  background-color: #5B4BE3;
  color: #ffffff;
}

.pck__trendhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.pck__tlab {
  font-size: 9px;
  font-weight: 700;
  color: #22262F;
}

.pck__tpct {
  font-size: 9px;
  font-weight: 700;
  color: #0EA5A0;
  font-variant-numeric: tabular-nums;
}

.pck__chart {
  position: relative;
  padding: 8px;
  border-radius: 9px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #FAFBFE;
}

.pck__svg {
  display: block;
  width: 100%;
  height: 52px;
}

/* Stroke widths are in user units on a 100x44 box that is then stretched, so
   vector-effect keeps them even rather than squashing them horizontally. */

.pck__line {
  fill: none;
  stroke: #0EA5A0;
  stroke-width: 1.6;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.pck__target {
  stroke: #D6DAE6;
  stroke-width: 1;
  stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke;
}

.pck__tnote {
  position: absolute;
  top: 6px;
  right: 10px;
  font-size: 6.5px;
  font-weight: 600;
  color: #A6ADBD;
}

.pck__foot {
  display: flex;
  justify-content: space-between;
  font-size: 7px;
  font-weight: 600;
  color: #A6ADBD;
}

.pck__alab {
  margin-top: 2px;
  font-size: 9px;
  font-weight: 700;
  color: #22262F;
}

.pck__log {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin: 0;
  padding: 0;
  list-style: none;
  min-height: 0;
}

.pck__item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 6px;
  padding: 6px 8px;
  border-radius: 8px;
  border: 1px solid rgba(16, 24, 48, 0.07);
}

.pck__who {
  font-size: 8.5px;
  font-weight: 700;
  color: #22262F;
}

.pck__when {
  font-size: 7.5px;
  font-weight: 500;
  color: #A6ADBD;
  text-align: right;
}

.pck__move {
  grid-column: 1;
  font-size: 8.5px;
  font-weight: 500;
  color: #6B7285;
  font-variant-numeric: tabular-nums;
}

.pck__move b {
  color: #22262F;
}

.pck__tag {
  grid-column: 2;
  justify-self: end;
  padding: 1.5px 6px;
  border-radius: 100px;
  font-size: 6.5px;
  font-weight: 700;
  font-style: normal;
}

.pck__tag--on   {
  background-color: #E6F6EC;
  color: #167C3C;
}

.pck__tag--risk {
  background-color: #FCF0DF;
  color: #B4761B;
}

.pck__note {
  grid-column: 1 / -1;
  font-size: 7px;
  font-weight: 500;
  color: #A6ADBD;
}

/* ---- 03 the review summary ---- */

.prv__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.prv__pill {
  flex: none;
  padding: 4px 10px;
  border-radius: 7px;
  background-color: #5B4BE3;
  color: #ffffff;
  font-size: 8px;
  font-weight: 700;
}

.prv__who {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: 10px;
  border: 1px solid rgba(16, 24, 48, 0.08);
}

.prv__av {
  display: grid;
  place-items: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 100px;
  background-color: #E9A23B;
  color: #ffffff;
  font-size: 10px;
  font-weight: 700;
}

.prv__whobody {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.prv__line1 {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10.5px;
  color: #22262F;
}

.prv__code {
  padding: 1px 6px;
  border-radius: 100px;
  border: 1px solid rgba(16, 24, 48, 0.12);
  font-size: 7px;
  font-style: normal;
  font-weight: 600;
  color: #6B7285;
}

.prv__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 7.5px;
  font-weight: 500;
  color: #8A90A0;
}

.prv__scores {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.prv__score {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 7px 9px;
  border-radius: 9px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #FAFBFE;
}

.prv__slab {
  font-size: 7px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.prv__srow {
  display: flex;
  align-items: center;
  gap: 6px;
}

.prv__srow em {
  font-size: 10px;
  font-weight: 700;
  font-style: normal;
  color: #22262F;
}

.prv__stars {
  display: inline-flex;
  gap: 1.5px;
}

.prv__star {
  width: 11px;
  height: 11px;
  fill: #E2E5EE;
}

.prv__star.is-on {
  fill: #F5B531;
}

.prv__stars--sm .prv__star {
  width: 8px;
  height: 8px;
}

.prv__table {
  border-radius: 10px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  overflow: hidden;
}

/* The two reviewer bands over their own column pairs. */

.prv__owners {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr) minmax(0, 1fr);
}

.prv__ocell {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 6px 8px;
  font-size: 8.5px;
  font-weight: 700;
  color: #22262F;
}

.prv__ocell em {
  padding: 1px 5px;
  border-radius: 100px;
  font-size: 6.5px;
  font-style: normal;
  font-weight: 700;
}

.prv__ocell--kra {
  color: #6B7285;
  background-color: #F7F8FC;
}

.prv__ocell--self {
  background-color: #EAF1FE;
}

.prv__ocell--self em {
  background-color: #D5E3FC;
  color: #1D4ED8;
}

.prv__ocell--mgr {
  background-color: #F5EEFC;
}

.prv__ocell--mgr em {
  background-color: #E7D9F8;
  color: #6D28D9;
}

.prv__cols,
.prv__row {
  display: grid;
  grid-template-columns: 84px 48px 64px minmax(0, 1fr) 64px minmax(0, 1fr);
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
}

.prv__cols {
  border-top: 1px solid rgba(16, 24, 48, 0.06);
  border-bottom: 1px solid rgba(16, 24, 48, 0.06);
  background-color: #FAFBFE;
  font-size: 6.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.prv__row + .prv__row {
  border-top: 1px solid rgba(16, 24, 48, 0.05);
}

.prv__kra {
  font-size: 8.5px;
  font-weight: 600;
  color: #22262F;
}

.prv__wt {
  justify-self: start;
  padding: 1.5px 6px;
  border-radius: 100px;
  background-color: #EDEFF5;
  font-size: 7px;
  font-weight: 700;
  color: #4A5164;
}

.prv__rate {
  display: flex;
  align-items: center;
  gap: 4px;
}

.prv__rate em {
  font-size: 7.5px;
  font-weight: 700;
  font-style: normal;
  color: #4A5164;
}

.prv__cmt {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 7.5px;
  font-weight: 500;
  color: #8A90A0;
}

.prv__row--sum {
  background-color: #FAFBFE;
}

.prv__row--sum .prv__kra {
  color: #4A5164;
}

/* The summary row has no weight of its own, and an empty .prv__wt still drew
   its grey pill. */

.prv__row--sum .prv__wt {
  background-color: transparent;
}

.prv__final {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 10px;
  border: 1px solid rgba(91, 75, 227, 0.35);
  background-color: #FAFAFE;
}

.prv__fbody {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.prv__flab {
  font-size: 7px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #A6ADBD;
}

.prv__flab--hr {
  margin-top: 4px;
}

.prv__hr {
  font-size: 8px;
  font-weight: 500;
  color: #6B7285;
}

.prv__done {
  flex: none;
  padding: 2px 8px;
  border-radius: 100px;
  background-color: #E7E4FB;
  font-size: 7px;
  font-style: normal;
  font-weight: 700;
  color: #4B3BD1;
}

/* Narrow frame: the comment columns are the first thing to go, then the
   check-in dialog stops being two columns. */

@container (max-width: 420px) {
  .pgo__cols, .pgo__row {
    grid-template-columns: minmax(0, 1fr) 60px 84px;
  }

  .pgo__type {
    display: none;
  }

  .prv__cols, .prv__row {
    grid-template-columns: 74px 40px 58px 58px;
  }

  .prv__cmt {
    display: none;
  }

  .prv__owners {
    grid-template-columns: 74px minmax(0, 1fr) minmax(0, 1fr);
  }

  .pck__body {
    grid-template-columns: minmax(0, 1fr);
  }

  .pck__right {
    display: none;
  }
}

/* The heading is two lines long and its first line does not fit the shared
   720px measure. Widened here rather than by taking .hs-head--wide, which
   would also bring the nowrap that ran this heading off the page. The lead
   keeps a reading measure of its own. */

.hjy__head {
  max-width: 940px;
}

.hjy__head .hs-head__lead {
  max-width: 620px;
  margin-left: auto;
  margin-right: auto;
}

/* A medium-risk position. The high-risk pill is the default; this is the same
   pill in a calmer colour, so the two read as a scale rather than as two
   unrelated tags. */

.scr__risk--mid {
  background-color: #EDEFF5;
  color: #5A6070;
}

/* A critical position with nobody named against it. Marked, not left blank:
   an empty cell reads as missing data, and this is the finding. */

.scr__miss {
  display: inline-grid;
  place-items: center;
  width: 13px;
  height: 13px;
  border-radius: 100px;
  background-color: #FBE9E7;
  color: #B3261E;
  font-size: 8px;
  font-weight: 700;
}

/* The readiness summary under the nine-box: the same six people the boxes
   hold, grouped by how far off they are. */

.scg__sum {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.scg__sitem {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 10px;
  background-color: #F7F8FC;
}

.scg__snum {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  flex: none;
  border-radius: 7px;
  font-size: 11px;
  font-weight: 700;
}

.scg__snum--good {
  background-color: #E6F6EC;
  color: #167C3C;
}

.scg__snum--cool {
  background-color: #EAF1FE;
  color: #1D4ED8;
}

.scg__snum--weak {
  background-color: #FBE9E7;
  color: #B3261E;
}

.scg__slab {
  font-size: 8.5px;
  font-weight: 600;
  line-height: 1.3;
  color: #5A6070;
}

/* The skill matrix sequence carries the longest titles of any showcase on the
   site: "See Every Employee's Skill Level" needs more than the shared 480px
   before its own line break can land where the copy asks for it. Scoped to
   this section so every other sequence keeps the narrower measure. */

#sk-showcase .sc-panel__body {
  max-width: 560px;
}

/* The pulse is the marker's shadow on the ground, under the tip. */

.fdl__pin .fdl__pulse {
  inset: auto auto -4px 50%;
  width: 16px;
  height: 6px;
  margin-left: -8px;
  border-radius: 100px;
}

/* The path fills the box; the letter sits in the round head above the tip. */

.fdl__marker {
  display: block;
  width: 100%;
  height: 100%;
  fill: currentColor;
}

.fdl__pin .fdl__initials {
  position: absolute;
  left: 0;
  right: 0;
  top: 4px;
  text-align: center;
  color: #ffffff;
}

/* The sourcing comparison heading is two lines and long: its first line runs to
   about 1120px at the desktop heading size. It needs more measure than the
   shared 720px, but not the nowrap that .hs-head--wide brings, which pushed
   both lines out of the box and left them sitting against its left edge.
   1180px is as wide as the 1200px content column allows. */

.so-vs__head {
  max-width: 1180px;
}

.so-vs__head .hs-head__lead {
  max-width: 620px;
  margin-left: auto;
  margin-right: auto;
}

.hover\:-translate-y-\[2px\]:hover {
  --tw-translate-y: -2px;
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.hover\:bg-line:hover {
  --tw-bg-opacity: 1;
  background-color: rgb(221 229 237 / var(--tw-bg-opacity, 1));
}

.hover\:bg-surface:hover {
  --tw-bg-opacity: 1;
  background-color: rgb(237 241 244 / var(--tw-bg-opacity, 1));
}

.hover\:text-ink:hover {
  --tw-text-opacity: 1;
  color: rgb(29 29 29 / var(--tw-text-opacity, 1));
}

.hover\:opacity-100:hover {
  opacity: 1;
}

.focus\:not-sr-only:focus {
  position: static;
  width: auto;
  height: auto;
  padding: 0;
  margin: 0;
  overflow: visible;
  clip: auto;
  white-space: normal;
}

.focus\:fixed:focus {
  position: fixed;
}

.focus\:left-4:focus {
  left: 1rem;
}

.focus\:top-4:focus {
  top: 1rem;
}

.focus\:z-\[100\]:focus {
  z-index: 100;
}

.focus\:rounded-pill:focus {
  border-radius: 100px;
}

.focus\:bg-ink:focus {
  --tw-bg-opacity: 1;
  background-color: rgb(29 29 29 / var(--tw-bg-opacity, 1));
}

.focus\:px-5:focus {
  padding-left: 1.25rem;
  padding-right: 1.25rem;
}

.focus\:py-3:focus {
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}

.focus\:text-body-xs:focus {
  font-size: 14px;
  line-height: 1.3;
}

.focus\:font-semibold:focus {
  font-weight: 600;
}

.focus\:text-white:focus {
  --tw-text-opacity: 1;
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}

@media (min-width: 640px) {
  .sm\:left-\[10\%\] {
    left: 10%;
  }

  .sm\:col-span-2 {
    grid-column: span 2 / span 2;
  }

  .sm\:block {
    display: block;
  }

  .sm\:inline-flex {
    display: inline-flex;
  }

  .sm\:h-\[370px\] {
    height: 370px;
  }

  .sm\:h-\[394px\] {
    height: 394px;
  }

  .sm\:h-\[86px\] {
    height: 86px;
  }

  .sm\:w-\[380px\] {
    width: 380px;
  }

  .sm\:w-\[400px\] {
    width: 400px;
  }

  .sm\:w-\[86px\] {
    width: 86px;
  }

  .sm\:w-auto {
    width: auto;
  }

  .sm\:grid-cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .sm\:grid-cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .sm\:grid-cols-\[1fr_225px\] {
    grid-template-columns: 1fr 225px;
  }

  .sm\:flex-row {
    flex-direction: row;
  }

  .sm\:justify-center {
    justify-content: center;
  }

  .sm\:gap-6 {
    gap: 1.5rem;
  }

  .sm\:p-9 {
    padding: 2.25rem;
  }

  .sm\:px-\[30px\] {
    padding-left: 30px;
    padding-right: 30px;
  }

  .sm\:pb-\[46px\] {
    padding-bottom: 46px;
  }

  .sm\:text-\[72px\] {
    font-size: 72px;
  }

  .sm\:text-body-lg {
    font-size: 20px;
    line-height: 1.3;
  }

  .sm\:text-body-md {
    font-size: 18px;
    line-height: 1.3;
  }

  .sm\:text-body-sm {
    font-size: 16px;
    line-height: 1.3;
  }

  .sm\:text-display-sm {
    font-size: 32px;
    line-height: 1.2;
    letter-spacing: -0.2px;
  }

  .sm\:text-display-xs {
    font-size: 28px;
    line-height: 1.2;
  }
}

@media (min-width: 768px) {
  .md\:block {
    display: block;
  }

  .md\:inline {
    display: inline;
  }

  .md\:grid-cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .md\:grid-cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .md\:flex-row {
    flex-direction: row;
  }

  .md\:items-center {
    align-items: center;
  }

  .md\:justify-between {
    justify-content: space-between;
  }

  .md\:rounded-\[14px\] {
    border-radius: 14px;
  }

  .md\:rounded-\[22px\] {
    border-radius: 22px;
  }

  .md\:p-\[10px\] {
    padding: 10px;
  }

  .md\:px-\[100px\] {
    padding-left: 100px;
    padding-right: 100px;
  }

  .md\:py-\[100px\] {
    padding-top: 100px;
    padding-bottom: 100px;
  }

  .md\:pt-\[100px\] {
    padding-top: 100px;
  }

  .md\:pt-\[194px\] {
    padding-top: 194px;
  }

  .md\:text-body-lg {
    font-size: 20px;
    line-height: 1.3;
  }

  .md\:text-body-md {
    font-size: 18px;
    line-height: 1.3;
  }

  .md\:text-display-2xs {
    font-size: 24px;
    line-height: 1.2;
  }

  .md\:text-display-xs {
    font-size: 28px;
    line-height: 1.2;
  }
}

@media (min-width: 1024px) {
  .lg\:sticky {
    position: sticky;
  }

  .lg\:bottom-\[232px\] {
    bottom: 232px;
  }

  .lg\:top-\[80px\] {
    top: 80px;
  }

  .lg\:my-\[-12px\] {
    margin-top: -12px;
    margin-bottom: -12px;
  }

  .lg\:block {
    display: block;
  }

  .lg\:flex {
    display: flex;
  }

  .lg\:inline-flex {
    display: inline-flex;
  }

  .lg\:grid {
    display: grid;
  }

  .lg\:hidden {
    display: none;
  }

  .lg\:h-\[124px\] {
    height: 124px;
  }

  .lg\:h-\[1525px\] {
    height: 1525px;
  }

  .lg\:h-\[260px\] {
    height: 260px;
  }

  .lg\:h-\[505px\] {
    height: 505px;
  }

  .lg\:w-\[124px\] {
    width: 124px;
  }

  .lg\:flex-\[380_380_0\%\] {
    flex: 380 380 0%;
  }

  .lg\:flex-\[790_790_0\%\] {
    flex: 790 790 0%;
  }

  .lg\:grid-cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .lg\:grid-cols-\[minmax\(0\2c 1fr\)_minmax\(0\2c 1\.25fr\)\] {
    grid-template-columns: minmax(0,1fr) minmax(0,1.25fr);
  }

  .lg\:grid-cols-\[minmax\(0\2c 420px\)_minmax\(0\2c 1fr\)\] {
    grid-template-columns: minmax(0,420px) minmax(0,1fr);
  }

  .lg\:grid-cols-\[minmax\(0\2c 460px\)_minmax\(0\2c 1fr\)\] {
    grid-template-columns: minmax(0,460px) minmax(0,1fr);
  }

  .lg\:flex-row {
    flex-direction: row;
  }

  .lg\:items-end {
    align-items: flex-end;
  }

  .lg\:justify-between {
    justify-content: space-between;
  }

  .lg\:gap-\[100px\] {
    gap: 100px;
  }

  .lg\:gap-\[70px\] {
    gap: 70px;
  }

  .lg\:py-\[100px\] {
    padding-top: 100px;
    padding-bottom: 100px;
  }

  .lg\:pt-\[110px\] {
    padding-top: 110px;
  }

  .lg\:text-right {
    text-align: right;
  }

  .lg\:text-\[100px\] {
    font-size: 100px;
  }

  .lg\:tracking-\[-1\.4px\] {
    letter-spacing: -1.4px;
  }
}

@media (min-width: 1280px) {
  .xl\:block {
    display: block;
  }

  .xl\:hidden {
    display: none;
  }

  .xl\:gap-10 {
    gap: 2.5rem;
  }
}

/* The AI cube standing in for the word "AI" inside the rotating phrase. Sized
   in em so it scales with the heading at every breakpoint, and nudged up a
   fraction because the glyphs beside it sit on a baseline while the cube is a
   box centred on the line. */
.hero-ai-mark {
  display: inline-block;
  vertical-align: middle;
  margin: 0 0.04em;
}

.hero-ai-cube {
  display: block;
  width: 0.92em;
  height: 0.92em;
  margin-top: -0.1em;
}

/* The Vimeo player fills the same 16:9 frame the local film uses, so the panel
   is the same size whichever kind of film it is showing. */
.vmodal__embed {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: inherit;
  background-color: #000;
}

.vmodal__embed[hidden] { display: none; }

/* ==========================================================================
   LIVE FEATURE BENTO — sections/live-features.php

   Seven steps of the employee lifecycle, each with a small working interface,
   on an auto-playing rail that shows three at a time. Every panel is markup
   rather than a screenshot, so it stays sharp at any density and starts
   without a network request.

   The loops run 8 to 12 seconds and are deliberately never the same length, so
   the seven do not fall into step. Seven short animations in sync read as a
   page still loading; seven long ones that never meet read as seven things
   quietly working.
   ========================================================================== */

.lfx {
  background-color: #F7F9FC;
  background-image: linear-gradient(180deg, #FFFFFF 0%, #F4F7FC 46%, #FFFFFF 100%);
}

/* Phone padding, cut to the 40 the statement section above it now runs at.
   .section's own 70 sat on top of a stage that is already a viewport tall and
   centres what is in it, so the heading started a long way down a screen that
   has none to spare. Only below 768: the desktop rail is tuned around its
   100. */

@media (max-width: 767px) {
  .lfx {
    padding-top: 24px;
    padding-bottom: 40px;
  }
}

.lfx-lede {
  max-width: 760px;
  margin: 0 auto 18px;
  text-align: center;
}

/* The band between the lede and the first card was the lede's own margin, the
   stage's gap and the row's top padding stacked — near 80px of nothing on a
   stage that is already only one viewport tall. The stage gap is narrowed here
   rather than on .hs-rail__stage itself: the industries rail shares that class
   and has a taller heading block above its row. */

.lfx .hs-rail__stage {
  gap: clamp(14px, 1.8vh, 24px);
}

.lfx-lede__text {
  margin-top: 16px;
}

/* ---- the row ----

   The rail is pinned: .hs-rail__stage sticks under the navbar inside a tall
   .hs-rail__track, and js/industries-pan.js turns the scroll into the row's x.
   Everything about the pin is shared with the industries rail, including
   --rail-inset, which is the gutter that lines the first card up with the
   heading above it and keeps the last card off the right edge when it lands.

   SIZED BY HEIGHT, NOT WIDTH
   Same constraint the industries cards have and for the same reason: the stage
   is one viewport tall and carries a heading, so a card measured against the
   viewport's WIDTH comes out too tall to fit on a laptop in landscape. The
   panel's 3:2 and the copy under it are what set the height, so the width
   follows from a clamp rather than from a share of the column. */

.lfx-row {
  display: flex;
  flex-wrap: nowrap;
  width: -moz-max-content;
  width: max-content;
  gap: clamp(14px, 1.6vw, 22px);
  margin: 0;
  padding: 0 var(--rail-inset) 26px;
  list-style: none;
}

.lfx-card {
  flex: 0 0 auto;
  width: clamp(280px, 30vw, 400px);
  /* The focus effect: cards being cut off by either edge of the rail sit back
     a little. js/industries-pan.js writes the values, this curve carries them,
     and it is short because they change every frame the reader scrolls. */
  transition:
    opacity 260ms var(--ease-smooth),
    transform 260ms var(--ease-smooth),
    box-shadow 320ms var(--ease-soft);
}

/* ---- a card ----

   The card is the TINTED surface and the panel inside it is the white one, not
   the other way round. That inversion is what makes the interface read as a
   window set into the card rather than a sticker laid on top of it, and it is
   why the panel's own elements carry a faint tint below: white on white needs
   a border to exist, white on tint does not. */

.lfx-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 30px 28px 28px;
  border-radius: 26px;
  background-color: var(--lfx-ground, #F1F7FF);
  /* Left, not centred. The name and the line under it are the card's opening
     sentence and the panel below is what it is talking about; ranged left they
     read as one column, centred they read as a label floating over a picture. */
  text-align: left;
}

.lfx-card:hover {
  transform: translateY(-3px);
}


/* ---- one pastel per step ----

   Seven grounds rather than one, so the rail reads as a set of distinct things
   rather than seven printings of the same card. They are held deliberately
   pale: the interface inside each card is white and the type on top is near
   black, and both of those have to survive whatever the ground is doing. Every
   tone here sits above 92% lightness for that reason — a ground with any real
   saturation in it would start competing with the panel it holds.

   The hairline is the same hue a step or two darker, so a card's edge belongs
   to its ground instead of being one grey border used seven times. */

/* ONE GROUND, NOT EIGHT

   The rail used to wear a different pastel per step. The reference card is a
   single pale blue with a blue outline on every card in its row, and a set of
   cards that differ only in what is inside them reads as one system where eight
   tints read as eight unrelated things.

   The per-step tints are kept here rather than deleted, so putting them back is
   a paste and not a rebuild:

     sourcing #EDF3FD/#DCE7F9   hiring   #F1EFFD/#E1DCF8
     onboarding #E9F6F0/#D3ECE0 attendance #E8F4FA/#D2E8F3
     payroll  #FDF2EA/#F6E1CF   pms      #FBF5E8/#F1E6CC
     rewards  #FCEFF4/#F5DCE6   exit     #EEF1F7/#DFE4EF

   --lfx-ground stays a custom property: the corner button punches a ring of the
   card's own ground through the panel it overlaps, so something other than the
   card itself needs to know what that ground is. */

.lfx-card {
  --lfx-ground: #F1F7FF;
}

/* The exit card keeps a ground of its own: a cool slate, because every other
   tone in the rail is a colour with a mood on it and an exit is the one step
   that should read as neutral rather than as bad news or a celebration. */
.lfx-card--exit { --lfx-ground: #EEF1F7; }

/* The outline is the reference's own signature and it is a real blue, not a
   grey hairline: it is what makes the card read as drawn rather than as a
   tinted rectangle. No glow under it — the outline is the whole edge, and the
   card sits flat on the section rather than hovering over it. */

.lfx-card {
  box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.42);
}

.lfx-card:hover {
  box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.75);
}

/* Hover keeps the card's own hue and simply deepens the edge, rather than
   snapping all seven to one blue. */

.lfx-card--sourcing:hover   { box-shadow: inset 0 0 0 1px #C6D8F5, 0 30px 56px -34px rgba(21, 82, 199, 0.4); }
.lfx-card--hiring:hover     { box-shadow: inset 0 0 0 1px #CDC4F3, 0 30px 56px -34px rgba(84, 60, 200, 0.4); }
.lfx-card--onboarding:hover { box-shadow: inset 0 0 0 1px #B9E0CD, 0 30px 56px -34px rgba(24, 128, 90, 0.36); }
.lfx-card--attendance:hover { box-shadow: inset 0 0 0 1px #B8DCEC, 0 30px 56px -34px rgba(22, 106, 146, 0.36); }
.lfx-card--payroll:hover    { box-shadow: inset 0 0 0 1px #EFCDB0, 0 30px 56px -34px rgba(176, 96, 40, 0.34); }
.lfx-card--pms:hover        { box-shadow: inset 0 0 0 1px #E7D6AB, 0 30px 56px -34px rgba(158, 122, 30, 0.32); }
.lfx-card--rewards:hover    { box-shadow: inset 0 0 0 1px #EFC6D8, 0 30px 56px -34px rgba(176, 60, 110, 0.32); }

/* The stage every interface sits on. A fixed ratio rather than a height, so
   the seven panels stay the same shape as the rail resizes and the row never
   develops a ragged bottom edge. 3:2 is set by the tallest of the seven, the
   search with its three results — the rest simply have more air. */

.lfx-art {
  position: relative;
  /* Pushed to the foot. Cards in a rail stretch to the tallest of them, and the
     heads above run to different depths; anchored at the bottom the panels line
     up across the row however long the copy above each one is. */
  margin-top: auto;
  overflow: hidden;
  aspect-ratio: 3 / 2;
  border-radius: 20px;
  /* Still white, and deliberately. The reference floats its illustration
     straight on the card, but its illustration is built of white shapes; ours
     are eight working interfaces whose own surfaces are pale, and on a blue
     ground half of them would stop having edges.

     No shadow: white on a pale blue ground is already its own edge. */
  background-color: #FFFFFF;
}

/* The step name, at display size, over the panel it names. */

.lfx-card__head {
  margin-bottom: 24px;
}

.lfx-card__title {
  margin-top: 0;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 27px;
  font-weight: 700;
  line-height: 1.18;
  letter-spacing: -0.6px;
  /* Navy rather than near-black. On a blue ground a black heading reads as
     borrowed from another page; the reference takes its darkest tone from the
     same hue the card is made of. */
  color: #0B1B33;
}

/* 27px is a desktop card's heading. The card is a fixed 280px at the bottom of
   its clamp, so on a phone the longer names ("Employee Management", "Payroll
   and Compliance") set two and three lines at that size and pushed the panel
   under them down. 20 keeps them to one or two. */

@media (max-width: 767px) {
  .lfx-card__title {
    font-size: 20px;
  }
}

/* Kept for the promise line the card no longer prints; see the note in
   sections/live-features.php beside the heading. Restoring that line should
   not also mean rewriting its styling. */

.lfx-card__lede {
  margin-top: 7px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
  color: #6B7688;
}

.lfx-card__text {
  /* The copy is written to two lines and the measure is what keeps it there:
     the narrowest card is 280px, so a measure any wider than this would hold
     two lines on a desktop card and spill to three on a laptop. */
  max-width: 32ch;
  margin-top: 8px;
  font-size: 16.5px;
  font-weight: 500;
  line-height: 1.52;
  color: #33415A;
}

/* ---- the link, as a corner button ----

   It replaces a "Read more" pill that appeared on hover, swapped in over the
   description and gated on a pointer that could hover. That gave the card one
   layout for mice and another for touch. A button that is simply there has one
   layout and one behaviour.

   Absolutely placed, so it is out of flow and cannot lengthen the card or shift
   the panel it sits over. The ring is the card's own ground, which is what makes
   it read as punched through the panel's corner rather than dropped on top of
   it — and it is why the tone above is a custom property. */

.lfx-card__go {
  position: absolute;
  right: 20px;
  bottom: 20px;
  display: grid;
  place-items: center;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background-color: #2563EB;
  box-shadow:
    0 0 0 8px var(--lfx-ground, #F1F7FF),
    0 14px 26px -14px rgba(21, 82, 199, 0.9);
  color: #FFFFFF;
  transition:
    background-color 260ms var(--ease-soft),
    transform 320ms var(--ease-smooth),
    box-shadow 320ms var(--ease-soft);
}

.lfx-card__go svg { width: 22px; height: 22px; }

.lfx-card__go:hover {
  background-color: #1D4ED8;
  transform: scale(1.06);
  box-shadow:
    0 0 0 8px var(--lfx-ground, #F1F7FF),
    0 18px 32px -14px rgba(21, 82, 199, 0.95);
}

.lfx-card__go:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: 3px;
}

/* Kept for the "Explore X" link the card no longer prints; see the note in
   sections/live-features.php. Restoring the link should not also mean
   rewriting its styling. Pushed to the foot so the links line up across the
   rail whatever the copy above them runs to. */

.lfx-card__link {
  display: inline-flex;
  align-self: center;
  align-items: center;
  gap: 7px;
  margin-top: auto;
  padding-top: 18px;
  font-size: 13.5px;
  font-weight: 600;
  color: #2563EB;
  transition: color 260ms var(--ease-soft);
}

.lfx-card__link:hover {
  color: #1D4ED8;
}

.lfx-card__arrow {
  width: 13px;
  height: 8px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 8'%3E%3Cpath d='M9 .8 12.2 4 9 7.2M12 4H.8' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 8'%3E%3Cpath d='M9 .8 12.2 4 9 7.2M12 4H.8' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform 260ms var(--ease-soft);
}

.lfx-card__link:hover .lfx-card__arrow {
  transform: translateX(3px);
}

/* Every panel fills the stage it sits on. */

.lfx-src,
.lfx-pipe,
.lfx-check,
.lfx-att,
.lfx-pay,
.lfx-perf,
.lfx-kudo,
.lfx-exit {
  position: absolute;
  inset: 0;
}

/* ---- the panels' own surfaces ----

   Faintly tinted, because the stage under them is now white. These were white
   cards on a tinted stage; inverted, they need their own tone or they exist
   only as a hairline. The floating pieces — the candidate crossing the board,
   the paid stamp, the medal — stay white or coloured on purpose: they are the
   things meant to lift off the surface rather than sit in it. */

/* ==========================================================================
   01 · ONE SEARCH, THREE SOURCES

   Vertical padding in px, not per cent. Percentage padding resolves against
   the WIDTH on both axes, so the narrower this card gets the more vertical
   padding it would grow — the opposite of what it needs.
   ========================================================================== */

.lfx-src {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 7px;
  padding: 14px 16px;
}

.lfx-src__field {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 100px;
  background-color: #F7FAFE;
  box-shadow: inset 0 0 0 1px #E9EFFA;
}

.lfx-src__glass {
  flex: none;
  color: #2563EB;
}

.lfx-src__glass svg {
  display: block;
  width: 15px;
  height: 15px;
}

/* A width animation on a clipped span rather than a JS typewriter: it cannot
   desync, and it stops on the finished line under reduced motion. */

.lfx-src__typed {
  overflow: hidden;
  flex: none;
  max-width: 100%;
  white-space: nowrap;
  font-size: 12.5px;
  font-weight: 600;
  color: #2B3140;
  animation: lfx-type 10s steps(38, end) infinite;
}

@keyframes lfx-type {
  0%, 6%    { width: 0; }
  34%, 100% { width: 100%; }
}

.lfx-src__caret {
  flex: none;
  width: 1.5px;
  height: 13px;
  background-color: #2563EB;
  animation: lfx-caret 0.9s steps(2, end) infinite;
}

@keyframes lfx-caret {
  50% { opacity: 0; }
}

.lfx-src__pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.lfx-src__pill {
  padding: 5px 10px;
  border-radius: 100px;
  background-color: #F7FAFE;
  box-shadow: inset 0 0 0 1px #E9EFFA;
  font-size: 10.5px;
  font-weight: 600;
  color: #7C879B;
  animation: lfx-pill 10s var(--ease-soft) infinite;
  animation-delay: calc(var(--i) * 360ms);
}

@keyframes lfx-pill {
  0%, 32%   { color: #7C879B; background-color: #FFFFFF; box-shadow: inset 0 0 0 1px #E9EFFA; }
  40%, 56%  { color: #1D6BF3; background-color: #EEF4FE; box-shadow: inset 0 0 0 1px #BFD6FB; }
  66%, 100% { color: #7C879B; background-color: #FFFFFF; box-shadow: inset 0 0 0 1px #E9EFFA; }
}

.lfx-src__hits {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.lfx-src__hit {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 10px;
  border-radius: 13px;
  background-color: #F7FAFE;
  box-shadow: inset 0 0 0 1px #EDF2FB;
  /* --i is the row index. One variable drives both the entrance and the meter
     fill, so a bar never starts before the row it belongs to arrives. */
  animation: lfx-hit 10s var(--ease-soft) infinite;
  animation-delay: calc(var(--i) * 420ms);
}

@keyframes lfx-hit {
  0%, 46%   { opacity: 0; transform: translateY(9px); }
  56%, 94%  { opacity: 1; transform: none; }
  100%      { opacity: 0; transform: translateY(9px); }
}

.lfx-src__badge {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background-color: #EEF4FE;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.2px;
  color: #1D6BF3;
}

.lfx-src__who {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 1px;
}

.lfx-src__who strong {
  font-size: 12px;
  font-weight: 600;
  color: #14161D;
}

.lfx-src__who em {
  font-size: 10px;
  font-style: normal;
  font-weight: 500;
  color: #7C879B;
}

.lfx-src__meter {
  overflow: hidden;
  flex: 1;
  min-width: 24px;
  height: 5px;
  margin-left: auto;
  border-radius: 100px;
  background-color: #EDF1F9;
}

.lfx-src__fill {
  display: block;
  width: var(--w);
  height: 100%;
  border-radius: inherit;
  background-image: linear-gradient(90deg, #7CB0FC, #2563EB);
  transform-origin: left center;
  animation: lfx-fill 10s var(--ease-soft) infinite;
  animation-delay: calc(var(--i) * 420ms);
}

@keyframes lfx-fill {
  0%, 52%   { transform: scaleX(0); }
  66%, 94%  { transform: scaleX(1); }
  100%      { transform: scaleX(0); }
}

.lfx-src__pct {
  flex: none;
  font-size: 11px;
  font-weight: 700;
  color: #1D6BF3;
  font-variant-numeric: tabular-nums;
}


/* The third result is the one that goes when the card is narrow. Three across
   at 1024px leaves the panel about 190px tall and this is the busiest of the
   seven — a query, its sources and two matches is still the idea; three of them
   crushed past the bottom edge is not. Above 1200px there is room for all
   three. */

@media (max-width: 1199px) {
  .lfx-src__hit:last-child {
    display: none;
  }
}

/* ==========================================================================
   02 · A CANDIDATE CROSSING THE BOARD
   ========================================================================== */

.lfx-pipe {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  padding: 16px;
}

.lfx-pipe__col {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 9px 8px;
  border-radius: 14px;
  background-color: #F7FAFE;
  box-shadow: inset 0 0 0 1px #EDF2FB;
}

.lfx-pipe__head {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: #7C879B;
}

.lfx-pipe__dot {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: #D3DEEF;
  /* Lights as the card reaches this column, so the header and the card agree
     about where in the process the candidate is. */
  animation: lfx-stage 12s var(--ease-soft) infinite;
  animation-delay: calc(var(--i) * 3.2s);
}

@keyframes lfx-stage {
  0%, 2%    { background-color: #D3DEEF; }
  8%, 24%   { background-color: #2563EB; }
  30%, 100% { background-color: #D3DEEF; }
}

.lfx-pipe__slot {
  height: 26px;
  border-radius: 9px;
  background-color: #EDF2FB;
  box-shadow: inset 0 0 0 1px #EDF2FB;
}

/* The one that moves. Absolutely placed on the stage rather than inside a
   column, because a candidate is not copied at each stage — they move, and the
   picture should say the same. */

.lfx-pipe__card {
  position: absolute;
  top: 32%;
  left: 7%;
  display: flex;
  align-items: center;
  gap: 7px;
  width: 26%;
  padding: 8px 9px;
  border-radius: 11px;
  background-color: #FFFFFF;
  box-shadow: 0 12px 22px -14px rgba(21, 82, 199, 0.85), inset 0 0 0 1px #DCE7F9;
  animation: lfx-move 12s var(--ease-soft) infinite;
}

@keyframes lfx-move {
  0%, 22%   { left: 7%;  transform: none; }
  28%, 32%  { left: 7%;  transform: translateY(-3px) scale(1.03); }
  40%, 55%  { left: 37%; transform: none; }
  61%, 65%  { left: 37%; transform: translateY(-3px) scale(1.03); }
  73%, 92%  { left: 67%; transform: none; }
  100%      { left: 7%;  transform: none; }
}

.lfx-pipe__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 21px;
  height: 21px;
  border-radius: 50%;
  background-color: #EEF4FE;
  font-size: 8.5px;
  font-weight: 700;
  color: #1D6BF3;
}

.lfx-pipe__bars {
  display: grid;
  gap: 4px;
  flex: 1;
  min-width: 0;
}

.lfx-pipe__bars span {
  display: block;
  width: var(--w);
  height: 4px;
  border-radius: 100px;
  background-color: #E4EBF7;
}

/* ==========================================================================
   03 · READY BEFORE DAY ONE
   ========================================================================== */

.lfx-check {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 7px;
  padding: 16px 18px;
}

.lfx-check__chip {
  display: inline-flex;
  align-self: center;
  align-items: center;
  gap: 7px;
  padding: 6px 11px;
  border-radius: 100px;
  background-color: #F7FAFE;
  box-shadow: inset 0 0 0 1px #E9EFFA;
  font-size: 11px;
  font-weight: 600;
  color: #2B3140;
}

.lfx-check__chip svg {
  display: block;
  width: 14px;
  height: 14px;
  color: #2563EB;
}

.lfx-check__list {
  display: grid;
  gap: 7px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.lfx-check__row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 11px;
  border-radius: 12px;
  background-color: #F7FAFE;
  box-shadow: inset 0 0 0 1px #EDF2FB;
  font-size: 11.5px;
  font-weight: 600;
  color: #2B3140;
}

.lfx-check__box {
  display: grid;
  place-items: center;
  flex: none;
  width: 17px;
  height: 17px;
  border-radius: 6px;
  background-color: #FFFFFF;
  color: transparent;
  box-shadow: inset 0 0 0 1.5px #D9E2F2;
  animation: lfx-tick 9s var(--ease-soft) infinite;
  animation-delay: calc(var(--i) * 700ms);
}

.lfx-check__box svg {
  width: 10px;
  height: 10px;
}

@keyframes lfx-tick {
  0%, 14%   { background-color: #FFFFFF; color: transparent; box-shadow: inset 0 0 0 1.5px #D9E2F2; }
  22%, 88%  { background-color: #22A06B; color: #FFFFFF; box-shadow: none; }
  96%, 100% { background-color: #FFFFFF; color: transparent; box-shadow: inset 0 0 0 1.5px #D9E2F2; }
}

/* ==========================================================================
   04 · THE WEEK IN HOURS

   Everything is placed as a share of the stage rather than in pixels. The panel
   is a 3:2 box that runs from about 224px wide to 344, so a layout in fixed
   offsets fits one end of that range and spills at the other.
   ========================================================================== */

.lfx-att { padding: 0; }

.lfx-att__chart {
  position: absolute;
  top: 19%; right: 4%; bottom: 19%; left: 9%;
  border-radius: 12px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #EDF2FA;
}

/* Three rules with a number on each, not an axis: at this size an axis is a
   line nobody can read a value off, where three rules say what the tall bar
   means at a glance. */
.lfx-att__grid {
  position: absolute;
  inset: 12% 6% 26% 6%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  margin: 0; padding: 0; list-style: none;
}

.lfx-att__grid li { position: relative; height: 1px; background-color: #EEF3FB; }

.lfx-att__grid span {
  position: absolute;
  top: 50%; left: 0;
  transform: translateY(-50%);
  padding-right: 4px;
  background-color: #FFFFFF;
  font-size: 8px; font-weight: 600; color: #A9B4C6;
}

.lfx-att__bars {
  position: absolute;
  inset: 12% 6% 6% 22%;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 6%;
  margin: 0; padding: 0; list-style: none;
}

.lfx-att__bars li {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  height: 100%;
}

/* The plot, and only the plot. The avatar sits below it, so a bar at 92% is
   92% of the space bars are drawn in rather than 92% of the column. Without
   this the flex column shrinks the tall bars and the chart draws numbers it
   was not given. */
.lfx-att__track {
  display: flex;
  flex: 1;
  align-items: flex-end;
  width: 100%;
  min-height: 0;
}

.lfx-att__bars i {
  display: block;
  flex: none;
  width: 100%;
  height: var(--h, 50%);
  border-radius: 4px 4px 0 0;
  background-color: #8FB6F5;
  transform-origin: bottom;
  animation: lfx-att-bar 10s var(--ease-smooth) infinite;
  animation-delay: calc(var(--i) * 140ms);
}

.lfx-att__bars li:nth-child(2) i { background-color: #5D95F0; }

.lfx-att__bars img {
  width: 17px; height: 17px;
  margin-top: 5px;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 0 0 1.5px #FFFFFF, 0 0 0 2.5px #E4EBF7;
}

@keyframes lfx-att-bar {
  0%, 16%   { transform: scaleY(0); }
  34%, 88%  { transform: scaleY(1); }
  100%      { transform: scaleY(0); }
}

.lfx-att__stat {
  position: absolute;
  top: 4%; left: 2%;
  margin: 0;
  padding: 7px 11px;
  border-radius: 11px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #E9EFFA, 0 10px 22px -16px rgba(21, 82, 199, 0.75);
}

.lfx-att__stat strong {
  display: block;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px; font-weight: 700; line-height: 1.1;
  letter-spacing: -0.4px; color: #7C93B8;
}

.lfx-att__stat em {
  display: block;
  margin-top: 1px;
  font-size: 8.5px; font-style: normal; font-weight: 700; color: #2B3140;
}

.lfx-att__shift {
  position: absolute;
  right: 8%; bottom: 2%; left: 4%;
  display: flex;
  gap: 5px;
  margin: 0;
  padding: 5px;
  border-radius: 100px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #E9EFFA, 0 12px 24px -18px rgba(21, 82, 199, 0.8);
  list-style: none;
}

.lfx-att__shift li {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 5px 4px;
  border-radius: 100px;
  font-size: 9.5px; font-weight: 600; white-space: nowrap; color: #7C879B;
}

.lfx-att__shift svg { flex: none; width: 11px; height: 11px; }

/* One of the two is the one being looked at, and it says so in a tint rather
   than by being the only one with an icon: both shifts are real, only one is
   selected. */
.lfx-att__shift .is-on { background-color: #EEF4FE; color: #1D6BF3; }

/* ==========================================================================
   05 · THE RUN BEING ASSEMBLED
   ========================================================================== */

.lfx-pay { padding: 0; }

.lfx-pay__card {
  position: absolute;
  top: 4%; right: 5%; bottom: 24%; left: 5%;
  display: flex;
  flex-direction: column;
  padding: 9px 10px;
  border-radius: 13px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #EDF2FA;
}

.lfx-pay__head {
  display: flex;
  align-items: baseline;
  gap: 5px;
  margin: 0 0 7px;
  padding-bottom: 7px;
  border-bottom: 1px solid #F1F5FC;
}

.lfx-pay__ppl { align-self: center; width: 13px; height: 13px; color: #2563EB; }
.lfx-pay__ppl svg { display: block; width: 100%; height: 100%; }

.lfx-pay__head strong {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15px; font-weight: 700; letter-spacing: -0.3px; color: #14161D;
}

.lfx-pay__head em {
  font-size: 8.5px; font-style: normal; font-weight: 600; color: #8A94A6;
}

.lfx-pay__row {
  display: flex;
  align-items: center;
  flex: 1;
  gap: 4px;
  animation: lfx-pay-row 10s var(--ease-soft) infinite;
  animation-delay: calc(var(--i) * 260ms);
}

@keyframes lfx-pay-row {
  0%, 10%   { opacity: 0; transform: translateY(6px); }
  22%, 88%  { opacity: 1; transform: none; }
  100%      { opacity: 0; transform: translateY(6px); }
}

.lfx-pay__what {
  flex: 1 1 38%;
  min-width: 0;
  font-size: 9px; font-weight: 700; line-height: 1.2; color: #2B3140;
}

.lfx-pay__val { flex: 0 0 25%; min-width: 0; }

.lfx-pay__val b {
  display: block;
  font-size: 9px; font-weight: 700; line-height: 1.2; color: #14161D;
}

.lfx-pay__val i {
  display: block;
  font-size: 7px; font-style: normal; font-weight: 600; color: #8A94A6;
}

/* The rows with no figures on them. Two rules at the weights the numbers above
   them would have: the darker one stands for the value, the paler for its
   caption, so the column reads as continuing rather than as empty. */
.lfx-pay__val--bare u,
.lfx-pay__val--bare s {
  display: block;
  height: 4px;
  border-radius: 100px;
  text-decoration: none;
}

.lfx-pay__val--bare u { width: 62%; background-color: #A9C9FA; }
.lfx-pay__val--bare s { width: 88%; margin-top: 3px; background-color: #E4EBF7; }

.lfx-pay__up { flex: none; width: 14px; height: 14px; color: #5D95F0; }
.lfx-pay__up svg { display: block; width: 100%; height: 100%; }

.lfx-pay__chip {
  position: absolute;
  bottom: 2%; left: 14%;
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 0;
  padding: 6px 9px;
  border-radius: 12px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #E9EFFA, 0 12px 24px -18px rgba(21, 82, 199, 0.8);
  animation: lfx-pay-chip 10s var(--ease-soft) infinite;
}

@keyframes lfx-pay-chip {
  0%, 46%   { opacity: 0; transform: translateY(8px); }
  56%, 88%  { opacity: 1; transform: none; }
  100%      { opacity: 0; transform: translateY(8px); }
}

/* Red, and the only red in the rail. Loss of pay is the one figure on this
   panel that is a deduction rather than a payment. */
.lfx-pay__cal {
  display: grid;
  place-items: center;
  width: 17px; height: 17px;
  border-radius: 5px;
  background-color: #FDEAEA;
  color: #E5484D;
}

.lfx-pay__cal svg { width: 11px; height: 11px; }

.lfx-pay__chip strong {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 13px; font-weight: 700; letter-spacing: -0.3px; color: #14161D;
}

.lfx-pay__chip em {
  font-size: 8.5px; font-style: normal; font-weight: 600; color: #8A94A6;
}

.lfx-pay__sync { width: 11px; height: 11px; margin-left: 2px; color: #A9B4C6; }
.lfx-pay__sync svg { display: block; width: 100%; height: 100%; }

/* ==========================================================================
   06 · THE TREND
   ========================================================================== */

.lfx-perf {
  display: flex;
  flex-direction: column;
  padding: 16px 18px 0;
}

.lfx-perf__stat {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 7px;
  margin: 0;
}

.lfx-perf__stat strong {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 26px; font-weight: 700; line-height: 1;
  letter-spacing: -0.8px; color: #14161D;
}

/* Green, and the only green on this panel: it is the one mark here that says
   which way the number is going, and a rise sharing its colour with the line
   under it would just be more blue. */
.lfx-perf__rise {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px 7px;
  border-radius: 100px;
  background-color: #E6F6EE;
  font-size: 9.5px; font-weight: 700; color: #12805C;
}

.lfx-perf__rise svg { width: 8px; height: 8px; }

.lfx-perf__stat em {
  flex: 1 0 100%;
  font-size: 9.5px; font-style: normal; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase; color: #8A94A6;
}

.lfx-perf__plot {
  position: relative;
  flex: 1;
  min-height: 0;
  margin: 10px -18px 0;
}

.lfx-perf__plot svg { display: block; width: 100%; height: 100%; }

.lfx-perf__area { fill: rgba(37, 99, 235, 0.10); }

/* preserveAspectRatio is none on the svg, so the viewBox stretches to the panel
   and the stroke would stretch with it. vector-effect keeps the line one weight
   whatever the box does to it. */
.lfx-perf__line {
  stroke: #2563EB;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: lfx-perf-draw 10s var(--ease-smooth) infinite;
}

@keyframes lfx-perf-draw {
  0%, 6%    { stroke-dashoffset: 100; }
  40%, 88%  { stroke-dashoffset: 0; }
  100%      { stroke-dashoffset: 100; }
}

/* Positioned in percentages off the same viewBox the path is drawn in —
   266/300 across and 16/110 down, the last point of the path — so the two
   cannot drift apart when the panel resizes. */
.lfx-perf__dot {
  position: absolute;
  top: 14.5%; left: 88.7%;
  width: 9px; height: 9px;
  border-radius: 50%;
  background-color: #FFFFFF;
  box-shadow: 0 0 0 2.5px #2563EB;
  transform: translate(-50%, -50%);
  animation: lfx-perf-dot 10s var(--ease-soft) infinite;
}

@keyframes lfx-perf-dot {
  0%, 36%   { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
  46%, 88%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  100%      { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
}

.lfx-perf__foot {
  position: absolute;
  top: 4px; right: 18px;
  font-size: 9px; font-weight: 600; color: #A9B4C6;
}

/* ==========================================================================
   07 · RECOGNITION

   Three things stacked: a post somebody wrote, the reactions it collects, and
   the board it puts people on. The reactions overlap the post's bottom edge,
   which is what makes them read as landing ON it rather than sitting under it.
   ========================================================================== */

.lfx-kudo {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 14px;
}

.lfx-kudo__post {
  width: 76%;
  padding: 9px;
  border-radius: 14px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #E9EFFA, 0 10px 22px -18px rgba(21, 82, 199, 0.7);
}

.lfx-kudo__who { display: flex; align-items: center; gap: 8px; }

.lfx-kudo__who img {
  flex: none;
  width: 24px; height: 24px;
  border-radius: 50%;
  object-fit: cover;
}

/* Two grey rules rather than a name and a line of copy. The post is the shape
   of a post, not a post anyone is meant to read. */
.lfx-kudo__lines { display: grid; gap: 5px; flex: 1; }

.lfx-kudo__lines i {
  display: block;
  height: 5px;
  border-radius: 100px;
  background-color: #E4EBF7;
}

.lfx-kudo__lines i:last-child { width: 58%; }

.lfx-kudo__shot {
  display: block;
  height: 34px;
  margin-top: 8px;
  border-radius: 9px;
  background-image: linear-gradient(160deg, #DCE9FF 0%, #EEF4FE 60%, #F6F9FF 100%);
}

.lfx-kudo__react {
  position: relative;
  z-index: 1;
  display: flex;
  gap: 5px;
  margin: -13px 0 0;
  padding: 0;
  list-style: none;
}

.lfx-kudo__react li {
  display: grid;
  place-items: center;
  width: 27px; height: 27px;
  border-radius: 50%;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #E9EFFA, 0 6px 14px -10px rgba(21, 82, 199, 0.8);
  font-size: 13px; line-height: 1;
  /* One after another, not all together: arriving in sequence is the part that
     says other people saw it. */
  animation: lfx-react 10s var(--ease-soft) infinite;
  animation-delay: calc(var(--i) * 420ms);
}

@keyframes lfx-react {
  0%, 8%    { opacity: 0; transform: translateY(8px) scale(0.6); }
  16%       { opacity: 1; transform: translateY(0) scale(1.18); }
  22%, 88%  { opacity: 1; transform: translateY(0) scale(1); }
  96%, 100% { opacity: 0; transform: translateY(8px) scale(0.6); }
}

.lfx-kudo__pod {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}

.lfx-kudo__spot {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.lfx-kudo__spot img {
  width: 32px; height: 32px;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 3px #DCE7F9;
}

.lfx-kudo__spot--win img {
  width: 38px; height: 38px;
  box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 3px #A9C9FA;
}

/* The rank rides on the avatar's top edge, half over it, which is where a badge
   goes: inside the circle it would be a hat and beside it a label. */
.lfx-kudo__star {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 19px; height: 19px;
  margin-bottom: -8px;
  color: #F0B429;
}

.lfx-kudo__star svg { position: absolute; inset: 0; width: 100%; height: 100%; }

.lfx-kudo__star b {
  position: relative;
  font-size: 9px; font-weight: 800; line-height: 1; color: #7A4E05;
}

/* scaleY from the foot, so it grows up out of the floor rather than sliding in
   from somewhere. */
.lfx-kudo__block {
  width: 40px;
  height: var(--h, 24px);
  margin-top: 7px;
  border-radius: 6px 6px 0 0;
  background-image: linear-gradient(180deg, #C9DDFB 0%, #E7EFFD 100%);
  transform-origin: bottom;
  animation: lfx-podium 10s var(--ease-smooth) infinite;
  animation-delay: calc(var(--i) * 160ms);
}

.lfx-kudo__spot--win .lfx-kudo__block {
  background-image: linear-gradient(180deg, #A9C9FA 0%, #DCE9FF 100%);
}

@keyframes lfx-podium {
  0%, 30%   { transform: scaleY(0); }
  46%, 88%  { transform: scaleY(1); }
  100%      { transform: scaleY(0); }
}

/* ==========================================================================
   08 · THE LAST FOUR THINGS

   The onboarding list's structure with a name on top and a bar underneath. It
   borrows .lfx-check__box and the lfx-tick keyframes rather than growing its own
   tick: it is the same mark doing the same job at the other end of the record.
   ========================================================================== */

.lfx-exit {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  padding: 16px 18px;
}

.lfx-exit__who {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 11.5px; font-weight: 700; color: #2B3140;
}

.lfx-exit__ava {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px; height: 22px;
  border-radius: 50%;
  background-color: #DCE3F0;
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.02em; color: #47506A;
}

.lfx-exit__day {
  margin-left: auto;
  padding: 4px 9px;
  border-radius: 100px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #E4E9F3;
  font-size: 10px; font-weight: 600; color: #5A6478;
}

.lfx-exit__list { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }

.lfx-exit__row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 11px;
  border-radius: 12px;
  background-color: #F8FAFD;
  box-shadow: inset 0 0 0 1px #E9EDF6;
  font-size: 11.5px; font-weight: 600; color: #2B3140;
}

/* Fills as the four rows close, on the same 9s loop and finishing just after
   the last tick lands. A progress bar that finished first would be describing a
   different list. */
.lfx-exit__bar {
  display: block;
  height: 5px;
  border-radius: 100px;
  background-color: #E4E9F3;
  overflow: hidden;
}

.lfx-exit__bar b {
  display: block;
  width: 0;
  height: 100%;
  border-radius: inherit;
  background-color: #22A06B;
  animation: lfx-exit-fill 9s var(--ease-soft) infinite;
}

@keyframes lfx-exit-fill {
  0%, 14%   { width: 0; }
  30%       { width: 25%; }
  46%       { width: 50%; }
  62%       { width: 75%; }
  78%, 88%  { width: 100%; }
  96%, 100% { width: 0; }
}

/* ==========================================================================
   PHONES — one column

   The pin, the travel and the horizontal scroll are all off by now: the
   section carries data-rail-stack, and "PHONES — a rail that stops being a
   rail" up by .hs-rail has already put it back in ordinary flow. Left here is
   what the row becomes once it is free of the rail — eight steps, one under
   the other, full width. A rail that shows three cards at a time shows two
   thirds of one on a phone, and the pan then spends a screen-height of scroll
   on each card to say what a column gives away at a glance.

   These sit down here rather than in the padding block above because a media
   query adds no specificity: .lfx .hs-rail__stage and .lfx-card are both
   matched again further up the file, and the last rule of equal weight wins.
   ========================================================================== */

@media (max-width: 767px) {
  .lfx .hs-rail__stage {
    gap: 24px;
  }

  .lfx-row {
    flex-direction: column;
    width: auto;
    gap: 16px;
    padding-bottom: 0;
  }

  /* Full bleed to the row's own 20px gutter, rather than the 280px a card is
     given when three of them have to share a viewport. */
  .lfx-card {
    width: 100%;
  }
}

/* ==========================================================================
   REDUCED MOTION

   The rail stops and every loop settles on its finished frame: the query is
   fully typed, the meters and rings are full, the checklist is ticked, the
   payslip is stamped and the note is on screen. The section still says
   everything it says; it just stops moving.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .lfx-card,
  .lfx-card__arrow,
  .lfx-src__caret,
  .lfx-src__pill,
  .lfx-src__hit,
  .lfx-pipe__dot,
  .lfx-pipe__card,
  .lfx-check__box,
  .lfx-att__bars i,
  .lfx-pay__row,
  .lfx-pay__chip,
  .lfx-kudo__react li,
  .lfx-kudo__block {
    animation: none;
    transition: none;
  }

  .lfx-src__typed {
    animation: none;
    width: 100%;
  }

  .lfx-src__caret {
    opacity: 0;
  }

  .lfx-src__fill {
    animation: none;
    transform: none;
  }

  /* The bars stand at full height rather than freezing part-grown: the plot
     still says who worked what, it just stops filling. */
  .lfx-att__bars i {
    animation: none;
    transform: scaleY(1);
  }

  /* The line stands drawn and the head sits at the end of it. */
  .lfx-perf__line {
    animation: none;
    stroke-dashoffset: 0;
  }

  .lfx-perf__dot {
    animation: none;
    opacity: 1;
    transform: translate(-50%, -50%);
  }

  .lfx-check__box {
    background-color: #22A06B;
    color: #FFFFFF;
    box-shadow: none;
  }

  /* The reactions settle on screen rather than mid-pop, and the blocks stand
     at their full height: the board still says who won, it just stops
     arriving. */
  .lfx-kudo__react li {
    opacity: 1;
    transform: none;
  }

  .lfx-kudo__block {
    transform: scaleY(1);
  }
}

/* ==========================================================================
   RECRUITER PERFORMANCE DASHBOARD — includes/recruiter-perf-ui.php

   Showcase panel 06. Markup rather than a screenshot, for the reasons the
   sourcing panel gives: it stays sharp at any density, recolours with the
   page, and starts without a network request.

   EVERY SIZE IS IN cqw
   The container is the query container, so one set of numbers holds at the
   560px showcase frame and at any other width the panel is ever given. Nothing
   here needs a breakpoint.

   The box is 1272 x 1137 — the ratio every showcase artwork is authored at, so
   the frame never resizes between steps.
   ========================================================================== */

.rpf {
  aspect-ratio: 1272 / 1137;
  background: linear-gradient(168deg, #E7ECF8 0%, #DFE6F4 46%, #E9EDF7 100%);
}

/* The app itself, inset from the artwork's ground so it reads as a window onto
   a product rather than as the product printed to the edge of the tile. */

.rpf__chrome {
  position: absolute;
  inset: 3.4%;
  display: flex;
  overflow: hidden;
  border-radius: 2.6cqw;
  background-color: #FFFFFF;
  box-shadow: 0 2.4cqw 5cqw -2.6cqw rgba(20, 30, 60, 0.34);
}

/* ---- the content ---- */

.rpf__main {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  gap: 2cqw;
  padding: 2.2cqw 2.6cqw 2.6cqw;
}

/* ---- the three figures ---- */

.rpf__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.8cqw;
}

.rpf__stat {
  display: flex;
  align-items: center;
  gap: 1.4cqw;
  padding: 1.5cqw 1.6cqw;
  border-radius: 1.6cqw;
  box-shadow: inset 0 0 0 1px #E9EEF7;
}

.rpf__statico {
  display: grid;
  place-items: center;
  flex: none;
  width: 4.6cqw;
  height: 4.6cqw;
  border-radius: 1.4cqw;
}

.rpf__statico svg {
  width: 2.4cqw;
  height: 2.4cqw;
}

.rpf__statico--violet { background-color: #EEEBFD; color: #5B4BD6; }
.rpf__statico--sky    { background-color: #E4F1FC; color: #2F86C8; }
.rpf__statico--mint   { background-color: #E4F5EC; color: #23976A; }

.rpf__statbody {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 0.2cqw;
}

.rpf__statbody b {
  font-size: 3.4cqw;
  font-weight: 700;
  letter-spacing: -0.04cqw;
  color: #171B26;
  font-variant-numeric: tabular-nums;
}

.rpf__statbody em {
  font-size: 1.9cqw;
  font-style: normal;
  font-weight: 500;
  color: #7C879B;
}

/* ---- the three panels under them ---- */

.rpf__body {
  display: grid;
  /* The funnel column is the widest of the three: it carries four labels of
     real words where the chart carries three short ones and the team column
     carries names. Sized by what has to fit, not split evenly. */
  grid-template-columns: 1fr 1.06fr 1.06fr;
  flex: 1;
  min-height: 0;
  gap: 2cqw;
}

.rpf__card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 2.2cqw;
  border-radius: 1.8cqw;
  box-shadow: inset 0 0 0 1px #E9EEF7;
}

.rpf__cardtitle {
  font-size: 2.3cqw;
  font-weight: 700;
  color: #171B26;
}

/* ---- 1 · the funnel ---- */

.rpf__funnel {
  display: flex;
  align-items: flex-start;
  gap: 1.2cqw;
}

/* The cone. Four bars whose widths ARE the four figures beside them, centred
   on each other so the taper reads as one shape rather than four rules. */

.rpf__cone {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: none;
  gap: 0.5cqw;
  width: 27%;
  padding-top: 0.4cqw;
}

.rpf__cone i {
  display: block;
  width: var(--w);
  height: 1.9cqw;
  border-radius: 0.5cqw;
  background-image: linear-gradient(100deg, #7C5CFC, #5B4BD6);
  transform: scaleX(0);
  transition: transform 760ms var(--ease-smooth);
  transition-delay: var(--d, 0ms);
}

.rpf__cone i:first-child { height: 3.4cqw; }

.is-showing .rpf__cone i,
.is-active .rpf__cone i {
  transform: scaleX(1);
}

.rpf__legend {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  gap: 1.8cqw;
  margin: 0;
  padding: 0;
  list-style: none;
}

.rpf__legend li {
  display: flex;
  align-items: baseline;
  gap: 0.9cqw;
}

.rpf__legend b {
  flex: none;
  min-width: 2.4cqw;
  font-size: 2.4cqw;
  font-weight: 700;
  color: #5B4BD6;
  font-variant-numeric: tabular-nums;
}

.rpf__legend span {
  font-size: 1.85cqw;
  font-weight: 500;
  line-height: 1.25;
  white-space: nowrap;
  color: #66718A;
}

/* The card inside the card. It sits on white where its parent is outlined, so
   it lifts rather than nests. */

.rpf__promo {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: auto;
  padding: 1.8cqw 1.4cqw;
  border-radius: 1.6cqw;
  background-color: #FFFFFF;
  box-shadow: 0 1.4cqw 3cqw -1.6cqw rgba(91, 75, 214, 0.45), inset 0 0 0 1px #EDE9FC;
  text-align: center;
}

.rpf__promoico {
  display: grid;
  place-items: center;
  width: 5.4cqw;
  height: 5.4cqw;
  border-radius: 50%;
  background-image: linear-gradient(150deg, #8B72FF, #5B4BD6);
  color: #FFFFFF;
  box-shadow: 0 1cqw 2cqw -0.8cqw rgba(91, 75, 214, 0.7);
}

.rpf__promoico svg {
  width: 2.8cqw;
  height: 2.8cqw;
}

.rpf__promotitle {
  margin-top: 1cqw;
  font-size: 2.3cqw;
  font-weight: 700;
  color: #171B26;
}

.rpf__promotext {
  margin-top: 0.5cqw;
  font-size: 1.75cqw;
  font-weight: 500;
  line-height: 1.4;
  color: #7C879B;
}

/* ---- 2 · openings by client ---- */

.rpf__chart {
  display: flex;
  flex: 1;
  min-height: 0;
  gap: 1.2cqw;
}

/* The axis is a flex column with the ticks spread across it, so the labels sit
   at the heights the bars are measured against rather than at heights chosen
   to look about right. */

.rpf__axis {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  flex: none;
  margin: 0;
  padding: 0 0 2.6cqw;
  list-style: none;
  font-size: 1.75cqw;
  font-weight: 500;
  color: #A8B2C6;
  font-variant-numeric: tabular-nums;
}

.rpf__plot {
  display: flex;
  align-items: flex-end;
  justify-content: space-around;
  flex: 1;
  min-width: 0;
  gap: 1.2cqw;
}

.rpf__barcol {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  min-width: 0;
  height: 100%;
  justify-content: flex-end;
  gap: 0.8cqw;
}

.rpf__bar {
  width: 100%;
  max-width: 7.4cqw;
  height: var(--h);
  border-radius: 0.6cqw 0.6cqw 0 0;
  transform: scaleY(0);
  transform-origin: bottom center;
  transition: transform 820ms var(--ease-smooth);
  transition-delay: var(--d, 0ms);
}

.is-showing .rpf__bar,
.is-active .rpf__bar {
  transform: scaleY(1);
}

.rpf__bar--mint  { background-color: #4ECB8C; }
.rpf__bar--amber { background-color: #F5CE4A; }
.rpf__bar--teal  { background-color: #4CCBBE; }

.rpf__barcol em {
  font-size: 1.75cqw;
  font-style: normal;
  font-weight: 500;
  color: #66718A;
}

.rpf__key {
  display: flex;
  align-items: center;
  gap: 0.8cqw;
  margin-top: 1.2cqw;
  font-size: 1.85cqw;
  font-weight: 500;
  color: #66718A;
}

.rpf__key i {
  width: 1.5cqw;
  height: 1.5cqw;
  border-radius: 50%;
  background-color: #4ECB8C;
}

/* ---- 3 · the team ---- */

.rpf__thead {
  display: flex;
  justify-content: space-between;
  margin-top: 1.6cqw;
  padding-bottom: 0.9cqw;
  border-bottom: 1px solid #EDF1F8;
  font-size: 1.6cqw;
  font-weight: 700;
  letter-spacing: 0.12cqw;
  color: #8A93A6;
}

.rpf__team {
  display: flex;
  flex-direction: column;
  gap: 1.4cqw;
  margin: 1.4cqw 0 0;
  padding: 0;
  list-style: none;
}

.rpf__who {
  display: block;
  margin-bottom: 0.7cqw;
  font-size: 2cqw;
  font-weight: 500;
  color: #4A5468;
}

/* Dark track, coloured fill: the score is how far along a fixed bar it gets,
   so the bar has to be visible where the score has not reached. */

.rpf__score {
  display: block;
  overflow: hidden;
  height: 0.9cqw;
  border-radius: 100px;
  background-color: #1B2130;
}

.rpf__score i {
  display: block;
  width: var(--w);
  height: 100%;
  border-radius: inherit;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 760ms var(--ease-smooth);
  transition-delay: var(--d, 0ms);
}

.is-showing .rpf__score i,
.is-active .rpf__score i {
  transform: scaleX(1);
}

.rpf__score--violet { background-color: #5B4BD6; }
.rpf__score--sky    { background-color: #43B6F0; }
.rpf__score--mint   { background-color: #4ECB8C; }

/* It overhangs its own card so it reads as lifted off the dashboard rather
   than filed into it — but only into the gutter beside it, never across the
   chart. Earlier versions reached far enough left to cover the third bar and
   clip its label, which is the picture saying the floating card matters more
   than the data underneath it. */

.rpf__float {
  position: absolute;
  right: -0.6cqw;
  bottom: -0.8cqw;
  left: -1.6cqw;
  padding: 2cqw;
  border-radius: 1.8cqw;
  background-color: #FFFFFF;
  box-shadow: 0 2.4cqw 4.4cqw -1.8cqw rgba(20, 30, 60, 0.4), inset 0 0 0 1px #EEF1F8;
}

.rpf__floattitle {
  font-size: 2.2cqw;
  font-weight: 700;
  line-height: 1.2;
  color: #171B26;
}

.rpf__floattext {
  margin-top: 0.7cqw;
  font-size: 1.85cqw;
  font-weight: 500;
  line-height: 1.4;
  color: #7C879B;
}

.rpf__floatrow {
  display: flex;
  gap: 1.1cqw;
  margin-top: 1.4cqw;
}

.rpf__floatrow i {
  display: grid;
  place-items: center;
  width: 4.6cqw;
  height: 4.6cqw;
  border-radius: 50%;
  background-color: #EFEBFD;
  color: #5B4BD6;
  transform: scale(0.7);
  opacity: 0;
  transition: transform 520ms var(--ease-smooth), opacity 520ms var(--ease-smooth);
  transition-delay: var(--d, 0ms);
}

.rpf__floatrow i svg {
  width: 2.3cqw;
  height: 2.3cqw;
}

.is-showing .rpf__floatrow i,
.is-active .rpf__floatrow i {
  transform: none;
  opacity: 1;
}

.rpf__brand {
  position: absolute;
  right: 2.2cqw;
  bottom: 1cqw;
  font-size: 2cqw;
  font-weight: 700;
  color: #171B26;
}

/* Nothing here carries meaning the panel's own heading does not, so under
   reduced motion every part simply starts finished. */

@media (prefers-reduced-motion: reduce) {
  .rpf__cone i,
  .rpf__score i {
    transform: scaleX(1);
    transition: none;
  }

  .rpf__bar {
    transform: scaleY(1);
    transition: none;
  }

  .rpf__floatrow i {
    transform: none;
    opacity: 1;
    transition: none;
  }
}

/* ==========================================================================
   ALTERNATIVES PAGES — /alternatives/<vendor>-alternatives/
   --------------------------------------------------------------------------
   Hand-authored, like the HRMS block above and for the same reason: there is
   no build step in this repo and css/style.css is committed as generated
   output, so a Tailwind utility not already used somewhere on the site would
   be absent from the file and would silently do nothing.

   Namespaced alt-, and named for the series rather than for GreytHR: the live
   site carries five of these pages and they are one page with five subjects.
   Nothing below mentions a vendor.

   The only classes borrowed from elsewhere are ones the site already renders:
   .badge, .btn-*, .section, .section-title, .section-lead, .hs-head,
   .hs-hero__sky, .hs-scenic, .hs-cta, .hs-i, .faq-item, .reveal.

   ONE LEVEL SCALE, USED IN THREE PLACES
   The capability read is 0 none, 1 limited, 2 good, 3 full. It colours the
   bars in the seven panels and the dots in the comparison table, and the two
   are set from the same four values below so a panel and its table row cannot
   come out saying different things. Nothing is ever carried by the colour
   alone: every bar and every dot has the word printed beside it.
   ========================================================================== */

:root {
  --alt-lv0: #C3CCD9;
  --alt-lv1: #F59E0B;
  --alt-lv2: #2563EB;
  --alt-lv3: #10B981;
}

/* ------------------------------------------------------------------
   Hero — centred, no artwork
   ------------------------------------------------------------------ */

/* The hero is the shared two-column one (.hs-hero__grid), so this page adds
   only what that block has no opinion about: the trail above the badge, and
   two measures widened for this page's longer copy. */

/* The shared 56px, as asked for. These headings are long sentences rather than
   the three or four words a product page opens on, so at this size five of the
   eight fall into three lines inside the copy column instead of two: GreytHR,
   HROne, BambooHR, Zoho People and Zoho Recruit. Keka, Workday and HireVue
   stay at two.

   text-wrap: balance is what keeps a three-line heading from ending on an
   orphan, so it stays. The floor is the shared 34px and the ramp is the shared
   5.4vw, so a narrow screen behaves exactly as every other hero does. */
.alt-hero .hs-hero__title {
  font-size: clamp(34px, 5.4vw, 56px);
  line-height: 1.1;
  text-wrap: balance;
}

/* This lead runs to a paragraph rather than the sentence the product pages
   open with, so it gets more measure than the shared 520px and the grid gives
   the copy column the larger half. Between them the copy and the artwork come
   out close to the same height, which is the only reason either number is not
   the shared one. */
.alt-hero .hs-hero__lead { max-width: 560px; }

@media (min-width: 1024px) {
  .alt-hero .hs-hero__grid {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  }
}

/* The trail above the badge. Slashes are drawn rather than typed so they are
   not read out as content, and the whole rail sits at the small size because
   it is orientation, not copy. */
.alt-crumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 13px;
  font-weight: 500;
  color: #1D1D1D;
}

.alt-crumbs li {
  display: flex;
  align-items: center;
  gap: 8px;
}

.alt-crumbs li + li::before {
  content: '';
  width: 1px;
  height: 11px;
  background-color: #C3CCD9;
  transform: rotate(18deg);
}

/* Black rather than the grey this ran at. The links and the current page are
   now the same colour, so "you are here" is no longer carried by weight of
   ink; the hover below is what still tells a link from the page you are on. */

.alt-crumbs a {
  color: #1D1D1D;
  text-decoration: none;
  transition: color 240ms var(--ease-soft);
}

.alt-crumbs a:hover { color: #2563EB; }

.alt-crumbs [aria-current] { color: #1D1D1D; }

/* The badge sits under the trail, not beside it. 18px is enough that the two
   read as separate rows rather than as one wrapped line. */
.alt-crumbs { margin-bottom: 18px; }

/* ------------------------------------------------------------------
   Why people leave — the page's one inverted band
   ------------------------------------------------------------------ */

.alt-neg-sec {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-top: 78px;
  padding-bottom: 78px;
  background-color: #0B0D12;
}

@media (min-width: 768px) {
  .alt-neg-sec {
    padding-top: 106px;
    padding-bottom: 106px;
  }
}

/* Two faint washes so the ground is not a flat rectangle of black. Both are
   brand hues at very low alpha: the band is inverted, not a different site. */
.alt-neg-sec::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(60% 46% at 50% 0%, rgba(37, 99, 235, 0.20), rgba(37, 99, 235, 0) 68%),
    radial-gradient(46% 40% at 88% 100%, rgba(139, 92, 246, 0.16), rgba(139, 92, 246, 0) 66%);
  pointer-events: none;
}

.alt-neg__head {
  margin-left: auto;
  margin-right: auto;
  max-width: 820px;
  text-align: center;
}

.alt-neg__title { color: #FFFFFF; }

.alt-neg__lead {
  margin-top: 18px;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.66);
}

@media (min-width: 768px) {
  .alt-neg__lead { font-size: 16px; }
}

.alt-neg__lead--sub {
  margin-top: 12px;
  color: rgba(255, 255, 255, 0.5);
}

.alt-neg__grid {
  display: grid;
  gap: 18px;
  margin-top: 46px;
}

@media (min-width: 700px) {
  .alt-neg__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .alt-neg__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 20px;
  }
}

/* Not .card. That component is a white panel with a pale border and neither
   survives being dropped on near-black; this is the same geometry drawn in the
   inverted palette. */
.alt-neg__card {
  padding: 26px 24px 28px;
  border-radius: 20px;
  border: 1px solid rgba(255, 255, 255, 0.09);
  background-color: rgba(255, 255, 255, 0.04);
  transition:
    transform 380ms var(--ease-smooth),
    border-color 380ms var(--ease-soft),
    background-color 380ms var(--ease-soft);
}

.alt-neg__card:hover {
  transform: translate3d(0, -4px, 0);
  border-color: rgba(255, 255, 255, 0.18);
  background-color: rgba(255, 255, 255, 0.07);
}

.alt-neg__icon {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  margin-bottom: 18px;
  border-radius: 13px;
  background-color: rgba(255, 255, 255, 0.09);
  color: #FFFFFF;
}

.alt-neg__icon .hs-i { width: 21px; height: 21px; }

.alt-neg__name {
  margin-bottom: 9px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.25;
  color: #FFFFFF;
}

.alt-neg__text {
  font-size: 14px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.62);
}

/* ------------------------------------------------------------------
   The buying framework — eight tinted cards
   ------------------------------------------------------------------ */

.alt-crit {
  margin-top: 48px;
}

/* Room for the arrows to sit over the ends of the rail, and for a card's
   hover lift and shadow to show rather than being clipped by the marquee's
   own overflow: hidden. */
.alt-crit__rail {
  padding: 10px 0 24px;
  --cards: 1.15;
}

@media (min-width: 640px)  { .alt-crit__rail { --cards: 2; } }
@media (min-width: 900px)  { .alt-crit__rail { --cards: 3; } }
@media (min-width: 1200px) { .alt-crit__rail { --cards: 4; } }

/* The same width formula the feature rails use: the content measure, less the
   gaps between the cards on screen, divided by how many are meant to show. A
   fraction at the small end so the next card is visibly cut off, which is what
   says "this scrolls" without an instruction. */
.alt-crit__rail .alt-crit__card {
  flex: 0 0 auto;
  width: calc(
    (min(1200px, 100vw - 40px) - (var(--cards) - 1) * var(--gap, 20px)) / var(--cards)
  );
  /* A floor, not a height: the group is a flex row, so every card takes the
     height of the tallest and they still match — they simply match at
     whatever the longest criterion needs. */
  min-height: 250px;
}

/* The tint fades out downward, so the card ends on white and the text at the
   foot of a long one is never sitting on colour. */
.alt-crit__card {
  position: relative;
  overflow: hidden;
  padding: 26px 22px 28px;
  border-radius: 20px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #FFFFFF;
  transition: transform 380ms var(--ease-smooth), box-shadow 380ms var(--ease-soft);
}

.alt-crit__card:hover {
  transform: translate3d(0, -4px, 0);
  box-shadow: 0 18px 40px -22px rgba(16, 24, 48, 0.28);
}

.alt-crit__card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(180deg, var(--alt-tint) 0%, rgba(255, 255, 255, 0) 62%);
  pointer-events: none;
}

.alt-crit__card > * { position: relative; z-index: 1; }

.alt-crit__card--blue   { --alt-tint: rgba(37, 99, 235, 0.10);  --alt-key: #2563EB; }
.alt-crit__card--violet { --alt-tint: rgba(139, 92, 246, 0.11); --alt-key: #7C3AED; }
.alt-crit__card--mint   { --alt-tint: rgba(16, 185, 129, 0.11); --alt-key: #0E9F6E; }
.alt-crit__card--amber  { --alt-tint: rgba(245, 158, 11, 0.13); --alt-key: #B45309; }

.alt-crit__icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: 16px;
  border-radius: 12px;
  background-color: #FFFFFF;
  border: 1px solid rgba(16, 24, 48, 0.07);
  color: var(--alt-key);
}

.alt-crit__icon .hs-i { width: 20px; height: 20px; }

.alt-crit__name {
  /* Block, because the marquee's second group sets this as a <span>: see the
     note in sections/alternatives/criteria.php. An inline clone would sit on
     the same line as the copy under it. */
  display: block;
  margin-bottom: 8px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.25;
  color: #1D1D1D;
}

.alt-crit__text {
  font-size: 14px;
  line-height: 1.6;
  color: #4D585F;
}

/* ------------------------------------------------------------------
   The seven entries
   ------------------------------------------------------------------ */

/* The section carries its own ground rather than taking .section's white. A
   cyan wash at the head and a mint one low on the right, both fading out well
   before the foot, so the run of seven reads as one long passage with an edge
   at the top and dissolves into the white the table starts on. */
.alt-list-sec {
  position: relative;
  isolation: isolate;
  padding-top: 70px;
  padding-bottom: 70px;
  background:
    radial-gradient(120% 52% at 50% 0%, rgba(56, 189, 248, 0.26), rgba(56, 189, 248, 0) 64%),
    radial-gradient(48% 26% at 96% 62%, rgba(16, 185, 129, 0.13), rgba(16, 185, 129, 0) 70%),
    linear-gradient(180deg, #E3F5FB 0%, #F1FAFD 22%, #FFFFFF 46%, #FFFFFF 100%);
}

@media (min-width: 768px) {
  .alt-list-sec {
    padding-top: 100px;
    padding-bottom: 100px;
  }
}

.alt-list__head {
  margin: 0 auto 52px;
  max-width: 900px;
  text-align: center;
}

@media (min-width: 768px) {
  .alt-list__head { margin-bottom: 68px; }
}

.alt-items {
  display: grid;
  gap: 72px;
}

@media (min-width: 768px) {
  .alt-items { gap: 110px; }
}

/* No card around an entry. Seven boxed slabs down a page turn a long read
   into a filing cabinet; the whitespace between them is the separation, and
   the two verdict columns are the only bounded thing inside. */
.alt-item__top {
  display: grid;
  gap: 34px;
  align-items: start;
}

@media (min-width: 1024px) {
  .alt-item__top {
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
    gap: 66px;
  }
}

/* ------------------------------------------------------------------
   The artwork and the plate behind it
   ------------------------------------------------------------------ */

.alt-item__art {
  position: relative;
  z-index: 0;
}

/* The published screenshot, placed bare. It arrives on a transparent ground
   with the violet slab, the offset and the drop shadow already drawn into it,
   so a frame, a border or a shadow added here would be a second copy of all
   three sitting a few pixels off the first. */
.alt-item__shot {
  display: block;
  width: 100%;
  height: auto;
  /* Never square. A photograph or screenshot with hard corners reads as
     unstyled beside this site's cards, panels and pills, which are all
     rounded. */
  border-radius: 10px;
}

/* Drawn only for the two vendors with no published screenshot, so their
   scorecard sits in the same shape as the five images either side of it: a
   tinted slab up and to the left, a band of it showing past two edges, its
   bottom stopping short so the overlap reads as depth rather than as a
   misaligned border. */
.alt-item__plate {
  position: absolute;
  inset: 0 10% 46px 0;
  z-index: -1;
  border-radius: 28px;
  background: linear-gradient(158deg, #E1E9F6 0%, #EFF3FA 100%);
}

.alt-item__art .alt-score {
  position: relative;
  z-index: 1;
  margin: 26px 0 0 26px;
}

@media (min-width: 640px) {
  .alt-item__art .alt-score {
    margin: 46px 0 0 46px;
  }
}

/* ------------------------------------------------------------------
   Rank, heading and the opening paragraph
   ------------------------------------------------------------------ */

.alt-item__title {
  display: flex;
  align-items: flex-start;
  gap: 16px;
}

@media (min-width: 768px) {
  .alt-item__title { gap: 24px; }
}

/* Set large, in the same ink as the heading beside it. It reads as part of the
   title rather than as a watermark behind it, which is what the rank is: the
   page is a ranking, and the position is half of what each heading says. Still
   hidden from screen readers in the markup — the order is already carried by
   the list itself and by the ItemList in the page's schema, so reading "zero
   one" before every heading would only add noise. */
.alt-item__num {
  flex: none;
  margin-top: -0.12em;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 54px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -2px;
  color: #1D1D1D;
}

@media (min-width: 768px) {
  .alt-item__num { font-size: 76px; letter-spacing: -3px; }
}

@media (min-width: 1280px) {
  .alt-item__num { font-size: 92px; }
}

.alt-item__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 24px;
  font-weight: 500;
  line-height: 1.28;
  letter-spacing: -0.4px;
  color: #1D1D1D;
}

@media (min-width: 768px) {
  .alt-item__name { font-size: 30px; }
}

@media (min-width: 1280px) {
  .alt-item__name { font-size: 34px; }
}

/* The separator is set in the muted grey so the product name and the verdict
   read as two things rather than one long title. */
.alt-item__dash { color: #9AA5B4; }

.alt-item__lede {
  margin-top: 22px;
  font-size: 16px;
  line-height: 1.65;
  color: #3C4550;
}

@media (min-width: 768px) {
  .alt-item__lede { font-size: 18px; }
}

/* The paragraphs after the first, at full width. A second column of body copy
   beside a picture that has already ended is a column of white space. */
.alt-item__prose {
  margin-top: 34px;
}

.alt-item__prose p {
  font-size: 16px;
  line-height: 1.65;
  color: #3C4550;
}

@media (min-width: 768px) {
  .alt-item__prose p { font-size: 18px; }
}

.alt-item__prose p + p { margin-top: 18px; }

/* ------------------------------------------------------------------
   The capability panel — the table row for one vendor, drawn
   ------------------------------------------------------------------ */

.alt-score {
  padding: 22px 20px 24px;
  border-radius: 18px;
  border: 1px solid rgba(16, 24, 48, 0.1);
  background-color: #FFFFFF;
  box-shadow: 0 24px 50px -32px rgba(16, 24, 48, 0.36);
}

.alt-score__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding-bottom: 16px;
  margin-bottom: 6px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.08);
}

.alt-score__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 600;
  color: #1D1D1D;
}

.alt-score__cap {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: #8A94A3;
}

.alt-score__rows { margin: 0; }

.alt-score__row {
  display: grid;
  gap: 4px;
  padding: 12px 0;
}

.alt-score__row + .alt-score__row {
  border-top: 1px solid rgba(16, 24, 48, 0.06);
}

@media (min-width: 420px) {
  .alt-score__row {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 14px;
  }
}

.alt-score__label {
  font-size: 13px;
  font-weight: 500;
  line-height: 1.35;
  color: #4D585F;
}

.alt-score__val {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
}

/* Four steps, three of them drawn: an empty track is level 0, and a bar with
   no segments lit is how "none" reads without needing a fourth shape. */
.alt-score__bar {
  display: inline-flex;
  flex: none;
  gap: 3px;
}

.alt-score__bar i {
  display: block;
  width: 14px;
  height: 6px;
  border-radius: 3px;
  background-color: #E7ECF3;
}

.alt-score__bar--1 i:nth-child(1) { background-color: var(--alt-lv1); }
.alt-score__bar--2 i:nth-child(-n+2) { background-color: var(--alt-lv2); }
.alt-score__bar--3 i { background-color: var(--alt-lv3); }

.alt-score__word {
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.3;
  color: #1D1D1D;
}

/* ------------------------------------------------------------------
   The verdict — Pros one side, Cons and the two panels the other
   ------------------------------------------------------------------ */

.alt-vd {
  display: grid;
  gap: 26px;
  margin-top: 34px;
  align-items: start;
}

@media (min-width: 900px) {
  .alt-vd {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 30px;
  }
}

@media (min-width: 768px) {
  .alt-vd { margin-top: 42px; }
}

.alt-i {
  width: 22px;
  height: 22px;
}

/* A banner, not a label. The two lists are long enough that the reader needs
   to be able to find which side they are on from anywhere down the column,
   and a tinted bar the full width of the column does that where a small
   heading over the first card does not. */
.alt-vd__head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
  padding: 13px 22px;
  border-radius: 14px;
  border: 1.5px solid;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.2;
}

@media (min-width: 768px) {
  .alt-vd__head { font-size: 20px; }
}

.alt-vd__dot {
  width: 9px;
  height: 9px;
  flex: none;
  border-radius: 50%;
  background-color: currentColor;
}

.alt-vd__head--pro {
  border-color: #B4E5C7;
  background-color: #F0FBF4;
  color: #1F9D55;
}

.alt-vd__head--con {
  border-color: #F5DFA6;
  background-color: #FFFAEF;
  color: #E8890C;
}

.alt-vd__list {
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.alt-vd__row {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 11px 16px;
  border-radius: 13px;
  border: 1px solid rgba(16, 24, 48, 0.06);
  background-color: #FFFFFF;
  box-shadow: 0 10px 26px -20px rgba(16, 24, 48, 0.26);
}

/* A disc, not a tick. The column's banner has already said which list this is,
   so the mark only has to carry the sentiment, and a thumb reads as an opinion
   where a tick reads as a fact being confirmed. */
.alt-vd__mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
}

/* The disc came down with the row, so the thumb inside comes down with it.
   .alt-i is 22px, which filled the old 44px disc and would crowd a 34px one. */
.alt-vd__mark .alt-i { width: 17px; height: 17px; }

.alt-vd__mark--pro { background-color: #D8F6E4; color: #16A34A; }
.alt-vd__mark--con { background-color: #FEE2E2; color: #EF4444; }

.alt-vd__text {
  font-size: 14.5px;
  line-height: 1.45;
  color: #1D1D1D;
}

@media (min-width: 768px) {
  .alt-vd__text { font-size: 15.5px; }
}

/* ------------------------------------------------------------------
   Fit and price — one statement each, so a panel rather than a list row
   ------------------------------------------------------------------ */

.alt-panel {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-top: 14px;
  padding: 22px 22px 24px;
  border-radius: 15px;
  background-color: #EFEBFE;
}

.alt-panel__mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 13px;
  background-color: #FFFFFF;
  color: #5B4BE8;
}

.alt-panel__head {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.25;
  color: #5B4BE8;
}

@media (min-width: 768px) {
  .alt-panel__head { font-size: 20px; }
}

.alt-panel__text {
  margin-top: 7px;
  font-size: 15px;
  line-height: 1.55;
  color: #3C4550;
}

@media (min-width: 768px) {
  .alt-panel__text { font-size: 17px; }
}

/* ------------------------------------------------------------------
   The comparison matrix
   ------------------------------------------------------------------ */

.alt-tbl-wrap {
  margin-top: 46px;
  overflow: hidden;
  border-radius: 20px;
  border: 1px solid rgba(16, 24, 48, 0.09);
  background-color: #FFFFFF;
  box-shadow: 0 24px 60px -40px rgba(16, 24, 48, 0.4);
}

/* Ten columns will not fit any phone, so the table scrolls inside this rather
   than restacking into eight cards — see the note at the head of the section
   file. tabindex makes the scroller reachable from the keyboard, which is the
   half of "it scrolls" that is easy to forget. */
.alt-tbl-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.alt-tbl-scroll:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: -2px;
}

/* min-width is what forces the sideways scroll, so it is set to the narrowest
   the columns stay readable at rather than to a round number. table-layout is
   fixed, and the widths come from $ALT_TABLE['widths'] as inline <col style>
   because the column count differs per page. */
.alt-tbl {
  width: 100%;
  min-width: 860px;
  table-layout: fixed;
  border-collapse: collapse;
  text-align: left;
}

.alt-tbl--tight { min-width: 1000px; }

.alt-tbl th,
.alt-tbl td {
  padding: 18px 16px;
  vertical-align: top;
  /* A rule between every column, not just between rows. Nine readings across
     a row is a lot to track, and the vertical rules are what stop the eye
     drifting a column left on the way across. */
  border-right: 1px solid #E8E9EC;
  border-bottom: 1px solid #E8E9EC;
  overflow-wrap: break-word;
}

.alt-tbl--tight th,
.alt-tbl--tight td { padding: 12px 10px; }

.alt-tbl th:last-child,
.alt-tbl td:last-child { border-right: 0; }

.alt-tbl tbody tr:last-child th,
.alt-tbl tbody tr:last-child td { border-bottom: 0; }

/* A dark bar, not a grey one. It is the only band on the page that is not
   content, so it reads as the frame the table hangs in and stops the eye
   mistaking the first row for a heading. */
.alt-tbl thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background-color: #1E2340;
  border-right-color: rgba(255, 255, 255, 0.1);
  border-bottom: 0;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.3;
  text-transform: none;
  color: #FFFFFF;
  white-space: normal;
}

.alt-tbl--tight thead th { font-size: 12px; }

/* Alternating grounds, faint enough to be a rhythm rather than stripes. */
.alt-tbl tbody tr:nth-child(even) th,
.alt-tbl tbody tr:nth-child(even) td { background-color: #FAFAFB; }

/* The name column is pinned, so a reader three columns deep can still see
   whose row they are on. It needs its own ground or the cells scrolling under
   it show through, and a z-index above the body cells for the same reason. */
.alt-tbl__rowhead {
  position: sticky;
  left: 0;
  z-index: 1;
  background-color: #FFFFFF;
}

.alt-tbl tbody tr:nth-child(even) .alt-tbl__rowhead { background-color: #FAFAFB; }

.alt-tbl thead .alt-tbl__rowhead {
  z-index: 3;
  background-color: #1E2340;
}

/* The vendor's name in the vendor's colour. --brand comes from the row's data
   and falls back to ink, so Niyuk's own row and any vendor with no colour set
   are unaffected. */
.alt-tbl__brand {
  display: block;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 19px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--brand, #1D1D1D);
}

.alt-tbl--tight .alt-tbl__brand { font-size: 14px; }

.alt-tbl__brand--italic { font-style: italic; }

.alt-tbl__brand--upper {
  text-transform: uppercase;
  letter-spacing: 0.4px;
  font-size: 17px;
}

.alt-tbl--tight .alt-tbl__brand--upper { font-size: 12.5px; }

/* The recommendation, marked by its ground alone. It used to carry a
   "Recommended" pill as well; the tinted row and the green chip on its price
   say it twice already, and three marks for one claim is the table shouting
   its own conclusion. */
.alt-tbl__win th,
.alt-tbl__win td,
.alt-tbl tbody tr.alt-tbl__win:nth-child(even) th,
.alt-tbl tbody tr.alt-tbl__win:nth-child(even) td { background-color: #EFEFF3; }

.alt-cell {
  display: block;
  font-size: 15px;
  line-height: 1.5;
  color: #2B3038;
}

.alt-tbl--tight .alt-cell { font-size: 12px; line-height: 1.4; }

/* The one reading that is coloured. See the note in the section file. */
.alt-cell--no { color: #E5484D; }

/* Two chips, for the readings that are neither a plain yes nor a plain no. */
.alt-cell--good,
.alt-cell--warn {
  display: inline-block;
  padding: 6px 13px;
  border-radius: 100px;
  font-weight: 600;
  line-height: 1.35;
}

.alt-cell--good { background-color: #D7F7E3; color: #0B7A43; }
.alt-cell--warn { background-color: #FCF2CE; color: #86610A; }

.alt-tbl--tight .alt-cell--good,
.alt-tbl--tight .alt-cell--warn { padding: 3px 8px; }

/* The price sits a shade back: it is a figure rather than a verdict, and the
   column reads as reference once the eye has the readings beside it. The fit
   does not — it is the sentence the whole row resolves to, so it stays in ink
   with everything else. */
.alt-tbl__note--price .alt-cell { color: #6B7280; }

.alt-tbl__note .alt-cell--good { color: #0B7A43; }
.alt-tbl__note .alt-cell--warn { color: #86610A; }

.alt-tbl__stamp {
  margin-top: 14px;
  text-align: right;
  font-size: 12.5px;
  color: #8A94A3;
}

/* ------------------------------------------------------------------
   Recommendation by use case
   ------------------------------------------------------------------ */

.alt-uses {
  display: grid;
  gap: 18px;
  margin-top: 48px;
}

@media (min-width: 700px) {
  .alt-uses { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1100px) {
  .alt-uses {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 20px;
  }
}

/* Column layout with the chip pushed to the foot, so seven cards of unequal
   copy still line their answers up along one edge. */
.alt-use {
  display: flex;
  flex-direction: column;
  padding: 26px 24px 24px;
  border-radius: 20px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #FFFFFF;
  transition: transform 380ms var(--ease-smooth), box-shadow 380ms var(--ease-soft);
}

.alt-use:hover {
  transform: translate3d(0, -4px, 0);
  box-shadow: 0 20px 44px -26px rgba(16, 24, 48, 0.3);
}

.alt-use__q {
  margin-bottom: 11px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
  color: #1D1D1D;
}

.alt-use__a {
  font-size: 14px;
  line-height: 1.6;
  color: #4D585F;
}

.alt-use__pick {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: auto;
  padding-top: 18px;
}

.alt-use__picklabel {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: #8A94A3;
}

.alt-use__pickname {
  padding: 5px 12px;
  border-radius: 100px;
  background-color: #EEF3FF;
  font-size: 13px;
  font-weight: 600;
  color: #2563EB;
}

/* The one entry that links out: our own. See the note beside 'links' in
   includes/alt-greythr-content.php for why the six competitors are named
   rather than linked. */

.alt-item__links {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 10px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid rgba(16, 24, 48, 0.08);
}

.alt-item__linklab {
  font-size: 13px;
  font-weight: 600;
  color: #4D585F;
}

.alt-item__link {
  padding: 5px 12px;
  border-radius: 100px;
  background-color: #EEF3FF;
  font-size: 13px;
  font-weight: 600;
  color: #2563EB;
  transition: background-color 220ms var(--ease-soft), color 220ms var(--ease-soft);
}

.alt-item__link:hover {
  background-color: #2563EB;
  color: #FFFFFF;
}

/* ------------------------------------------------------------------
   "Why Niyuk.AI Should Be Your First Evaluation" — optional per page
   ------------------------------------------------------------------ */

.alt-first {
  display: grid;
  gap: 34px;
  align-items: center;
}

@media (min-width: 1024px) {
  .alt-first {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    gap: 58px;
  }
}

.alt-first__lead {
  margin-top: 18px;
  font-size: 16px;
  line-height: 1.6;
  color: #4D585F;
}

@media (min-width: 768px) {
  .alt-first__lead { font-size: 17px; }
}

.alt-first__list {
  display: grid;
  gap: 12px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.alt-first__row {
  display: flex;
  align-items: flex-start;
  gap: 13px;
  padding: 15px 18px;
  border-radius: 14px;
  border: 1px solid rgba(16, 24, 48, 0.07);
  background-color: #FFFFFF;
  box-shadow: 0 10px 26px -22px rgba(16, 24, 48, 0.26);
}

/* A tick, not the thumb the entry verdicts carry: these five are not weighed
   against a set of cons, so a thumb would imply a facing column that is not
   there. */
.alt-first__mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background-color: rgba(16, 185, 129, 0.13);
  color: #0E9F6E;
}

.alt-first__text {
  font-size: 15px;
  line-height: 1.5;
  color: #1D1D1D;
}

@media (min-width: 768px) {
  .alt-first__text { font-size: 16px; }
}

.alt-first__close {
  margin-top: 22px;
  font-size: 15px;
  line-height: 1.6;
  color: #4D585F;
}

@media (min-width: 768px) {
  .alt-first__close { font-size: 16px; }
}

.alt-first__art img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 20px;
}

/* ------------------------------------------------------------------
   A closing passage of prose — optional per page
   ------------------------------------------------------------------ */

.alt-prose {
  margin-left: auto;
  margin-right: auto;
  max-width: 780px;
}

.alt-prose__title {
  margin-bottom: 26px;
  text-align: center;
}

.alt-prose__body p {
  font-size: 16px;
  line-height: 1.7;
  color: #3C4550;
}

@media (min-width: 768px) {
  .alt-prose__body p { font-size: 18px; }
}

.alt-prose__body p + p { margin-top: 20px; }

/* ------------------------------------------------------------------
   The byline
   ------------------------------------------------------------------ */

/* The byline chip, under the hero lead. It replaced a full-width card carrying
   a portrait, a bio and a rule: a page needs to say who stands behind it, and
   it needs to say that where the claim is made, but it does not need a panel
   the size of a section to do it. The bio and the review date still reach a
   crawler through the Article node. */

/* A white chip rather than bare text on the sky. It renders over the hero
   photograph on both pages that carry it, and at 13-15px the name was reading
   against whatever happened to be behind it. inline-flex keeps the box the
   width of its contents, so it stays a chip and never a band across the
   column. The left padding is tighter than the right because the portrait is a
   circle: matched padding would leave the curve looking inset. */

.alt-by {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  margin-top: 26px;
  padding: 10px 22px 10px 10px;
  border-radius: 20px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #FFFFFF;
  box-shadow: 0 18px 40px -30px rgba(16, 24, 48, 0.45);
}

/* Round, not the card's dashed square mount: at this size a rounded rectangle
   reads as a cropped photograph and a circle reads as a person. */
.alt-by__frame {
  display: grid;
  place-items: center;
  flex: none;
  width: 46px;
  height: 46px;
  overflow: hidden;
  border-radius: 50%;
  background-color: #E8EEFB;
  color: #2563EB;
}

.alt-by__photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.alt-by__mono {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.alt-by__text {
  display: grid;
  gap: 2px;
}

.alt-by__line {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.2;
  color: #0B0D12;
}

/* The name carries the brand colour and the "Written By" does not: the label
   is scaffolding and the name is the thing being said. */
.alt-by__line b {
  font-weight: 700;
  color: #4F46E5;
}

/* The name as a link to the writer's page. Inherits the line's own colour, so
   the chip is unchanged at rest and only answers to the pointer. */

.alt-by__name {
  color: inherit;
  text-decoration: none;
  transition: color 240ms var(--ease-soft);
}

.alt-by__name:hover {
  color: #2563EB;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.alt-by__name:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: 2px;
  border-radius: 4px;
}

/* The role as a link. Underlined on hover only: inside a chip this small a
   permanent underline reads as a second line of rule under the name above it.
   The colour is the role's own, so the chip looks the same until the pointer
   arrives. */

.alt-by__role--link {
  text-decoration: none;
  transition: color 240ms var(--ease-soft);
}

.alt-by__role--link:hover {
  color: #2563EB;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.alt-by__role--link:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: 2px;
  border-radius: 4px;
}

.alt-by__role {
  font-size: 15px;
  font-weight: 500;
  line-height: 1.3;
  color: #4F46E5;
}

@media (max-width: 520px) {
  .alt-by__frame { width: 40px; height: 40px; }
  .alt-by__line  { font-size: 15.5px; }
  .alt-by__role  { font-size: 14px; }
}

/* ------------------------------------------------------------------
   Reduced motion
   ------------------------------------------------------------------
   The lifts are the only motion this page adds of its own; everything else is
   the shared reveal system, which already stands itself down. */

@media (prefers-reduced-motion: reduce) {
  .alt-neg__card,
  .alt-crit__card,
  .alt-use {
    transition: none;
  }

  .alt-neg__card:hover,
  .alt-crit__card:hover,
  .alt-use:hover {
    transform: none;
  }
}

/* ==========================================================================
   INDUSTRY PAGE

   /industries/healthcare/ and whatever follows it. Eleven blocks, and only five
   shapes between them: a hero on the shared .hs-hero frame, a card grid used by
   five sections at three different column counts, a two-column comparison, a
   run of alternating detail rows, and the shared scenic band to close. Nothing
   here is about healthcare — the words come from a content file, so the next
   industry is a content file and an index.
   ========================================================================== */

/* ---- hero ---- */

/* The second line of the heading. It is one sentence across two lines, so the
   tint is a span inside the h1 rather than a second heading under it. */
/* Two lines, one per sentence. At 56px the first sentence needed 624px against
   a 556px column, so both halves wrapped and the headline came out as four
   short lines. 48px fits each of them whole. Scoped to the industry hero: the
   product pages' headlines are shorter and hold at the larger size. */

/* 51px flat once the hero is two columns. The clamp that was here scaled with
   the viewport, so a 1366 laptop got 49px and a 1280 one 46px — right for a
   headline that has to fit a fixed column, wrong when the size itself is the
   thing being specified. Below the breakpoint the hero stacks and the copy has
   the full width, so it scales from there. */

/* :not(--fit) on both of these. A page that sets 'fit' sizes its heading
   against the column with a container query, and these two selectors are a
   class more specific than that rule — so without the exclusion they win and
   the fitted heading goes back to breaking in four. */

.ind-hero .hs-hero__title:not(.ind-hero__title--fit) {
  font-size: clamp(32px, 3.95vw, 51px);
}

/* Flat 51px from 1280 up, where the copy column is 556px and holds each
   sentence whole. Below that the column narrows faster than the headline can
   afford — at 1100 it is 473px, and 51px there breaks two sentences into four
   lines — so the clamp above takes over and scales the type with the column. */

@media (min-width: 1280px) {
  .ind-hero .hs-hero__title:not(.ind-hero__title--fit) {
    font-size: 51px;
  }
}

/* A heading long enough that the default hero size breaks both halves mid
   phrase. This holds each to one line.

   The size is measured against the copy column with container query units, not
   against the viewport: nowrap plus a vw-based size overflows as soon as the
   column is narrower than the viewport implies, and the hero column is a little
   under half the shell. Measured in Bricolage Grotesque, the longer of the two
   lines fits at 8.04% of the column; 7.6% leaves the margin.

   The accent is display:block, so the break between the two halves is the block
   boundary rather than a wrap, and nowrap cannot join them. */

.hs-hero__copy:has(.ind-hero__title--fit) { container-type: inline-size; }

/* Scoped to .ind-hero, and text-wrap spelled out. The heading also carries
   .sp-title, which sets `text-wrap: balance` — and text-wrap is a component of
   the white-space shorthand, so at equal specificity the later rule was
   quietly putting the wrapping back and the heading broke into four lines
   while the font-size from here applied. */

.ind-hero .ind-hero__title--fit {
  white-space: nowrap;
  text-wrap: nowrap;
  font-size: clamp(20px, 7.6cqw, 44px);
  /* em rather than the base rule's fixed -1.2px, which at this smaller size
     would pull the letters noticeably tighter than the rest of the page. */
  letter-spacing: -0.02em;
}

/* The second line of the h1, on a line of its own. It ran as a blue-to-violet
   gradient clipped to the glyphs, which meant the one heading was two colours
   and the industry's name was the part that read as decoration.

   Plain now, and inherited rather than restated: .hs-hero__title sets #0B0D12
   and this takes it, so the two lines cannot drift apart if that colour ever
   changes. `display: block` stays — that is what puts the accent on its own
   line, and it is the only thing this rule was ever really doing.

   The background-clip pair goes with it. Left behind with the colour set back
   to a real value they would do nothing, but a `background-clip: text` on an
   element with no background-image is a trap for whoever reads it next. */

.ind-hero__accent {
  display: block;
  color: inherit;
}

/* No bottom padding, so the banner can reach the section's edge. A negative
   margin on the image was tried and did not work: the padding is not the whole
   of the gap, so it overshot and the overflow clip took the bottom off the
   picture. Removing the padding removes the gap itself. */
.ind-hero { padding-bottom: 0; }

.ind-hero .hs-hero__art { align-self: end; }

/* ---- the cards around the cut-out ----

   The stage is the positioning context: the image keeps its own width and
   negative margin, and the cards hang off the stage rather than off the
   picture, so moving one does not move the other.

   They are hidden below 1024px. The hero stacks there and the image takes the
   full column, which would put a card over her face rather than beside it. */

.ind-hero__stage {
  position: relative;
}

.ind-chip {
  position: absolute;
  z-index: 2;
  display: none;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.7);
  /* Frosted rather than solid: it sits over sky, and a white tile would read
     as a sticker on the photograph instead of something in front of it. */
  background-color: rgba(255, 255, 255, 0.82);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  box-shadow: 0 18px 36px -22px rgba(16, 33, 66, 0.45);
  white-space: nowrap;
}

@media (min-width: 1024px) {
  .ind-chip { display: inline-flex; }
}

.ind-chip__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background-color: #EAF1FE;
  color: #2563EB;
}

.ind-chip__body {
  display: grid;
  gap: 1px;
}

.ind-chip__body b {
  font-size: 13px;
  font-weight: 700;
  color: #14161D;
}

.ind-chip__body em {
  font-size: 11.5px;
  font-style: normal;
  font-weight: 500;
  color: #5B6472;
}

/* Placed off the corners of the stage, not the corners of the picture: the
   cut-out is transparent at its edges, so hanging them off the image would put
   them against nothing.

   DEPTH, NOT A COLLISION
   The subject sits in the middle of the stage and the space either side of her
   is about 100px — narrower than a card. Rather than shrinking the cards or
   pushing them into the copy, the left pair sits BEHIND the cut-out and she
   occludes them; the right pair sits in front. That is why the image carries a
   z-index of its own: it has to be able to cover one pair and be covered by
   the other. The transparent ground around her lets the hidden part show
   through everywhere she is not. */

.ind-hero__img {
  position: relative;
  z-index: 2;
}

/* The two on the left sit behind the figure and the two on the right in front
   of it. That is the depth the default geometry is built on: the cut-out takes
   the right half of the column, so its left edge passes over the left chips and
   the picture reads as having something in front of it and something behind. */
.ind-chip--tl { top: 4%;  left: 6%;  z-index: 1; }
.ind-chip--l  { top: 44%; left: 0;   z-index: 1; }
.ind-chip--tr { top: 13%; right: 0;  z-index: 3; }
.ind-chip--r  { top: 60%; right: 2%; z-index: 3; }

/* A wide cut-out spans the whole column, so there is no left edge for a chip to
   tuck behind — it simply covers them, and a label reading "Back… 8 rol…" is
   worse than no depth at all. All four come to the front here.

   A sibling selector because the image is drawn before the chips, and this way
   the rule follows the flag on the image rather than needing a second flag on
   the section. */
.ind-hero__img--wide ~ .ind-chip { z-index: 3; }

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


/* The padding the section gave up, given back to the copy alone — otherwise the
   buttons sit on the section's edge with the next band directly under them. */
.ind-hero .hs-hero__copy { padding-bottom: 56px; }

@media (min-width: 1024px) {
  .ind-hero .hs-hero__copy { padding-bottom: 90px; }
}

/* Near-black, not the grey these take on white. The industry hero sets them
   over a photograph, and a mid grey that reads as quiet body copy on a white
   page reads as washed out against sky. Scoped to this hero so the product
   pages keep the grey they were tuned with. */

.ind-hero__note {
  color: #14161D;
}

.ind-hero__note {
  margin-top: 20px;
  /* One line. 46ch held it to 416px inside a 556px column and broke it in
     two; the sentence wants 457px. The cap stays so it cannot outrun the
     lead above it on a wider screen. */
  max-width: 52ch;
  font-size: 14px;
  font-weight: 500;
}

/* Wider than its column, and grown from the middle so it does not simply run
   off the right-hand side. */
.ind-hero__img {
  display: block;
  width: 50%;
  max-width: none;
  height: auto;
  margin-left: 29%;
  vertical-align: bottom;
}

@media (max-width: 1023px) {
  .ind-hero__img { width: 100%; margin-left: 0; }
}

/* Gone on phones. Stacked, the cut-out lands under the copy at the full width
   of the column and is most of the first screen — a portrait with nothing said
   on it, between the buttons and the section below them. The chips are already
   off at this width for the same kind of reason, so what is left to hide is the
   picture and the stage holding it.

   The whole .hs-hero__art rather than the img alone: the stage is the only
   thing in it, and an empty grid cell still takes its row. .ind-hero, so the
   product heroes keep their artwork.

   After .ind-hero .hs-hero__art above, which weighs the same. */

@media (max-width: 767px) {
  .ind-hero .hs-hero__art {
    display: none;
  }
}

/* A landscape cut-out rather than a tall one. The 50%/29% above is the geometry
   of a standing figure, which has height to spare and needs pushing right so it
   grows from the middle; a wide picture has neither problem and simply takes
   the column. Nudged up so it still overlaps the fold the way the tall one
   does. */
.ind-hero__img--wide {
  width: 100%;
  margin-left: 0;
}

@media (min-width: 1024px) {
  .ind-hero__img--wide { margin-top: 18px; }
}

/* ---- the grounds ----

   Two, alternating down the page, so eleven sections do not read as one long
   scroll of the same white. */

.ind-band { background-color: #FFFFFF; }

.ind-band--tint {
  background-image: linear-gradient(180deg, #EEF4FB 0%, #F7FAFD 55%, #FFFFFF 100%);
}

/* ---- the section head, used by five of them ---- */

/* 760px held every heading on this page to two lines by a hair: "Common HR
   Problems in Healthcare" wants 770px at 48px, ten more than it had. The lead
   under it keeps the narrower measure, which is the one that was tuned for
   reading. */

.ind-head {
  /* Wide enough for the longest single-line heading on the page: "Spend Less
     Time on HR Operations With Niyuk" wants 979px at 48px, and 860 broke it in
     two. The lead below keeps its own narrower measure, which is the one tuned
     for reading. */
  max-width: 1000px;
  margin: 0 auto;
  text-align: center;
}

.ind-head__lead {
  max-width: 760px;
  margin-left: auto;
  margin-right: auto;
}

.ind-head__title { margin-top: 18px; }

.ind-head__lead {
  margin-top: 16px;
  color: #5B6472;
}

/* ---- the card grid ----

   One grid, five sections, three column counts. --ind-cols is set in the
   markup because the count belongs to the list: nine modules want three across
   and four settings want four. It stays a single column until 640 and two
   until 1024 whatever that number says, because three 300px cards do not fit
   on a phone however the data feels about it. */

/* ---- cards on one side, a picture on the other ----

   The list keeps its own grid, so --ind-cols still decides how many across;
   this only decides how much room it gets. The image is centred in its column
   rather than stretched: it is a portrait-ish banner and a column taller than
   the picture would leave it floating at the top.

   One column below 960px, image last, so a phone gets the six controls before
   it gets the artwork. */

.ind-split {
  display: grid;
  gap: 32px;
  margin-top: 44px;
}

@media (min-width: 960px) {
  .ind-split {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    gap: 48px;
    align-items: center;
  }
}

.ind-split__list {
  margin-top: 0;
}

.ind-split__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 13px;
}

.ind-grid {
  display: grid;
  gap: 16px;
  margin: 44px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 640px) {
  .ind-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .ind-grid {
    grid-template-columns: repeat(var(--ind-cols, 3), minmax(0, 1fr));
    gap: 18px;
  }
}

.ind-gcard {
  padding: 26px 24px 28px;
  border-radius: 20px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  transition: border-color 320ms var(--ease-soft), box-shadow 320ms var(--ease-soft);
}

.ind-gcard:hover {
  border-color: #C9DAF6;
  box-shadow: 0 26px 50px -38px rgba(21, 82, 199, 0.5);
}

/* Large, pale and set back: the number orders the list without competing with
   the sentence under it. */
.ind-gcard__num {
  display: block;
  margin-bottom: 12px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 26px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.04em;
  color: #A9C9FA;
}

.ind-gcard__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: 16px;
  border-radius: 13px;
  background-color: #EEF4FE;
  color: #2563EB;
}

.ind-i { width: 21px; height: 21px; }

.ind-gcard__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.28;
  color: #0B1B33;
}

.ind-gcard__text {
  margin-top: 8px;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.6;
  color: #5B6472;
}

/* The AI section's cards, on its dark ground. */
.ind-gcard--dark {
  border-color: rgba(255, 255, 255, 0.10);
  background-color: rgba(255, 255, 255, 0.04);
}

.ind-gcard--dark:hover {
  border-color: rgba(255, 255, 255, 0.22);
  box-shadow: none;
}

.ind-gcard--dark .ind-gcard__num   { color: #5D95F0; }
.ind-gcard--dark .ind-gcard__title { color: #FFFFFF; }
.ind-gcard--dark .ind-gcard__text  { color: #A7B0C0; }

/* The AI band's cards carry a number and no glyph, so this tile is only ever
   drawn on the case study's dark block. #EEF4FE on near-black is a lit panel
   rather than a tinted one, so it comes down to the same rgba the card ground
   uses and the glyph goes to the lighter blue the number runs at. */
.ind-gcard--dark .ind-gcard__icon {
  background-color: rgba(255, 255, 255, 0.07);
  color: #5D95F0;
}

/* ---- the CHRO page's audiences, on the dark ground ----

   Same ground as .ind-ai and the case study's dark block, not a third
   near-black. The cards come from .ind-gcard--dark above; only the heading and
   its optional lead need saying here, because .ind-head does not know what it
   is standing on. */

/* The recruiters page's audiences, on the same dark ground as .ch-who and
   .ind-ai. Three sections, one near-black. */

/* The AI Agents page's workflow grid, on the same dark ground as .rc-who,
   .ch-who and .ind-ai. Four sections, one near-black. */

.ag-flows {
  background-color: #0B0D12;
  background-image:
    radial-gradient(70% 55% at 50% 0%, rgba(37, 99, 235, 0.22), rgba(37, 99, 235, 0) 68%);
}

.ag-flows .ind-head__title { color: #FFFFFF; }
.ag-flows .ind-head__lead  { color: #A7B0C0; }

.rc-who {
  background-color: #0B0D12;
  background-image:
    radial-gradient(70% 55% at 50% 0%, rgba(37, 99, 235, 0.22), rgba(37, 99, 235, 0) 68%);
}

.rc-who .ind-head__title { color: #FFFFFF; }
.rc-who .ind-head__lead  { color: #A7B0C0; }

.ch-who {
  background-color: #0B0D12;
  background-image:
    radial-gradient(70% 55% at 50% 0%, rgba(37, 99, 235, 0.22), rgba(37, 99, 235, 0) 68%);
}

.ch-who .ind-head__title { color: #FFFFFF; }
.ch-who .ind-head__lead  { color: #A7B0C0; }

/* ---- the shared audience blocks — sections/audience/ ----

   .aud-who and .aud-hero__img are what sections/audience/ emits. They are the
   same rules as .rc-who / .ch-who and .rc-hero__img / .fd-hero__img, which are
   the per-page copies the recruiters, CHRO and founders pages still carry.
   Those four collapse into these two the moment those pages move onto the
   shared blocks; until then all six stay, because deleting a rule a live page
   still names would strip the ground out from under it. */

.aud-who {
  background-color: #0B0D12;
  background-image:
    radial-gradient(70% 55% at 50% 0%, rgba(37, 99, 235, 0.22), rgba(37, 99, 235, 0) 68%);
}

.aud-who .ind-head__title { color: #FFFFFF; }
.aud-who .ind-head__lead  { color: #A7B0C0; }

.aud-hero__img {
  display: block;
  width: 100%;
  max-width: 550px;
  height: auto;
  margin-inline: auto;
  border-radius: 24px;
}

/* ---- the case study's one dark block ----

   Same ground as .ind-ai, the industries page's AI band, rather than a second
   near-black invented here: one page of this site should not have two blacks.
   The heading and its paragraphs invert with it; the cards are handled by
   .ind-gcard--dark above, which already existed for this ground. */

.cs-take--dark {
  background-color: #0B0D12;
  background-image:
    radial-gradient(70% 55% at 50% 0%, rgba(37, 99, 235, 0.22), rgba(37, 99, 235, 0) 68%);
}

.cs-take__prose--dark .section-title { color: #FFFFFF; }
.cs-take__prose--dark .sb-prose__p   { color: #A7B0C0; }

/* The outcome cards. The figure is the first thing in the card and the largest
   thing in it, which is the whole point of the section — and the reason the
   placeholders in it are so visible. That is deliberate. */
.ind-gcard__stat {
  margin: 0 0 14px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 19px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.4px;
  color: #2563EB;
}

.ind-gcard--stat { border-color: #D8E3F7; }

/* ---- rows, for the sections that are a list rather than a set ----

   Six complaints or six controls are a list. Boxing each one turns a list into
   a grid of unrelated things, and this page already has a card grid doing that
   job properly. These sit on the ground with a hairline between them. */

.ind-rows {
  display: grid;
  gap: 0;
  margin: 40px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 860px) {
  .ind-rows {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 56px;
  }
}

.ind-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 16px;
  align-items: start;
  padding: 22px 0;
  border-top: 1px solid #EAEEF6;
}

/* Cards, not hairline rows, in the stacked column.

   The note in sections/industries/problems.php argues for rules over boxes,
   and it is right when the list runs across the page: six borders there make a
   grid of unrelated things. In this column the list is beside a held image and
   has half the width, and a card is what gives each complaint an edge of its
   own so the eye can take them one at a time.

   It also gives the picture something to hold through: sticky travel is the
   difference between the list's height and the image's, and carding the rows
   adds most of 200px to the list. */

.ind-rows--stack {
  gap: 12px;
}

.ind-rows--stack .ind-row {
  padding: 26px 28px;
  gap: 18px;
  border-top: 0;
  border: 1px solid #E7EDF7;
  border-radius: 18px;
  background-color: #FFFFFF;
  transition: border-color 260ms var(--ease-soft), box-shadow 260ms var(--ease-soft);
}

/* Bigger type in the cards than in the hairline list: a card carries its own
   edge, so the title inside it has to hold the box rather than just start a
   line. The number grows with it so the two still read as one pair. */

.ind-rows--stack .ind-row__title {
  font-size: 20px;
}

.ind-rows--stack .ind-row__text {
  margin-top: 8px;
  font-size: 15px;
}

/* Bigger and in the brand blue, not the pale tint the hairline list uses. In
   that list the number is a marker beside a rule; in a card it is the only
   thing carrying the sequence, so it has to be legible on its own. */

.ind-rows--stack .ind-row__num {
  font-size: 26px;
  line-height: 1.15;
  color: #2563EB;
}

.ind-rows--stack .ind-row:hover {
  border-color: #D3E0F5;
  box-shadow: 0 18px 36px -28px rgba(16, 24, 48, 0.4);
}

/* The rule the two-column list drops on its first row, and the one it puts
   back on its second, are both about hairlines. There are none here. */

.ind-rows--stack .ind-row:first-child,
.ind-rows--stack .ind-row:nth-child(2) {
  border-top: 1px solid #E7EDF7;
}

/* The first row of each column loses its rule, so the list starts clean at the
   top of both columns rather than only the left one. */
.ind-row:first-child { border-top: 0; }

@media (min-width: 860px) {
  .ind-row:nth-child(2) { border-top: 0; }
}

/* ---- the implementation timeline, a card per month ----

   Three equal steps, so three equal boxes. It ran on .ind-rows, the site's
   hairline list, which is right for six complaints read as one list and wrong
   for three phases that are a set.

   Two across from 760 and three from 1024, not three the whole way: the third
   card's paragraph runs six lines, and a third of a tablet is not a measure to
   set six lines in. */

.cs-time {
  display: grid;
  gap: 18px;
  margin: 40px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 760px) {
  .cs-time { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .cs-time {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 22px;
  }
}

.cs-time__card {
  display: flex;
  flex-direction: column;
  padding: 26px 26px 30px;
  border-radius: 22px;
  border: 1px solid rgba(37, 99, 235, 0.12);
  /* The section already stands on .ind-band's tint, so the card is a step up
     from it rather than white: white here would read as the page showing
     through three holes in the band. */
  background-color: #F3F7FF;
}

/* The glyph and the month on one line, pushed to opposite edges. */
.cs-time__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}

.cs-time__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 14px;
  background-color: #FFFFFF;
  color: #2563EB;
}

.cs-time__when {
  flex: none;
  padding: 7px 15px;
  border-radius: 100px;
  background-color: rgba(37, 99, 235, 0.1);
  font-size: 13.5px;
  font-weight: 600;
  color: #2563EB;
}

.cs-time__title {
  margin-top: 26px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 20px;
  font-weight: 700;
  line-height: 1.28;
  letter-spacing: -0.2px;
  color: #0B1B33;
}

.cs-time__text {
  margin-top: 12px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.65;
  color: #5B6472;
}

/* ---- the picture that holds while the list moves ----

   The banner sticks under the fixed header and the complaints scroll past it.
   `position: sticky` and nothing else: the image stops when its column runs
   out, so the section ends on its own and the one below takes the screen with
   no scroll listener, no pinning and nothing to undo. --nav-h is the header's
   own token, so the two cannot drift apart.

   One column below 960px: a sticky image beside a list needs the list to be
   taller than the image, and on a narrow screen it is not. */

.ind-stick {
  display: grid;
  gap: 32px;
  margin-top: 40px;
}

@media (min-width: 960px) {
  .ind-stick {
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
    gap: 56px;
    align-items: start;
  }

  .ind-stick__media {
    position: sticky;
    top: calc(var(--nav-h) + 28px);
  }

  /* A page whose photograph is not on disk yet draws no media column, so the
     two-column rule above would leave the list in a half-width first column
     with nothing beside it. One column instead, held to a readable measure and
     centred under the section heading. See sections/industries/problems.php. */
  .ind-stick--solo {
    grid-template-columns: minmax(0, 1fr);
    max-width: 900px;
    margin-inline: auto;
  }
}

.ind-stick__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 13px;
}

/* Stacked, not the two-across the list uses when it has the page to itself. */

.ind-rows--stack {
  margin-top: 0;
}

@media (min-width: 860px) {
  .ind-rows--stack {
    grid-template-columns: minmax(0, 1fr);
    column-gap: 0;
  }

  /* The second row keeps its rule here: with one column it is no longer the
     top of a second column, and the rule is what separates it from the first. */
  .ind-rows--stack .ind-row:nth-child(2) {
    border-top: 1px solid #EAEEF6;
  }
}

.ind-row__num {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.5;
  color: #A9C9FA;
}

.ind-row__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17.5px;
  font-weight: 700;
  line-height: 1.3;
  color: #0B1B33;
}

.ind-row__text {
  margin-top: 6px;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.6;
  color: #5B6472;
}

/* ---- the bare variant of the card grid ----

   Same grid, no card. Used where the section is a list of things the reader
   scans rather than a set of things they compare: nine modules, six controls,
   six figures. Only the four settings stay as real cards, which is what keeps
   that section reading as a choice between four options. */

.ind-grid--bare .ind-gcard,
.ind-gcard--bare {
  padding: 0;
  border: 0;
  background: none;
}

.ind-grid--bare { gap: 30px 26px; }

@media (min-width: 1024px) {
  .ind-grid--bare { gap: 34px 40px; }
}

.ind-gcard--bare:hover {
  border: 0;
  box-shadow: none;
}

/* On the bare variant the tile becomes a plain mark: a filled tile with no card
   behind it reads as a button. */
.ind-gcard--bare .ind-gcard__icon {
  width: 34px;
  height: 34px;
  margin-bottom: 12px;
  border-radius: 10px;
  background-color: #EEF4FE;
}

.ind-gcard--bare .ind-i { width: 18px; height: 18px; }

/* The outcome figures carry the section, so they are set at display size and
   the label under them steps down to suit. */
.ind-gcard--bare.ind-gcard--stat .ind-gcard__stat {
  font-size: 22px;
  line-height: 1.25;
}

.ind-gcard--bare.ind-gcard--stat .ind-gcard__title {
  font-size: 16px;
}

/* ---- the module rail ----

   Almost nothing. The section uses .hs-scenic and .hs-feat__*, which bring the
   ground, the card and the four-across width with them. Only the lead under
   the heading is new: that rail's header row was built for a badge and a title
   alone. */

.ind-mod__lead {
  margin-top: 14px;
  max-width: 52ch;
}

/* ---- before and after ----

   Two panels, each on its own ground: a flat, drained grey for the way things
   work now, and the brand blue for the way they work after. The rows are white
   cards on both sides so the two lists are read the same way.

   THE TILT IS THE ARGUMENT
   On the "before" side each row sits at a slightly different angle, the way a
   stack of paper does when nobody has squared it up. On the "with" side they
   are straight. That contrast says what the section is about before a word is
   read, and it costs one transform. It is decoration only: both lists carry the
   same six lines in the same order, and a screen reader gets them identically.
   ========================================================================== */

/* A white ground that lifts to a faint blue through the middle and returns to
   white at the foot. The two panels inside are strongly coloured, so the
   section behind them stays almost white: enough to separate it from the plain
   white sections either side, not enough to compete with what it holds.

   background-color stays as the fallback for anything that cannot paint the
   gradient. */
/* A tinted band, not the near-white it had. The section above it is white and
   the one below is white, so a gradient that starts and ends white made this
   read as more of the same page rather than as its own section. These are the
   .sec-wash stops the rest of the site uses for exactly this: brand blue and
   violet washed in from opposite corners over a pale ground, ending white so
   the join with the section below stays soft. */

.ind-shift {
  background-color: #EDF2FE;
  background-image:
    radial-gradient(85% 60% at 10% 0%, rgba(37, 99, 235, 0.10), rgba(37, 99, 235, 0) 62%),
    radial-gradient(70% 55% at 92% 100%, rgba(139, 92, 246, 0.09), rgba(139, 92, 246, 0) 64%),
    linear-gradient(180deg, #EDF2FE 0%, #F1F5FE 46%, #F6F9FF 74%, #FFFFFF 100%);
}

.ind-shift__grid {
  display: grid;
  gap: 18px;
  margin-top: 44px;
}

@media (min-width: 860px) {
  .ind-shift__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }
}

/* The two panels without a section of their own: the timesheet page's why
   block opens with prose and the comparison sits under it, so the grid needs
   the top margin the section's head would otherwise have provided. */

.ind-shift__grid--bare {
  margin-top: 44px;
}

.ind-shift__col {
  padding: 30px 24px 34px;
  border-radius: 24px;
}

@media (min-width: 768px) {
  .ind-shift__col { padding: 36px 32px 40px; }
}

/* Drained on purpose: the grey is the same hue as the blue opposite it with the
   colour taken out, so the pair reads as one picture in two states rather than
   as two unrelated panels. */
.ind-shift__col--before {
  background-image: linear-gradient(165deg, #9AA3B2 0%, #B4BCC8 55%, #C6CCD6 100%);
}

.ind-shift__col--after {
  background-image: linear-gradient(165deg, #2F6BE0 0%, #4B86F0 55%, #7CB0FC 100%);
}

.ind-shift__title {
  margin-bottom: 24px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 21px;
  font-weight: 700;
  text-align: center;
  color: #FFFFFF;
}

.ind-shift__list {
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ind-shift__list li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  border-radius: 12px;
  background-color: #FFFFFF;
  box-shadow: 0 14px 26px -18px rgba(16, 24, 48, 0.5);
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #22262F;
}

/* Six angles written out rather than derived from --i. A formula gives a fan,
   which reads as a deliberate arrangement; what this wants is the look of
   nobody having straightened them, and that is easier to place by hand. */
.ind-shift__col--before .ind-shift__list li:nth-child(1) { transform: rotate(-0.9deg); }
.ind-shift__col--before .ind-shift__list li:nth-child(2) { transform: rotate(0.7deg)  translateX(4px); }
.ind-shift__col--before .ind-shift__list li:nth-child(3) { transform: rotate(-0.5deg) translateX(-3px); }
.ind-shift__col--before .ind-shift__list li:nth-child(4) { transform: rotate(1deg); }
.ind-shift__col--before .ind-shift__list li:nth-child(5) { transform: rotate(-0.7deg) translateX(3px); }
.ind-shift__col--before .ind-shift__list li:nth-child(6) { transform: rotate(0.5deg)  translateX(-2px); }

.ind-shift__mark {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
}

.ind-shift__col--before .ind-shift__mark { background-color: #E5484D; color: #FFFFFF; }
.ind-shift__col--after  .ind-shift__mark { background-color: #2563EB; color: #FFFFFF; }

.ind-shift__mark .hs-i { width: 13px; height: 13px; }

/* ---- the five capabilities in depth ----

   Almost nothing of its own. The section is the site's .showcase, so the
   ground, the pin, the panels, the tints and the dots all come with it. Only
   the supporting points under each description are new: the home page's panels
   carry a description and a button, and these carry three lines between them. */

.sc-panel__points {
  display: grid;
  gap: 10px;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}

.sc-panel__points li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.5;
  /* Lighter than the description above it: these support the paragraph rather
     than competing with it, and the panel is already near-black. */
  color: #A7B0C0;
}

.sc-panel__points span {
  display: grid;
  place-items: center;
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  border-radius: 50%;
  /* White, not the panel's accent. The accent tick on an accent bubble was two
     near-values of the same hue and it sat almost invisible against a near-black
     panel; white reads at a glance on all four accents. */
  background-color: rgba(255, 255, 255, 0.14);
  color: #FFFFFF;
}

.sc-panel__points .hs-i { width: 11px; height: 11px; }

/* ---- the AI band ---- */

.ind-ai {
  background-color: #0B0D12;
  background-image:
    radial-gradient(70% 55% at 50% 0%, rgba(37, 99, 235, 0.22), rgba(37, 99, 235, 0) 68%);
}

.ind-ai__title { color: #FFFFFF; }
.ind-ai__lead  { color: #A7B0C0; }

/* ---- the note under the trust cards ---- */

/* ---- trust: one column beside an artwork that stays put ---- */

/* A ground of its own. The showcase above ends dark and the FAQ below is white,
   so this sits between them as a soft blue wash that clears to white at the
   bottom and hands over without a seam. */

.ind-trust {
  background-color: #F4F7FE;
  background-image:
    radial-gradient(75% 55% at 88% 4%, rgba(37, 99, 235, 0.09), rgba(37, 99, 235, 0) 62%),
    radial-gradient(60% 50% at 6% 96%, rgba(139, 92, 246, 0.07), rgba(139, 92, 246, 0) 66%),
    linear-gradient(180deg, #F4F7FE 0%, #F7FAFE 52%, #FFFFFF 100%);
}

/* The title is one line by design: "Employee Data Security and Access Control"
   is a single statement and reads as one. It needs more than the 860px the
   shared head allows, so the head is unbounded here and the size scales with
   the viewport until it reaches the usual 48px, at which point there is room
   for it at full size. Below 900px it wraps like any other heading. */

@media (min-width: 1024px) {
  .ind-trust .ind-head { max-width: none; }

  .ind-trust .ind-head__title {
    white-space: nowrap;
    font-size: clamp(28px, 4.1vw, 48px);
  }
}


.ind-trust__grid {
  display: grid;
  gap: 34px;
  margin-top: 44px;
}

/* Even halves: the cards get one, the artwork gets the other. 1024px rather
   than 900 because half of a 900px shell is not enough for a card to hold its
   heading, and a cramped half is worse than a stacked full width. */
@media (min-width: 1024px) {
  .ind-trust__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 40px;
    align-items: start;
  }
}

.ind-trust__list {
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Two across, but only where two will actually fit. Below 1024px the section is
   stacked and the list has the whole shell, so 620px is enough. From 1024 it
   only has half the shell, and half is not wide enough for two cards until
   1180px. In between it stays one column beside the artwork rather than
   squeezing two cards into 460px. The gap is tight because the cards carry
   padding of their own, and the two together were reading as too much air. */
@media (min-width: 620px) and (max-width: 1023.98px) {
  .ind-trust__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 12px;
  }
}

@media (min-width: 1180px) {
  .ind-trust__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 12px;
  }
}

/* Mark and title on one line, description under the TITLE rather than under the
   mark, so the six headings share a left edge and the column can be read on
   those alone. */
.ind-trust__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 2px 12px;
  align-items: center;
  padding: 15px 17px 17px;
  border: 1px solid rgba(11, 27, 51, 0.07);
  border-radius: 18px;
  background-color: #FFFFFF;
  /* No shadow. The tinted ground behind is what separates the cards from the
     page, so a shadow would only be a second answer to a question already
     settled. */
}

/* One green for all six: the mark inside is what tells them apart, so the tile
   behind it should not be trying to as well. */
.ind-trust__mark {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background-color: #E6F6EE;
  color: #12805C;
}

.ind-trust__mark .hs-i { width: 16px; height: 16px; }

.ind-trust__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1.28;
  color: #0B1B33;
}

.ind-trust__text {
  grid-column: 2;
  margin-top: 4px;
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #5B6472;
}

/* The artwork holds its place while the list moves past it. Offset by the
   navbar so it settles below the bar rather than under it, and only from the
   breakpoint where there are two columns for it to sit beside. */
.ind-trust__aside { display: none; }

@media (min-width: 1024px) {
  .ind-trust__aside { display: block; }

  .ind-trust__sticky {
    position: sticky;
    top: calc(var(--nav-h) + 40px);
  }
}

/* 90% of the half rather than all of it, centred in what is left. At full
   width the artwork was heavier than the six cards it sits opposite; pulling it
   in a notch evens the two sides without changing the split. */
.ind-trust__art {
  display: block;
  width: 90%;
  max-width: 100%;
  height: auto;
  margin-inline: auto;
  border-radius: 10px;
}

.ind-trust__note {
  max-width: 780px;
  margin: 26px auto 0;
  padding: 26px 26px 28px;
  border-radius: 20px;
  background-color: #F6F9FD;
  box-shadow: inset 0 0 0 1px #E9EFFA;
  text-align: center;
}

.ind-trust__notetitle {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 19px;
  font-weight: 700;
  color: #0B1B33;
}

.ind-trust__note p {
  margin-top: 10px;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.65;
  color: #5B6472;
}

/* The caveat about certifications, set quieter than the paragraph above it: it
   is a status note rather than a claim, and it should read like one. */
.ind-trust__note p:last-child {
  font-size: 13px;
  color: #7C879B;
}

/* ---- the closing band ----

   None. It uses .hs-scenic / .hs-cta, the band a dozen other pages close with,
   so there is nothing for this page to style. */

/* ==========================================================================
   SIGNUP FLOW

   /signup/, /signup/verify/ and /signup/plan/. Form on the left, the reasons to
   finish it on the right, and a three-segment bar across the top. No navbar and
   no footer: a checkout is not a page to wander off.
   ========================================================================== */

.su-main {
  min-height: 100vh;
  background-color: #F6F8FD;
  background-image:
    radial-gradient(78% 46% at 12% 0%, rgba(37, 99, 235, 0.10), rgba(37, 99, 235, 0) 62%),
    radial-gradient(62% 42% at 92% 8%, rgba(139, 92, 246, 0.07), rgba(139, 92, 246, 0) 66%),
    linear-gradient(180deg, #EDF1FA 0%, #F5F8FE 46%, #F7F9FD 100%);
}

.su { padding: 26px 18px 60px; }
.su__inner { max-width: 1100px; margin: 0 auto; }
/* Centred and larger. There is no navbar on these three pages — the logo is the
   only mark on them and the only way out that is not a step — so ranged left at
   32px it read as the corner of a header that was not there. In the middle at
   twice the size it reads as the page's own masthead. */
.su__top {
  padding-bottom: 26px;
  text-align: center;
}

.su__brand {
  display: inline-block;
}

.su__brand img {
  display: block;
  height: 44px;
  width: auto;
}

@media (min-width: 768px) {
  .su__top { padding-bottom: 32px; }
  .su__brand img { height: 56px; }
}

/* ---- the progress ----

   A numbered dot per step with its name beside it, joined by a rule that grows
   to fill whatever is left. It replaced three plain bars, and the markup it is
   written against is the one in includes/signup-shell.php: `is-past` for a step
   already done, `is-now` for the one being filled in. A stale rule set keyed on
   `is-done` styled none of them, which is what left the labels sitting on top of
   the line under them. */

.su__prog { margin-bottom: 24px; }

.su__steps {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.su__step {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* Every step but the first is preceded by the rule that joins it to the one
   before. It is flex: 1, so the row spaces itself however wide the card is and
   whatever the labels run to. */
.su__step + .su__step {
  flex: 1;
  min-width: 0;
}

.su__step + .su__step::before {
  content: '';
  flex: 1;
  min-width: 12px;
  height: 2px;
  border-radius: 100px;
  background-color: #E1E8F4;
}

.su__stepdot {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background-color: #E9EEF7;
  font-size: 12px;
  font-weight: 700;
  color: #7C879B;
  transition:
    background-color 420ms var(--ease-soft),
    color 420ms var(--ease-soft),
    box-shadow 420ms var(--ease-soft);
}

.su__stepdot svg { width: 13px; height: 13px; }

/* Done is green and carries a tick; the step being filled in is brand blue with
   a ring, so the two states are told apart by shape and colour rather than by
   colour alone. */
.su__step.is-past .su__stepdot {
  background-color: #16A34A;
  color: #FFFFFF;
}

.su__step.is-now .su__stepdot {
  background-image: linear-gradient(150deg, #3B82F6 0%, #2563EB 100%);
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.14);
  color: #FFFFFF;
}

.su__steplabel {
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  color: #8A94A6;
}

.su__step.is-past .su__steplabel { color: #22262F; }
.su__step.is-now .su__steplabel { color: #0B1B33; }

/* The names go before the dots do. On a narrow card three labels and three dots
   cannot both fit, and the dots are what carry the position. */
@media (max-width: 560px) {
  .su__steplabel { display: none; }
}

.su__stepnote {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin: 14px 0 0;
  font-size: 13.5px;
  font-weight: 600;
  color: #22262F;
}

.su__steptime { font-size: 13px; font-weight: 500; color: #7C879B; }

.su__grid { display: grid; gap: 22px; }

@media (min-width: 900px) {
  .su__grid {
    /* The form is the job and the rail is the reassurance, so the form takes the
       larger share rather than the two splitting evenly. */
    grid-template-columns: 1.25fr 1fr;
    gap: 40px;
    align-items: start;
  }
}

.su__card {
  padding: 26px 22px 28px;
  border-radius: 20px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  box-shadow: 0 30px 60px -44px rgba(16, 24, 48, 0.5);
}

@media (min-width: 768px) {
  .su__card { padding: 34px 32px 34px; }
}

.su__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 26px; font-weight: 700; line-height: 1.16;
  letter-spacing: -0.7px; color: #0B1B33;
}

.su__lead { margin-top: 6px; font-size: 15px; font-weight: 500; color: #5B6472; }
.su__lead strong { color: #22262F; font-weight: 700; }

/* Green, because it is the one line on the page reporting that something has
   already gone right. */
.su__ok { color: #12805C; font-weight: 600; }

.su__form { margin-top: 22px; }
.su__field { margin: 0 0 16px; }

.su__label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px; font-weight: 600; color: #22262F;
}

.su__input {
  width: 100%;
  padding: 10px 13px;
  border-radius: 10px;
  border: 1px solid rgba(16, 24, 48, 0.13);
  background-color: #FBFBFE;
  font-family: inherit;
  font-size: 15px; font-weight: 500; color: #0B0D12;
  transition: border-color 240ms var(--ease-soft), box-shadow 240ms var(--ease-soft);
}

.su__input::placeholder { color: #A6ADBD; }

.su__input:focus {
  outline: none;
  border-color: #2563EB;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.14);
}

/* Six digits, spaced out and centred: a code is read back character by character
   against a message, not skimmed as a word. */
.su__input--code {
  text-align: center;
  font-size: 19px; font-weight: 700;
  letter-spacing: 0.5em; text-indent: 0.5em;
}

.su__select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%235B6472' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 10px 6px;
  padding-right: 34px;
}

.su__two,
.su__three { display: grid; gap: 0 12px; }

@media (min-width: 560px) {
  .su__two { grid-template-columns: 1fr 1fr; }
}

/* Employees, billing and country on one line. Country takes the largest share
   because its options are the longest ("United Arab Emirates (AED)"); the
   headcount is a number and needs least. Below 620px they stack: three selects
   across a phone would each be too narrow to read their own value. */
@media (min-width: 620px) {
  .su__three { grid-template-columns: 0.72fr 0.86fr 1.1fr; }
}

/* Set tight and clear of the field. It is a footnote to the input above it,
   so it wants air between the two and as little height of its own as it can
   read in: at 1.5 line-height and 13px it was as tall as a form row. */
.su__note {
  display: block;
  margin-top: 10px;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.35;
  color: #7C879B;
}

/* Not colour alone: the message is words, and the field it belongs to is the one
   directly above it. */
.su__error {
  display: block;
  margin-top: 10px;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.35;
  color: #C4262C;
}

.su__go {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 52px;
  margin-top: 4px;
  border-radius: 100px;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  box-shadow: 0 8px 20px -8px rgba(37, 99, 235, 0.55);
  font-family: inherit;
  font-size: 15.5px; font-weight: 600; color: #FFFFFF;
  cursor: pointer;
  transition:
    transform 260ms var(--ease-soft),
    filter 260ms var(--ease-soft),
    box-shadow 260ms var(--ease-soft);
}

.su__go:hover {
  transform: translateY(-2px);
  filter: saturate(1.08) brightness(1.03);
  box-shadow: 0 16px 30px -10px rgba(37, 99, 235, 0.6);
}

.su__go--link { text-decoration: none; }

.su__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 16px 0 0;
}

.su__link {
  font-family: inherit;
  font-size: 14px; font-weight: 600; color: #2563EB;
  cursor: pointer;
  transition: color 240ms var(--ease-soft);
}

.su__link:hover { color: #1D4ED8; }

.su__quiet {
  font-size: 14px; font-weight: 500; color: #7C879B;
  transition: color 240ms var(--ease-soft);
}

.su__quiet:hover { color: #22262F; }

.su__sum {
  margin: 4px 0 20px;
  padding: 14px 16px;
  border-radius: 13px;
  background-color: #F7F9FD;
  box-shadow: inset 0 0 0 1px #E9EFFA;
}

.su__sum div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.su__sum div + div { margin-top: 8px; }

.su__sum dt { font-size: 14px; font-weight: 500; color: #5B6472; }

.su__sum dd {
  margin: 0;
  font-size: 14px; font-weight: 600; color: #22262F;
  font-variant-numeric: tabular-nums;
}

.su__sum--total {
  margin-top: 12px !important;
  padding-top: 11px;
  border-top: 1px solid #E4EAF5;
}

.su__sum--total dt,
.su__sum--total dd { font-size: 15.5px; font-weight: 700; color: #0B1B33; }

.su__rail { display: grid; gap: 18px; }

/* ---- the founder's note ----

   The same pale ground and meadow the home page's .fn and the HRMS page's
   .hs-note use. Written against this rail's own measure rather than reusing
   those classes: both are section-width cards and this one sits in a 1fr
   column beside a form, so the sizes differ even though the treatment does
   not. */

.su__letter {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  margin: 0;
  padding: 24px 22px 26px;
  border-radius: 18px;
  background-color: #FFFFFF;
}

.su__letterhead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.su__lettertitle {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.5px;
  color: #0B1B33;
}

.su__letterkicker {
  margin-top: 4px;
  font-size: 14px;
  font-weight: 500;
  color: #5B6472;
}

/* The dashed frame is the founder note's own: it reads as a photograph pinned
   to the letter rather than an avatar bolted to a card. */
.su__letterframe {
  display: grid;
  place-items: center;
  flex: none;
  width: 62px;
  height: 62px;
  padding: 4px;
  border-radius: 16px;
  border: 1px dashed #C3CCD6;
}

.su__letterframe img {
  width: 100%;
  height: 100%;
  border-radius: 12px;
  object-fit: cover;
}

/* No portrait on file, so the frame holds the mark rather than a stock face,
   which would be claiming something about a real person. */
.su__letterframe--mark img {
  width: 60%;
  height: auto;
  border-radius: 0;
  object-fit: contain;
}

.su__letterbody {
  /* Narrow enough to clear the meadow rising on the right. */
  max-width: 30ch;
  margin-top: 22px;
}

.su__letterbody p {
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.65;
  color: #4D585F;
}

.su__letterbody p + p { margin-top: 12px; }

/* The meadow, on the same corner and with the same masked left edge as
   .fn__grass — the PNG has a straight edge that falls inside the card and
   reads as a seam, so it is dissolved into the ground over the first fifth. */
.su__lettergrass {
  position: absolute;
  right: -2%;
  bottom: -1px;      /* kills the hairline a scaled image can leave sitting
                        exactly on the card's edge */
  z-index: -1;
  width: 52%;
  height: auto;
  pointer-events: none;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  /* TWO MASKS, INTERSECTED — the pair .hs-note__grass uses, and for its reason.
     Horizontal, because the PNG has a straight left edge that falls inside the
     card and reads as a seam. Vertical, because this card is short and the
     letter runs across the meadow's crest: fading the top thins the hilltop to
     nothing exactly where type can reach it, whatever the card's height.

     Where mask-composite is unsupported the layers add instead of intersecting,
     which lands back on the horizontal-only behaviour. That is the right way
     for this to fail. */
  -webkit-mask-image:
    linear-gradient(to right, transparent 0%, #000 20%),
    linear-gradient(to bottom, transparent 0%, #000 55%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent 0%, #000 20%),
    linear-gradient(to bottom, transparent 0%, #000 55%);
  mask-composite: intersect;
}

.su__prooftitle {
  margin: 0 0 12px;
  font-size: 13px; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase; color: #7C879B;
}

.su__logos {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.su__logos li {
  display: grid;
  place-items: center;
  padding: 12px 8px;
  border-radius: 12px;
  background-color: #FFFFFF;
  box-shadow: inset 0 0 0 1px #E9EFFA;
}

/* Held back to a grey, as they are in the strip on the home page: they are
   evidence, not six brands competing with the form. */
.su__logos img {
  max-width: 100%;
  height: 20px;
  object-fit: contain;
  opacity: 0.7;
}

.su__sure { display: grid; gap: 9px; margin: 0; padding: 0; list-style: none; }

.su__sure li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 14px; font-weight: 500; color: #4D585F;
}

.su__tick {
  display: grid;
  place-items: center;
  flex: none;
  width: 18px; height: 18px;
  border-radius: 50%;
  background-color: #16A34A;
  color: #FFFFFF;
}

.su__tick .hs-i { width: 11px; height: 11px; }

@media (prefers-reduced-motion: reduce) {
  .su__go:hover { transform: none; }
}

/* =========================================================================
   /small-companies/ — HR software for small businesses

   Four things this page needs that nothing else on the site has: the hero's
   card stack, the problem statement, the three reasons on a rule, and the
   eight-name pill row. Everything else it uses (.hs-hero, .ind-band, .ind-head,
   .ind-grid, .ind-gcard, .hs-scenic, the FAQ) is already here.
   ========================================================================= */

/* ---- hero: the old way stacked behind the new one ----

   Four cards in one grid cell, all on row 1 / column 1, so they overlap rather
   than flow. The three artefacts fan out behind and the Niyuk record sits in
   front square to the page: the tilt is what makes them read as a pile that has
   been dropped somewhere, and the one that is straight is the point. */

/* The lead runs black here rather than the site's grey: it is the only sentence
   in this hero besides the h1, and it carries the page's argument. */


.sb-stack {
  display: grid;
  place-items: center;
  min-height: 380px;
  padding: 20px;
}

.sb-stack__card {
  grid-area: 1 / 1;
  width: min(100%, 340px);
  padding: 18px 20px;
  border-radius: 16px;
  border: 1px solid rgba(11, 27, 51, 0.08);
  background-color: #FFFFFF;
  box-shadow: 0 30px 60px -44px rgba(11, 27, 51, 0.55);
}

.sb-stack__card--1 { transform: rotate(-7deg) translate(-38px, -104px); }
.sb-stack__card--2 { transform: rotate(4.5deg) translate(46px, -46px); }
.sb-stack__card--3 { transform: rotate(-3deg) translate(-30px, 22px); }

/* The artefacts are paler than the record in front, which is what puts them
   behind it without a z-index fight. */
.sb-stack__card--1,
.sb-stack__card--2,
.sb-stack__card--3 {
  background-color: #F7F9FD;
  box-shadow: 0 18px 36px -30px rgba(11, 27, 51, 0.4);
}

.sb-stack__front {
  position: relative;
  transform: translateY(96px);
  padding: 22px 24px 24px;
  border-color: rgba(37, 99, 235, 0.18);
  background-color: #FFFFFF;
}

.sb-stack__tag,
.sb-stack__line,
.sb-stack__title,
.sb-stack__sub { display: block; }

/* Mono for the stamps, because the source's labels are file names and record
   types and they should look like the machine wrote them. */
/* No text-transform: the source's own labels carry their case, and one of them
   is a filename. Uppercasing it would print SHEET_04.XLSX, which is not the
   file it names. */
.sb-stack__tag {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  color: #98A2B3;
}

.sb-stack__tag--brand { color: #2563EB; }

.sb-stack__line {
  margin-top: 6px;
  font-size: 14px;
  font-weight: 500;
  color: #5B6472;
}

.sb-stack__title {
  margin-top: 8px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 20px;
  font-weight: 700;
  color: #0B1B33;
}

.sb-stack__sub {
  margin-top: 4px;
  font-size: 14px;
  font-weight: 500;
  color: #5B6472;
}

/* Below the two-column breakpoint the stack has less width to fan into, so it
   pulls its offsets in rather than pushing cards off the side. */
@media (max-width: 720px) {
  .sb-stack { min-height: 330px; }
  .sb-stack__card { width: min(100%, 300px); }
  .sb-stack__card--1 { transform: rotate(-6deg) translate(-16px, -88px); }
  .sb-stack__card--2 { transform: rotate(4deg) translate(20px, -38px); }
  .sb-stack__card--3 { transform: rotate(-2.5deg) translate(-12px, 18px); }
  .sb-stack__front  { transform: translateY(80px); }
}

/* ---- a titled passage of plain paragraphs ----

   Centred on a reading measure rather than cut into cards. Two sections use
   it: the problem passage before the capabilities and the growth passage after
   them. Both are an argument, and an argument in boxes stops being one. */

/* 840px rather than the 760px this passage used to run at: the longest
   paragraph measures 1536px of Inter 500 at 16.5px, so a narrower column
   breaks it over three lines and leaves "again." alone on the last one. */

/* Two measures, not one. The block is as wide as its longest heading needs and
   the paragraphs are held narrower inside it.

   960 rather than the 840 this ran at, because "Enterprise HR Should Be Simple
   to Manage" measures 907px of Bricolage Grotesque 600 at 48px: at 840 it broke
   over two lines with "Manage" alone on the second. This is the same reason
   .ind-head runs to 1000px while the lead under it keeps its own measure. */

.sb-prose {
  max-width: 960px;
  margin: 0 auto;
  text-align: center;
}

/* 840 is the reading measure, and every paragraph gets the same one so a run of
   them squares up rather than stepping in and out.

   No text-wrap: balance. Balance sizes each paragraph's lines to its own word
   count, so two paragraphs of different lengths settle at visibly different
   widths — which is exactly what it looked like. Filling the measure is what
   makes them agree. */

.sb-prose__p {
  max-width: 840px;
  margin: 18px auto 0;
  font-size: 16.5px;
  font-weight: 500;
  line-height: 1.75;
  color: #5B6472;
}

/* The first paragraph sits closer to the heading than the ones after it. */
.sb-prose .section-title + .sb-prose__p { margin-top: 24px; }

/* The heading takes the block's full 960; only the paragraphs are held in. */
.sb-prose .section-title { max-width: none; }

/* ---- the three reasons, on a rule rather than in a box ---- */

.sb-why__grid {
  display: grid;
  gap: 34px;
  margin: 44px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 860px) {
  .sb-why__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 40px;
  }

  /* One column when the list runs beside the sticky picture instead of across
     the section: three of these in half the width would set two words to a
     line. The margin goes because .ind-stick supplies the gap above it. */
  .sb-why__grid--stack {
    grid-template-columns: minmax(0, 1fr);
    gap: 30px;
  }
}

.sb-why__grid--stack { margin-top: 0; }

.sb-why__item {
  padding-top: 22px;
  border-top: 2px solid #E4EAF5;
}

/* Icon and heading on one row. align-items: center rather than baseline: a
   heading that wraps to two lines would otherwise pull the mark down to sit
   beside the first line only, and it belongs to the whole heading. */
.sb-why__title {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 0;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 20px;
  font-weight: 700;
  line-height: 1.3;
  color: #0B1B33;
}

/* min-width: 0, or the words never wrap.
   A flex item's min-width is auto, which means "no narrower than your longest
   unbreakable run" — and for a run of text that is the whole line, not the
   longest word. So the heading held its full width and ran out of the card on
   any column narrower than it, rather than breaking onto a second line. */
.sb-why__label {
  min-width: 0;
}

.sb-why__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background-color: #EEF4FE;
  color: #2563EB;
}

.sb-why__icon .hs-i { width: 17px; height: 17px; }

/* Indented to the heading's left edge rather than the icon's, so the sentence
   hangs under the words it belongs to. 34px mark plus the 12px gap. */
.sb-why__text {
  margin-top: 10px;
  padding-left: 46px;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.65;
  color: #5B6472;
}

/* ---- the eight names ---- */

.sb-pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin: 40px auto 0;
  padding: 0;
  max-width: 900px;
  list-style: none;
}

.sb-pill {
  padding: 11px 20px;
  border-radius: 100px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  font-size: 15px;
  font-weight: 600;
  color: #0B1B33;
}

/* ---- the module cards' stamp ----

   The glyph and the source's lettered code share the top of the card, one at
   each end, so the stamp reads as a filing mark rather than a second title. */

.sb-mod__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

/* The icon's own bottom margin belongs to a card that stacks; here it sits in a
   row, and the row carries the space instead. */
.sb-mod__top .ind-gcard__icon { margin-bottom: 0; }

.sb-stamp {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  color: #98A2B3;
}

/* =========================================================================
   /alternatives/ — the hub

   A centred hero and eight cards. Everything else on the page (the sky, the
   badge, the shell, the ground) is already here.
   ========================================================================= */

/* ---- the hero, centred ----

   .alt-hero sets a two-column grid for the comparison pages, which have a
   screenshot to put beside the heading. This one has nothing there, so the
   copy takes the measure and centres in it. */

/* The shared hero is sized for a page that opens on a heading beside a
   screenshot: 88px of sky above the copy and 100px reserved below it, with the
   card section adding its own 100px on top of that. This page has three lines
   of type and then the cards, so all three come in.

   The top keeps the navbar clearance, which is not optional — the bar is fixed
   and overlays the page — and cuts only the sky beyond it. */
.alt-hero--hub {
  padding-top: calc(var(--nav-h) + 26px);
  padding-bottom: 24px;
}

.alt-hub { padding-top: 20px; }

@media (min-width: 768px) {
  .alt-hero--hub {
    padding-top: calc(var(--nav-h) + 40px);
    padding-bottom: 34px;
  }

  .alt-hub { padding-top: 28px; }
}

.alt-hero--hub .alt-hub__head {
  max-width: 820px;
  margin: 0 auto;
  text-align: center;
}

/* 50px, up from the 42px the shared hero rule gives it. This is the hub page's
   only heading and it sits alone above the grid, so it carries the page rather
   than introducing a column. */

/* Near-black, and set to three lines. The shared hero rule gives the lead a
   mid grey chosen for body copy on white; on these pages it sits under a large
   heading and reads as washed out. The measure is what holds the line count:
   the copy is written to about 165 characters and 620px is what turns that
   into three lines rather than four. */

.alt-hero .hs-hero__lead {
  max-width: 620px;
}

.alt-hero--hub .hs-hero__title {
  font-size: clamp(32px, 3.9vw, 50px);
}

.alt-hero--hub .hs-hero__lead {
  /* The shared rule caps the lead at 520px and pins it left, which is right
     beside a screenshot and wrong under a centred heading. */
  max-width: 660px;
  margin-left: auto;
  margin-right: auto;
}

/* ---- the cards ---- */

.alt-hub__grid {
  display: grid;
  gap: 22px;
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 620px) {
  .alt-hub__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 940px) {
  .alt-hub__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* The whole tile is the link. A reader who clicks the logo or the heading
   expects to arrive, and only the pill being clickable is a trap. */
.alt-hub__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
  position: relative;
  /* Room at the foot for the corner mark, which is absolutely positioned and
     so takes no space of its own. */
  padding: 34px 26px 76px;
  border-radius: 24px;
  border: 1px solid #DCE6FA;
  /* Pale blue clearing to white, as the reference tile has it. It replaced a
     lilac ramp: blue is the brand, and the arrow in the corner is blue. */
  background-image: linear-gradient(170deg, #F1F5FE 0%, #F5F8FE 46%, #FDFEFF 100%);
  text-align: center;
  text-decoration: none;
  transition: transform 320ms var(--ease-soft), box-shadow 320ms var(--ease-soft),
              border-color 320ms var(--ease-soft);
}

.alt-hub__card:hover {
  transform: translateY(-3px);
  border-color: rgba(37, 99, 235, 0.22);
  box-shadow: 0 30px 56px -40px rgba(21, 82, 199, 0.55);
}

/* A fixed box rather than a fixed width: eight logos of eight different
   proportions line up on their centres only if the space each one sits in is
   the same, and object-fit keeps every one inside it without distortion. */
.alt-hub__logo {
  display: grid;
  place-items: center;
  width: 100%;
  height: 54px;
  margin-bottom: 22px;
}

.alt-hub__logo img {
  max-width: 190px;
  max-height: 64%;
  width: auto;
  height: auto;
  object-fit: contain;
}

.alt-hub__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 19px;
  font-weight: 600;
  line-height: 1.25;
  color: #0B1B33;
}

.alt-hub__lead {
  margin-top: 12px;
  max-width: 30ch;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.55;
  color: #5B6472;
}

/* margin-top:auto pushes the pill to the foot, so it sits on one line across a
   row whose cards carry one, two or three lines of type above it.

   Not .btn-primary: that class is an <a>, and this pill is inside one already.
   It borrows the gradient and the radius and nothing else. */
/* The corner mark. A ring of the card's own ground sits between the disc and
   the tile's edge, which is what makes it read as sitting on top of the card
   rather than cut into its corner. */

.alt-hub__go {
  position: absolute;
  right: 22px;
  bottom: 22px;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  box-shadow:
    0 0 0 7px #F5F8FE,
    0 12px 24px -10px rgba(37, 99, 235, 0.55);
  color: #FFFFFF;
  transition: transform 320ms var(--ease-soft), box-shadow 320ms var(--ease-soft);
}

.alt-hub__go svg {
  width: 17px;
  height: 17px;
}

/* The mark is not the hover target, the card is, so it answers to the card. */
.alt-hub__card:hover .alt-hub__go {
  transform: translateY(-2px);
  box-shadow:
    0 0 0 7px #F5F8FE,
    0 18px 30px -12px rgba(37, 99, 235, 0.6);
}

/* The type above the pill and the pill itself both need the gap, and only the
   type is what varies, so the space rides on the text rather than the button. */
/* No bottom gap of its own now: the corner mark is out of the flow and the
   card's own foot padding is what holds the space under the copy. */
.alt-hub__lead { margin-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .alt-hub__card:hover { transform: none; }
}

/* ---- pricing: the two "talk to us" cards ----

   Neither is a plan, so neither looks like one: no price, no feature list, no
   filled button. A hairline card with a tinted mark, a claim, a sentence and
   one quiet action. */

.pr-seg__grid {
  display: grid;
  gap: 22px;
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 820px) {
  .pr-seg__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.pr-seg__card {
  padding: 34px 34px 32px;
  border-radius: 22px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  /* The wash sits in the top-right corner and fades out well before the copy,
     so it reads as a tint on the card rather than a panel behind the text.
     --seg is set per tone below. */
  background-image: radial-gradient(80% 70% at 100% 0%,
                    rgba(var(--seg), 0.16), rgba(var(--seg), 0) 62%);
  transition: border-color 320ms var(--ease-soft), box-shadow 320ms var(--ease-soft);
}

.pr-seg__card:hover {
  border-color: #C9DAF6;
  box-shadow: 0 26px 50px -38px rgba(21, 82, 199, 0.5);
}

.pr-seg__card--blue   { --seg: 37, 99, 235; }
.pr-seg__card--mint   { --seg: 14, 164, 122; }
/* A third tone, for the industry pages' three-card row. */
.pr-seg__card--violet { --seg: 124, 92, 246; }

/* ---- the same card, three across and clickable whole ----

   The pricing pages run two of these and put the action in a button inside the
   card. The industry pages run three, each a single destination, so the card
   itself is the link: display and height so it fills its grid cell and the
   three line up whatever their copy runs to, and the button inside is drawn
   rather than nested. */

/* .pr-seg__grid sets margin: 0 because the pricing pages put nothing above it.
   This one opens under a heading, so it takes the 44px .ind-grid takes after
   the same .ind-head — the gap every other section on these pages uses. */
.pr-seg__grid--sizes { margin-top: 44px; }

@media (min-width: 900px) {
  .pr-seg__grid--sizes { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.ind-sizes__card {
  display: flex;
  flex-direction: column;
  height: 100%;
  text-decoration: none;
}

/* The button is a span here, so it does not shrink to its text inside a flex
   column, and it is pushed to the foot so the three sit on one line. */
.ind-sizes__card .pr-seg__go {
  align-self: flex-start;
  margin-top: auto;
  padding-top: 13px;
}

.ind-sizes__card .pr-seg__text {
  margin-bottom: 26px;
}

/* The hover belongs to the card now, not to a button inside it. */
.ind-sizes__card:hover .pr-seg__go {
  transform: translateY(-2px);
  filter: saturate(1.08) brightness(1.03);
  box-shadow: 0 16px 30px -10px rgba(37, 99, 235, 0.6);
}

.ind-sizes__card:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: 3px;
}

.pr-seg__icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-bottom: 22px;
  border-radius: 50%;
  background-color: rgba(var(--seg), 0.12);
  color: rgb(var(--seg));
}

.pr-seg__icon .hs-i { width: 24px; height: 24px; }

.pr-seg__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.25;
  color: #0B1B33;
}

.pr-seg__text {
  margin-top: 12px;
  max-width: 46ch;
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.6;
  color: #5B6472;
}

/* An outline, not a filled button. Every plan card above already carries a
   filled primary, and this is the quieter path for somebody the published
   prices do not fit. */
/* The nav's Signup button, in this card. It was a blue outline with a blue
   label, which read as a secondary action on a page whose whole job is to get
   somebody to act. Same gradient, pill and lift as .btn-brand, so the two
   cannot drift apart in tone. */

.pr-seg__go {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 26px;
  padding: 13px 26px;
  border-radius: 100px;
  border: 0;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  box-shadow: 0 8px 20px -8px rgba(37, 99, 235, 0.55);
  font-size: 15px;
  font-weight: 600;
  color: #FFFFFF;
  text-decoration: none;
  transition:
    transform 300ms var(--ease-smooth),
    filter 260ms var(--ease-soft),
    box-shadow 260ms var(--ease-soft);
}

.pr-seg__go:hover {
  transform: translateY(-2px);
  filter: saturate(1.08) brightness(1.03);
  box-shadow: 0 16px 30px -10px rgba(37, 99, 235, 0.6);
  color: #FFFFFF;
}

@media (prefers-reduced-motion: reduce) {
  .pr-seg__go:hover { transform: none; }
}

/* The arrow inherits currentColor, so it flips with the label on hover and
   needs no second rule. */
.pr-seg__arrow {
  display: block;
  flex: none;
  width: 16px;
  height: 16px;
}

/* The section sits between the comparison table and the FAQ, both of which
   carry a full section's padding, so it takes less of its own. */
.pr-seg {
  padding-top: 0;
  padding-bottom: 56px;
}

@media (min-width: 768px) {
  .pr-seg { padding-bottom: 76px; }
}

@media (prefers-reduced-motion: reduce) {
  .pr-seg__card { transition: none; }
}

/* ---- desktime: "Why Businesses Choose Niyuk DeskTime" on one line ----

   .hs-what caps its measure at 760px, which is right for the lead under the
   heading and thirty pixels short for this particular heading: measured in
   Bricolage Grotesque at the 48px desktop size it wants 858px, so it broke
   after "Niyuk". The head gets the room, and the lead keeps the 760px measure
   it was tuned at rather than stretching with it.

   Scoped to this section: .hs-what is shared by seven others whose headings
   already fit. */

#dt-why .hs-what { max-width: 920px; }

#dt-why .hs-what__lead {
  max-width: 760px;
  margin-left: auto;
  margin-right: auto;
}

/* =========================================================================
   /startup-launchpad/

   Four blocks the site did not already have: the hero's second lead line, the
   two product panels, the three-column comparison, and the audience band.
   Everything else on the page (the sky, .ind-band, .ind-grid, .ind-gcard, the
   scenic band, the FAQ) is already here.
   ========================================================================= */

/* ---- hero ---- */

/* The published page sets a short line naming the platform between the h1 and
   the paragraph. Heavier than the lead under it and lighter than the heading
   over it, so the three read as a descending order rather than two headings.

   Black rather than the brand blue it ran in. The paragraph that used to sit
   under it is gone, so this is the only sentence in the hero now, and a blue
   line directly under a black h1 read as a second heading in another colour
   rather than as the line that explains the first. */
.sl-hero__sub {
  margin-top: 18px;
  max-width: 520px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.4;
  color: #0B0D12;
}

.sl-hero__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 14px;
}

/* ---- the two product panels ---- */

.sl-eco__panel {
  display: grid;
  gap: 32px;
  align-items: center;
  margin-top: 48px;
}

@media (min-width: 940px) {
  .sl-eco__panel {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 56px;
  }

  /* The second panel reverses, so two panels of the same shape do not stack as
     one long column of the same thing. Order, not direction: direction would
     also reverse the reading order for a screen reader. */
  .sl-eco__panel--flip .sl-eco__copy  { order: 2; }
  .sl-eco__panel--flip .sl-eco__media { order: 1; }
}

.sl-eco__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.25;
  color: #0B1B33;
}

.sl-eco__lead {
  margin-top: 10px;
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.6;
  color: #5B6472;
}

/* .sl-eco__title and .sl-eco__text stood here, for the heading and sentence
   each panel carried between its lead and its feature list. Both were cut on
   2026-09-01 and the rules went with them; the list title below now follows
   the lead directly, which is why its margin is the larger one. */

.sl-eco__listtitle {
  margin-top: 26px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #0B1B33;
}

.sl-eco__list {
  display: grid;
  gap: 10px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 560px) {
  .sl-eco__list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 20px; }
}

.sl-eco__list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #303845;
}

.sl-eco__list span {
  display: grid;
  place-items: center;
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  border-radius: 50%;
  background-color: #E6F6EE;
  color: #12805C;
}

.sl-eco__list .hs-i { width: 11px; height: 11px; }

.sl-eco__media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 14px;
}

/* ---- the three-column comparison ---- */

.sl-tbl-wrap {
  margin-top: 44px;
  border-radius: 20px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  overflow: hidden;
}

.sl-tbl-scroll { overflow-x: auto; }

.sl-tbl {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  text-align: left;
}

.sl-tbl th,
.sl-tbl td {
  padding: 18px 22px;
  border-bottom: 1px solid #EDF1F8;
  font-size: 15px;
  font-weight: 500;
  color: #5B6472;
  vertical-align: top;
}

.sl-tbl tbody tr:last-child th,
.sl-tbl tbody tr:last-child td { border-bottom: 0; }

.sl-tbl thead th {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15px;
  font-weight: 700;
  color: #0B1B33;
  background-color: #F6F9FD;
}

.sl-tbl tbody th {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-weight: 600;
  color: #0B1B33;
}

/* The column the table is arguing for, tinted down its whole length so the
   claim is made once by the ground rather than repeated in every cell. */
.sl-tbl__win {
  background-color: rgba(37, 99, 235, 0.05);
  color: #14315F;
  font-weight: 600;
}

.sl-tbl thead .sl-tbl__win { background-color: rgba(37, 99, 235, 0.1); }

.sl-tbl__pill {
  display: inline-block;
  margin-left: 10px;
  padding: 3px 10px;
  border-radius: 100px;
  background-color: #2563EB;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #FFFFFF;
  vertical-align: middle;
}

/* ---- the audience band ---- */

.sl-who__grid {
  display: grid;
  gap: 36px;
  align-items: center;
}

@media (min-width: 940px) {
  .sl-who__grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); gap: 56px; }
}

.sl-who__title { margin: 0; }

.sl-who__kicker {
  margin-top: 16px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 19px;
  font-weight: 700;
  color: #2563EB;
}

.sl-who__lead {
  margin-top: 12px;
  max-width: 56ch;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.65;
  color: #5B6472;
}

.sl-who__pills {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 26px 0 0;
  padding: 0;
  list-style: none;
}

.sl-who__pill {
  padding: 10px 18px;
  border-radius: 100px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  font-size: 14.5px;
  font-weight: 600;
  color: #0B1B33;
}

.sl-who__media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 14px;
}

/* ---- the customer quote ---- */

.sl-quote {
  position: relative;
  max-width: 760px;
  margin: 40px auto 0;
  padding: 40px 34px 32px;
  border-radius: 22px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  text-align: center;
}

/* Set behind the words rather than beside them: it is a texture on the card,
   not a character being read. */
.sl-quote__mark {
  position: absolute;
  top: 6px;
  left: 28px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 96px;
  line-height: 1;
  color: rgba(37, 99, 235, 0.1);
  pointer-events: none;
}

.sl-quote__text {
  position: relative;
  margin: 0;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.45;
  color: #0B1B33;
}

@media (min-width: 768px) {
  .sl-quote__text { font-size: 26px; }
}

.sl-quote__by {
  display: grid;
  gap: 2px;
  margin-top: 24px;
}

.sl-quote__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 700;
  color: #0B1B33;
}

.sl-quote__role {
  font-size: 14.5px;
  font-weight: 500;
  color: #5B6472;
}

.sl-quote__meta {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid #EDF1F8;
  font-size: 13px;
  font-weight: 500;
  color: #7C879B;
}

/* ---- warehouse: the hero cut-out sits its own way ----

   The shared .ind-hero__img geometry (50% wide, pushed 29% right) is tuned for
   a tall standing figure. This page's banner is a different shape and wants
   more width and less offset. Scoped to the page, so the other industry heroes
   are untouched. */

.ind-hero--warehouse .ind-hero__img {
  display: block;
  width: 69%;
  max-width: none;
  height: auto;
  margin-left: 14%;
  vertical-align: bottom;
}

/* Below the two-column breakpoint the shared rule already gives it the full
   width, and that is still right here. */
@media (max-width: 1023px) {
  .ind-hero--warehouse .ind-hero__img { width: 100%; margin-left: 0; }
}

/* ---- contact: the two figures beside the form ----

   The home page's device, adapted. There the pair stand at negative offsets
   either side of the dashboard plate; here .ct-head clips its overflow, so
   they sit inside the shell instead and tuck behind the card's edges. Same
   files, same bottom alignment, same reveal.

   They appear only from 1180px. Below that the gutter beside a 620px card is
   not wide enough for a standing figure, and half a person behind a form is
   worse than none. */

.ct-formwrap { position: relative; }

/* Above the figures, so the card's white ground reads as being in front. */
.ct-form { position: relative; z-index: 1; }

/* HEIGHT IS WHAT KEEPS THEM OUT FROM BEHIND THE CARD

   Both are `width: auto`, so height is the only size control and each one's
   width follows its own aspect: cast-pair.webp is 495x550 (0.90) and
   cast-woman.webp 367x550 (0.67). The pair is the wide one, and it is the one
   that decides these numbers.

   Both were PNGs at 1190x1322 and 1024x1536 until 2026-09-03. The WebPs are
   the same two aspects at a smaller size, so every number below is unchanged;
   what changed is 1.6MB of transfer becoming 54KB. They still carry alpha,
   which these need — they are cut-out figures standing on a gradient.

   The gutter they stand in does not grow with the viewport. .shell caps at
   1260 with 30px of padding, so the row is 1200 at most and the card is a
   fixed 620: (1200 - 620) / 2 = 290px either side, at every width from 1260 up.
   Below that the shell is the viewport, so at 1180 the gutter is only 250.

   At the old 440 the pair rendered 396 wide and put 111px of itself behind the
   card, which cut the second man in half; the 1440 rule took it to 500, or
   160px behind, on a gutter that had not changed. 350 renders it 315 wide, so
   it tucks 25px behind the card edge, which is the overlap the device wants. */
.ct-cast {
  display: none;
  position: absolute;
  bottom: 0;
  z-index: 0;
  width: auto;
  max-width: none;
  height: 300px;
  pointer-events: none;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}

@media (min-width: 1180px) {
  .ct-cast { display: block; }

  .ct-cast--left  { left: 0; }

  /* She stands in from the edge, where the pair stands on it.

     Both are sized by height, and she is the narrower picture: at 300 tall the
     pair renders 270 wide and she renders 200, in a gutter of 250. So at
     right: 0 the pair reaches past the card by 20px and she stops 50px short
     of it — 70px further out, which read as her having drifted away from the
     form while the pair leant into it.

     The offset is that width difference, so she keeps the same relationship to
     the card's edge that the pair has. */
  .ct-cast--right { right: 70px; }
}

/* The full 290px gutter arrives when .shell hits its cap, not at some wider
   breakpoint, so this is where they can stand taller. Above it nothing changes,
   because the gutter does not. */
@media (min-width: 1260px) {
  .ct-cast { height: 350px; }

  /* The same difference at the taller size: the pair renders 315 wide and she
     renders 233, in a gutter of 290. */
  .ct-cast--right { right: 82px; }
}

/* Slower than the shared .reveal default, matching the home page's figures.
   Doubled class so it wins on specificity rather than on source order. */
.reveal.ct-cast {
  transition:
    opacity 1100ms var(--ease-soft),
    transform 1100ms var(--ease-soft),
    filter 1100ms var(--ease-soft);
}

/* ---- technology: two chips moved ----

   The shared placement is tuned for a tall cut-out on the right of the column.
   This page's figure is a wide one that fills it, so the top-left chip comes in
   towards the middle and the top-right one drops clear of the shoulder.

   Scoped to the page: the other nine industry heroes keep the shared
   placement, and eight of them are on the default geometry it was written for. */

.ind-hero--technology .ind-chip--tl { top: 4%;  left: 46%; }
.ind-hero--technology .ind-chip--tr { top: 29%; right: 0; }

/* =========================================================================
   /about-us/

   Two blocks the site did not already have: the copy-beside-a-picture panel
   that runs three times, and the closing line under the four cards. The hero
   borrows the alternatives hub's centred head, and "We Cater" borrows the
   small-companies pill row, because both are exactly the same object.
   ========================================================================= */

.ab-split {
  display: grid;
  gap: 32px;
  align-items: center;
}

@media (min-width: 940px) {
  .ab-split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 56px;
  }

  /* Order, not direction: direction would also reverse the reading order for a
     screen reader. */
  .ab-split--flip .ab-split__copy  { order: 2; }
  .ab-split--flip .ab-split__media { order: 1; }
}

.ab-split__title { margin: 0; }

.ab-split__body {
  margin-top: 18px;
  max-width: 54ch;
  font-size: 16.5px;
  font-weight: 500;
  line-height: 1.7;
  color: #5B6472;
}

.ab-split__list {
  display: grid;
  gap: 14px;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}

.ab-split__list li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  max-width: 54ch;
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.65;
  color: #303845;
}

.ab-split__list span {
  display: grid;
  place-items: center;
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 3px;
  border-radius: 50%;
  background-color: #E6F6EE;
  color: #12805C;
}

.ab-split__list .hs-i { width: 12px; height: 12px; }

.ab-split__media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 14px;
}

/* The sentence that closes "What Niyuk Do?" on the live page. Part of that
   section rather than a section of its own, so it is set as a line under the
   cards and centred on the same measure the head above them uses. */
.ab-what__close {
  max-width: 760px;
  margin: 40px auto 0;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.7;
  color: #5B6472;
  text-align: center;
}

/* Three names, not eight, so they centre rather than filling a row. */
.ab-cater .sb-pills { max-width: 720px; }

/* ---- the growth passage, on the scenic band ----

   .hs-scenic brings its own padding (90/130px), so the section needs none of
   .section's. What it does need is text that holds up over a photograph: the
   heading goes to full ink and the paragraphs a shade darker than the grey
   they use on white, because the meadow is busier than a flat ground. */

.sb-prose-sec--scenic .sb-prose__p {
  color: #303845;
}

/* The band's fades are 180px top and bottom, so the copy sits inside them
   rather than starting in the middle of one. */
@media (min-width: 768px) {
  .sb-prose-sec--scenic { padding-top: 150px; padding-bottom: 150px; }
}

/* =========================================================================
   /comparison/ — Niyuk HR vs a competitor

   Four blocks: the hero's lead form, the feature table, the category reader on
   its dark ground, and the two "best for you" lists. Everything else on the
   page (the sky, the crumbs, the byline chip, the scenic band, the FAQ) is
   already here.
   ========================================================================= */

/* ---- the picture, where a product page puts a screenshot ----

   Square artwork in a column sized for a form, so it is capped and centred
   rather than stretched to the column: at full width it would stand taller
   than the copy beside it and push the h1 off the top of the screen. */

.cmp-hero__img {
  display: block;
  width: 100%;
  max-width: 460px;
  height: auto;
  margin-inline: auto;
  border-radius: 20px;
}

/* No picture on a phone. The hero grid stacks below 1024, so it lands under
   the h1 as a 460px square of two logos either side of a VS — which is what
   the heading directly above it already says, at the cost of a screenful
   before the reader reaches the button.

   The wrapper goes rather than just the image: an emptied column still takes
   the grid's 44px gap. Scoped to --img so the Bullhorn comparison, whose
   column holds the lead form instead, keeps it. */

@media (max-width: 767px) {
  .hs-hero__art--img {
    display: none;
  }
}

/* ---- the lead form, the fallback for a comparison with no picture ---- */

.cmp-form {
  display: grid;
  gap: 14px;
  padding: 26px 24px 24px;
  border-radius: 20px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #FFFFFF;
  box-shadow: 0 30px 70px -34px rgba(16, 24, 48, 0.4);
}

.cmp-form__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 21px;
  font-weight: 700;
  color: #0B1B33;
}

.cmp-form__go { width: 100%; justify-content: center; }

.cmp-form__note {
  font-size: 13px;
  font-weight: 500;
  color: #7C879B;
  text-align: center;
}

/* ---- the opening paragraphs and the feature table ---- */

/* Centred, and on a measure narrower than the table below it: this is the
   page's verdict rather than an article opening, and it is read as one
   statement before anyone works down twenty rows. */

.cmp-intro__copy {
  max-width: 860px;
  margin: 0 auto;
  text-align: center;
}

/* The heading belongs to the paragraphs under it, so it sits closer to them
   than the section's own top padding would leave it. */
.cmp-intro .cmp-intro__copy { margin-top: 6px; }

.cmp-intro__p {
  margin-top: 16px;
  font-size: 16.5px;
  font-weight: 500;
  line-height: 1.75;
  color: #5B6472;
}

/* The heading over the table, where a page puts one there rather than over the
   passage above it. */
.cmp-tbl__head {
  margin-top: 56px;
  text-align: center;
}

.cmp-tbl-wrap {
  margin-top: 44px;
  border-radius: 20px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  overflow: hidden;
}

.cmp-tbl-scroll { overflow-x: auto; }

.cmp-tbl {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  text-align: left;
}

.cmp-tbl th,
.cmp-tbl td {
  padding: 16px 20px;
  border-bottom: 1px solid #EDF1F8;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.5;
  color: #5B6472;
  vertical-align: top;
}

.cmp-tbl tbody tr:last-child th,
.cmp-tbl tbody tr:last-child td { border-bottom: 0; }

/* The head row centres where the body rows sit at the top. The pill beside the
   recommended column makes that cell taller than the other two, and with
   everything top-aligned the three labels sat on different lines. The body
   keeps vertical-align: top, because a two-line cell should start level with
   its neighbours, not float in the middle of them. */
.cmp-tbl thead th {
  vertical-align: middle;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15px;
  font-weight: 700;
  color: #0B1B33;
  background-color: #F6F9FD;
}

.cmp-tbl tbody th {
  width: 30%;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-weight: 600;
  color: #0B1B33;
}

/* The column the table argues for, tinted down its whole length so the claim
   is made once by the ground rather than repeated in every cell. */
.cmp-tbl__win {
  background-color: rgba(37, 99, 235, 0.05);
  color: #14315F;
  font-weight: 600;
}

.cmp-tbl thead .cmp-tbl__win { background-color: rgba(37, 99, 235, 0.1); }

.cmp-tbl__pill {
  display: inline-block;
  margin-left: 10px;
  padding: 3px 10px;
  border-radius: 100px;
  background-color: #2563EB;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #FFFFFF;
  vertical-align: middle;
}

.cmp-tbl__stamp {
  margin-top: 16px;
  font-size: 13px;
  font-weight: 500;
  color: #7C879B;
  text-align: right;
}

/* ---- the category reader ----

   A dark ground, the index sticky on the left, the write-ups scrolling past on
   the right. The green is the site's own deep ink rather than a new colour. */

/* Near-black rather than the deep green it started on, so it sits in the same
   family as the home page's showcase (#08090D) and the industry AI band
   (#0B0D12) instead of introducing a third dark ground.

   Two washes over it: brand blue entering from the top, where the heading is,
   and the teal that marks the recommended side entering from the bottom left,
   where the last panels are. Both fade out well before the middle, so the copy
   is read on flat black and the colour is felt at the edges rather than behind
   the words. */
.cmp-cats {
  position: relative;
  padding-top: 80px;
  padding-bottom: 80px;
  background-color: #08090D;
  background-image:
    radial-gradient(78% 48% at 50% 0%, rgba(59, 130, 246, 0.20), rgba(59, 130, 246, 0) 66%),
    radial-gradient(62% 46% at 4% 100%, rgba(85, 201, 180, 0.14), rgba(85, 201, 180, 0) 68%),
    linear-gradient(180deg, #0B1020 0%, #08090D 46%, #08090D 100%);
  color: #FFFFFF;
}

@media (min-width: 768px) {
  .cmp-cats { padding-top: 120px; padding-bottom: 120px; }
}

.cmp-cats__title {
  max-width: 900px;
  margin: 0 auto;
  color: #FFFFFF;
  text-align: center;
}

/* minmax(0, 1fr), not the implicit `auto` track a single-column grid gets by
   default. .cmp-cat__table declares min-width: 520px and sits inside
   .cmp-cat__scroll, which is overflow-x: auto and exists to scroll it. But
   .cmp-cat is an ordinary block, so that 520 propagates up as a min-content
   contribution, and an `auto` track will not size below it — the whole section
   was 522px wide inside a 390px phone and every paragraph in it ran off the
   right-hand edge. A 0 minimum lets the track take the column's width and hands
   the overflow back to the scroller that was built for it. */

.cmp-cats__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 40px;
  margin-top: 56px;
}

@media (min-width: 1024px) {
  .cmp-cats__grid {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    gap: 64px;
    align-items: start;
  }
}

/* Sticky, offset by the navbar so it settles below the bar rather than under
   it. No .reveal on this box: a transform on an ancestor makes it the
   containing block and stops the sticky offset resolving against the viewport. */
@media (min-width: 1024px) {
  .cmp-cats__nav {
    position: sticky;
    top: calc(var(--nav-h) + 48px);
  }
}

.cmp-cats__nav ol {
  display: grid;
  gap: 20px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.cmp-cats__nav a {
  display: block;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.25;
  /* Dim until it is the one being read. The bullet is drawn rather than a
     list-style marker so it dims with the label. */
  color: rgba(255, 255, 255, 0.34);
  text-decoration: none;
  transition: color 260ms var(--ease-soft);
}

.cmp-cats__nav a::before {
  content: "\00B7";
  margin-right: 8px;
}

.cmp-cats__nav a:hover { color: rgba(255, 255, 255, 0.7); }
.cmp-cats__nav a.is-on { color: #FFFFFF; }

@media (min-width: 1024px) {
  .cmp-cats__nav a { font-size: 26px; }
}

/* Same 0 minimum, for the same table: this is the track the articles sit in. */
.cmp-cats__body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 64px; }

/* Clears the fixed navbar when a link in the index is followed, so the heading
   does not land underneath it. */
.cmp-cat { scroll-margin-top: calc(var(--nav-h) + 32px); }

/* The block's own heading, and it stays on screen at every width. Following a
   link in the index jumps the right column on its own, and without a heading
   over the passage that lands there the reader has only the dimmed list on
   the left to work out what they are now reading. The rule under it closes
   the heading off from the prose so the two do not read as one block. */
.cmp-cat__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
  padding-bottom: 16px;
  margin-bottom: 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  color: #FFFFFF;
}

@media (min-width: 1024px) {
  .cmp-cat__name { font-size: 28px; }
}

.cmp-cat__p {
  margin-top: 14px;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.82);
}

.cmp-cat__p:first-of-type { margin-top: 0; }

/* Each vendor's passage in a panel of its own, so the two are told apart at a
   glance rather than by reading the heading. */
.cmp-cat__side {
  margin-top: 26px;
  padding: 24px 24px 26px;
  border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background-color: rgba(255, 255, 255, 0.04);
}

/* The recommended side is marked once, by a bar down its full height. A reader
   scanning the eight categories should be able to tell the two panels apart
   without reading either heading, and a rule at the edge does that where a
   slightly different tint does not.

   overflow: hidden so the bar is clipped to the card's radius instead of
   squaring off its corners. The bar is a pseudo-element rather than a thick
   border-left, because a border that heavy fights the 1px on the other three
   sides and the radius bends it into a wedge. */
.cmp-cat__side--niyuk {
  position: relative;
  overflow: hidden;
  border-color: rgba(120, 220, 180, 0.28);
  background-color: rgba(120, 220, 180, 0.07);
}

.cmp-cat__side--niyuk::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 4px;
  background-image: linear-gradient(180deg, #55C9B4 0%, #3B82F6 100%);
}

/* ---- the VS mark between two panels ----

   A disc with a slash running through it, the way a fixture card marks two
   sides against each other. The slash is a pseudo-element behind the disc
   rather than a border on it, so it can overshoot at both ends the way the
   design does.

   It sits in the same column flow as the panels and pulls the gap in around
   itself with negative margins, so the two panels stay their normal distance
   apart and the mark reads as sitting between them rather than adding a third
   row of height. */

.cmp-cat__vs {
  position: relative;
  z-index: 0;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  /* margin-inline, not justify-self: the article this sits in is a block
     container, and justify-self only means something to a grid or flex item.
     display:grid makes the span block-level, so auto margins centre it. */
  margin-top: 6px;
  margin-bottom: 6px;
  margin-inline: auto;
  border-radius: 50%;
  background-image: linear-gradient(135deg, #55C9B4 0%, #3B82F6 100%);
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 0.02em;
  /* Near-black, matching the section's own ground: the disc is a bright
     gradient, so the letters have to be the dark, and the old value was the
     green this section used before. */
  color: #08090D;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}

.cmp-cat__vs::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 50%;
  left: 50%;
  width: 108px;
  height: 3px;
  border-radius: 2px;
  background-image: linear-gradient(90deg, #55C9B4 0%, #3B82F6 100%);
  transform: translate(-50%, -50%) rotate(-45deg);
}

@media (prefers-reduced-motion: no-preference) {
  .cmp-cat__vs { transition: transform 320ms var(--ease-soft); }
}

.cmp-cat__side-name {
  margin-bottom: 12px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 700;
  color: #FFFFFF;
}

.cmp-cat__scenario {
  margin-top: 26px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 700;
  color: #FFFFFF;
}

.cmp-cat__scroll {
  margin-top: 16px;
  overflow-x: auto;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.12);
}

.cmp-cat__table {
  width: 100%;
  min-width: 520px;
  border-collapse: collapse;
  text-align: left;
}

.cmp-cat__table th,
.cmp-cat__table td {
  padding: 12px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  font-size: 14.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.82);
  vertical-align: top;
}

.cmp-cat__table tbody tr:last-child th,
.cmp-cat__table tbody tr:last-child td { border-bottom: 0; }

.cmp-cat__table thead th {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-weight: 700;
  color: #FFFFFF;
  background-color: rgba(255, 255, 255, 0.06);
}

.cmp-cat__table tbody th {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-weight: 600;
  color: #FFFFFF;
}

.cmp-cat__win {
  background-color: rgba(120, 220, 180, 0.08);
  color: #FFFFFF;
}

/* The verdict, set apart from the passage above it by a rule rather than a
   box: it is the last line of the argument, not a separate claim. */
.cmp-cat__winner {
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.6;
  color: #FFFFFF;
}

.cmp-cat__winner-label { color: #7BE0BB; }

/* ---- which platform is best for you ---- */

/* ---- the verdict, in the client-story card ----

   The card's own body is a pull quote sized for one sentence. This one holds
   three paragraphs, so --prose sets them at reading size and gives them the
   measure the quote does not need. Everything else about the card is the
   card's. */

.hs-note--prose .hs-note__prose {
  margin-top: 30px;
  max-width: 720px;
}

.hs-note--prose .hs-note__prose p {
  margin-top: 16px;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.75;
  color: #303845;
}

.hs-note--prose .hs-note__prose p:first-child { margin-top: 0; }

/* The two panels are the shared before/after block; only the line under them
   is this page's. Centred on a reading measure, because it qualifies the whole
   comparison rather than one column of it. */
.cmp-fit__close {
  max-width: 820px;
  margin: 34px auto 0;
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.7;
  color: #5B6472;
  text-align: center;
}

/* ---- the sign-off under the closing button ---- */

.cmp-cta__note {
  margin-top: 24px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15px;
  font-weight: 600;
  color: #0B1B33;
}

/* ---- bullet lists and pulled review quotes inside a category ---- */

.cmp-cat__list {
  display: grid;
  gap: 10px;
  margin: 14px 0 0;
  padding: 0 0 0 20px;
  list-style: disc;
}

.cmp-cat__list li {
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.82);
}

.cmp-cat__list li::marker { color: rgba(255, 255, 255, 0.4); }

/* A review quoted from elsewhere, set apart by a rule at its edge rather than
   a box: it is somebody else's sentence inside this passage, not a panel of
   its own. */
.cmp-cat__quote {
  margin: 18px 0 0;
  padding-left: 18px;
  border-left: 2px solid rgba(255, 255, 255, 0.22);
}

.cmp-cat__quote blockquote {
  margin: 0;
  font-size: 16px;
  font-style: italic;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.9);
}

.cmp-cat__quote figcaption {
  margin-top: 8px;
  font-size: 13.5px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.55);
}

/* ---- the line above the two closing buttons ---- */

.cmp-cta__sub {
  margin-top: 26px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.4;
  color: #0B1B33;
}

/* ==========================================================================
   COMPARISON — the blocks one page has and the others do not
   The product shelf, the switchover note and the two customer quotes that
   close /comparison/niyuk-hr-vs-greyt-hr/. Drawn by
   sections/comparison/extras.php, which prints only what a page supplies, so
   nothing here reaches a comparison that sets none of it.
   ========================================================================== */

/* ---- the product shelf ---- */

/* A second heading inside the section, under the lead: the shelf is a named
   group rather than a continuation of the paragraph above it. */
.cmp-inv__sub {
  margin-top: 42px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.02em;
  color: #0B1B33;
}

.cmp-inv__grid { margin-top: 24px; }

/* The link sits on the card's floor whatever the copy above it runs to, so a
   row of three cards keeps one line of "Read more" rather than three at
   different heights. */
.cmp-inv__card {
  display: flex;
  flex-direction: column;
}

.cmp-inv__card .ind-gcard__text { flex: 1 1 auto; }

.cmp-inv__go {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
  font-size: 14.5px;
  font-weight: 600;
  color: #2563EB;
  transition: gap 240ms var(--ease-soft), color 240ms var(--ease-soft);
}

.cmp-inv__go svg {
  width: 12px;
  height: 12px;
  flex: none;
}

.cmp-inv__go:hover {
  gap: 12px;
  color: #1D4FD7;
}

/* ---- the switchover note ---- */

.cmp-switch__box {
  display: grid;
  gap: 22px;
  padding: 34px 32px;
  border-radius: 26px;
  border: 1px solid #E4EAF5;
  background:
    radial-gradient(120% 160% at 100% 0%, #EEF4FE 0%, rgba(238, 244, 254, 0) 62%),
    #FFFFFF;
}

@media (min-width: 900px) {
  .cmp-switch__box {
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 34px;
    padding: 38px 40px;
  }
}

.cmp-switch__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 26px;
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -0.02em;
  color: #0B1B33;
}

.cmp-switch__p {
  margin-top: 10px;
  max-width: 62ch;
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.65;
  color: #5B6472;
}

.cmp-switch__go { justify-self: start; }

/* ---- the two customer quotes ---- */

.cmp-voices__grid {
  display: grid;
  gap: 22px;
  margin-top: 40px;
}

@media (min-width: 800px) {
  .cmp-voices__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.cmp-voice {
  display: flex;
  padding: 30px 28px;
  border-radius: 20px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  box-shadow: 0 26px 50px -42px rgba(11, 27, 51, 0.45);
}

/* The card is the flex item; the figure inside it has to stretch so the name
   can be pushed to the floor of the taller of the two. */
.cmp-voice figure {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  margin: 0;
}

/* align-self, or the mark is stretched across the card: the figure above is a
   flex column, and a block-level image in one is stretched to the cross axis
   unless it opts out. With that off, `auto` reads the file's own 182x30. */
.cmp-voice__stars {
  align-self: flex-start;
  width: auto;
  height: 18px;
}

.cmp-voice__quote {
  flex: 1 1 auto;
  margin: 18px 0 0;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6;
  color: #0B1B33;
}

.cmp-voice__by {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid #EEF2F8;
}

.cmp-voice__name {
  display: block;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 16px;
  font-weight: 700;
  color: #0B1B33;
}

.cmp-voice__role {
  display: block;
  margin-top: 3px;
  font-size: 13.5px;
  font-weight: 500;
  color: #5B6472;
}

/* ---- the standout-features block ---- */

.cmp-stand__grid {
  display: grid;
  gap: 22px;
  margin-top: 44px;
}

@media (min-width: 860px) {
  .cmp-stand__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.cmp-stand__card {
  padding: 28px 26px 30px;
  border-radius: 20px;
  border: 1px solid #E4EAF5;
  background:
    radial-gradient(120% 150% at 0% 0%, #F4F8FF 0%, rgba(244, 248, 255, 0) 60%),
    #FFFFFF;
}

/* The cards have no titles, so the numeral is what tells a reader these are
   three of a set rather than one paragraph broken in three. */
.cmp-stand__num {
  display: block;
  margin-bottom: 14px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 26px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.04em;
  color: #A9C9FA;
}

.cmp-stand__text {
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.65;
  color: #0B1B33;
}

.cmp-stand__close {
  max-width: 74ch;
  margin: 34px auto 0;
  text-align: center;
}

.cmp-stand__close p {
  font-size: 16px;
  font-weight: 500;
  line-height: 1.7;
  color: #5B6472;
}

.cmp-stand__close p + p { margin-top: 12px; }

/* ---- the author bio ---- */

.cmp-bio__box {
  max-width: 860px;
  margin-inline: auto;
  padding: 34px 32px 30px;
  border-radius: 26px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  box-shadow: 0 26px 50px -42px rgba(11, 27, 51, 0.45);
}

.cmp-bio__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.2;
  color: #0B1B33;
}

.cmp-bio__text {
  margin-top: 14px;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.7;
  color: #5B6472;
}

.cmp-bio__by {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 22px;
  padding-top: 20px;
  border-top: 1px solid #EEF2F8;
}

.cmp-bio__face {
  flex: none;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  object-fit: cover;
}

.cmp-bio__name {
  display: block;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 17px;
  font-weight: 700;
  color: #0B1B33;
}

.cmp-bio__role {
  display: block;
  margin-top: 2px;
  font-size: 14px;
  font-weight: 500;
  color: #5B6472;
}

.cmp-bio__stamp {
  margin-top: 16px;
  font-size: 13.5px;
  font-weight: 500;
  color: #8A94A6;
}

/* A column's own line, between its heading and its list. */
.ind-shift__lead {
  margin-top: 10px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.5;
  color: #5B6472;
}

.ind-shift__col--after .ind-shift__lead { color: rgba(255, 255, 255, 0.72); }

/* The marks are buttons now, so the browser's own button styling has to go
   before .sc-dot's sizing means anything. Kept beside the rule it resets
   rather than in a global reset: nothing else on the site is a 6px button. */
@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .sc-dots li { display: flex; }

  .sc-dot {
    appearance: none;
    -webkit-appearance: none;
    padding: 0;
    border: 0;
    font: inherit;
    cursor: pointer;
  }

  /* A wider target than the mark. 6px is a fair size for something to look at
     and an unfair one to hit, so the button keeps its 6px paint and takes its
     click area from a pseudo-element that reaches the 24px either side. */
  .sc-dot {
    position: relative;
  }

  .sc-dot::after {
    content: "";
    position: absolute;
    inset: -9px -12px;
  }

  .sc-dot:hover { background-color: rgba(255, 255, 255, 0.55); }
  .sc-dot.is-on:hover { background-color: #ffffff; }

  .sc-dot:focus-visible {
    outline: 2px solid #ffffff;
    outline-offset: 4px;
  }
}

/* ==========================================================================
   SIGNUP — /signup/, choose your platform
   A heading on the sky over two product cards. The card is the link; the pill
   in it only says which corner to look at, so it is a span.
   ========================================================================== */

.su-choose {
  padding-top: calc(var(--nav-h) + 56px);
  padding-bottom: 96px;
}

.su-choose__head { text-align: center; }

/* Narrower than the shell and centred. Two cards spread across the full 1260
   put the artwork at a size that competes with the heading above it, and left
   the copy running to a measure nobody reads a two-line paragraph at. At 940
   each card is about 457 wide, which is the size the pictures were cut for. */
.su-choose__grid {
  display: grid;
  gap: 26px;
  max-width: 940px;
  margin: 52px auto 0;
}

@media (min-width: 900px) {
  .su-choose__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.su-choose__card {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 20px 20px 26px;
  border-radius: 28px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  box-shadow: 0 30px 60px -46px rgba(11, 27, 51, 0.55);
  text-decoration: none;
  transition:
    transform 320ms var(--ease-soft),
    border-color 320ms var(--ease-soft),
    box-shadow 320ms var(--ease-soft);
}

.su-choose__card:hover {
  transform: translateY(-4px);
  border-color: #C9DAF6;
  box-shadow: 0 34px 64px -40px rgba(21, 82, 199, 0.5);
}

/* A radius on the shot as well as the card: the picture reaches the card's
   inner edge, and a square corner inside a 28px one reads as a mistake. */
.su-choose__shot {
  display: block;
  overflow: hidden;
  border-radius: 18px;
}

.su-choose__shot img {
  display: block;
  width: 100%;
  height: auto;
}

.su-choose__title {
  margin-top: 24px;
  padding-inline: 6px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 23px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: #0B1B33;
}

.su-choose__text {
  flex: 1 1 auto;
  margin-top: 10px;
  padding-inline: 6px;
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.65;
  color: #5B6472;
}

/* Everything the pill looks like comes from .btn-brand. This is only where it
   sits in the card, and the arrow, which the header's button does not have. */
.su-choose__go {
  align-self: flex-start;
  margin: 22px 6px 0;
}

.su-choose__go svg {
  width: 16px;
  height: 16px;
  flex: none;
}

/* The card is the link, so the pill has to answer to the card's hover rather
   than its own: nothing is ever pointing at the span itself. */
.su-choose__card:hover .su-choose__go {
  transform: translateY(-2px);
  filter: saturate(1.08) brightness(1.03);
  box-shadow: 0 16px 30px -10px rgba(37, 99, 235, 0.6);
}

.su-choose__card:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: 4px;
}

/* The small-business hero picture, in the column the rebuilt card stack used
   to fill. Rounded like every other photograph on the site, and capped so it
   sits at the same size the stack did rather than filling the column edge to
   edge. */
.sb-hero__img {
  display: block;
  width: 100%;
  max-width: 550px;
  height: auto;
  margin-inline: auto;
  border-radius: 24px;
}

/* This page's h1 is a sentence where a product page opens on three or four
   words, and the copy sets its own turn after "Enterprise HR". At the shared
   56px that second line measures 686px against a 556px column, so it broke
   again and left "Use" alone on a third. 46px is the largest size at which the
   line the copy asks for actually fits, and the column below is widened the
   way .alt-hero widens its own for the same reason. The 34px floor and the
   5.4vw ramp are the shared ones, so a narrow screen behaves as every other
   hero does. */

.lb-hero .hs-hero__title {
  font-size: clamp(34px, 5.4vw, 46px);
  line-height: 1.1;
}

/* The lead runs black rather than the site's grey, the way it does on the
   small-business and global heroes: it is the only sentence in this hero
   besides the h1 now that the paragraph under it is gone, and it carries the
   page's argument on its own. */


@media (min-width: 1024px) {
  .lb-hero .hs-hero__grid {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  }
}

/* The large-companies hero picture. Same treatment and same 550 cap as
   .sb-hero__img, kept separate so this page's hero art can be resized without
   moving the small-business one. */
.lb-hero__img {
  display: block;
  width: 100%;
  max-width: 550px;
  height: auto;
  margin-inline: auto;
  border-radius: 24px;
}

/* The lead runs black here rather than the site's grey, the way it does on the
   small-business hero: it is the only sentence in this hero besides the h1 now
   that the two paragraphs under it are gone, and it carries the page's
   argument on its own. */


/* The global-companies hero picture. Same treatment and same 550 cap as
   .sb-hero__img and .lb-hero__img, kept separate so this page's hero art can be
   resized without moving the other two. */
.gb-hero__img {
  display: block;
  width: 100%;
  max-width: 550px;
  height: auto;
  margin-inline: auto;
  border-radius: 24px;
}

/* Section headings on phones. The scale above starts at 34px, which is more
   than a 375px screen wants once a heading runs to two or three words per
   line, so below the sm breakpoint it drops to 25px. The 640px cut is the same
   line the sm:text-[40px] step sits on, so nothing above phone width moves. */
@media (max-width: 639px) {
  .section-title {
    font-size: 25px;
  }
}

/* ==========================================================================
   PHONES — one button height

   58 is the desktop figure: a 38px arrow badge with 10 above and below it. On
   a phone that is a lot of pill for a screen where these usually run full
   width and stacked, so the four variants come down to 45 and the badge comes
   down with them — 6 + 33 + 6 is the same shape the 58 was, a size smaller.

   min-height rather than height, so a label that wraps to two lines grows the
   button instead of spilling out of it. The text-only variants have no badge
   to set their figure and sit on the 45 directly.

   Last in the file on purpose: .vsol__btn and the other per-section rules
   restate the vertical padding further up, and a media query adds no
   specificity to beat them from where the base heights are set.

   .btn-brand and .btn-nav-white are left alone — they are the navbar's own
   pills, already 45 and 46, and tuned against --nav-h.
   ========================================================================== */

@media (max-width: 767px) {
  .btn-primary,
  .btn-dark,
  .btn-solid,
  .btn-white {
    min-height: 45px;
    padding-top: 6px;
    padding-bottom: 6px;
  }

  .btn-primary .btn__icon,
  .btn-dark .btn__icon,
  .btn-solid .btn__icon,
  .btn-white .btn__icon {
    height: 33px;
    width: 33px;
  }
}

/* ==========================================================================
   HR SOFTWARE FOR CHROs — /hr-software-for-chros/

   The page is built from blocks that already exist (the hero frame, the prose
   measure, .sb-pills, .ind-grid and the scenic band), so the only thing it
   needs of its own is its hero picture.
   ========================================================================== */

/* Same treatment as .lb-hero__img and .gb-hero__img, kept separate so this
   page's hero art can be resized without moving the other two. The radius is
   not optional: no square-cornered photograph ships on this site. */

/* The lead runs black rather than the site's grey, the way it does on the
   small-business, large-companies and global heroes: it is the only passage in
   this hero besides the h1, and it carries the page's argument. */


.ch-hero__img {
  display: block;
  width: 100%;
  max-width: 550px;
  height: auto;
  margin-inline: auto;
  border-radius: 24px;
}

/* Two paragraphs inside one .vlc step, which this page's seven have and the
   three pages already running that block do not. .vlc__text pads 26 below
   itself to close the open panel; on a pair that would be the gap BETWEEN
   them as well as after them. The closing padding stays on the last one and
   the pair gets a smaller gap of its own. A step with a single paragraph is
   its own last child, so nothing there changes. */

.vlc__text:not(:last-child) {
  padding-bottom: 14px;
}

/* The sign-off under the closing band's button. Quieter than the two leads
   above it, because it is a sign-off rather than another argument, and it is
   the last thing on the page. */

.ch-cta__sign {
  margin-top: 26px;
  font-size: 15px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.72);
}

/* ==========================================================================
   CASE STUDY — /case-study/<client>/

   A rebuild of the published case study. Everything here is a case study's own
   furniture; every other block on the page is one the site already had (the
   hero frame, .sb-prose, .ind-rows, .ind-grid, .sb-why__item, the quote, the
   FAQ and the scenic band).
   ========================================================================== */

/* One column, not the product hero's two. The headline is a long sentence and
   the figures under it want the full measure rather than half of it. */

.cs-hero__copy {
  max-width: 900px;
}

/* Smaller than the product heroes' 56, because this headline is a sentence
   rather than a phrase and it has to sit on two lines, not four. */

.cs-hero__title {
  font-size: clamp(30px, 4.4vw, 46px);
}

/* ---- the reported figures ----

   Four numbers under the hero, each one stated again in the page's own prose
   further down. They are the case study's summary, which is why they sit above
   everything rather than in a band of their own halfway down. */

.cs-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 28px 20px;
  margin: 48px 0 0;
  padding: 0;
  list-style: none;
}

/* auto-fit, not a fixed four: Harnex reports four figures and TalentInsightful
   five, and a hard four would leave the fifth alone on a row of its own. The
   160 floor is what stops a sixth from squeezing the labels to one word a
   line. */

@media (min-width: 860px) {
  .cs-stats {
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 24px;
  }
}

/* A white card each, rather than the blue rule over bare copy this used to be.
   The hero stands on a photographed meadow, and a figure set straight onto it
   was reading against flowers and a footpath — legible in the pale corners and
   not in the busy ones. An opaque card gives all four the same ground wherever
   the photograph happens to be light or dark underneath them.

   Same 20px radius, hairline and shadow as .py-change and .alt-by, so these
   read as the site's cards rather than a fifth kind of box.

   The 2px blue rule goes with it: a card already has an edge, and a coloured
   line inside one reads as a divider to something. */

.cs-stat {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 20px 20px 18px;
  border-radius: 20px;
  border: 1px solid rgba(16, 24, 48, 0.08);
  background-color: #FFFFFF;
  box-shadow: 0 18px 40px -30px rgba(16, 24, 48, 0.45);
}

.cs-stat__num {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: clamp(28px, 3.4vw, 38px);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.8px;
  color: #14161D;
}

.cs-stat__label {
  font-size: 14px;
  font-weight: 500;
  line-height: 1.4;
  color: #14161D;
}

/* ---- a passage with a photograph beside it ----

   Copy first in the source order, so it is what a screen reader and a phone
   meet first. The picture takes the second column only once there is room for
   two. */

.cs-split {
  display: grid;
  gap: 32px;
  align-items: center;
}

@media (min-width: 960px) {
  .cs-split {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: 56px;
  }
}

.cs-split__copy .section-title + .sb-prose__p {
  margin-top: 24px;
}

.cs-split__img {
  display: block;
  width: 100%;
  max-width: 618px;
  height: auto;
  margin-inline: auto;
  /* No square-cornered photograph ships on this site. */
  border-radius: 18px;
}

/* ---- the three results, on the sticky stack ----

   Everything about the stacking is .hs-stack's, shared with the HRMS page's
   workflow. Three things differ here and only three.

   The tail is the hold that keeps the last card under the navbar instead of
   being carried away the moment it lands. 46vh is written for six cards, where
   the reader has already spent five card-heights of scroll getting there. With
   three it is a long empty gap before the table, so it comes in. */

.cs-stack .hs-stack__tail {
  height: 22vh;
}

@media (min-width: 768px) {
  .cs-stack .hs-stack__tail {
    height: 26vh;
  }
}

/* Space between the last card and what follows it, which the workflow stack
   never needs because nothing follows it inside its section. The heading is
   what follows now, so it carries the gap; the scroller under it is no longer
   the stack's adjacent sibling and the old form of this rule stopped matching
   when the heading went in. */

.cs-stack + .cs-table__head {
  margin-top: 80px;
}

/* The section's own foot, trimmed.

   .section pads 100 top and bottom, which is the rhythm every band on the site
   keeps and is right when a band ends on a paragraph or a grid. This one ends
   on a 253px table under a 1664px stack, and 100 of this section plus 100 of
   the next put the table over a void twice its own height. 64 here, and the
   next section's 100 still does the separating. */

@media (min-width: 768px) {
  #cs-results {
    padding-bottom: 64px;
  }
}

/* ---- the card head: number, mark and name on one line ----

   .hs-stack__inner is two columns from 768 up, a 150px gutter holding the
   numeral beside the body. Right for the workflow's one-line steps, wrong
   here: these cards carry two or three paragraphs each, and 150px plus a 48px
   gap is a sixth of the card given to a two-digit number. One column instead,
   and the numeral joins the mark and the name at the top of it. */

.cs-stack .hs-stack__inner {
  grid-template-columns: minmax(0, 1fr);
  gap: 22px;
}

.cs-stack__head {
  display: flex;
  align-items: center;
  gap: 16px;
  /* Wraps on a narrow card, so the name drops under the numeral and the mark
     rather than being squeezed to two words a line. */
  flex-wrap: wrap;
}

/* Both come down from the sizes they take when each has a line to itself: at
   68px and 52px against the name they would be the head rather than sit in
   it. */

.cs-stack .hs-stack__num {
  font-size: clamp(30px, 3.4vw, 42px);
}

.cs-stack .hs-stack__icon {
  width: 44px;
  height: 44px;
  margin-bottom: 0;
  border-radius: 13px;
}

.cs-stack .hs-stack__icon .hs-i {
  width: 22px;
  height: 22px;
}

.cs-stack .hs-stack__title {
  margin: 0;
  font-size: clamp(21px, 2.6vw, 30px);
}

/* The paragraphs take the card's full width.

   .hs-stack__text caps at 640px, which is a reading measure and is right for
   the workflow stack: there the numeral sits in a 150px column to the left, so
   the body is already narrow and 640 is most of it. Here the numeral moved up
   into the head and the body is the whole card, so the cap left a third of
   every card empty down the right-hand side. */

.cs-stack .hs-stack__text {
  max-width: none;
}

/* ---- the before-and-after table ----

   The table itself is sections/hrms/_table.php, the block the product pages
   and the comparisons run: dark head, the winning column on blue with its
   pill, a caution against each "before" and a tick against each "after". It
   brings its own .hs-table styles, so all that is left here is the heading
   standing over it.

   A hand-rolled .cs-table lived here first. It went when the shared block came
   in: two tables of the same kind, styled twice, is how two designs start. */

/* Size, weight and colour come from .section-title on the element, the same
   rule "Prime Takeaways" uses further down the page, so the two headings match
   without either repeating the other's numbers. Only the centring and the
   spacing are this heading's own. */

.cs-table__head {
  margin-top: 44px;
  text-align: center;
}

/* The shared table wrap carries its own top margin for every other use; under
   this heading it belongs to the heading, so the gap closes. */

.cs-table__head + .hs-table-wrap {
  margin-top: 18px;
}

/* ---- takeaways ----
   The line that introduces the four cards, set apart from the paragraph above
   it because it is a lead-in rather than another sentence of the argument. */

.cs-takeaways__lead {
  margin-top: 26px;
  font-weight: 600;
  color: #14161D;
}

/* ---- benefits ----

   Statements with no second line, so the item is its heading and nothing else.
   .sb-why__item pads for a paragraph that is not here; without that padding
   the four rows sit as a list rather than as four empty boxes. */

.cs-benefits .sb-why__item {
  padding-bottom: 4px;
}

/* Icon above the sentence, not beside it.

   .sb-why__title is a centred flex row, which is right where the heading is
   three or four words: the mark sits level with them. Here every heading is a
   whole sentence running to two, three or five lines, so centring put each of
   the four icons at a different height down the row and they read as scattered
   rather than as a set.

   Ranged to the top of its own column instead, so all four sit on one line
   directly under the rule, and the sentence gets the full column width rather
   than the column less 34px and a gap. */

.cs-benefits .sb-why__title {
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
}

/* ---- the criteria picture ----

   .ind-stick__img rounds to 13, which is the figure five other why-blocks use
   (industries, small, large, global and the CHRO page). Scoped here rather
   than changed there: this is one page's art being asked for a softer corner,
   not a decision about all six. */

.cs-pain__criteria .ind-stick__img {
  border-radius: 33px;
}

/* Four across, not the three .sb-why__grid gives every other list that uses
   it. There are exactly four benefits, and at three the fourth dropped onto a
   row of its own and read as an afterthought rather than one of a set.

   1024, not the grid's own 860: each of these is a whole sentence rather than
   the three or four words the small-business list carries, and a quarter of
   860 is too narrow to set one in. Between 860 and 1023 they stay three
   across, and the fourth wraps as before. */

@media (min-width: 1024px) {
  .cs-benefits {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 32px;
  }
}

/* ---- Challenges and Solution, as the two-panel shift ----

   The block is .ind-shift, shared with the industry and comparison pages. What
   differs here is only what is IN a row: everywhere else it is one short line,
   and this page argues in paragraphs, because the instruction on a rebuild is
   to carry the published copy across unchanged.

   So the row keeps its card, its mark and its tilt, and gets the type and the
   padding a paragraph needs. Scoped to .cs-shift, so the one-line lists
   elsewhere are untouched. */

.cs-shift .ind-shift__list li {
  gap: 14px;
  padding: 16px 18px;
}

/* The two parts of a row, stacked. A grid rather than a block so the gap
   between the name and its sentence is one number instead of a margin that
   has to be cancelled on the last child. */

.cs-shift__body {
  display: grid;
  gap: 5px;
  min-width: 0;
}

.cs-shift__name {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 15.5px;
  font-weight: 700;
  line-height: 1.35;
  color: #14161D;
}

.cs-shift__text {
  font-size: 14px;
  font-weight: 500;
  line-height: 1.55;
  color: #4A5568;
}

/* The mark is centred on a single line by .ind-shift__mark; against a
   paragraph it wants to sit on the first line rather than halfway down the
   block, which align-items: flex-start on the row already gives it. This is
   the nudge that lines it up with the cap height of that first line. */

.cs-shift .ind-shift__mark {
  margin-top: 2px;
}

/* Two headings, one per column, and they are the page's own <h2>s rather than
   a section heading with two <h3>s under it. The block's title rule sizes them
   already; this only stops .section-title's margins from reaching them. */

.cs-shift .ind-shift__title {
  margin-top: 0;
}

/* The solution photograph, under the pair rather than inside the blue column
   it would otherwise have to share with four lines of type. */

.cs-shift__media {
  margin-top: 40px;
  text-align: center;
}

/* ==========================================================================
   CASE STUDY HUB — /case-study/

   The alternatives hub's tile with two additions: the industry over the name
   and the three figures under it. Everything else about the card — the
   gradient, the border, the lift, the corner mark — is .alt-hub__card, so the
   two hubs stay one design and a change to that block moves both.
   ========================================================================== */

/* Taller than the vendor tile's 76: this one carries a row of figures above
   the corner mark, and the mark is absolute so it takes no space of its own. */

.cs-hub__card {
  padding-bottom: 92px;
}

/* The industry. Small, uppercase and quiet, so it labels the tile without
   competing with the name under it. */

.cs-hub__kicker {
  display: block;
  margin-bottom: 10px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #7C8798;
}

/* The three figures, on a rule under the name.

   A hard three, not auto-fit. Measured, auto-fit laid a fourth track in the
   330px column and collapsed it to zero, which left the three numbers spread
   across three quarters of the card with a gap of dead space after them. Three
   is also what every card has. */

.cs-hub__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px 10px;
  width: 100%;
  margin: 22px 0 0;
  padding: 20px 0 0;
  border-top: 1px solid #DCE6FA;
  list-style: none;
}

.cs-hub__stats li {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.cs-hub__num {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.5px;
  color: #1552C7;
}

.cs-hub__label {
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.35;
  color: #5B6472;
}

/* The hero picture. Same treatment as .ch-hero__img and .lb-hero__img, kept
   separate so this page's hero art can be resized without moving the others.
   The radius is not optional: no square-cornered photograph ships here. */

.rc-hero__img {
  display: block;
  width: 100%;
  max-width: 550px;
  height: auto;
  margin-inline: auto;
  border-radius: 24px;
}

/* ==========================================================================
   LEGAL PAGES — /privacy-policy/ and its siblings

   A document, not a landing page: one column, one reading measure, read
   straight down. No cards, no grid, no accordion. A policy has to survive
   being printed, searched and linked into, and a section a reader has to open
   is a section they can miss.
   ========================================================================== */

/* Centred, unlike every other hero on the site. A legal page has no artwork
   and no button, so there is no second column pulling the copy left, and a
   title alone on the left of a wide band reads as the top of a page that lost
   its picture. */

/* Tighter than the shared hero, top and bottom. .hs-hero clears the navbar and
   then leaves 58px, and takes 100px below from 768 up, both sized for a hero
   with artwork beside the copy and a button under it. This one is a title, a
   date and a sentence, and at those numbers it stood in a band of white with
   nothing in it. The navbar clearance itself is untouched. */

.lg-hero {
  padding-top: calc(var(--nav-h) + 38px);
  padding-bottom: 70px;
}

@media (min-width: 768px) {
  .lg-hero { padding-bottom: 70px; }
}

/* The portrait, on the one legal-layout page that has a person as its subject.
   Round and above the badge, the same shape the byline chip uses for the same
   face, so the two read as one person rather than two treatments of a photo. */

.lg-hero__frame {
  display: block;
  width: 96px;
  height: 96px;
  margin: 0 auto 22px;
  overflow: hidden;
  border-radius: 50%;
  border: 3px solid #FFFFFF;
  box-shadow: 0 18px 40px -24px rgba(16, 24, 48, 0.55);
}

.lg-hero__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.lg-hero__copy {
  /* The container's own width, not a reading measure. The opening sentence is
     1455px of Inter 500 at 16px: at the 720 this ran at, with the lead capped
     at 620 inside it, it set three lines with a short last one. Across the
     full 1200 it lands on two. */
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

/* The effective date, between the heading and the opening paragraph, which is
   where the published page puts it and the first thing a reader checks. */

.lg-hero__date {
  margin-top: 18px;
  font-size: 15px;
  font-weight: 600;
  color: #000000;
}

/* The shared rule caps the lead at 520px and pins it left, which is right
   beside artwork and wrong under a centred heading. The cap goes entirely
   here: the sentence is meant to run the width of the container, which is what
   puts it on two lines. */

.lg-hero__copy .hs-hero__lead {
  max-width: none;
  margin-inline: auto;
}

/* The terms intro on two thirds of the column.

   Its first sentence is short and its second is long, so across the full width
   the pair read as one short line adrift above a long one. 66% pulls them to a
   closer length. The privacy page keeps the full width: its first sentence
   measures 833px and would wrap at anything narrower, which is the three-line
   setting that width was widened to fix. */

.lg-hero--tc .hs-hero__lead {
  max-width: 66%;
}

/* The ground the sheet sits on. Flat, not .ind-band--tint: that is a gradient
   which has reached white by 55% of its band, which is right for a section a
   screen tall and useless under a document five thousand pixels long, where
   the sheet would simply dissolve into the page halfway down. */

.lg-body {
  background-color: #F1F5FB;
  background-image: none;
  /* 40, not .section's 100. The sheet carries its own 60 of padding inside it,
     so the band's 100 on top of that put 160px of nothing above the first
     heading and the same below the last. */
  padding-top: 40px;
  padding-bottom: 40px;
}

/* ---- the document ----

   One white sheet on that ground, which is what gives a policy the shape of a
   document rather than of a web page. The measure inside it is unchanged: the
   sheet is wider than the text so the type keeps a comfortable line length and
   the padding does the rest. */

.lg-doc {
  max-width: 880px;
  margin-inline: auto;
  padding: 40px 24px 44px;
  border-radius: 24px;
  border: 1px solid #E7ECF6;
  background-color: #FFFFFF;
  box-shadow: 0 2px 4px rgba(16, 24, 48, 0.04), 0 34px 70px -46px rgba(16, 24, 48, 0.4);
}

@media (min-width: 768px) {
  .lg-doc {
    padding: 60px 64px 66px;
    border-radius: 28px;
  }
}

.lg-sec + .lg-sec {
  margin-top: 44px;
}

.lg-sec__title {
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  /* Tops out at 22, not 26: these are the clause headings inside the document
     sheet, and at 26 they sat close enough to the page's own h1 to read as a
     second run of page titles rather than as sections of one policy. */
  font-size: clamp(21px, 2.4vw, 22px);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.3px;
  color: #14161D;
}

/* The numeral is drawn beside the heading rather than baked into the string,
   so the heading stays searchable as words. aria-hidden on the span: a screen
   reader gets "Information We Collect", and the count is visual ordering. */

.lg-sec__num {
  margin-right: 8px;
  color: #2563EB;
}

.lg-sec__p {
  margin-top: 14px;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.65;
  color: #3F4A55;
}

.lg-sec__list {
  display: grid;
  gap: 10px;
  margin: 16px 0 0;
  padding: 0 0 0 22px;
  list-style: disc;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.65;
  color: #3F4A55;
}

.lg-sec__list::marker,
.lg-sec__list li::marker {
  color: #A9C7F7;
}

.lg-sec__list strong {
  font-weight: 600;
  color: #14161D;
}

.lg-sec__address {
  margin-top: 14px;
  font-size: 16px;
  font-weight: 500;
  font-style: normal;
  line-height: 1.65;
  color: #3F4A55;
}

/* A real link, not grey text: an address you cannot mail is decoration. */

.lg-sec__link {
  font-weight: 600;
  color: #1552C7;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.lg-sec__link:hover {
  color: #0B3FA0;
}

/* The founders hero picture. Same treatment as .rc-hero__img and its siblings,
   kept separate so this page's hero art can be resized without moving the
   others. The radius is not optional: no square-cornered photograph ships. */

.fd-hero__img {
  display: block;
  width: 100%;
  max-width: 550px;
  height: auto;
  margin-inline: auto;
  border-radius: 24px;
}

/* ---- the two nav actions ----------------------------------------------

   Signup and Book a demo, both in the bar. Signup was `hidden sm:inline-flex`
   and the demo `hidden lg:inline-flex`, which meant a phone got neither — and
   the demo appeared regardless, because .btn-nav-white declares `display` far
   later in this stylesheet than .hidden does and wins at equal specificity.
   Utilities cannot govern these two, so the widths live here.

   Scoped under #site-nav so they outrank the button rules by specificity
   rather than by position, which is what went wrong the first time.

   WHY THE DEMO WAITS FOR 420px
   Measured, not guessed: at their desktop size the pair needs 464px of bar
   once the logo, the burger and the gaps are counted, and compact they still
   need 404px. Below that something has to go, and it is the demo — Signup is
   the button that was missing, and the drawer under the burger carries the
   demo at every width, so nothing becomes unreachable.
   ---------------------------------------------------------------------- */

#site-nav .nav-cta--signup {
  display: inline-flex;
}

#site-nav .nav-cta--demo {
  display: none;
}

@media (min-width: 420px) {
  #site-nav .nav-cta--demo {
    display: inline-flex;
  }
}

/* Compact until the desktop bar, where there is room for the full size. */

@media (max-width: 1023px) {
  #site-nav .nav-cta--demo {
    gap: 8px;
    padding: 10px 14px;
    font-size: 13.5px;
  }

  #site-nav .nav-cta--signup {
    padding: 11px 14px;
    font-size: 13.5px;
  }
}

/* ==========================================================================
   404 — /404.php
   The hero is .hs-hero--center, already drawn above. Only the list of
   suggestions under the buttons is new.
   ========================================================================== */

.nf-links {
  margin-top: 44px;
  padding-top: 28px;
  border-top: 1px solid rgba(16, 24, 48, 0.10);
}

/* Black rather than the grey this ran at. It is the only line introducing the
   list under it, and at #6B7280 in 13px uppercase it read as a caption on the
   block rather than as the sentence that tells you what the links are. */

.nf-links__head {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #0B0D12;
}

/* Centred and wrapping, because the block it sits in is centred and the number
   of suggestions is a content decision rather than a fixed grid. */

.nf-links__list {
  margin: 16px auto 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 12px;
  list-style: none;
}

.nf-links__list a {
  display: inline-flex;
  align-items: center;
  padding: 9px 16px;
  border-radius: 100px;
  border: 1px solid rgba(16, 24, 48, 0.12);
  background-color: #FFFFFF;
  font-size: 14px;
  font-weight: 600;
  color: #0B0D12;
  transition: border-color 240ms var(--ease-soft), color 240ms var(--ease-soft),
              transform 240ms var(--ease-smooth);
}

.nf-links__list a:hover,
.nf-links__list a:focus-visible {
  border-color: rgba(37, 99, 235, 0.45);
  color: #1D4ED8;
  transform: translate3d(0, -2px, 0);
}

@media (prefers-reduced-motion: reduce) {
  .nf-links__list a {
    transition: none;
  }

  .nf-links__list a:hover,
  .nf-links__list a:focus-visible {
    transform: none;
  }
}

/* ==========================================================================
   HRMS COST CALCULATOR — /hrms-cost-calculator/
   ========================================================================== */

.calc-sec { padding-top: 56px; }

.calc-head { margin: 0 auto 36px; max-width: 720px; text-align: center; }
.calc-head__title { margin-top: 18px; }
.calc-head__lead  { margin: 14px auto 0; max-width: 560px; color: #000000; }

.calc {
  margin: 0 auto;
  max-width: 860px;
  padding: 28px 22px 30px;
  border-radius: 24px;
  border: 1px solid rgba(16, 24, 48, 0.09);
  background-color: #FFFFFF;
  box-shadow: 0 34px 74px -46px rgba(16, 24, 48, 0.45);
}

@media (min-width: 640px) { .calc { padding: 34px 34px 36px; } }

/* ---- the progress rail ------------------------------------------------- */

.calc-rail {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  margin: 0 0 28px;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.calc-rail__step { display: flex; flex-direction: column; align-items: center; gap: 7px; }

.calc-rail__dot {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 100px;
  border: 2px solid rgba(16, 24, 48, 0.14);
  background-color: #FFFFFF;
  font-size: 14px;
  font-weight: 600;
  color: #9AA1AF;
  transition: border-color 260ms var(--ease-soft), background-color 260ms var(--ease-soft),
              color 260ms var(--ease-soft);
}

.calc-rail__label { font-size: 11px; font-weight: 600; color: #9AA1AF; text-align: center; }

.calc-rail__step.is-active .calc-rail__dot { border-color: #2563EB; color: #2563EB; }
.calc-rail__step.is-active .calc-rail__label { color: #0B0D12; }

.calc-rail__step.is-done .calc-rail__dot {
  border-color: #2563EB;
  background-color: #2563EB;
  color: #FFFFFF;
}

.calc-rail__step.is-done .calc-rail__label { color: #5A6070; }

/* ---- a panel ----------------------------------------------------------- */

.calc-kicker {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #2563EB;
}

.calc-title {
  margin-top: 8px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 24px;
  font-weight: 600;
  line-height: 1.2;
  color: #0B0D12;
}

.calc-lead { margin-top: 8px; font-size: 15px; line-height: 1.5; color: #5A6070; }

/* Animate the panel in, but only the one being shown: `hidden` is what the
   script toggles, so the rule keys off :not([hidden]) rather than a class it
   would have to add and remove as well. */

.calc-panel:not([hidden]) { animation: calc-in 340ms var(--ease-smooth) both; }

@keyframes calc-in {
  from { opacity: 0; transform: translate3d(0, 10px, 0); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .calc-panel:not([hidden]) { animation: none; }
}

/* ---- step 1 · the options --------------------------------------------- */

.calc-opts {
  margin: 22px 0 0;
  padding: 0;
  display: grid;
  gap: 10px;
  grid-template-columns: minmax(0, 1fr);
  list-style: none;
}

@media (min-width: 560px) { .calc-opts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* The radio itself is off-screen rather than display:none, so it stays
   focusable and the keyboard can still move through the group. */

.calc-opts input[type="radio"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.calc-opts label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  height: 100%;
  padding: 14px 16px;
  border-radius: 14px;
  border: 1px solid rgba(16, 24, 48, 0.12);
  background-color: #FFFFFF;
  cursor: pointer;
  transition: border-color 220ms var(--ease-soft), background-color 220ms var(--ease-soft);
}

.calc-opts label:hover { border-color: rgba(37, 99, 235, 0.42); }

.calc-opts input:checked + label {
  border-color: #2563EB;
  background-color: rgba(37, 99, 235, 0.05);
}

/* The focus ring the hidden input can no longer show for itself. */

.calc-opts input:focus-visible + label {
  outline: 2px solid #2563EB;
  outline-offset: 2px;
}

.calc-opt__name { font-size: 15px; font-weight: 600; color: #0B0D12; }
.calc-opt__note { font-size: 13px; color: #6B7280; }

.calc-opts--none { margin-top: 10px; display: block; }

/* ---- fields ------------------------------------------------------------ */

.calc-field { margin-top: 22px; }

.calc-field__label {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: 600;
  color: #0B0D12;
}

.calc-req { color: #DC2626; }

.calc-slider { display: flex; align-items: center; gap: 14px; }

.calc-slider input[type="range"] {
  flex: 1;
  min-width: 0;
  height: 6px;
  border-radius: 100px;
  background: linear-gradient(90deg, #2563EB 0%, rgba(37, 99, 235, 0.16) 0%);
  background-color: rgba(16, 24, 48, 0.10);
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  cursor: pointer;
}

.calc-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
          appearance: none;
  width: 22px;
  height: 22px;
  border-radius: 100px;
  border: 3px solid #FFFFFF;
  background-color: #2563EB;
  box-shadow: 0 2px 8px rgba(16, 24, 48, 0.28);
  cursor: pointer;
}

.calc-slider input[type="range"]::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border-radius: 100px;
  border: 3px solid #FFFFFF;
  background-color: #2563EB;
  box-shadow: 0 2px 8px rgba(16, 24, 48, 0.28);
  cursor: pointer;
}

.calc-num,
.calc-input,
.calc-select {
  width: 100%;
  padding: 11px 14px;
  border-radius: 12px;
  border: 1px solid rgba(16, 24, 48, 0.14);
  background-color: #FFFFFF;
  font-size: 15px;
  color: #0B0D12;
  transition: border-color 220ms var(--ease-soft), box-shadow 220ms var(--ease-soft);
}

.calc-num { width: 104px; flex: 0 0 auto; text-align: center; font-weight: 600; }

.calc-num:focus,
.calc-input:focus,
.calc-select:focus {
  outline: none;
  border-color: #2563EB;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.16);
}

.calc-slider__ends {
  display: flex;
  justify-content: space-between;
  margin-top: 7px;
  padding-right: 118px;
  font-size: 12px;
  color: #9AA1AF;
}

.calc-grid { display: grid; gap: 0 16px; grid-template-columns: minmax(0, 1fr); }

@media (min-width: 560px) {
  .calc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .calc-grid > .calc-field:not(.calc-field--half) { grid-column: 1 / -1; }
}

.calc-err {
  margin-top: 16px;
  padding: 11px 14px;
  border-radius: 12px;
  border: 1px solid rgba(220, 38, 38, 0.28);
  background-color: rgba(220, 38, 38, 0.06);
  font-size: 14px;
  color: #B91C1C;
}

.calc-privacy { margin-top: 14px; font-size: 13px; color: #6B7280; }

.calc-nav { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }

/* ---- step 4 · the answer ---------------------------------------------- */

.calc-hero {
  margin-top: 18px;
  padding: 26px 22px;
  border-radius: 18px;
  background-color: #0B0D12;
  background-image:
    radial-gradient(70% 55% at 50% 0%, rgba(37, 99, 235, 0.28), rgba(37, 99, 235, 0) 68%);
  text-align: center;
}

.calc-hero__lbl { font-size: 14px; color: #A7B0C0; }

.calc-hero__amt {
  margin-top: 8px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 44px;
  font-weight: 700;
  line-height: 1.05;
  color: #FFFFFF;
}

.calc-hero__even {
  margin-top: 8px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 26px;
  font-weight: 600;
  color: #FFFFFF;
}

.calc-hero__sub { margin-top: 10px; font-size: 14px; line-height: 1.5; color: #C7CEDA; }

.calc-metrics {
  margin: 14px 0 0;
  padding: 0;
  display: grid;
  gap: 10px;
  grid-template-columns: minmax(0, 1fr);
  list-style: none;
}

@media (min-width: 560px) { .calc-metrics { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.calc-metrics li {
  padding: 15px 16px;
  border-radius: 14px;
  border: 1px solid rgba(16, 24, 48, 0.10);
  background-color: #F7F9FC;
  text-align: center;
}

.calc-metrics span { display: block; font-size: 12px; color: #6B7280; }

.calc-metrics strong {
  display: block;
  margin-top: 5px;
  font-size: 19px;
  font-weight: 700;
  color: #0B0D12;
}

.calc-vs {
  display: grid;
  gap: 12px;
  margin-top: 14px;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 640px) { .calc-vs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.calc-vs__col { padding: 20px; border-radius: 16px; border: 1px solid rgba(16, 24, 48, 0.10); }
.calc-vs__col--old { background-color: #F4F5F7; }

.calc-vs__col--new {
  border-color: rgba(37, 99, 235, 0.30);
  background-color: rgba(37, 99, 235, 0.05);
}

.calc-vs__tag {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #6B7280;
}

.calc-vs__col--new .calc-vs__tag { color: #2563EB; }

.calc-vs__name { margin-top: 6px; font-size: 16px; font-weight: 600; color: #0B0D12; }
.calc-vs__sub  { margin-top: 2px; font-size: 12px; color: #6B7280; }

.calc-vs__total {
  margin-top: 10px;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 30px;
  font-weight: 700;
  color: #0B0D12;
}

.calc-vs__period { font-size: 12px; color: #6B7280; }

.calc-vs__line {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(16, 24, 48, 0.09);
  font-size: 13px;
  color: #5A6070;
}

.calc-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
  padding: 20px;
  border-radius: 16px;
  border: 1px solid rgba(16, 24, 48, 0.10);
  background-color: #FFFFFF;
}

.calc-cta__title { font-size: 17px; font-weight: 600; color: #0B0D12; }
.calc-cta__lead  { margin-top: 4px; font-size: 14px; color: #5A6070; }

.calc-assume {
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid rgba(16, 24, 48, 0.09);
}

.calc-assume__title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #6B7280;
}

.calc-assume__list { margin: 10px 0 0; padding-left: 18px; }

.calc-assume__list li { font-size: 13px; line-height: 1.55; color: #6B7280; }

.calc-cta__row { display: flex; flex-wrap: wrap; gap: 10px; }

/* ==========================================================================
   AI AGENTS — /ai-agents/

   Only what this page needed that the site did not already draw. Its hero,
   its one new card shape, and three small blocks the published page has and
   nothing else here does: a figure large enough to read as a headline, a
   headed citation list, and a ticked list of findings.
   ========================================================================== */

/* ---- hero ----

   One column and centred, like the legal pages: the published page has no
   artwork here, so there is no second column to pull the copy left. */

.ag-hero {
  padding-top: calc(var(--nav-h) + 38px);
  padding-bottom: 70px;
}

@media (min-width: 768px) {
  .ag-hero { padding-bottom: 84px; }
}

.ag-hero__copy {
  max-width: 900px;
  margin-inline: auto;
  text-align: center;
}

/* ---- the same hero, once it has a picture ----

   Centring is right for a headline standing alone and wrong beside artwork:
   ranged left, the copy and the picture read as two columns of one block. Only
   the page that supplies an image gets .ag-hero--art, so a hero without one
   keeps the centred column above.

   The measures go with it. 900 and 760 were chosen for a full-width column and
   are wider than the half this copy now occupies, so they would do nothing but
   confuse the next reader. */

.ag-hero--art .ag-hero__copy {
  max-width: none;
  margin-inline: 0;
  text-align: left;
}

.ag-hero--art .ag-hero__copy .hs-hero__lead,
.ag-hero--art .ag-hero__note {
  max-width: none;
  margin-inline: 0;
}

/* The button too. .ag-hero__cta centres its row, which is right under a
   centred headline and wrong under a ranged-left one — it left the button
   floating in the middle of the column with the copy stacked left of it. */

.ag-hero--art .ag-hero__cta {
  justify-content: flex-start;
}

/* Capped and centred in its column, the same treatment .sb-hero__img and
   .lb-hero__img get: the artwork is a 550 square and the column is wider than
   that on a large screen. */

.ag-hero__img {
  display: block;
  width: 100%;
  max-width: 550px;
  height: auto;
  margin-inline: auto;
  border-radius: 24px;
}

.ag-hero__copy .hs-hero__lead {
  max-width: none;
  margin-inline: auto;
}

/* The trust line under the pitch, not a second pitch: one step down in size
   and weight so the two paragraphs read in order rather than competing. Its
   own class, so changing it cannot move .hs-hero__lead on every other page. */

.ag-hero__note {
  max-width: 760px;
  margin: 14px auto 0;
  font-size: 15px;
  line-height: 1.65;
  color: #5A6070;
}

.ag-hero__cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 30px;
}

/* ---- the agent sequence ----

   Four panels on the site's pinned showcase. Only three things are this
   page's: the heading above the track, Niyuk GPT's subtitle, and a shared
   shape for the four screenshots. Everything else is .showcase and .sc-panel,
   unchanged. */

/* The heading sits on the showcase's own near-black ground, above the track,
   so the two read as one block rather than a titled band and a dark one. */

.ag-sc__head {
  position: relative;
  z-index: 2;
  margin-bottom: 20px;
  text-align: center;
}

@media (min-width: 1024px) {
  .ag-sc__head { margin-bottom: 8px; }
}

.ag-sc__title { color: #FFFFFF; }

.ag-sc__lead {
  margin: 14px auto 0;
  max-width: 620px;
  color: rgba(255, 255, 255, 0.66);
}

/* Niyuk GPT's subtitle, and only its. Set in the panel's own accent so it
   reads as part of the name above it rather than the start of the sentence
   below. */

.ag-sc__sub {
  margin-top: 10px;
  font-size: 16px;
  font-weight: 600;
  color: rgb(var(--tint));
}

/* It joins the panel's copy cascade rather than sitting outside it.

   Left out, it was the one thing in the column with no `is-showing` gate, so a
   step caught mid-handover showed "Your AI HR Assistant" floating alone in an
   otherwise empty column — the exact bug the note under "SHOWCASE — STEP COPY"
   describes for the eyebrow and the button.

   200ms puts it between the heading's cascade and the paragraph's 260ms, which
   is where it sits on the page. Same easing and the same two guards as its
   siblings: no transition on the way out, and a visible resting state for
   panel 01 before showcase.js has built its timeline. */

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .ag-sc__sub {
    opacity: 0;
    transform: translate3d(0, 12px, 0);
    filter: blur(4px);
    transition:
      opacity 640ms cubic-bezier(0.22, 1, 0.36, 1) 200ms,
      transform 640ms cubic-bezier(0.22, 1, 0.36, 1) 200ms,
      filter 640ms cubic-bezier(0.22, 1, 0.36, 1) 200ms;
  }

  .sc-panel.is-showing .ag-sc__sub {
    opacity: 1;
    transform: translate3d(0, 0, 0);
    filter: blur(0);
  }

  .sc-panel:not(.is-showing) .ag-sc__sub { transition: none; }

  .sc-panel.is-active:not(.is-showing) .ag-sc__sub {
    opacity: 1;
    transform: none;
    filter: none;
  }
}

/* The plates need no shape of their own. Every .liveui carries its own
   aspect-ratio, all four panels share one grid cell, and the stage is a fixed
   height with its overflow hidden — so the sequence cannot resize on a
   handover however tall a drawing is. Same as sections/showcase.php.

   .sc-panel__frame--agents and .ag-sc__img were the override the four flat
   screenshots needed and are gone with them. */

/* ---- executes ----

   The button under the two columns, centred under the pair rather than under
   either one of them. */

.ag-exec__cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 36px;
}

/* ---- the six figures ----

   .ind-gcard__stat is 19px, sized for a figure that opens a card of prose.
   These six ARE the card, so they take the size of a heading. */

/* It sits under the heading now, not over it, so the gap it needs is above.
   18 below would have pushed the figures away from the paragraph that sets
   them up. */
.ag-stats__intro { margin-top: 16px; }

/* Three classes deep because .ind-gcard--bare.ind-gcard--stat .ind-gcard__stat
   already sets 22px, and a two-class selector loses to it however far down the
   file it sits. */

.ag-stats .ind-gcard--bare.ind-gcard--stat .ind-gcard__stat {
  font-size: 32px;
  letter-spacing: -0.8px;
}

@media (min-width: 768px) {
  .ag-stats .ind-gcard--bare.ind-gcard--stat .ind-gcard__stat { font-size: 36px; }
}

/* ---- the citations ----

   The published page heads its three sources with the word "Source" and dates
   them. The row itself is .hs-source, the same one every other cited table on
   this site prints, so only the heading above it is new. */

.ag-source { margin-top: 26px; }

.ag-source__title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #6B7280;
}

.ag-source__row { margin-top: 8px; }

/* ---- the quote card's own head ----

   .hs-note__head aligns to flex-start, which is right when the title has a
   kicker under it: the two lines and the 100px portrait frame all start
   together. These two pages print no kicker — /ai-agents/ moved its date under
   the attribution and /jd-builder/ carries a byline instead — so a single line
   of title sat at the top of a 100px row and left most of that row empty above
   the quote.

   Centred against the frame rather than shortening the frame, which is shared
   with every page that does carry a kicker. */

#ag-quote .hs-note__head,
#jd-quote .hs-note__head {
  align-items: center;
}

/* ---- the junction between the impact card and the quote ----

   Both sections carry the site's own 100px rhythm, so 200px of nothing falls
   between them — and the note card below adds 52px of its own padding on top
   of that, putting 252px between two bordered boxes.

   Between two plain passages that rhythm is right; between two cards it reads
   as a hole rather than as a break, because each box already draws its own
   end. Scoped to this pair by id rather than loosened on .section, which sets
   the spacing for every page on the site. */

#ag-why   { padding-bottom: 28px; }
#ag-quote { padding-top: 28px; }

@media (min-width: 768px) {
  #ag-why   { padding-bottom: 40px; }
  #ag-quote { padding-top: 40px; }
}

/* ---- the business impact ----

   Six findings, ticked. Not cards: the section above this one is already a
   card grid, and a second would read as twelve unrelated boxes. Two columns
   from 900px, because these are short lines and one column of six across the
   full width leaves most of the row empty. */

/* A wash rather than flat white, and a shadow rather than only a hairline: the
   card sits on .ind-band's own tint, and white-on-tint with a 1px border read
   as a box drawn on the page instead of one lifted off it. The gradient runs
   from the palest blue at the top-left corner to white well before the copy,
   so it is a light on the card and never a panel behind the text. */

.ag-impact {
  max-width: 960px;
  margin: 44px auto 0;
  padding: 28px 24px;
  border-radius: 22px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  background-image:
    radial-gradient(120% 90% at 0% 0%, rgba(37, 99, 235, 0.07), rgba(37, 99, 235, 0) 58%);
  box-shadow: 0 30px 60px -46px rgba(16, 24, 48, 0.5);
}

@media (min-width: 768px) {
  .ag-impact { padding: 32px 36px; }
}

/* 20, and a rule under it. At 18 with nothing below, the heading sat level with
   the list and read as its first line rather than as its title. The rule is the
   card's own hairline carried across, which is what closes the head off from
   the findings under it. */

.ag-impact__title {
  padding-bottom: 16px;
  border-bottom: 1px solid #E7EDF7;
  font-family: 'Bricolage Grotesque', system-ui, sans-serif;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.2px;
  color: #0B1B33;
}

.ag-impact__list {
  display: grid;
  gap: 14px;
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 900px) {
  .ag-impact__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    /* 26 down and 44 across, up from 16/32. Two columns of three-line
       sentences need more air between the columns than within them, or the
       right column's first words read as the end of the left column's line. */
    gap: 26px 44px;
  }
}

.ag-impact__item {
  display: flex;
  gap: 12px;
  font-size: 15px;
  line-height: 1.6;
  /* A step darker than the 5A6070 this ran at. These are findings, not the
     caption under something else, and on a tinted card the lighter grey was
     doing the sentence no favours. */
  color: #4A5568;
}

/* The figure is the point of every line here, so it is set in the ink the
   headings use and a weight above the sentence around it. Not blue: six blue
   numbers down a card would read as six links. */

.ag-impact__fig {
  font-weight: 700;
  color: #0B1B33;
}

.ag-impact__mark {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  margin-top: 1px;
  border-radius: 999px;
  background-color: #E8F0FE;
  /* A ring, so the disc has an edge of its own against the card's own pale
     wash instead of dissolving into it. */
  box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.12);
  color: #2563EB;
}

/* ---- the quote ----

   Both lines of the caption are links on the published page. They stay the
   colour they were: a caption set in link blue would pull the eye off the
   sentence above it, which is what the block is for. */

.hs-note__by a {
  color: inherit;
  text-decoration: none;
}

.hs-note__by a:hover { text-decoration: underline; }

/* ==========================================================================
   JD BUILDER — /jd-builder/

   A tool page, so the tool is the hero: the field, the draft it returns, and
   the dialog that mails it. Everything below that band is existing site
   furniture and needs nothing here.
   ========================================================================== */

/* ---- the hero band ----

   Centred and one column: the generator sits under the headline and wants the
   full measure, so there is no second column to fill. */

.jd-hero {
  padding-top: calc(var(--nav-h) + 38px);
  padding-bottom: 64px;
}

@media (min-width: 768px) {
  .jd-hero { padding-bottom: 80px; }
}

.jd-hero__copy {
  max-width: 900px;
  margin-inline: auto;
  text-align: center;
}

.jd { margin-top: 30px; }

/* ---- the field ----

   The input and the button on one white plate, which reads as a single
   control. Stacked below 768: a button beside a field is unusable once the
   field is narrower than the words going into it. */

.jd-form {
  display: grid;
  gap: 10px;
  padding: 10px;
  border-radius: 20px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  box-shadow: 0 20px 46px -34px rgba(16, 32, 72, 0.45);
}

@media (min-width: 768px) {
  .jd-form {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    border-radius: 100px;
    padding: 8px 8px 8px 10px;
  }
}

.jd-form__input {
  width: 100%;
  min-width: 0;
  padding: 14px 16px;
  border: 0;
  border-radius: 14px;
  background-color: transparent;
  font-size: 16px;
  font-weight: 600;
  color: #0B0D12;
}

.jd-form__input::-moz-placeholder { color: #6B7280; font-weight: 500; }

.jd-form__input::placeholder { color: #6B7280; font-weight: 500; }

.jd-form__input:focus { outline: 0; }

/* The plate takes the focus ring, not the borderless field inside it, so the
   whole control reads as focused. :focus-within, so it works for the button
   too and needs no script. */
.jd-form:focus-within {
  border-color: #A9C4F2;
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.14);
}

.jd-form__go { width: 100%; }

@media (min-width: 768px) {
  .jd-form__go { width: auto; }
}

.jd-form__go[disabled] { opacity: 0.65; cursor: default; }

/* ---- the prompt chips ---- */

.jd-chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}

.jd-chip {
  padding: 7px 18px;
  border-radius: 100px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  font-size: 13.5px;
  line-height: 1.4;
  color: #0B0D12;
  cursor: pointer;
  transition: border-color 220ms var(--ease-soft), background-color 220ms var(--ease-soft);
}

.jd-chip:hover {
  border-color: #C9DAF6;
  background-color: #F5F8FE;
}

/* ---- the draft ----

   Left-aligned inside a centred hero: a job description is a document, and a
   centred one cannot be read. */

.jd-out {
  margin-top: 22px;
  padding: 22px 20px;
  border-radius: 20px;
  border: 1px solid #E4EAF5;
  background-color: #FFFFFF;
  text-align: left;
}

@media (min-width: 768px) {
  .jd-out { padding: 26px 28px; }
}

.jd-out__head {
  padding-bottom: 16px;
  border-bottom: 1px solid rgba(16, 24, 48, 0.09);
}

.jd-out__title {
  font-size: 19px;
  font-weight: 600;
  color: #0B0D12;
}

/* The API returns headings and lists, so the tags it is allowed to send are
   given a size here rather than inheriting whatever the page sets. */

.jd-out__body {
  margin-top: 18px;
  font-size: 15.5px;
  line-height: 1.7;
  color: #2C3242;
}

.jd-out__body h1,
.jd-out__body h2,
.jd-out__body h3,
.jd-out__body h4 {
  margin-top: 18px;
  font-size: 16px;
  font-weight: 600;
  color: #0B0D12;
}

/* list-style explicitly, because the site's CSS reset strips markers from
   every ul and ol. Everywhere else that is right — the site's lists are
   navigation and card grids. Here the API returns real prose lists, and
   responsibilities without bullets read as orphaned sentences. */

.jd-out__body ul,
.jd-out__body ol { margin: 10px 0 0; padding-left: 22px; }

.jd-out__body ul { list-style: disc; }
.jd-out__body ol { list-style: decimal; }

.jd-out__body li { margin-top: 4px; display: list-item; }

/* The API separates its blocks with <br/>, so a run of them lands between the
   headings and paragraphs it already spaces. Collapsed to nothing: the margins
   on the blocks themselves are what should set the rhythm. */
.jd-out__body br { display: none; }

.jd-out__body p { margin-top: 10px; }

.jd-out__err {
  margin-top: 14px;
  font-size: 14px;
  color: #B42318;
}

.jd-out__foot {
  display: flex;
  justify-content: center;
  margin-top: 22px;
  padding-top: 20px;
  border-top: 1px solid rgba(16, 24, 48, 0.09);
}

/* While a request is in flight the field is still readable but plainly not
   accepting a second one. */
.jd.is-busy .jd-form__input { color: #6B7280; }

/* ---- the mail dialog ----

   A real <dialog>. The UA centres it and paints the backdrop, so only the card
   and the fields need describing. `[open]` covers the fallback path, where the
   element is shown by removing `hidden` instead. */

.jd-modal {
  width: min(440px, calc(100vw - 32px));
  padding: 0;
  border: 0;
  border-radius: 20px;
  background-color: transparent;
}

.jd-modal::backdrop { background-color: rgba(11, 13, 18, 0.62); }

.jd-modal__card {
  position: relative;
  padding: 30px 26px 26px;
  border-radius: 20px;
  background-color: #FFFFFF;
  text-align: left;
}

.jd-modal__x {
  position: absolute;
  top: 10px;
  right: 12px;
  padding: 4px 8px;
  border: 0;
  background-color: transparent;
  font-size: 26px;
  line-height: 1;
  color: #9AA1B1;
  cursor: pointer;
}

.jd-modal__x:hover { color: #0B0D12; }

.jd-modal__title {
  font-size: 19px;
  font-weight: 600;
  text-align: center;
  color: #0B0D12;
}

.jd-modal__label {
  display: block;
  margin-top: 20px;
  font-size: 14px;
  font-weight: 500;
  color: #5A6070;
}

.jd-modal__input {
  width: 100%;
  margin-top: 8px;
  padding: 11px 14px;
  border: 1px solid #E4EAF5;
  border-radius: 12px;
  font-size: 15px;
  color: #0B0D12;
}

.jd-modal__input:focus {
  outline: 0;
  border-color: #A9C4F2;
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.14);
}

.jd-modal__go { width: 100%; margin-top: 18px; justify-content: center; }

.jd-modal__status {
  min-height: 20px;
  margin-top: 12px;
  font-size: 13.5px;
  text-align: center;
  color: #5A6070;
}

.jd-modal__status.is-good { color: #157347; }
.jd-modal__status.is-bad  { color: #B42318; }

/* The no-<dialog> fallback: the script removes `hidden`, so the element has to
   place and cover the page itself. */
.jd-modal[open]:not(:modal) {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100vw;
  height: 100vh;
  background-color: rgba(11, 13, 18, 0.62);
}

.jd-modal[open]:not(:modal) .jd-modal__card {
  width: min(440px, calc(100vw - 32px));
}

/* ---- the closing band ----

   Not the scenic photograph: this page already runs that band twice above,
   and a third would be the same picture three times on one page. A tinted
   plate instead, so the last ask still reads as an ask. */

.jd-close { background-color: #F3F6FD; }

.jd-close__body {
  max-width: 760px;
  margin-inline: auto;
  text-align: center;
}

.jd-close__lead { margin: 14px auto 0; max-width: 560px; }

.jd-close__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 26px;
}

/* The audience list beside the artwork. .ind-row is drawn for a numeral in its
   first column; these four are audiences rather than steps and carry none, so
   the row is one column here. */

.jd-rows--plain .ind-row { grid-template-columns: minmax(0, 1fr); }

/* ==========================================================================
   NIYUK GPT — the AI HR assistant drawing
   --------------------------------------------------------------------------
   /ai-agents/ showcase panel 01. Built the way .ais, .aia and .aiv are built,
   because the four run as one sequence: the shared .liveui stage under it,
   geometry as a percentage of the box, type in cqw off the container.

   The ratio is the family's 984/880 rather than the 602x468 of the screenshot
   this replaces. Four panels of four different shapes is what the run looked
   like before; matching them is most of what makes it read as one product.
   ========================================================================== */

.ngp {
  aspect-ratio: 984 / 880;
}

/* The device. A plain rounded shell, not a drawn tablet: the screenshot's
   bezel was most of its height, and inside the showcase's 560px frame that
   left the interface smaller than the copy beside it. */

.ngp__shell {
  position: absolute;
  left: 5.6%;
  top: 5.2%;
  width: 88.8%;
  height: 89.6%;
  display: flex;
  flex-direction: column;
  padding: 2.6cqw 2.9cqw 2.4cqw;
  border-radius: 2.4cqw;
  background-color: #FFFFFF;
  box-shadow:
    0 3.2cqw 6cqw -2.6cqw rgba(23, 34, 66, 0.30),
    0 0.2cqw 0.8cqw rgba(23, 34, 66, 0.07);
}

/* ---- 1. product bar ---------------------------------------------------- */

.ngp__bar {
  display: flex;
  align-items: center;
  gap: 1.1cqw;
  padding-bottom: 1.9cqw;
  border-bottom: max(1px, 0.1cqw) solid #EDEFF5;
}

.ngp__mark {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4.3cqw;
  height: 4.3cqw;
  border-radius: 1.2cqw;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  color: #FFFFFF;
}

.ngp__mark svg {
  width: 2.6cqw;
  height: 2.6cqw;
}

.ngp__brand {
  display: flex;
  flex-direction: column;
  gap: 0.25cqw;
}

.ngp__name {
  font-size: 2.5cqw;
  font-weight: 700;
  line-height: 1.15;
  color: #1B2130;
}

.ngp__role {
  font-size: 1.72cqw;
  font-weight: 500;
  line-height: 1.15;
  color: #9198A8;
}

/* ---- 2. greeting ------------------------------------------------------- */

.ngp__hello {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 3.4cqw;
}

.ngp__bot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 6.4cqw;
  height: 6.4cqw;
  border-radius: 1.8cqw;
  background-color: #E8F0FE;
  color: #2563EB;
}

.ngp__bot svg {
  width: 3.6cqw;
  height: 3.6cqw;
}

.ngp__ask {
  margin-top: 2.2cqw;
  font-size: 2.9cqw;
  font-weight: 700;
  line-height: 1.2;
  color: #1B2130;
}

.ngp__sub {
  margin-top: 0.7cqw;
  font-size: 1.85cqw;
  font-weight: 500;
  color: #9198A8;
}

/* ---- 3. the six prompts ------------------------------------------------ */

/* Two equal columns with a fixed row height, so a two-line prompt and a
   one-line prompt make cards of the same size and the grid stays a grid. */

.ngp__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 6.4cqw;
  gap: 1.35cqw;
  margin-top: 3cqw;
}

.ngp__chip {
  display: flex;
  align-items: center;
  padding: 0 1.5cqw;
  border: max(1px, 0.1cqw) solid #E9ECF3;
  border-radius: 1.1cqw;
  background-color: #FFFFFF;
  font-size: 1.78cqw;
  font-weight: 500;
  line-height: 1.32;
  color: #414A5C;
}

/* ---- 4. composer ------------------------------------------------------- */

/* margin-top:auto pins it to the bottom of the shell whatever the grid above
   measures, so the note under it never floats. */

.ngp__composer {
  display: flex;
  align-items: center;
  gap: 1.2cqw;
  margin-top: auto;
  padding: 1.3cqw 1.3cqw 1.3cqw 1.9cqw;
  border: max(1px, 0.1cqw) solid #E9ECF3;
  border-radius: 1.4cqw;
  background-color: #FBFBFD;
}

.ngp__typedwrap {
  flex: 1;
  min-width: 0;
  display: inline-block;
  font-size: 1.85cqw;
  line-height: 1.25;
  color: #A5AAB6;
  white-space: nowrap;
}

.ngp__typed {
  white-space: nowrap;
}

/* The caret only exists while the line is being typed — .is-live is the
   handover to the ambient layer, and a cursor blinking forever in a
   placeholder reads as a stuck field rather than as activity. */

.ngp__caret {
  display: inline-block;
  width: max(1px, 0.16cqw);
  height: 2.1cqw;
  margin-left: 0.24cqw;
  vertical-align: -0.4cqw;
  background-color: #2563EB;
  opacity: 0;
}

.ngp__send {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4.1cqw;
  height: 4.1cqw;
  border-radius: 1.1cqw;
  background-image: linear-gradient(150deg, #7CB0FC 0%, #3B82F6 45%, #2563EB 100%);
  color: #FFFFFF;
}

.ngp__send svg {
  width: 2.1cqw;
  height: 2.1cqw;
}

/* ---- 5. disclaimer ----------------------------------------------------- */

.ngp__note {
  margin-top: 1.5cqw;
  font-size: 1.5cqw;
  font-weight: 500;
  text-align: center;
  color: #AEB3BF;
}

/* ==========================================================================
   NIYUK GPT — SCROLL ENTRANCE
   Two ways in, one set of from-states, exactly as "AI SOURCING — SCROLL
   ENTRANCE" describes: buildGpt() in js/showcase-live.js drives a GSAP
   timeline when GSAP is present, and without it an IntersectionObserver adds
   .is-in and the transitions below run the same order off per-element delays.

   Only transform, opacity and the composer's typing clip-path are animated,
   and the shell reserves every box, so no step can shift the layout.
   ========================================================================== */

.ngp [data-ngp] {
  opacity: 0;
}

.ngp__shell {
  transform: translate3d(0, 3.4cqw, 0) scale(0.985);
}

.ngp__bar {
  transform: translate3d(0, 1.1cqw, 0);
}

.ngp__bot {
  transform: scale(0.55);
}

.ngp__ask {
  transform: translate3d(0, 1.2cqw, 0);
}

.ngp__sub {
  transform: translate3d(0, 0.8cqw, 0);
}

.ngp__chip {
  transform: translate3d(0, 1.1cqw, 0);
}

.ngp__composer {
  transform: translate3d(0, 1.4cqw, 0);
}

.ngp__typedwrap {
  clip-path: inset(0 100% 0 0);
}

.ngp__send {
  transform: scale(0.7);
}

.ngp__note {
  transform: translate3d(0, 0.6cqw, 0);
}

/* ---- fallback path: IntersectionObserver adds .is-in -------------------- */

.ngp.is-in [data-ngp] {
  opacity: 1;
  transition:
    opacity 320ms var(--ease-smooth) var(--d, 0ms),
    transform 360ms var(--ease-smooth) var(--d, 0ms),
    clip-path 410ms var(--ease-smooth) var(--d, 0ms);
}

.ngp.is-in .ngp__shell,
.ngp.is-in .ngp__bar,
.ngp.is-in .ngp__ask,
.ngp.is-in .ngp__sub,
.ngp.is-in .ngp__chip,
.ngp.is-in .ngp__composer,
.ngp.is-in .ngp__note {
  transform: translate3d(0, 0, 0);
}

.ngp.is-in .ngp__bot,
.ngp.is-in .ngp__send {
  transform: scale(1);
}

.ngp.is-in .ngp__typedwrap {
  clip-path: inset(0 0 0 0);
}

/* The six prompts arrive in reading order. --i is set by mountAll() in
   js/showcase-live.js, so the delays follow the markup and a reordered grid
   cannot leave a gap in the sequence. */

.ngp.is-in .ngp__chip {
  --d: calc(340ms + var(--i, 0) * 55ms);
}

.ngp.is-in .ngp__composer { --d: 720ms; }
.ngp.is-in .ngp__typedwrap { --d: 840ms; }
.ngp.is-in .ngp__send { --d: 980ms; }
.ngp.is-in .ngp__note { --d: 1050ms; }

@media (prefers-reduced-motion: reduce) {
  .ngp [data-ngp] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    animation: none !important;
  }

  .ngp__typedwrap {
    clip-path: none !important;
  }
}

/* ==========================================================================
   NIYUK GPT — AMBIENT LAYER ("the system is thinking")
   Starts when the entrance finishes and js/showcase-live.js adds .is-live.
   Small and slow: the panel holds the screen for a few seconds and anything
   livelier here would pull the eye off the copy beside it.
   ========================================================================== */

@keyframes ngp-breathe {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(0, -0.28cqw, 0) scale(1.004); }
}

.ngp.is-live .ngp__shell {
  animation: ngp-breathe 7.5s ease-in-out infinite;
}

@keyframes ngp-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0); }
  45%      { box-shadow: 0 0 1.6cqw 0.2cqw rgba(37, 99, 235, 0.42); }
}

.ngp.is-live .ngp__send {
  animation: ngp-glow 3.6s ease-in-out infinite;
}

/* The assistant's own mark, pulsing on the beat the send button is off, so the
   two ends of the panel take turns rather than blinking together. */

@keyframes ngp-mark {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.06); }
}

.ngp.is-live .ngp__bot {
  animation: ngp-mark 4.4s ease-in-out infinite 1.8s;
}

@media (prefers-reduced-motion: reduce) {
  .ngp.is-live .ngp__shell,
  .ngp.is-live .ngp__send,
  .ngp.is-live .ngp__bot {
    animation: none !important;
  }
}

/* ==========================================================================
   MEETING THANK YOU — /meeting-thank-you/

   Two blocks: a centred confirmation and the three downloads under it. The
   card grid, the badge and the buttons are all the site's own; what is here is
   the tick over the heading, the centring, and the small link chips inside the
   cards.
   ========================================================================== */

.ty-hero__copy {
  max-width: 720px;
  margin-inline: auto;
  text-align: center;
}

/* The mark that says it happened, before the sentence that says it. Emerald
   rather than the brand blue: this is a confirmation, and green is what the
   site already uses when something has gone right. */

.ty-hero__mark {
  position: relative;
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  margin: 0 auto 22px;
  border-radius: 50%;
  background-color: #E7F7F0;
  box-shadow: 0 0 0 8px rgba(16, 185, 129, 0.08);
  color: #0EA47A;
}

/* ---- the tick draws itself ----

   The stroke is dashed to its own length and the offset animated back to 0, so
   the line is drawn the way it would be by hand rather than appearing whole.
   The path is `m4.5 12.5 5 5 10-11` on a 24 grid: 7.07 units to the corner and
   14.87 up, so a shade under 22. 24 is that rounded up — a dasharray shorter
   than the path would leave a gap in the finished mark.

   The animation is on the path only. The span itself carries .reveal-scale,
   whose transform the site's own script drives, and a keyframe on the same
   property would fight it.

   The delay lets the disc arrive first: the mark lands, then it is ticked. */

@keyframes ty-tick {
  to { stroke-dashoffset: 0; }
}

.ty-hero__mark svg path {
  stroke-dasharray: 24;
  stroke-dashoffset: 24;
  animation: ty-tick 520ms var(--ease-smooth) 260ms forwards;
}

/* One ring, out and gone. It is drawn on a pseudo-element rather than by
   animating the box-shadow above, so the resting ring stays put while this
   travels through it. */

@keyframes ty-ring {
  from { transform: scale(1);   opacity: 0.55; }
  to   { transform: scale(1.9); opacity: 0;    }
}

.ty-hero__mark::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid rgba(16, 185, 129, 0.5);
  animation: ty-ring 1200ms var(--ease-smooth) 300ms forwards;
  pointer-events: none;
}

/* Drawn and done, for a reader who has asked for less movement: the tick is
   whole from the start and the ring never runs. */

@media (prefers-reduced-motion: reduce) {
  .ty-hero__mark svg path {
    stroke-dashoffset: 0;
    animation: none;
  }

  .ty-hero__mark::after {
    display: none;
  }
}

.ty-hero__copy .hs-hero__lead {
  max-width: none;
  margin-inline: auto;
}

.ty-hero__cta {
  display: flex;
  justify-content: center;
  margin-top: 30px;
}

/* The store buttons inside a card. Outlines, not filled: there are five of
   them across the row and five filled buttons would compete with the one the
   hero is actually asking for. They sit at the foot of the card, so the three
   line up however long the sentences above them run. */

.ty-app__links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 18px;
}

.ty-app__go {
  display: inline-flex;
  align-items: center;
  padding: 9px 16px;
  border-radius: 100px;
  border: 1px solid #D8E3F7;
  background-color: #FFFFFF;
  font-size: 13.5px;
  font-weight: 600;
  color: #0B1B33;
  text-decoration: none;
  transition:
    border-color 240ms var(--ease-soft),
    background-color 240ms var(--ease-soft),
    color 240ms var(--ease-soft);
}

.ty-app__go:hover {
  border-color: #2563EB;
  background-color: #2563EB;
  color: #FFFFFF;
}

.ty-app__go:focus-visible {
  outline: 2px solid #2563EB;
  outline-offset: 2px;
}

/* The cards hold a button row, so their contents run to the foot rather than
   stopping at the sentence. */

#ty-apps .ind-gcard {
  display: flex;
  flex-direction: column;
}

#ty-apps .ty-app__links {
  margin-top: auto;
  padding-top: 18px;
}


/* ==========================================================================
   MEETING THANK YOU — the hero standing alone
   /meeting-thank-you/ prints no navbar (2026-09-03), so the padding .hs-hero
   carries to clear the fixed bar is now clearing nothing: --nav-h is 98px and
   the section reserved that plus 58 on top, leaving 156px of empty page above
   a confirmation that should be the first thing seen.

   Replaced rather than zeroed — the block still wants air around it, it just
   does not want a navbar's worth.
   ========================================================================== */

/* Fills the screen, because nothing follows it. At 78vh the sky ended part
   way down and left a strip of bare body colour under it with no footer to
   close the page off — an unfinished edge rather than a margin. svh, not vh:
   on a phone vh is the tallest the viewport ever gets, so a 100vh block sits
   under the browser's own chrome until the address bar retracts. */

.ty-hero {
  padding-top: 72px;
  padding-bottom: 72px;
  min-height: 100svh;
  display: flex;
  align-items: center;
}

@supports not (min-height: 100svh) {
  .ty-hero { min-height: 100vh; }
}

@media (min-width: 768px) {
  .ty-hero {
    padding-top: 88px;
    padding-bottom: 88px;
  }
}


/* ==========================================================================
   PRICING — THE ADD-ON PRICE POPOVER
   The pill says an add-on exists; this says what it costs. It replaced a
   `title` attribute (2026-09-03), which waited a second, could not be styled
   and never appeared on a touch screen.

   Shown on hover AND on keyboard focus, so the price is not mouse-only.
   Announced through aria-describedby rather than relying on the drawing, which
   is why it fades with opacity instead of `display:none` or `visibility` —
   both of those take the text out of the accessibility tree.
   ========================================================================== */

.pr-addwrap {
  position: relative;
  display: inline-block;
}

/* The pill is focusable now, so it needs a focus ring of its own. */
.pr-addwrap .pr-add {
  cursor: help;
}

.pr-addwrap .pr-add:focus-visible {
  outline: 2px solid #B4761B;
  outline-offset: 2px;
}

/* Touch has no hover. A tap focuses the pill, and :focus-within above is what
   then shows the price — which is the whole reason this is not a `title`. */

.pr-add__tip {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  z-index: 20;
  padding: 6px 11px;
  border-radius: 8px;
  background-color: #22262F;
  color: #FFFFFF;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.35;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateX(-50%) translateY(4px);
  transition: opacity 160ms var(--ease-soft), transform 160ms var(--ease-soft);
  box-shadow: 0 6px 20px -6px rgba(16, 24, 48, 0.45);
}

/* The little pointer down onto the pill. */
.pr-add__tip::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  margin-left: -5px;
  border: 5px solid transparent;
  border-top-color: #22262F;
}

/* :focus-within rather than .pr-add:focus-visible. focus-visible is a browser
   heuristic about whether focus came from a keyboard, and it deliberately does
   not match focus moved by script — which also makes it the wrong hook for a
   tooltip, where any route to the pill should reveal the price. */

.pr-addwrap:hover .pr-add__tip,
.pr-addwrap:focus-within .pr-add__tip {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* THE END COLUMNS WOULD PUSH IT OFF THE TABLE
   The grid scrolls sideways inside its own container, so a popover centred on
   a pill in the first or last column can overflow that box and be clipped.
   These two anchor it to the pill's edge instead of its centre. */

.pr-grid td:first-of-type .pr-add__tip {
  left: 0;
  transform: translateX(0) translateY(4px);
}

.pr-grid td:first-of-type .pr-addwrap:hover .pr-add__tip,
.pr-grid td:first-of-type .pr-addwrap:focus-within .pr-add__tip {
  transform: translateX(0) translateY(0);
}

.pr-grid td:first-of-type .pr-add__tip::after { left: 26px; }

.pr-grid td:last-child .pr-add__tip {
  left: auto;
  right: 0;
  transform: translateX(0) translateY(4px);
}

.pr-grid td:last-child .pr-addwrap:hover .pr-add__tip,
.pr-grid td:last-child .pr-addwrap:focus-within .pr-add__tip {
  transform: translateX(0) translateY(0);
}

.pr-grid td:last-child .pr-add__tip::after { left: auto; right: 26px; }

@media (prefers-reduced-motion: reduce) {
  .pr-add__tip { transition: none; }
}


/* ---- mobile: the price is printed, not hidden behind a hover -------------
   A popover is a hover affordance, and a phone has no hover. It also lives
   inside .pr-grid-scroll, which scrolls sideways — so on a narrow screen the
   panel was being clipped by the very box it sits in.

   Below 768 the same element stops being a popover and becomes a line of text
   under the pill. Nothing is added to the markup and nothing is fetched twice:
   the price was always in the DOM, it was only positioned out of view. */

@media (max-width: 767px) {
  .pr-addwrap {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
  }

  .pr-add__tip {
    position: static;
    opacity: 1;
    transform: none;
    padding: 0;
    border-radius: 0;
    background-color: transparent;
    box-shadow: none;
    color: #B4761B;
    font-size: 10.5px;
    font-weight: 600;
    line-height: 1.3;
    /* Wraps now. nowrap is what keeps a popover on one line; as a caption in a
       182px column it would just overflow the cell. */
    white-space: normal;
    transition: none;
  }

  /* The arrow pointed at the pill from a floating panel. There is no panel. */
  .pr-add__tip::after { display: none; }

  /* Not a control any more — the price it used to reveal is already on screen,
     so there is nothing left to hover or focus for. */
  .pr-addwrap .pr-add { cursor: default; }

  /* The edge-column nudges exist to keep a floating panel inside the scroll
     box. Static text needs none of it, and left/right offsets would push the
     caption out of its own cell. */
  .pr-grid td:first-of-type .pr-add__tip,
  .pr-grid td:last-child .pr-add__tip {
    left: auto;
    right: auto;
    transform: none;
  }
}
