/* Shared English / Simplified Chinese usability fixes. */
html { scroll-behavior: auto !important; }
main, .container, .service-card, .lbm-card { min-width: 0; }
.scroll-reveal, .fade-in-up { opacity: 1 !important; transform: none !important; }
:focus-visible { outline: 3px solid #f39b55; outline-offset: 4px; }
header .lang-switch a { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
header .lang-switch { overflow: visible; padding-block: 0; }
#primary-navigation a { min-height: 44px; display: inline-flex; align-items: center; }
.about-rationale-page .lead { max-width: 72ch; }
.about-rationale-page h1, .about-rationale-page h2 { overflow-wrap: anywhere; }
html:lang(zh) .about-rationale-page h1, html:lang(zh) .about-rationale-page h2,
html:lang(zh) #featured-video h2 { font-family: "PingFang SC", "Microsoft YaHei", sans-serif; line-height: 1.4; }
.service-features, .service-card p, .footer-section { overflow-wrap: anywhere; }
#what-we-do .service-art { display: none !important; }
#projectForm input, #projectForm select, #projectForm textarea { font-size: 16px !important; }
#projectForm input, #projectForm select { min-height: 48px; }
.services-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) {
  .services-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  header.sticky #primary-navigation { top: var(--navigation-offset, 84px); max-height: calc(100dvh - var(--navigation-offset, 84px) - 16px); overflow-y: auto; }
  #primary-navigation a { display: flex; min-height: 48px; }
}
@media (max-width: 640px) {
  header .topbar { gap: 8px; }
  header .brand { flex: 1 1 auto; min-width: 0; }
  header .brand img { width: 112px; max-width: 100%; height: auto; }
  header .brand-name { display: none; }
  header .menu-toggle { flex: 0 0 44px; }
  header .header-actions { flex: 0 0 auto; margin-left: 0; }
  header .lang-switch { font-size: 11px; max-width: none; gap: 5px; padding-inline: 7px; }
  .services-grid { grid-template-columns: minmax(0, 1fr); }
  .service-card { padding: 26px 20px; }
  .service-card p, .service-features { font-size: 16px; line-height: 1.65; }
  #featured-video h2 { font-size: clamp(28px, 7vw, 42px); }
  .about-page-intro { padding-top: calc(var(--navigation-offset, 84px) + 28px); }
  .about-rationale-page .section-header { text-align: left; }
  .about-rationale-page .section-header .lead { margin-inline: 0; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

.ux-skip { position: fixed; top: 8px; left: 8px; z-index: 2000; padding: 12px 18px; background: #fff; color: #111; transform: translateY(-200%); }
.ux-skip:focus { transform: none; }

/* ======================================================================
   Corrections added during the September 2026 execution pass.
   Each block notes the defect it addresses so later edits do not
   reintroduce the symptom-level workaround it replaced.
   ====================================================================== */

/* 1. Honeypot containment.
   The spam trap used position:absolute;left:-9999px, which extends the
   document's scrollable box to the left. That single element was the only
   reason overflow-x had to be clipped on <body> (verified by measuring
   documentElement.scrollWidth at 320-1920px). Clipping to a 1px box keeps
   the field submittable and reachable for bots while contributing nothing
   to layout, so the overflow workaround is no longer load-bearing. */
.hp-field {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* 2. Screen-reader-only text utility (used by the theme toggle, which
   previously exposed only a bare emoji as its accessible name). */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* 3. Valid heading font stack.
   The declared stack was `'Garamond', Regular, serif`. `Regular` is not a
   font family, so the stack was invalid after the first entry, and Garamond
   ships on very few devices, meaning most visitors fell through to the
   generic default serif. Garamond is kept first to preserve the intended
   look where it exists; the rest is a real cross-platform serif chain with
   CJK coverage so Chinese headings do not fall back to a Latin-only face. */
/* Corrected at source in each page's :root. No override needed here. */

/* 4. Do not truncate the ehyong.com preview card.
   visual-refresh.css capped .service-site-preview at 430px with
   overflow:hidden. The card's image is 1333x2333, so the cap cut off the
   "Visit ehyong.com" label itself (measured 428px client vs 452px content).
   Constrain the image instead of the link, so the label always renders. */
.service-site-preview {
  max-height: none;
  overflow: visible;
  display: block;
}
.service-site-preview img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 380px;
  object-fit: cover;
  object-position: top center;
  border-radius: 12px;
}
.service-site-preview span {
  display: block;
  margin-top: 10px;
}

/* 5. Form status messaging (see js/enquiry-form.js). Success is only shown
   after the backend accepts the submission; this styles the failure and
   validation states that previously had nowhere to appear. */
.form-status {
  max-width: 900px;
  margin: 14px auto 0;
  padding: 12px 16px;
  border-radius: 12px;
  text-align: center;
  border: 1px solid var(--border);
}
.form-status[data-kind="error"] {
  border-color: #ff8383;
  background: color-mix(in srgb, #ff8383 12%, var(--card));
  color: var(--text);
}
#projectForm button[aria-busy="true"] { opacity: .75; cursor: progress; }
#projectForm [aria-invalid="true"] { border-color: #ff8383 !important; }

/* 6. Language switcher: keep both labels on one comfortable target and
   mark the current language without relying on colour alone. */
.lang-switch a[aria-current="true"] { text-decoration: underline; text-underline-offset: 3px; }

/* 7. Heading balance. Short display headings read better balanced than
   ragged; browsers without support simply keep the previous behaviour. */
h1, h2, h3, .moar-beat h2, .section-header h2 { text-wrap: balance; }
p.lead, .moar-support { text-wrap: pretty; }

/* 8. Chinese line-breaking.
   The previous system combined three mechanisms: manual <br class="zh-break">
   elements, `word-break: keep-all` on every section heading below 768px, and
   .zh-*-line spans forced to display:block + white-space:nowrap.

   `keep-all` suppresses line breaking inside CJK text entirely. Any Chinese
   heading that had not been manually split therefore could not wrap at all:
   #clientele's heading measured 330px of content in a 288px column at 320px
   wide, and the ZH story heading pushed the document to 374px. Both were
   invisible only because overflow-x was clipped on <body>.

   The replacement lets Chinese break at character boundaries as it normally
   does, while `line-break: strict` keeps opening punctuation off the end of a
   line and closing punctuation off the start, and `overflow-wrap: break-word`
   breaks a long Latin run such as "Little Bit Moar" only when it would
   otherwise overflow. The authored .zh-*-line phrase boundaries are kept as
   preferred break points (they are separated by a real space) rather than as
   forced ones, so line counts adapt to the viewport instead of being fixed. */
html[lang^="zh"] .section-header h2,
html[lang^="zh"] .cta-content h2,
html[lang^="zh"] .zh-services-title,
html[lang^="zh"] .zh-story-title,
html[lang^="zh"] .zh-card-split {
  word-break: normal;
  line-break: strict;
  overflow-wrap: break-word;
}
html[lang^="zh"] .zh-services-line,
html[lang^="zh"] .zh-story-line,
html[lang^="zh"] .zh-card-line {
  display: inline;
  white-space: normal;
}
html[lang^="zh"] .zh-services-line:not(:last-child)::after,
html[lang^="zh"] .zh-story-line:not(:last-child)::after,
html[lang^="zh"] .zh-card-line:not(:last-child)::after { content: " "; }

/* 9. Footer touch targets. Footer links measured 18px tall, below the 24px
   WCAG 2.2 AA minimum for target size. */
.footer-section ul li { margin-bottom: 2px; }
.footer-section ul a {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding-block: 3px;
}

/* 10. "Back to home" link on the about pages measured 19px tall, under the
   24px minimum in WCAG 2.2 AA Target Size (Minimum). */
.about-page-intro > a {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 4px 2px;
}
