/* Eto landing: tokens, base, type, buttons, icons. Loaded first.
   Fonts: Perfectly Nineties (local) for headings, Geist and Geist Mono
   (aside.com, hyperspell.com, generaltranslation.com, replicas.dev) for
   everything else, Givonic (local) for the wordmark. */

@font-face { font-family: "Perfectly Nineties"; src: url("fonts/PerfectlyNineties-Regular.otf") format("opentype"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Perfectly Nineties"; src: url("fonts/PerfectlyNineties-Italic.otf") format("opentype"); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: "Givonic"; src: url("fonts/Givonic-Regular.otf") format("opentype"); font-weight: 400; font-style: normal; font-display: swap; }

:root {
  color-scheme: light;
  --bg: #ffffff;
  --bg-2: #fafafa;
  --ink: #070707;                 /* generaltranslation.com ink */
  --text: #18181b;
  --muted: rgba(7, 7, 7, 0.63);   /* generaltranslation.com body */
  --faint: rgba(7, 7, 7, 0.45);
  --line: #e4e4e7;                /* generaltranslation.com hairline */
  --line-2: #d4d4d8;
  --ink-5: rgba(7, 7, 7, 0.05);   /* hover fill on generaltranslation.com and aside.com */
  --accent: #E98146;              /* Eto orange: brand mark, glow, button sweep */
  --glow: #E98146;
  --font-display: "Perfectly Nineties", "Iowan Old Style", Georgia, serif;
  --font-body: "Geist", ui-sans-serif, system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --font-mark: "Givonic", "Geist", sans-serif;
  --container: 1280px;            /* hyperspell.com and radiusbrowser.com max width */
  --gutter: 20px;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);  /* radiusbrowser.com hero-window-rise */
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--bg); scrollbar-width: none; -ms-overflow-style: none; }
html::-webkit-scrollbar { width: 0; height: 0; display: none; }

body.lp {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}
.lp ::selection { background: #e4e4e7; color: var(--ink); }
.lp a { color: inherit; text-decoration: none; }
.lp a:focus-visible, .lp button:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; border-radius: 4px; }
.lp button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
.lp img, .lp svg { display: block; }
:where(.lp h1, .lp h2, .lp h3, .lp h4, .lp p, .lp ul, .lp figure) { margin: 0; font-weight: 400; }
:where(.lp ul) { padding: 0; list-style: none; }

/* Lucide icons: full sprite in lucide.svg, glyphs in currentColor. */
.lp .li { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.lp .li-sm { width: 15px; height: 15px; }
.lp .li-lg { width: 24px; height: 24px; }

/* Type */
.lp-h1 { font-family: var(--font-display); font-weight: 400; font-size: clamp(34px, 8.4vw, 72px); line-height: 1.0; letter-spacing: -0.015em; color: var(--ink); text-wrap: balance; }
.lp-h2 { font-family: var(--font-display); font-weight: 400; font-size: clamp(27px, 6vw, 52px); line-height: 1.05; letter-spacing: -0.012em; color: var(--ink); text-wrap: balance; }
.lp-h3 { font-family: var(--font-display); font-weight: 400; font-size: clamp(22px, 4.6vw, 32px); line-height: 1.15; letter-spacing: -0.01em; color: var(--ink); }
.lp-h4 { font-family: var(--font-body); font-weight: 500; font-size: 17px; line-height: 1.35; letter-spacing: -0.01em; color: var(--ink); }
.lp-lede { font-size: clamp(16px, 4vw, 19px); line-height: 1.55; color: var(--muted); text-wrap: pretty; max-width: 44ch; }
.lp-body { font-size: 16px; line-height: 1.6; color: var(--muted); text-wrap: pretty; }
.lp-small { font-size: 14px; line-height: 1.5; color: var(--muted); }
.lp-mono { font-family: var(--font-mono); font-size: 12px; letter-spacing: -0.02em; text-transform: uppercase; color: var(--muted); }
.lp-body a, .lp-lede a, .lp-small a { color: var(--ink); text-decoration: underline; text-decoration-style: dotted; text-decoration-thickness: 2px; text-decoration-color: rgba(7, 7, 7, 0.4); text-underline-offset: 4px; }
.lp-body a:hover, .lp-lede a:hover, .lp-small a:hover { text-decoration-style: solid; text-decoration-color: var(--ink); }

/* The solid pill's label sits on the ink fill. Pages that flip --ink to a
   light value for dark mode (the developer docs) must flip the label too, or
   "Accept" on the cookie banner renders white on white. --on-ink is that one
   token; light pages never touch it. */
:root { --on-ink: #fff; }
html[data-theme="dark"] { --on-ink: var(--bg, #141518); }
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]):has(body.dapi-docs) { --on-ink: var(--bg, #141518); }
}

/* Buttons. Pills sized like radiusbrowser.com's nav pill (border, px 14,
   pt 7 pb 5, 14px) and its download button. No shadows, no gradients.
   The solid pill's hover is a sweep: Eto orange slides in from the left
   under the label, and the arrow moves 4px (replicas.dev group-hover). */
.lp .lp-btn { position: relative; isolation: isolate; overflow: hidden; display: inline-flex; align-items: center; justify-content: center; gap: 10px; height: 44px; padding: 0 20px 0 22px; border-radius: 999px; border: 1px solid var(--ink); background: var(--ink); color: var(--on-ink, #fff); font-weight: 500; font-size: 15px; white-space: nowrap; }
.lp .lp-btn::before { content: ""; position: absolute; inset: -1px; z-index: -1; background: var(--accent); transform: translateX(-101%); transition: transform 0.42s var(--ease-out); }
.lp .lp-btn:hover::before { transform: translateX(0); }
.lp .lp-btn:hover { border-color: var(--accent); }
.lp .lp-btn .li { transition: transform 0.3s var(--ease-out); }
.lp .lp-btn:hover .li { transform: translateX(4px); }
.lp .lp-btn:active { transform: translateY(1px); }
.lp .lp-btn-line { display: inline-flex; align-items: center; justify-content: center; gap: 10px; height: 44px; padding: 0 20px; border-radius: 999px; border: 1px solid var(--line-2); background: transparent; color: var(--ink); font-weight: 500; font-size: 15px; white-space: nowrap; transition: border-color 0.2s, background-color 0.2s; }
.lp .lp-btn-line:hover { border-color: var(--ink); background: var(--ink-5); }
.lp .lp-btn-line:active { transform: translateY(1px); }
.lp .lp-btn-sm, .lp .lp-btn-line.lp-btn-sm { height: 34px; padding: 0 14px; font-size: 14px; }
.lp .lp-link { display: inline-flex; align-items: center; gap: 4px; color: var(--ink); font-weight: 500; font-size: 15px; text-decoration: underline; text-decoration-style: dotted; text-decoration-thickness: 2px; text-decoration-color: rgba(7, 7, 7, 0.4); text-underline-offset: 4px; }
.lp .lp-link:hover { text-decoration-style: solid; text-decoration-color: var(--ink); }
.lp .lp-link .li { transition: transform 0.3s var(--ease-out); }
.lp .lp-link:hover .li { transform: translate(2px, -2px); }

/* Motion, all taken from the sites:
   radiusbrowser.com  hero-window-rise, radius-build-in, radius-caret
   replicas.dev       landingReveal (words rise 22px as they scroll into view)
   generaltranslation.com  tct-blink (typewriter caret) */
@keyframes lp-window-rise { 0% { opacity: 0; transform: translateY(28px); } 100% { opacity: 1; transform: translateY(0); } }
@keyframes lp-build-in { 0% { opacity: 0; transform: translateY(5px); } 100% { opacity: 1; transform: none; } }
@keyframes lp-caret { 0% { opacity: 1; } 50% { opacity: 0; } }
@keyframes lp-reveal { 0% { opacity: 0; transform: translateY(22px); animation-timing-function: cubic-bezier(0.2, 0, 0, 1); } 100% { opacity: 1; transform: translate(0, 0); } }
.lp-rise { animation: lp-window-rise 0.42s var(--ease-out) both; }
.lp-build { animation: lp-build-in 0.34s ease-out both; }
.lp-caret { display: inline-block; width: 8px; height: 1.05em; margin-left: 2px; vertical-align: -0.15em; background: var(--ink); animation: lp-caret 1.06s step-end infinite; }
/* Scroll reveal for frames and blocks below the fold. The hidden state is only
   armed once motion.js has run (html.has-lp-reveal), so a script that never
   loads leaves the page fully visible instead of blank. `.lp-shot.is-reveal`
   is the same thing addressed through the shot tag's variant argument. */
html.has-lp-reveal .lp-reveal,
html.has-lp-reveal .lp-shot.is-reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.55s var(--ease-out), transform 0.7s var(--ease-out); }
html.has-lp-reveal .lp-reveal.is-in,
html.has-lp-reveal .lp-shot.is-reveal.is-in { opacity: 1; transform: none; }
.lp-words > span { display: inline-block; animation: lp-reveal 0.9s cubic-bezier(0.2, 0, 0, 1) both; animation-delay: calc(var(--i, 0) * 45ms); animation-play-state: paused; }
.lp-words.is-in > span { animation-play-state: running; }
@supports (animation-timeline: view()) {
  .lp-words > span { animation-play-state: running; animation-timeline: view(); animation-range: entry 0% entry calc(12% + var(--i, 0) * 0.8%); }
}
@media (prefers-reduced-motion: reduce) {
  .lp-rise, .lp-build, .lp-words > span { animation: none; opacity: 1; transform: none; }
  .lp-caret { animation: none; }
  html.has-lp-reveal .lp-reveal,
  html.has-lp-reveal .lp-shot.is-reveal { opacity: 1; transform: none; transition: none; }
}
