/* ════════════════════════════════════════════════════════════════
   page-chain.css — TARANG STRUCTURAL PASS for chain.html + story.html
   (v9.3, 2026-08-08)

   Linked LAST, after tarang.css, on those two pages only. It never touches
   the shared files: chain.css and tarang.css belong to the lead.

   These two pages were already REPAINTED (right tokens, right colours) but
   were still LAID OUT as the old cinematic site: a photo hero with the copy
   floating on it, prose in two columns, boxes for capabilities, and almost
   no product on screen. What is added here is the structure index.html
   already has:

     · a printed MASTHEAD  - 3px page rule, mono rubric, live meta, a huge
       headline that rises out of its own clipping window, and a plate.
     · ruled ENTRIES       - copy on one side, a real app screenshot in a
       printed plate on the other, opened by a 2px ink rule.
     · figure STRIPS       - four plates of equal weight, each with a mono
       caption strap carrying a stamp.
     · the ODOMETER        - .odo lives in v9.css, which these two pages do
       not load, so [data-count] would have rendered a stack of ten digits.
       It is repeated here rather than linked, because loading v9.css would
       drag the whole homepage layout in with it.

   Rules, not boxes. Paper end to end. html.dark flips all of it.
   ════════════════════════════════════════════════════════════════ */

/* ── 1 · the odometer ────────────────────────────────────────────
   chain.js rolls any [data-count] into place by building one column per
   digit with a 0-9 strip inside it. Without these four rules the strip is
   not clipped and the figure reads "0123456789". */
.odo{ display:inline-flex; font-style:normal; }
.odo__c{ display:block; overflow:hidden; height:1em; }
.odo__s{ display:block; will-change:transform; }
.odo__s span{ display:block; height:1em; line-height:1; }
@media (prefers-reduced-motion:reduce){ .odo__s{ transition:none !important; } }

/* ── 2 · the masthead ────────────────────────────────────────────
   Its own namespace so nothing here can leak into the 19 pages that still
   render the old .chero. The rubric rule is 3px: a page opener, not a
   section opener. */
.mh{
  position:relative;
  background:var(--paper);
  padding:clamp(108px,13.5vh,150px) 0 clamp(46px,6vh,74px);
  overflow:hidden;
}
.mh .wrap{ position:relative; z-index:1; }

.mh__rubric{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap:18px;
  flex-wrap:wrap;
  padding-top:11px;
  border-top:3px solid var(--rule);
}
.mh__meta{
  display:flex;
  align-items:center;
  gap:10px;
  flex-wrap:wrap;
  white-space:normal;
}
.mh__meta-sep{ width:22px; height:1px; background:var(--hair); display:inline-block; flex:none; }

/* the headline. Each line is a clipping window; the line rises out of it.
   Driven by a load animation rather than an observer: the masthead is above
   the fold on every viewport, so "on arrival" and "on load" are the same
   moment, and a rubric can never be left clipped by an observer that a
   programmatic scroll outran. */
.mh__h{
  font-family:var(--font);
  font-weight:700;
  font-size:clamp(40px,8.2vw,102px);
  line-height:1;
  letter-spacing:-.045em;
  color:var(--tx);
  margin:clamp(22px,3.6vw,44px) 0 0;
  max-width:16ch;
}
body[data-lang="th"] .mh__h,
body[data-lang="zh"] .mh__h{ line-height:1.2; letter-spacing:-.02em; }
.mh__h em{ font-style:normal; color:var(--teal); }
.mh__l{ display:block; overflow:hidden; padding-bottom:.07em; }
/* Thai tone marks sit above the line and Chinese fills the full em box. The
   clipping window that makes the line rise will shave both at Latin metrics. */
body[data-lang="th"] .mh__l,
body[data-lang="zh"] .mh__l{ padding-bottom:.14em; }
.mh__l > span{ display:block; }
html.js .mh__l > span{
  animation:mh-rise .95s var(--ease) both;
  animation-delay:calc(var(--ld,0)*120ms + .12s);
}
@keyframes mh-rise{ from{ transform:translateY(112%); } to{ transform:none; } }

/* the same determinism for the masthead's teleprinter rubric */
html.js .mh .tg-tele{
  animation:mh-type .62s steps(14,end) .1s both;
  clip-path:inset(0 0 0 0);
}
@keyframes mh-type{ from{ clip-path:inset(0 100% 0 0); } to{ clip-path:inset(0 0 0 0); } }

/* the offer, said as a ruled strip where the eye already is */
.mh__index{ margin:clamp(26px,3.4vw,40px) 0 0; list-style:none; padding:0; }
.mh__index li{ font-size:15px; font-weight:600; color:var(--tx); line-height:1.5; }
.mh__index .tg-cols__n{ color:var(--tx-4); }
.mh__index li:last-child{ font-weight:500; color:var(--tx-2); }
.mh__index li:last-child .tg-cols__n{ color:var(--teal); }

.mh__body{
  display:grid;
  grid-template-columns:minmax(0,1.06fr) minmax(0,.94fr);
  gap:clamp(26px,4vw,58px);
  align-items:start;
  margin-top:clamp(26px,3.4vw,44px);
}
.mh__lede{
  font-size:clamp(16px,1.45vw,18.5px);
  line-height:1.8;
  color:var(--tx-2);
  max-width:58ch;
}
.mh__ctas{ display:flex; flex-wrap:wrap; gap:12px; margin-top:clamp(22px,2.6vw,30px); }
.mh__trust{ margin-top:18px; white-space:normal; }
.mh__plate{ margin:0; align-self:start; }
.mh__plate > img{ aspect-ratio:16/9; object-fit:cover; }

/* the credit line, and the proof figures under it */
.mh__cred{
  margin-top:clamp(26px,3.4vw,42px);
  padding-top:13px;
  border-top:1px solid var(--hair);
  white-space:normal;
}
.mh__cred em{ font-style:normal; color:var(--teal); }
.mh__stats{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:0;
  margin-top:clamp(24px,3vw,34px);
  border-top:2px solid var(--rule);
  border-left:1px solid var(--hair);
  list-style:none;
  padding:0;
}
.mh__stats > li{
  padding:20px 22px;
  border-right:1px solid var(--hair);
  border-bottom:1px solid var(--hair);
  min-width:0;
}
.mh__stats > li:last-child{ border-right:0; }
.mh__stats b{
  display:block;
  font-weight:700;
  font-size:clamp(34px,4.4vw,60px);
  line-height:1.05;
  letter-spacing:-.045em;
  color:var(--ink);
  font-variant-numeric:tabular-nums;
}
/* direct children ONLY. `.mh__stats span` also matched the odometer's own
   digit columns, which inherit their height from font-size - the figures
   rendered as 10px specks under a full-size "+". */
.mh__stats > li > span{
  display:block;
  margin-top:8px;
  font-family:var(--mono);
  font-size:10.5px;
  line-height:1.5;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:var(--tx-3);
}

@media(max-width:900px){
  .mh__body{ grid-template-columns:1fr; gap:28px; }
  .mh__ctas .tg-btn{ width:100%; }
  .mh__stats{ grid-template-columns:1fr; border-left:0; }
  .mh__stats > li{ border-right:0; padding:16px 0; }
}

/* ── 3 · the ruled entry: copy beside a printed figure ───────────
   The single biggest change on chain.html. A capability used to be a line
   of text inside a box; it is now an entry in a spec sheet with the real
   screen printed next to it. */
.ents{ margin-top:clamp(6px,1vw,10px); }
.ent{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,.84fr);
  gap:clamp(26px,4.4vw,66px);
  align-items:center;
  padding:clamp(32px,4.4vw,58px) 0;
  border-top:2px solid var(--rule);
}
.ent:first-child{ border-top-width:3px; }
.ent--flip .ent__copy{ order:2; }
.ent--flip .ent__fig{ order:1; }
/* a desktop capture is 16:10, not a phone: give it the wider half or it lands
   on the page smaller than the phone shots above it. */
.ent--wide{ grid-template-columns:minmax(0,.86fr) minmax(0,1.14fr); }
.ent__kick{
  display:block;
  font-family:var(--mono);
  font-size:10.5px;
  line-height:1.5;
  font-weight:600;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--teal);
  margin-bottom:10px;
  font-variant-numeric:tabular-nums;
}
.ent__copy h3{
  font-size:clamp(24px,3vw,38px);
  font-weight:700;
  line-height:1.14;
  letter-spacing:-.03em;
  color:var(--tx);
  margin:0 0 16px;
}
body[data-lang="th"] .ent__copy h3,
body[data-lang="zh"] .ent__copy h3{ line-height:1.3; letter-spacing:-.015em; }
.ent__copy h3 em{ font-style:normal; color:var(--teal); }
.ent__copy p{ color:var(--tx-2); font-size:16px; line-height:1.8; max-width:52ch; }
.ent__facts{ list-style:none; margin:18px 0 0; padding:0; border-top:1px solid var(--hair); }
.ent__facts li{
  display:flex;
  gap:12px;
  align-items:flex-start;
  padding:12px 0;
  border-bottom:1px solid var(--hair);
  font-size:15px;
  line-height:1.65;
  color:var(--tx-2);
}
.ent__facts svg{ flex:none; margin-top:5px; color:var(--teal); }
.ent__fig{ margin:0; }
.ent__fig img{ width:100%; height:auto; display:block; }
@media(max-width:860px){
  .ent{ grid-template-columns:1fr; gap:24px; padding:30px 0; }
  .ent--flip .ent__copy{ order:0; }
  .ent--flip .ent__fig{ order:0; }
  .ent__fig{ max-width:340px; }
  .ent--wide .ent__fig{ max-width:none; }
}

/* ── 4 · figure strips: plates of equal weight ───────────────────*/
.figs{
  display:grid;
  gap:clamp(14px,1.8vw,22px);
  margin-top:clamp(28px,3.4vw,46px);
}
.figs--2{ grid-template-columns:repeat(2,1fr); }
.figs--4{ grid-template-columns:repeat(4,1fr); }
.figs figure{ margin:0; }
.figs img{ width:100%; height:auto; display:block; }
.figs--4 img{ aspect-ratio:4/5; object-fit:cover; object-position:center top; }
.figs--2 img{ aspect-ratio:3/2; object-fit:cover; object-position:center top; }
@media(max-width:900px){ .figs--4{ grid-template-columns:repeat(2,1fr); } }
@media(max-width:520px){ .figs--4,.figs--2{ grid-template-columns:1fr; } }
/* the LINE rich menus exist as a Thai capture and a zh-TW capture. There is
   no English one, so the strip is hidden on EN rather than showing an English
   reader a Thai screen. index.html hides its .linemenu section the same way. */
body[data-lang="en"] .figs--oa{ display:none; }

/* a single wide plate used as a section rest */
.plate-wide{ margin:clamp(28px,3.4vw,46px) 0 0; }
.plate-wide > img{ aspect-ratio:16/9; object-fit:cover; }

/* ── 5 · the lead form as a ruled document ───────────────────────
   chain.css already stripped the floating white card off .form. What was
   missing was the document furniture: a header strap that says what the
   sheet is, ruled field rows, and a filled ink submit. Nothing structural
   about the form changed - same Web3Forms key, same name= attributes, same
   honeypot, same #leadForm / #leadBtn / #leadOk / #leadErr hooks. */
.doc-strap{
  display:flex;
  align-items:center;
  gap:10px;
  flex-wrap:wrap;
  font-family:var(--mono);
  font-size:10.5px;
  line-height:1.5;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:var(--tx-3);
  padding-bottom:16px;
  margin-bottom:18px;
  border-bottom:1px solid var(--hair);
}
.form .fgrid{ gap:18px; }
.form .tg-btn{ width:100%; margin-top:20px; }
.lead .form__note{ text-align:left; font-family:var(--mono); font-size:10.5px;
  line-height:1.6; letter-spacing:.06em; color:var(--tx-3); text-transform:none; }
.lead__aside li::marker{ content:none; }
.msg{ border:0; border-top:3px solid var(--rule); border-radius:0; padding:22px 0 0; margin-top:22px; }
.msg--ok{ background:none; border-top-color:var(--teal); }
.msg--ok b{ color:var(--teal-deep); }
.msg--err{ background:none; border-top-color:var(--red); }

/* ── 6 · the last of the cinematic grammar on these two pages ────
   .split__media kept a drop-shadow filter that no token could reach, so the
   phone still floated over the paper like a product render. A figure on
   this site is printed, not lit. */
.split__media img{ filter:none; box-shadow:none; border-radius:0; }
.split__media .tg-plate{ width:100%; }
.split__media .tg-plate img{ border:0; }

/* ── 7 · section furniture shared by both pages ──────────────────*/
.sec__lead{ max-width:62ch; }
.punch{ border-left-width:3px; border-left-color:var(--rule); }
.punch em{ font-style:normal; color:var(--teal); }
.sec__note{
  margin-top:clamp(26px,3vw,38px);
  padding-top:14px;
  border-top:1px solid var(--hair);
  font-family:var(--mono);
  font-size:10.5px;
  line-height:1.7;
  letter-spacing:.1em;
  text-transform:uppercase;
  color:var(--tx-3);
}
.sec__note b{ color:var(--tx); font-weight:700; }

/* a standalone figure, set the way the app sets one */
.fig-line{
  display:flex;
  align-items:baseline;
  gap:14px;
  flex-wrap:wrap;
  margin-top:clamp(24px,3vw,36px);
  padding-top:clamp(22px,2.6vw,32px);
  border-top:2px solid var(--rule);
}
.fig-line__n{
  font-weight:700;
  font-size:clamp(38px,5.4vw,76px);
  line-height:1;
  letter-spacing:-.05em;
  color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.fig-line__n .tg-suf{
  font-family:var(--mono);
  font-size:.3em;
  font-weight:600;
  letter-spacing:.06em;
  color:var(--tx-3);
  vertical-align:24%;
  margin-left:4px;
}
.fig-line__cap{
  flex:1 1 340px;
  min-width:0;
  font-family:var(--mono);
  font-size:10.5px;
  line-height:1.7;
  letter-spacing:.1em;
  text-transform:uppercase;
  color:var(--tx-3);
  max-width:660px;   /* ch is useless here: 1ch of 10.5px mono is ~6px */
}
.fig-line__cap b{ color:var(--tx); font-weight:700; }

/* the closing call, centred on its own rule */
.close{ text-align:center; }
.close .kicker{ text-align:center; }
.close__h{
  font-size:clamp(28px,4.4vw,60px);
  font-weight:700;
  line-height:1.08;
  letter-spacing:-.035em;
  color:var(--tx);
  margin:0 auto;
  max-width:20ch;
}
body[data-lang="th"] .close__h,
body[data-lang="zh"] .close__h{ line-height:1.26; letter-spacing:-.015em; }
.close__h em{ font-style:normal; color:var(--teal); }
.close__ctas{ display:flex; flex-wrap:wrap; gap:12px; justify-content:center;
  margin-top:clamp(24px,3vw,34px); }
.close__trust{ margin-top:20px; white-space:normal; }
@media(max-width:640px){
  .close__ctas{ flex-direction:column; align-items:stretch; }
  .close__ctas .tg-btn{ width:100%; }
}

/* ── 8 · nav: the CTA is a Tarang button, like index ─────────────*/
#nav .tg-btn--sm{ flex:none; }
@media(max-width:820px){ .tg-btn--nav-hide{ display:none; } }

/* ── 9 · reduced motion = the printed page ───────────────────────*/
@media (prefers-reduced-motion:reduce){
  html.js .mh__l > span{ animation:none !important; transform:none !important; }
  html.js .mh .tg-tele{ animation:none !important; clip-path:none !important; }
}

/* ── 10 · the film ───────────────────────────────────────────────
   chain.html does not load v9.css, so the two rules the video needs are
   restated here rather than pulling in the homepage sheet for them. Kept
   byte-identical in behaviour to v9.css so the two pages render the film the
   same way. The frame itself is tg-plate, which tarang.css already provides. */
.vid__frame{ margin:0; max-width:1000px; }
.vid__media{ display:block; width:100%; height:auto; aspect-ratio:16/9;
  background:var(--paper-2); }

/* ── "the app is not English, only this film is" ────────────────────────────
   Same line as the homepage carries, for the same reason: the picture inside
   the film is the English app in every language. TH and zh only - with no .en
   span inside, the line collapses for English readers on its own, and this
   rule makes that explicit. Last in the file: .tg-plate__cap rules sit above. */
.vid__lang{ margin:10px 0 0; font-size:13px; line-height:1.6; color:var(--tx-3); }
body[data-lang="en"] .vid__lang{ display:none; }
