/* vedika-standard.css — one nav, one font, one button, one ground, one sheet.
 *
 * WHY THIS FILE EXISTS, AND WHY IT IS ALLOWED TO SHOUT.
 * 92 of the 116 top-level pages ship their own <style> block, and those blocks
 * set fonts, button colours and card treatments that contradict each other --
 * measured 2026-08-02: 12 distinct webfont sets, 5 navbar variants, 6 button
 * systems, 55 pages with no nav CSS at all. A politely-scoped stylesheet loses
 * to every one of them, which is exactly how the site arrived here.
 *
 * So the rules below are deliberately loud in one narrow way: the TYPE and the
 * SURFACE tokens carry !important, because a page that keeps its own font is a
 * page that still looks foreign. Everything else -- layout, spacing, anything a
 * page might legitimately need to specialise -- is left at normal weight so a
 * page can still override it when it has a reason.
 *
 * The link tag for this file must be the LAST stylesheet in <head>, after any
 * inline <style>, or equal-specificity rules lose on source order alone.
 */

/* ── TOKENS ──────────────────────────────────────────────────────────────── */
:root {
  --vk-display: 'Newsreader', Georgia, 'Times New Roman', serif;
  --vk-body:    'DM Sans', system-ui, -apple-system, sans-serif;
  --vk-mono:    'Fragment Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Brand hues held back to roughly 70% chroma. Full-strength #7C3AED across a
   * surface reads as signage; this reads as pigment. The warm anchor is a rose,
   * not the gold token -- violet and yellow blend through olive, which is what
   * made the old cards look muddy. */
  --vk-std-ink:        #16171D;
  --vk-std-ink-soft:   #33384A;
  --vk-std-ink-mute:   #5B6274;
  --vk-std-paper:      #EDEEF3;
  --vk-std-surface:    #FFFFFF;
  --vk-std-space:      #0B0B0D;
  --vk-std-violet:     #8B6FD4;
  --vk-std-teal:       #7FA9AD;
  --vk-std-rose:       #E4A0B4;

  --vk-std-grid:       132px;   /* 40px read as graph paper; a background grid should be felt, not counted */
  --vk-std-grid-line:  rgba(22,23,29,.055);
  --vk-std-r-pill:     999px;
  --vk-std-r-sheet:    3px;
}

/* ── TYPE ── the loud part, and the reason the site looked like six sites ─── */
body,
body p, body li, body td, body th, body dd, body dt,
body input, body select, body textarea, body button, body label {
  font-family: var(--vk-body) !important;
}
body h1, body h2, body h3, body h4,
body .display, body .vk-display {
  font-family: var(--vk-display) !important;
  font-weight: 300;
  letter-spacing: -.02em;
}
body code, body pre, body kbd, body samp,
body .mono, body .vk-mono, body .eyebrow, body .kicker {
  font-family: var(--vk-mono) !important;
}
body { color: var(--vk-std-ink); -webkit-font-smoothing: antialiased; }

/* ── GROUND ── ruled, never a full-page colour wash ──────────────────────── */
.vk-ground {
  position: relative;
  background-color: var(--vk-std-paper);
}
/* The rules are painted by a masked bloom canvas when JS runs; this is the
 * static fallback so a no-JS or no-WebGL page still gets the ruled ground
 * rather than flat grey. */
.vk-ground[data-vk-grid]::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* OPT-IN, and only where rules earn their place.
   * LARGE, AND FADED AT THE EDGES.
   * A 40px lattice reads as graph paper: dense enough to count, so the eye
   * treats it as content. At 132px the same rules become architecture -- you
   * feel the alignment without reading the tiles. The radial mask is the part
   * that makes it look designed rather than tiled: rules at full strength in
   * the middle of the viewport, dissolved to nothing at the edges, so the page
   * never ends on a hard lattice. */
  background-image:
    linear-gradient(var(--vk-std-grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--vk-std-grid-line) 1px, transparent 1px);
  background-size: var(--vk-std-grid) var(--vk-std-grid);
  -webkit-mask-image: radial-gradient(115% 85% at 50% 32%, #000 0%, rgba(0,0,0,.55) 52%, transparent 88%);
          mask-image: radial-gradient(115% 85% at 50% 32%, #000 0%, rgba(0,0,0,.55) 52%, transparent 88%);
}
.vk-ground > * { position: relative; z-index: 1; }

.vk-grid-flow {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  /* Was a bloom masked down to 1px rules -- a grid wearing the field's colour.
   * Now the field itself, unmasked and very quiet, fading out down the page so
   * it never competes with content below the fold. */
  /* THE DEFAULT GROUND. Same field as the hero, same engine, held back enough
   * that body copy stays comfortable over it. Strong at the top where a page
   * opens, easing down so a long article is not read through moving colour. */
  opacity: .72;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.62) 42%, rgba(0,0,0,.28) 72%, rgba(0,0,0,.14) 100%);
          mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.62) 42%, rgba(0,0,0,.28) 72%, rgba(0,0,0,.14) 100%);
}

/* THE RULES LIGHT UP UNDER THE CURSOR.
 * A second copy of the same lattice, brighter and in the brand violet, masked
 * to a soft disc that follows the pointer. Only the rules inside that disc are
 * visible, so moving the mouse appears to illuminate the grid rather than
 * drawing anything new -- the lattice is static, the light is what moves. */
.vk-grid-live {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  opacity: 0; transition: opacity .45s ease;
  background-image:
    linear-gradient(rgba(139,111,212,.42) 1px, transparent 1px),
    linear-gradient(90deg, rgba(139,111,212,.42) 1px, transparent 1px);
  background-size: var(--vk-std-grid) var(--vk-std-grid);
  -webkit-mask-image: radial-gradient(320px circle at var(--vk-mx,50%) var(--vk-my,50%),
    #000 0%, rgba(0,0,0,.45) 42%, transparent 72%);
          mask-image: radial-gradient(320px circle at var(--vk-mx,50%) var(--vk-my,50%),
    #000 0%, rgba(0,0,0,.45) 42%, transparent 72%);
}
.vk-ground[data-vk-grid]:hover .vk-grid-live { opacity: 1; }
.vk-ground:not([data-vk-grid]) .vk-grid-live { display: none; }
.vk-grid-flow canvas { width: 100% !important; height: 100% !important; display: block; }

/* A light that follows the pointer, so the ruled ground reads as a lit surface
 * rather than printed paper. Position comes from --vk-mx/--vk-my. */
.vk-ground-light {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  opacity: 0; transition: opacity .5s ease;
  background: radial-gradient(420px circle at var(--vk-mx,50%) var(--vk-my,50%),
    rgba(139,111,212,.13), rgba(127,169,173,.07) 42%, transparent 68%);
}
.vk-ground:hover .vk-ground-light { opacity: 1; }

/* ── HERO ── bloom only, no rules; overlaps the next section ─────────────── */
.vk-hero { position: relative; overflow: hidden; background: var(--vk-std-paper); }
.vk-hero__field {
  position: absolute; inset: 0; z-index: 0;
  /* Ends on paper rather than on an edge, so the section below can overlap it
   * instead of abutting -- two boxes that merely touch always show their join. */
  -webkit-mask-image: linear-gradient(180deg,#000 0%,#000 62%,rgba(0,0,0,.74) 80%,rgba(0,0,0,.30) 92%,transparent 100%);
          mask-image: linear-gradient(180deg,#000 0%,#000 62%,rgba(0,0,0,.74) 80%,rgba(0,0,0,.30) 92%,transparent 100%);
}
.vk-hero__field canvas { width: 100% !important; height: 100% !important; display: block; }
/* Centred veil: quiet behind the words, art alive on both sides. A left-biased
 * scrim only works for left-aligned type and leaves a dead zone otherwise. */
.vk-hero__scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(120% 78% at 50% 40%,
    rgba(255,255,255,.82) 0%, rgba(255,255,255,.58) 34%,
    rgba(255,255,255,.20) 58%, transparent 76%);
}
.vk-hero > * { position: relative; z-index: 2; }

/* ── CAPSULE ── one button system replaces six ───────────────────────────── */
.vk-pill {
  position: relative; display: inline-flex; align-items: center; overflow: hidden;
  height: 56px; min-width: 220px; padding: 0 54px 0 24px; border: 0; cursor: pointer;
  border-radius: var(--vk-std-r-pill); text-decoration: none;
  background: var(--vk-std-space);
  /* Depth on all four sides: contact + ambient + a ring, a top light and a
   * bottom shade, plus rim light on the left and shade on the right. Two inset
   * lines describe a ridge; this describes a solid. */
  box-shadow:
    0 1px 2px rgba(16,16,24,.16),
    0 6px 12px rgba(16,16,24,.13),
    0 18px 34px rgba(16,16,24,.14),
    inset 0 0 0 1px rgba(255,255,255,.10),
    inset 0 1px 0 rgba(255,255,255,.26),
    inset 0 -1px 0 rgba(0,0,0,.26),
    inset 2px 0 6px -4px rgba(255,255,255,.22),
    inset -2px 0 6px -4px rgba(0,0,0,.24);
  transform: translateZ(0);
  transition: transform .5s cubic-bezier(.2,.7,.2,1), box-shadow .5s cubic-bezier(.2,.7,.2,1);
}
.vk-pill.is-live { transition: transform .09s linear, box-shadow .09s linear; }
.vk-pill:active { transform: translateY(-1px) scale(.998); transition-duration: .09s; }

.vk-pill__blob {
  position: absolute; top: 0; right: 0; bottom: 0; width: 58%; pointer-events: none;
  border-radius: 0 var(--vk-std-r-pill) var(--vk-std-r-pill) 0;
  /* The parent's overflow does not clip a masked child to the cap, so the blob
   * clips its own canvas. Without this the colour ends in a square step. */
  overflow: hidden; isolation: isolate;
  -webkit-mask: linear-gradient(90deg,transparent 0%,rgba(0,0,0,.38) 40%,rgba(0,0,0,.82) 74%,#000 100%);
          mask: linear-gradient(90deg,transparent 0%,rgba(0,0,0,.38) 40%,rgba(0,0,0,.82) 74%,#000 100%);
}
/* No radius here: two antialiased curves over the same pixels produced a bright
 * hairline on the right cap. The blob owns the rounding; the canvas oversizes
 * slightly so its raw edge never lands on the curve. */
.vk-pill__blob canvas {
  width: 100% !important; height: 100% !important; display: block;
  transform: scale(1.02); transform-origin: center; backface-visibility: hidden;
}
.vk-pill__label {
  position: relative; z-index: 2; display: flex; flex-direction: column;
  gap: 4px; text-align: left;
  /* The wrapper, not just its children. Adopted markup often puts text directly
   * here rather than inside a <b>, and that text kept the page's old colour. */
  color: #fff !important;
}
.vk-pill--light .vk-pill__label { color: var(--vk-std-ink) !important; }
.vk-pill__label b {
  font-family: var(--vk-body) !important;
  font-size: 14.5px; font-weight: 600; letter-spacing: .002em;
  color: #fff !important; line-height: 1;
}
.vk-pill__label span {
  font-family: var(--vk-mono) !important;
  font-size: 10px; letter-spacing: .13em; text-transform: uppercase;
  color: rgba(255,255,255,.60) !important; line-height: 1;
}
.vk-pill--light {
  background: var(--vk-std-surface);
  box-shadow:
    0 1px 2px rgba(16,16,24,.10),
    0 6px 12px rgba(16,16,24,.08),
    0 18px 34px rgba(16,16,24,.10),
    inset 0 0 0 1px rgba(16,16,24,.05),
    inset 0 1px 0 rgba(255,255,255,.95),
    inset 0 -1px 0 rgba(0,0,0,.09),
    inset 2px 0 6px -4px rgba(255,255,255,.9),
    inset -2px 0 6px -4px rgba(0,0,0,.09);
}
/* Light body carries dark type. Its absence is what made "Try the sandbox"
 * render as white-on-cyan and unreadable. */
.vk-pill--light .vk-pill__label b    { color: var(--vk-std-ink) !important; }
.vk-pill--light .vk-pill__label span { color: var(--vk-std-ink-mute) !important; }
/* Anything nested inside a label -- icons, price spans, Alpine-bound text --
 * inherits rather than keeping the page's old colour. */
.vk-pill .vk-pill__label * { color: inherit !important; }

/* Specular sweep on hover: a moving highlight is what sells a curved surface. */
.vk-pill::after {
  content: ''; position: absolute; inset: -40% -60%; z-index: 3; pointer-events: none;
  background: linear-gradient(100deg, transparent 38%, rgba(255,255,255,.42) 48%,
    rgba(255,255,255,.62) 51%, rgba(255,255,255,.42) 54%, transparent 64%);
  transform: translateX(-62%) rotate(2deg); opacity: 0; transition: opacity .18s ease;
}
.vk-pill:hover::after { opacity: 1; animation: vk-pill-sheen .78s cubic-bezier(.3,.6,.2,1); }
.vk-pill--light::after {
  background: linear-gradient(100deg, transparent 38%, rgba(255,255,255,.75) 50%, transparent 64%);
}
@keyframes vk-pill-sheen {
  from { transform: translateX(-62%) rotate(2deg); }
  to   { transform: translateX(62%)  rotate(2deg); }
}

/* ── SHEET ── sharp corners, bloom inside, type above it on clean paper ──── */
.vk-std-sheet {
  position: relative; overflow: hidden; background: var(--vk-std-surface);
  border-radius: var(--vk-std-r-sheet);
  display: flex; flex-direction: column; padding: 26px;
  box-shadow:
    0 1px 2px rgba(16,16,24,.07),
    0 6px 14px rgba(16,16,24,.06),
    0 16px 34px rgba(16,16,24,.06),
    inset 0 1px 0 rgba(255,255,255,.9);
  transform: translateZ(0);
  transition: transform .5s cubic-bezier(.2,.7,.2,1), box-shadow .5s cubic-bezier(.2,.7,.2,1);
}
.vk-std-sheet.is-live { transition: transform .09s linear, box-shadow .09s linear; }
.vk-std-sheet__field { position: absolute; inset: 0; z-index: 0; }
.vk-std-sheet__field canvas { width: 100% !important; height: 100% !important; display: block; }
/* Short opaque band behind the type only. The first version ramped over 46% of
 * the card and bleached the artwork; the words need a ground, not the top half. */
.vk-std-sheet__veil {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg,#fff 0%,#fff 20%,rgba(255,255,255,.86) 30%,
    rgba(255,255,255,.30) 40%, rgba(255,255,255,0) 50%);
}
.vk-std-sheet__body { position: relative; z-index: 2; }
.vk-std-sheet p { color: var(--vk-std-ink-soft); }
.vk-std-sheet--dark { background: var(--vk-std-space); }
.vk-std-sheet--dark .vk-std-sheet__veil {
  background: linear-gradient(180deg,#0B0B0D 0%,#0B0B0D 20%,rgba(11,11,13,.86) 30%,
    rgba(11,11,13,.30) 40%, rgba(11,11,13,0) 50%);
}
.vk-std-sheet--dark, .vk-std-sheet--dark h3 { color: #fff; }
.vk-std-sheet--dark p { color: rgba(255,255,255,.86); }

/* ── 3D ── perspective lives on the container or the tilt has nothing to do ─ */
.vk-tilt-scope { perspective: 1100px; }

/* ── FOOTER ── one dark band, not a floating inset card ──────────────────── */
.vk-std-footer { background: var(--vk-std-space); color: #fff; }
.vk-std-footer a { color: rgba(255,255,255,.78); text-decoration: none; }
.vk-std-footer a:hover { color: #fff; }

@media (prefers-reduced-motion: reduce) {
  /* The canvases keep rendering -- a still bloom is still the design. Only the
   * CSS motion stops. vedika-sheet-gl.js froze its whole field here, which is
   * why the live site looked static to anyone with this setting on. */
  .vk-pill, .vk-std-sheet { transition: none; }
  .vk-pill:hover::after { animation: none; }
}

/* ── CHARTS & METERS ── same material as a sheet, data never touched ─────── */
.vk-std-chart > canvas, .vk-std-chart > svg,
.vk-std-chart canvas, .vk-std-chart svg { position: relative; z-index: 2; }
/* Near-opaque behind a chart: colour should read at the edges and under the
 * plot, never through the data.
 *
 * `opacity: .55` was the exact opposite of that comment. On /dashboard the
 * marble ran straight through both plots and "Response Times" stopped being
 * readable at all. adoptCharts also never built the veil this promised -- only
 * adoptCards did -- so nothing stood between the field and the data. The wash
 * below is that missing veil, as a pseudo-element so no markup has to change. */
.vk-std-chart .vk-std-sheet__field { opacity: .16; }
.vk-std-chart::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: rgba(255,255,255,.86);
}
.vk-std-sheet--dark.vk-std-chart::before { background: rgba(11,11,13,.86); }

.vk-std-meter { overflow: hidden; border-radius: var(--vk-std-r-pill); }
.vk-std-meter__field { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.vk-std-meter__field canvas { width: 100% !important; height: 100% !important; display: block; }
.vk-std-meter > *:not(.vk-std-meter__field) { position: relative; z-index: 1; }


/* ── GLASS ── large panels let the ground move through them ──────────────── */
.vk-std-sheet--glass {
  background: rgba(255,255,255,.62);
  -webkit-backdrop-filter: saturate(1.35) blur(22px);
          backdrop-filter: saturate(1.35) blur(22px);
  border: 1px solid rgba(255,255,255,.55);
  box-shadow:
    0 1px 2px rgba(16,16,24,.05),
    0 10px 30px rgba(16,16,24,.08),
    0 30px 70px rgba(16,16,24,.10),
    inset 0 1px 0 rgba(255,255,255,.75);
}
/* Glass shows the field, so it must not also paint its own. */
.vk-std-sheet--glass > .vk-std-sheet__field,
.vk-std-sheet--glass > .vk-std-sheet__veil { display: none; }
.vk-std-sheet--glass--dark {
  background: rgba(11,11,13,.55);
  border-color: rgba(255,255,255,.10);
}


/* ── THE PAGE'S OWN TILES ─────────────────────────────────────────────────
 * 21 pages carry `.bg-grid` from the old design system, a 40px lattice painted
 * on <body>. On a hero page that is the texture the founder wants, so it is
 * left alone and simply scaled up to match the standard. On every other page
 * -- auth screens, dashboards -- it is the "cheq boxes in random places"
 * problem, and the flowing field is the ground instead. */
.vk-ground[data-vk-grid] .bg-grid,
.vk-ground[data-vk-grid].bg-grid,
body[data-vk-standard] .vk-ground[data-vk-grid] ~ .bg-grid {
  background-size: var(--vk-std-grid) var(--vk-std-grid) !important;
}
.vk-ground:not([data-vk-grid]) .bg-grid,
.vk-ground:not([data-vk-grid]).bg-grid {
  background-image: none !important;
}
