/* ==========================================================================
   /guides/, /industries/, /privacy/ — the reading surface. 34 pages.

   WHY THIS IS A SEPARATE STYLESHEET, AND A SEPARATE KIND OF PAGE

   The rest of the site is one WebGL scroll experience: `/`, `/about/`,
   `/solutions/` and the nine `/solutions/<id>/` pages are all the same engine,
   and its detail-page type tops out at roughly 300 words of copy — that is a
   structural ceiling (see README, "The detail page is a case-study gallery,
   not an article"), not a styling choice. Answer engines retrieve at passage
   level, so a site that cannot host passages cannot be quoted on anything but
   its own brand name.

   So these are deliberately NOT engine pages. No canvas, no preloader, no
   ~23 MB of textures, no router. It is HTML and this file — which is also why
   they load in well under a second on a phone on 4G, and why an HTML-only
   crawler (OpenAI's do not execute JavaScript) reads all of them.

   WHAT THE VISUAL LAYER IS ALLOWED TO COST. These pages exist to be retrieved
   and quoted, so the brief has a hard floor under it:

     - No JavaScript. Not one line. Nothing may depend on it.
     - Nothing that moves content out of the first chunk, reorders headings or
       touches the copy. Every rule here is presentational; the generator
       emits the same document it did before plus one wrapper div.
     - No new network request except the brand's own Regular weight (31 KB,
       `font-display:swap`, so first paint never waits for it).

   INTEGRATION, not isolation — and this file is where that is decided, since
   none of the engine is loaded here. What it borrows, element by element:

     engine                                      here
     ----------------------------------------    ---------------------------
     black #000 / off-white #f0f1fa, inverted     the same two tokens, and the
       section to section (html.is-white-bg)        masthead inverts
     UniwebSans display, tight, very large        h1, h2
     IBMPlexMono uppercase tracked .16em labels   .g-kicker, .g-box-title
     zero-padded 001 in mono, in a column         .g-toc, .g-list, .g-faq,
       beside hairline-separated rows               .g-related, section h2
     full-bleed hairlines between groups          section separators
     pill CTA that goes blue on hover             .g-cta
     --color-blue #1a2ffb                         links and accents

   THE ONE THING NOT BORROWED IS MOTION. The engine animates on a render loop;
   a reading surface carrying 22,000 words must not. What is here is a single
   scroll-linked fade, pure CSS, behind @supports and off under
   prefers-reduced-motion — and it never sets a resting opacity outside that
   guard, so a browser without view timelines shows finished text rather than
   blank space.

   CJK: the small tracked-out mono labels are sized for uppercase Latin. At
   .72rem with .16em of tracking a Chinese glyph is ~10px and loses its
   interior strokes — the same lesson the engine pages learned in #73 — so the
   Chinese labels get their own size and almost no tracking.

   LINKING BOTH WAYS. Anchors from an engine page into /guides/ MUST carry
   data-link-type="external" — the router intercepts same-origin clicks and
   `/guides/…` matches none of its five route patterns, so without the
   attribute the click is swallowed and logged as "external/unknown route
   ignored". Anchors from here back into the site are ordinary links; nothing
   is intercepting them, because the engine is not loaded on this page.
   ========================================================================== */

/* THESE PAGES ARE DARK, AND NOT BECAUSE OF THE READER'S OS.

   They used to carry two palettes and switch on `prefers-color-scheme`, and
   the light one is what this block used to hold. It was a defensible idea and
   it produced an indefensible page, because the light palette is not simply
   the dark one lightened: three blocks are INVERTED on purpose — the
   masthead, "In short" and the closing CTA (see --g-band below). On a dark
   page those lift a step, from #05050a to #101018, and the page reads as one
   surface. On a light page they go to pure black, full-bleed (`.g-mast`
   carries `box-shadow: 0 0 0 100vmax var(--g-band)`), and an article becomes
   three black slabs stacked between white ones. Reported, exactly, as 熊猫色.

   So the light palette is gone rather than repaired, for two reasons. The
   inversion is the design — it is what ties these pages to the engine's own
   sections — and taking it out to make light mode work would cost more than
   light mode is worth here. And the reader never chose it: the same phone
   showed the same page dark in the evening and panda in the morning, which
   is not a preference being honoured, it is a page that will not hold still.

   `color-scheme: dark` is the other half and is not decoration. It tells the
   UA that this page is dark, so the scrollbar, the form controls, the tap
   highlight and the space under an over-scroll all come out dark instead of
   staying light around a dark page.

   The print block at the bottom of this file is what makes this affordable:
   it already flips everything back to black-on-white, so a merchant printing
   a guide to compare providers does not spend a cartridge on the background. */
:root {
  color-scheme: dark;

  /* the engine's own tokens, not approximations of them */
  --g-offwhite: #f0f1fa;
  --g-blue: #1a2ffb;

  --g-bg: #05050a;
  --g-fg: var(--g-offwhite);
  --g-muted: #9a9ba6;
  --g-rule: rgba(240, 241, 250, .18);
  --g-rule-soft: rgba(240, 241, 250, .10);
  --g-card: #101018;
  --g-accent: #8b97ff;     /* #1a2ffb has too little contrast on black */

  /* The inverted block: masthead, "In short", the closing CTA. On a black page
     it cannot invert to black, so it lifts instead — the move the engine makes
     when two dark sections meet. */
  --g-band: #101018;
  --g-band-fg: var(--g-offwhite);
  --g-band-muted: rgba(240, 241, 250, .64);
  --g-band-rule: rgba(240, 241, 250, .16);

  --g-max: 46rem;          /* the reading measure */
  --g-chrome-max: 72rem;   /* header and footer frame the page, wider */
  --g-radius: 16px;
  --g-pad: 1.25rem;
}

*, *::before, *::after { box-sizing: border-box; }

html { font-size: 100%; -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--g-bg);
  color: var(--g-fg);
  /* the brand face, not system-ui — see the generator's font block */
  font-family: UniwebSans, system-ui, "Segoe UI", Roboto, Helvetica, Arial,
               sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  font-size: 1.0625rem;
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
}

/* The Chinese tree has no CJK webfont — same decision as the engine pages, for
   the same reason (a subset covering this copy is larger than the entire rest
   of the page). Name the platform faces so the fallback is a designed choice
   rather than whatever the browser reaches for first. UniwebSans leads, and
   carries the Latin inside a Chinese sentence — Sunmi P3, Dynamic PayNow, T+1
   — while the CJK falls through to the platform face. */
:lang(zh-Hans), [lang="zh-Hans"] {
  font-family: UniwebSans, system-ui, "PingFang SC", "Hiragino Sans GB",
               "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", sans-serif;
  line-height: 1.9;
}

a { color: inherit; text-decoration: underline;
    text-underline-offset: .18em; text-decoration-thickness: .06em;
    text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); }
@media (hover: hover) {
  a:hover { text-decoration-thickness: .12em; text-decoration-color: var(--g-accent); }
}

::selection { background: var(--g-accent); color: #fff; }

.g-wrap { max-width: var(--g-max); margin: 0 auto; padding: 0 var(--g-pad); }


/* --- chrome --------------------------------------------------------------
   The header had no responsive treatment at all: `.g-head-in` is a flex row
   and flex items shrink below their content, so at 320-390 everything that
   COULD break, broke — `Uniweb Pay` onto two lines, 指南 into 指 / 南 — and on
   the English pages `Guides` and `Solutions` could not break at all, so they
   overflowed and took document.scrollWidth to 373 in a 320 viewport. Only
   `.g-cta` survived, because it was the one item carrying nowrap.

   nowrap on the brand and the links is the fix; below 560 the nav then drops
   to its own row, so row one keeps the two things a reader reaches for.    */

.g-head {
  border-bottom: 1px solid var(--g-rule);
  position: sticky; top: 0; z-index: 10;
  background: color-mix(in srgb, var(--g-bg) 88%, transparent);
  backdrop-filter: saturate(1.6) blur(10px);
}
/* The chrome is wider than the reading column. The engine's header spans the
   whole viewport and only its content is constrained; a five-item site nav
   does not fit in a 46rem document measure, and a header pinned to the text
   width reads as a document rather than as the site. */
.g-head-in {
  max-width: var(--g-chrome-max); margin: 0 auto; padding: .8rem var(--g-pad);
  display: flex; align-items: center; gap: 1rem;
}
/* the brand lockup, matching the engine header's own
   `#header-logo{display:inline-flex;align-items:center;gap:10px}` with a
   30px rounded mark — scaled here to the smaller wordmark this header uses */
.g-logo {
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: Poppins, Arial, Helvetica, sans-serif;
  font-weight: 500; font-size: 1.06rem; letter-spacing: -.01em;
  text-decoration: none; margin-right: auto;
}
.g-logo-mark { width: 26px; height: 26px; border-radius: 8px; display: block; flex: none; }
/* `align-items: baseline` is the whole fix for "中文 sits low", and the reason
   is worth writing down because the earlier attempt chased the wrong thing.

   Flex items are independent block containers. With the default
   `align-items: normal` (stretch) they do NOT share a baseline — each one puts
   its text on its own line box's baseline, and a line box's baseline sits
   lower the larger its font is. Measured: the three Latin labels had their
   baseline at y=33.94 and 中文, one step larger, at y=35.94. Two pixels, and
   nothing to do with CJK metrics at all — the ink was fine, the boxes were
   flush top and bottom (stretch made sure of that, which is exactly what hid
   it), and only the baselines disagreed. */
.g-nav {
  display: flex; align-items: baseline; gap: 1.15rem; font-size: .76rem;
  font-family: IBMPlexMono, ui-monospace, monospace;
  text-transform: uppercase; letter-spacing: .1em;
}
.g-nav a { text-decoration: none; color: var(--g-muted); }
@media (hover: hover) { .g-nav a:hover { color: var(--g-fg); } }
.g-logo, .g-nav a { white-space: nowrap; }

/* CJK nav labels are not uppercase Latin: .16em of tracking reads as broken
   spacing on full-width glyphs, and uppercase is a no-op on them. But the two
   cases are NOT the same and were wrong to share a rule.

   On a CHINESE page every label is CJK, so the row sets its own size and can
   afford to be a step larger.

   On an ENGLISH page the single 中文 switch has to sit in a row of tracked-out
   Latin capitals, and size is what makes it a peer rather than an intruder.
   A capital only fills its cap height — about .70em — while a CJK glyph fills
   nearly the whole em, .93em of ink. So at .84rem against the row's .76rem the
   中文 was rendering 1.47x the height of its neighbours: above their cap line
   and below their baseline at the same time, which is what reads as "not
   aligned". Matching the nominal size drops that to 1.33x, which is simply
   what CJK next to Latin caps looks like, and the optical centres then differ
   by 0.1px. It is not made smaller than the row — that is the #73 trap — it is
   made the same. */
[lang="zh-Hans"] .g-nav a {
  text-transform: none; letter-spacing: .02em; font-size: .84rem;
}
.g-nav a[lang="zh-Hans"] {
  text-transform: none; letter-spacing: .02em; font-size: .78rem;
}

@media (max-width: 560px) {
  .g-head-in { flex-wrap: wrap; gap: .55rem 1rem; padding: .7rem var(--g-pad); }
  /* `flex-basis:100%` sets the nav's base width but cannot shrink it below its
     own content, and four nowrap labels are 309px against the 280px a 320
     viewport leaves — which is the page panning sideways again, one level
     down. The labels stay nowrap; the nav wraps between them instead. */
  .g-nav { order: 3; flex-basis: 100%; flex-wrap: wrap; gap: .5rem 1.15rem; }
}

.g-cta {
  display: inline-block; padding: .5rem 1.05rem; border-radius: 100px;
  background: var(--g-fg); color: var(--g-bg) !important;
  text-decoration: none !important; font-size: .8rem; font-weight: 500;
  white-space: nowrap;
  transition: background .45s cubic-bezier(.35, 0, 0, 1), color .45s;
}
.g-cta[aria-disabled="true"] { cursor: default; pointer-events: none; }
@media (hover: hover) { .g-cta:hover { background: var(--g-blue); color: #fff !important; } }
@media (hover: hover) {
  .g-cta[aria-disabled="true"]:hover { background: var(--g-fg); color: var(--g-bg) !important; }
}

.g-alt {
  display: inline-block; padding: .5rem 1.05rem; border-radius: 100px;
  border: 1px solid currentColor; color: inherit;
  text-decoration: none !important; font-size: .8rem; font-weight: 500;
  white-space: nowrap; opacity: .82;
  transition: opacity .4s;
}
@media (hover: hover) { .g-alt:hover { opacity: 1; } }


/* --- masthead ------------------------------------------------------------
   The full-bleed band is a spread box-shadow rather than a 100vw width: `vw`
   includes the scrollbar, so a vw-wide band is a horizontal scrollbar on every
   desktop browser that shows one. A shadow paints outside the box without
   entering the scroll width at all, and the clip-path keeps it from bleeding
   vertically past the band's own edges.                                    */

.g-mast {
  background: var(--g-band); color: var(--g-band-fg);
  box-shadow: 0 0 0 100vmax var(--g-band);
  clip-path: inset(0 -100vmax);
  padding: 3.4rem 0 2.9rem;
  margin: 0 0 3rem;
}

.g-kicker {
  font-family: IBMPlexMono, ui-monospace, monospace; font-size: .72rem;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--g-band-muted); margin: 0 0 1.4rem;
}
[lang="zh-Hans"] .g-kicker {
  font-size: .84rem; letter-spacing: .04em; text-transform: none;
}

h1 {
  font-family: UniwebSans, system-ui, sans-serif;
  font-weight: 500; font-size: clamp(2.05rem, 6.1vw, 3.8rem); line-height: 1.04;
  letter-spacing: -.022em; margin: 0 0 1.3rem;
  text-wrap: balance;
}
[lang="zh-Hans"] h1 {
  line-height: 1.28; letter-spacing: 0;
  font-size: clamp(1.8rem, 5.3vw, 3.1rem);
}

/* The lead is the answer capsule: an engine that chunks this page gets a
   self-contained answer in the first chunk, before any navigation or context.
   It is kept to 40-80 words for exactly that reason — and set large here,
   because the thing that has to survive retrieval should also be the thing a
   human reads first. */
.g-lead {
  font-size: clamp(1.08rem, 2.3vw, 1.28rem); line-height: 1.56;
  margin: 0; max-width: 38rem; text-wrap: pretty;
}
[lang="zh-Hans"] .g-lead { line-height: 1.8; }
.g-mast a { color: inherit; }


/* --- article -------------------------------------------------------------
   Sections are separated by a hairline and numbered in the margin in mono,
   which is the engine's own list signature (Accepts / 001 / Contactless).  */

main { padding: 0 0 4rem; counter-reset: g-sec; }

/* `.g-related` is navigation, not a section of the argument, so it is left out
   of the numbering. It has to be excluded HERE rather than overridden later:
   `main > .g-wrap > section > h2::before` is (0,1,4) and a later
   `.g-related h2::before{content:none}` is only (0,1,2), so the override loses
   and the related list was numbered 008. */
article > section:not(.g-related),
main > .g-wrap > section:not(.g-related) {
  counter-increment: g-sec;
}
article > section, main > .g-wrap > section {
  border-top: 1px solid var(--g-rule);
  padding-top: 2.6rem; margin-top: 2.6rem;
}

h2 {
  font-family: UniwebSans, system-ui, sans-serif;
  font-weight: 500; font-size: clamp(1.4rem, 3.4vw, 1.95rem); line-height: 1.16;
  letter-spacing: -.015em; margin: 0 0 1rem; scroll-margin-top: 6rem;
  text-wrap: balance;
}
article > section:not(.g-related) > h2::before,
main > .g-wrap > section:not(.g-related) > h2::before {
  content: "0" counter(g-sec, decimal-leading-zero);
  display: block; margin-bottom: .7rem;
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .72rem; font-weight: 400; letter-spacing: .16em;
  color: var(--g-muted);
}
h3 {
  font-family: UniwebSans, system-ui, sans-serif;
  font-weight: 500; font-size: 1.1rem; line-height: 1.4; margin: 2rem 0 .5rem;
}
[lang="zh-Hans"] h2, [lang="zh-Hans"] h3 { line-height: 1.5; letter-spacing: 0; }

p { margin: 0 0 1.15rem; text-wrap: pretty; }
ul, ol { margin: 0 0 1.25rem; padding-left: 1.3rem; }
li { margin: 0 0 .5rem; }
li::marker { color: var(--g-muted); }
strong { font-weight: 500; }


/* --- "In short", which is the retrievable payload ------------------------
   Inverted, because on a page whose job is to be quoted the summary is the
   most important block on it — and because inverting a block against the page
   is what the engine does section to section. */

.g-box {
  background: var(--g-band); color: var(--g-band-fg);
  border-radius: var(--g-radius);
  padding: 1.5rem 1.5rem 1.6rem; margin: 0 0 2rem;
}
.g-box p:last-child, .g-box ul:last-child, .g-box ol:last-child { margin-bottom: 0; }
.g-box li::marker { color: var(--g-band-muted); }
.g-box a { color: inherit; }

.g-box-title {
  font-family: IBMPlexMono, ui-monospace, monospace; font-size: .7rem;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--g-band-muted); margin: 0 0 .9rem;
}
[lang="zh-Hans"] .g-box-title {
  font-size: .82rem; letter-spacing: .04em; text-transform: none;
}


/* --- table of contents: hairline rows, numbered in mono ------------------ */

.g-toc {
  background: none; color: inherit;
  border: 1px solid var(--g-rule); border-radius: var(--g-radius);
  padding: 1.35rem 1.5rem;
}
.g-toc .g-box-title { color: var(--g-muted); }
.g-toc ol { margin: 0; padding: 0; list-style: none; counter-reset: g-toc; }
.g-toc li {
  counter-increment: g-toc; margin: 0;
  border-top: 1px solid var(--g-rule-soft);
}
.g-toc li:first-child { border-top: 0; }
.g-toc a {
  display: grid; grid-template-columns: 3.1rem 1fr auto; gap: .5rem;
  align-items: baseline; padding: .62rem 0;
  text-decoration: none; font-size: .97rem;
}
.g-toc a::before {
  content: "0" counter(g-toc, decimal-leading-zero);
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .74rem; letter-spacing: .1em; color: var(--g-muted);
}
@media (hover: hover) { .g-toc a:hover { color: var(--g-accent); } }


/* --- index lists (/guides/, /industries/) --------------------------------
   The engine's clearest editorial pattern is a numbered row against a
   hairline, so the two index pages are built out of exactly that.          */

.g-list { list-style: none; margin: 0; padding: 0; counter-reset: g-item; }
.g-list > li {
  counter-increment: g-item;
  border-top: 1px solid var(--g-rule);
  padding: 1.7rem 0 1.6rem; margin: 0;
  display: grid; grid-template-columns: 3.4rem 1fr; gap: 0 .6rem;
}
.g-list > li:last-child { border-bottom: 1px solid var(--g-rule); }
.g-list > li::before {
  content: "0" counter(g-item, decimal-leading-zero);
  grid-row: 1 / span 2;
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .74rem; letter-spacing: .1em; color: var(--g-muted);
  padding-top: .5rem;
}
.g-list h2 {
  margin: 0 0 .45rem; font-size: clamp(1.18rem, 2.8vw, 1.5rem); line-height: 1.24;
}
.g-list h2::before { content: none; }
.g-list h2 a { text-decoration: none; }
@media (hover: hover) { .g-list h2 a:hover { color: var(--g-accent); } }
.g-list p { margin: 0; color: var(--g-muted); font-size: .97rem; }

@media (max-width: 460px) {
  .g-list > li { grid-template-columns: 1fr; }
  .g-list > li::before { grid-row: auto; padding: 0 0 .5rem; }
}


/* --- tables --------------------------------------------------------------
   Wide content scrolls inside its own box; the page body never does. That is
   the responsive-table pattern working, not an overflow bug — a width probe
   that flags ink past the viewport without asking whether an ancestor scrolls
   reports about forty false positives across these pages. */

.g-tablewrap { overflow-x: auto; margin: 0 0 1.9rem; -webkit-overflow-scrolling: touch; }
table {
  border-collapse: collapse; width: 100%; font-size: .93rem; min-width: 30rem;
  line-height: 1.5;
}
caption.g-box-title { text-align: left; color: var(--g-muted); padding-bottom: .7rem; }
th, td {
  text-align: left; padding: .68rem .85rem .68rem 0;
  border-bottom: 1px solid var(--g-rule-soft); vertical-align: top;
}
thead th {
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .7rem; letter-spacing: .1em; text-transform: uppercase;
  font-weight: 400; color: var(--g-muted);
  border-bottom-color: var(--g-rule); white-space: nowrap;
}
[lang="zh-Hans"] thead th {
  text-transform: none; letter-spacing: .02em; font-size: .82rem;
}
tbody th { font-weight: 500; white-space: normal; }
tbody tr:last-child td, tbody tr:last-child th { border-bottom: 0; }

.g-note {
  border-left: 2px solid var(--g-accent); padding-left: 1.1rem;
  color: var(--g-muted); font-size: .96rem; margin: 0 0 1.7rem;
}


/* --- FAQ ---------------------------------------------------------------- */

.g-faq > div {
  padding: 1.5rem 0 1.4rem; border-bottom: 1px solid var(--g-rule-soft);
}
.g-faq > div:first-of-type { border-top: 1px solid var(--g-rule-soft); }
.g-faq > div:last-child { border-bottom: 0; }
.g-faq h3 { margin: 0 0 .55rem; }
.g-faq h3 + p { margin-bottom: 0; }
.g-faq p { color: var(--g-muted); }


/* --- /faq/ and /glossary/ ------------------------------------------------
   Both pages are long lists of short, self-contained entries, and both are
   read the same way: scanned for one item, not read through. So they share a
   shape — a hairline per entry, the term or question at body weight, the
   answer in the muted tone the guide FAQ already uses.

   The entries are NOT numbered. Every other list on these pages carries the
   zero-padded mono counter (see .g-toc, .g-list, .g-related), and it earns its
   place there because those lists are short and ordered. Ninety questions
   counted to 089 reads as a form to fill in, and a glossary is looked up
   rather than worked through. */

.g-qa, .g-term {
  padding: 1.45rem 0 1.35rem; border-top: 1px solid var(--g-rule-soft);
}
section > .g-qa:first-of-type, section > .g-term:first-of-type { border-top: 0; padding-top: .4rem; }
.g-qa h3, .g-term h3 { margin: 0 0 .5rem; }
.g-qa > p, .g-term > p { color: var(--g-muted); margin-bottom: 0; }
.g-qa > p + p, .g-term > p + p { margin-top: .7rem; }

/* the note keeps the accent rule the guides use for an aside, at the smaller
   size these entries are set in */
.g-term .g-note { margin: .7rem 0 0; font-size: .92rem; padding-left: .95rem; }
.g-term .g-note strong { color: var(--g-fg); font-weight: 500; }

/* The back-links are deliberately quiet. On /faq/ every entry has one, so at
   body weight ninety of them would out-shout the answers they sit under. */
.g-qa-src, .g-term-see {
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .73rem; letter-spacing: .05em; margin-top: .75rem !important;
  color: var(--g-muted);
}
/* the group-level source sits under the h2 and above the first entry, so it
   takes the heading's spacing rather than an entry's */
.g-qa-src-group { margin: -.4rem 0 1.6rem !important; }
.g-qa-src a, .g-term-see a { color: var(--g-fg); text-decoration: none; border-bottom: 1px solid var(--g-rule); }
@media (hover: hover) {
  .g-qa-src a:hover, .g-term-see a:hover { color: var(--g-accent); border-bottom-color: currentColor; }
}
/* 中文 sets these strings in the body face, not the Latin mono — IBM Plex Mono
   has no CJK coverage, so a mono rule here would silently fall back mid-string
   and the label would not match the link beside it. */
[lang="zh-Hans"] .g-qa-src, [lang="zh-Hans"] .g-term-see {
  font-family: inherit; font-size: .8rem; letter-spacing: .02em;
}

/* --- the visible breadcrumb ----------------------------------------------

   Every document page has carried BreadcrumbList markup since the layer was
   built and none of them showed one. Google's guidance is that the markup
   should describe a trail the page presents, and a reader arriving on a guide
   from a search result had no indication that /guides/ existed.

   Set quiet and small on purpose: it sits above the masthead, and a breadcrumb
   that competes with an h1 is a breadcrumb nobody wanted. The current page is a
   <span>, not a link — a final crumb linking to itself is a no-op that screen
   readers announce as a destination. */
.g-crumbs {
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .72rem; letter-spacing: .05em;
  color: var(--g-muted);
  /* Top margin, because the header is sticky and its bottom rule is a hard
     edge: with `margin-top: 0` the trail sat ON that line with nothing between
     them, which read as part of the header rather than as the first thing on
     the page. It is roughly symmetrical with the space below — the crumb sits
     in the page background, between the header's rule and the masthead band,
     and wants to look like it is in that gap rather than stuck to one side of
     it. */
  margin: 1.5rem 0 1.6rem;
  /* nowrap, because the leaf truncates instead of wrapping — see below */
  display: flex; flex-wrap: nowrap; align-items: baseline; gap: .45rem;
}
.g-crumbs a { color: var(--g-muted); text-decoration: none; }
.g-crumbs [aria-current] { color: var(--g-fg); }
.g-crumb-sep { color: var(--g-rule); }
@media (hover: hover) {
  .g-crumbs a:hover { color: var(--g-accent); }
}
/* IBM Plex Mono has no CJK coverage, so a mono rule here falls back mid-string
   and the trail renders in two faces. Same fix as .g-qa-src. */
[lang="zh-Hans"] .g-crumbs {
  font-family: inherit; font-size: .8rem; letter-spacing: .02em;
}
/* THE LEAF TRUNCATES; IT IS NEVER HIDDEN.

   It used to be hidden below 640px, on the reasoning that a full page title
   wrapping to three lines above the h1 is worse than no breadcrumb. Two things
   were wrong with that.

   The selector did not work. `.g-crumb-sep:last-of-type` is type-based — it
   means "the last <span> among its siblings" — and the leaf is a <span> too,
   so `:last-of-type` matched the LEAF rather than the last separator. The leaf
   was hidden twice and the separator was never hidden at all, so every document
   page on a phone rendered a breadcrumb reading "Home /" with a dangling slash
   and nothing after it.

   And the idea was wrong even with a working selector. The page carries
   `BreadcrumbList` markup naming three items; Google's guidance is that the
   markup should describe a trail the page actually presents, and hiding the
   third one on the viewport most readers use makes the two disagree.

   So the trail stays whole at every width and the leaf shrinks: one line, no
   wrap, an ellipsis when there is not enough room. `min-width: 0` is what makes
   that possible — a flex item's default `min-width: auto` refuses to shrink
   below its content, so `text-overflow` would never fire without it. */
.g-crumbs > * { white-space: nowrap; }
.g-crumbs [aria-current] {
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}

/* --- grouped collection indexes ------------------------------------------

   The index used to be one <ul> of <h2> entries. At twenty-five guides that is
   a wall, so the group is the h2 and the page title is the h3 under it — see
   tools/topics.data.mjs for why the grouping exists at all.

   The count beside each group in the jump nav is the one piece of information a
   reader scanning it actually wants ("is 'money' four pages or fifteen?"), and
   it is the reason this nav is worth the space when the plain g-toc would not
   have been. */
.g-group { margin-top: 3.2rem; }
.g-group:first-of-type { margin-top: 2.4rem; }
.g-group > h2 { margin-bottom: .2rem; }
/* The third grid column of .g-toc a, used only by the grouped collection
   indexes — the per-page tables of contents have a two-item grid and simply
   leave it empty, which costs nothing. */
.g-toc a span {
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .72rem; letter-spacing: .06em; color: var(--g-muted);
  justify-self: end;
}
[lang="zh-Hans"] .g-toc a span { font-family: inherit; font-size: .78rem; letter-spacing: 0; }

/* --- /sitemap/ — the HTML index of every page ----------------------------

   A list of 142 links wants to be dense and scannable, which is the opposite
   of the reading measure the rest of this layer is set to. So it drops the
   body size, tightens the leading and — for the glossary block, which is 74
   short items — goes multi-column. Columns rather than a grid because the
   items are one line each and reading order down a column is what a reader
   scanning an alphabet-ish list expects. */
.g-sitemap {
  list-style: none; padding: 0; margin: 1rem 0 0;
  font-size: .95rem; line-height: 1.6;
}
.g-sitemap li { margin: 0 0 .42rem; }
.g-sitemap a { color: var(--g-fg); text-decoration: none;
               border-bottom: 1px solid var(--g-rule-soft); }
@media (hover: hover) {
  .g-sitemap a:hover { color: var(--g-accent); border-bottom-color: currentColor; }
}

/* The topic groups from tools/topics.data.mjs, reused here so a reader moving
   between /guides/ and /sitemap/ meets one structure rather than two. The
   label is not a link — the group is not a page. */
.g-sitemap-group {
  margin-top: 1.3rem;
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--g-muted);
}
.g-sitemap-group:first-child { margin-top: .2rem; }
[lang="zh-Hans"] .g-sitemap-group {
  font-family: inherit; font-size: .8rem; letter-spacing: .02em; text-transform: none;
}
.g-sitemap-group > ul {
  list-style: none; padding: 0; margin: .5rem 0 0;
  font-family: UniwebSans, system-ui, sans-serif;
  font-size: .95rem; letter-spacing: 0; text-transform: none; color: var(--g-fg);
}
[lang="zh-Hans"] .g-sitemap-group > ul { font-family: inherit; }

/* 74 one-line items. Two columns from 600px, three from 900px — `columns`
   rather than grid because each item is a single line and a reader scanning
   a vocabulary list reads down, not across. break-inside stops an item
   splitting across a column boundary, which is the one thing that makes
   multi-column text unreadable. */
.g-sitemap-wide { columns: 1; column-gap: 2rem; }
.g-sitemap-wide li { break-inside: avoid; }
@media (min-width: 600px) { .g-sitemap-wide { columns: 2; } }
@media (min-width: 900px) { .g-sitemap-wide { columns: 3; } }

/* --- /glossary/<term>/ — the per-term pages ------------------------------

   Three additions, and each exists because the term page is a SHORTER document
   than anything else in this layer. A guide is two thousand words and its
   navigation is a small proportion of it; a term page is three paragraphs, and
   at guide weights the links would out-mass the definition they surround.

   The kicker is a link on these pages (it goes back to the index) and is not
   on any other page in this layer, so it needs the anchor reset that the
   plain-text version never did. */
.g-kicker a { color: inherit; text-decoration: none; border-bottom: 1px solid var(--g-rule); }
@media (hover: hover) {
  .g-kicker a:hover { color: var(--g-accent); border-bottom-color: currentColor; }
}

/* Related terms: many short items, so a wrapping inline list rather than a
   bulleted column. Fifty-two terms in a stack would be the tallest thing on
   the page and the least useful. */
.g-term-list {
  list-style: none; padding: 0; margin: .9rem 0 0;
  display: flex; flex-wrap: wrap; gap: .5rem .55rem;
}
.g-term-list li { margin: 0; }
.g-term-list a {
  display: inline-block; padding: .3rem .7rem;
  border: 1px solid var(--g-rule); border-radius: 999px;
  font-size: .85rem; color: var(--g-muted); text-decoration: none;
}
@media (hover: hover) {
  .g-term-list a:hover { color: var(--g-fg); border-color: var(--g-fg); }
}

/* Previous / index / next. Grid rather than flex with space-between, because
   the first and last terms have no previous and no next — an empty <span>
   holds the column so "All 53 terms" stays centred instead of sliding to the
   edge on two pages out of fifty-three. */
.g-term-nav {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 1rem; align-items: center;
  margin: 2.6rem 0 0; padding-top: 1.4rem; border-top: 1px solid var(--g-rule-soft);
  font-size: .85rem;
}
.g-term-nav a { color: var(--g-muted); text-decoration: none; }
.g-term-nav a[rel="next"] { text-align: right; }
.g-term-nav > a:not([rel]) {
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .73rem; letter-spacing: .05em; text-transform: uppercase;
  white-space: nowrap;
}
[lang="zh-Hans"] .g-term-nav > a:not([rel]) {
  font-family: inherit; font-size: .8rem; letter-spacing: .02em; text-transform: none;
}
@media (hover: hover) {
  .g-term-nav a:hover { color: var(--g-accent); }
}
/* Below 640px the three columns cannot hold two term names and a label, so
   they stack and the index link leads — it is the one destination a reader on
   a phone is most likely to want. */
@media (max-width: 640px) {
  .g-term-nav { grid-template-columns: 1fr; gap: .7rem; text-align: left; }
  .g-term-nav a[rel="next"] { text-align: left; }
  .g-term-nav > a:not([rel]) { order: -1; }
  .g-term-nav > span { display: none; }
}


/* --- closing CTA, echoing the site's end section ------------------------- */

.g-cta-block {
  background: var(--g-band); color: var(--g-band-fg);
  box-shadow: 0 0 0 100vmax var(--g-band);
  clip-path: inset(0 -100vmax);
  padding: 2.8rem 0 3rem; margin: 3.6rem 0 0;
}
.g-cta-block h2 { margin-top: 0; font-size: clamp(1.5rem, 4vw, 2.2rem); }
.g-cta-block h2::before { content: none; }
.g-cta-block p { color: var(--g-band-muted); max-width: 34rem; }
.g-cta-block .g-cta { background: var(--g-band-fg); color: var(--g-band) !important; }
@media (hover: hover) {
  .g-cta-block .g-cta:hover { background: var(--g-blue); color: #fff !important; }
}
.g-actions { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.3rem; }
.g-actions .g-cta, .g-actions .g-alt { padding: .62rem 1.15rem; font-size: .86rem; }


/* --- related, meta, footer ----------------------------------------------- */

.g-related { border-top: 1px solid var(--g-rule); padding-top: 2.6rem; margin-top: 3rem; }
.g-related h2 { font-size: clamp(1.18rem, 2.6vw, 1.38rem); }
.g-related h2::before { content: none; }
.g-related ul { list-style: none; margin: 0; padding: 0; counter-reset: g-rel; }
.g-related li {
  counter-increment: g-rel; margin: 0;
  padding: 1.05rem 0; border-top: 1px solid var(--g-rule-soft);
  display: grid; grid-template-columns: 3.4rem 1fr; gap: 0 .6rem;
}
.g-related li::before {
  content: "0" counter(g-rel, decimal-leading-zero);
  grid-row: 1 / span 2;
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .74rem; letter-spacing: .1em; color: var(--g-muted); padding-top: .28rem;
}
.g-related a { text-decoration: none; font-weight: 500; }
@media (hover: hover) { .g-related a:hover { color: var(--g-accent); } }
.g-related span { color: var(--g-muted); font-size: .93rem; }

.g-meta {
  margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--g-rule);
  color: var(--g-muted); font-size: .86rem; line-height: 1.65;
}
.g-meta p { margin: 0 0 .5rem; }
/* the index list already closes itself with a rule; two parallel hairlines a
   clear 3rem apart read as a mistake rather than as a division */
.g-list + .g-meta { border-top: 0; padding-top: 0; margin-top: 2.2rem; }

.g-foot {
  border-top: 1px solid var(--g-rule); padding: 2.4rem 0 3rem;
  color: var(--g-muted); font-size: .86rem; line-height: 1.65;
}
.g-foot > .g-wrap { max-width: var(--g-chrome-max); }
.g-foot a { color: inherit; }
.g-foot-links {
  display: flex; flex-wrap: wrap; gap: .7rem 1.3rem; margin-bottom: 1.3rem;
  font-family: IBMPlexMono, ui-monospace, monospace;
  font-size: .72rem; letter-spacing: .12em; text-transform: uppercase;
}
.g-foot-links a { text-decoration: none; color: var(--g-fg); }
@media (hover: hover) { .g-foot-links a:hover { color: var(--g-accent); } }
[lang="zh-Hans"] .g-foot-links {
  text-transform: none; letter-spacing: .03em; font-size: .82rem;
}


/* --- motion --------------------------------------------------------------
   One scroll-linked fade, and that is deliberately the whole budget. The
   resting opacity is set ONLY inside the @supports block, so a browser without
   view timelines — and every crawler, which renders no CSS at all — gets
   finished text rather than an empty page. Off under reduced motion.       */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    article > section, main > .g-wrap > section,
    .g-list > li, .g-related li, .g-cta-block {
      animation: g-rise both linear;
      animation-timeline: view();
      animation-range: entry 2% cover 16%;
    }
    @keyframes g-rise {
      from { opacity: 0; transform: translate3d(0, 12px, 0); }
      to   { opacity: 1; transform: none; }
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}


/* --- print ---------------------------------------------------------------
   Merchants print and PDF these to compare providers, and an inverted
   masthead costs a page of toner for nothing. */

@media print {
  .g-head, .g-cta-block, .g-foot-links { display: none; }
  .g-mast, .g-box {
    background: none !important; color: #000 !important;
    box-shadow: none !important; clip-path: none !important;
  }
  .g-box { border: 1px solid #999; }
  .g-mast { border-bottom: 2px solid #000; }
  body { background: #fff; color: #000; font-size: 11pt; }
  a { text-decoration: underline; }
}
