/* ==========================================================================
   BONDEE — RESET, LAYOUT PRIMITIVES, TYPE CLASSES
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: auto; /* Lenis owns scrolling */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--f-display);
  font-size: var(--t-body);
  line-height: var(--t-body-lh);
  letter-spacing: var(--t-body-ls);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
  overflow-x: clip; /* never a horizontal scrollbar; clip beats hidden here */
}

h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg, video { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
input { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

/* Visible, on-brand focus. A company selling machine-readability cannot ship
   focus-invisible interactive elements. */
:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
}

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

.skip-link {
  position: fixed; top: 0; left: 50%; translate: -50% -120%;
  z-index: 10000; padding: 0.75rem 1.25rem;
  background: var(--signal); color: #fff;
  font-family: var(--f-label); font-size: var(--t-label);
  letter-spacing: var(--t-label-ls); text-transform: uppercase;
  transition: translate var(--d-micro) var(--e-soft);
}
.skip-link:focus-visible { translate: -50% 0; }

/* --------------------------------------------------------------------------
   GRAIN — one fixed node, one paint. No per-frame cost.
   -------------------------------------------------------------------------- */
.grain {
  position: fixed;
  inset: 0;
  z-index: 9000;
  pointer-events: none;
  opacity: var(--grain-opacity);
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
  will-change: transform;
}

/* --------------------------------------------------------------------------
   LAYOUT PRIMITIVES
   -------------------------------------------------------------------------- */
/* width:100% is load-bearing. Inside a flex column (.hero), an auto inline
   margin cancels align-self: stretch and the shell shrink-wraps to its content
   — which silently narrows the hero and adds a line to the headline. */
.shell {
  width: 100%;
  padding-inline: var(--margin);
  max-width: 120rem;
  margin-inline: auto;
}

@media (min-width: 1280px) {
  .shell { padding-left: calc(var(--margin) + var(--rail-w)); }
}

.grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
  gap: var(--gutter);
}

.section {
  position: relative;
  background: var(--bg);
  color: var(--fg);
  padding-block: clamp(5rem, 12vh, 11rem);
}

/* Hairline that reads as a document rule, not a border. */
.rule { border: 0; height: 1px; background: var(--rule); width: 100%; }

/* --------------------------------------------------------------------------
   TYPE CLASSES
   Display is always lowercase. Positive tracking only on mono uppercase.
   -------------------------------------------------------------------------- */
.d1, .d2, .d3 {
  font-family: var(--f-display);
  font-weight: 500;
  text-transform: lowercase;
}

/* balance is right for two- and three-word section heads. On the hero it
   redistributes into an extra line, so d1 breaks naturally instead. */
.d2, .d3 { text-wrap: balance; }

.d1 { font-size: var(--t-d1); line-height: var(--t-d1-lh); letter-spacing: var(--t-d1-ls); }
.d2 { font-size: var(--t-d2); line-height: var(--t-d2-lh); letter-spacing: var(--t-d2-ls); }
.d3 { font-size: var(--t-d3); line-height: var(--t-d3-lh); letter-spacing: var(--t-d3-ls); }

/* The single most Trionn-ish gesture: one serif italic word inside a grotesk
   headline. Exactly one per headline — enforced by review, not by CSS. */
.accent {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--signal);
  letter-spacing: -0.01em;
  /* Instrument Serif runs optically smaller than Familjen at the same px. */
  font-size: 1.08em;
  text-transform: none;
}

.numeral {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: var(--t-numeral);
  line-height: var(--t-numeral-lh);
  letter-spacing: var(--t-numeral-ls);
  font-variant-numeric: tabular-nums;
}

.lead {
  font-size: var(--t-lead);
  line-height: var(--t-lead-lh);
  letter-spacing: var(--t-lead-ls);
  max-width: 34ch;
  color: var(--fg);
}

.body { max-width: 62ch; color: var(--fg-muted); }

.label,
.micro {
  font-family: var(--f-label);
  font-weight: 300;
  text-transform: uppercase;
  font-feature-settings: "tnum" 1;
}

.label { font-size: var(--t-label); line-height: var(--t-label-lh); letter-spacing: var(--t-label-ls); }
.micro { font-size: var(--t-micro); line-height: var(--t-micro-lh); letter-spacing: var(--t-micro-ls); }

.muted { color: var(--fg-muted); }
.signal { color: var(--signal); }

.mono { font-family: var(--f-mono); font-weight: 300; }

/* --------------------------------------------------------------------------
   JAPANESE
   ch is the width of "0" — a half-width glyph — so a Latin ch-based measure
   collapses to roughly half the intended line length in Japanese. Measures are
   restated in em, where 1em is one full-width character.
   -------------------------------------------------------------------------- */
html[lang="ja"] .accent {
  font-style: normal;   /* Mincho has no italic; a synthesised slant looks broken */
  font-size: 1em;       /* and it needs no optical size correction either */
  letter-spacing: -0.02em;
}

html[lang="ja"] .d1,
html[lang="ja"] .d2,
html[lang="ja"] .d3 {
  word-break: auto-phrase; /* break on phrase boundaries, not mid-word */
  line-break: strict;      /* honour kinsoku shori */
}

html[lang="ja"] .lead { max-width: 24em; }
html[lang="ja"] .body { max-width: 32em; }

/* Locale crossfade. CSS-driven so the swap survives a throttled rAF. */
main, .footer { transition: opacity 0.35s var(--e-soft); }
html.locale-swapping main,
html.locale-swapping .footer { opacity: 0; transition-duration: 0.22s; }

/* --------------------------------------------------------------------------
   SECTION HEADER — number, slug, hairline. The connective tissue.
   -------------------------------------------------------------------------- */
.sec-head {
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
  padding-bottom: 1rem;
  margin-bottom: clamp(2.5rem, 6vh, 5rem);
  border-bottom: 1px solid var(--rule);
}
.sec-head__num { color: var(--signal); }
.sec-head__slug { color: var(--fg-muted); }
.sec-head__meta { margin-left: auto; color: var(--fg-muted); text-align: right; }

/* --------------------------------------------------------------------------
   MASKED LINE REVEAL — SplitText writes into these
   -------------------------------------------------------------------------- */
.line-mask { overflow: hidden; display: block; }

/* Pre-reveal state, removed by JS once GSAP takes over so no-JS still reads. */
.js [data-reveal] > .line-mask > * { will-change: transform; }

/* --------------------------------------------------------------------------
   MARQUEE
   -------------------------------------------------------------------------- */
.marquee {
  display: flex;
  width: max-content;
  gap: 0;
  will-change: transform;
}
.marquee__item {
  display: flex;
  align-items: center;
  gap: 2.5rem;
  padding-right: 2.5rem;
  white-space: nowrap;
}
.marquee-wrap { overflow: hidden; }

/* --------------------------------------------------------------------------
   BUTTONS / LINKS
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9375rem 1.5rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  font-family: var(--f-label);
  font-size: var(--t-label);
  letter-spacing: var(--t-label-ls);
  text-transform: uppercase;
  transition: background-color var(--d-micro) var(--e-soft),
              color var(--d-micro) var(--e-soft),
              border-color var(--d-micro) var(--e-soft);
}
.btn:hover { background: var(--signal); border-color: var(--signal); color: #fff; }

.btn--solid { background: var(--signal); border-color: var(--signal); color: #fff; }
.btn--solid:hover { background: var(--signal-dim); border-color: var(--signal-dim); }

/* Underline that draws rather than appears. */
.ul-link { position: relative; }
.ul-link::after {
  content: "";
  position: absolute; left: 0; bottom: -0.15em;
  width: 100%; height: 1px;
  background: currentColor;
  scale: 0 1; transform-origin: left;
  transition: scale var(--d-ui) var(--e-soft);
}
.ul-link:hover::after { scale: 1 1; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.2s !important;
  }
  .grain { display: none; }
}
