/* ============================================================
   base.css — design tokens, fonts, reset and global typography
   ============================================================ */

/* ---- Brand fonts --------------------------------------------------
   Display: Chakra Petch (OFL) — squared, technical, engineered feel.
   Text:    IBM Plex Mono (OFL) — precise, code-native body voice.
   Both self-hosted (latin subset) from Google Fonts. ------------------ */
@font-face {
  font-family: "Chakra Petch";
  src: url("../assets/fonts/chakra-petch-500.woff2") format("woff2");
  font-weight: 100 599;
  font-display: swap;
}

@font-face {
  font-family: "Chakra Petch";
  src: url("../assets/fonts/chakra-petch-700.woff2") format("woff2");
  font-weight: 600 900;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("../assets/fonts/ibm-plex-mono-400.woff2") format("woff2");
  font-weight: 100 449;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("../assets/fonts/ibm-plex-mono-500.woff2") format("woff2");
  font-weight: 450 599;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("../assets/fonts/ibm-plex-mono-700.woff2") format("woff2");
  font-weight: 600 900;
  font-display: swap;
}

/* ---- Design tokens ------------------------------------------------ */
:root {
  /* palette — Devsteem brand teal
     (--c-brown / --c-burnt / --c-rose keep their names but now hold the
      deep / mid / bright teals so the whole site recolours from here) */
  --c-brown: #004d63;        /* deep teal — primary-dark, used for dark fields */
  --c-brown-fade: #004d6300; /* same, transparent (gradient stops)            */
  --c-burnt: #006885;        /* mid teal — primary, chips / accents            */
  --c-rose: #00a8cc;         /* bright teal — highlights                       */
  --c-white: #fff;
  --c-ink: #646464;
  --c-mist: #dedede;
  --c-haze: #f4f4f4;
  /* extra brand stops, available if needed */
  --c-teal-soft: #4dd0e1;
  --c-teal-pale: #b2ebf2;

  /* type families */
  --font-display: "Chakra Petch", "sans-serif";
  --font-text: "IBM Plex Mono", monospace;

  /* motion */
  --ease-soft: cubic-bezier(0, 0, 0.2, 1);
  --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);
}

/*
  Layout breakpoints used throughout the stylesheets:
    phone      576px
    compact    768px
    tablet    1024px
    laptop    1280px
    wide      1440px
    cinema    1600px
*/

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

html,
body {
  overscroll-behavior: none;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

body {
  font-family: var(--font-text);
  font-size: 0.875rem;
  line-height: 1.625;
  color: var(--c-brown);
  min-height: 100vh;
}

@media (min-width: 1600px) {
  body {
    line-height: 1.5;
  }
}

ul,
ol,
menu {
  list-style: none;
}

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

img,
svg,
video,
canvas,
iframe {
  display: block;
  vertical-align: middle;
}

img,
video {
  max-width: 100%;
  height: auto;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  background-color: transparent;
  border: 0;
  border-radius: 0;
}

strong,
b {
  font-weight: 700;
}

/* used by GSAP SplitText line masks and the menu toggle */
.mask-lines {
  overflow: hidden;
}
.overflow-hidden {
  overflow: hidden;
}

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

/* ---- Type scale --------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  /* Chakra Petch needs the bold cut to match the presence the old
     display font had at its single (bold) weight */
  font-weight: 700;
}

h1, .ty-h1 {
  font-size: 2.25rem;
  line-height: 1.1;
}
@media (min-width: 768px) {
  h1, .ty-h1 { font-size: 3rem; }
}
@media (min-width: 1280px) {
  h1, .ty-h1 { font-size: 4.5rem; }
}
@media (min-width: 1600px) {
  h1, .ty-h1 { font-size: 80px; line-height: 1.1; }
}

h2, .ty-h2 {
  font-size: 1.875rem;
  line-height: 1.1;
}
@media (min-width: 576px) {
  h2, .ty-h2 { font-size: 2.25rem; }
}
@media (min-width: 1280px) {
  h2, .ty-h2 { font-size: 3rem; }
}

h3, .ty-h3 {
  font-size: 1.875rem;
  line-height: 1.1;
}

h4, .ty-h4 {
  font-size: 1.5rem;
  line-height: 1.25;
}

h5, .ty-h5 {
  font-size: 4.5rem;
  line-height: 1.1;
}

h6, .ty-h6 {
  font-size: 1.25rem;
  line-height: 1.25;
}
@media (min-width: 1280px) {
  h6, .ty-h6 { font-size: 1.5rem; }
}

.kicker {
  font-family: var(--font-display);
  font-size: 18px;
  line-height: 1;
}

.copy-indent {
  text-indent: 3rem;
}

/* ---- Shared accents ----------------------------------------------- */
.spark {
  animation: blip 1s infinite;
}

@keyframes blip {
  0%,
  100% { opacity: 1; }
  50% { opacity: 0; }
}

/* shooting star used beside headings — a fading trail tipped with a
   glowing star that streaks toward the words (replaces the plain rule) */
.hairline {
  position: relative;
  height: 2px;
  width: 44px;
  background-image: linear-gradient(
    to left,
    var(--rule-color, currentColor),
    transparent
  );
  flex-shrink: 0;
}
.hairline::after {
  content: "";
  position: absolute;
  right: -3px;
  top: 50%;
  width: 9px;
  height: 9px;
  transform: translateY(-50%);
  background-color: var(--rule-color, currentColor);
  clip-path: polygon(
    50% 0,
    58% 42%,
    100% 50%,
    58% 58%,
    50% 100%,
    42% 58%,
    0 50%,
    42% 42%
  );
  filter: drop-shadow(0 0 4px rgba(0, 168, 204, 0.8));
}
@media (min-width: 576px) {
  .hairline { width: 64px; }
}
@media (min-width: 1280px) {
  .hairline { width: 120px; }
}

/* ---- Lenis smooth-scroll hooks ------------------------------------ */
html.lenis,
html.lenis body {
  height: auto;
}
.lenis.lenis-smooth [data-lenis-prevent] {
  overscroll-behavior: contain;
}
.lenis.lenis-stopped {
  overflow: clip;
}
.lenis.lenis-smooth iframe {
  pointer-events: none;
}

/* ---- Film-grain texture -------------------------------------------- */
/* The noise is painted per background surface — not as one fixed layer
   over the page — so on every surface it sits ABOVE the background but
   BELOW the content laid over it:  background → grain → content.
   The noise is desaturated to pure luminance so it reads as texture
   regardless of the colour underneath.
   Tune the feel:
     --grain-opacity — how visible the grain is (0.05 subtle … 0.2 heavy)
     baseFrequency   — grain size (higher = finer/tighter speckle)
     background-size — tile scale on screen                              */
:root {
  --grain-opacity: 0.18;
  --grain-img: url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='grain'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.6' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='3' intercept='-1.69'/%3E%3CfeFuncG type='linear' slope='3' intercept='-1.69'/%3E%3CfeFuncB type='linear' slope='3' intercept='-1.69'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23grain)'/%3E%3C/svg%3E");
}

/* Over the live 3D scene (hero journey + wherever the pinned scene shows
   through: CTA band, footer wordmark). The scene canvas stacks at z-auto;
   the copy layered over it sits at z 20/30, so grain at z 10 lands
   between them. */
#scene::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 10;
  pointer-events: none;
  opacity: var(--grain-opacity);
  background-image: var(--grain-img);
  background-size: 180px 180px;
}

/* Flat background fields. Each of these owns a stacking context, so a
   negative-z pseudo paints above the element's own background but below
   every descendant (text, images, devices). */
.opener::after,
.slab::before,
.ribbon__inner::before,
.mirror-hall::after,
.pagefoot__panel::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: var(--grain-opacity);
  background-image: var(--grain-img);
  background-size: 180px 180px;
}
/* .ribbon__inner has no stacking context of its own — give it one so the
   negative-z grain stays above its background instead of escaping under it */
.ribbon__inner {
  isolation: isolate;
}
/* The mirror hall paints its backdrop in a canvas (z auto): grain at z 0
   slots above the render, below the CSS3D card labels (z 1) and HUD (z 3) */
.mirror-hall::after {
  z-index: 0;
}
