/* ==========================================================================
   vexlo — design tokens + base
   Art direction: Otl Aicher signage (Munich '72) + Braun instrument faces.
   Warm paper ground, thin rules instead of card chrome, one signal-amber
   accent reserved exclusively for actuating controls.
   ========================================================================== */

@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo-var-latin.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('/assets/fonts/plexmono-400-latin.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('/assets/fonts/plexmono-500-latin.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

:root {
  /* --- Color: warm paper ground, warm ink. Never pure #000 on white. --- */
  --ground: #faf8f4;
  --surface: #ffffff;
  --surface-sunk: #f2eee7;

  --ink: #1a1815;
  --ink-2: #46403a; /* secondary text — 8.9:1 on ground */
  --ink-3: #6b6259; /* meta text    — 5.2:1 on ground */
  --ink-4: #8a8078; /* 非文字 UI（箭头/占位符）3.6:1，达 WCAG 非文字 3:1 */

  --rule: #e2dcd2;
  --rule-strong: #cfc7ba;

  /* The accent is the rarest color on screen: primary actions only. */
  --accent: #b8410e; /* 5.6:1 on ground */
  --accent-press: #9a350b;
  --accent-wash: #fdf1ea;

  --ok: #166534;
  --ok-wash: #edf7f0;
  --warn: #92400e;
  --err: #b42318;
  --err-wash: #fdf2f1;

  /* --- Type: 1.25 modular scale on a 17px mobile body base --- */
  --font-ui: 'Archivo', 'Helvetica Neue', Helvetica, sans-serif;
  --font-num: 'Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --t-xs: 0.75rem;   /* 12 */
  --t-sm: 0.875rem;  /* 14 */
  --t-base: 1.0625rem; /* 17 */
  --t-md: 1.3125rem; /* 21 */
  --t-lg: 1.6875rem; /* 27 */
  --t-xl: 2.0625rem; /* 33 */
  --t-2xl: 2.625rem; /* 42 */

  /* --- Space: 8px grid, 4px fine --- */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;
  --s-8: 64px;
  --s-9: 96px;

  /* --- Radius varies by role on purpose --- */
  --r-input: 6px;
  --r-btn: 8px;
  --r-card: 14px;
  --r-pill: 999px;

  --shell: 960px;
  --prose: 68ch;

  --ease: cubic-bezier(0.2, 0.6, 0.2, 1);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--t-base);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 {
  line-height: 1.15;
  margin: 0 0 var(--s-3);
  letter-spacing: -0.015em;
  font-weight: 700;
}
h1 { font-size: var(--t-xl); }
h2 { font-size: var(--t-lg); margin-top: var(--s-7); }
h3 { font-size: var(--t-md); margin-top: var(--s-5); font-weight: 600; }

p { margin: 0 0 var(--s-4); }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-press); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-input);
}

code, kbd { font-family: var(--font-num); font-size: 0.9em; }

.mono { font-family: var(--font-num); font-variant-numeric: tabular-nums; }

/* ---------- Layout shell ---------- */

.wrap {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--s-4);
}
@media (min-width: 768px) { .wrap { padding-inline: var(--s-5); } }

.prose { max-width: var(--prose); }
.prose li { margin-bottom: var(--s-2); }

/* ---------- Header: 4 top-level items, no hamburger ---------- */

.site-head {
  border-bottom: 1px solid var(--rule);
  background: var(--ground);
  position: sticky;
  top: 0;
  z-index: 20;
}
.site-head__in {
  display: flex;
  align-items: center;
  gap: var(--s-5);
  height: 56px;
}
.brand {
  font-weight: 700;
  font-size: var(--t-md);
  letter-spacing: -0.03em;
  color: var(--ink);
  text-decoration: none;
  flex: none;
}
.brand span { color: var(--accent); }

.nav {
  display: flex;
  gap: var(--s-4);
  overflow-x: auto;
  scrollbar-width: none;
  margin-left: auto;
  min-width: 0;
  /* 窄屏放不下 4 项时右侧渐隐，明确告诉用户还能横向滑，而不是看起来被截断了 */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
  padding-right: var(--s-5);
}
@media (min-width: 620px) {
  .nav {
    -webkit-mask-image: none;
    mask-image: none;
    padding-right: 0;
  }
}
.nav::-webkit-scrollbar { display: none; }
.nav a {
  color: var(--ink-2);
  text-decoration: none;
  font-size: var(--t-sm);
  font-weight: 500;
  white-space: nowrap;
  /* 44px 最小触达：56px 的头部正好放得下 */
  min-height: 44px;
  display: flex;
  align-items: center;
  border-bottom: 2px solid transparent;
}
.nav a:hover { color: var(--ink); }
.nav a[aria-current='page'] { color: var(--ink); border-bottom-color: var(--accent); }

/* ---------- Breadcrumb ---------- */

.crumb {
  font-size: var(--t-sm);
  color: var(--ink-3);
  margin: var(--s-4) 0 var(--s-3);
}
.crumb a { color: var(--ink-3); text-decoration: none; }
.crumb a:hover { color: var(--ink); text-decoration: underline; }

/* ---------- Tool head ---------- */

.tool-head { margin-bottom: var(--s-5); }
.tool-head h1 { margin-bottom: var(--s-2); }
.tool-head .lede {
  color: var(--ink-2);
  font-size: var(--t-md);
  max-width: 46ch;
  line-height: 1.4;
  margin: 0;
}

/* 窄屏收一档标题：工具本身必须尽量靠近首屏顶部，标题不该把它推下去。 */
@media (max-width: 599px) {
  .tool-head h1 { font-size: var(--t-lg); }
  .tool-head .lede { font-size: var(--t-base); }
}

/* 首页 / 404 的大标题：这两页没有首屏工具要让位，可以放开一档。 */
.hero { margin-top: var(--s-7); }
.hero h1 { font-size: var(--t-xl); max-width: 18ch; }
@media (min-width: 600px) { .hero h1 { font-size: var(--t-2xl); max-width: 16ch; } }

.disclaimer {
  color: var(--ink-3);
  font-size: var(--t-sm);
  border-top: 1px solid var(--rule);
  padding-top: var(--s-4);
}

.row__err { color: var(--err); }
.note-sub { color: var(--ink-3); font-weight: 400; }

/* Privacy line — the differentiation point, stated concretely. */
.privacy-line {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-sm);
  color: var(--ok);
  background: var(--ok-wash);
  border: 1px solid #cfe6d8;
  border-radius: var(--r-pill);
  padding: var(--s-2) var(--s-4);
  margin: var(--s-4) 0 0;
  width: fit-content;
  max-width: 100%;
}
.privacy-line svg { flex: none; }

/* ---------- Drop zone: the biggest thing on the page ---------- */

.drop {
  border: 2px dashed var(--rule-strong);
  border-radius: var(--r-card);
  background: var(--surface);
  padding: var(--s-7) var(--s-4);
  text-align: center;
  transition: border-color 200ms var(--ease), background 200ms var(--ease);
  cursor: pointer;
  display: block;
  width: 100%;
  font: inherit;
  color: inherit;
}
.drop:hover { border-color: var(--accent); }
.drop.is-over {
  border-color: var(--accent);
  background: var(--accent-wash);
}
.drop__verb {
  /* 与正文同号、靠字重和 188px 高的虚线框拿存在感，不靠加大字号 ——
     首屏这样只剩 3 档字号（标题 / 正文 / 元信息），层级更干净。 */
  font-size: var(--t-base);
  font-weight: 600;
  display: block;
  margin-bottom: var(--s-1);
}
.drop__verb em { color: var(--accent); font-style: normal; text-decoration: underline; }
.drop__hint { font-size: var(--t-sm); color: var(--ink-3); display: block; }
.drop input[type='file'] { display: none; }

/* ---------- Options row ---------- */

.opts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  margin-top: var(--s-4);
  padding: var(--s-4);
  background: var(--surface-sunk);
  border-radius: var(--r-card);
}
.opt { flex: 1 1 200px; min-width: 0; }
.opt label {
  display: block;
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s-2);
}
.opt__val {
  font-family: var(--font-num);
  font-size: var(--t-sm);
  color: var(--ink);
  float: right;
  text-transform: none;
  letter-spacing: 0;
}

input[type='range'] {
  width: 100%;
  accent-color: var(--accent);
  /* 44px 触达高度：滑轨本身只有几像素，靠容器高度把可点区域撑够 */
  height: 44px;
}
input[type='number'],
input[type='text'],
select {
  width: 100%;
  font-family: var(--font-num);
  font-size: var(--t-base);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--rule-strong);
  border-radius: var(--r-input);
  background: var(--surface);
  color: var(--ink);
  min-height: 44px;
}
select { font-family: var(--font-ui); }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 44px;
  padding: var(--s-2) var(--s-5);
  border-radius: var(--r-btn);
  border: 1px solid transparent;
  font: inherit;
  font-weight: 600;
  font-size: var(--t-sm);
  cursor: pointer;
  text-decoration: none;
  transition: background 200ms var(--ease), transform 100ms var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-press); color: #fff; }
.btn--ghost {
  background: transparent;
  color: var(--ink-2);
  border-color: var(--rule-strong);
}
.btn--ghost:hover { background: var(--surface-sunk); color: var(--ink); }
.btn[disabled] { opacity: 0.45; cursor: not-allowed; }
.btn--block { width: 100%; }

/* ---------- Results ---------- */

.results { margin-top: var(--s-5); }
.results__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-bottom: var(--s-3);
}
.results__count {
  font-size: var(--t-sm);
  color: var(--ink-3);
  font-family: var(--font-num);
}

.row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--rule);
}
/* 入场动画只在首批结果出现时播一次。拖画质滑块会重跑转换，
   每次都重播一遍入场动画会让整个列表不停闪 —— 频繁操作不该带动画。 */
.results--fresh .row { animation: row-in 220ms var(--ease) both; }
@keyframes row-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
.row__thumb {
  width: 48px;
  height: 48px;
  border-radius: var(--r-input);
  object-fit: cover;
  background: var(--surface-sunk);
  flex: none;
}
.row__body { min-width: 0; flex: 1; }
.row__name {
  font-size: var(--t-sm);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.row__meta {
  font-family: var(--font-num);
  font-size: var(--t-xs);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.row__meta .saved { color: var(--ok); }
.row__meta .grew { color: var(--warn); }
.row__act { flex: none; }

.progress {
  height: 4px;
  background: var(--surface-sunk);
  border-radius: var(--r-pill);
  overflow: hidden;
  margin-top: var(--s-4);
}
.progress__bar {
  height: 100%;
  background: var(--accent);
  width: 0;
  transition: width 200ms var(--ease);
}

/* States: empty / error. Both say what happened and what to do next. */
.note {
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-input);
  font-size: var(--t-sm);
  margin-top: var(--s-4);
}
.note svg { flex: none; margin-top: 2px; }
.note--empty { color: var(--ink-3); background: var(--surface-sunk); }
.note--err { color: var(--err); background: var(--err-wash); border: 1px solid #f4d5d2; }

/* ---------- Calculator ---------- */

.calc { display: grid; gap: var(--s-5); }
@media (min-width: 800px) { .calc { grid-template-columns: 1fr 1fr; align-items: start; } }

.field { margin-bottom: var(--s-4); }
.field label {
  display: block;
  font-size: var(--t-sm);
  font-weight: 600;
  margin-bottom: var(--s-2);
}
.field__help { font-size: var(--t-xs); color: var(--ink-3); margin-top: var(--s-1); }
.field__wrap { position: relative; display: flex; align-items: center; }
.field__prefix,
.field__suffix {
  position: absolute;
  font-family: var(--font-num);
  font-size: var(--t-sm);
  color: var(--ink-3);
  pointer-events: none;
}
.field__prefix { left: var(--s-3); }
.field__suffix { right: var(--s-3); }
.field__wrap--prefixed input { padding-left: 28px; }
.field__wrap--suffixed input { padding-right: 40px; }

/* Answer-first: one big number, breakdown below. */
.answer {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-card);
  padding: var(--s-5);
  position: sticky;
  top: 72px;
}
.answer__label {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s-1);
}
.answer__big {
  font-family: var(--font-num);
  font-size: var(--t-2xl);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.answer__sub { font-size: var(--t-sm); color: var(--ink-3); margin-top: var(--s-1); }

.breakdown { margin-top: var(--s-5); border-top: 1px solid var(--rule); }
.breakdown dl { margin: 0; }
.breakdown div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--rule);
}
.breakdown dt { font-size: var(--t-sm); color: var(--ink-2); margin: 0; }
.breakdown dd {
  margin: 0;
  font-family: var(--font-num);
  font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.bar-split { display: flex; height: 8px; border-radius: var(--r-pill); overflow: hidden; margin-top: var(--s-4); }
.bar-split i { display: block; height: 100%; }
.legend { display: flex; gap: var(--s-4); flex-wrap: wrap; margin-top: var(--s-2); font-size: var(--t-xs); color: var(--ink-3); }
.legend span { display: inline-flex; align-items: center; gap: var(--s-1); }
.legend i { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }

/* ---------- Tool index ---------- */

.tool-list { list-style: none; padding: 0; margin: 0; border-top: 1px solid var(--rule); }
.tool-list li { border-bottom: 1px solid var(--rule); }
.tool-list a {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  padding: var(--s-4) 0;
  text-decoration: none;
  color: var(--ink);
}
.tool-list a:hover .tool-list__name { color: var(--accent); }
.tool-list__name { font-weight: 600; font-size: var(--t-base); flex: none; min-width: 0; }
.tool-list__desc { font-size: var(--t-sm); color: var(--ink-3); min-width: 0; }
.tool-list__arrow { margin-left: auto; color: var(--ink-4); flex: none; }

/* 窄屏把说明文字换到第二行：名称 + 箭头一行，说明独占一行。
   同一行硬塞三样东西在 320px 上会把页面撑出横向滚动条。 */
@media (max-width: 560px) {
  .tool-list a { flex-wrap: wrap; row-gap: var(--s-1); }
  .tool-list__name { flex: 1 1 auto; }
  .tool-list__arrow { order: 2; }
  .tool-list__desc { order: 3; flex-basis: 100%; }
}

.section-label--first { margin-top: var(--s-7); }
.section-label {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: var(--s-7) 0 var(--s-3);
}

/* ---------- FAQ ---------- */

.faq { border-top: 1px solid var(--rule); }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  padding: var(--s-4) 0;
  font-weight: 600;
  font-size: var(--t-base);
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: '+'; color: var(--accent); font-weight: 400; font-size: var(--t-md); line-height: 1; }
.faq details[open] summary::after { content: '\2212'; }
.faq details p { color: var(--ink-2); font-size: var(--t-sm); padding-bottom: var(--s-3); margin: 0; max-width: var(--prose); }

/* ---------- Ad slots ----------
   Reserved boxes with min-height so ad insertion never shifts layout (CLS).
   Never placed above the tool: the tool must win the billboard test. */

.ad {
  margin: var(--s-6) 0;
  /* 112 = 8×14，够放 728×90 横幅 + "Advertisement" 标签，且仍在 8px 栅格上 */
  min-height: 112px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  clear: both;
  /* 联盟发的是固定尺寸 iframe（最宽 728px），375px 手机上会把页面撑出横向滚动条。
     这里兜底裁掉溢出部分 —— 宁可广告被切边，也不能让整站布局坏掉。 */
  max-width: 100%;
  overflow: hidden;
}
.ad iframe { max-width: 100%; }
.ad--inline { min-height: 280px; }
.ad__label {
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* 广告披露是必须能读的合规文案，不能用最浅的那一档灰 */
  color: var(--ink-3);
  text-align: center;
  display: block;
  margin-bottom: var(--s-1);
}
.ad__ph {
  border: 1px dashed var(--rule-strong);
  border-radius: var(--r-input);
  color: var(--ink-4);
  font-size: var(--t-xs);
  padding: var(--s-5);
  width: 100%;
  text-align: center;
  font-family: var(--font-num);
}

/* ---------- Footer ---------- */

.site-foot {
  border-top: 1px solid var(--rule);
  margin-top: var(--s-9);
  padding: var(--s-6) 0 var(--s-7);
  font-size: var(--t-sm);
  color: var(--ink-3);
}
.site-foot__cols { display: flex; flex-wrap: wrap; gap: var(--s-6); margin-bottom: var(--s-5); }
.site-foot h4 {
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-2);
  margin: 0 0 var(--s-2);
}
.site-foot ul { list-style: none; padding: 0; margin: 0; }
.site-foot li { margin-bottom: 0; }
.site-foot a {
  color: var(--ink-3);
  text-decoration: none;
  display: block;
  padding: var(--s-3) 0;  /* 22px 行高 + 24px 内边距 = 46px 触达 */
}
.site-foot a:hover { color: var(--ink); text-decoration: underline; }
.site-foot__legal { border-top: 1px solid var(--rule); padding-top: var(--s-4); font-size: var(--t-xs); }

.skip {
  position: absolute;
  left: -9999px;
  background: var(--accent);
  color: #fff;
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r-btn);
  z-index: 50;
}
.skip:focus { left: var(--s-4); top: var(--s-2); }

.hidden { display: none !important; }

/* WCAG 2.3.3 — reduce, don't remove. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- App call-to-action ----------
   The block that tells a browser player the game also exists as an app. Kept to
   the same thin-rule vocabulary as everything else: no card shadow, no badge
   image, no colour that isn't already in the palette. The accent is allowed here
   because the link is an actuating control, which is exactly what it is reserved
   for. */

.appcta {
  display: flex;
  gap: var(--s-4);
  align-items: flex-start;
  margin: var(--s-7) 0;
  padding: var(--s-5);
  border: 1px solid var(--rule);
  border-radius: var(--r-btn);
  background: var(--surface);
}

.appcta__icon {
  flex: none;
  width: 64px;
  height: 64px;
  border-radius: 14px;
  border: 1px solid var(--rule);
}

.appcta__body { min-width: 0; }

.appcta__title {
  margin: 0 0 var(--s-2);
  font-weight: 600;
  color: var(--ink);
}

.appcta__blurb {
  margin: 0 0 var(--s-4);
  font-size: var(--t-sm);
  color: var(--ink-2);
}

.appcta__btn {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: var(--s-2) var(--s-5);
  border-radius: var(--r-btn);
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  font-size: var(--t-sm);
  text-decoration: none;
}

.appcta__btn:hover { background: var(--accent-press); color: #fff; }
