/* Hallmark · checked: 2026-10-22 · genre: modern-minimal (inferred)
 * built: the project · redesign: polish · v2.0.0
 * scope: shared UI; existing layout, brand, artwork and content retained.
 * Full legacy gate compliance is not claimed; see .hallmark/review.json. */
/* ==========================================================================
   Vamocles — base: reset, type, layout primitives, motion system
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 24px);
  background: var(--paper);
  hanging-punctuation: first last;
  overflow-x: clip;
}
/* A full-width section that is jumped to meets the header edge: its own top padding
   clears the bar, and no strip of the section before it is left under the header.
   Sections whose content starts at their top edge keep the 24px. */
main > section[id] { scroll-margin-top: -24px; }
main > :is(.ab-team, .ax-limits, .ax-feedback, .ct-directory, .pl-flow)[id] { scroll-margin-top: 0; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font-text);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  letter-spacing: var(--tracking-body);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: "kern", "liga", "calt", "ss01";
  overflow-x: clip;
  transition: background-color var(--t-med) var(--ease-soft), color var(--t-med) var(--ease-soft);
}

/* Theme switch: suppress transitions for one frame so nothing animates on load */
html.theme-switching *, html.theme-switching *::before, html.theme-switching *::after {
  transition-duration: 0s !important;
}

img, svg, video, canvas, picture { display: block; max-width: 100%; }
img, video { height: auto; }
svg { overflow: visible; }
button, input, textarea, select { font: inherit; color: inherit; letter-spacing: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
a { color: inherit; text-decoration: none; }
p, h1, h2, h3, h4, h5, h6, figure, blockquote, dl, dd { margin: 0; }
:where(ul[role="list"], ol[role="list"]) { list-style: none; margin: 0; padding: 0; }
hr { border: 0; height: 1px; background: var(--line); margin: 0; }
table { border-collapse: collapse; width: 100%; }
[hidden] { display: none !important; }

::selection { background: var(--crimson); color: var(--white); }

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }   /* outlines follow each control’s own corners */
/* Sections and headings that receive focus from a jump link or script are landmarks, not controls: no ring */
[tabindex="-1"]:focus, [tabindex="-1"]:focus-visible { outline: none !important; }

/* Headings */
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4 {
  font-family: var(--font-sans);
  font-weight: 700;
  line-height: var(--lh-head);
  letter-spacing: var(--tracking-head);
  color: var(--ink);
  text-wrap: balance;
  overflow-wrap: break-word;
  min-width: 0;
}
h1, .h1 { font-size: var(--fs-h1); line-height: 1.02; letter-spacing: var(--tracking-display); }
h2, .h2 { font-size: var(--fs-h2); line-height: var(--lh-snug); letter-spacing: var(--tracking-display); }
h3, .h3 { font-size: var(--fs-h3); line-height: 1.18; letter-spacing: var(--tracking-head); font-weight: var(--weight-heading); }
h4, .h4 { font-size: var(--fs-h4); line-height: 1.25; letter-spacing: -0.016em; font-weight: 650; }

p { text-wrap: pretty; }

.display {
  font-family: var(--font-sans);
  font-size: var(--fs-display);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
  overflow-wrap: break-word;
  min-width: 0;
}
.mega {
  font-family: var(--font-sans);
  font-size: var(--fs-mega);
  font-weight: 750;
  line-height: 0.88;
  letter-spacing: var(--tracking-mega);
}
.lead {
  font-size: var(--fs-lead);
  line-height: var(--lh-lead);
  letter-spacing: var(--tracking-body);
  color: var(--ink-2);
  text-wrap: pretty;
}
.muted { color: var(--ink-3); }
.small { font-size: var(--fs-small); }
.micro { font-size: var(--fs-micro); }
.mono { font-family: var(--font-mono); letter-spacing: 0; }
.accent { color: var(--accent-text); }
.ink { color: var(--ink); }
.nowrap { white-space: nowrap; }
.balance { text-wrap: balance; }

/* Context labels: retain useful product names without decorative chrome. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-label);
  font-size: var(--fs-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: none;
  color: var(--ink-3);
  line-height: var(--lh-label);
}
.eyebrow::before {
  content: "";
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--crimson);
  flex: none;
  display: none;
}
.surface-crimson .eyebrow::before { background: #fff; }
.eyebrow--plain::before { display: none; }

/* Gradient ink — used sparingly on display words */
.ink-gradient {
  background: linear-gradient(180deg, var(--ink) 30%, rgb(var(--ink-rgb) / 0.55) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.crimson-gradient {
  background: linear-gradient(100deg, var(--crimson-300) 0%, var(--crimson) 45%, var(--crimson-700) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Long-form text */
.prose { max-width: var(--container-text); color: var(--ink-2); }
.prose > * + * { margin-top: 1.1em; }
.prose h2 { margin-top: 2.2em; font-size: var(--fs-h3); color: var(--ink); }
.prose h3 { margin-top: 1.8em; font-size: var(--fs-h4); color: var(--ink); }
.prose a { color: var(--accent-text); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.prose a:hover { text-decoration-thickness: 2px; }
.prose ul, .prose ol { padding-left: 1.25em; }
.prose li + li { margin-top: 0.45em; }
.prose li::marker { color: var(--ink-3); }
.prose strong { color: var(--ink); font-weight: 650; }
.prose code { font-family: var(--font-mono); font-size: 0.9em; background: var(--paper-2); border: 1px solid var(--line); padding: 0.1em 0.4em; border-radius: 6px; }

/* Layout primitives */
.container { width: 100%; max-width: calc(var(--container) + var(--gutter) * 2); margin-inline: auto; padding-inline: var(--gutter); }
.container--wide { max-width: calc(var(--container-wide) + var(--gutter) * 2); }
.container--text { max-width: calc(var(--container-text) + var(--gutter) * 2); }

.section { position: relative; padding-block: var(--section-y); }
.section--sm { padding-block: var(--section-y-sm); }
.section--flush-top { padding-top: 0; }
.section--flush-bottom { padding-bottom: 0; }

.stack > * + * { margin-top: var(--stack, var(--s-5)); }
.stack-sm > * + * { margin-top: var(--s-3); }
.stack-lg > * + * { margin-top: var(--s-7); }

.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cluster-gap, var(--s-3)); }
.center { text-align: center; margin-inline: auto; }
.center.cluster { justify-content: center; }

.grid { display: grid; gap: var(--grid-gap, clamp(16px, 2vw, 24px)); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1024px) { .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 680px) { .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); } }

.section-head { max-width: 860px; margin-bottom: var(--space-section-head); }
.section-head.center { margin-inline: auto; text-align: center; }
.section-head .eyebrow + * { margin-top: var(--space-label); }
.section-head h2 + .lead, .section-head .display + .lead { margin-top: var(--space-copy); }
.section-head.center .lead { margin-inline: auto; max-width: 680px; }
.section-head > :first-child, .split__copy > :first-child { margin-top: 0; }

/* Accessibility */
.visually-hidden, .sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}
.skip-link {
  position: fixed;
  top: 12px; left: 12px;
  z-index: calc(var(--z-header) + 20);
  padding: 12px 18px;
  border-radius: var(--r-xs);
  background: var(--ink);
  color: var(--paper);
  font-weight: 600;
  font-size: var(--fs-small);
  transform: translateY(-160%);
}
.skip-link:focus-visible { transform: none; }   /* focus is never animated */

/* --------------------------------------------------------------------------
   Motion: page entry, section reveals and page-to-page (MOTION-SPEC v1)
   · Interior heroes enter on first paint, CSS only: eyebrow and title at 0,
     then the lead (+60ms) and the actions and visual (+120ms); 14px rise.
   · Below-the-fold [data-reveal] / [data-split] blocks rise 16px once, when
     they reach 96% of the viewport height. core.js runs them through the Web
     Animations API, so nothing here hides content: without JS, under reduced
     motion and in print everything is simply visible, and each component keeps
     its own transitions. data-delay="1..8" maps to 60ms steps, 240ms at most; a run
     of five or more siblings spreads evenly over those 240ms.
   -------------------------------------------------------------------------- */
/* Not quite 0, as for img-pending below: text first painted fully transparent is not
   counted as painted until the entry ends, which reported the largest paint 600ms late. */
@keyframes vm-enter { from { opacity: 0.001; translate: 0 14px; } }
@keyframes vm-fade { from { opacity: 0.001; } }
/* A block below the fold waiting for its reveal (core.js adds and removes it). Static
   and uncomposited: no will-change, and transitions are held so nothing fades out on load. */
.reveal-pending { opacity: 0 !important; translate: 0 16px !important; transition: none !important; }
.reveal-pending[data-reveal="fade"] { translate: none !important; }
/* A photo marked data-arrive that is still loading or decoding when the page is first
   painted (core.js adds and removes it): hidden until decoded, then faded in. Print shows it.
   Not quite 0: an image first painted fully transparent is never counted as the page's
   largest paint (Orbit's fell from its photo to the headline, 540ms to 1080ms). */
@media screen { img.img-pending { opacity: 0.001 !important; } }
[data-delay="1"] { --d: 1; } [data-delay="2"] { --d: 2; } [data-delay="3"] { --d: 3; } [data-delay="4"] { --d: 4; }
[data-delay="5"] { --d: 5; } [data-delay="6"] { --d: 6; } [data-delay="7"] { --d: 7; } [data-delay="8"] { --d: 8; }
@media (prefers-reduced-motion: no-preference) {
  :is(.page-hero, .ix-hero, .art-head, .nf) :is([data-reveal], [data-split]) {
    animation: vm-enter var(--t-enter) var(--ease-out) backwards;
    animation-delay: calc(var(--hero-step, 0) * var(--stagger));
  }
  :is(.page-hero, .ix-hero, .art-head, .nf) :is([data-delay="2"], [data-delay="3"]) { --hero-step: 1; }
  :is(.page-hero, .ix-hero, .art-head, .nf) :is([data-delay="4"], [data-delay="5"], [data-delay="6"], [data-delay="7"], [data-delay="8"]) { --hero-step: 2; }
  :is(.page-hero, .ix-hero, .art-head, .nf) [data-reveal="fade"] { animation-name: vm-fade; }

  /* Page to page: one quiet cross-fade, shared with the theme switch. theme-boot.js
     declares the same opt-in inline, so Chrome sees it before the first frame. */
  @view-transition { navigation: auto; }
  ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 220ms; animation-timing-function: var(--ease-soft); }
  /* Behind the two pictures of the cross-fade, which cover it completely. Chrome can drop
     the incoming picture for a frame early in the fade, and what showed through then was
     the white canvas: an arrival at a dark page lifted to a grey veil for a frame.
     theme-boot.js sets a coarse copy of the incoming page's colours here instead. */
  ::view-transition { background: var(--vt-backdrop, none); }
  /* A page that arrives through that cross-fade (theme-boot.js adds .vt-arrival on
     pagereveal) is brought in by the fade alone: its hero does not enter a second time.
     Back, Forward and reload add it too, before the first style: a page comes back as
     it was left, with no entry.
     Heroes with an entrance of their own follow the same rule beside it (home-cutout,
     thymos, monitor, services, assessment, air, infrastructure). */
  .vt-arrival :is(.page-hero, .ix-hero, .art-head, .nf) :is([data-reveal], [data-split]) { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; animation-delay: 0s !important;
    transition-duration: 0.01ms !important; transition-delay: 0s !important;
  }
}
@media print {
  [data-reveal], [data-split], .reveal-pending { opacity: 1 !important; translate: none !important; animation: none !important; }
  .skip-link { display: none; }
  /* Paper is white whatever the screen theme, so dark-theme ink would print near-invisible */
  :root[data-theme="dark"] { --paper: #FFFFFF; --ink: #0A0A0C; --ink-2: #3B3B42; --ink-3: #6B6B74; }
  body { color: #0A0A0C; background: #fff; }
}

/* Guard: nothing that moves ever creates sideways scroll. clip keeps position:sticky working. */
main { overflow-x: clip; }
/* List markers: a short ink rule, never a round bullet */
.prose ul, .art-prose ul { list-style: none; padding-left: 0; }
.prose ul > li, .art-prose ul > li { position: relative; padding-left: 26px; }
.prose ul > li::before, .art-prose ul > li::before { content: ""; position: absolute; left: 0; top: 0.78em; width: 12px; height: 1.5px; border-radius: 1px; background: var(--ink-3); }
