/* ============================================================
   eor.vn — design system v3 "Giấy Trắng"
   Warm off-white base · near-black ink · seal-red accent
   Display/body: Hanken Grotesk · UI: Be Vietnam Pro
   One dark band (stats) + black split panel as counterpoint
   ============================================================ */

:root {
  --base: #f7f6f5;
  --card: #ffffff;
  --panel: #f1efe9;
  --text: #191a23;
  --text-2: #4a4f57;
  --muted: #60646b;
  --line: #e6e4dd;
  --line-2: #d8d5cc;

  --dark: #0c1624;
  --dark-2: #122036;
  --dk-text: #b9c3cf;
  --dk-text-2: #8496a8;
  --dk-line: rgba(255, 255, 255, 0.09);

  --seal: #c4332f;
  --seal-tint: #faece9;
  --black: #111318;

  --font-display: 'Hanken Grotesk', 'Segoe UI', system-ui, sans-serif;
  --font-body: 'Hanken Grotesk', 'Segoe UI', system-ui, sans-serif;
  --font-ui: 'Be Vietnam Pro', 'Segoe UI', system-ui, sans-serif;

  --wrap: 1180px;
  --wrap-narrow: 800px;
  --r-sm: 10px;
  --r-card: 16px;
  --r-lg: 24px;
  --r-btn: 12px;
  --shadow-1: 0 1px 2px rgba(20, 22, 26, 0.04), 0 6px 18px rgba(20, 22, 26, 0.04);
  --shadow-2: 0 4px 10px rgba(20, 22, 26, 0.05), 0 24px 60px rgba(20, 22, 26, 0.1);
  --shadow-hero: 0 2px 6px rgba(20, 22, 26, 0.05), 0 48px 100px rgba(20, 22, 26, 0.13);

  /* motion redesign */
  --wash: #eef1f6;
  --wash-2: #e7ecf2;
  --grid-dot: rgba(25, 26, 35, 0.055);
  --rail: #eceae3;
  --seal-ink: #9e2b27;
  --drum: rgba(25, 26, 35, 0.06);
  --font-mono: 'IBM Plex Mono', ui-monospace, 'Be Vietnam Pro', monospace;
}

html[lang='ja'] { --font-display: 'Noto Sans JP', sans-serif; --font-body: 'Noto Sans JP', sans-serif; --font-ui: 'Noto Sans JP', sans-serif; --font-mono: 'IBM Plex Mono', 'Noto Sans JP', sans-serif; }
html[lang='ko'] { --font-display: 'Noto Sans KR', sans-serif; --font-body: 'Noto Sans KR', sans-serif; --font-ui: 'Noto Sans KR', sans-serif; --font-mono: 'IBM Plex Mono', 'Noto Sans KR', sans-serif; }
html[lang='zh-Hans'] { --font-display: 'Noto Sans SC', sans-serif; --font-body: 'Noto Sans SC', sans-serif; --font-ui: 'Noto Sans SC', sans-serif; --font-mono: 'IBM Plex Mono', 'Noto Sans SC', sans-serif; }
html[lang='zh-Hant'] { --font-display: 'Noto Sans TC', sans-serif; --font-body: 'Noto Sans TC', sans-serif; --font-ui: 'Noto Sans TC', sans-serif; --font-mono: 'IBM Plex Mono', 'Noto Sans TC', sans-serif; }

@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.2s; }

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 1.04rem;
  line-height: 1.66;
  color: var(--text);
  background: var(--base);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg { display: block; max-width: 100%; }
a { color: var(--text); text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: var(--line-2); }
a:hover { color: var(--seal); text-decoration-color: var(--seal); }
p { margin: 0 0 1em; }
ul, ol { margin: 0 0 1.2em; padding-left: 1.3em; }
li { margin-bottom: 0.4em; }
strong { font-weight: 600; }
::selection { background: var(--black); color: #fff; }
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 22px; }
.wrap-narrow { max-width: var(--wrap-narrow); }

h1, h2, h3, h4, .logo-word {
  font-family: var(--font-display);
  color: var(--text);
  line-height: 1.08;
  letter-spacing: -0.03em;
  margin: 0 0 0.5em;
  font-weight: 550;
}
h1 { font-size: clamp(2.5rem, 5.2vw, 4rem); }
h2 { font-size: clamp(1.75rem, 3.1vw, 2.55rem); }
h3 { font-size: 1.16rem; font-weight: 600; line-height: 1.35; letter-spacing: -0.015em; }
.lead {
  font-family: var(--font-display);
  font-size: clamp(1.12rem, 1.5vw, 1.35rem); font-weight: 300;
  line-height: 1.5; letter-spacing: -0.012em; color: var(--text-2);
}

/* eyebrow → bordered pill label */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text);
  margin: 0 0 1.2em;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 13px;
  border: 1px solid var(--line-2); border-radius: 999px;
  background: var(--card);
}
.eyebrow::before {
  content: '';
  width: 6px; height: 6px;
  background: var(--seal); border-radius: 50%;
  flex: none;
}

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--black); color: #fff; padding: 10px 18px; z-index: 300;
  font-family: var(--font-ui);
}
.skip:focus { left: 10px; top: 10px; }
:focus-visible { outline: 3px solid var(--seal); outline-offset: 2px; border-radius: 3px; }

/* ---------- buttons: quiet black, Neo-style ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-ui); font-weight: 600; font-size: 0.94rem;
  padding: 13px 26px; border-radius: var(--r-btn);
  text-decoration: none; border: 1.5px solid transparent;
  transition: transform 0.15s ease, background 0.18s ease, color 0.18s ease,
    border-color 0.18s ease, box-shadow 0.22s ease;
  cursor: pointer; position: relative; overflow: hidden;
}
.btn-primary {
  background: var(--black); color: #fff;
  box-shadow: 0 1px 2px rgba(17, 19, 24, 0.25);
}
.btn-primary:hover { color: #fff; transform: translateY(-1px); box-shadow: 0 10px 28px rgba(17, 19, 24, 0.22); }
.btn-ghost { border-color: var(--line-2); color: var(--text); background: var(--card); }
.btn-ghost:hover { border-color: var(--black); color: var(--text); }
.btn-light { background: #fff; color: var(--text); box-shadow: var(--shadow-1); }
.btn-light:hover { color: var(--seal); }
.btn-sm { padding: 9px 18px; font-size: 0.88rem; }

.btn .ripple {
  position: absolute; border-radius: 50%; pointer-events: none;
  background: rgba(255, 255, 255, 0.35);
  transform: scale(0); animation: ripple 0.55s ease-out forwards;
}
.btn-ghost .ripple, .btn-light .ripple { background: rgba(17, 19, 24, 0.12); }
@keyframes ripple { to { transform: scale(2.6); opacity: 0; } }

/* ---------- header: light, airy ---------- */
.site-head {
  position: sticky; top: 0; z-index: 100;
  background: rgba(247, 246, 245, 0.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
  transition: background 0.3s ease, box-shadow 0.3s ease;
}
.site-head.scrolled { background: rgba(247, 246, 245, 0.95); box-shadow: 0 8px 30px rgba(20, 22, 26, 0.06); }
.head-row { display: flex; align-items: center; gap: 26px; min-height: 68px; }
.logo { text-decoration: none; }
.logo-word {
  display: inline-flex; align-items: baseline;
  font-size: 1.42rem; font-weight: 700; letter-spacing: -0.04em; color: var(--text);
  margin: 0;
}
.logo-seal { width: 0.6em; height: 0.6em; color: var(--seal); margin: 0 0.07em; align-self: center; }
.logo:hover .logo-seal { animation: logoSpin 0.7s cubic-bezier(0.3, 0.8, 0.3, 1); }
@keyframes logoSpin { from { transform: rotate(0); } to { transform: rotate(360deg); } }
.site-nav { margin-left: 6px; }
.site-nav ul { display: flex; gap: 2px; list-style: none; margin: 0; padding: 0; }
.site-nav a {
  display: block; padding: 10px 13px; position: relative;
  font-family: var(--font-ui); font-size: 0.92rem; font-weight: 500;
  color: var(--text-2); text-decoration: none; border-radius: 9px;
  transition: color 0.15s ease, background 0.15s ease;
}
.site-nav a::after {
  content: ''; position: absolute; left: 13px; right: 13px; bottom: 5px; height: 2px;
  background: var(--seal); border-radius: 2px;
  transform: scaleX(0); transform-origin: left; transition: transform 0.22s cubic-bezier(0.3, 0.8, 0.3, 1);
}
.site-nav a:hover::after, .site-nav a[aria-current='page']::after { transform: scaleX(1); }
.site-nav a:hover { color: var(--text); }
.site-nav a[aria-current='page'] { color: var(--text); font-weight: 600; }
.head-actions { margin-left: auto; display: flex; align-items: center; gap: 12px; }

.lang { position: relative; font-family: var(--font-ui); }
.lang summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.84rem; font-weight: 600; color: var(--text-2);
  padding: 8px 13px; border-radius: 999px; border: 1px solid var(--line-2); background: var(--card);
  transition: color 0.15s ease, border-color 0.15s ease;
}
.lang summary::-webkit-details-marker { display: none; }
.lang summary:hover { color: var(--text); border-color: var(--black); }
.lang .ico { width: 15px; height: 15px; }
.lang ul {
  position: absolute; right: 0; top: calc(100% + 10px);
  background: #fff;
  border: 1px solid var(--line); border-radius: 14px;
  box-shadow: var(--shadow-2); padding: 8px; margin: 0;
  display: grid; grid-template-columns: repeat(2, minmax(118px, 1fr)); gap: 1px;
  list-style: none; z-index: 120; min-width: 264px;
}
.lang li { margin: 0; }
.lang ul a {
  display: block; padding: 8px 11px; font-size: 0.87rem; border-radius: 8px;
  color: var(--text-2); text-decoration: none;
}
.lang ul a:hover { background: var(--panel); color: var(--text); }
.lang ul a[aria-current='true'] { color: var(--seal); font-weight: 700; }

/* mega menu under "EOR services" (hover or keyboard focus) */
.has-mega { position: relative; }
.mega {
  position: absolute; left: -8px; top: calc(100% + 12px); z-index: 130;
  display: grid; grid-template-columns: 1fr 200px; width: 620px;
  background: #fff; border: 1px solid var(--line); border-radius: 16px;
  box-shadow: var(--shadow-2); overflow: hidden;
  opacity: 0; visibility: hidden; transform: translateY(6px);
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
}
.mega::before { content: ''; position: absolute; left: 0; right: 0; top: -14px; height: 14px; }
.has-mega:hover .mega, .has-mega:focus-within .mega { opacity: 1; visibility: visible; transform: none; }
.mega-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; padding: 10px; }
.site-nav .mega a::after { display: none; }
.site-nav .mega-item { display: flex; align-items: center; gap: 11px; padding: 10px 11px; font-size: 0.89rem; color: var(--text); border-radius: 10px; }
.site-nav .mega-item:hover { background: var(--base); }
.mega-ico { flex: none; width: 34px; height: 34px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 10px; background: var(--base); }
.mega-ico svg { width: 18px; height: 18px; }
.mega-side { background: var(--base); border-left: 1px solid var(--line); padding: 14px 10px; display: flex; flex-direction: column; gap: 2px; }
.site-nav .mega-side a { padding: 8px 11px; font-size: 0.86rem; color: var(--text-2); border-radius: 8px; }
.site-nav .mega-side a:hover { background: #fff; color: var(--text); }

.nav-toggle { display: none; }
.scroll-progress {
  position: absolute; left: 0; bottom: -1px; height: 2px; width: 100%;
  background: var(--seal);
  transform-origin: left; transform: scaleX(0); pointer-events: none;
}

/* ---------- hero: centered, paper-white, product-mock below ---------- */
.hero {
  background: linear-gradient(180deg, var(--wash) 0, var(--base) 620px);
  overflow: hidden; position: relative;
}
.hero .hero-grid { position: relative; z-index: 2; }
.hero-grid {
  display: grid; grid-template-columns: 1fr;
  gap: 0; align-items: start;
  padding-top: clamp(40px, 4.4vw, 64px); padding-bottom: clamp(48px, 6vw, 84px);
  text-align: center;
}
.hero-copy { max-width: 1040px; margin: 0 auto; }
.hero .eyebrow { margin-bottom: 1.6em; }
.hero h1 { margin: 0 auto 0.4em; text-wrap: balance; }
.hero h1 em { font-style: normal; color: var(--seal); }
.hero .lead { max-width: 42em; margin-left: auto; margin-right: auto; }
.hero-ctas { display: flex; flex-wrap: wrap; gap: 12px; margin: 1.5em 0 1.3em; justify-content: center; }
.hero-points {
  list-style: none; padding: 0; margin: 0;
  font-family: var(--font-ui); font-size: 0.82rem; color: var(--muted);
  display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 22px;
}
.hero-points li { display: inline-flex; gap: 8px; align-items: center; margin: 0; }
.hero-points .tick { color: var(--text); flex: none; width: 15px; height: 15px; }

/* hero copy entrance */
.hero h1 .w { display: inline-block; }
.anim-words .w {
  opacity: 0; transform: translateY(0.5em);
  animation: wordIn 0.6s cubic-bezier(0.2, 0.8, 0.2, 1) var(--wd, 0ms) forwards;
}
@keyframes wordIn { to { opacity: 1; transform: none; } }
.anim-words em, .anim-words em .w { color: var(--seal); background: none; }
.anim-rise { opacity: 0; animation: riseIn 0.8s cubic-bezier(0.2, 0.8, 0.2, 1) 0.1s forwards; }
@keyframes riseIn { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
.hero-enter .lead { opacity: 0; animation: riseIn 0.7s ease 0.45s forwards; }
.hero-enter .hero-ctas { opacity: 0; animation: riseIn 0.7s ease 0.62s forwards; }
.hero-enter .hero-points { opacity: 0; animation: riseIn 0.7s ease 0.78s forwards; }

/* ---------- ribbon → quiet ticker ---------- */
.ribbon { background: var(--card); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); overflow: hidden; }
.ribbon .wrap {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6px 28px;
  padding-top: 17px; padding-bottom: 17px;
  font-family: var(--font-ui); font-size: 0.86rem; color: var(--muted);
}
.ribbon b { color: var(--text); font-weight: 600; }
.ribbon.is-marquee .wrap { max-width: none; padding-left: 0; padding-right: 0; flex-wrap: nowrap; justify-content: flex-start; gap: 0; }
.marquee-inner { display: flex; flex: none; align-items: center; gap: 0; animation: marquee 36s linear infinite; }
.marquee-inner > span { white-space: nowrap; padding: 0 28px; position: relative; }
.marquee-inner > span::after {
  content: ''; position: absolute; right: -3px; top: 50%; width: 5px; height: 5px;
  border-radius: 50%; background: var(--seal); transform: translateY(-50%);
}
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-100%); } }
.ribbon.is-marquee:hover .marquee-inner,
.ribbon.is-marquee:focus-within .marquee-inner,
.ribbon.is-marquee.is-paused .marquee-inner,
.ribbon.anim-off .marquee-inner { animation-play-state: paused; }

/* ---------- brand quote (testimonial-slot) ---------- */
.quote { padding: clamp(80px, 10vw, 150px) 0; background: var(--card); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.quote blockquote { margin: 0; text-align: center; }
.quote blockquote p {
  font-family: var(--font-display); font-weight: 450;
  font-size: clamp(1.5rem, 3vw, 2.3rem); line-height: 1.3; letter-spacing: -0.02em;
  color: var(--text); max-width: 26em; margin: 0 auto 1.2em; text-wrap: balance;
}
.quote footer {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  font-family: var(--font-ui); font-size: 0.88rem; color: var(--muted);
}
.quote .q-seal { width: 20px; height: 20px; color: var(--seal); }
.quote footer b { color: var(--text); font-weight: 700; }

/* ---------- scrollytelling features ---------- */
.feat { display: grid; grid-template-columns: 290px 1fr; gap: clamp(32px, 5vw, 72px); align-items: start; }
.feat-nav {
  position: sticky; top: 100px;
  display: flex; flex-direction: column; gap: 2px;
  font-family: var(--font-ui); font-size: 0.95rem;
}
.feat-nav span {
  padding: 10px 16px; color: var(--muted); cursor: pointer;
  border-left: 2px solid var(--line); transition: color 0.2s ease, border-color 0.2s ease;
}
.feat-nav span:hover { color: var(--text); }
.feat-nav span.on { color: var(--text); font-weight: 600; border-left-color: var(--seal); }
.feat-panels { display: grid; gap: clamp(48px, 6vw, 84px); }
.feat-panel h3 { font-size: 1.3rem; margin-bottom: 0.4em; }
.feat-panel > p { color: var(--text-2); max-width: 56ch; font-size: 1rem; }
.feat-fig {
  margin-top: 20px; background: var(--wash);
  border: 1px solid var(--line); border-radius: var(--r-card);
  overflow: hidden;
}
.feat-fig svg { width: 100%; height: auto; }

/* faint Dong Son rings behind the quote */
.quote { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 800' fill='none' stroke='%23191a23' stroke-opacity='.055'%3E%3Ccircle cx='400' cy='400' r='130'/%3E%3Ccircle cx='400' cy='400' r='200'/%3E%3Ccircle cx='400' cy='400' r='270'/%3E%3Ccircle cx='400' cy='400' r='340'/%3E%3Ccircle cx='400' cy='400' r='396'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: center; background-size: min(820px, 96vw); }

/* page-edge rails, home only; multiply makes them vanish on the dark band */
@media (min-width: 1240px) {
  .page-home main { position: relative; }
  .page-home main::after {
    content: ''; position: absolute; top: 0; bottom: 0; left: 50%; width: var(--wrap); transform: translateX(-50%);
    border-left: 1px solid var(--rail); border-right: 1px solid var(--rail);
    pointer-events: none; z-index: 1; mix-blend-mode: multiply;
  }
}

.fx-head-split { display: grid; grid-template-columns: minmax(0, 1fr) clamp(240px, 26vw, 330px); gap: clamp(28px, 5vw, 64px); align-items: center; }
.fx-head-split .fx-cov { margin-inline: 0; }
@media (max-width: 760px) { .fx-head-split { grid-template-columns: 1fr; } .fx-head-split .fx-cov { max-width: 280px; margin-inline: auto; } }

/* a closed mega menu stays closed until focus or pointer leaves */
.has-mega.mega-off .mega { opacity: 0; visibility: hidden; }

/* film controls stay quiet until wanted */
.fx-film__pp { width: 30px; height: 30px; opacity: 0.72; transition: opacity 0.18s ease, color 0.18s ease, border-color 0.18s ease; }
.fx-film__pp svg { width: 13px; height: 13px; }
.fx-film:hover .fx-film__pp, .fx-film__pp:focus-visible { opacity: 1; }

/* ---------- media on inner pages ---------- */
.fx-inline { margin: 26px 0 30px; border: 1px solid var(--line); border-radius: var(--r-card); overflow: hidden; background: var(--wash); }
.fx-inline--plain { border: 0; border-radius: 0; background: none; overflow: visible; }
/* clip, not hidden: the stage backdrop + satellites bleed past the viewport at
   980–1200px and must not create a horizontal page scroll */
.fx-page-stage { padding: clamp(8px, 2vw, 20px) 0 clamp(36px, 5vw, 64px); overflow-x: clip; }
.fx-page-band { padding: clamp(28px, 4vw, 52px) 0; }

/* ---------- sections ---------- */
.section { padding: clamp(72px, 9vw, 128px) 0; }
.section-paper { background: var(--card); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.section-head { max-width: 760px; margin-bottom: clamp(34px, 4.5vw, 58px); }
.section-head p:last-child { margin-bottom: 0; }
.section-head h2 + p, .section-head h2 ~ p { color: var(--text-2); }

/* ---------- cards ---------- */
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 30px 30px 28px; position: relative; overflow: hidden;
  transition: box-shadow 0.22s ease, transform 0.22s ease, border-color 0.22s ease;
}
.section-paper .card { background: var(--base); }
.card:hover { box-shadow: var(--shadow-2); transform: translateY(-3px); border-color: var(--line-2); }
.card h3 { margin: 0 0 0.45em; }
.card p { font-size: 0.95rem; color: var(--text-2); margin-bottom: 0; }
.card .card-ico {
  width: 44px; height: 44px; border-radius: var(--r-sm);
  background: var(--panel);
  color: var(--text);
  display: flex; align-items: center; justify-content: center; margin-bottom: 20px;
  transition: transform 0.25s cubic-bezier(0.3, 1.4, 0.4, 1), background 0.2s ease, color 0.2s ease;
}
.card:hover .card-ico { transform: translateY(-2px); background: var(--black); color: #fff; }
.card .card-ico svg { width: 22px; height: 22px; }
.card:hover .card-ico svg * { stroke-dasharray: 90; animation: icoDraw 0.85s cubic-bezier(0.3, 0.7, 0.3, 1) forwards; }
@keyframes icoDraw { from { stroke-dashoffset: 90; } to { stroke-dashoffset: 0; } }

@media (min-width: 1021px) {
  #services .grid-3 { grid-template-columns: repeat(6, 1fr); }
  #services .card { grid-column: span 2; }
}

/* ---------- split panels ---------- */
.split { display: grid; grid-template-columns: 1fr 1fr; border-radius: var(--r-lg); overflow: hidden; border: 1px solid var(--line); box-shadow: var(--shadow-2); }
.split-panel { padding: clamp(32px, 4.5vw, 54px); }
.split-panel.is-ink { background: var(--panel); color: var(--text-2); border-right: 1px solid var(--line); }
.split-panel.is-paper { background: var(--card); }
.split-panel .eyebrow { background: transparent; }
.split-list { list-style: none; padding: 0; margin: 0; }
.split-list li { display: flex; gap: 12px; align-items: flex-start; padding: 9px 0; font-size: 0.97rem; }
.split-list .tick { width: 17px; height: 17px; flex: none; margin-top: 4px; color: var(--text); }

/* ---------- dark stats band (the one dark counterpoint) ---------- */
.band { background: var(--dark); color: var(--dk-text); position: relative; overflow: hidden; }
.band::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(60% 70% at 88% 0%, rgba(196, 51, 47, 0.12), transparent 60%);
}
.band .wrap { position: relative; z-index: 1; }
.band h2 { color: #fff; }
.band .eyebrow { color: #e9edf2; border-color: rgba(255, 255, 255, 0.22); background: transparent; }
.stat-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
  background: var(--dk-line); border: 1px solid var(--dk-line);
  border-radius: var(--r-card); overflow: hidden;
}
.stat { background: var(--dark); padding: 30px 28px 26px; position: relative; }
.stat .n {
  font-family: var(--font-display); font-weight: 550; font-size: clamp(2rem, 3.4vw, 3rem);
  letter-spacing: -0.03em; font-variant-numeric: tabular-nums; color: #fff;
}
.stat .n sup { font-size: 0.55em; }
.stat .d { font-size: 0.88rem; margin-top: 8px; }
.stat::after {
  content: ''; position: absolute; left: 28px; bottom: 18px; height: 2px; width: 44px;
  background: var(--seal);
  border-radius: 2px; transform: scaleX(0); transform-origin: left;
  transition: transform 0.7s cubic-bezier(0.2, 0.8, 0.3, 1) 0.25s;
}
.js .stat.reveal.in::after { transform: scaleX(1); }
.band .note { font-size: 0.85rem; color: var(--dk-text-2); margin-top: 20px; }
.band a { color: #d7e0ea; }
.band a:hover { color: #fff; }

/* ---------- steps ---------- */
.steps { counter-reset: step; list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(5, 1fr); gap: 20px; }
.steps li { counter-increment: step; position: relative; padding-top: 62px; margin: 0; }
.steps li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute; top: 0; left: 0;
  font-family: var(--font-ui); font-weight: 700; font-size: 0.95rem;
  color: var(--text); background: var(--card);
  border: 1px solid var(--line-2);
  width: 46px; height: 46px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  transition: transform 0.25s cubic-bezier(0.3, 1.4, 0.4, 1), background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.steps li:hover::before { transform: scale(1.1); background: var(--black); border-color: var(--black); color: #fff; }
.steps li::after { content: ''; position: absolute; top: 23px; left: 56px; right: -10px; border-top: 1px solid var(--line-2); }
.steps li:last-child::after { display: none; }
.steps h3 { font-size: 1.02rem; margin-bottom: 0.35em; }
.steps p { font-size: 0.9rem; color: var(--text-2); margin: 0; }
.steps .s-time { display: inline-block; font-family: var(--font-ui); font-size: 0.72rem; font-weight: 600; color: var(--muted); background: var(--panel); border-radius: 99px; padding: 2px 10px; margin-bottom: 8px; }

/* ---------- tables ---------- */
.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r-card); background: #fff; }
table.data { border-collapse: collapse; width: 100%; font-size: 0.94rem; min-width: 560px; }
table.data th, table.data td { text-align: left; padding: 14px 18px; border-bottom: 1px solid var(--line); vertical-align: top; }
table.data thead th {
  font-family: var(--font-ui); font-size: 0.72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted);
  background: #faf9f7; border-bottom: 1px solid var(--line);
}
table.data tbody tr { transition: background 0.15s ease; }
table.data tbody tr:hover { background: #fbfaf8; }
table.data tbody tr:last-child td { border-bottom: none; }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.data .row-total td { font-weight: 700; background: #faf9f7; }
table.data thead th:nth-child(2) { color: var(--seal); }
#compare table.data td:nth-child(2) { background: rgba(196, 51, 47, 0.035); }
.tbl-note { font-size: 0.85rem; color: var(--muted); margin-top: 12px; }
.yes { color: var(--text); font-weight: 700; }
.no { color: var(--seal); }

/* ---------- pricing ---------- */
.price-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; align-items: stretch; }
.price-card {
  background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); padding: 38px;
  display: flex; flex-direction: column; position: relative; overflow: hidden;
  transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.price-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); }
.price-card.is-featured { border: 1.5px solid var(--black); box-shadow: var(--shadow-2); }
.price-card .p-badge {
  position: absolute; top: 18px; right: 20px;
  background: var(--black); color: #fff; font-family: var(--font-ui);
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  padding: 5px 13px; border-radius: 99px;
}
.price-card .p-name { font-family: var(--font-ui); font-weight: 700; font-size: 1.02rem; }
.price-card .p-amount { font-family: var(--font-display); font-weight: 550; font-size: clamp(2.5rem, 3.4vw, 3rem); letter-spacing: -0.03em; color: var(--text); margin: 10px 0 2px; }
.price-card .p-amount span { font-family: var(--font-ui); font-size: 0.95rem; font-weight: 500; color: var(--muted); letter-spacing: 0; }
.price-card .p-sub { font-size: 0.88rem; color: var(--muted); font-family: var(--font-ui); }
.price-card ul { list-style: none; padding: 0; margin: 24px 0 28px; }
.price-card li { display: flex; gap: 10px; align-items: flex-start; font-size: 0.94rem; padding: 6px 0; margin: 0; color: var(--text-2); }
.price-card .tick { width: 16px; height: 16px; flex: none; margin-top: 4px; color: var(--text); }
.price-card .btn { margin-top: auto; }

.price-anchor { font-family: var(--font-ui); font-size: 0.9rem; color: var(--muted); margin: 14px 0 0; }

/* ---------- FAQ ---------- */
.faq { padding: clamp(72px, 9vw, 128px) 0; }
.faq-list { border-top: 1px solid var(--line); }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 16px;
  padding: 22px 10px; border-radius: var(--r-sm);
  transition: background 0.15s ease;
}
.faq-item summary:hover { background: rgba(20, 22, 26, 0.03); }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary h3 { margin: 0; font-size: 1.05rem; flex: 1; font-weight: 550; }
.faq-item summary .ico { width: 19px; height: 19px; color: var(--muted); flex: none; transition: transform 0.25s ease, color 0.2s ease; }
.faq-item[open] summary .ico { transform: rotate(180deg); color: var(--seal); }
.faq-item summary:hover h3 { color: var(--seal); }
.faq-a { padding: 2px 10px 24px; max-width: 65ch; color: var(--text-2); font-size: 0.97rem; }
.faq-a p:last-child { margin-bottom: 0; }
details[open] .faq-a { animation: faqIn 0.3s ease; }
@keyframes faqIn { from { opacity: 0; transform: translateY(-7px); } to { opacity: 1; transform: none; } }

/* ---------- CTA band: light, centered weight ---------- */
.cta-band { background: var(--card); border-top: 1px solid var(--line); position: relative; overflow: hidden; }
.cta-band .wrap { position: relative; z-index: 1; }
.cta-band .cta-inner { max-width: 640px; padding: clamp(68px, 8.5vw, 116px) 0; }
.cta-band h2 { font-size: clamp(2rem, 3.6vw, 3rem); }
.cta-band .lead { color: var(--text-2); }
/* .cta-seal (the EOR◎VN drum mark) is laid out in fx/fx-drum-mark.css */
.cta-band .hero-ctas { margin-bottom: 0; justify-content: flex-start; }

/* ---------- article / guide heads: light ---------- */
.article-head {
  background:
    radial-gradient(50% 320px at 22% -10%, rgba(190, 206, 235, 0.25), transparent 70%),
    radial-gradient(44% 300px at 80% -8%, rgba(240, 212, 205, 0.22), transparent 70%),
    var(--base);
  border-bottom: 1px solid var(--line);
  padding: clamp(52px, 7vw, 88px) 0 clamp(44px, 6vw, 64px);
  position: relative; overflow: hidden;
}
.article-head .wrap { position: relative; z-index: 1; }
.article-head h1 { max-width: 17em; text-wrap: balance; }
.article-head .lead { max-width: 38em; }
.byline {
  display: flex; flex-wrap: wrap; gap: 8px 22px; margin-top: 24px;
  font-family: var(--font-ui); font-size: 0.84rem; color: var(--muted);
}
.byline b { color: var(--text); font-weight: 600; }
.byline .dot-sep { color: var(--seal); }
.article-body { padding: clamp(44px, 5.5vw, 72px) 0 clamp(60px, 7.5vw, 96px); }
.article-body .wrap-narrow > h2 { margin-top: 2em; padding-top: 0.6em; position: relative; }
.article-body .wrap-narrow > h2::before {
  content: ''; position: absolute; top: 0; left: 0; width: 52px; height: 3px;
  background: var(--seal); border-radius: 2px;
}
.article-body .wrap-narrow > h3 { margin-top: 1.6em; }
.article-body .table-wrap { margin: 1.4em 0; }
.toc {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 24px 28px; margin: 0 0 2.2em; font-family: var(--font-ui);
}
.toc h2 { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.14em; color: var(--muted); margin: 0 0 12px; font-weight: 700; }
.toc ol { margin: 0; padding-left: 1.2em; font-size: 0.92rem; columns: 2; column-gap: 36px; }
.toc li { margin-bottom: 7px; break-inside: avoid; }
.toc a { color: var(--text-2); text-decoration: none; }
.toc a:hover { color: var(--seal); text-decoration: underline; }
.callout {
  border-left: 3px solid var(--seal); background: #fdf3f1;
  border-radius: 0 var(--r-sm) var(--r-sm) 0; padding: 20px 24px; margin: 1.6em 0; font-size: 0.97rem;
}
.callout.is-leaf { border-left-color: var(--text); background: var(--panel); }
.callout p:last-child { margin-bottom: 0; }

.answer-box {
  background: var(--card); border: 1.5px solid var(--black); border-radius: var(--r-card);
  padding: 24px 28px; margin: 1.4em 0 2em; position: relative;
}
.answer-box::before {
  content: attr(data-label);
  position: absolute; top: -12px; left: 18px;
  background: var(--black); color: #fff; font-family: var(--font-ui);
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 4px 12px; border-radius: 99px;
}
.answer-box p:last-child { margin-bottom: 0; }

/* ---------- contact ---------- */
.contact-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: clamp(30px, 5vw, 70px); align-items: start; }
.contact-card { background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-2); padding: clamp(28px, 3.5vw, 44px); }
body.page-contact #main > .section:first-child { padding-top: clamp(44px, 5vw, 68px); }
.field { margin-bottom: 18px; }
.field label { display: block; font-family: var(--font-ui); font-size: 0.86rem; font-weight: 600; margin-bottom: 6px; }
.field input, .field textarea, .field select {
  width: 100%; padding: 13px 16px; font: inherit; font-size: 0.97rem;
  border: 1.5px solid #8a8578; border-radius: var(--r-sm); background: #fff; color: var(--text);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.field input:focus, .field textarea:focus, .field select:focus {
  border-color: var(--black); box-shadow: 0 0 0 4px rgba(17, 19, 24, 0.08);
}
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible {
  outline: 3px solid var(--seal); outline-offset: 2px;
}
.form-note { font-size: 0.84rem; color: var(--muted); font-family: var(--font-ui); margin-top: 12px; }
.contact-aside .eyebrow { margin-top: 2em; }
.contact-aside .eyebrow:first-child { margin-top: 0; }
.contact-aside p { color: var(--text-2); }
.contact-aside .big-mail { font-family: var(--font-display); font-size: 1.3rem; font-weight: 600; }
.next-steps { list-style: none; padding: 0; margin: 0; font-family: var(--font-ui); font-size: 0.92rem; color: var(--text-2); counter-reset: ns; }
.next-steps li { counter-increment: ns; position: relative; padding: 8px 0 8px 42px; margin: 0; }
.next-steps li::before {
  content: counter(ns);
  position: absolute; left: 0; top: 7px; width: 27px; height: 27px; border-radius: 50%;
  background: var(--card); color: var(--text); border: 1px solid var(--line-2);
  font-weight: 700; font-size: 0.78rem;
  display: flex; align-items: center; justify-content: center;
}
.next-steps strong { color: var(--text); font-weight: 600; }

/* ---------- city band: quiet skyline divider ---------- */
.city-band { background: linear-gradient(180deg, var(--base) 0%, #efede8 100%); position: relative; line-height: 0; overflow: hidden; border-top: 1px solid var(--line); }
.city-band .city-skyline { width: 100%; height: clamp(90px, 12vw, 170px); color: var(--text); opacity: 0.08; display: block; }
.city-band .win-lights { display: none; }
.city-band::before { display: none; }
.city-band .city-names {
  position: absolute; left: 0; right: 0; top: clamp(16px, 3.5vw, 40px);
  text-align: center; line-height: 1.4; margin: 0;
  font-family: var(--font-ui); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.3em; text-transform: uppercase; color: var(--muted);
}
.city-band .city-names::after {
  content: ''; display: block; width: 38px; height: 2px; margin: 10px auto 0;
  background: var(--seal); border-radius: 2px;
}

/* ---------- footer: framed, column labels in mono ---------- */
.site-foot { background: #fbfaf7; color: var(--muted); font-family: var(--font-ui); margin-top: -1px; border-top: 1px solid var(--line); }
.foot-frame { border-left: 1px solid var(--rail); border-right: 1px solid var(--rail); padding-top: clamp(44px, 5.4vw, 72px); }
.foot-top { display: grid; grid-template-columns: minmax(230px, 1fr) minmax(0, 3.1fr); gap: clamp(32px, 5vw, 76px); padding-bottom: clamp(36px, 4.4vw, 56px); }
.foot-tile { display: inline-flex; padding: 10px 15px 11px; background: #fff; border: 1px solid var(--line); border-radius: 12px; }
.site-foot .logo-word { color: var(--text); font-size: 1.22rem; }
.foot-brand p { font-size: 0.88rem; line-height: 1.55; margin: 16px 0 0; max-width: 30em; color: var(--text-2); }
.foot-marks { display: flex; flex-wrap: wrap; gap: 6px; }
.foot-marks span {
  font-family: var(--font-mono); font-size: 0.64rem; font-weight: 500; line-height: 1;
  padding: 7px 9px; color: var(--text-2); background: #fff;
  border: 1px solid var(--line-2); border-radius: 999px; white-space: nowrap;
}
.foot-cols { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 44px clamp(20px, 3vw, 40px); align-content: start; }
.site-foot h3 {
  font-family: var(--font-mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); margin: 0 0 15px;
}
.site-foot nav a { display: block; color: var(--text); text-decoration: none; font-size: 0.9rem; line-height: 1.35; padding: 6px 0; overflow-wrap: anywhere; transition: color 0.15s ease; }
.site-foot nav a:hover { color: var(--seal); }
.foot-langs { grid-column: 1 / -1; padding-top: 28px; border-top: 1px solid var(--line); }
.foot-lang-links { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2px clamp(20px, 3vw, 40px); }
.foot-lang-links a { color: var(--text-2); text-decoration: none; font-size: 0.86rem; padding: 4px 0; }
.foot-lang-links a:hover { color: var(--seal); }
.foot-legal { display: flex; justify-content: space-between; gap: 18px; flex-wrap: wrap; border-top: 1px solid var(--line); padding-top: 18px; padding-bottom: 22px; font-size: 0.8rem; }
.foot-legal p { margin: 0; }
.foot-legal a { color: var(--text-2); }

/* ---------- floating helpers ---------- */
.mobile-cta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
  background: rgba(247, 246, 245, 0.92);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
  transform: translateY(110%); transition: transform 0.35s cubic-bezier(0.2, 0.8, 0.3, 1);
  display: none;
}
.mobile-cta .btn { width: 100%; }
.mobile-cta.show { transform: translateY(0); }
@media (max-width: 880px) { .mobile-cta { display: block; } }

.to-top {
  position: fixed; right: 20px; bottom: 20px; z-index: 95;
  width: 46px; height: 46px; border-radius: 50%;
  background: #fff; color: var(--text);
  border: 1px solid var(--line-2);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  opacity: 0; pointer-events: none; transform: translateY(14px);
  transition: opacity 0.3s ease, transform 0.3s ease, border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
  box-shadow: var(--shadow-2);
}
.to-top.show { opacity: 1; pointer-events: auto; transform: none; }
.to-top:hover { background: var(--black); border-color: var(--black); color: #fff; }
.to-top svg { width: 19px; height: 19px; }
@media (max-width: 880px) { .to-top { bottom: 84px; } }

/* ---------- scroll reveal ---------- */
.js .reveal { opacity: 0; transform: translateY(24px); }
.js .reveal.in {
  opacity: 1; transform: none;
  transition: opacity 0.7s ease calc(var(--d, 0) * 1ms), transform 0.7s cubic-bezier(0.2, 0.8, 0.3, 1) calc(var(--d, 0) * 1ms);
}

/* pause decorative loops while off-screen */
.js .hero.anim-off .hero-art { animation-play-state: paused; }

/* scroll-driven cinema (Chromium; others skip) */
@supports (animation-timeline: scroll()) {
  .city-band .city-skyline { animation: skyDrift linear both; animation-timeline: view(); animation-range: entry 0% exit 100%; }
  @keyframes skyDrift {
    from { transform: translateX(-2%) scale(1.05); }
    to { transform: translateX(2%) scale(1.05); }
  }
}

/* ---------- responsive ---------- */
@media (max-width: 1020px) {
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .steps { grid-template-columns: repeat(2, 1fr); gap: 26px 20px; }
  .steps li::after { display: none; }
  .foot-top { grid-template-columns: 1fr; }
  .foot-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot-lang-links { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 880px) {
  .mega { display: none; }
  .site-nav {
    display: none;
    position: absolute; top: 100%; left: 0; right: 0;
    background: rgba(247, 246, 245, 0.98);
    backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-2); padding: 10px 14px 16px;
  }
  body.nav-open .site-nav { display: block; }
  .site-nav ul { flex-direction: column; gap: 0; }
  .site-nav a { padding: 13px 12px; font-size: 1.02rem; border-radius: 10px; }
  .nav-toggle {
    display: flex; flex-direction: column; justify-content: center; gap: 4.5px;
    width: 42px; height: 42px; padding: 0 9px;
    background: #fff; border: 1px solid var(--line-2); border-radius: 10px; cursor: pointer;
  }
  .nav-toggle span { height: 2px; background: var(--text); border-radius: 2px; transition: transform 0.2s ease, opacity 0.2s ease; }
  body.nav-open .nav-toggle span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
  body.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
  body.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }
  .head-actions .btn { display: none; }
  .hero-grid { padding-top: 44px; }
  .feat { grid-template-columns: 1fr; }
  .feat-nav { display: none; }
  .split { grid-template-columns: 1fr; }
  .split-panel.is-ink { border-right: none; border-bottom: 1px solid var(--line); }
  .price-grid { grid-template-columns: 1fr; }
  .contact-grid { grid-template-columns: 1fr; }
  .stat-grid { grid-template-columns: 1fr 1fr; }
  .toc ol { columns: 1; }
}
@media (max-width: 560px) {
  .hero-points { display: none; }
  .grid-3, .grid-2, .steps { grid-template-columns: 1fr; }
  .stat-grid { grid-template-columns: 1fr; }
  .foot-lang-links { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero-ctas .btn { width: 100%; }
  .lang ul { position: fixed; left: 14px; right: 14px; top: 72px; min-width: 0; }
}
/* ---------- motion & print ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  ::view-transition-group(*), ::view-transition-image-pair(*),
  ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}
@media (forced-colors: active) {
  .site-nav a[aria-current='page'] { text-decoration: underline; }
}
@media print {
  .site-head, .site-foot, .cta-band, .city-band, .nav-toggle, .mobile-cta, .to-top { display: none; }
  .fx-film .fx-film__pp, .fx-rings__pp { display: none !important; }
  .reveal { opacity: 1 !important; transform: none !important; }
  .band { background: #fff !important; color: #000 !important; }
  .band h2, .stat .n { color: #000 !important; }
  .stat .d, .band .note { color: #333 !important; }
}

/* fx:_fx-core.css */
/* fx-core — shared film box + the primitives every fx component leans on.
 * Depends only on tokens the integrator adds to :root (--wash, --grid-dot,
 * --line, --seal, --font-mono, --text, --muted, --card). Component-specific
 * CSS lives in its own assets/css/fx/*.css file.
 *
 * The film box reserves its space with aspect-ratio (CLS = 0) and shows the
 * poster as the complete state. The <video> only becomes visible once the
 * player attaches and starts it; with no JS or reduced motion the poster is all
 * there is, which is exactly correct.
 */

.fx-film {
  position: relative;
  display: block;
  width: 100%;
  overflow: hidden;
  border-radius: var(--r-card, 16px);
  border: 1px solid var(--line, #e6e4dd);
  background-color: var(--wash, #eef1f6);
  /* faint dot grid behind the frame — decorative, ≤ one hairline value */
  background-image: radial-gradient(var(--grid-dot, rgba(25, 26, 35, 0.055)) 1px, transparent 1.4px);
  background-size: 22px 22px;
  background-position: -11px -11px;
  isolation: isolate;
}

/* poster = the complete, readable state. Always painted; never removed. */
.fx-film__poster {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  padding: clamp(14px, 4%, 34px);
  opacity: 1;
  transition: opacity 420ms cubic-bezier(.2, .7, .2, 1);
}
.fx-film__poster > svg,
.fx-film__poster > img {
  width: 100%;
  height: auto;
  max-height: 100%;
  object-fit: contain;
  display: block;
}

/* video sits above the poster; hidden until the player starts it */
.fx-film__video {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 420ms cubic-bezier(.2, .7, .2, 1);
  background: var(--wash, #eef1f6);
}

/* caption — mono, quiet, bottom-right. Holds the sample-data disclosure. */
.fx-film__cap {
  position: absolute;
  z-index: 3;
  right: 10px;
  bottom: 10px;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.64rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1;
  color: var(--muted, #60646b);
  background: color-mix(in srgb, var(--card, #fff) 82%, transparent);
  border: 1px solid var(--line, #e6e4dd);
  border-radius: 999px;
  padding: 4px 9px;
  pointer-events: none;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

/* pause / play control — hairline round button, hidden until a video attaches
 * (so no-JS and reduced-motion never show a dead control). */
.fx-film__pp {
  position: absolute;
  z-index: 3;
  left: 10px;
  bottom: 10px;
  display: none;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--line-2, #d8d5cc);
  border-radius: 50%;
  background: color-mix(in srgb, var(--card, #fff) 88%, transparent);
  color: var(--text, #191a23);
  cursor: pointer;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  transition: color 200ms ease, border-color 200ms ease, transform 200ms ease;
}
.fx-film__pp:hover { color: var(--seal, #c4332f); border-color: var(--seal, #c4332f); }
.fx-film__pp:active { transform: scale(0.94); }
.fx-film__pp svg { width: 16px; height: 16px; display: block; fill: currentColor; }

/* focus visibility, matching the site */
.fx-film__pp:focus-visible { outline: 3px solid var(--seal, #c4332f); outline-offset: 2px; }

/* Under reduced motion the player never attaches a video: keep the poster as
 * the complete state and keep the dead control hidden. */
@media (prefers-reduced-motion: reduce) {
  .fx-film__video { display: none; }
  .fx-film__poster { transition: none; }
}

/* fx:fx-band.css */
/* fx-band — the cinematic layer behind the one dark #numbers band (SPEC D.1).
 * Everything here is injected by fx-band.js; with no JS nothing applies and the
 * plain dark band is the complete state. The `nuoc-ve-dem` film sits full-bleed
 * behind the section under a dark scrim; the opaque stat panels ride on top, the
 * white heading reads AA over the scrim, and a mono 01–06 label sits on each
 * stat. The band remains the only dark surface and the only red is the film's
 * own sun-star.
 */

/* the section already is position:relative; overflow:hidden (.band). */
#numbers.has-fx-band .wrap { position: relative; z-index: 1; }   /* stats above film */

/* ---------- the film layer (behind .wrap, over the band's own dark bg) ---------- */
#numbers.has-fx-band { padding-top: clamp(230px, 31vw, 440px); }

.fx-band {
  position: absolute;
  inset: 0 0 auto 0;
  height: clamp(300px, 40vw, 580px);
  z-index: 0;
  overflow: hidden;
  pointer-events: none;         /* only the pause button opts back in */
}

/* re-point the film's aspect-ratio box to a full-bleed cover surface */
.fx-band .fx-film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: 0;
  background-color: var(--dark, #0c1624);
  background-image: none;
}
.fx-band .fx-film__poster { padding: 0; }
.fx-band .fx-film__poster > img,
.fx-band .fx-film__poster > svg {
  width: 100%;
  height: 100%;
  max-height: none;
  object-fit: cover;
}
.fx-band .fx-film__video { background: var(--dark, #0c1624); }

/* the pause control + caption live up in the section's top padding, clear of
 * the heading and the grid, and over the film (the only parts that opt back
 * into pointer events). */
.fx-band .fx-film__pp,
.fx-band .fx-film__cap { pointer-events: auto; }
.fx-band .fx-film__pp {
  top: clamp(18px, 3.4vw, 40px);
  left: clamp(14px, 3vw, 40px);
  right: auto;
  bottom: auto;
  border-color: rgba(255, 255, 255, 0.28);
  background: color-mix(in srgb, #0c1624 62%, transparent);
  color: #fff;
}
.fx-band .fx-film__pp:hover { color: #fff; border-color: var(--seal, #c4332f); }
.fx-band .fx-film__cap {
  top: clamp(18px, 3.4vw, 40px);
  right: clamp(14px, 3vw, 40px);
  bottom: auto;
  color: rgba(255, 255, 255, 0.82);
  background: color-mix(in srgb, #0c1624 60%, transparent);
  border-color: rgba(255, 255, 255, 0.22);
}

/* dark scrim: transparent across the top padding (film + controls read there),
 * darkening behind the heading and the stat grid so white text stays AA. */
.fx-band__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(12, 22, 36, 0) 0%, rgba(12, 22, 36, 0) 62%, var(--dark, #0c1624) 100%);
}

/* ---------- mono 01–06 strip, one per stat ---------- */
.fx-band__num {
  position: absolute;
  top: 16px;
  right: 20px;
  z-index: 2;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  line-height: 1;
  color: rgba(255, 255, 255, 0.6);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.js #numbers.has-fx-band .fx-band__num {
  opacity: 0;
  transform: translateY(-5px);
  transition:
    opacity 0.5s cubic-bezier(.2, .7, .2, 1),
    transform 0.5s cubic-bezier(.2, .7, .2, 1);
  transition-delay: calc(var(--i, 0) * 70ms);
}
.js #numbers.has-fx-band.is-seen .fx-band__num { opacity: 1; transform: none; }

/* small screens: keep the strip clear of the number */
@media (max-width: 760px) {
  .fx-band__num { top: 14px; right: 16px; }
}

/* reduced motion: no scrub, labels settled, film never attaches (poster only) */
@media (prefers-reduced-motion: reduce) {
  .js #numbers.has-fx-band .fx-band__num {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* fx:fx-connector.css */
/* fx-connector — the red thread drawn through a `.steps` list by
 * assets/js/fx/fx-connector.js. The player adds `.fx-conn-host` to the list and
 * injects one `.fx-conn` SVG as its first child, behind the numbered circles.
 *
 * Palette gate: the thread is the one red (var(--seal)); nothing else is added.
 * It replaces the native grey hairline (`.steps li::after`) only while the
 * enhancement is live — with JS off the class is never added, so the native
 * hairline remains and the steps are complete. The circles keep their solid
 * card background, so the thread reads as passing *through* them.
 */

/* host: give the list a positioning context and retire the native hairline so
 * the red thread is the only connector while the enhancement is on. */
.steps.fx-conn-host { position: relative; }
.steps.fx-conn-host > li::after { display: none; }

.fx-conn {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
  /* painted before the <li>s (first child, z-index auto) so the circles,
   * painted after, sit on top and the thread passes behind them. */
}

.fx-conn__path {
  fill: none;
  stroke: var(--seal, #c4332f);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  /* drawn once on view: dasharray/offset are set by the player; this is the
   * calm eased reveal (no bounce). */
  transition: stroke-dashoffset 0.8s cubic-bezier(.2, .7, .2, 1);
}

/* Mobile: the steps stack into one column, so the thread becomes a vertical
 * rail. Indent the step content past the circle column so the rail runs down a
 * clean left gutter instead of crossing the text. Matches site.css's 1-column
 * breakpoint, which is exactly when the player switches to vertical. */
@media (max-width: 560px) {
  .steps.fx-conn-host > li {
    padding-top: 0;
    padding-left: 68px;
    min-height: 46px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .fx-conn__path { transition: none; }
}

/* fx:fx-costbar.css */
/* fx-costbar — the pricing cost-stack bar drawn by costBar() in
 * src/fx/costbar.mjs and injected into #pricing-teaser by fx-costbar.js.
 *
 * Palette gate: only ink, white, --wash, hairline and the one red survive.
 *   gross base = ink   ·  statutory band = --wash-2  ·  fee sliver = --seal.
 * Red is on the fee segment ONLY. The bar grows once from the left and the
 * three figures count up (fx-costbar.js); with no JS nothing is injected and
 * the teaser copy stands alone; under reduced motion the site-wide
 * `* { transition:none }` rule makes `.is-in` snap straight to the final bar.
 */

.fx-cost {
  display: block;
  max-width: 560px;
  margin: clamp(26px, 4vw, 40px) auto 2px;
  padding: 0;
  text-align: left;
}

/* ---- the bar ---- */
.fx-cost__barwrap {
  position: relative;
}
.fx-cost__bar {
  display: block;
  width: 100%;
  height: clamp(42px, 6vw, 54px);
  border: 1px solid var(--line, #e6e4dd);
  border-radius: var(--r-btn, 12px);
  overflow: hidden;              /* rounds the outer corners; inner gaps stay crisp */
  background: var(--card, #fff);
}

/* grows from the left on reveal; one calm eased sweep, no bounce */
.fx-cost__grow {
  transform: scaleX(1);
  transform-origin: left center;
  transform-box: fill-box;
  transition: transform 1.15s cubic-bezier(.2, .7, .2, 1);
}
.fx-cost.is-armed .fx-cost__grow { transform: scaleX(0); }
.fx-cost.is-armed.is-in .fx-cost__grow { transform: scaleX(1); }

.fx-cost__seg--gross { fill: var(--text, #191a23); }
.fx-cost__seg--add   { fill: var(--wash-2, #e7ecf2); }
.fx-cost__seg--fee   { fill: var(--seal, #c4332f); }

/* ---- fee callout, pinned over the red sliver ---- */
.fx-cost__fee {
  position: absolute;
  right: 2px;
  bottom: calc(100% + 7px);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--seal, #c4332f);
  white-space: nowrap;
  transition: opacity .4s ease .5s, transform .4s cubic-bezier(.2, .7, .2, 1) .5s;
}
.fx-cost.is-armed .fx-cost__fee { opacity: 0; transform: translateY(4px); }
.fx-cost.is-armed.is-in .fx-cost__fee { opacity: 1; transform: none; }
.fx-cost__dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--seal, #c4332f);
  flex: none;
}

/* ---- the three milestone figures ---- */
.fx-cost__axis {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: end;
  gap: 8px 10px;
  margin-top: 14px;
}
.fx-cost__fig {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-variant-numeric: tabular-nums;
  font-size: clamp(0.72rem, 2.3vw, 0.9rem);
  font-weight: 500;
  color: var(--text-2, #4a4f57);
  letter-spacing: 0.01em;
  transition: opacity .5s ease;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.fx-cost.is-armed .fx-cost__fig { opacity: 0; }
.fx-cost.is-armed.is-in .fx-cost__fig { opacity: 1; }
.fx-cost__fig:nth-child(1) { justify-self: start; transition-delay: .05s; }
.fx-cost__fig:nth-child(2) { justify-self: center; transition-delay: .28s; }
.fx-cost__fig:nth-child(3) { justify-self: end; transition-delay: .55s; }
.fx-cost__num { font-weight: 500; white-space: nowrap; }

/* the all-in figure carries the one red accent (the fee is folded in) */
.fx-cost__fig--all { color: var(--text, #191a23); font-weight: 600; }
.fx-cost__fig--all::before {
  content: '';
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--seal, #c4332f);
  flex: none;
}

@media (max-width: 480px) {
  .fx-cost__axis { gap: 6px 6px; }
  .fx-cost__fig { gap: 5px; }
  .fx-cost__fee { font-size: 0.62rem; }
}

.fx-cost__fig { flex-direction: column; gap: 3px; }
.fx-cost__fig:nth-child(1) { align-items: flex-start; }
.fx-cost__fig:nth-child(2) { align-items: center; text-align: center; }
.fx-cost__fig:nth-child(3) { align-items: flex-end; text-align: right; }
.fx-cost__fig--all::before { display: none; }
.fx-cost__lab { font-family: var(--font-mono); font-size: 0.62rem; font-weight: 500; letter-spacing: 0.04em; color: var(--muted); }

/* fx:fx-coverage.css */
/* fx-coverage — the Vietnam dot-map drawn by coverage() in src/fx/coverage.mjs.
 *
 * A <canvas> dot-field (fx-coverage.js) sits over a complete static SVG fallback
 * (coastline + coarse dot field + three red city dots). With no JS or under
 * reduced motion the canvas stays hidden and the fallback is the complete state;
 * with JS + motion the canvas fades in and the three city dots pulse calmly. The
 * HTML city labels show in both states. Red is used on ONLY the three city dots;
 * every other dot is ink. No isometric disc, no fabricated scale.
 */

.fx-cov {
  display: block;
  margin: 0;
  width: 100%;
  max-width: 360px;
  margin-inline: auto;
}

.fx-cov__stage {
  position: relative;
  width: 100%;
  aspect-ratio: 490 / 570;      /* reserves height -> CLS 0 */
  color: var(--text, #191a23);
}

/* animated field — hidden until fx-coverage.js sets .is-live */
.fx-cov__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 420ms cubic-bezier(.2, .7, .2, 1);
}
.fx-cov.is-live .fx-cov__canvas { opacity: 1; }

/* static fallback — the complete readable state with no JS / reduced motion */
.fx-cov__fallback {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: var(--text, #191a23);
  transition: opacity 420ms cubic-bezier(.2, .7, .2, 1);
}
.fx-cov.is-live .fx-cov__fallback { opacity: 0; }

.fx-cov__coast { stroke: currentColor; stroke-width: 1.1; opacity: 0.26; stroke-linejoin: round; }
.fx-cov__dots { opacity: 0.32; }
.fx-cov__cities { fill: var(--seal, #c4332f); }

/* city labels — mono, quiet, crisp HTML; shown in both states */
.fx-cov__labels { position: absolute; inset: 0; pointer-events: none; }
.fx-cov__label {
  position: absolute;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  line-height: 1;
  white-space: nowrap;
  color: var(--text, #191a23);
  text-transform: uppercase;
}
.fx-cov__label--l { transform: translate(calc(-100% - 10px), -50%); }
.fx-cov__label--r { transform: translate(10px, -50%); }
.fx-cov__label--isle { transform: translate(-50%, -50%); color: var(--muted, #60646b); font-weight: 500; font-size: 0.58rem; text-transform: none; letter-spacing: 0.03em; }

/* host layout: injected into #what .section-head at ≥980px — copy left, map right */
.fx-cov-host {
  display: flex;
  align-items: center;
  gap: clamp(30px, 5vw, 70px);
  max-width: none !important;
}
.fx-cov-host__body { flex: 1 1 auto; min-width: 0; max-width: 760px; }
.fx-cov-host .fx-cov { flex: 0 0 auto; width: clamp(250px, 27vw, 340px); margin-inline: 0; }

@media (prefers-reduced-motion: reduce) {
  .fx-cov .fx-cov__canvas { opacity: 0 !important; }
  .fx-cov .fx-cov__fallback { opacity: 1 !important; }
}

/* fx:fx-diligence-fan.css */
/* fx-diligence-fan — a tiny document thumbnail fanned into the top of each of
 * the three existing #diligence .card items (ADDENDUM §4). Enhancement only:
 * the markup is injected by fx-diligence-fan.js, so nothing here applies without
 * JS. Calm, one-shot reveal — the row fans in once, each doc's marks settle,
 * then it holds. No continuous loop, no bounce. Only ink, cream, white, the
 * hairline and the one red.
 */

.fx-fan {
  width: 112px;
  max-width: 46%;
  margin: 0 0 16px -30px;
  /* resting = fanned; the pre-reveal state below is what animates toward this */
}
.fx-fan__svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  color: var(--text, #191a23);          /* ink, for the hairline marks */
}

/* the document sheet */
.fx-fan__pg {
  fill: var(--card, #fff);
  stroke: var(--line, #e6e4dd);
  stroke-width: 1.4;
}

/* ruled text lines (ink hairlines) */
.fx-fan__ln {
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-opacity: 0.24;
}

/* report baseline */
.fx-fan__base {
  stroke: var(--line-2, #d8d5cc);
  stroke-width: 1.4;
  stroke-linecap: round;
}

/* report bars (ink) */
.fx-fan__bar {
  fill: var(--text, #191a23);
  fill-opacity: 0.82;
}

/* registration header band (ink) */
.fx-fan__hd {
  fill: var(--text, #191a23);
  fill-opacity: 0.85;
}

/* the one red: contract seal + registration stamp */
.fx-fan__seal-ring { fill: none; stroke: var(--seal, #c4332f); stroke-width: 1.6; }
.fx-fan__seal-star { fill: var(--seal, #c4332f); }

/* ---------- pre-reveal state (the row sits stacked, tilted, faded) ---------- */
.js .fx-fan {
  opacity: 0;
  transform: translateY(12px) rotate(-7deg) scale(0.92);
  transform-origin: 22% 100%;
  transition:
    opacity 0.5s cubic-bezier(.2, .7, .2, 1),
    transform 0.6s cubic-bezier(.2, .7, .2, 1);
  transition-delay: calc(var(--fan-i, 0) * 110ms);
}
.js .fx-fan__ln,
.js .fx-fan__hd {
  opacity: 0;
  transform: scaleX(0.35);
  transform-box: fill-box;
  transform-origin: left center;
  transition: opacity 0.42s ease, transform 0.52s cubic-bezier(.2, .7, .2, 1);
  transition-delay: calc(var(--fan-i, 0) * 110ms + 220ms + var(--i, 0) * 55ms);
}
.js .fx-fan__bar {
  opacity: 0;
  transform: scaleY(0);
  transform-box: fill-box;
  transform-origin: center bottom;
  transition: opacity 0.3s ease, transform 0.5s cubic-bezier(.2, .7, .2, 1);
  transition-delay: calc(var(--fan-i, 0) * 110ms + 260ms + var(--i, 0) * 60ms);
}
.js .fx-fan__seal,
.js .fx-fan__stamp {
  opacity: 0;
  transform: scale(0.35) rotate(-16deg);
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 0.34s ease, transform 0.44s cubic-bezier(.2, .7, .2, 1);
  transition-delay: calc(var(--fan-i, 0) * 110ms + 420ms);
}

/* ---------- fanned-in (settled) ---------- */
.js .fx-fan.is-fanned { opacity: 1; transform: none; }
.js .fx-fan.is-fanned .fx-fan__ln,
.js .fx-fan.is-fanned .fx-fan__hd,
.js .fx-fan.is-fanned .fx-fan__bar { opacity: 1; transform: none; }
.js .fx-fan.is-fanned .fx-fan__seal,
.js .fx-fan.is-fanned .fx-fan__stamp { opacity: 1; transform: none; }

/* smaller cards (2-up / 1-up): keep the thumbnail tidy */
@media (max-width: 1020px) {
  .fx-fan { width: 104px; }
}

/* reduced motion: injected but settled, no animation, no pre-reveal flash */
@media (prefers-reduced-motion: reduce) {
  .js .fx-fan,
  .js .fx-fan__ln,
  .js .fx-fan__hd,
  .js .fx-fan__bar,
  .js .fx-fan__seal,
  .js .fx-fan__stamp {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

.fx-fan + .card-ico { display: none; }

/* fx:fx-drum-mark.css */
/* fx-drum-mark — the EOR◎VN wordmark standing on a Đông Sơn drum face, drawn by
 * drumMark() in src/fx/drum-mark.mjs. It replaces the round red seal in the CTA
 * band (here) and at the centre of the statute rings (fx-legal-rings.css).
 *
 * Everything is sized in em, so a context only sets font-size. The resting
 * markup IS the settled state — no JS and reduced motion both show it still.
 * fx-drum-mark.js adds `.is-in` once the mark is well inside the viewport and
 * removes it when it has fully left, so the entry plays each time it is seen:
 * the word drops onto the drum, its shadow lands, two seal-red ripples run out
 * (≈3.7s in all, then still), and the drum keeps a 120s turn that stops off-screen.
 * Only accent: the ring between EOR and VN and the ripples (seal red).
 */

.dmark {
  position: relative;
  display: block;
  width: 4.7em;
  height: 2.4em;
  perspective: 9em;
  /* the mark is Latin in every locale: never fall to a CJK display face */
  font-family: 'Hanken Grotesk', var(--font-display, 'Segoe UI'), system-ui, sans-serif;
  font-weight: 650;
  line-height: 0.92;
  letter-spacing: -0.045em;
  color: var(--text, #191a23);
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
}

/* the drum face, laid flat in perspective under the word */
.dmark__floor {
  position: absolute;
  left: 50%;
  top: 66%;
  width: 5.4em;
  height: 5.4em;
  transform: translate(-50%, -50%) rotateX(76deg);
}
.dmark__drum {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0.22;
  overflow: visible;
}
.dmark__rip {
  position: absolute;
  inset: 31%;
  border: 0.028em solid var(--seal, #c4332f);
  border-radius: 50%;
  opacity: 0;
}

/* contact shadow where the word meets the drum */
.dmark__shade {
  position: absolute;
  left: 50%;
  top: 64%;
  width: 3.3em;
  height: 0.42em;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(20, 22, 26, 0.2), rgba(20, 22, 26, 0));
}

.dmark__word {
  position: absolute;
  left: 50%;
  top: 42%;
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}
.dmark__lt {
  color: inherit;
  text-shadow:
    0 0.012em 0 #101118, 0 0.024em 0 #0c0d12, 0 0.036em 0 #090a0d,
    0 0.07em 0.05em rgba(0, 0, 0, 0.1);
}
.dmark__ring {
  flex: 0 0 auto;
  display: block;
  width: 0.66em;
  height: 0.66em;
  margin: 0 0.07em 0 0.05em;
  color: var(--seal, #c4332f);
}

/* --- entry, only while .is-in (set by fx-drum-mark.js when motion is allowed) --- */
.dmark.is-in .dmark__word  { animation: dmarkDrop 0.9s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
.dmark.is-in .dmark__shade { animation: dmarkShade 0.9s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
.dmark.is-in .dmark__rip   { animation: dmarkRip 2.2s cubic-bezier(0.2, 0.7, 0.2, 1) 0.6s both; }
.dmark.is-in .dmark__rip--2 { animation-delay: 1.5s; }
.dmark.is-in .dmark__drum  { animation: dmarkSpin 120s linear infinite; }

@keyframes dmarkDrop {
  from { opacity: 0; transform: translate(-50%, -95%); }
  to   { opacity: 1; transform: translate(-50%, -50%); }
}
@keyframes dmarkShade {
  from { opacity: 0; transform: translate(-50%, -50%) scale(0.45); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes dmarkRip {
  0%   { opacity: 0; transform: scale(0.3); }
  14%  { opacity: 0.85; }
  100% { opacity: 0; transform: scale(1.95); }
}
@keyframes dmarkSpin { to { transform: rotate(360deg); } }

/* ---------- CTA band: the mark replaces the faint spinning seal ---------- */
.cta-band .cta-seal { font-size: clamp(56px, 6.4vw, 92px); }

/* wide: beside the copy, centred in the free right-hand column */
@media (min-width: 1080px) {
  .cta-band .cta-seal {
    position: absolute;
    top: 50%;
    right: clamp(22px, 4vw, 64px);
    transform: translateY(-50%);
  }
}

/* narrow: under the buttons, pulled up into the band's bottom padding */
@media (max-width: 1079px) {
  .cta-band .wrap { display: flex; flex-direction: column; }
  .cta-band .cta-seal {
    order: 2;
    align-self: center;
    font-size: clamp(50px, 12vw, 80px);
    margin: calc(-1 * clamp(24px, 5vw, 56px)) 0 clamp(40px, 7vw, 72px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .dmark *, .dmark *::before, .dmark *::after { animation: none !important; }
}

@media (forced-colors: active) {
  .dmark__lt { text-shadow: none; }
  .dmark__shade { display: none; }
}

/* fx:fx-drum.css */
/* fx-drum — the Đông Sơn ring field drawn by drum() in src/fx/drum.mjs.
 *
 * It is purely decorative: a static hairline ring field at ≤10% opacity that
 * rotates once every 240s (calm, no bounce). With no JS it is a still SVG; under
 * reduced motion the rotation is off; a global `.anim-off` ancestor also pauses
 * it; fx-drum.js pauses the spin while the field is off-screen to save CPU.
 *
 * Colour is inherited (currentColor) so a dark surface can set a cool white;
 * on cream it uses ink. Only ever ink / white — never a second hue.
 */

.fx-drum {
  display: block;
  width: 100%;
  height: 100%;
  color: var(--text, #191a23);
  opacity: 0.07;                 /* ≤10% — decorative texture only */
  pointer-events: none;
  overflow: visible;
}

.fx-drum__spin {
  transform-box: view-box;
  transform-origin: 300px 300px; /* centre of the 600×600 viewBox */
  animation: fxDrumSpin 240s linear infinite;
  will-change: transform;
}

/* fx-drum.js adds .is-rest while the field is scrolled out of view; a site-wide
 * `.anim-off` also stops it. Rotation never affects layout, so CLS stays 0. */
.fx-drum.is-rest .fx-drum__spin,
.anim-off .fx-drum__spin {
  animation-play-state: paused;
}

@keyframes fxDrumSpin {
  to { transform: rotate(360deg); }
}

/* Small screens: keep a calm three-ring field, static. */
@media (max-width: 760px) {
  .fx-drum .fx-drum__ring--outer { display: none; }
  .fx-drum__spin { animation: none; transform: none; }
}

/* Reduced motion: a still ring field. */
@media (prefers-reduced-motion: reduce) {
  .fx-drum__spin { animation: none; }
}

/* fx:fx-film.css */
/* fx-film — player state on top of the box defined in _fx-core.css.
 * Nothing here runs without JS: the state classes (.is-ready / .is-attached /
 * .is-playing) are only ever added by fx-film.js once a video is eligible and
 * has buffered a frame, so the poster-only path is untouched.
 */

/* reveal the pause control only once the player has taken over the box */
.fx-film.is-ready .fx-film__pp { display: flex; }

/* crossfade: once the video has a frame buffered, fade the poster out under it
 * (the poster stays in the DOM as the fallback, just visually behind). */
.fx-film.is-attached .fx-film__video { opacity: 1; }
.fx-film.is-attached .fx-film__poster { opacity: 0; }

/* a resting film (paused by the viewer, or settled) keeps its last frame shown */
.fx-film.is-attached:not(.is-playing) .fx-film__video { opacity: 1; }

/* small screens: keep the caption and control comfortably tappable */
@media (max-width: 760px) {
  .fx-film__pp { width: 30px; height: 30px; }
  .fx-film__cap { font-size: 0.54rem; }
  .fx-film__cap { font-size: 0.6rem; padding: 3px 7px; }
}

/* reduced motion: fx-film.js never attaches, so force the poster-complete state
 * regardless of any stale class and keep the control hidden. */
@media (prefers-reduced-motion: reduce) {
  .fx-film .fx-film__poster { opacity: 1 !important; }
  .fx-film .fx-film__video { opacity: 0 !important; display: none; }
  .fx-film .fx-film__pp { display: none !important; }
}

/* fx:fx-legal-rings.css */
/* fx-legal-rings — the statute orbit drawn by legalRings() in
 * src/fx/legal-rings.mjs. The honest conversion of joinneo's security hexagon:
 * the Eor.VN seal at the centre with four Vietnamese statutes revolving around it.
 *
 * Motion is OFF by default and only runs once fx-legal-rings.js adds `.is-live`
 * (which it does only when JS is present AND motion is allowed, and it also
 * reveals the pause control). So with no JS or under reduced motion the field is
 * a still, fully readable emblem — and the 24s revolve always has a pause button
 * (WCAG 2.2.2). The orbit layer turns one way; each chip counter-turns about its
 * own centre so every label stays upright and readable. Only accent: seal red
 * (the centre seal + the four node dots). No bounce, no second hue.
 */

.fx-rings {
  position: relative;
  display: block;
  margin: 0;
  width: 100%;
  max-width: 360px;
}

.fx-rings__field {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  color: var(--text, #191a23);
  container-type: inline-size;   /* the centre mark scales with the field (cqi) */
}

/* concentric orbit tracks + the faint Đông Sơn dotted band (ink hairline) */
.fx-rings__tracks {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.16;
  overflow: visible;
}

/* the centre mark — EOR◎VN on the drum (fx-drum-mark.css). Its own drum face is
 * hidden here because the ring field already is the drum; the ripple stays. */
.fx-rings__dmark {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 26px;
  font-size: 7.4cqi;
  z-index: 2;
}
.fx-rings__dmark .dmark__drum,
.fx-rings__dmark .dmark__rip--2 { display: none; }

/* the revolving layer — still until .is-live */
.fx-rings__orbit {
  position: absolute;
  inset: 0;
  z-index: 3;
  transform-origin: 50% 50%;
}

/* each mark is anchored on the orbit via --x/--y (% of the field) and centred on
 * that point; under the orbit's rotation the anchor revolves, so the chip inside
 * counter-rotates to stay upright. */
.fx-rings__mark {
  position: absolute;
  left: calc(50% + var(--x, 0%));
  top: calc(50% + var(--y, 0%));
  transform: translate(-50%, -50%);
}

.fx-rings__chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  width: max-content;
  max-width: 118px;
  padding: 5px 11px 5px 8px;
  background: color-mix(in srgb, var(--card, #fff) 90%, transparent);
  border: 1px solid var(--line, #e6e4dd);
  border-radius: 999px;
  transform-origin: 50% 50%;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}

.fx-rings__node {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--seal, #c4332f);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--seal, #c4332f) 15%, transparent);
}

.fx-rings__text {
  font-family: var(--font-ui, 'Be Vietnam Pro', sans-serif);
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.16;
  letter-spacing: 0.004em;
  color: var(--text, #191a23);
  text-wrap: balance;
}

/* pause / play — hairline round button, revealed by JS only when the orbit runs */
.fx-rings__pp {
  position: absolute;
  right: 4px;
  bottom: 4px;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--line-2, #d8d5cc);
  border-radius: 50%;
  background: color-mix(in srgb, var(--card, #fff) 88%, transparent);
  color: var(--text, #191a23);
  cursor: pointer;
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  transition: color 200ms ease, border-color 200ms ease, transform 200ms ease;
}
.fx-rings__pp[hidden] { display: none; }
.fx-rings__pp:hover { color: var(--seal, #c4332f); border-color: var(--seal, #c4332f); }
.fx-rings__pp:active { transform: scale(0.94); }
.fx-rings__pp svg { width: 15px; height: 15px; display: block; fill: currentColor; }
.fx-rings__pp:focus-visible { outline: 3px solid var(--seal, #c4332f); outline-offset: 2px; }

/* --- motion, only when JS says so (and a pause control exists) --- */
.fx-rings.is-live .fx-rings__orbit { animation: fxRingsSpin 24s linear infinite; }
.fx-rings.is-live .fx-rings__chip  { animation: fxRingsSpin 24s linear infinite reverse; }
.fx-rings.is-live .fx-rings__dmark .dmark__rip  { animation: fxRingsRip 4.5s cubic-bezier(0.2, 0.7, 0.2, 1) 0.9s infinite; }
.fx-rings.is-live .fx-rings__dmark .dmark__word { animation: fxRingsFloat 5s ease-in-out infinite alternate; }
.fx-rings.is-live.is-paused .fx-rings__orbit,
.fx-rings.is-live.is-paused .fx-rings__chip,
.fx-rings.is-live.is-paused .fx-rings__dmark .dmark__rip,
.fx-rings.is-live.is-paused .fx-rings__dmark .dmark__word { animation-play-state: paused; }

@keyframes fxRingsSpin { to { transform: rotate(360deg); } }
@keyframes fxRingsRip {
  0%   { opacity: 0; transform: scale(0.3); }
  12%  { opacity: 0.8; }
  100% { opacity: 0; transform: scale(1.95); }
}
@keyframes fxRingsFloat {
  from { transform: translate(-50%, -50%); }
  to   { transform: translate(-50%, -57%); }
}

/* host layout: joinneo "security split" — section head left, rings right.
 * fx-legal-rings.js adds .fx-rings-host to a .section-head and wraps the existing
 * copy in .fx-rings-host__body. */
.fx-rings-host {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(28px, 5vw, 64px);
  max-width: none !important;
}
.fx-rings-host__body { flex: 1 1 420px; min-width: 0; max-width: 620px; }
.fx-rings-host .fx-rings { flex: 0 0 auto; width: clamp(300px, 30vw, 360px); margin-inline: auto; }

/* --- small screens: single column, static (SPEC D.1) ---
 * Below the desktop threshold the square field has no room for the horizontal
 * 3-/9-o'clock chips to sit beside the seal without clipping its arc, so the
 * orbit reflows to a calm vertical emblem: the seal on top, then the four
 * statutes as full-width pills. Nothing revolves here (fx-legal-rings.js does not
 * set .is-live below 980px), so the state is static and the seal — arc +
 * ĐÚNG LUẬT VIỆT NAM — is fully legible, unobscured by any label. */
@media (max-width: 979px) {
  .fx-rings { max-width: 420px; }
  .fx-rings-host { gap: clamp(26px, 4vw, 44px); }
  .fx-rings-host .fx-rings { width: min(360px, 42vw); }

  .fx-rings__field {
    aspect-ratio: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
  }
  .fx-rings__tracks { display: none; }

  /* the tracks are hidden here, so the mark brings its own drum face back */
  .fx-rings__dmark {
    position: static;
    order: 0;
    transform: none;
    font-size: clamp(38px, 10vw, 50px);
    margin: 2px 0 6px;
  }
  .fx-rings__dmark .dmark__drum { display: block; }

  .fx-rings__orbit {
    position: static;
    inset: auto;
    order: 1;
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 9px;
    transform: none !important;
    animation: none !important;
  }
  .fx-rings__mark {
    position: static;
    left: auto;
    top: auto;
    width: 100%;
    transform: none;
  }
  .fx-rings__chip {
    width: 100%;
    max-width: none;
    gap: 10px;
    padding: 9px 14px;
    transform: none !important;
    animation: none !important;
  }
  .fx-rings__text { font-size: 0.78rem; }
}

/* phones: stack the security split into one column (head above the emblem) */
@media (max-width: 720px) {
  .fx-rings-host { flex-direction: column; align-items: stretch; }
  .fx-rings-host .fx-rings { width: min(360px, 100%); }
}

@media (prefers-reduced-motion: reduce) {
  .fx-rings .fx-rings__orbit,
  .fx-rings .fx-rings__chip { animation: none !important; }
}

/* fx:fx-stage.css */
/* fx-stage — the hero stage (ADDENDUM §2): a joinneo-class app-window that holds
 * the `hero-tour` film, with satellites sliding in over its edges, a cool wash +
 * Đông Sơn ring field behind, and a seal ripple fired at the stamp.
 *
 * Layout is reserved by the film's aspect-ratio box, so the hero paints at its
 * final height before any pixel of video loads (CLS = 0). The scroll-scale and
 * the slide-in are transforms only — they never reflow. With no JS or reduced
 * motion the posters show and nothing is hidden.
 *
 * Palette lock: only ink, cream, --wash, white, hairline and the one red.
 */

.fx-stage {
  position: relative;
  width: 100%;
  max-width: 1180px;
  margin: clamp(44px, 6vw, 76px) auto 0;
  isolation: isolate;
}

/* ---------- behind: cool wash + the ring field ---------- */
.fx-stage__bg {
  position: absolute;
  inset: -5% -3% -9%;
  z-index: 0;
  pointer-events: none;
}
.fx-stage__wash {
  position: absolute;
  inset: 0;
  border-radius: 30px;
  background: radial-gradient(120% 92% at 50% 16%, var(--wash, #eef1f6), transparent 72%);
}
.fx-drum.fx-stage__drum {
  position: absolute;
  left: 50%;
  top: 44%;
  width: min(900px, 118%);
  height: auto;
  transform: translate(-50%, -50%);
}

/* ---------- the seal ripple (behind the frame, over the wash) ---------- */
.fx-stage__rings {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  overflow: visible;
}
.fx-stage__rings span {
  position: absolute;
  left: var(--ox, 68%);
  top: var(--oy, 72%);
  width: 64px;
  height: 64px;
  margin: -32px 0 0 -32px;
  border-radius: 50%;
  border: 1.5px solid var(--seal, #c4332f);
  opacity: 0;
  transform: scale(0.18);
}
.fx-stage__rings.is-rippling span {
  animation: fxRipple 1250ms cubic-bezier(.2, .7, .2, 1) both;
}
.fx-stage__rings.is-rippling span:nth-child(2) {
  animation-delay: 150ms;
  border-color: var(--seal-ink, #9e2b27);
}
.fx-stage__rings.is-rippling span:nth-child(3) {
  animation-delay: 300ms;
  border-width: 1px;
  border-color: var(--drum, rgba(25, 26, 35, 0.3));
}
@keyframes fxRipple {
  0%   { opacity: 0;    transform: scale(0.18); }
  10%  { opacity: 0.58; }
  100% { opacity: 0;    transform: scale(var(--k, 12)); }
}

/* ---------- the scaling composition (frame + satellites) ---------- */
.fx-stage__scaler {
  position: relative;
  z-index: 2;
  transform: scale(var(--fx-scale, 1));
  transform-origin: center top;
  will-change: transform;
}

/* ---------- the window frame ---------- */
.fx-stage__frame {
  position: relative;
  z-index: 1;
  max-width: 1040px;
  margin: 0 auto;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.55);
  box-shadow:
    0 0 0 1px var(--line, #e6e4dd),
    0 2px 4px rgba(20, 22, 26, 0.04),
    0 10px 22px rgba(20, 22, 26, 0.05),
    0 30px 60px rgba(20, 22, 26, 0.09),
    0 64px 120px rgba(20, 22, 26, 0.08);
}

/* the film fills the frame edge-to-edge: the window chrome is inside the video,
 * so the poster/video cover the box with no mat and no second border. */
.fx-stage__frame .fx-film {
  border: none;
  border-radius: 18px;
  background: var(--wash, #eef1f6);
  background-image: none;
}
.fx-stage__frame .fx-film__poster { padding: 0; }
.fx-stage__frame .fx-film__poster > img {
  object-fit: cover;
  height: 100%;
}

/* ---------- satellites ---------- */
/* The figure is sized to its media; the label is an absolute chip straddling
 * the media's top edge (fully opaque, so nothing behind bleeds through). */
.fx-sat {
  position: absolute;
  z-index: 3;
  margin: 0;
  display: block;
}
.fx-sat__label {
  position: absolute;
  z-index: 5;
  top: -14px;
  left: 12px;
  padding: 4px 10px;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text, #191a23);
  background: var(--card, #fff);
  border: 1px solid var(--line, #e6e4dd);
  border-radius: 999px;
  box-shadow: 0 2px 8px rgba(20, 22, 26, 0.09);
  white-space: nowrap;
}
.fx-sat__media { display: block; }
.fx-sat__film {
  border-radius: 16px;
  border: 1px solid var(--line, #e6e4dd);
  box-shadow: 0 2px 6px rgba(20, 22, 26, 0.06), 0 12px 32px rgba(20, 22, 26, 0.14);
  background: var(--card, #fff);
  background-image: none;
}
.fx-sat__film .fx-film__poster { padding: 0; }
.fx-sat__film .fx-film__poster > img,
.fx-sat__film .fx-film__poster > svg {
  object-fit: cover;
  height: 100%;
}
/* the stage has one caption and one pause control, both on the main film */
.fx-sat__film .fx-film__cap,
.fx-sat__film .fx-film__pp { display: none !important; }

/* placement over the frame edges (desktop composition). Onboarding and leave
 * sit high so their labels land in the wash above the frame; the payslip phone
 * hangs off the lower-right and labels its own (opaque) status bar. */
.fx-sat--onboarding { left: -3%;  top: 10%; width: 20.5%; }
.fx-sat--leave      { right: -3%; top: 12%; width: 23%; }
.fx-sat--payslip    { right: 2.5%; bottom: -7%; width: 15%; }

/* the payslip satellite is a phone: rounder, its own bezel, no card border */
.fx-sat--payslip .fx-sat__film {
  border: none;
  border-radius: 30px;
  box-shadow: 0 4px 10px rgba(20, 22, 26, 0.08), 0 18px 44px rgba(20, 22, 26, 0.18);
}

/* ---------- slide-in reveal (only when JS is on and motion is allowed) ---------- */
@media (prefers-reduced-motion: no-preference) {
  .js .fx-stage .fx-sat {
    opacity: 0;
    transition: opacity 0.56s cubic-bezier(.2, .7, .2, 1), transform 0.56s cubic-bezier(.2, .7, .2, 1);
  }
  .js .fx-stage .fx-sat--onboarding { transform: translateX(-30px); }
  .js .fx-stage .fx-sat--leave      { transform: translateX(30px); transition-delay: 0.08s; }
  .js .fx-stage .fx-sat--payslip     { transform: translateX(30px) translateY(14px); transition-delay: 0.16s; }
  .js .fx-stage.is-in .fx-sat {
    opacity: 1;
    transform: none;
  }
}

/* ---------- responsive ---------- */
/* Below 980px: satellites are hidden (display:none keeps the player from ever
 * attaching, so their video is never downloaded) and the frame holds still. */
@media (max-width: 979px) {
  .fx-sat { display: none; }
  .fx-stage__scaler { transform: none; }
  .fx-stage { max-width: 1040px; }
}
@media (max-width: 760px) {
  .fx-stage__frame { border-radius: 14px; }
  .fx-stage__frame .fx-film { border-radius: 14px; }
}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .fx-stage__scaler { transform: none; }
  .fx-stage__rings { display: none; }
  .fx-stage__frame .fx-film__poster { transition: none; }
}

/* the phone covers the frame's bottom-right corner, so the caption sits by the pause button */
.fx-stage__frame .fx-film__cap { right: auto; left: 48px; }
