/* ============================================================================
   Zb International — site stylesheet
   Anchor: "The revision block — say what changed, and who signed it."
   Every colour is a token, defined three times (see dual-theme-ui).
   Never write a raw colour in a component. Never define a colour only inside
   a media query or a [data-theme] block.
   r1 — 2026.08.23
   ========================================================================= */

/* --- fonts ---------------------------------------------------------------- */
@font-face{font-family:'Archivo';src:url('fonts/archivo-latin-400-normal.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Archivo';src:url('fonts/archivo-latin-500-normal.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:'Archivo';src:url('fonts/archivo-latin-600-normal.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:'Archivo';src:url('fonts/archivo-latin-700-normal.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:'Plex Sans';src:url('fonts/ibm-plex-sans-latin-400-normal.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Plex Sans';src:url('fonts/ibm-plex-sans-latin-500-normal.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:'Plex Sans';src:url('fonts/ibm-plex-sans-latin-600-normal.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:'Plex Mono';src:url('fonts/ibm-plex-mono-latin-400-normal.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Plex Mono';src:url('fonts/ibm-plex-mono-latin-500-normal.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
/* Thai — the Thai sibling of the site's own face, so weight and rhythm match.
   Loaded only where the page uses it (the /th/ pages preload it). */
@font-face{font-family:'Plex Sans Thai';src:url('fonts/ibm-plex-sans-thai-thai-400-normal.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Plex Sans Thai';src:url('fonts/ibm-plex-sans-thai-thai-600-normal.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:'Plex Sans Thai';src:url('fonts/ibm-plex-sans-thai-thai-700-normal.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap}

/* --- tokens · LIGHT is the default, no query --------------------------------
   Light = the printed drawing sheet. Cool, paper-grey, ink-black.            */
:root{
  --page:#E9ECEE;
  --sheet:#FAFBFC;
  --sunk:#DFE4E7;
  --ink:#0F151C;
  --ink-2:#46545F;
  --ink-3:#55626D;
  --line:#AFBCC6;
  --hair:#D3DBE0;
  --accent:#B3311F;          /* markup red — the checker's pen             */
  --accent-ink:#FFFFFF;      /* text on top of accent                      */
  --solid-ink:#FFFFFF;       /* text on top of a solid blue or gold fill   */
  --accent-soft:#F6E7E4;
  --blue:#12539F;            /* drafting blue — reference / in-build       */
  --blue-soft:#E6EDF7;
  --green:#0A6B42;           /* approved — live                            */
  --green-soft:#E3F0EA;
  --gold:#7A5412;            /* touchstone                                 */
  --gold-soft:#F3EDDF;
  --shadow:0 1px 2px rgba(15,21,28,.06), 0 8px 24px rgba(15,21,28,.05);
  --grid:rgba(15,21,28,.06);

  --wrap:1680px;
  --gutter:clamp(20px,3.4vw,64px);
  --measure:64ch;
  --radius:2px;
}

/* --- tokens · OS dark, unless the reader explicitly chose light ------------ */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --page:#090E14;
    --sheet:#121A23;
    --sunk:#0D141C;
    --ink:#ECF1F4;
    --ink-2:#A3B3C0;
    --ink-3:#7B8D9C;
    --line:#334353;
    --hair:#22303C;
    --accent:#FF7A69;
    --accent-ink:#2A0B06;
    --solid-ink:#0A121C;
    --accent-soft:#2A1512;
    --blue:#79AEFF;
    --blue-soft:#101E32;
    --green:#4CCB93;
    --green-soft:#0C2419;
    --gold:#DCA84C;
    --gold-soft:#241C0C;
    --shadow:none;
    --grid:rgba(255,255,255,.04);
  }
}

/* --- tokens · explicit choice always wins --------------------------------- */
:root[data-theme="dark"]{
  --page:#090E14;
  --sheet:#121A23;
  --sunk:#0D141C;
  --ink:#ECF1F4;
  --ink-2:#A3B3C0;
  --ink-3:#7B8D9C;
  --line:#334353;
  --hair:#22303C;
  --accent:#FF7A69;
  --accent-ink:#2A0B06;
  --solid-ink:#0A121C;
  --accent-soft:#2A1512;
  --blue:#79AEFF;
  --blue-soft:#101E32;
  --green:#4CCB93;
  --green-soft:#0C2419;
  --gold:#DCA84C;
  --gold-soft:#241C0C;
  --shadow:none;
  --grid:rgba(255,255,255,.04);
}

/* ========================================================================== */
*,*::before,*::after{box-sizing:border-box}
*{margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  font-family:'Plex Sans',system-ui,-apple-system,'Segoe UI',sans-serif;
  background:var(--page);              /* never transparent */
  color:var(--ink);
  font-size:var(--t-1);line-height:1.62;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img,svg{max-width:100%;height:auto}
a{color:inherit}
::selection{background:var(--accent);color:var(--accent-ink)}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:var(--radius)}

.wrap{max-width:var(--wrap);margin:0 auto;padding:0 var(--gutter);width:100%}
.narrow{max-width:var(--measure)}
.mono{font-family:'Plex Mono',ui-monospace,'SFMono-Regular',Menlo,monospace}
.muted{color:var(--ink-2)}
.skip{position:absolute;left:-9999px}
.skip:focus{left:12px;top:12px;z-index:99;background:var(--sheet);color:var(--ink);
  padding:10px 16px;border:1px solid var(--line)}

/* --- type ------------------------------------------------------------------ */
/* ONE SCALE, and every size on the site is a step on it.

   The steps are a root-two progression — 18 · 25 · 36 · 51 · 72 — so each
   size is 1.414 times the one below it and the relationship between any two
   headings is the same relationship. There used to be no scale at all: the
   jump from h2 to h3 was 46 to 22 while h3 to body was 22 to 18.5, which is
   why the page read as a set of unrelated sizes rather than an order.

   The clamp minimums are the same steps taken down for a phone. Nothing on
   this site may use a font-size that is not one of these. */
:root{
  --t-1:  clamp(16px, 0.22vw + 15.4px, 18px);   /* body            */
  --t-2:  clamp(17px, 0.45vw + 15px,   21px);   /* lede            */
  --t-3:  clamp(19px, 1.40vw,          25px);   /* h3, card titles */
  --t-4:  clamp(26px, 2.40vw,          36px);   /* h2              */
  --t-5:  clamp(30px, 3.40vw,          51px);   /* h1.sm           */
  --t-6:  clamp(38px, 5.00vw,          72px);   /* h1, display     */
  --t-0:  15px;                                 /* small print, buttons, lists */
  --t-m:  12.5px;                               /* monospace values */
  --t-u:  11px;                                 /* monospace labels, chips, stamps */
}
h1,h2,h3,h4{font-family:'Archivo',system-ui,sans-serif;letter-spacing:-.022em;line-height:1.12}
h1{font-weight:700;font-size:var(--t-6);line-height:.98;letter-spacing:-.04em;max-width:15ch}
h1.sm{font-size:var(--t-5);line-height:1.02;letter-spacing:-.032em;max-width:19ch}
h2{font-weight:600;font-size:var(--t-4);letter-spacing:-.03em;max-width:22ch}
h3{font-weight:600;font-size:var(--t-3);letter-spacing:-.018em}
h4{font-weight:600;font-size:var(--t-0);letter-spacing:-.01em}
p+p{margin-top:16px}
.lede{font-size:var(--t-2);line-height:1.55;color:var(--ink-2)}
strong{font-weight:600;color:var(--ink)}
/* The ONE relative size on the site, and it is an optical correction, not a
   step: a monospace face set at the same nominal size as the sans around it
   reads noticeably larger, so it is taken down a touch wherever it appears
   inside running text. It stays on whatever step its parent is on. */
code,.tt{font-family:'Plex Mono',monospace;font-size:.9em}

/* --- field label: the voice of the title block ----------------------------- */
.field{font-family:'Plex Mono',monospace;font-size:var(--t-u);font-weight:500;
  letter-spacing:.15em;text-transform:uppercase;color:var(--ink-3)}

/* ============================ header ====================================== */
.topbar{background:var(--sheet);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:40}
.topbar-in{display:flex;align-items:center;gap:26px;height:70px}
.brand{display:flex;align-items:center;text-decoration:none;flex:0 0 auto}
/* --- the logo -------------------------------------------------------------
   Drawn inline in the page as one <svg>, filled with currentColor, so its
   colour is the same token as the rest of the text and there is only ever
   ONE logo element. An <img> pointing at an SVG cannot do this: the SVG
   would answer to the operating system, not to this page's toggle.        */
.logo{display:block;width:auto;color:var(--ink)}
/* The company mark is all ink to the edge of its box, so its box height IS
   its cap height. 34px in a 70px bar: large enough to be read as the mark
   of the sheet, small enough that the bar stays a bar. (Was 26px; SPS asked
   for a bigger logo, r17; bigger again, r18.) */
.brand .logo{height:40px}
footer .logo{height:30px;margin-bottom:14px}
.nav{display:flex;gap:2px;margin-left:auto;align-items:center}
.nav a{text-decoration:none;font-size:var(--t-0);color:var(--ink-2);padding:7px 11px;
  border-radius:var(--radius);white-space:nowrap}
.nav a:hover{color:var(--ink);background:var(--sunk)}
.nav a[aria-current="page"]{color:var(--ink);font-weight:600;
  box-shadow:inset 0 -2px 0 var(--accent)}
.tools{display:flex;align-items:center;gap:10px;margin-left:8px}
.tel{font-family:'Plex Mono',monospace;font-size:var(--t-m);color:var(--ink-2);
  text-decoration:none;white-space:nowrap}
.tel:hover{color:var(--ink)}

.themebtn{display:inline-flex;align-items:center;gap:7px;background:transparent;
  border:1px solid var(--line);color:var(--ink-2);cursor:pointer;
  font-family:'Plex Mono',monospace;font-size:var(--t-u);letter-spacing:.13em;
  text-transform:uppercase;padding:7px 10px;border-radius:var(--radius);line-height:1}
.themebtn:hover{color:var(--ink);border-color:var(--ink-3)}
.themebtn svg{width:13px;height:13px;flex:0 0 auto}
.themebtn .t-dark,.themebtn .l-dark{display:none}
:root[data-theme="dark"] .themebtn .t-light,
:root[data-theme="dark"] .themebtn .l-light{display:none}
:root[data-theme="dark"] .themebtn .t-dark,
:root[data-theme="dark"] .themebtn .l-dark{display:inline}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .themebtn .t-light,
  :root:not([data-theme="light"]) .themebtn .l-light{display:none}
  :root:not([data-theme="light"]) .themebtn .t-dark{display:inline-block}
  :root:not([data-theme="light"]) .themebtn .l-dark{display:inline}
}
:root[data-theme="dark"] .themebtn .t-dark{display:inline-block}

.menubtn{display:none;background:transparent;border:1px solid var(--line);
  color:var(--ink);cursor:pointer;padding:8px 10px;border-radius:var(--radius);
  font-family:'Plex Mono',monospace;font-size:var(--t-u);letter-spacing:.12em}

/* ======================= title block (page header) ======================== */
.titleblock{background:var(--sunk);border-bottom:1px solid var(--line)}
.tb-in{display:grid;grid-template-columns:2.2fr 1fr 1fr 1fr;
  border-left:1px solid var(--hair)}
.tb-cell{padding:11px 16px;border-right:1px solid var(--hair);min-width:0}
.tb-cell dd{font-size:var(--t-0);color:var(--ink);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tb-cell dd.mono{font-family:'Plex Mono',monospace;font-size:var(--t-m)}

/* ============================== hero ====================================== */
.hero{background:var(--sheet);border-bottom:1px solid var(--line);
  padding:clamp(48px,5.5vw,86px) 0 clamp(48px,5vw,74px);position:relative;overflow:hidden}
.hero::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:
    repeating-linear-gradient(90deg,var(--grid) 0 1px,transparent 1px 72px),
    repeating-linear-gradient(0deg,var(--grid) 0 1px,transparent 1px 72px);
  mask-image:linear-gradient(180deg,rgba(0,0,0,.85),transparent 78%);
  -webkit-mask-image:linear-gradient(180deg,rgba(0,0,0,.85),transparent 78%)}
.hero > .wrap{position:static}
.hero .eyebrow{margin-bottom:20px}
.hero p.lede{margin-top:22px;max-width:50ch}

/* hero laid out as a sheet: the words on the left, the drawing on the right */
/* the sheet: the drawing is the ground, the words sit on it */
.hero{display:flex;align-items:center;min-height:min(86vh,840px)}
.hero-copy{position:relative;z-index:2;max-width:min(50%,640px)}
.hero-art{position:absolute;top:0;right:0;bottom:0;left:51%;z-index:1;pointer-events:none;
  display:flex;align-items:center;justify-content:flex-end;
  padding-right:clamp(0px,3vw,60px)}
/* fill the width available beside the words, and cap the height so a tall
   drawing never pushes past the sheet. width:auto + height:86% used to
   letterbox the drawing inside a box wider than it needed. */
.hero-art svg{width:100%;height:auto;max-width:100%;max-height:84%}
/* Below 1040px there is no room beside the words, so the drawing stops being
   a background and becomes a panel of its own, underneath them, at full
   strength. It used to be laid behind the text at 14% opacity, which on a
   phone reads as no drawing at all — the drawings are the point of this
   site, so on a small screen they get their own space rather than a ghost of
   one. */
@media (max-width:1040px){
  .hero{display:block;min-height:auto;overflow:visible}
  .hero-copy{max-width:100%}
  /* --sheet, not --sunk: the drawings fill their solid areas with --sunk, so
     a --sunk panel would swallow every door, louvre and plate on it. */
  .hero-art{position:static;display:block;margin-top:clamp(28px,5vw,44px);
    border:1px solid var(--line);border-radius:var(--radius);
    background:var(--sheet);padding:clamp(18px,4vw,28px) clamp(12px,3vw,22px);
    opacity:1;overflow:hidden}
  .hero-art svg{height:auto;width:100%;max-width:none;display:block}
}

/* --- the drawing ----------------------------------------------------------
   Every stroke carries pathLength="1", so one rule draws them all, in order,
   the way a drawing is actually laid down. Runs once, on load.            */
/* THE RULE, WITHOUT EXCEPTION: nothing is hidden by CSS alone.
   A drawing is fully visible with no stylesheet, no JavaScript and no
   animation support. The plotting effect is added only after zb.js has
   confirmed it can take it away again.                                   */
/* Pace, set twice by SPS on the live site: r17 slowed everything down and
   made it play on scroll; r18 brought it back up to a middle speed — quick
   enough to feel alive, slow enough to watch. */
.js .draw.plot [pathLength]{stroke-dasharray:1;stroke-dashoffset:1;
  animation:draw-in 1.7s cubic-bezier(.33,.9,.42,1) forwards;
  animation-delay:calc(var(--d,0) * 110ms)}
.js .draw.plot text,.js .draw.plot .fadein{opacity:0;
  animation:fade-in .9s ease-out forwards;
  animation-delay:calc(var(--d,0) * 110ms + 500ms)}
@keyframes draw-in{to{stroke-dashoffset:0}}
@keyframes fade-in{to{opacity:1}}

.d-obj{fill:none;stroke:var(--ink);stroke-width:1.6;stroke-linejoin:round;stroke-linecap:round}
.d-thin{fill:none;stroke:var(--ink-2);stroke-width:1;stroke-linecap:round}
.d-con{fill:none;stroke:var(--ink-3);stroke-width:.8;stroke-linecap:round}
.d-mark{fill:none;stroke:var(--accent);stroke-width:1.4;stroke-linecap:round}
.d-fill{fill:var(--sunk);stroke:none}
.d-hatch{fill:url(#hatch);stroke:none}
.d-hatch-sm{fill:url(#hatch-sm);stroke:none}
.d-plate{fill:var(--sunk);stroke:none}
.d-label .what{fill:var(--ink-2)}
.d-label{font-family:'Plex Mono',monospace;font-size:11px;letter-spacing:.12em;
  fill:var(--ink-3)}
.d-label.hot{fill:var(--accent)}
.d-tag{font-family:'Archivo',sans-serif;font-weight:700;font-size:26px;
  letter-spacing:-.02em;fill:var(--accent)}
.d-dim{font-family:'Plex Mono',monospace;font-size:10.5px;fill:var(--ink-2)}

/* --- motion, added only where JS confirms it can be undone ---------------
   Nothing below hides content by default. The .js class is stamped by the
   head script; if the script never runs, everything is already in its
   final state.                                                            */
.js .zone{overflow:hidden}
.js .zone::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:var(--accent);transform:scaleX(0);transform-origin:left}
.zone{position:relative}
.js .zone.in::after{transform:scaleX(1);
  transition:transform 1.2s cubic-bezier(.22,.7,.35,1)}

.js .lift{opacity:0;transform:translateY(14px)}
/* On a phone the rise is taller, so the movement registers at thumb-scroll
   speed. Desktop keeps the quieter 14px. */
@media (max-width:860px){.js .lift{transform:translateY(24px)}}
.js .lift.in{opacity:1;transform:none;
  transition:opacity 1s ease-out,transform 1s cubic-bezier(.22,.7,.35,1)}
.js .lift.in:nth-child(2){transition-delay:.13s}
.js .lift.in:nth-child(3){transition-delay:.26s}
.js .lift.in:nth-child(4){transition-delay:.39s}

/* a hairline traces the card when the cursor is on it */
.cell{position:relative}
.cell::after{content:"";position:absolute;left:0;top:0;height:2px;width:0;
  background:var(--accent);transition:width .4s cubic-bezier(.22,.7,.35,1)}
.cell:hover::after{width:100%}

/* the flow arrows carry one pulse */
.farrow svg path{stroke-dasharray:30;stroke-dashoffset:0}
.js .flow.in .farrow svg path{animation:arrow-run 2.4s ease-out .35s 1}
@keyframes arrow-run{0%{stroke-dashoffset:30}60%,100%{stroke-dashoffset:0}}

.fig .n,.tb-cell dd.mono{font-variant-numeric:tabular-nums}

@media (prefers-reduced-motion: reduce){
  .js .draw.plot [pathLength]{animation:none;stroke-dashoffset:0}
  .js .draw.plot text,.js .draw.plot .fadein{animation:none;opacity:1}
  .js .lift,.js .lift.in{opacity:1;transform:none;transition:none}
  .js .zone::after,.js .zone.in::after{transform:scaleX(1);transition:none}
  .js .flow.in .farrow svg path{animation:none}
}
.btns{margin-top:30px;display:flex;gap:11px;flex-wrap:wrap;align-items:center}

/* buttons */
.btn{display:inline-flex;align-items:center;gap:9px;text-decoration:none;
  font-weight:600;font-size:var(--t-0);padding:13px 22px;border-radius:var(--radius);
  border:1px solid transparent;line-height:1.2;cursor:pointer;white-space:nowrap;
  font-family:'Plex Sans',sans-serif}
.btn svg{flex:0 0 auto;width:22px;height:10px;max-width:none}
.btn-primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.btn-primary:hover{filter:brightness(1.08)}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--line)}
.btn-ghost:hover{border-color:var(--ink-3);background:var(--sunk)}
.btn-blue{background:var(--blue);color:var(--solid-ink);border-color:var(--blue)}
.btn-gold{background:var(--gold);color:var(--solid-ink);border-color:var(--gold)}

/* ============================ sections ==================================== */
section{padding:clamp(52px,6vw,96px) 0}
.sheet{background:var(--sheet);border-top:1px solid var(--line);
  border-bottom:1px solid var(--line)}
.sunkband{background:var(--sunk);border-top:1px solid var(--line);
  border-bottom:1px solid var(--line)}
.zone{display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  padding-bottom:11px;border-bottom:1px solid var(--line);margin-bottom:34px}
.zone h2{margin:0}

/* --- status chip ----------------------------------------------------------- */
.chip{display:inline-flex;align-items:center;gap:7px;font-family:'Plex Mono',monospace;
  font-size:var(--t-u);font-weight:500;letter-spacing:.15em;text-transform:uppercase;
  padding:5px 9px;border:1px solid currentColor;border-radius:var(--radius);line-height:1}
.chip .dot{width:6px;height:6px;border-radius:50%;background:currentColor;flex:0 0 auto}
.chip-live .dot{animation:live-pulse 2.6s ease-in-out infinite}
@keyframes live-pulse{0%,100%{opacity:1;box-shadow:0 0 0 0 currentColor}
  50%{opacity:.55;box-shadow:0 0 0 3px transparent}}
@media (prefers-reduced-motion: reduce){.chip-live .dot{animation:none}}
.chip-live{color:var(--green);background:var(--green-soft)}
.chip-build{color:var(--blue);background:var(--blue-soft)}
.chip-prac{color:var(--accent);background:var(--accent-soft)}
.chip-gold{color:var(--gold);background:var(--gold-soft)}

/* --- card grid ------------------------------------------------------------- */
.grid{display:grid;gap:1px;background:var(--line);border:1px solid var(--line)}
.g3{grid-template-columns:repeat(3,1fr)}
.g2{grid-template-columns:repeat(2,1fr)}
.g4{grid-template-columns:repeat(4,1fr)}
.cell{background:var(--sheet);padding:clamp(24px,2vw,34px) clamp(20px,1.8vw,30px);
  display:flex;flex-direction:column;min-width:0;
  transition:background .25s ease, box-shadow .25s ease}
.cell:hover{background:var(--sunk)}
.golink{transition:color .2s ease}
.cell:hover .golink{letter-spacing:.005em}
.cell p{color:var(--ink-2);font-size:var(--t-0)}
.cell h3{margin:14px 0 9px}
.cell .foot{margin-top:auto;padding-top:20px}
.cell .chip{align-self:flex-start}
.cell .stamp{margin-top:14px;padding-top:12px;border-top:1px dashed var(--hair);
  font-family:'Plex Mono',monospace;font-size:var(--t-u);color:var(--ink-3);line-height:1.7}
.golink{font-weight:600;font-size:var(--t-0);text-decoration:none;
  border-bottom:1px solid currentColor;padding-bottom:1px}

/* --- pull quote (checker's note) ------------------------------------------ */
.note{font-family:'Archivo',sans-serif;font-weight:600;
  font-size:var(--t-4);line-height:1.28;letter-spacing:-.022em;
  max-width:28ch;margin:30px 0;padding-left:20px;border-left:2px solid var(--accent)}

/* --- feature list (no numbers: these are not a sequence) ------------------- */
.features{display:grid;grid-template-columns:repeat(2,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);margin-top:12px}
.feature{background:var(--sheet);padding:24px 22px}
.feature h3{margin-bottom:7px;display:flex;gap:10px;align-items:baseline}
.feature h3::before{content:"";width:14px;height:1px;background:var(--accent);
  flex:0 0 auto;transform:translateY(-6px)}
.feature p{color:var(--ink-2);font-size:var(--t-0)}

/* --- scope list ------------------------------------------------------------ */
.pillar{border-top:1px solid var(--line);padding:26px 0;
  display:grid;grid-template-columns:1fr 1.5fr;gap:34px}
.pillar:last-of-type{border-bottom:1px solid var(--line)}
.pillar .by{margin-top:14px;padding-top:12px;border-top:1px dashed var(--hair);
  font-family:'Plex Mono',monospace;font-size:var(--t-u);line-height:1.7;color:var(--ink-3)}
.pillar .motif{margin-top:16px;max-width:150px}
.scope{list-style:none}
.scope li{padding:8px 0 8px 20px;position:relative;border-bottom:1px dashed var(--hair);
  font-size:var(--t-0)}
.scope li:last-child{border-bottom:0}
.scope li::before{content:"";position:absolute;left:0;top:17px;width:11px;height:1px;
  background:var(--accent)}

/* --- data table ------------------------------------------------------------ */
.tablewrap{overflow-x:auto;margin-top:8px}
table.data{width:100%;border-collapse:collapse;font-size:var(--t-0);min-width:520px}
table.data th{font-family:'Plex Mono',monospace;font-size:var(--t-u);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);text-align:left;font-weight:500;
  padding:0 14px 10px 0;border-bottom:1px solid var(--line)}
table.data td{padding:13px 14px 13px 0;border-bottom:1px solid var(--hair);color:var(--ink-2)}
table.data td.n{font-family:'Plex Mono',monospace;font-size:var(--t-m);color:var(--accent);width:36px}
table.data td.what{color:var(--ink)}
table.data td.by{font-family:'Plex Mono',monospace;font-size:var(--t-u);color:var(--ink-3)}

/* --- big numbers ----------------------------------------------------------- */
.figs{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line);
  border:1px solid var(--line);margin:28px 0}
.fig{background:var(--sheet);padding:22px}
.fig .n{font-family:'Archivo',sans-serif;font-weight:700;font-size:var(--t-4);
  letter-spacing:-.03em;line-height:1;color:var(--gold);font-variant-numeric:tabular-nums}
.fig .l{font-family:'Plex Mono',monospace;font-size:var(--t-u);letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-3);margin-top:8px;line-height:1.55}

/* --- callout --------------------------------------------------------------- */
.callout{padding:22px 24px;background:var(--sunk);border-left:3px solid var(--line)}
.callout.mark{border-left-color:var(--accent)}
.callout.blue{border-left-color:var(--blue);background:var(--blue-soft)}
.callout.gold{border-left-color:var(--gold);background:var(--gold-soft)}
.callout.green{border-left-color:var(--green);background:var(--green-soft)}
.callout p{color:var(--ink-2)}
.callout h3{margin-bottom:8px}

/* --- the marked change: hero feature with revision cloud ------------------- */
.revbox{position:relative;margin-top:16px;padding:clamp(26px,3vw,44px) clamp(22px,2.6vw,42px);
  background:var(--sunk);border:1px solid var(--line)}
.revintro{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(18px,3vw,52px);align-items:start}
.revintro h2{max-width:20ch;margin:0}
.revintro p{margin:0;max-width:52ch}
@media (max-width:880px){.revintro{grid-template-columns:1fr;gap:14px}}
.revcloud{position:absolute;inset:-14px;pointer-events:none;overflow:visible;
  max-width:none;height:auto}
.revcloud path{fill:none;stroke:var(--accent);stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:var(--len,4000);stroke-dashoffset:var(--len,4000)}
.revbox.drawn .revcloud path{transition:stroke-dashoffset 3.4s cubic-bezier(.22,.61,.36,1);
  stroke-dashoffset:0}
.revballoon{position:absolute;top:-14px;left:24px;transform:translateY(-50%);
  background:var(--accent);color:var(--accent-ink);
  font-family:'Plex Mono',monospace;font-size:var(--t-u);font-weight:500;letter-spacing:.16em;
  padding:5px 10px;border-radius:var(--radius);z-index:2;line-height:1}
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  .revcloud path{stroke-dashoffset:0;transition:none}
}

/* --- the flow diagram ------------------------------------------------------ */
.flow{display:grid;grid-template-columns:1fr auto 1fr auto 1fr;align-items:stretch;
  margin-top:30px}
.fnode{background:var(--sheet);border:1px solid var(--line);padding:20px 18px;min-width:0}
.fnode.mid{border-color:var(--blue);border-width:2px;background:var(--blue-soft)}
.fnode .k{font-family:'Plex Mono',monospace;font-size:var(--t-u);letter-spacing:.15em;
  text-transform:uppercase;color:var(--ink-3);margin-bottom:8px}
.fnode.mid .k{color:var(--blue)}
.fnode .t{font-family:'Archivo',sans-serif;font-weight:600;font-size:var(--t-3);
  letter-spacing:-.012em;margin-bottom:6px}
.fnode .s{font-size:var(--t-0);color:var(--ink-2);line-height:1.5}
.farrow{display:flex;align-items:center;justify-content:center;padding:0 12px;
  color:var(--accent)}
.farrow svg{width:26px;height:12px;max-width:none;flex:0 0 auto}
.flownote{margin-top:20px;padding-top:16px;border-top:1px dashed var(--hair);
  font-size:var(--t-0);color:var(--ink-2);max-width:72ch}

/* --- architecture diagram wrapper ----------------------------------------- */
.figure{margin-top:8px;background:var(--sheet);border:1px solid var(--line);padding:26px 22px}
.figure svg{display:block;width:100%;height:auto}
.figcap{margin-top:14px;padding-top:11px;border-top:1px dashed var(--hair);
  font-family:'Plex Mono',monospace;font-size:var(--t-u);color:var(--ink-3);line-height:1.7}

/* --- form ------------------------------------------------------------------ */
.form{display:grid;gap:16px;max-width:560px}
.form .row{display:grid;gap:6px}
.form label{font-family:'Plex Mono',monospace;font-size:var(--t-u);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3)}
/* 16px exactly, and off the scale on purpose: below 16px iOS Safari zooms
   the page when the field takes focus. */
.form input,.form textarea,.form select{
  font-family:'Plex Sans',sans-serif;font-size:16px;color:var(--ink);
  background:var(--sheet);border:1px solid var(--line);border-radius:var(--radius);
  padding:11px 13px;width:100%}
.form input:focus,.form textarea:focus,.form select:focus{border-color:var(--accent);outline:none}
.form textarea{min-height:130px;resize:vertical}
.form .hp{position:absolute;left:-9999px}
.formmsg{padding:13px 16px;border-radius:var(--radius);font-size:var(--t-0);display:none}
.formmsg.ok{display:block;background:var(--green-soft);color:var(--green);
  border:1px solid currentColor}
.formmsg.err{display:block;background:var(--accent-soft);color:var(--accent);
  border:1px solid currentColor}

/* --- contact strip --------------------------------------------------------- */
.contactstrip{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);margin-top:8px}
.contactstrip > div{background:var(--sheet);padding:22px}
.contactstrip a{text-decoration:none;font-size:var(--t-1);border-bottom:1px solid var(--line)}
.contactstrip a:hover{border-color:var(--accent)}

/* ============================== footer ==================================== */
footer{background:var(--sunk);border-top:1px solid var(--line);padding:44px 0 0}
.footgrid{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:34px;padding-bottom:34px}

footer p,footer li{font-size:var(--t-0);color:var(--ink-2)}
footer ul{list-style:none;display:grid;gap:7px}
footer a{text-decoration:none}
footer a:hover{color:var(--ink)}
.footcol h4{margin-bottom:12px}

/* the revision strip — the anchor, made literal */
.revstrip{border-top:1px solid var(--line);overflow-x:auto}
.revstrip table{width:100%;border-collapse:collapse;min-width:600px}
.revstrip th,.revstrip td{font-family:'Plex Mono',monospace;font-size:var(--t-m);
  letter-spacing:.08em;text-align:left;padding:9px 14px 9px 0;color:var(--ink-3);
  white-space:nowrap;font-weight:400}
.revstrip th{text-transform:uppercase;letter-spacing:.15em;
  border-bottom:1px solid var(--hair);padding-bottom:7px}
.revstrip td.rev{color:var(--accent)}
.legal{border-top:1px solid var(--hair);padding:16px 0 22px;
  display:flex;flex-wrap:wrap;gap:8px 22px;justify-content:space-between;
  font-family:'Plex Mono',monospace;font-size:var(--t-m);color:var(--ink-3)}

/* ============================ responsive ================================== */
@media (max-width:1000px){
  .nav{display:none}
  .menubtn{display:inline-block;margin-left:auto}
  .tools{margin-left:10px}
  .tel{display:none}
  .topbar.open .nav{display:grid;position:absolute;top:66px;left:0;right:0;
    background:var(--sheet);border-bottom:1px solid var(--line);padding:8px;gap:0}
  .topbar.open .nav a{padding:12px 14px;border-bottom:1px solid var(--hair)}
}
@media (max-width:860px){
  .tb-in{grid-template-columns:1fr 1fr}
  .tb-cell{border-bottom:1px solid var(--hair)}
  .g3,.g4,.g2,.features,.pillar,.footgrid,.contactstrip{grid-template-columns:1fr}
  .figs{grid-template-columns:1fr 1fr}
  .flow{grid-template-columns:1fr}
  .farrow{padding:10px 0;transform:rotate(90deg)}
  section{padding:48px 0}
  .hero{padding:52px 0 44px}
  .revbox{padding:26px 20px}
  .wrap{padding:0 20px}
}
@media print{
  .topbar,.themebtn,.menubtn,.btns{display:none}
  body{background:#fff;color:#000}
}

/* ============ a dark band, for rhythm down the page ======================
   The band re-declares the surface tokens for its own subtree, so every
   component inside it works untouched, in both themes.                   */
.inkband{
  --page:#0B1017; --sheet:#121A23; --sunk:#0D141C;
  --ink:#ECF1F4; --ink-2:#A3B3C0; --ink-3:#8195A5;
  --line:#334353; --hair:#22303C;
  --accent:#FF7A69; --accent-ink:#2A0B06; --accent-soft:#2A1512;
  --solid-ink:#0A121C;
  --blue:#79AEFF; --blue-soft:#101E32;
  --green:#4CCB93; --green-soft:#0C2419;
  --gold:#DCA84C; --gold-soft:#241C0C;
  --grid:rgba(255,255,255,.045);
  background:var(--page);color:var(--ink);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  position:relative;overflow:hidden}
.inkband::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:repeating-linear-gradient(90deg,var(--grid) 0 1px,transparent 1px 72px),
             repeating-linear-gradient(0deg,var(--grid) 0 1px,transparent 1px 72px);
  mask-image:radial-gradient(120% 90% at 50% 0%,rgba(0,0,0,.9),transparent 75%);
  -webkit-mask-image:radial-gradient(120% 90% at 50% 0%,rgba(0,0,0,.9),transparent 75%)}
.inkband > .wrap{position:relative;z-index:1}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .inkband{
    --page:#16202B; --sheet:#1C2733; --sunk:#131D27; --line:#3B4C5D; --hair:#2A3947}
}
:root[data-theme="dark"] .inkband{
  --page:#16202B; --sheet:#1C2733; --sunk:#131D27; --line:#3B4C5D; --hair:#2A3947}

/* ============ small line motif inside a card ============================ */
.motif{width:100%;max-width:168px;height:auto;color:var(--ink-2);margin:6px 0 2px}
.motif .s{fill:none;stroke:currentColor;stroke-width:1.4;stroke-linejoin:round;
  stroke-linecap:round}
.motif .t{fill:none;stroke:currentColor;stroke-width:.9;opacity:.65}
.motif .h{fill:none;stroke:var(--accent);stroke-width:1.4;stroke-linecap:round}
.motif .f{fill:var(--sunk);stroke:none}
.cell:hover .motif{color:var(--ink)}
.motif{transition:color .3s ease}

/* ============ the value travelling through the flow ===================== */
.flowline{position:relative;height:18px;margin-top:-9px;pointer-events:none}
.js .flowline::after{content:"";position:absolute;top:6px;left:0;width:7px;height:7px;
  border-radius:50%;background:var(--accent);
  box-shadow:0 0 0 4px var(--accent-soft);
  animation:travel 6s cubic-bezier(.5,0,.5,1) infinite}
@keyframes travel{
  0%{left:2%;opacity:0}
  8%{opacity:1}
  92%{opacity:1}
  100%{left:98%;opacity:0}}
@media (max-width:860px){.flowline{display:none}}
@media (prefers-reduced-motion: reduce){.js .flowline::after{animation:none;left:50%}}

/* ============ a diagram that fills its own band ========================= */
.diagram{margin-top:8px}
.diagram svg{display:block;width:100%;height:auto}
.diagram figcaption{margin-top:14px;padding-top:11px;border-top:1px dashed var(--hair);
  font-family:'Plex Mono',monospace;font-size:var(--t-u);color:var(--ink-3);line-height:1.7}

/* ============ product wordmark lockup =================================== */
.wordmark{display:flex;align-items:center;flex-wrap:wrap;gap:clamp(12px,1.4vw,20px);
  padding:clamp(14px,1.5vw,20px) clamp(16px,1.6vw,24px);
  border:1px solid var(--line);background:var(--sheet);
  border-radius:var(--radius);width:fit-content;max-width:100%}
.wordmark .mk{flex:0 0 auto;width:clamp(56px,5vw,78px);height:auto;color:var(--ink-2)}
.wordmark .mk .s{fill:none;stroke:currentColor;stroke-width:1.6;stroke-linejoin:round;
  stroke-linecap:round}
.wordmark .mk .t{fill:none;stroke:currentColor;stroke-width:1;opacity:.6}
.wordmark .mk .h{fill:none;stroke:var(--accent);stroke-width:1.6;stroke-linecap:round}
.wordmark .mk .f{fill:var(--sunk);stroke:none}
.wordmark .nm{display:flex;flex-direction:column;gap:6px;min-width:0}
.wordmark .nm b{font-family:'Archivo',sans-serif;font-weight:700;
  font-size:var(--t-3);letter-spacing:-.028em;line-height:1}
.wordmark .nm .chip{align-self:flex-start}

/* ============ a strip of what the trade actually builds ================= */
.strip{display:flex;flex-wrap:wrap;gap:1px;background:var(--line);
  border:1px solid var(--line);margin-top:8px}
.strip span{background:var(--sheet);padding:11px 16px;flex:1 1 auto;text-align:center;
  font-family:'Plex Mono',monospace;font-size:var(--t-u);letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-2);white-space:nowrap}
.strip span.on{color:var(--accent)}
/* On a phone the flex strip broke into two ragged columns with clipped
   words. A grid gives two equal columns; the text may wrap but never
   splits mid-column. (SPS, r17.) */
@media (max-width:860px){
  .strip{display:grid;grid-template-columns:1fr 1fr}
  .strip span{white-space:normal;text-align:left;padding:10px 12px;line-height:1.5}
}

/* ============ product logos =============================================
   ONE FILE PER LOGO. No light copy, no dark copy, no swap.

   This site showed two logos at once three separate times, and every time
   the cause was the same: two files shipped, CSS asked to hide one, and the
   rule that does the hiding arrived late, stale or not at all. So the rule
   was deleted. Each mark is now a single SVG drawn straight into the page
   whose lettering is currentColor — it inherits the colour of the text
   around it and is correct in any theme, in a dark band, in a print
   stylesheet, and with no stylesheet at all. There is nothing to hide, so
   nothing can fail to be hidden.

   Never recolour the gradients or the gold; never stretch these.         */
/* --- ONE SCALE FOR THE MARKS TOO ------------------------------------
   The number that is set is `--mark`: the CAP HEIGHT of the lettering, not
   the height of the file's box. The three marks carry very different amounts
   of air inside their artboards, so sizing them all to the same box height
   is exactly what made them look mismatched — the same 40px gave YouFlow a
   small word and Touchstone a large one.

   Each mark's box is therefore its cap height divided by its own measured
   cap fraction. The fractions are taken from the artwork and written down
   here so the next person does not have to measure them again:

     youflow.svg       cap  66 / box  130  = .508  ->  box = 1.97 x cap
     touchstone.svg    cap 1500 / box 2430 = .617  ->  box = 1.62 x cap
     youflow-eng.svg   a glyph, not a lockup. Set to 1.35 x cap, the usual
                       standing height for a symbol beside its own name.

   `--mark` itself is set by the context — a card, a lockup — never by the
   individual mark.                                                       */
.pl{display:block;height:auto;max-width:100%;width:auto}
.pl-yf {height:calc(var(--mark) * 1.97)}
.pl-ts {height:calc(var(--mark) * 1.62)}
.pl-yfe{height:calc(var(--mark) * 1.35)}

/* the lockup block on a product page: the mark's cap matches the h3 step */
.wordmark{--mark:clamp(19px,1.5vw,25px)}
.wordmark .pl{flex:0 0 auto}
.wordmark.wm-yfe .engname em{font-style:normal;color:var(--blue)}

/* the product row on the home page */
.products{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);margin-top:8px}
.products a{background:var(--sheet);padding:clamp(22px,2.4vw,34px) clamp(18px,2vw,28px);
  text-decoration:none;display:flex;flex-direction:column;gap:16px;min-width:0;
  transition:background .25s ease}
.products a:hover{background:var(--sunk)}
.products .logo-slot{--mark:17px;display:flex;align-items:center;gap:12px;min-height:46px}
.products .logo-slot .engname{font-family:'Archivo',sans-serif;font-weight:700;
  font-size:var(--t-3);letter-spacing:-.028em;color:var(--ink)}
.products .logo-slot .engname em{font-style:normal;color:var(--blue)}
.products p{font-size:var(--t-0);color:var(--ink-2);margin:0}
.products .go{margin-top:auto;font-weight:600;font-size:var(--t-0);
  border-bottom:1px solid currentColor;align-self:flex-start;padding-bottom:1px}
@media (max-width:860px){.products{grid-template-columns:1fr}}

/* The marks draw themselves in once, using the same .draw / .plot machinery
   as every other drawing here: the class is added by zb.js and stripped again
   four seconds later, so a mark is plainly visible if any part of that fails.
   Each carries class="draw" in its own file; all that is set here is how long
   a stroke takes to be laid down.

     YouFlow Eng   one line, w into e                       1.5s
     YouFlow       "You", then "Flow", then the wave draws
                   through to finish the word               1.1s
     Touchstone    four streaks in turn, then the word      (fades only)   */
.js .draw.plot .yfe-line{animation-duration:2.2s}
.js .draw.plot .c-wave {animation-duration:1.8s}

/* ============ the solutions index ========================================
   Engineering is the parent sheet; each solution is a card that leads to its
   own page or to an enquiry. The first one is running, so it is marked.
   These are links, so everything inside them stays legible with no CSS at
   all — the card is decoration on top of an ordinary list of links.      */
.solgrid{display:grid;grid-template-columns:repeat(2,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);margin-top:8px}
.solution{background:var(--sheet);text-decoration:none;color:inherit;
  padding:clamp(24px,2.6vw,38px) clamp(20px,2.2vw,32px);
  display:flex;flex-direction:column;gap:12px;min-width:0;position:relative;
  transition:background .25s ease}
.solution:hover{background:var(--sunk)}
.solution::after{content:"";position:absolute;left:0;top:0;height:2px;width:0;
  background:var(--accent);transition:width .45s cubic-bezier(.22,.7,.35,1)}
.solution:hover::after{width:100%}
.solution.is-live::before{content:"RUNNING NOW";position:absolute;top:0;right:0;
  font-family:'Plex Mono',monospace;font-size:var(--t-u);letter-spacing:.15em;
  color:var(--accent-ink);background:var(--accent);padding:5px 12px}
.solution .sol-n{font-size:var(--t-m);letter-spacing:.18em;color:var(--ink-3)}
.solution .motif{max-width:132px;margin:2px 0 4px}
.solution:hover .motif{color:var(--accent)}
.solution h3{font-family:'Archivo',sans-serif;font-weight:600;
  font-size:var(--t-3);letter-spacing:-.02em;line-height:1.22;margin:0}
.solution p{font-size:var(--t-0);color:var(--ink-2);margin:0;line-height:1.62}
.solution .stamp{font-family:'Plex Mono',monospace;font-size:var(--t-u);letter-spacing:.06em;
  color:var(--ink-3);padding-top:12px;border-top:1px dashed var(--hair);margin-top:4px}
.solution .sol-go{margin-top:auto;padding-top:14px;font-weight:600;font-size:var(--t-0);
  color:var(--accent);display:inline-flex;align-items:center;gap:9px}
.solution .sol-go svg{width:24px;height:11px;flex:0 0 auto;
  transition:transform .3s cubic-bezier(.22,.7,.35,1)}
.solution:hover .sol-go svg{transform:translateX(5px)}
@media (max-width:860px){.solgrid{grid-template-columns:1fr}}

/* ============ breadcrumb on a child sheet ================================ */
.trail{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:18px;
  font-family:'Plex Mono',monospace;font-size:var(--t-u);letter-spacing:.13em;
  text-transform:uppercase;color:var(--ink-3)}
.trail a{color:var(--accent);text-decoration:none;border-bottom:1px solid transparent}
.trail a:hover{border-bottom-color:currentColor}
.trail span[aria-hidden]{color:var(--ink-3);opacity:.6}

/* a child page, listed under its parent in the footer */
.footcol .sub{padding-left:14px;position:relative}
.footcol .sub::before{content:"";position:absolute;left:0;top:.72em;width:8px;height:1px;
  background:var(--ink-3)}

/* ============ Thai pages (/th/) =========================================
   Same type scale, same sheet — Thai faces. Archivo carries no Thai glyphs,
   so headings fall to Plex Sans Thai 700. Thai stacks its vowels and tone
   marks above and below the line, so leading opens up a step; tracking that
   flatters Latin capitals does nothing for Thai and is zeroed. Latin that
   appears inside Thai text (YouFlow, ASME, figures) still renders in the
   original faces — the stacks fall through per glyph. */
html[lang="th"] body{
  font-family:'Plex Sans','Plex Sans Thai','Noto Sans Thai',system-ui,sans-serif;
  line-height:1.75}
html[lang="th"] h1,html[lang="th"] h2,html[lang="th"] h3,html[lang="th"] h4{
  font-family:'Archivo','Plex Sans Thai','Noto Sans Thai',sans-serif;
  letter-spacing:0;line-height:1.25}
html[lang="th"] h1{line-height:1.2;max-width:18ch}
html[lang="th"] h1.sm{max-width:24ch}
html[lang="th"] h2{max-width:30ch}
html[lang="th"] .lede{line-height:1.8}
html[lang="th"] .field,html[lang="th"] .stamp,html[lang="th"] .chip,
html[lang="th"] .d-label{
  font-family:'Plex Mono','Plex Sans Thai','Noto Sans Thai',monospace;
  letter-spacing:.06em}
/* the language switch in the top bar */
.langbtn{font-family:'Plex Mono','Plex Sans Thai',monospace;font-size:var(--t-m);
  color:var(--ink-2);text-decoration:none;padding:6px 10px;border:1px solid var(--line);
  border-radius:var(--radius);white-space:nowrap}
.langbtn:hover{color:var(--ink);background:var(--sunk)}
