/* ==========================================================================
   Kyoungil System — home page
   Implemented from the Claude Design source "Website Home.dc.html".

   The design keeps layout in inline styles (that is its source of truth), so
   this file carries only what an inline style attribute cannot express:
   the design tokens, the base reset, responsive rules, and the pseudo-class
   rules that the design expressed as style-hover / style-focus attributes.
   ========================================================================== */

:root {
  --paper:#F6F5F1; --paper-90:rgba(246,245,241,0.92); --surface:#FFFFFF;
  --ink:#101418; --ink-2:#24292E; --steel:#5A6470;
  --fog:#D9DDE1; --line:#E3E5E6; --line-2:#EEEDEA;
  --brand:#0C104D; --brand-100:#E7E8F2; --brand-200:#B9BCD6;
  --inverse-bg:#101418; --inverse-fg:#FFFFFF; --inverse-muted:#D9DDE1;
  --inverse-dim:#6E777F; --inverse-line:#24292E; --inverse-line-2:#2F343A;
  --cta-bg:#0C104D; --cta-fg:#FFFFFF; --cta-muted:#B9BCD6; --cta-btn-bg:#FFFFFF;
  --cta-btn-fg:#0C104D; --cta-btn-hover:#B9BCD6; --cta-dim:#8F95C4; --cta-line:#23295E;
  /* Loop tokens, from the Claude Design source. The hero loops reference these
     directly; without them the header bar of every imported loop rendered with
     no background at all. */
  --hmi-bar:#0C104D; --hmi-bar-fg:#FFFFFF; --ok:#15703C; --ok-fg:#FFFFFF;
}

a, button, [role="button"] {
  transition: background-color 120ms ease-out, color 120ms ease-out, box-shadow 120ms ease-out;
}
input, textarea { transition: border-color 120ms ease-out, box-shadow 120ms ease-out; }

a:focus-visible, button:focus-visible, input:focus-visible,
textarea:focus-visible, [role="button"]:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--brand-200);
}

::selection { background: var(--brand-100); color: var(--ink); }

html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--paper);
  overflow-x: hidden; word-break: keep-all; overflow-wrap: break-word;
}
* { box-sizing: border-box; }
a { color: var(--brand); text-decoration: none; }
a:hover { color: var(--ink); }

@media (max-width: 860px) {
  [data-screen-label] > div, header > div { padding-left: 24px !important; padding-right: 24px !important; }
}
/* --- primary nav -----------------------------------------------------------
   Below 700px the three section links used to be hidden with nothing in their
   place, which left 서비스 / 제품 / 회사소개 unreachable on a phone entirely.

   They now live in a <details>, so the mobile menu needs no JavaScript at all:
   <summary> is the hamburger and the browser supplies the toggling, the
   keyboard handling and the expanded/collapsed announcement. That also means
   the menu still works if site.js fails to load — navigation should never
   depend on a script.

   Above 700px the disclosure is undone in CSS (summary hidden, items forced
   back into the flex row) so both layouts come from one set of markup. */
/* --- primary nav -----------------------------------------------------------
   Below 700px the three section links used to be hidden with nothing in their
   place, leaving 서비스 / 제품 / 회사소개 unreachable on a phone entirely.

   There are now two copies: a plain row for desktop, and a <details> for the
   phone. The phone menu therefore needs no JavaScript - <summary> is the
   hamburger and the browser supplies the toggling, the keyboard handling and
   the expanded/collapsed announcement - so navigation still works if site.js
   fails to load.

   The duplication is deliberate. Sharing one copy means showing the contents of
   a *closed* <details> on desktop, and that cannot be done: the browser hides
   closed content with content-visibility, which no display override reverses.
   The links get layout boxes and are simply never painted. Both copies are
   emitted from one place in tools/build-site.sh. */
.nav-links { display: flex; align-items: center; gap: 32px; }
.nav-menu  { display: none; }

@media (max-width: 700px) {
  .nav-links { display: none; }

  /* The menu sits first in the source (reading and tab order); a hamburger
     belongs at the edge of the bar, not between the logo and the language
     switch. order moves the control without moving the markup. */
  .nav-menu { display: block; position: relative; order: 9; margin-left: -6px; }

  .nav-menu__btn {
    display: flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; cursor: pointer; color: var(--ink);
    list-style: none;                 /* Firefox: drop the disclosure triangle */
  }
  .nav-menu__btn::-webkit-details-marker { display: none; }   /* Safari/Chrome */
  .nav-menu[open] .nav-menu__btn { color: var(--brand); }

  .nav-menu__items {
    display: flex; flex-direction: column;
    position: absolute; right: 0; top: calc(100% + 12px); z-index: 60;
    min-width: 170px; padding: 6px;
    background: var(--surface);
    box-shadow: 0 14px 34px -14px rgba(16,20,24,0.38), inset 0 0 0 1px var(--line);
  }
  .nav-menu__items a { padding: 12px 14px; font-size: 15.5px; white-space: nowrap; }
  .nav-menu__items a:hover { background: var(--paper); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}

/* Even with the section links hidden, the header row does not fit a phone:
   logo + language switch + CTA come to more than 375px at the design's 32px
   gaps, and the English CTA ("Request a quote") is half again as wide as the
   Korean one. Tighten the row rather than dropping the language switch, which
   is the one control a visitor on the wrong language needs. */
@media (max-width: 480px) {
  [data-screen-label] > div, header > div { padding-left: 16px !important; padding-right: 16px !important; }
  header nav { gap: 14px !important; }
  header nav a[href$="#contact"],
  header nav a[href="/#contact"] { padding: 0 14px !important; font-size: 13.5px !important; }

  /* The privacy page's definition list reserves up to 140px for the term,
     which leaves too little for "kyoungilsystem@gmail.com". Stack instead. */
  [style*="minmax(110px,140px)"] { grid-template-columns: 1fr !important; }

  /* The product page's download table and its tab row are sized by their cell
     padding; at 20px a side the three columns do not fit. Halve it rather than
     collapsing the table, which would lose the row structure. */
  [style*="grid-template-columns:2fr 1fr 140px"] > div,
  [style*="grid-template-columns:2fr 1fr 140px"] > div > div { padding-left: 10px !important; padding-right: 10px !important; }
  nav[aria-label] a[style*="padding:12px 20px"],
  [style*="border-bottom"] > a[style*="padding:12px 20px"] { padding-left: 10px !important; padding-right: 10px !important; }
}

/* The designs size their section grids with minmax(300px..380px, 1fr), none of
   which fits a phone once the 24px gutters are off — the column keeps its floor
   and the page scrolls sideways. (This predates the hero loops: the photos that
   used to sit in these grids overflowed by exactly the same amount.) Collapse
   them to one column. Matching on minmax() is what keeps the loops out of it —
   they lay their internals out with explicit tracks, never minmax. */
@media (max-width: 620px) {
  div[style*="minmax(300px"],
  div[style*="minmax(320px"],
  div[style*="minmax(340px"],
  div[style*="minmax(380px"] { grid-template-columns: 1fr !important; }
}
}

/* --- pseudo-class rules -----------------------------------------------------
   Each corresponds to a style-hover / style-focus attribute in the design. */

.lnk:hover        { color: var(--brand); }
.lnk-brand:hover  { color: var(--ink); }
.lnk-foot:hover   { color: var(--cta-fg); }

.btn-dark:hover    { background: var(--ink);   color: var(--surface); }
.btn-outline:hover { background: var(--ink);   color: var(--surface); }
.btn-cta:hover     { background: var(--cta-btn-hover); color: var(--cta-btn-fg); }
.btn-submit:hover  { background: var(--ink); }

.field:focus { border-color: var(--brand); background: var(--surface); }

/* --- customer tiles ---------------------------------------------------------
   Each tile carries a thin rule in that company's brand colour, set per tile as
   --accent. Companies whose colour has not been confirmed fall back to our own
   navy, so an unconfirmed tile still looks deliberate.

   A rule, not a filled card: 25 saturated fills would overwhelm a design built
   from paper, navy and a single accent — and a coloured card behind a company
   name starts to imitate a logo lockup, which is the thing the wordmark
   approach exists to avoid. See docs/customer-list.md.

   The rule is decorative (the company name carries the meaning), so it is not
   subject to WCAG text-contrast limits. */
.client { position: relative; }
.client::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--accent, var(--brand));
}
/* The [data-placeholder] outline rule lived here until every unfilled value
   was supplied (2026-08-21). If you reintroduce a placeholder, bring the rule
   back with it so the gap is visible on the page rather than shipping as an
   em dash nobody notices:
     [data-placeholder] { outline:1px dashed var(--brand); outline-offset:2px; } */

/* Hero loops — animated process cards from the design source
   "Hero Loops.dc.html". Each card keeps its layout in inline styles
   like the rest of the site; only the keyframes live here, because a
   style attribute cannot express them. The Lucide icons the design
   loaded from a CDN are inlined as SVG instead — the site ships a CSP
   and has no other third-party script. */
.loop { --loop-motion: running; }

@keyframes kis-blip { 0%,72% { opacity:0.28; } 76%,88% { opacity:1; } 100% { opacity:0.28; } }
@keyframes kis-digits { to { transform:translateY(-90.909%); } }
@keyframes kis-rise { 0% { transform:translateY(0); opacity:0; } 12% { opacity:1; } 88% { opacity:1; } 100% { transform:translateY(-152px); opacity:0; } }
@keyframes kis-draw { 0% { stroke-dashoffset:1200; } 55% { stroke-dashoffset:0; } 100% { stroke-dashoffset:-1200; } }
@keyframes kis-sweepx { 0% { transform:translateX(-12%); } 100% { transform:translateX(112%); } }

/* Keyframes for the hero loops imported from "Hero Loops.dc.html"
   (Claude Design project 77258eef). The rest of the kis-* set was already
   here from the first loop adoption. */
@keyframes kis-climb { 0% { top:100%; opacity:0; } 5% { opacity:1; } 95% { opacity:1; } 100% { top:0%; opacity:0; } }
@keyframes kis-heart { 0%,49% { opacity:1; } 50%,100% { opacity:0; } }
@keyframes kis-io { 0%,46% { opacity:0; } 52%,94% { opacity:1; } 100% { opacity:0; } }
@keyframes kis-layer { 0%,2% { opacity:0; } 7%,15% { opacity:1; } 22%,100% { opacity:0; } }
@keyframes kis-val-a { 0%,3% { opacity:1; } 5%,100% { opacity:0; } }
@keyframes kis-val-b { 0%,3% { opacity:0; } 5%,100% { opacity:1; } }
@keyframes kis-bar { 0%,100% { transform:scaleY(0.24); } 50% { transform:scaleY(1); } }
@keyframes kis-fill { 0%,100% { transform:scaleY(0.34); } 50% { transform:scaleY(0.82); } }
@keyframes kis-cell { 0%,100% { opacity:0; } 3%,9% { opacity:1; } 14% { opacity:0; } }
@keyframes kis-fault { 0%,44% { background:#D7262B; } 50%,100% { background:#25A05B; } }
@keyframes kis-segon { 0%,100% { opacity:0.18; } 6%,12% { opacity:1; } 20% { opacity:0.18; } }
@keyframes kis-latch { 0% { opacity:0; } 3%,90% { opacity:1; } 100% { opacity:0; } }
@keyframes kis-msg { 0%,100% { opacity:0.22; } 5%,11% { opacity:1; } 18% { opacity:0.22; } }
@keyframes kis-io-tint { 0%,46% { opacity:0; } 52%,94% { opacity:0.13; } 100% { opacity:0; } }
@keyframes kis-poll { 0%,2% { opacity:0; } 3%,5% { opacity:1; } 7%,100% { opacity:0; } }
@keyframes kis-tx { 0% { transform:translateX(0); opacity:0; } 10% { opacity:1; } 90% { opacity:1; } 100% { transform:translateX(var(--tx)); opacity:0; } }

/* The loops are decorative; each carries the alt text of the photo it
   replaced as an aria-label. Motion is the whole point of them, so it
   must be the first thing to go when the visitor asks for less. */
@media (prefers-reduced-motion: reduce) {
  .loop *, .loop *::before, .loop *::after { animation: none !important; }
}

/* Screen-reader-only helper for the skip link. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--surface); padding: 12px 18px; font-size: 14px;
  /* it lives outside the wrapper that carries the page font, so it needs its own */
  font-family: 'Noto Sans', 'Noto Sans KR', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
.skip:focus { left: 0; }

/* Below 380px — small Androids and the iPhone SE's narrowest mode — the
   English header still does not fit, and long unbroken values (the email
   address, URLs) push their column open. */
@media (max-width: 380px) {
  header nav { gap: 10px !important; }
  header nav a[href$="#contact"],
  header nav a[href="/#contact"] { padding: 0 10px !important; font-size: 12.5px !important; }
  dd, dd a, address, address a { overflow-wrap: anywhere; }
}

/* At 320px the English CTA ("Request a quote") still will not fit beside the
   logo and the language switch. Drop the header switch — the footer carries
   the same pair of links, so nothing becomes unreachable. */
@media (max-width: 340px) {
  header nav > div { display: none !important; }   /* the KO/EN switch is the only bare div in the nav */

  /* The product page's three tabs are one word longer in English. */
  nav[aria-label] a[style*="padding:12px 20px"],
  [style*="border-bottom"] > a[style*="padding:12px 20px"] {
    padding-left: 6px !important; padding-right: 6px !important; font-size: 13.5px !important;
  }
}

/* Romanised Korean place names carry a real hyphen (Yunggeon-ro, Hwaseong-si,
   Gyeonggi-do), and a hyphen is a break opportunity — in the narrow contact
   and footer columns the browser was splitting names across lines as
   "Hwaseong-" / "si,". Keep each name whole; the address still wraps between
   names, so nothing overflows on mobile. */
.nb { white-space: nowrap; }

/* The header language switch is 12px mono, which made it a 16x15 tap target on
   a phone — under the 24px minimum. The padding gives it a real hit area and
   the matching negative margin keeps the header layout exactly as it was. */
.lang { display: inline-block; padding: 8px; margin: -8px; }

/* The services and products pages are single pages with in-page anchors, and
   the header is sticky, so a jump would otherwise land under it. */
#scada, #data, #mes-erp, #fa-m3v, #ath-1i15c { scroll-margin-top: 88px; }

/* Spec and fact tables are a label column plus a value column. On a phone the
   label column takes more than half the width and the values wrap mid-value
   ("135-04-" / "73942"), so stack them instead. The rule has to beat an inline
   grid-template-columns, hence !important. */
@media (max-width: 560px) {
  dl > div[style*="grid-template-columns:minmax"] {
    grid-template-columns: 1fr !important;
    gap: 6px !important;
  }
}
