/**
 * SPC — public site.
 *
 * Dark-first palette (semantic opposite of the Zitro fork this file grew out
 * of): deep near-black surfaces carry gold type and neon accents. Chosen from
 * the client brief — black, gold, mint, purple — anchored on the reference
 * mood (dark background with gold typography and cool neon detail).
 *
 * `--c-roast` (originally "brown type on cream") stays dark on purpose: it is
 * only used as *inverted* type where gold paints the background (button
 * hover, chip fill). Primary reading colour lives in `--c-text`, which flips
 * to warm off-white to pair with gold without going bright-white.
 *
 * Mint and purple are the accent slots — mint reads as "go" (primary CTAs,
 * success), purple as "explore" (secondary CTAs, links, active navigation).
 * Every foreground value was checked against `--c-bg`; the lowest is muted
 * body copy at ~5.4:1 (WCAG AA passes at 4.5:1).
 */

:root {
  /* ─── Brand — gold ─────────────────────────────────
     Rich Cyprus/luxury gold. Measured 9:1 on --c-bg, ideal for headlines,
     wordmark, primary button gradients. */
  --c-primary:        #D4AF37;
  --c-primary-dark:   #B08928;
  --c-primary-light:  #F4CF67;
  /* Deep gold for low-emphasis type on a gold surface (kicker labels inside
     a lemon band, chip borders, etc). ~5.6:1 on the emphasis band. */
  --c-primary-darker: #8B7028;
  --c-primary-rgb:    212, 175, 55;

  /* ─── Surfaces — dark ─────────────────────────────── */
  --c-bg:        #0B0B12;   /* deep near-black with a hair of indigo — reads richer than #000 */
  --c-surface:   #14141F;   /* elevated section background */
  --c-roast:     #0B0B12;   /* text against gold surfaces — stays dark */
  --c-lemon:     #1A1332;   /* emphasis band — deep purple-tinted panel */
  --c-lemon-2:   #10101A;   /* softer band, footer */

  /* ─── Text — light on dark ────────────────────────── */
  --c-text:        #F0EEE6;    /* warm off-white — pairs with gold, not clinical white */
  /* Bumped from 0.62 (AA-legal 5.4:1) after live check — footer/hero muted
     copy read as dim on the deep-black surface. 0.78 measures ~8:1. */
  --c-text-muted:  rgba(240, 238, 230, 0.78);

  --c-border:      rgba(212, 175, 55, 0.14);
  --c-border-dark: rgba(212, 175, 55, 0.28);

  /* ─── Accents — mint & purple ─────────────────────── */
  --c-mint:        #5EEAD4;    /* CTA / success / positive — ~12:1 on --c-bg */
  --c-mint-dark:   #2FB89C;
  /* Vivid violet — the pastel-lavender #C4B5FD read as "not our purple" on
     the logo/UI; this saturation matches the neon-purple reference mood
     without losing WCAG AA (5.5:1 on --c-bg). */
  --c-purple:      #8B5CF6;    /* brand purple: logo 'Pay', secondary CTA, links, active nav */
  --c-purple-dark: #7C3AED;

  --gradient-primary: linear-gradient(180deg, #B08928 0%, #D4AF37 100%);

  --shadow-soft:  0 4px 14px rgba(212, 175, 55, 0.08), 0 2px 6px rgba(0, 0, 0, 0.40);
  --shadow-lift:  0 10px 28px rgba(212, 175, 55, 0.14), 0 4px 10px rgba(0, 0, 0, 0.50);

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* One number drives every gutter, so the whole page breathes together. */
  --gutter: clamp(20px, 5vw, 72px);
  --section-y: clamp(56px, 7vw, 112px);
  /* One scale, used everywhere. Pills read as consumer-app buttons; a small
     radius reads as a company that moves money. */
  --radius-sm: 6px;    /* inputs, chips, small controls */
  --radius:    8px;    /* buttons */
  --radius-lg: 12px;   /* cards, panels, the cookie bar */
}

/* ─────────────────────────── base ─────────────────────────── */

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* The grey-blue rectangle a mobile browser paints over whatever you tap. It
     ignores our border radius, so it flashes a hard-edged box over round-
     cornered buttons and looks like a rendering fault. Suppressed site-wide.
     This removes only the *touch* feedback — :focus-visible below still draws
     a real ring for anyone navigating by keyboard, and buttons keep their own
     hover and active states, so nothing is left without feedback. */
  -webkit-tap-highlight-color: transparent;
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  color: var(--c-text);
  background: var(--c-bg);
  /* Belt and braces. The marquee is clipped by its own wrapper — relying on
     this alone is unreliable, iOS Safari in particular. */
  overflow-x: clip;
}

img { max-width: 100%; height: auto; display: block; }

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

h1, h2, h3, h4 { margin: 0; font-weight: 800; line-height: 1.08; letter-spacing: -0.02em; }

p { margin: 0; }

::selection { background: var(--c-primary); color: var(--c-roast); }

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

.shell { width: 100%; max-width: 1560px; margin: 0 auto; padding: 0 var(--gutter); }

.section { padding: var(--section-y) 0; }

/* The emphasis band. Same brown type as everywhere else — only the surface
   changes, so nothing has to be re-checked for contrast. */
.section--accent {
  background: var(--c-lemon);
  color: var(--c-text);
}

.section--surface { background: var(--c-surface); }

/* A small uppercase kicker above a heading — the sample's "welcome" / "our
   services" labels, which do a lot of work for very little ink. */
.kicker {
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--c-text);
  margin-bottom: 18px;
}

.section--accent .kicker { color: var(--c-text); }

.lede {
  font-size: clamp(22px, 3vw, 40px);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.02em;
}

.muted { color: var(--c-text-muted); }
/* Solid, not alpha: --c-text-muted (0.78 alpha) blends with --c-lemon's deep
   purple and comes out muddy purple-brown. The emphasis band is high-contrast
   by design — body copy on it is a full off-white. */
.section--accent .muted { color: var(--c-text); }

/* ─────────────────────────── header ─────────────────────────── */

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(20, 20, 31, 0.86);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--c-border);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 72px;
}

@media (min-width: 760px) { .site-header__inner { gap: 24px; min-height: 78px; } }

/* On a phone the call-to-action and the burger fight for the same few pixels
   and the header pushes the whole document 3px wide. The menu carries the same
   link and the address, so the button stands down rather than the menu. */
.site-header .btn { display: none; }

@media (min-width: 760px) { .site-header .btn { display: inline-flex; } }

.brand { display: flex; align-items: center; margin-right: auto; }

/* Text wordmark — a placeholder until the client's real SPC mark arrives, but
   works as a real logo: "SPC" carries the brand in gold, "Pay" reads as the
   descriptor in off-white. No external font, no image dep, no cache to bust
   when the type changes. Same visual weight as the original 34/38px lemon PNG. */
.brand__logo {
  display: inline-flex;
  align-items: baseline;
  gap: 0.18em;
  font-family: var(--font);
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--c-text);
  text-transform: none;
}
.brand__logo b { color: var(--c-primary); font-weight: 900; letter-spacing: 0; }
.brand__logo em { font-style: normal; color: var(--c-purple); font-weight: 900; }
@media (min-width: 760px) { .brand__logo { font-size: 26px; } }

/* The header carried the email and the postal address next to the logo. At
   anything under a wide desktop it crowded the button and the burger, and it
   duplicated the footer and the contact page. Removed; the CTA is the header's
   job. */

/* ─────────────────────────── buttons ─────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* 48px tall and never narrower than a thumb — this is the one element a
     phone user is meant to hit. */
  min-height: 48px;
  padding: 0 26px;
  border: 0;
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform .18s ease, box-shadow .18s ease, background .18s ease;
}

.btn--primary {
  background: var(--gradient-primary);
  color: var(--c-roast);
  box-shadow: var(--shadow-soft);
}

.btn--primary:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }

/* Something has to acknowledge a tap now that the browser's own flash is gone. */
.btn:active { transform: translateY(1px); }
.rail-btn:active, .menu-toggle:active { transform: scale(0.96); }

.btn--ghost {
  background: transparent;
  color: inherit;
  border: 1.5px solid currentColor;
}

.btn--ghost:hover { background: var(--c-primary); border-color: var(--c-primary); color: var(--c-roast); }

.btn__arrow { transition: transform .18s ease; }
.btn:hover .btn__arrow { transform: translateX(4px); }

/* A slow sheen across the primary buttons. Seven seconds apart and gone in
   under one, so it catches the eye at the edge of vision without ever being
   the thing you are looking at. It is decoration on top of a button that is
   already legible, so it can be switched off entirely without loss. */
.btn--primary { position: relative; overflow: hidden; isolation: isolate; }

.btn--primary::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg,
    transparent 35%,
    rgba(255, 255, 255, 0.55) 50%,
    transparent 65%);
  transform: translateX(-120%);
  animation: sheen 7s ease-in-out infinite;
}

/* Pointing at it is deliberate attention; the nudge has done its job. */
.btn--primary:hover::after { animation-play-state: paused; }

@keyframes sheen {
  0%, 82%  { transform: translateX(-120%); }
  92%      { transform: translateX(120%); }
  100%     { transform: translateX(120%); }
}

@media (prefers-reduced-motion: reduce) {
  .btn--primary::after { animation: none; content: none; }
}

/* ─────────────────────────── menu ─────────────────────────── */

.menu-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: 0;
  padding: 12px 0;
  min-height: 48px;
  font: inherit;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: inherit;
  cursor: pointer;
}

.menu-toggle__bars { display: grid; gap: 5px; width: 30px; }
.menu-toggle__bars span { height: 2px; background: currentColor; border-radius: 2px; transition: transform .25s ease, opacity .2s ease; }

body.menu-open .menu-toggle__bars span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
body.menu-open .menu-toggle__bars span:nth-child(2) { opacity: 0; }
body.menu-open .menu-toggle__bars span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.menu {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: var(--c-lemon);
  color: var(--c-text);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 96px var(--gutter) 40px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px);
  transition: opacity .28s ease, transform .28s ease, visibility .28s;
  overflow-y: auto;
}

body.menu-open .menu { opacity: 1; visibility: visible; transform: none; }
body.menu-open { overflow: hidden; }

.menu__list { display: grid; gap: 6px; margin: 0 0 48px; padding: 0; list-style: none; }

.menu__link {
  display: inline-block;
  padding: 8px 0;
  font-size: clamp(34px, 8vw, 76px);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.05;
  text-transform: uppercase;
  transition: color .2s ease, transform .2s ease;
}

.menu__link:hover { color: var(--c-primary-light); transform: translateX(10px); }

.menu__foot { display: grid; gap: 8px; font-size: 14px; color: var(--c-text-muted); }
.menu__foot a:hover { color: var(--c-primary-light); }

/* ─────────────────────────── hero ─────────────────────────── */

.hero { padding-top: clamp(40px, 7vw, 90px); }

.hero__grid {
  display: grid;
  gap: 28px;
  padding-bottom: clamp(40px, 6vw, 80px);
  border-bottom: 1px solid var(--c-border);
}

@media (min-width: 900px) {
  .hero__grid { grid-template-columns: 1fr 2fr; gap: 60px; align-items: start; }
}

/* Same two columns as the hero, without the hero's closing rule and the
   padding that goes with it — reusing .hero__grid for ordinary sections left
   a couple of hundred pixels of dead space under every one of them. */
.split { display: grid; gap: 24px; }

@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 2fr; gap: 60px; align-items: start; }
}

/* Clips the oversized wordmark. Without a wrapper that actually crops it, the
   document itself becomes 1800px wide and a phone scrolls sideways. */
.marquee-wrap { overflow: hidden; }

/* The oversized wordmark that slides across the page. Two identical tracks
   sit side by side and the pair is translated by exactly half its width, so
   the loop has no seam and no JavaScript. */
.marquee {
  display: flex;
  width: max-content;
  padding: clamp(18px, 3vw, 40px) 0;
  animation: marquee 26s linear infinite;
}

.marquee__track {
  display: flex;
  flex: 0 0 auto;
  gap: 0.3em;
  padding-right: 0.3em;
  font-size: clamp(64px, 15vw, 210px);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--c-text);
}

.marquee__track em { font-style: normal; color: var(--c-primary); }

@keyframes marquee { to { transform: translateX(-50%); } }

@media (prefers-reduced-motion: reduce) {
  .marquee { animation: none; }
}

/* ─────────────────────────── numbered blocks ─────────────────────────── */

.pillars { display: grid; gap: 1px; background: var(--c-border); border: 1px solid var(--c-border); border-radius: var(--radius-lg); overflow: hidden; }

@media (min-width: 760px)  { .pillars { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1200px) { .pillars { grid-template-columns: repeat(4, 1fr); } }

.pillar { background: var(--c-surface); padding: clamp(24px, 3vw, 40px); display: grid; gap: 14px; align-content: start; }
.pillar__no { font-size: 13px; font-weight: 800; letter-spacing: 0.2em; color: var(--c-primary-dark); }
.pillar__title { font-size: 19px; font-weight: 800; }
.pillar__text { font-size: 15px; color: var(--c-text-muted); }

/* ─────────────────────────── capability cards ─────────────────────────── */

/* auto-fit rather than a fixed column count: a group of four then fills the
   row instead of leaving the fourth card stranded on a line of its own. */
.cards {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 270px), 1fr));
}

.card {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  padding: clamp(24px, 3vw, 36px);
  display: grid;
  gap: 12px;
  align-content: start;
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}

.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); border-color: var(--c-primary-dark); }

.section--accent .card {
  background: var(--c-surface);
  border-color: var(--c-border-dark);
}

.card__icon {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: var(--radius-sm);
  background: var(--gradient-primary);
  color: var(--c-roast);
  font-weight: 800;
}

.card__title { font-size: 19px; font-weight: 800; }
.card__text { font-size: 15px; color: var(--c-text-muted); }
.section--accent .card__text { color: var(--c-text-muted); }

/* ─────────────────────────── carousel ─────────────────────────── */

/* Scroll-snap rather than a slider library: it is a row of cards that can be
   swiped on a phone and nudged with buttons on a desktop, and it keeps
   working with JavaScript disabled. */
.rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(280px, 34%);
  gap: 20px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding: 0 var(--gutter);
  padding-bottom: 12px;
  /* Firefox */
  scrollbar-width: thin;
  scrollbar-color: var(--c-border-dark) transparent;
}
/* WebKit — the default light thumb reads as a hard grey bar against the
   deep-black surface. */
.rail::-webkit-scrollbar { height: 8px; }
.rail::-webkit-scrollbar-track { background: transparent; }
.rail::-webkit-scrollbar-thumb {
  background: var(--c-border-dark);
  border-radius: 4px;
}
.rail::-webkit-scrollbar-thumb:hover { background: var(--c-primary); }

.rail > * { scroll-snap-align: start; }

@media (max-width: 720px) { .rail { grid-auto-columns: 84%; } }

.rail-nav { display: flex; gap: 10px; margin-top: 22px; }

.rail-btn {
  width: 48px; height: 48px;
  display: grid; place-items: center;
  border-radius: var(--radius);
  border: 1.5px solid currentColor;
  background: none;
  color: inherit;
  cursor: pointer;
  transition: background .18s ease, color .18s ease, opacity .18s ease;
}

.rail-btn:hover { background: var(--c-primary); border-color: var(--c-primary); color: var(--c-roast); }
.rail-btn[disabled] { opacity: .35; cursor: default; }
.rail-btn[disabled]:hover { background: none; color: inherit; border-color: currentColor; }

/* ─────────────────────────── contact ─────────────────────────── */

.contact-grid { display: grid; gap: 40px; }

@media (min-width: 960px) { .contact-grid { grid-template-columns: 1fr 1fr; gap: 72px; } }

.field { display: grid; gap: 8px; margin-bottom: 18px; }

.field label { font-size: 12px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: var(--c-text-muted); }

.field input, .field textarea {
  width: 100%;
  min-height: 52px;
  padding: 14px 16px;
  font: inherit;
  font-size: 16px; /* 16px keeps iOS from zooming the page on focus */
  color: var(--c-text);
  background: var(--c-surface);
  border: 1.5px solid var(--c-border);
  border-radius: var(--radius-sm);
  transition: border-color .18s ease, box-shadow .18s ease;
}

.field textarea { min-height: 150px; resize: vertical; }

.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--c-primary-dark);
  box-shadow: 0 0 0 4px rgba(var(--c-primary-rgb), 0.22);
}

/* Bots fill in everything they can see; this one is invisible to people and
   its being filled is the tell. */
.field--trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-note { margin-top: 14px; font-size: 15px; min-height: 24px; }
.form-note--ok { color: var(--c-primary); font-weight: 700; }
.form-note--bad { color: #F87171; font-weight: 700; }
/* Neutral in-flight state — 'Sending…' is neither success nor failure. */
.form-note--pending { color: var(--c-text-muted); font-weight: 500; }

.detail-list { display: grid; gap: 22px; }
.detail-list dt { font-size: 12px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: var(--c-primary); margin-bottom: 4px; }
.detail-list dd { margin: 0; font-size: 17px; font-weight: 600; }

/* ─────────────────────────── prose (legal pages) ─────────────────────────── */

.prose { max-width: 78ch; }
.prose h2 { font-size: clamp(22px, 2.6vw, 30px); margin: 48px 0 14px; }
.prose h3 { font-size: 19px; margin: 30px 0 10px; }
.prose p, .prose li { font-size: 16px; color: var(--c-text-muted); }
.prose p + p { margin-top: 14px; }
.prose ul { margin: 12px 0; padding-left: 20px; display: grid; gap: 8px; }
.prose strong { color: var(--c-text); }

/* ─────────────────────────── footer ─────────────────────────── */

/* A softer lemon than the emphasis band so the two do not merge where a CTA
   section sits directly above the footer. */
.site-footer { background: var(--c-lemon-2); color: var(--c-text); padding: clamp(56px, 7vw, 100px) 0 40px; border-top: 1px solid var(--c-primary-border); }

.footer-grid { display: grid; gap: 42px; }

@media (min-width: 860px) { .footer-grid { grid-template-columns: 1.6fr 1fr 1fr; gap: 60px; } }

.footer-logo {
  display: inline-flex;
  align-items: baseline;
  gap: 0.18em;
  font-family: var(--font);
  font-size: 30px;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--c-text);
  margin-bottom: 20px;
}
.footer-logo b { color: var(--c-primary); font-weight: 900; letter-spacing: 0; }
.footer-logo em { font-style: normal; color: var(--c-purple); font-weight: 900; }

.footer-col h3 { font-size: 12px; font-weight: 800; letter-spacing: 0.2em; text-transform: uppercase; color: var(--c-primary-darker); margin-bottom: 18px; }
.footer-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.footer-col a { color: var(--c-text-muted); }
.footer-col a:hover { color: var(--c-primary-darker); }

.footer-bottom {
  margin-top: 56px;
  padding-top: 24px;
  border-top: 1px solid var(--c-primary-border);
  display: flex;
  flex-wrap: wrap;
  gap: 12px 24px;
  justify-content: space-between;
  font-size: 13px;
  color: var(--c-text-muted);
}

/* ─────────────────────────── language switch ─────────────────────────── */

/* Present from day one so adding a second language is a data change, not a
   layout change. It hides itself while only one language exists. */
.lang {
  position: relative;
  display: none;
}

.lang[data-multi="true"] { display: block; }

.lang__btn {
  display: flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 0 14px;
  background: none; border: 1.5px solid var(--c-border); border-radius: var(--radius);
  font: inherit; font-size: 12px; font-weight: 800; letter-spacing: 0.12em;
  text-transform: uppercase; color: inherit; cursor: pointer;
}

.lang__menu {
  position: absolute; right: 0; top: calc(100% + 8px);
  min-width: 168px; padding: 8px;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lift);
  display: none;
  z-index: 70;
}

.lang.is-open .lang__menu { display: grid; }

.lang__opt {
  display: block; width: 100%;
  padding: 10px 12px;
  background: none; border: 0; border-radius: var(--radius-sm);
  font: inherit; font-size: 15px; text-align: left; color: var(--c-text); cursor: pointer;
}

.lang__opt:hover { background: rgba(var(--c-primary-rgb), 0.18); }
.lang__opt[aria-current="true"] { font-weight: 800; }

/* ─────────────────────────── cookie notice ─────────────────────────── */

.cookie {
  position: fixed;
  left: 50%; bottom: 20px;
  transform: translateX(-50%) translateY(140%);
  z-index: 80;
  width: min(760px, calc(100vw - 32px));
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  padding: 16px 20px;
  background: var(--c-surface);
  border: 1px solid var(--c-primary-dark);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lift);
  transition: transform .35s cubic-bezier(.2,.8,.2,1);
}

.cookie.is-shown { transform: translateX(-50%) translateY(0); }
.cookie p { flex: 1 1 220px; font-size: 14px; }

@media (max-width: 560px) { .cookie { border-radius: var(--radius); } }

/* ─────────────────────────── reveal on scroll ─────────────────────────── */

/* Hidden only once JavaScript has announced itself — the `js` class is set by
   an inline script in <head>. Without it the animation never arms, and a page
   whose scripts failed to load still shows every word. An effect must not be
   able to make content disappear. */
.js .reveal { opacity: 0; transform: translateY(22px); transition: opacity .6s ease, transform .6s ease; }
.js .reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
}

/* Until the translation layer has painted, text nodes still hold their build-
   time English. That is the right fallback, so nothing is hidden here — the
   page is readable even if the JSON never loads. */
