/* TITECH v3 · components.css: owned by the work order listed in work-orders/DESIGN-SPEC.md §1. */
/* Buttons, arrows, text links, tags, icons, cards, focus, FAQ and forms (DESIGN-SPEC §6). Text, surfaces and lines
   come only from the --ctx-* contract, so each component works on light and dark sections. Legacy rules are beaten
   by loading later at equal specificity. Hover lifts, nudges and flips use translate, rotate and scale (not transform),
   so motion.css reveals, which set transform, cannot cancel them. */

:root {
  /* Glyphs are masks, so they take currentColor. Arrows are 14px with a 1.5 stroke. */
  --cmp-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1.75 7h10.5M8.25 3l4 4-4 4'/%3E%3C/svg%3E");
  --cmp-arrow-up-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 10.5l7-7M4.75 3.5h5.75v5.75'/%3E%3C/svg%3E");
  --cmp-plus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E");
  --cmp-icon: var(--c-signal-ink);
  --cmp-ring: rgb(76 141 255 / .18);
  --cmp-invalid: var(--c-state-error);   /* brandbook error #CE3C52 */
  --cmp-card-pad: 26px;
}
/* Icons are --c-signal on dark and --c-signal-ink on light. The list is the exact set of dark sections in §5. */
:is(.hero, .page-hero, .solutions-section, .section:has(.industry-list), .cta-band, .site-footer, .section-navy) {
  --cmp-icon: var(--c-signal);
}
@media (max-width: 600px) { :root { --cmp-card-pad: 22px; } }

/* Focus: one ring in every context. The legacy hero, footer and CTA rule coloured it with --orange. */
:focus-visible { outline: 2px solid var(--ctx-focus, var(--c-signal)); outline-offset: 3px; }
.hero :focus-visible, .site-footer :focus-visible, .cta-band :focus-visible { outline-color: var(--c-signal); }
/* Buttons take the ring from their context everywhere, the hero, footer and CTA band included. */
:is(.button, .enquiry-form__submit):focus-visible { outline: 2px solid var(--ctx-focus, var(--c-signal)); outline-offset: 3px; }

/* Primary button: the owner's option B, the "inverse pill" (OWNER-DECISIONS, 2026-09-22; it replaces the §6 signal
   fill, which was hard to read). Navy with white text on light sections; white with ink text on dark ones, where it
   also lights the navy around it: faintly at rest, twice as much on hover. Contexts set the --btn-* values and the
   button rules only read them. The dark list is §5 plus the other local dark contexts, in :where() like the --ctx-*
   values in surfaces.css, so it carries no specificity. */
/* Colleague review 2026-09-29, note 9: on light sections the button is the brand blue (Deep Navy, the colour of the
   banner), not the near-black ink it was; it reads as the site's blue and still carries white text at 9.7:1. Its hover step
   is the next shade up the brandbook's ladder (--c-ink-700, Deep Navy x1.13). The white-pill values for the dark
   contexts are below and unchanged. */
:root {
  --btn-fill: var(--c-navy-600);
  --btn-fill-hover: var(--c-ink-700);
  --btn-ink: var(--c-white);
  --btn-glow: 0 0 0 0 rgb(38 67 108 / 0), 0 10px 28px -12px rgb(38 67 108 / 0);
  --btn-glow-hover: 0 0 0 0 rgb(38 67 108 / 0), 0 10px 28px -12px rgb(38 67 108 / .5);
}
:where(.hero, .page-hero, .solutions-section, .section:has(.industry-list), .cta-band, .site-footer, .section-navy,
    .featured-tile--dark, .site-header, .case-study, .proof-grid .proof-card:is(:nth-child(2), :nth-child(3))) {
  --btn-fill: #F2F5FA;
  --btn-fill-hover: var(--c-white);
  --btn-ink: var(--c-ink-950);
  --btn-glow: 0 0 0 1px rgb(255 255 255 / .05), 0 10px 32px -10px rgb(255 255 255 / .20);
  --btn-glow-hover: 0 0 0 1px rgb(255 255 255 / .10), 0 10px 32px -10px rgb(255 255 255 / .40);
}

/* Buttons. The legacy ::before fill is retired for every .button. .header-cta belongs to WO-03, so the shape and
   colour rules skip it. Height is a minimum so a label that wraps grows the pill instead of overflowing it. */
.button::before, .enquiry-form .enquiry-form__submit::before { content: none; }
.button:not(.header-cta), .enquiry-form .enquiry-form__submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 52px;
  padding: 12px 24px;
  border: 1px solid transparent;
  border-radius: var(--r-button); /* owner (2026-09-22): a 6px rounded rectangle on every button; the focus ring follows it */
  font-size: 15px;
  font-weight: 500;
  line-height: 1.4;
  transition: background-color var(--dur-hover) var(--ease-hover), border-color var(--dur-hover) var(--ease-hover), color var(--dur-hover) var(--ease-hover),
    box-shadow var(--dur-hover) var(--ease-hover), translate var(--dur-fast) var(--ease-out);
}
/* The border stays transparent (not none), so the pill keeps an edge in forced-colours mode. Hover and keyboard focus
   share the lifted state; legacy site.css set white text on both, which the full set here overrides. */
.button-primary:not(.header-cta), .button-light:not(.header-cta), .enquiry-form .enquiry-form__submit {
  border-color: transparent;
  background-color: var(--btn-fill);
  color: var(--btn-ink);
  box-shadow: var(--btn-glow);
}
:is(.button-primary, .button-light):not(.header-cta):is(:hover, :focus-visible),
.enquiry-form .enquiry-form__submit:is(:hover, :focus-visible) {
  border-color: transparent;
  background-color: var(--btn-fill-hover);
  color: var(--btn-ink);
  box-shadow: var(--btn-glow-hover);
}
.button-outline:not(.header-cta) {
  border-color: var(--ctx-line-strong);
  background-color: transparent;
  color: var(--ctx-heading);
}
.button-outline:not(.header-cta):hover {
  border-color: var(--c-signal);
  background-color: rgb(76 141 255 / .08);
  box-shadow: var(--glow-soft);
}
.button:not(.header-cta):active, .enquiry-form .enquiry-form__submit:active { translate: 0 1px; }

/* Arrows. The <span aria-hidden="true">↗</span> keeps its place in the markup but its glyph is hidden, and a 14px
   mask arrow is drawn on its ::before. Internal links get →, external and file links get ↗, as in §6. Without
   mask support the original glyph stays. */
@supports ((-webkit-mask-image: none) or (mask-image: none)) {
  :is(.button, .text-link) > span[aria-hidden="true"] {
    position: relative;
    display: inline-block;
    flex: 0 0 14px;
    width: 14px;
    height: 14px;
    border-radius: 0;
    font-size: 0;
    line-height: 0;
    vertical-align: middle; /* the zero-size glyph puts the baseline at the top edge, so inline links need this */
    transition: translate var(--dur-fast) var(--ease-out);
  }
  :is(.button, .text-link) > span[aria-hidden="true"]::before {
    content: "";
    position: absolute;
    inset: 0;
    background-color: currentColor;
    -webkit-mask: var(--cmp-arrow) center / contain no-repeat;
    mask: var(--cmp-arrow) center / contain no-repeat;
  }
  :is(a[target="_blank"], a[href$=".pdf"], a[href$=".jpg"], a[href$=".jpeg"], a[href$=".png"], a[href$=".webp"], a[href^="http"]:not([href*="titech.om"]):not([href^="http://127.0.0.1"]):not([href^="http://localhost"]), a[href^="mailto:"], a[href^="tel:"]) > span[aria-hidden="true"]::before {
    -webkit-mask-image: var(--cmp-arrow-up-right);
    mask-image: var(--cmp-arrow-up-right);
  }
  /* The hover nudge also runs when the whole card is hovered: .service-card-action is a span, not a link. */
  :is(.button, .text-link):is(:hover, :focus-visible) > span[aria-hidden="true"],
  .service-card:is(:hover, :focus-within) .service-card-action > span {
    background: none;
    color: inherit;
    translate: 3px 0;
  }
  /* RTL. Legacy flips the span with transform; the flip is redrawn here on ::before with scale, so → becomes ←
     and ↗ becomes ↖. The nudge goes toward inline-end, which is left. */
  [dir="rtl"] :is(.button, .text-link) > span[aria-hidden="true"] { transform: none; }
  [dir="rtl"] :is(.button, .text-link) > span[aria-hidden="true"]::before { scale: -1 1; }
  [dir="rtl"] :is(.button, .text-link):is(:hover, :focus-visible) > span[aria-hidden="true"],
  [dir="rtl"] .service-card:is(:hover, :focus-within) .service-card-action > span { translate: -3px 0; }
}

/* Text links: no box and no persistent underline. On hover a 1px underline grows from inline-start. */
.text-link {
  gap: 12px;
  padding: 4px 0;
  border: 0;
  border-radius: 0;
  color: var(--ctx-link);
  font-size: 15px;
  font-weight: 500;
  background-image: linear-gradient(currentColor, currentColor);
  background-position: left bottom;
  background-size: 0% 1px;
  transition: background-size var(--dur-base) var(--ease-out), color var(--dur-hover) var(--ease-hover);
}
.text-link:is(:hover, :focus-visible), .service-card:is(:hover, :focus-within) .service-card-action {
  border-color: transparent;
  color: var(--ctx-link);
  background-size: 100% 1px;
}
[dir="rtl"] .text-link { background-position: right bottom; }
/* details.css made the contact links tables, which ignore gap and centring. A block-level flex box keeps each on its own line. */
.contact-details .text-link { display: flex; width: fit-content; }
/* Legacy set white or grey link colours and 14px sizes per context. The colour now comes from --ctx-link. */
.hero .hero-meta .text-link, .section-navy .text-link, .cta-contact .text-link, .service-card-cta .text-link,
.context-cta .text-link { color: var(--ctx-link); }
.hero .hero-meta .text-link, .cta-contact .text-link, .cert-grid .cert-item .text-link, .industry-row > .text-link { font-size: 15px; }

/* Tags: mono outline pills. Plex Mono has no Arabic glyphs, so Arabic tags follow the Arabic label rules. */
.service-tags li {
  padding: 6px 10px;
  border: 1px solid var(--ctx-line);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--ctx-muted);
  font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px;
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: .08em;
  text-transform: uppercase;
}
:is([dir="rtl"], html[lang^="ar"]) .service-tags li {
  font-family: "IBM Plex Sans Arabic", "IBM Plex Sans", Tahoma, Arial, sans-serif;
  font-size: .8125rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}

/* Icons: a 48px bordered box holding a 24px line icon. The icon is the svg itself, so the box is border plus padding
   (48 - 2 - 22 = 24). The source svgs use a 32-unit viewBox, so the stroke is non-scaling to stay 1.5px on screen. */
.service-icon, svg.service-icon {
  flex: none;
  box-sizing: border-box;
  width: 48px;
  height: 48px;
  padding: 11px;
  border: 1px solid var(--ctx-line);
  border-radius: var(--r-md);
  background: transparent;
  color: var(--cmp-icon);
  stroke-width: 1.5px;
}
.service-icon :is(path, rect, circle, line, polyline, polygon, ellipse) { vector-effect: non-scaling-stroke; }
.service-icon svg { width: 24px; height: 24px; }

/* Cards (CARD_SELECTORS). Every card is a bordered surface. The two grid-qualified selectors match the specificity
   of the legacy .cert-grid and .leadership-grid rules. */
.service-card, .why-card, .capability-card, .usecase-card, .proof-card, .cert-item, .fact-card, .process-step, .leadership-card,
.cert-grid .cert-item, .leadership-grid .leadership-card {
  position: relative;
  isolation: isolate;
  overflow: visible;
  border: 1px solid var(--ctx-line);
  border-radius: var(--r-lg);
  background: var(--ctx-surface);
  /* The opacity and transform entries keep the legacy .reveal fade (site.js) working, since this list replaces it. */
  transition: opacity .65s var(--ease), transform .65s var(--ease), translate var(--dur-base) var(--ease-out),
    border-color var(--dur-hover) var(--ease-hover), box-shadow var(--dur-hover) var(--ease-hover), background-color var(--dur-hover) var(--ease-hover);
}
.why-card, .capability-card, .usecase-card, .process-step, .cert-item, .cert-grid .cert-item { padding: var(--cmp-card-pad); }
/* The legacy grids drew shared hairlines with no gap. Separate cards need one; 28px and 20px are the sibling
   .proof-grid and .cert-grid values. */
.service-grid, .process-grid, .facts-grid { gap: 28px; border: 0; }
@media (max-width: 600px) { .service-grid, .process-grid, .facts-grid { gap: 20px; } }
/* The legacy fact cards dropped their end border on the last and even cards. */
.fact-card:is(:last-child, :nth-child(2n)) { border-inline-end: 1px solid var(--ctx-line); }

/* The spotlight sits behind the content, above the surface. --mx and --my come from motion.js; without it the
   light falls at the top centre. */
.service-card::after, .why-card::after, .capability-card::after, .usecase-card::after, .proof-card::after, .cert-item::after,
.fact-card::after, .process-step::after, .leadership-card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: radial-gradient(420px circle at var(--mx, 50%) var(--my, 0%), rgb(76 141 255 / .10), transparent 60%);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-hover) var(--ease-hover);
}

/* The legacy service card lit sage green and rose 3px on hover and on focus-within. Reset it, then apply §6. */
.service-card:is(:hover, :focus-within) { background-color: var(--ctx-surface); transform: none; box-shadow: none; }
@media (hover: hover) {
  .service-card:hover, .why-card:hover, .capability-card:hover, .usecase-card:hover, .proof-card:hover, .cert-item:hover,
  .fact-card:hover, .process-step:hover, .leadership-card:hover, .cert-grid .cert-item:hover, .leadership-grid .leadership-card:hover {
    border-color: rgb(76 141 255 / .45);
    box-shadow: var(--shadow-card), var(--glow-soft);
    translate: 0 -2px;
  }
  .service-card:hover::after, .why-card:hover::after, .capability-card:hover::after, .usecase-card:hover::after,
  .proof-card:hover::after, .cert-item:hover::after, .fact-card:hover::after, .process-step:hover::after,
  .leadership-card:hover::after { opacity: 1; }
}
/* Keyboard focus on the stretched card link gets the same lit state and the §6 ring on the card. */
.service-card:has(.service-card-link:focus-visible) {
  border-color: rgb(76 141 255 / .45);
  box-shadow: var(--shadow-card);
  outline: 2px solid var(--ctx-focus, var(--c-signal));
  outline-offset: 3px;
}
.service-card:has(.service-card-link:focus-visible)::after { opacity: 1; }

/* Accent lines: 2px along the top edge, 48px wide, at inline-start and clear of the rounded corner. */
.service-card, .solution-row { --card-accent: var(--c-spec-4); }
.service-card.accent-green, .solution-row.accent-green { --card-accent: var(--c-spec-4); }
.service-card.accent-plum, .solution-row.accent-plum { --card-accent: var(--c-spec-2); }
.service-card.accent-rose, .solution-row.accent-rose { --card-accent: var(--c-spec-1); }
.service-card.accent-orange, .solution-row.accent-orange { --card-accent: var(--c-spec-3); }
.service-card::before, .proof-card::before {
  content: "";
  position: absolute;
  inset-block-start: -1px;
  inset-inline-start: var(--r-lg);
  width: 48px;
  height: 2px;
  background: var(--card-accent);
}
/* The proof cards carry no accent class, so their bar takes the spectrum. */
.proof-card::before { background: var(--g-spectrum); }
/* The process node sits on the top edge. Its ring matches the page behind the card, not the porcelain the legacy assumed. */
.process-step::before {
  inset-block-start: -4px;
  inset-inline-start: var(--cmp-card-pad);
  border-color: var(--ctx-bg);
}

/* Card text. --muted was a fixed colour, which is unreadable once a card sits on a dark section. */
.service-card p:not(.service-num), .why-card p:not(.service-num), .capability-card p, .capability-card ul, .usecase-card p,
.process-step p:not(.service-num), .proof-card p, .fact-card p:not(.fact-value), .cert-item p, .cert-item span,
.cert-grid .cert-item p + p, .leadership-grid .leadership-card p:not(.service-num):not(.leadership-role) { color: var(--ctx-body); }
.service-card p.service-num, .why-card .service-num, .process-step .service-num, .process-step > span,
.leadership-grid .leadership-card .service-num, .leadership-grid .leadership-card .leadership-role { color: var(--ctx-muted); }
.proof-card .proof-number { color: var(--ctx-heading); }
.proof-number small, .proof-number span { color: var(--ctx-muted); }
.fact-card .fact-value { color: var(--ctx-heading); }
.cert-grid .cert-item .cert-badge { border-color: var(--ctx-line); border-radius: var(--r-md); background: var(--c-white); }

/* Use cases: the need and the result lose their green tints. */
.usecase-card .usecase-need { color: var(--ctx-heading); }
.usecase-card .usecase-result {
  border: 1px solid var(--ctx-line);
  border-radius: var(--r-md);
  background: var(--ctx-tint);
  color: var(--ctx-body);
}

/* Deliverables panel and check list. */
.deliverables-panel {
  border: 1px solid var(--ctx-line);
  border-radius: var(--r-lg);
  background: var(--ctx-tint);
}
.deliverables-panel p:not(.section-kicker):not(.eyebrow) { color: var(--ctx-body); }
.check-list li { border-block-end-color: var(--ctx-line); color: var(--ctx-body); }
.check-list li::before { border-inline-start-color: var(--ctx-link); border-block-end-color: var(--ctx-link); }
.check-list strong { color: var(--ctx-heading); }

/* FAQ: hairline separators and a plus that rotates 45° when open. Legacy already rotates ::after with transform. */
.faq-item { border-block-start: 1px solid var(--ctx-line); }
.faq-item:last-child { border-block-end: 1px solid var(--ctx-line); }
.faq-item summary {
  color: var(--ctx-heading);
  font-size: var(--fs-h3);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -.01em;
  transition: color var(--dur-base) var(--ease-out);
}
.faq-item summary:is(:hover, :focus-visible) { color: var(--ctx-link); }
.faq-item p { color: var(--ctx-body); }
.faq-item summary::after { color: var(--ctx-link); }
@supports ((-webkit-mask-image: none) or (mask-image: none)) {
  .faq-item summary::after {
    content: "";
    inset-block-start: calc(50% - 12px);
    background-color: currentColor;
    font-size: 0;
    -webkit-mask: var(--cmp-plus) center / contain no-repeat;
    mask: var(--cmp-plus) center / contain no-repeat;
    transition: transform var(--dur-base) var(--ease-out);
  }
}

/* Forms. Field height is a minimum, and the textarea keeps its own. Long :not() chains match the legacy
   .enquiry-form input rules, which stack four of them. */
.contact-form-panel {
  border: 1px solid var(--ctx-line);
  border-radius: var(--r-lg);
  background: var(--ctx-surface);
}
.enquiry-form__field label, .form-field label { color: var(--ctx-heading); }
.contact-form-panel > p, .enquiry-form > p, .enquiry-form__hint, .enquiry-form__privacy, .form-note, .form-field label span { color: var(--ctx-muted); }
.enquiry-form input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]),
.enquiry-form select, .enquiry-form textarea {
  border: 1px solid var(--ctx-field-border, var(--ctx-line-strong));
  border-radius: var(--r-md);
  background: var(--ctx-surface);
  color: var(--ctx-heading);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.enquiry-form input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]),
.enquiry-form select { min-height: 52px; }
.enquiry-form input::placeholder, .enquiry-form textarea::placeholder { color: var(--ctx-muted); }
.enquiry-form input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]):focus,
.enquiry-form select:focus, .enquiry-form textarea:focus {
  border-color: var(--ctx-focus, var(--c-signal));
  box-shadow: 0 0 0 4px var(--cmp-ring);
  outline: 2px solid transparent; /* stays visible in forced-colors mode */
}
/* Invalid: red border and ring. The legacy border rule is !important, so this one has to be too. */
.enquiry-form [aria-invalid="true"] { --cmp-ring: rgb(206 60 82 / .18); border-color: var(--cmp-invalid) !important; }
.enquiry-form input[type="checkbox"] { accent-color: var(--c-signal-ink); }

/* Form messages. Sage and peach fills are retired; the state shows in the inline-start bar, and the text keeps
   full contrast (#D64545 alone is 4.4:1 on white, just under AA for small text). */
.enquiry-form__status, .form-status, .form-error {
  border: 1px solid var(--ctx-line);
  border-inline-start: 3px solid var(--c-spec-4);
  border-radius: var(--r-md);
  background: var(--ctx-tint);
  color: var(--ctx-body);
}
/* The legacy error variant is .enquiry-form__status:not(--received), (0,2,0), so it needs the full set here. */
.enquiry-form__status:not(.enquiry-form__status--received), .form-error {
  border-color: var(--ctx-line);
  border-inline-start-color: var(--cmp-invalid);
  background: var(--ctx-tint);
  color: var(--ctx-body);
}
.form-field .form-error { border: 0; background: transparent; color: var(--ctx-body); }

/* Arabic FAQ questions: heading line height is the Latin 1.2 plus 0.15 (§3). Legacy forced 1.65 under [dir="rtl"]. */
[dir="rtl"] .faq-item summary { letter-spacing: 0; line-height: 1.35; }

/* Reduced motion: state changes stay, movement goes. Card lifts, arrow nudges and the press offset are movement. */
@media (prefers-reduced-motion: reduce) {
  .service-card:hover, .why-card:hover, .capability-card:hover, .usecase-card:hover, .proof-card:hover, .cert-item:hover,
  .fact-card:hover, .process-step:hover, .leadership-card:hover, .cert-grid .cert-item:hover, .leadership-grid .leadership-card:hover,
  .button:not(.header-cta):active, .enquiry-form .enquiry-form__submit:active { translate: none; }
  :is(.button, .text-link):is(:hover, :focus-visible) > span[aria-hidden="true"],
  .service-card:is(:hover, :focus-within) .service-card-action > span,
  [dir="rtl"] :is(.button, .text-link):is(:hover, :focus-visible) > span[aria-hidden="true"],
  [dir="rtl"] .service-card:is(:hover, :focus-within) .service-card-action > span { translate: none; }
}

/* Print: legacy print rules force white paper and inherited link colours, so a filled pill prints as an outline. */
@media print {
  .button-primary:not(.header-cta), .button-light:not(.header-cta), .enquiry-form .enquiry-form__submit {
    border-color: currentColor;
    background: none;
    box-shadow: none;
  }
}

/* Forced colours drop background-color, which would erase the mask glyphs. */
@media (forced-colors: active) {
  :is(.button, .text-link) > span[aria-hidden="true"]::before, .faq-item summary::after {
    forced-color-adjust: none;
    background-color: CanvasText;
  }
}

/* Owner request (2026-09-22): the proof cards form a checkerboard, light/dark then dark/light (the grid is two
   columns at every width). The dark cards are local dark contexts, so their contents follow the dark --ctx-* values.
   They are the banner's navy and aurora with a 1px spectrum edge, like the dark featured tiles.
   WO-22a: the card sits in a light section, so it carries the dark spectrum tints and the dark --ctx-* values
   itself, and the brandbook's Gradient 3 wash is the first (topmost) layer. Five layers now: the wash, the
   banner's three, and the spectrum, which is the only one painted under the border. */
.proof-grid .proof-card:is(:nth-child(2), :nth-child(3)) {
  --c-spec-1-rgb: 227 185 192;
  --c-spec-2-rgb: 193 182 195;
  --c-spec-3-rgb: 168 180 196;
  --c-spec-4-rgb: 192 213 195;
  --c-spec-1: rgb(var(--c-spec-1-rgb));
  --c-spec-2: rgb(var(--c-spec-2-rgb));
  --c-spec-3: rgb(var(--c-spec-3-rgb));
  --c-spec-4: rgb(var(--c-spec-4-rgb));
  --g-spectrum: linear-gradient(90deg, rgb(var(--c-spec-1-rgb)) 0%, rgb(var(--c-spec-2-rgb)) 34%, rgb(var(--c-spec-3-rgb)) 67%, rgb(var(--c-spec-4-rgb)) 100%);
  --g-spectrum-soft: linear-gradient(90deg, rgb(var(--c-spec-1-rgb) / .45), rgb(var(--c-spec-2-rgb) / .45), rgb(var(--c-spec-3-rgb) / .45), rgb(var(--c-spec-4-rgb) / .45));
  --ctx-bg: var(--c-banner);
  --ctx-surface: rgb(255 255 255 / .05);
  --ctx-heading: #F4F7FB;
  --ctx-body: #D3DCE8;
  --ctx-muted: #BCC8D5;
  --ctx-line: rgb(255 255 255 / .12);
  --ctx-link: var(--c-signal-soft);
  --ctx-focus: var(--c-signal-soft);
  border: 1px solid transparent;
  background-color: var(--c-banner);
  background-image: var(--g-card-wash), var(--bg-banner), var(--g-spectrum-soft);
  background-origin: padding-box, padding-box, padding-box, padding-box, border-box;
  background-clip: padding-box, padding-box, padding-box, padding-box, border-box;
  color: var(--ctx-body);
}
/* The brandbook's supporting gradient (Gradient 3, green to blue) on the solution cards, which are the other dark
   card surface. It is a wash, not a panel: the sage is gone before the middle of the card. */
.solutions-section .service-card {
  background-image: var(--g-card-wash);
}

/* Architect (owner request): hover colour and glow changes fade over --dur-hover, also for visitors who prefer
   reduced motion. The legacy site.css cuts every transition to .01ms with !important under reduced motion;
   colour and glow are not movement, so they are restored here (the only way to beat a legacy !important is
   another one). Movement stays off: the transition list below names no transform, translate or size property. */
@media (prefers-reduced-motion: reduce) {
  :is(.button, .enquiry-form__submit, .text-link, .nav-link, .desktop-nav a, .language-link, .menu-toggle, .faq-item summary,
      .service-card, .why-card, .capability-card, .usecase-card, .proof-card, .cert-item, .fact-card, .process-step, .leadership-card),
  :is(.service-card, .why-card, .capability-card, .usecase-card, .proof-card, .cert-item, .fact-card, .process-step, .leadership-card)::after {
    transition-property: color, background-color, border-color, box-shadow, opacity !important;
    transition-duration: var(--dur-hover) !important;
    transition-timing-function: var(--ease-hover) !important;
  }
}

/* Owner request (2026-09-22): four smaller proof cards in a 2x2 grid. The legacy theme paints whichever card is
   last in navy (details.css:194-196); with four cards that would be the 4th, so it is reset to a normal card. */
.proof-grid .proof-card:last-child:not(:nth-child(2)) { background: var(--ctx-surface); border-color: var(--ctx-line); }
.proof-grid .proof-card:last-child:not(:nth-child(2)) :is(.proof-number, .proof-label) { color: var(--ctx-heading); }
.proof-grid .proof-card:last-child:not(:nth-child(2)) p:not(.proof-number) { color: var(--ctx-body); }
.proof-grid .proof-card { --cmp-card-pad: clamp(20px, 2vw, 28px); padding: var(--cmp-card-pad); }
.proof-grid .proof-card .proof-number { font-size: clamp(2.5rem, 1.7rem + 2.2vw, 3.75rem); line-height: 1; margin-block-end: 14px; }
.proof-grid .proof-card p:not(.proof-number) { font-size: .9375rem; line-height: 1.55; }
