/* ============================================================================
   eVamb Cinematic — COMPONENTS  (signature primitives)
   Depends on tokens.css + base.css.

   Reveal primitive (the progressive-enhancement rule): page is FULLY VISIBLE with no JS. Motion is
   gated under html.anim, added by reveal.js only when prefers-reduced-motion
   is NOT set. Full prefers-reduced-motion reset lives at the bottom.
   ========================================================================== */

/* ---- Diamond markers REMOVED site-wide -------------------------------
   The copper/gold diamond glyph is no longer rendered anywhere on either
   site (before eyebrows, the "Explore eVamb Labs" cross-link, and any
   standalone .diamond mark). Label text is kept; only the glyph is gone. */
.diamond-list { display: grid; gap: var(--sp-3); }
.diamond-list > li {
  position: relative;
  padding-left: var(--sp-5);
  line-height: var(--lh-body);
}
/* (was: gold diamond bullet) — marker removed, text kept */
.diamond-list > li::before { content: none !important; }

/* Standalone diamond mark — fully suppressed, never renders */
.diamond { display: none !important; }

/* ---- Eyebrow / HUD label --------------------------------------------- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}
/* (was: gold diamond before eyebrow) — marker removed, text kept */
.eyebrow::before { content: none !important; }
.hud {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--text-on-ink-faint);
  display: inline-flex;
  gap: var(--sp-2);
  align-items: center;
}

/* ---- Cards: soft-radius cream ---------------------------------------- */
.card {
  background: var(--surface-cream-raise);
  border: 1px solid var(--hairline-on-cream);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
  box-shadow: var(--shadow-card);
  transition: transform var(--dur-3) var(--ease-brand),
              box-shadow var(--dur-3) var(--ease-brand);
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 2px 4px rgba(10,13,20,.07), 0 18px 44px rgba(10,13,20,.12);
}

/* ---- Cards: edge-lit ink (faint azure→copper left edge) --------------- */
.card-ink {
  position: relative;
  background: var(--surface-ink-raise);
  color: var(--text-on-ink);
  border: 1px solid var(--hairline-on-ink);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
  overflow: hidden;
  box-shadow: var(--shadow-card-ink);
  transition: transform var(--dur-3) var(--ease-brand),
              border-color var(--dur-3) var(--ease-brand);
}
.card-ink::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--grad-edge);
  opacity: 0.55;
  transition: opacity var(--dur-3) var(--ease-brand);
}
.card-ink::after {
  /* soft inner left glow */
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 120px;
  background: linear-gradient(90deg, rgba(79,163,217,.10), transparent);
  pointer-events: none;
  opacity: 0.6;
}
.card-ink:hover { transform: translateY(-4px); border-color: var(--hairline-on-ink); }
.card-ink:hover::before { opacity: 1; }
.card-ink h3, .card-ink h4, .card-ink h5 { color: var(--text-on-ink); }
.card-ink p { color: var(--text-on-ink-muted); }

/* ---- Buttons (magnetic) ---------------------------------------------- */
.btn {
  --btn-bg: var(--copper);
  --btn-fg: #fff;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 14px 26px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-body);
  line-height: 1;
  color: var(--btn-fg);
  background: var(--btn-bg);
  border-radius: var(--r-pill);
  will-change: transform;
  transition: transform var(--dur-2) var(--ease-brand),
              box-shadow var(--dur-2) var(--ease-brand),
              background var(--dur-2) var(--ease-brand);
  /* magnetic offset set by JS via custom props (falls back to 0) */
  transform: translate(var(--mx, 0), var(--my, 0));
}
.btn:hover { box-shadow: var(--shadow-cta); }
.btn:active { transform: translate(var(--mx, 0), var(--my, 0)) scale(.98); }

/* magnetic inner label moves at a fraction of the button for parallax feel */
.btn > .btn-label { transform: translate(var(--lmx, 0), var(--lmy, 0)); display: inline-flex; gap: var(--sp-2); }

.btn-primary { --btn-bg: var(--copper); --btn-fg:#fff; }
/* (.btn-gold removed — no markup used it; deleting it prevents a future
   gold-button regression. The --grad-gold token stays for other surfaces.) */
.btn-ghost {
  --btn-bg: transparent;
  --btn-fg: currentColor;
  border: 1px solid currentColor;
}
.ground-ink .btn-ghost { border-color: var(--hairline-on-ink); color: var(--text-on-ink); }
.ground-ink .btn-ghost:hover { background: rgba(240,232,216,.06); box-shadow: none; }
.ground-cream .btn-ghost, .ground-paper .btn-ghost { border-color: var(--hairline-on-cream); }

.btn[data-magnetic] { cursor: pointer; }

/* ---- Draw-on link underline ------------------------------------------ */
.link {
  position: relative;
  display: inline-block;
  color: inherit;
  padding-bottom: 2px;
}
.link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1.5px;
  background: var(--copper);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-3) var(--ease-brand);
}
.ground-ink .link::after { background: var(--amber); }
.ground-cream .link::after, .ground-paper .link::after { background: var(--copper-on-cream); }
.link:hover::after, .link:focus-visible::after { transform: scaleX(1); }

/* ---- Trust / compliance band chips ----------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 8px 16px;
  border-radius: var(--r-pill);
  border: 1px solid var(--hairline-on-ink);
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-on-ink-muted);
}
.ground-cream .chip, .ground-paper .chip {
  border-color: var(--hairline-on-cream);
  color: var(--text-on-cream-muted);
}

/* ---- Stage label (HONEST product status — the honest-status rule) ------------------ */
.stage-label {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 4px 10px;
  border-radius: var(--r-pill);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  border: 1px solid currentColor;
}
.stage-label::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.stage-live    { color: #3FB27A; }
.stage-beta    { color: var(--azure); }
.stage-trial   { color: var(--amber); }
.stage-pilot   { color: var(--blue); }
.stage-dev     { color: var(--text-on-ink-faint); }

/* ============================================================================
   REVEAL primitive (tokenised) — initial/animated states gated under html.anim
   Without html.anim (no JS, or reduced-motion) content is fully visible.
   reveal.js reads data-reveal / data-reveal-delay / data-reveal-distance.
   ========================================================================== */
.reveal { /* visible by default — P15 */ }

html.anim .reveal {
  opacity: 0;
  transition:
    opacity var(--dur-4) var(--ease-brand),
    transform var(--dur-4) var(--ease-brand),
    clip-path var(--dur-4) var(--ease-brand);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}

/* variant: fade (default) */
html.anim .reveal[data-reveal="fade"] { transform: none; }

/* variant: translate-up (default when data-reveal absent) */
html.anim .reveal:not([data-reveal]),
html.anim .reveal[data-reveal="up"] {
  transform: translateY(var(--reveal-distance, 28px));
}
html.anim .reveal[data-reveal="down"] { transform: translateY(calc(-1 * var(--reveal-distance, 28px))); }
html.anim .reveal[data-reveal="left"] { transform: translateX(var(--reveal-distance, 28px)); }
html.anim .reveal[data-reveal="right"] { transform: translateX(calc(-1 * var(--reveal-distance, 28px))); }

/* variant: clip (wipe reveal) */
html.anim .reveal[data-reveal="clip"] {
  clip-path: inset(0 0 100% 0);
  transform: none;
}

/* animated (in-view) state — set by reveal.js */
html.anim .reveal.is-in {
  opacity: 1;
  transform: none;
  clip-path: inset(0 0 0 0);
}

/* staggered children */
html.anim .reveal-stagger > * {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--dur-4) var(--ease-brand),
              transform var(--dur-4) var(--ease-brand);
}
html.anim .reveal-stagger.is-in > * { opacity: 1; transform: none; }
html.anim .reveal-stagger.is-in > *:nth-child(1) { transition-delay: 40ms; }
html.anim .reveal-stagger.is-in > *:nth-child(2) { transition-delay: 100ms; }
html.anim .reveal-stagger.is-in > *:nth-child(3) { transition-delay: 160ms; }
html.anim .reveal-stagger.is-in > *:nth-child(4) { transition-delay: 220ms; }
html.anim .reveal-stagger.is-in > *:nth-child(5) { transition-delay: 280ms; }
html.anim .reveal-stagger.is-in > *:nth-child(6) { transition-delay: 340ms; }

/* ============================================================================
   prefers-reduced-motion — COMPLETE static path (the design spec §Degradation)
   Reset every transition/animation; force all reveals fully visible.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  html.anim .reveal,
  html.anim .reveal-stagger > * {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
  }
  .btn { transform: none !important; }
}


/* ---- Brand wordmark: e + V-mark glyph + amb (V = the logo from the brand kit) ----
   Lockup reads LARGER and the V glyph sits on the text baseline in BOTH the
   header and footer. Per-site agents fine-tune header-vs-footer wordmark size. */
.brand-lockup {
  display: inline-flex;
  align-items: center;
  gap: 0;
}
.brand-lockup .wordmark,
.brand-lockup .brand-wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0;
}
.brand-lockup .wordmark .letter { display: inline-block; }
.brand-lockup .v-glyph {
  width: 1.45em; height: 1.45em;
  margin: 0 -0.14em;
  vertical-align: middle;
  flex-shrink: 0;
}

/* Default wordmark size — reads bigger on both sites (per-site agents fine-tune) */
.brand-lockup .wordmark,
.brand-lockup .brand-wordmark,
.brand-wordmark { font-size: 1.35rem; }


/* global glyph fallback (footer-brand etc. that are not .brand-lockup) */
.v-glyph {
  width: 1.45em; height: 1.45em;
  margin: 0 -0.14em;
  vertical-align: middle;
  display: inline-block;
  flex-shrink: 0;
}
.brand-wordmark { display: inline-flex; align-items: center; }
.brand-wordmark .letter, .wordmark .letter { display: inline-block; }


/* lockup layout hardening (covers .brand route-shell lockups) */
.brand, .brand-lockup, .brand-wordmark { align-items: center; }
.letter { display: inline-block; }

/* hard guard: grid/flex must not override the HTML hidden attribute */
[hidden]{display:none!important}


/* ============================================================================
   CROSS-DEVICE HARDENING LAYER  (cross-device hardening · appended — DO NOT REWRITE ABOVE)
   Identical block lives in shared/, com/public/assets/, io/public/assets/.
   Goal: every page auto-adjusts to any device/browser at 320 → 1440+ widths
   with no horizontal overflow, no iOS auto-zoom, and correct mobile viewport
   height + notch handling. Loads after base.css/components.css; page CSS may
   still override intentionally (hero already fluid). APPEND-ONLY.
   ========================================================================== */

/* --- (1) Mobile dynamic-viewport height: 100vh FALLBACK then 100dvh -------
   100vh on mobile is the LARGE viewport (URL bar collapsed) and clips content
   when the bar is shown. dvh tracks the live viewport. Fallback line first so
   browsers without dvh keep a working value. Applies to the hero + any
   element opting in via [data-fullvh] / .is-fullvh without editing markup. */
.hero,
[data-fullvh],
.is-fullvh {
  min-height: 100vh;        /* fallback for browsers without dvh           */
  min-height: 100svh;       /* small viewport: never clipped by mobile UI  */
  min-height: 100dvh;       /* dynamic: tracks the live viewport           */
}

/* --- (2) Safe-area insets under viewport-fit=cover ------------------------
   Bottom-/side-fixed chrome must clear the notch / home indicator / rounded
   corners. max() keeps the original padding when insets are 0 (or when
   viewport-fit=cover is absent — then env() resolves to 0 and base value
   wins). Covers consent banner, mobile nav, sticky header, any FAB. */
.consent {
  padding-bottom: max(var(--sp-5, 32px), env(safe-area-inset-bottom));
  padding-left:   max(var(--sp-5, 32px), env(safe-area-inset-left));
  padding-right:  max(var(--sp-5, 32px), env(safe-area-inset-right));
}
.consent {
  /* the banner itself is offset from the viewport edges — pad the offsets */
  bottom: max(var(--sp-4, 24px), env(safe-area-inset-bottom));
}
.site-nav,
.site-header {
  padding-left:  max(var(--container-pad, 20px), env(safe-area-inset-left));
  padding-right: max(var(--container-pad, 20px), env(safe-area-inset-right));
}
.nav-mobile[open] {
  padding-bottom: max(var(--sp-5, 32px), env(safe-area-inset-bottom));
  padding-left:   max(var(--container-pad, 20px), env(safe-area-inset-left));
  padding-right:  max(var(--container-pad, 20px), env(safe-area-inset-right));
}
/* generic floating action button (any future .fab / [data-fab]) */
.fab,
[data-fab] {
  bottom: max(var(--sp-4, 24px), env(safe-area-inset-bottom));
  right:  max(var(--sp-4, 24px), env(safe-area-inset-right));
}

/* --- (3) >=16px font-size on every focusable field (no iOS auto-zoom) -----
   iOS Safari zooms the page when a focused control's font-size < 16px. Force
   the floor only on coarse-pointer / small screens so desktop type is intact.
   16px is the threshold; we never go below it. */
@media (max-width: 1023px) {
  input,
  select,
  textarea,
  button,
  [contenteditable="true"] {
    font-size: max(16px, 1rem);
  }
}
@media (pointer: coarse) {
  input,
  select,
  textarea,
  [contenteditable="true"] {
    font-size: max(16px, 1rem);
  }
}

/* --- (4) -webkit-backdrop-filter BEFORE backdrop-filter on glass ----------
   Safari/iOS still need the prefixed property, and it must come FIRST so the
   unprefixed value is the cascade winner where supported. Re-declares the
   known glass surfaces so the ordering is guaranteed regardless of where the
   page CSS set them. Values mirror the existing surfaces. */
/* Lighter blur (≤8px) on glass surfaces cuts per-frame scroll repaint cost. */
.site-nav {
  -webkit-backdrop-filter: blur(8px) saturate(120%);
          backdrop-filter: blur(8px) saturate(120%);
}
.site-header[data-scrolled="true"] {
  -webkit-backdrop-filter: saturate(140%) blur(8px);
          backdrop-filter: saturate(140%) blur(8px);
}
/* belt-and-braces for any other glass opt-in */
.glass,
[data-glass] {
  -webkit-backdrop-filter: blur(8px) saturate(130%);
          backdrop-filter: blur(8px) saturate(130%);
}

/* --- (5) Media never overflows + global horizontal-scroll guard ----------- */
img, video, canvas, svg, iframe, picture {
  max-width: 100%;
}
html, body {
  overflow-x: hidden;       /* hard guard against 1px-bleed scrollbars      */
  overscroll-behavior-y: none;
}
/* long unbroken strings (URLs, IDs, tokens) must not push layout wide */
p, li, dd, dt, figcaption, blockquote, code, pre, td, th {
  overflow-wrap: anywhere;
}

/* --- (6) Fluid type via clamp() — headlines never overflow at 320px -------
   Generic h1/h2 already inherit fluid tokens; this is a defensive floor so a
   page that forgets the token still scales. min() with the token keeps the
   intended max while guaranteeing a small-screen floor. */
h1 { font-size: clamp(2rem, 5vw + 1rem, var(--fs-h1, 3.5rem)); }
h2 { font-size: clamp(1.625rem, 3vw + 1rem, var(--fs-h2, 2.75rem)); }
.display { font-size: clamp(2.5rem, 7vw + 1rem, var(--fs-display, 6rem)); }
h1, h2, h3, .display { overflow-wrap: break-word; }

/* --- (7) Horizontal scrollers: touch pan + scroll-snap -------------------
   Any opt-in horizontal scroller pans cleanly on touch (no vertical hijack)
   and snaps to items. No markup edits needed — opt in via class/attr/role. */
.h-scroll,
[data-scroller="x"],
[role="tablist"][aria-orientation="horizontal"] {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  touch-action: pan-x;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;     /* momentum scroll on older iOS    */
  scrollbar-width: thin;
}
.h-scroll > *,
[data-scroller="x"] > * {
  scroll-snap-align: start;
  flex: 0 0 auto;
}

/* --- (8) Final < 380px safety — nothing overflows at 320–380px ------------
   Trim heavy padding, collapse multi-col grids to one column, allow any
   long heading to wrap mid-word as a last resort. */
@media (max-width: 380px) {
  :root {
    --container-pad: 16px;
    --sp-section: clamp(48px, 12vw, 72px);
  }
  .section { padding-inline: 16px; }
  .card,
  .card-ink,
  .consent__panel,
  .consent { padding: var(--sp-4, 24px); }
  /* force single column on the fluid 12-col grid + common flex rows */
  .grid { grid-template-columns: minmax(0, 1fr); }
  .col-3, .col-4, .col-6, .col-8, .col-12 { grid-column: 1 / -1; }
  .flow-row { gap: var(--sp-2, 8px); }
  h1, h2, h3, h4, .display { overflow-wrap: anywhere; hyphens: auto; }
  /* Content-flow CTA pills span the row so labels never clip. The compact nav
     CTA is intentionally excluded (full-width would break the fixed header). */
  .hero__ctas .btn,
  .flow-row > .btn,
  .consent__actions .btn,
  .consent__btn { flex: 1 1 100%; width: 100%; }
}


/* P17 follow-ups: win the cascade for fixed surfaces + collapse dense grids */
.consent { bottom: max(var(--sp-3), env(safe-area-inset-bottom)) !important; }
.parent-anchor { bottom: max(var(--sp-4), env(safe-area-inset-bottom)) !important; }
@media (max-width: 679px) { .ops-metrics { grid-template-columns: 1fr 1fr !important; } }
@media (max-width: 380px) { .ops-metrics { grid-template-columns: 1fr !important; } }
