
/* ── /support.html page CSS — ported from mockups/support_email/support_page.html
   between ##PAGE-CSS-START## / ##PAGE-CSS-END##. Everything resolves from theme.css
   tokens, so dark / light / EN / ZH all come for free. Two page-local additions
   only: --surface (opaque elevated fill — the floating-menu --glass-bg is
   translucent and needs a backdrop-filter to stay legible, and a content surface
   must never depend on one; same recipe as plans.html.j2) and --brand-a/b/c (the
   Mastermind mark's gradient stops, used ONLY for the headline accent). ────────── */
*{ box-sizing:border-box; }
body{ margin:0; padding-top:18px;            /* 18px top gap — house law, plans.html.j2 */
  background:var(--bg); color:var(--text); font:14.5px/1.55 var(--font-ui);
  -webkit-font-smoothing:antialiased; }
a{ color:var(--link); text-decoration:none; }

:root{
  --surface:color-mix(in srgb, var(--panel) 96%, var(--text));
  --brand-a:#3b82f6; --brand-b:#6366f1; --brand-c:#7c5cff;
}
html[data-theme="light"]{ --surface:color-mix(in srgb, var(--panel) 97%, #000); }

/* auth variants are mutually exclusive; the page boots signed-OUT (the common
   case) and the JS flips html[data-auth] once MDXAuth resolves a session, so an
   anonymous visitor never sees a flash of somebody else's identity chip. */
html[data-auth="out"] .auth-in{ display:none; }
html[data-auth="in"]  .auth-out{ display:none; }

/* mono micro-label — the instrument-panel voice used for every field label,
   card label and slip key on this page. This is the page's type signature. */
.mlab{ display:block; font:600 10.5px/1 var(--font-mono); letter-spacing:.14em;
  text-transform:uppercase; color:var(--muted); }
/* CJK typography: the mono stack has no Hanzi, so a ZH label falls through to
   whatever the system picks — on some machines a SERIF (SF Mono → Songti). Pin a
   sans CJK face ahead of the mono chain, and drop the wide Latin tracking, which
   reads as broken spacing on Hanzi (theme.css does the same for h2, line 172). */
html[data-lang="zh"] .mlab{ font-family:"PingFang SC","Hiragino Sans GB",
  "Microsoft YaHei","Noto Sans CJK SC",var(--font-mono); letter-spacing:.04em; }
html[data-lang="zh"] .hero .eyebrow{ letter-spacing:.08em; }
html[data-lang="zh"] .slip .k{ letter-spacing:.04em;
  font-family:"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans CJK SC",var(--font-mono); }

/* ── shell ────────────────────────────────────────────────────────────────── */
.wrap{ max-width:960px; margin:0 auto; padding:20px 18px 64px; }
@media (min-width:900px){ .wrap{ padding:28px 26px 88px; } }

/* ── hero ─────────────────────────────────────────────────────────────────── */
.hero{ text-align:center; padding:22px 6px 6px; }
.hero .eyebrow{ font:600 11px/1 var(--font-ui); letter-spacing:.18em; text-transform:uppercase;
  color:var(--muted); display:inline-flex; align-items:center; gap:8px; margin-bottom:15px; }
.hero .eyebrow::before,.hero .eyebrow::after{ content:""; width:26px; height:1px;
  background:linear-gradient(90deg,transparent,var(--line)); }
.hero .eyebrow::after{ background:linear-gradient(90deg,var(--line),transparent); }
.hero h1{ font:700 clamp(29px,5.2vw,45px)/1.06 var(--font-ui); letter-spacing:-.025em;
  margin:0 auto; max-width:20ch; }
/* inline-block keeps the second beat whole, so the headline always breaks at the
   sentence ("Write once." / "Get a real answer.") and never mid-phrase. It still
   wraps internally if a viewport is too narrow for the clause. */
.hero h1 .accent{ display:inline-block;
  background:linear-gradient(100deg,var(--brand-a),var(--brand-c));
  -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; }
.hero .sub{ font-size:clamp(14.5px,2.2vw,16.5px); color:var(--muted); max-width:50ch;
  margin:15px auto 0; line-height:1.5; }

/* ── two-column body ──────────────────────────────────────────────────────── */
.cols{ display:grid; grid-template-columns:1fr; gap:18px; margin-top:30px; }
@media (min-width:940px){
  .cols{ grid-template-columns:minmax(0,1fr) 300px; gap:22px; align-items:start; }
  .aside{ grid-column:2; grid-row:1; position:sticky; top:74px; }
  .ticket{ grid-column:1; grid-row:1; }
}

/* ── aside: fast answers (3 items, one line each) ─────────────────────────── */
.fast{ border:1px solid var(--glass-brd); border-radius:14px; background:var(--surface);
  box-shadow:var(--card-shadow); padding:14px 15px 8px; }
.fast .mlab{ margin-bottom:4px; }
.fast a{ display:flex; align-items:center; gap:10px; padding:9px 0; color:var(--text);
  font-size:13.4px; line-height:1.35; border-top:1px solid var(--line);
  transition:color .16s ease; }
.fast a:first-of-type{ border-top:0; }
.fast a:hover{ color:var(--link); }
.fast a .chev{ margin-left:auto; flex:none; color:var(--muted); transition:transform .16s ease; }
.fast a:hover .chev{ transform:translateX(2px); color:var(--link); }
.fast a .chev svg{ display:block; width:13px; height:13px; }

/* what happens next — quiet, unboxed, hairline rail */
.next{ margin:16px 0 0; padding:2px 0 2px 13px; border-left:1px solid var(--line); }
.next .mlab{ margin-bottom:8px; }
.next ol{ margin:0; padding:0; counter-reset:nx; }
/* Ordinals earn their place here: this really is a sequence in time, and the
   order is the information (ticket number first, reply-to-that-email last). */
.next li{ list-style:none; counter-increment:nx; position:relative; padding-left:19px;
  font-size:12.8px; line-height:1.45; color:var(--muted); margin:0 0 8px; }
.next li::before{ content:counter(nx); position:absolute; left:0; top:2px;
  font:600 10px/1.3 var(--font-mono); letter-spacing:.06em;
  color:color-mix(in srgb,var(--muted) 62%,transparent); }
.next li b{ color:var(--text); font-weight:600; }

/* ── the ticket panel ─────────────────────────────────────────────────────── */
.ticket{ position:relative; border:1px solid var(--glass-brd); border-radius:16px;
  background:var(--surface); box-shadow:var(--card-shadow); overflow:hidden; }
/* the routing rail — 3px accent edge; turns --ok on success, --act on error */
.ticket::before{ content:""; position:absolute; left:0; top:0; bottom:0; width:3px;
  background:var(--accent,var(--info)); transition:background .25s ease; }
html[data-form="success"] .ticket{ --accent:var(--ok); }
html[data-form="error"]   .ticket{ --accent:var(--act); }

.tk-head{ display:flex; align-items:center; gap:12px; padding:13px 18px;
  border-bottom:1px solid var(--line); }
.tk-head .mlab{ flex:1; color:var(--text); }
/* The blank ref slip: the header reads `REF ········` while the form is open —
   a promise that a number is coming and worth keeping. On success the header
   hands off to the slip below, where the real number stamps in at full size.
   The ref is never printed twice in one panel. */
.tk-ref{ font:600 12.5px/1 var(--font-mono); letter-spacing:.1em; color:var(--muted);
  display:inline-flex; align-items:baseline; gap:7px; white-space:nowrap; }
.tk-ref .k{ font-size:9.5px; letter-spacing:.14em; opacity:.75; }
.tk-ref .v{ font-size:12.5px; }
html[data-form="success"] .tk-ref{ display:none; }
/* header label follows the panel's state */
.tk-head .st-done{ display:none; }
html[data-form="success"] .tk-head .st-open{ display:none; }
html[data-form="success"] .tk-head .st-done{ display:inline; }
html[data-form="success"] .tk-head .mlab{ color:var(--ok); }
@keyframes stamp{ from{ opacity:0; transform:translateY(-2px) scale(1.06); letter-spacing:.26em; }
  to{ opacity:1; transform:none; letter-spacing:.06em; } }

.tk-body{ padding:18px; }
@media (min-width:600px){ .tk-body{ padding:22px 24px 20px; } }

/* ── fields ───────────────────────────────────────────────────────────────── */
.f{ margin:0 0 16px; }
.f .mlab{ margin-bottom:7px; }
/* Email and Topic share one row from 620px up: both are compact fields, and
   pairing them stops the panel towering over the aside column. The two auth
   variants sit inside ONE cell so hiding either never re-flows the grid. */
.frow{ display:grid; grid-template-columns:1fr; gap:0 16px; }
@media (min-width:620px){ .frow{ grid-template-columns:1fr 1fr; } }
.inp{ width:100%; box-sizing:border-box; padding:10px 13px; border-radius:10px;
  border:1px solid var(--line); background:var(--panel2); color:var(--text);
  font:inherit; font-size:14.5px; outline:none;
  transition:border-color .18s ease, box-shadow .25s ease; }
.inp::placeholder{ color:color-mix(in srgb,var(--muted) 80%,transparent); }
.inp:hover{ border-color:color-mix(in srgb,var(--link) 45%,var(--line)); }
/* focus recipe copied verbatim from theme.css .tbl-filter input:focus */
.inp:focus{ border-color:var(--link);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--link) 20%,transparent); }
textarea.inp{ min-height:118px; resize:vertical; line-height:1.55; }
select.inp{ appearance:none; -webkit-appearance:none; cursor:pointer; padding-right:38px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' fill='none' stroke='%238b93a1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 12px center; background-size:15px; }
.inp:invalid{ box-shadow:none; }            /* never shout before submit */
.f.bad .inp{ border-color:var(--act); }
.f.bad .fmsg{ color:var(--act); }
.fmsg{ display:block; margin-top:6px; font-size:12.2px; line-height:1.4; color:var(--muted); }
/* The pin renders no helper copy under a healthy field (see crops/), and the JS
   only fills .fmsg on a failed submit — so an empty one must take no space at
   all, or every field would carry a stray 6px gap the crops do not have. */
.fmsg:empty{ display:none; }

/* honeypot — abuse hardening (masterplan R2). Off-screen, never focusable.
   Deliberately NOT display:none: a bot that skips hidden inputs would sail past
   a display:none trap, and some assistive tech would too.
   The field's id/name/label are deliberately meaningless — see the markup. */
.hp{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }

/* signed-in identity chip (replaces the email input) */
.who{ display:inline-flex; align-items:center; gap:9px; padding:8px 13px 8px 11px;
  border:1px solid var(--line); border-radius:10px; background:var(--panel2);
  font:500 14px/1 var(--font-ui); color:var(--text); max-width:100%; }
.who .tick{ flex:none; width:16px; height:16px; color:var(--ok); }
.who .addr{ font-family:var(--font-mono); font-size:13px; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.who .pill{ flex:none; font:600 9.5px/1 var(--font-mono); letter-spacing:.1em;
  text-transform:uppercase; color:var(--ok); padding:3px 7px; border-radius:999px;
  background:color-mix(in srgb,var(--ok) 13%,transparent);
  border:1px solid color-mix(in srgb,var(--ok) 32%,transparent); }

/* ── the "what to include" line — the page's behavioural signature ─────────
   The hint swaps with the chosen topic, so one round-trip answers the ticket
   instead of three. Content, not decoration. */
.hint{ display:flex; gap:9px; align-items:flex-start; margin:-4px 0 18px;
  padding:10px 12px; border-radius:10px; font-size:12.9px; line-height:1.45;
  color:var(--muted); background:color-mix(in srgb,var(--info) 7%,transparent);
  border:1px solid color-mix(in srgb,var(--info) 22%,transparent); }
.hint .ic{ flex:none; width:15px; height:15px; margin-top:1px; color:var(--info); }
.hint .ic svg{ display:block; width:15px; height:15px; }
.hint b{ color:var(--text); font-weight:600; }

/* the shortcut line — appears only for topics with a same-second self-serve
   answer (billing, account). One quiet line, never a second card. */
.shortcut{ display:none; margin:-4px 0 16px; font-size:12.6px; color:var(--muted);
  padding-left:19px; position:relative; line-height:1.45; }
.shortcut.on{ display:block; }
.shortcut::before{ content:"→"; position:absolute; left:0; top:0; color:var(--info);
  font-family:var(--font-mono); font-size:12px; }
.shortcut a{ font-weight:600; }

/* ── submit row ───────────────────────────────────────────────────────────── */
.send{ display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  border-top:1px solid var(--line); padding-top:16px; margin-top:2px; }
.send .note{ font-size:12px; color:var(--muted); flex:1; min-width:180px; line-height:1.4; }
/* gbtn — house glass button (theme.css lines 302-328), -cta variant, no breathing
   animation here: a form's primary action should not pulse while you type. */
.btn{ position:relative; overflow:hidden; display:inline-flex; align-items:center;
  justify-content:center; gap:7px; padding:10px 20px; border-radius:11px;
  border:1px solid color-mix(in srgb,var(--info) 45%,var(--gbtn-brd));
  background:linear-gradient(180deg, color-mix(in srgb,var(--info) 16%,var(--gbtn-bg)), var(--gbtn-bg));
  -webkit-backdrop-filter:blur(12px) saturate(140%); backdrop-filter:blur(12px) saturate(140%);
  color:var(--text); font:600 13.5px/1 var(--font-ui); letter-spacing:.01em; cursor:pointer;
  box-shadow:inset 0 1px 0 var(--gbtn-sheen), 0 1px 2px rgba(3,7,18,.18);
  transition:background .2s ease, border-color .2s ease, transform .16s ease, box-shadow .25s ease; }
.btn:hover{ border-color:var(--info); transform:translateY(-1px);
  box-shadow:inset 0 1px 0 var(--gbtn-sheen), 0 8px 24px -10px color-mix(in srgb,var(--info) 55%,transparent); }
.btn:active{ transform:translateY(0) scale(.985); }
.btn:focus-visible{ outline:2px solid var(--link); outline-offset:2px; }
.btn::after{ content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(105deg,transparent 40%,rgba(255,255,255,.13) 50%,transparent 60%);
  transform:translateX(-140%) skewX(-8deg); }
.btn:hover::after{ transform:translateX(140%) skewX(-8deg); transition:transform .55s ease; }
/* Dimming ONLY. pointer-events suppresses mouse hit-testing and nothing else — not the
   keyboard activating an already-focused button, and not implicit submission from Enter
   in a text field. The re-entry guard that actually holds is the `busy` latch plus
   btn.disabled in the submit handler; this rule is the visual half of it. */
.btn[aria-busy="true"]{ pointer-events:none; opacity:.75; }
.btn:disabled{ opacity:.75; cursor:default; transform:none; }
.btn:disabled:hover{ transform:none; border-color:color-mix(in srgb,var(--info) 45%,var(--gbtn-brd));
  box-shadow:inset 0 1px 0 var(--gbtn-sheen), 0 1px 2px rgba(3,7,18,.18); }
.btn-ghost{ background:var(--gbtn-bg); border-color:var(--gbtn-brd); color:var(--muted);
  font-size:12.8px; padding:9px 16px; }
.btn-ghost:hover{ color:var(--text); border-color:var(--gbtn-brd-hover); box-shadow:none; }

/* ── error bar (interface voice: what happened + what to do) ───────────────── */
.err{ display:none; align-items:flex-start; gap:10px; margin:0 0 16px; padding:12px 14px;
  border-radius:11px; font-size:13.2px; line-height:1.45; color:var(--text);
  border:1px solid color-mix(in srgb,var(--act) 45%,var(--line));
  background:color-mix(in srgb,var(--act) 10%,transparent); }
html[data-form="error"] .err{ display:flex; }
.err .ic{ flex:none; width:16px; height:16px; margin-top:1px; color:var(--act); }
.err .ic svg{ display:block; width:16px; height:16px; }
/* keep the fallback address whole — a mid-address break reads as a typo */
.err a, .tk-done .after a{ white-space:nowrap; }
/* Two failures, two honest sentences. The pin specifies the generic one; a 429
   needs its own words because "check your connection and try again" is wrong
   advice when the server is asking you to wait. Same bar, same treatment. */
.err .e-rate{ display:none; }
html[data-err="rate"] .err .e-generic{ display:none; }
html[data-err="rate"] .err .e-rate{ display:inline; }

/* ── success state ────────────────────────────────────────────────────────── */
/* Two success copies, because there are two truths. The estate ships DARK until SMTP
   credentials land (docs/ops/email-support-setup.md), and the sends are deferred to a
   background job, so a response cannot know whether a confirmation went out — it can
   only know whether a relay exists. The API answers that in `mail`; the page must not
   claim an email it cannot send, and must not withhold one it can.
   Default is mail-OFF: an unknown answer never promises. */
.m-on{ display:none; }
html[data-mail="on"] .m-on{ display:inline; }
html[data-mail="on"] .m-off{ display:none; }
html[data-form="success"] .tk-form{ display:none; }
.tk-done{ display:none; }
html[data-form="success"] .tk-done{ display:block; }
.tk-done .seal{ width:38px; height:38px; border-radius:50%; display:grid; place-items:center;
  color:var(--ok); background:color-mix(in srgb,var(--ok) 13%,transparent);
  border:1px solid color-mix(in srgb,var(--ok) 34%,transparent); margin-bottom:14px; }
.tk-done .seal svg{ width:19px; height:19px; }
.tk-done h2{ font:700 21px/1.2 var(--font-ui); letter-spacing:-.01em; margin:0 0 8px; }
.tk-done p{ margin:0 0 18px; color:var(--muted); font-size:14px; line-height:1.55; max-width:46ch; }
.tk-done p b{ color:var(--text); font-weight:600; font-family:var(--font-mono); font-size:13.3px; }
/* the slip — same key/value anatomy as the email receipt's detail slip */
.slip{ border:1px solid var(--line); border-radius:11px; overflow:hidden;
  background:color-mix(in srgb,var(--panel2) 55%,transparent); }
.slip .row{ display:flex; align-items:center; gap:12px; padding:9px 14px;
  border-top:1px solid var(--line); }
.slip .row:first-child{ border-top:0; }
.slip .k{ font:600 10px/1 var(--font-mono); letter-spacing:.14em; text-transform:uppercase;
  color:var(--muted); flex:none; width:78px; }
.slip .v{ font:500 13.2px/1.3 var(--font-mono); color:var(--text); font-variant-numeric:tabular-nums; }
.slip .v.big{ font-size:15px; font-weight:600; letter-spacing:.06em; color:var(--ok);
  animation:stamp .42s cubic-bezier(.2,.8,.3,1) both; }
.tk-done .after{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-top:18px; }
.tk-done .after .note{ font-size:12.2px; color:var(--muted); flex:1; min-width:190px; line-height:1.45; }

/* ── footer — landing footer anatomy (templates/index.html ~1507-1534), but
   every colour resolved from theme tokens instead of the landing's hardcoded
   dark slab, because /support.html is a theme.css page with a real light mode.
   Class names kept identical so the two footers stay one component. ────────── */
.mx-footer{ border-top:1px solid var(--line); margin-top:52px;
  background:color-mix(in srgb,var(--panel) 45%,transparent);
  padding:38px 0 30px; color:var(--muted); font-size:13px; }
.mx-footer .f-in{ max-width:1000px; margin:0 auto; padding:0 22px; }
.mx-footer .f-grid{ display:flex; justify-content:space-between; align-items:flex-start;
  gap:30px; flex-wrap:wrap; }
.mx-footer .f-brand .fb-row{ display:flex; align-items:center; gap:9px; }
.mx-footer .f-brand .fm{ width:26px; height:26px; border-radius:7px;
  background:linear-gradient(135deg,var(--brand-a),var(--brand-c)); display:grid; place-items:center;
  font:800 14px/1 var(--font-ui); color:#fff; }
.mx-footer .f-brand .fn{ font:800 13px/1 var(--font-ui); letter-spacing:.08em; color:var(--text); }
.mx-footer .f-brand .ft{ margin:10px 0 0; color:var(--muted); font-size:12.5px; }
.mx-footer .f-cols{ display:flex; gap:clamp(30px,6vw,84px); }
.mx-footer .f-col p{ margin:0 0 8px; font:700 9px/1 var(--font-mono); letter-spacing:.14em;
  color:color-mix(in srgb,var(--muted) 78%,transparent); text-transform:uppercase; }
.mx-footer .f-col a{ display:block; color:var(--muted); padding:4.5px 0; font-size:13px; }
.mx-footer .f-col a:hover{ color:var(--text); }
.mx-footer .f-bot{ display:flex; justify-content:space-between; align-items:center;
  gap:12px 18px; flex-wrap:wrap; border-top:1px solid var(--line); margin-top:34px;
  padding-top:18px; font-size:12px; color:var(--muted); }

/* ── mobile ───────────────────────────────────────────────────────────────── */
@media (max-width:480px){
  .wrap{ padding:14px 14px 52px; }
  .hero{ padding:12px 2px 2px; text-align:left; }
  /* the eyebrow's leading hairline reads as a stray indent once the hero is
     left-aligned — keep only the trailing rule */
  .hero .eyebrow{ margin-bottom:12px; }
  .hero .eyebrow::before{ display:none; }
  .hero h1{ margin:0; max-width:none; }
  .hero .sub{ margin:12px 0 0; max-width:none; }
  .cols{ margin-top:22px; gap:16px; }
  .fast{ padding:12px 13px 6px; border-radius:12px; }
  .fast a{ font-size:13px; padding:8px 0; }
  .ticket{ border-radius:14px; }
  .tk-head{ padding:11px 14px; gap:8px; }
  .tk-ref .k{ display:none; }             /* keep the ref, drop its label */
  .tk-body{ padding:15px 14px 16px; }
  .send{ gap:10px; }
  .send .btn{ width:100%; order:-1; }
  .send .note{ min-width:0; }
  .mx-footer{ padding:30px 0 24px; margin-top:38px; }
  .mx-footer .f-in{ padding:0 16px; }
  .mx-footer .f-grid{ gap:24px; }
  .mx-footer .f-cols{ gap:40px; }
  .slip .k{ width:64px; }
}
@media (prefers-reduced-motion:reduce){
  .btn, .btn::after, .fast a .chev, .ticket::before{ transition:none; }
  html[data-form="success"] .tk-ref .v, .slip .v.big{ animation:none; }
  .btn:hover{ transform:none; }
}
