@import './tokens.css';

/* Jost (SIL OFL 1.1, see assets/fonts/Jost-OFL.txt): an open geometric sans
   standing in for Futura PT, which the stack named but never loaded. One
   variable file covers every weight; latin subset only. Preloaded per page. */
@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../../assets/fonts/jost-latin-wght.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

* {
  box-sizing: border-box;
}

html {
  min-height: 100%;
  scroll-behavior: smooth;
  background: var(--color-parchment);
}

/* Lenis smooth-scroll integration. When Lenis is active it owns the scroll, so
   native smooth scroll-behavior must yield to it to avoid the two fighting. */
html.lenis,
html.lenis body {
  height: auto;
}

.lenis.lenis-smooth {
  scroll-behavior: auto !important;
}

.lenis.lenis-smooth [data-lenis-prevent] {
  overscroll-behavior: contain;
}

.lenis.lenis-stopped {
  overflow: hidden;
}

body {
  min-height: 100%;
  margin: 0;
  overflow-x: clip;
  background: var(--color-parchment);
  color: var(--color-charcoal);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Form controls pick up the page font. (`body` must NOT be in this list:
   the `font` shorthand would reset the font-family set on body above to
   html's UA default -- Times -- killing the --font-sans stack site-wide.) */
button,
input,
select,
textarea {
  font: inherit;
}

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

button {
  color: inherit;
}

button,
a {
  -webkit-tap-highlight-color: transparent;
}

img,
video,
canvas {
  display: block;
  max-width: 100%;
}

figure {
  margin: 0;
}

main {
  position: relative;
  z-index: 2;
  background: var(--color-parchment);
}

/* gold ring with a dark band either side, so focus stays visible over
   light photos as well as the dark page (WCAG 1.4.11) */
:focus-visible {
  outline: 2px solid var(--color-brass);
  outline-offset: 3px;
  box-shadow: 0 0 0 7px color-mix(in oklab, var(--color-mahogany-dark) 85%, transparent);
}

.section {
  padding: clamp(5rem, 10vw, 10rem) 6vw;
}

.container {
  width: min(1240px, calc(100% - var(--grid-margin) * 2));
  margin: 0 auto;
}

.light {
  background: var(--color-parchment);
  color: var(--color-charcoal);
}

.dark {
  background: var(--color-mahogany-dark);
  color: var(--color-ivory);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Skip link — visually hidden until focused by keyboard (#4) */
.skip-link {
  position: fixed;
  top: 0.5rem;
  left: 0.5rem;
  z-index: 9999;
  padding: 0.6em 1.1em;
  border-radius: var(--radius-pill);
  background: var(--color-brass);
  color: var(--color-mahogany-dark);
  font-family: var(--font-sans);
  font-size: var(--font-size-body-sm);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  /* Off-screen when not focused */
  transform: translateY(-200%);
  transition: transform var(--duration-fast) var(--ease-soft);
}

.skip-link:focus-visible {
  transform: translateY(0);
  outline: 2px solid var(--color-ivory);
  outline-offset: 2px;
}

/* Reveal start states only apply under html.js (set by src/scripts/boot.js),
   so content stays visible when scripts are blocked or fail. */
html.js [data-reveal] {
  opacity: 0;
  transform: translateY(32px);
  transition:
    opacity var(--duration-medium) var(--ease-soft),
    transform var(--duration-medium) var(--ease-soft);
}

html.js [data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

.image-reveal {
  position: relative;
  overflow: hidden;
}

/* <picture> wrappers must not add a box: every image rule targets the img
   as if it were the figure's direct child */
picture {
  display: contents;
}

.image-reveal img,
.image-reveal video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

html.js .image-reveal img,
html.js .image-reveal video {
  transform: scale(1.08);
  clip-path: inset(0 0 100% 0);
  transition:
    transform 1.35s var(--ease-out-expo),
    clip-path 1.1s var(--ease-out-expo),
    opacity 450ms var(--ease-soft);
}

html.js .image-reveal.is-visible img,
html.js .image-reveal.is-visible video {
  transform: scale(1);
  clip-path: inset(0 0 0 0);
}

.ratio-wide {
  aspect-ratio: 16 / 9;
}

.poster-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

[data-webgl-card] {
  position: relative;
}

.webgl-card-canvas {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

[data-webgl-card].has-webgl img {
  opacity: 0;
}

.cursor {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 1600;
  width: 0;
  height: 0;
  opacity: 0;
  pointer-events: none;
  transform: translate3d(-100px, -100px, 0);
  transition: opacity var(--duration-fast) var(--ease-soft);
}

.cursor.is-visible {
  opacity: 1;
}

/* Cursor dot: fixed 18px base — states use transform:scale() (compositor-only, #7) */
.cursor-dot {
  --cursor-scale: 1;
  --cursor-press: 1;

  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  place-items: center;
  width: 18px;          /* fixed — never animate width/height */
  height: 18px;
  border-radius: var(--radius-pill);
  background: var(--color-ivory);
  color: var(--color-charcoal);
  mix-blend-mode: difference;
  transform: translate(-50%, -50%) scale(calc(var(--cursor-scale) * var(--cursor-press)));
  transition:
    transform var(--duration-fast) var(--ease-soft),
    background var(--duration-fast) var(--ease-soft),
    border-color var(--duration-fast) var(--ease-soft);
}

/* is-link: 2.5× (45px), Onyx's hover size; transform only, no layout (#7) */
.cursor.is-link .cursor-dot {
  --cursor-scale: 2.5;

  border: 1px solid color-mix(in oklab, var(--color-charcoal) 18%, transparent);
  background: color-mix(in oklab, var(--color-brass) 24%, transparent);
  mix-blend-mode: normal;
}

/* is-media: 3.2× (58px) over photos; transform only, no layout (#7) */
.cursor.is-media .cursor-dot {
  --cursor-scale: 3.2;

  border: 1px solid color-mix(in oklab, var(--color-charcoal) 22%, transparent);
  background: color-mix(in oklab, var(--color-ivory) 70%, transparent);
  mix-blend-mode: normal;
}

/* press squashes from the current size and springs back on release, like
   Onyx's click pulse */
.cursor.is-pressed .cursor-dot {
  --cursor-press: 0.6;
}

@media (pointer: coarse), (prefers-reduced-motion: reduce) {
  .cursor {
    display: none;
  }
}

/* keeps a short phrase (an hours range) on one line */
.nowrap {
  white-space: nowrap;
}

[data-char-reveal] {
  perspective: 600px;
}

.char {
  display: inline-block;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }

  html {
    scroll-behavior: auto;
  }

  html.js [data-reveal],
  html.js .image-reveal img,
  html.js .image-reveal video {
    opacity: 1;
    transform: none;
    clip-path: none;
  }

  [data-char-reveal] .char {
    opacity: 1;
    transform: none;
  }
}
