/* ==========================================================================
   Base — reset ringan, tipografi dasar, aksesibilitas
   ========================================================================== */

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

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  position: relative;
  font-family: var(--font-text);
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--foreground);
  background: var(--background);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Whisper of grain over the whole page — the flat off-white otherwise reads
   as cheap/empty rather than calm; a near-invisible noise film gives it the
   tactile, editorial-paper depth premium sites use instead of color/shadow. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 999;
  opacity: 0.035;
  mix-blend-mode: multiply;
  pointer-events: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

/* Slow drift shared by decorative ambient blobs (hero/final/feature block).
   Kept off under reduced-motion regardless of the has-motion (reveal) state —
   this is ambient decoration, not a reveal, so it isn't gated by JS. */
@keyframes ambient-float {
  0%,
  100% {
    transform: translate3d(0, 0, 0) scale(1);
  }
  50% {
    transform: translate3d(2%, -3%, 0) scale(1.05);
  }
}

@media (prefers-reduced-motion: reduce) {
  body::before {
    display: none;
  }
}

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

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

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

ul,
ol,
dl {
  padding: 0;
  list-style: none;
}

/* --- Judul ------------------------------------------------------------------ */
/* Weight/size are set per usage (.hero__title, .h-display, .h2, h3 itself) —
   editorial hierarchy mixes a light 300 display face with a 400 headline
   face, so a single shared h1/h2 rule would fight one of the two. */

h1,
h2,
h3 {
  font-family: var(--font-display);
  line-height: 1.1;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

/* text-wrap:balance recomputes line breaks against the text's natural word
   boxes — it doesn't account for the inline-block .w wrappers the split-word
   reveal uses, and on some viewport widths that mismatch lets the last word
   overflow past the edge instead of wrapping. Split headings need normal
   wrapping instead. */
[data-split] {
  text-wrap: normal;
}

h3 {
  font-size: var(--t-h3);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

/* Display face: hero, brand statement, the dark "unusual" section, final CTA.
   Light weight + tight tracking is the "editorial high-fashion tech" look
   DESIGN.md calls for on large type. */
.h-display {
  font-size: var(--t-display);
  font-weight: 300;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

/* Headline face: section intros ("Teknologi yang Dibuat...", "Cara Kami
   Bekerja") — one step down from display, normal weight. */
.h-headline {
  font-size: var(--t-h2);
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

/* <em> di judul = penekanan warna + italic, bukan sekadar warna — mengikuti
   pola desain sumber (Stitch): baris aksen tampil miring. Sage gelap dipakai
   (bukan sage mentah) supaya kontras teks tetap memenuhi AA di atas
   background terang. */
em {
  font-style: italic;
  color: var(--brand-dark);
}

p {
  text-wrap: pretty;
}

strong {
  font-weight: 600;
}

/* --- Aksesibilitas ------------------------------------------------------------ */

:focus-visible {
  outline: 3px solid var(--primary-hover);
  outline-offset: 3px;
  border-radius: 4px;
}

::selection {
  background: var(--brand-dark);
  color: var(--cta-text);
}

.skip-link {
  position: absolute;
  top: 0;
  left: 50%;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  font-weight: 600;
  color: var(--cta-text);
  background: var(--cta);
  border-radius: 0 0 var(--r-md) var(--r-md);
  transform: translate(-50%, -120%);
  transition: transform var(--dur) var(--ease-out);
}

.skip-link:focus-visible {
  transform: translate(-50%, 0);
}

/* --- Sistem reveal ------------------------------------------------------------ */
/* Konten tidak pernah disembunyikan permanen: state awal hanya berlaku saat JS
   motion aktif (html.has-motion), sehingga tanpa JS semuanya tetap terbaca. */

.has-motion [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  will-change: opacity, transform;
}

.has-motion [data-reveal].is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  .has-motion [data-reveal],
  .has-motion [data-reveal].is-in {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* --- Reveal per kata ---------------------------------------------------------- */

.w {
  display: inline-block;
  overflow: hidden;
  overflow: clip;
  overflow-clip-margin: 0.3em;
  vertical-align: bottom;
  padding-bottom: 0.22em;
  margin-bottom: -0.22em;
}

.w > i {
  display: inline-block;
  font-style: inherit;
}

.has-motion .w > i {
  transform: translate3d(0, 120%, 0);
  will-change: transform;
}

.has-motion [data-split].is-in .w > i {
  transform: none;
  transition: transform 680ms var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
  .has-motion .w > i {
    transform: none;
  }
}
