/* ==========================================================================
   V-Scale Exotics — core
   Tokens, reset, typography, layout primitives, motion.

   No web fonts are loaded. A strict CSP with no external origins is worth
   more here than a bespoke typeface, so the system stack is used deliberately
   and tuned hard: optical sizing, tight display tracking, and a serif/grotesque
   pairing that holds up at large scale.
   ========================================================================== */

:root {
  /* ---- Colour ---- */
  --obsidian:      #07080a;
  --ink:           #0b0d10;
  --slate:         #111419;
  --slate-2:       #171b21;
  --slate-3:       #1f242c;
  --line:          #262c35;
  --line-soft:     #1b2027;

  --bone:          #ece7dd;
  --bone-dim:      #b9b3a8;
  --muted:         #7c8391;
  --muted-2:       #5a616d;

  --brass:         #c6a15b;
  --brass-bright:  #e0c085;
  --brass-deep:    #8a6e35;
  --jade:          #7fe3a0;
  --jade-deep:     #2f7a4e;
  --oxblood:       #a33b3b;
  --amber:         #d8933f;

  --shadow-lift:   0 1px 2px rgba(0,0,0,.5), 0 8px 24px -12px rgba(0,0,0,.8);
  --shadow-deep:   0 24px 64px -24px rgba(0,0,0,.9), 0 2px 8px rgba(0,0,0,.5);

  /* ---- Type ---- */
  --font-display: ui-serif, "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;
  --font-body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", "JetBrains Mono", Menlo, Consolas, monospace;

  /* Fluid scale, 360px → 1600px */
  --t-xs:   clamp(.688rem, .66rem + .12vw, .75rem);
  --t-sm:   clamp(.813rem, .78rem + .14vw, .875rem);
  --t-base: clamp(.938rem, .9rem + .18vw, 1.031rem);
  --t-md:   clamp(1.063rem, 1rem + .3vw, 1.25rem);
  --t-lg:   clamp(1.25rem, 1.1rem + .7vw, 1.75rem);
  --t-xl:   clamp(1.625rem, 1.3rem + 1.5vw, 2.75rem);
  --t-2xl:  clamp(2.125rem, 1.5rem + 2.9vw, 4.25rem);
  --t-3xl:  clamp(2.75rem, 1.6rem + 5.2vw, 6.5rem);

  /* ---- Space ---- */
  --s-1: .25rem;  --s-2: .5rem;   --s-3: .75rem;  --s-4: 1rem;
  --s-5: 1.5rem;  --s-6: 2rem;    --s-7: 3rem;    --s-8: 4rem;
  --s-9: 6rem;    --s-10: 8rem;   --s-11: 12rem;

  --gutter: clamp(1.25rem, 4vw, 4rem);
  --measure: 68ch;
  --max: 1440px;
  --max-narrow: 860px;

  --radius: 2px;
  --radius-lg: 4px;

  /* ---- Motion ---- */
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --dur-fast: 180ms;
  --dur: 420ms;
  --dur-slow: 900ms;

  --header-h: 4.5rem;
  color-scheme: dark;
}

/* Light theme is deliberately not offered. This is a single committed look —
   a gallery, not a dashboard — and a half-hearted light mode would weaken it.
   Forced-colors mode is supported separately below for accessibility. */

/* ==========================================================================
   Reset
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 2rem);
}

body {
  background: var(--obsidian);
  color: var(--bone);
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: 1.65;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  min-height: 100vh;
}

img, svg, video, canvas { display: block; max-width: 100%; }
input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
p, li, figcaption { text-wrap: pretty; }
h1, h2, h3, h4 { text-wrap: balance; }

:target { scroll-margin-top: calc(var(--header-h) + 2rem); }

/* ==========================================================================
   Typography
   ========================================================================== */

.display, h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -.022em;
}

h1 { font-size: var(--t-2xl); }
h2 { font-size: var(--t-xl); }
h3 { font-size: var(--t-lg); letter-spacing: -.015em; }
h4 { font-size: var(--t-md); font-family: var(--font-body); font-weight: 600; letter-spacing: -.01em; line-height: 1.3; }

.display-xl { font-size: var(--t-3xl); line-height: .96; letter-spacing: -.032em; }

.eyebrow {
  font-family: var(--font-body);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--brass);
}
.eyebrow--muted { color: var(--muted); }

.lede {
  font-size: var(--t-md);
  line-height: 1.6;
  color: var(--bone-dim);
  max-width: var(--measure);
}

.prose { max-width: var(--measure); }
.prose > * + * { margin-top: var(--s-4); }
.prose p { color: var(--bone-dim); }
.prose strong { color: var(--bone); font-weight: 600; }

.mono {
  font-family: var(--font-mono);
  font-size: .875em;
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
}

.num { font-variant-numeric: tabular-nums; letter-spacing: -.01em; }

.text-muted { color: var(--muted); }
.text-dim { color: var(--bone-dim); }
.text-brass { color: var(--brass); }

/* Rule with a centred label */
.rule {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  color: var(--muted);
}
.rule::before, .rule::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--line), transparent);
}

/* ==========================================================================
   Links & focus
   ========================================================================== */

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

.link {
  color: var(--brass);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .25em;
  text-decoration-color: color-mix(in srgb, var(--brass) 40%, transparent);
  transition: text-decoration-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.link:hover { text-decoration-color: var(--brass); color: var(--brass-bright); }

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
  border-radius: 1px;
}

.skip-link {
  position: absolute;
  left: var(--s-4);
  top: var(--s-4);
  z-index: 200;
  padding: var(--s-3) var(--s-5);
  background: var(--brass);
  color: var(--obsidian);
  font-weight: 600;
  font-size: var(--t-sm);
  transform: translateY(-200%);
  transition: transform var(--dur-fast) var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   Layout
   ========================================================================== */

.shell {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.shell--narrow { max-width: var(--max-narrow); }
.shell--wide { max-width: 1680px; }

.section { padding-block: clamp(3.5rem, 8vw, var(--s-10)); }
.section--tight { padding-block: clamp(2.5rem, 5vw, var(--s-8)); }
.section--flush-top { padding-top: 0; }

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

.grid { display: grid; gap: var(--s-5); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr)); }

.split {
  display: grid;
  gap: clamp(2rem, 5vw, var(--s-8));
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 62rem) {
  .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .split--sidebar { grid-template-columns: minmax(0, 1fr) minmax(0, 22rem); }
  .split--aside-left { grid-template-columns: minmax(0, 18rem) minmax(0, 1fr); }
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  align-items: center;
}
.cluster--between { justify-content: space-between; }
.cluster--tight { gap: var(--s-2); }

.sticky-aside { position: sticky; top: calc(var(--header-h) + var(--s-5)); }

/* Horizontally scrollable region — required for wide tables and diagrams so
   the page body itself never scrolls sideways. */
.scroll-x {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.scroll-x::-webkit-scrollbar { height: 8px; }
.scroll-x::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
.scroll-x::-webkit-scrollbar-track { background: transparent; }

/* ==========================================================================
   Surface treatments — the "cinematic" layer
   ========================================================================== */

/* --------------------------------------------------------------------------
   Boot splash

   The chrome is rendered from JS, so between first paint and initShell() the
   page is real content with no header or footer around it. This covers that
   with the seal, breathing, instead of letting the furniture snap into place.

   Built from body's own pseudo-elements: no markup on twenty-eight pages, and
   it paints with the render-blocking stylesheet. A splash injected by script
   would arrive after the moment it exists to cover.

   The pulse is a 1.6s fade — roughly 0.6Hz, well under the three-per-second
   threshold in WCAG 2.3.1. A logo that actually strobes is a photosensitivity
   hazard, so this reads as a slow breath rather than a flash.

   Both layers clear themselves on a delay whether or not script ever runs, so
   a module error can never leave the site behind a black curtain.
   -------------------------------------------------------------------------- */

body::before,
body::after {
  content: '';
  position: fixed;
  z-index: 200;
  /* Never intercept input — the content underneath is already real. */
  pointer-events: none;
}

body::before {
  inset: 0;
  background: var(--obsidian);
  animation: boot-clear .55s var(--ease-out) 2.2s forwards;
}

/* The artwork was drawn for a white field, so it gets the same bone panel it
   wears in the header. */
body::after {
  top: 50%;
  left: 50%;
  z-index: 201;
  width: 4.25rem;
  height: 4.25rem;
  margin: -2.125rem 0 0 -2.125rem;
  background: var(--bone) url('/assets/img/brand-mark.png') center / 78% no-repeat;
  border-radius: 4px;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--brass) 40%, transparent),
              0 6px 28px -10px rgba(0, 0, 0, .9);
  animation: boot-pulse 1.6s var(--ease-in-out) infinite,
             boot-clear .55s var(--ease-out) 2.2s forwards;
}

@keyframes boot-pulse {
  0%, 100% { opacity: .38; transform: scale(.97); }
  50%      { opacity: 1;   transform: scale(1); }
}
@keyframes boot-clear {
  to { opacity: 0; visibility: hidden; }
}

/* Already opened this session (see core/boot.js). Not a faster fade — no
   paint at all, because a fade-out on every internal link is the flicker the
   splash exists to avoid. */
:root[data-boot="skip"] body::before,
:root[data-boot="skip"] body::after { display: none; }

/* Script reached the end of the shell build: stop the pulse and hand over.
   Replacing the animation list rather than adding to it is what ends the
   infinite pulse. */
:root[data-booted] body::before,
:root[data-booted] body::after {
  animation: boot-clear .45s var(--ease-out) forwards;
}

/* A pulsing mark is motion. Hold it still, show it briefly, move on. */
@media (prefers-reduced-motion: reduce) {
  body::before,
  body::after { animation: boot-clear .3s linear .6s forwards; }
  :root[data-booted] body::before,
  :root[data-booted] body::after { animation: boot-clear .3s linear forwards; }
}

/* Film grain. A tiny inline SVG turbulence, tiled — no image request, and it
   sits above everything to unify the palette the way a print emulsion would. */
.grain {
  position: fixed;
  inset: -50%;
  pointer-events: none;
  z-index: 90;
  opacity: .16;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  animation: grain-shift 8s steps(6) infinite;
}
@keyframes grain-shift {
  0%   { transform: translate(0, 0); }
  16%  { transform: translate(-2%, 1%); }
  33%  { transform: translate(1%, -2%); }
  50%  { transform: translate(-1%, 2%); }
  66%  { transform: translate(2%, 1%); }
  83%  { transform: translate(-2%, -1%); }
  100% { transform: translate(0, 0); }
}

.vignette {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 89;
  background: radial-gradient(120% 90% at 50% 40%, transparent 45%, rgba(0,0,0,.55) 100%);
}

/* Soft directional glow used behind hero and feature blocks */
.glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  opacity: .5;
  pointer-events: none;
}

.hairline { border-top: 1px solid var(--line-soft); }

/* ==========================================================================
   Scroll-driven reveal
   ========================================================================== */

[data-reveal] {
  opacity: 0;
  transform: translateY(1.75rem);
  transition:
    opacity var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
[data-reveal].is-revealed { opacity: 1; transform: none; }
[data-reveal="fade"] { transform: none; }
[data-reveal="left"] { transform: translateX(-1.5rem); }
[data-reveal="scale"] { transform: scale(.97); }

/* Staggered children */
[data-reveal-group] > * {
  opacity: 0;
  transform: translateY(1.25rem);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}
[data-reveal-group].is-revealed > * { opacity: 1; transform: none; }
[data-reveal-group].is-revealed > *:nth-child(1) { transition-delay: 0ms; }
[data-reveal-group].is-revealed > *:nth-child(2) { transition-delay: 70ms; }
[data-reveal-group].is-revealed > *:nth-child(3) { transition-delay: 140ms; }
[data-reveal-group].is-revealed > *:nth-child(4) { transition-delay: 210ms; }
[data-reveal-group].is-revealed > *:nth-child(5) { transition-delay: 280ms; }
[data-reveal-group].is-revealed > *:nth-child(6) { transition-delay: 350ms; }
[data-reveal-group].is-revealed > *:nth-child(n+7) { transition-delay: 420ms; }

/* ==========================================================================
   Reduced motion — honoured properly, not just shortened
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal], [data-reveal-group] > * { opacity: 1 !important; transform: none !important; }
  .grain { animation: none; }
}

/* ==========================================================================
   Forced colours / high contrast
   ========================================================================== */

@media (forced-colors: active) {
  body::before, body::after { display: none; }
  .grain, .vignette, .glow { display: none; }
  .card, .panel, .field { border: 1px solid CanvasText; }
  .btn { border: 1px solid ButtonText; }
}

/* ==========================================================================
   Print
   ========================================================================== */

@media print {
  :root { --obsidian: #fff; --bone: #000; }
  body { background: #fff; color: #000; }
  body::before, body::after { display: none !important; }
  .grain, .vignette, .glow, .site-header, .site-footer,
  .compare-tray, .cmdk, .hero-canvas, [data-no-print] { display: none !important; }
  [data-reveal], [data-reveal-group] > * { opacity: 1 !important; transform: none !important; }
  .card, .panel { border: 1px solid #ccc; break-inside: avoid; }
  a::after { content: " (" attr(href) ")"; font-size: .8em; color: #555; }
  a[href^="#"]::after, a[href^="javascript"]::after { content: ""; }
}
