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

/* O display:none que o browser dá a [hidden] vem do stylesheet do agente do
   utilizador, por isso perde para qualquer regra de autor que declare display,
   por menos específica que seja. Sem este reset, marcar um elemento como
   hidden no HTML não o esconde de facto: o painel de cookies abria sempre
   expandido (.cookie-consent__choices tem display:grid) e tapava 91% do ecrã
   em 390px, e o mesmo acontecia a campos de formulário condicionais.
   O !important é necessário porque components.css carrega depois deste
   ficheiro e ganharia na cascata. Regra verificada por check-design.mjs
   (regra hidden-leak). */
[hidden] {
  display: none !important;
}

html {
  font-family: var(--font-display);
  font-size: 16px;
  line-height: 1.4;
  color: var(--colors-blue);
  background: var(--colors-mercury);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

html::-webkit-scrollbar {
  display: none;
}

body {
  min-height: 100vh;
  background: var(--colors-mercury);
  color: var(--colors-blue);
  /* clip (not hidden) prevents horizontal scroll WITHOUT creating a scroll
     container, so position: sticky keeps working (e.g. .chrono-pin). */
  overflow-x: clip;
}

body.smoothscroll-body {
  height: 100vh;
  overflow: hidden;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1;
  color: inherit;
}

p {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.45;
  color: inherit;
}

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

button {
  font-family: var(--font-mono);
  font-size: var(--fs-14);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: transparent;
  border: none;
  color: inherit;
  cursor: pointer;
  padding: 0;
}

ul, ol {
  list-style: none;
}

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

::selection {
  background: var(--colors-accent);
  color: var(--colors-white);
}

::-moz-selection {
  background: var(--colors-accent);
  color: var(--colors-white);
}

/* Mono pattern is now Inter w/ wide tracking + tabular numerals — simulates a
   technical label without an actual monospace face. */
.mono {
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
  font-size: var(--fs-14);
  line-height: 1.1;
  font-feature-settings: "tnum", "ss01";
}

.mono-12 {
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
  font-size: var(--fs-14);
  line-height: 1.1;
  font-feature-settings: "tnum", "ss01";
}

.b-blue {
  border: var(--line) solid var(--colors-blue);
}

.bt-blue {
  border-top: var(--line) solid var(--colors-blue);
}

.bb-blue {
  border-bottom: var(--line) solid var(--colors-blue);
}

.bl-blue {
  border-left: var(--line) solid var(--colors-blue);
}

.br-blue {
  border-right: var(--line) solid var(--colors-blue);
}

.bg-blue { background: var(--colors-blue); color: var(--colors-mercury); }
.bg-mercury { background: var(--colors-mercury); color: var(--colors-blue); }
.bg-white { background: var(--colors-white); color: var(--colors-blue); }
.text-blue { color: var(--colors-blue); }
.text-mercury { color: var(--colors-mercury); }
.text-white { color: var(--colors-white); }

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

.reveal-mask {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  line-height: 1;
  /* Extra space inside the mask so descenders (g, p, y) and PT-PT
     diacritics (ç, ã, õ) don't get clipped by the overflow box.
     Negative margin compensates so layout stays put. */
  padding-bottom: 0.22em;
  margin-bottom: -0.22em;
}

.reveal-mask > span {
  display: inline-block;
  will-change: transform;
}

.js .reveal-mask > span {
  transform: translateY(110%);
}

.js .is-revealed .reveal-mask > span {
  transform: translateY(0);
}

.js .fade-up,
.js [data-fade-up] {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity var(--dur-800) var(--ease-out-expo),
    transform var(--dur-800) var(--ease-out-expo);
  will-change: opacity, transform;
}

.js .is-revealed.fade-up,
.js .fade-up.is-revealed,
.js .is-revealed[data-fade-up] {
  opacity: 1;
  transform: translateY(0);
}

/* Accessibility — honour the user's motion preference.
   When reduced-motion is requested, all reveals become instant (no transform,
   no opacity transition). Content stays accessible; only the staging removes. */
@media (prefers-reduced-motion: reduce) {
  .js .fade-up,
  .js [data-fade-up],
  .js .reveal-mask > span,
  .js [data-split] .split-char__i {
    transition: none !important;
    transform: none !important;
    opacity: 1 !important;
  }
  .js .hero__rules > span {
    animation: none !important;
    opacity: 0.22;
    transform: scaleY(1);
  }
  .js .stair-fill__bar {
    transition: none !important;
    transform: scaleX(1);
  }
  .js .process-card {
    transition: none !important;
    transform: rotate(var(--rot)) !important;
    opacity: 1 !important;
  }
  .btn,
  .btn::before {
    transition: none !important;
  }
  .menu-overlay {
    transition: none !important;
  }
}

/* split-text: per-character reveal (used on hero titles, split titles, testimonials, process pinned titles) */
.split-word {
  display: inline-block;
  white-space: nowrap;
}
.split-char {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  line-height: inherit;
  padding-bottom: 0.22em;
  margin-bottom: -0.22em;
}
.split-char__i {
  display: inline-block;
  transform: translateY(102%);
  opacity: 0;
  will-change: transform, opacity;
}
.js [data-split] .split-char__i {
  transition-property: transform, opacity;
  transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.js [data-split].is-split-revealed .split-char__i {
  transform: translateY(0);
  opacity: 1;
}

/* ============================== PAGE TRANSITIONS ============================== */
/* Native cross-document crossfade (opacity) between same-origin pages.
   The default `root` view transition is an opacity fade: the outgoing page
   fades out while the incoming page fades in.
   Supported in Chrome/Edge 126+ and Safari 18.2+; other browsers fall back
   to an instant navigation with no visual change. */
@view-transition {
  navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 420ms;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
  }
}
