/* assets/type.css · RIVET type ladder (Brand OS v1.2 locked ramp, role-mapped)
   One source of truth for every page. Fluid between 390px and 1280px.
   Loaded LAST in every <head> (tools/build/chrome.py links it right after nav.css); the certificate
   pages are exempt (fixed-ratio artefacts sized in cqw).
   Every clamp has spaces around + (an unspaced + is invalid CSS and is dropped).
   Headings are Plex Sans 600 in sentence case (owner, 28 Oct 2026); Mono is for eyebrows, meta, numerals. */
:root{
  /* ramp steps: mobile → desktop */
  --t-display-xl: clamp(3rem, 1.6854rem + 5.393vw, 6rem);       /* 48 → 96 */
  --t-display:    clamp(2.5rem, 1.8425rem + 2.697vw, 4rem);      /* 40 → 64 */
  --t-h1:         clamp(2rem, 1.5618rem + 1.798vw, 3rem);        /* 32 → 48 */
  --t-h2:         clamp(1.5rem, 1.2809rem + 0.899vw, 2rem);      /* 24 → 32 */
  --t-h3:         clamp(1.25rem, 1.1404rem + 0.4494vw, 1.5rem);  /* 20 → 24 */
  --t-h4:         clamp(1.125rem, 1.0702rem + 0.2247vw, 1.25rem);/* 18 → 20 */
  --t-lead:       clamp(1rem, 0.9452rem + 0.2247vw, 1.125rem);   /* 16 → 18 */
  --t-body:       1rem;   /* 16 on every screen (owner, 30 Oct 2026: easier reading on phones) */
  --t-small: 0.875rem;  /* 14 */
  --t-meta:  0.75rem;   /* 12 */
  --t-micro: 0.6875rem; /* 11 */

  --lh-display: 1.05; --lh-head: 1.2; --lh-text: 1.6; --lh-small: 1.5; --lh-meta: 1.4; --lh-micro: 1.3;
  --tr-display: -0.03em; --tr-title: -0.02em; --tr-label: 0.08em;

  /* roles */
  --role-hero-home: var(--t-display);   /* 64 desktop, 40 phone (owner, 30 Oct 2026) */
  --role-hero:      var(--t-display);
  --role-section:   var(--t-h1);
  --role-row:       var(--t-h2);
  --role-card:      var(--t-h3);
  --role-dense:     var(--t-h4);
  --role-lead-hero: var(--t-h4);
  --role-lead:      var(--t-lead);
  --role-stat:      var(--t-h1);
  --role-price:     var(--t-h2);

  /* the old fluid scale now points at the ramp, so stragglers land on ramp values */
  --step-5: var(--t-display); --step-4: var(--t-h1); --step-3: var(--t-h2); --step-2: var(--t-h3);
  --step-1: var(--t-lead);    --step-0: var(--t-body); --step--1: var(--t-meta); --step--2: var(--t-micro);

  /* motion tokens (--dur-*, --ease-*) and tracking (--track-*) come from assets/brand-tokens.css (A0); not redefined here */
}

/* brand heading line-height (was 1.12 in rivet.css) */
h1,h2,h3,h4{line-height:var(--lh-head)}

/* utility classes (use these in new markup) */
.t-hero-home{font:600 var(--role-hero-home)/var(--lh-display) var(--font-sans);letter-spacing:var(--tr-display);text-wrap:balance}
.t-hero{font:600 var(--role-hero)/var(--lh-display) var(--font-sans);letter-spacing:var(--tr-display);text-wrap:balance}
.t-section{font:600 var(--role-section)/var(--lh-head) var(--font-sans);letter-spacing:var(--tr-title);text-wrap:balance}
.t-row{font:600 var(--role-row)/var(--lh-head) var(--font-sans);letter-spacing:var(--tr-title);text-wrap:balance}
.t-card{font:600 var(--role-card)/var(--lh-head) var(--font-sans);letter-spacing:var(--tr-title)}
.t-dense{font:600 var(--role-dense)/var(--lh-head) var(--font-sans);letter-spacing:0}
.t-lead-hero{font:400 var(--role-lead-hero)/var(--lh-text) var(--font-sans);color:var(--fg-soft)}
.t-lead{font:400 var(--role-lead)/var(--lh-text) var(--font-sans);color:var(--fg-soft)}
.t-body{font:400 var(--t-body)/var(--lh-text) var(--font-sans)}
.t-small{font:400 var(--t-small)/var(--lh-small) var(--font-sans)}
.t-eyebrow,.t-meta{font:500 var(--t-meta)/var(--lh-meta) var(--font-mono);letter-spacing:var(--tr-label);text-transform:uppercase}
.t-eyebrow{color:var(--eyebrow-ink);margin:0}
.t-micro{font:500 var(--t-micro)/var(--lh-micro) var(--font-mono);letter-spacing:var(--tr-label);text-transform:uppercase}
.t-stat{font:500 var(--role-stat)/1.05 var(--font-mono);letter-spacing:var(--tr-title);font-variant-numeric:tabular-nums}
.t-price{font:500 var(--role-price)/1.05 var(--font-mono);letter-spacing:var(--tr-title);font-variant-numeric:tabular-nums}

/* two-tone heading: the tail recedes in ink-muted (solid colour, no gradient; replaces violet .hl spans) */
.h-tail{color:var(--slate)}                            /* light: slate #4A4A68, 8.6:1 on white */
html[data-mode="dark"] .h-tail{color:var(--slate-on-dark)} /* #9A9BBD, AA on black */

/* EMPHASIS (A4): every violet or cyan run inside a heading (.hl) becomes the same solid receding tail.
   Dark surfaces inside light pages (the ink bands) use the dark-mode tail. */
:is(h1,h2,h3,h4) .hl{color:var(--slate)}
.pp-h1 > span:last-child{color:var(--slate)}   /* pricing H1 tail (products.css:47 still sets violet; that file is the pricing lane's) */
html[data-mode="dark"] :is(h1,h2,h3,h4) .hl, html[data-mode="dark"] .h-tail,
body.gtm-dark :is(h1,h2,h3,h4) :is(.hl,.h-tail),
:is(.pdp-ink,.nh-ltr,.ctaband,.finale,.share,.impact__out) :is(h1,h2,h3,h4) :is(.hl,.h-tail){color:var(--slate-on-dark)}

/* Arabic: the font shorthands above set Plex Sans; Arabic text must be Almarai (Brand OS), with no
   negative tracking and no forced caps. Numerals (stats, prices) stay Plex Mono with Western digits. */
:lang(ar) :is(.t-hero-home,.t-hero,.t-section,.t-row,.t-card,.t-dense,.t-lead-hero,.t-lead,.t-body,.t-small,.t-eyebrow,.t-meta,.t-micro){
  font-family:var(--font-ar);letter-spacing:0;text-transform:none}
:lang(ar) :is(.t-hero-home,.t-hero){line-height:var(--lh-head)}  /* 1.05 clips Arabic ascenders; use the brand heading 1.2 */

/* one section-opening grammar: eyebrow → H2 → lead, with optional hairline above */
.sec-open{display:grid;gap:12px;max-width:52rem}
.sec-open > .t-eyebrow{color:var(--eyebrow-ink)}
.sec-open > .t-lead{max-width:44rem}
.sec-open--rule{border-top:1px solid var(--line);padding-top:24px}


/* ===================================================================================================
   ROLE MAP: existing template selectors → ramp roles. The size lines were deleted from their source
   files, so this is the one source of truth. Course pages need #main to beat their inline styles.
   =================================================================================================== */

/* HOME HERO (#main: every page's <main> carries id="main", so the hero group's #main h1 would otherwise win) */
.nh-hero h1, #main .nh-hero h1{font-size:var(--role-hero-home);line-height:var(--lh-display);letter-spacing:var(--tr-display);max-width:16ch}

/* PAGE / PRODUCT HEROES */
.phero h1, .display, .h1, main.pdp .pdp-h1, .pp-h1, .ovhero h1, .evhero h1, .evp2 h1, .lh-title,
#main h1, #main .chero__copy h1, .chero--single .chero__copy h1{
  font-size:var(--role-hero);line-height:var(--lh-display);letter-spacing:var(--tr-display);font-weight:600}

/* CLOSING H2s that borrow a hero class (plans/*, academy/gtm-engineering, academy/infinite-analytics use
   <h2 class="display">; membership uses <h2 class="h1">). Without this rule they would equal the 64px hero. */
:is(h2,h3):is(.display,.h1){font-size:var(--role-section);line-height:var(--lh-head);letter-spacing:var(--tr-title)}

/* HOME CHAPTER OPENER + HOME CLOSE (home only; the home hero is 96, so 64 stays below it) */
#main .nh-close h2, #main .nh-access h2, .nh-close h2, .nh-access h2{font-size:var(--role-section);line-height:var(--lh-head);letter-spacing:var(--tr-title)}   /* below the 64px home hero */

/* SECTION H2 */
.h2, .frow__copy h2, .ctaband h2, main.pdp h2.h2, .pp-h2, .sec-head h2, #main .h2, #main .sec-head :is(h2,.h2),
.nh-chal h2, .nh-how h2, .nh-ltr__body h2, .nh-faq h2, .evband h2, .arcband h2, .cch h2{
  font-size:var(--role-section);line-height:var(--lh-head);letter-spacing:var(--tr-title)}

/* ROW / PANEL HEADINGS */
.prose h2, .aeo h2, .cx-title, .rost__ph h3, .osx__title, .rolepanel h3, .liccard h3{
  font-size:var(--role-row);line-height:var(--lh-head);letter-spacing:var(--tr-title)}

/* CARD H3 */
.h3, main.pdp .pdp-card__title, .course h3, .dmode h3, .bene__card h3, .tile h3, .step h3, .sstep h3,
.lib-card__title, .evcl__c h3, .evsp h3, .evcard__t, .evcard--feat .evcard__t, .evx h3, .evpspk h3, .evx__h, .evc__t,
.mcard h3, .rh-card__title, .jx-title, .tier h3, .stack-card__body h3, .share h3, main.pdp .pdp-fit__col h3,
.pp-plan__name, .cert-prev h3, .nh-chal h3, .nh-step h3{
  font-size:var(--role-card);line-height:var(--lh-head);letter-spacing:var(--tr-title)}

/* DENSE / H4 */
.pp-qa__q, main.pdp .pdp-qa__q, .rcard__h b, #rivet-footer .ftr__join-h, .lib-modal__title, .rf-title, .rfa__title{
  font-size:var(--role-dense);line-height:var(--lh-head);letter-spacing:0}

/* LEADS */
.nh-sub, .lh-sub, main.pdp .pdp-hero .lead, .evp2__lead, .phero .lead, .ovhero .lead, .pp-phero .pp-lead, .chero__copy .lead{
  font-size:var(--role-lead-hero);line-height:var(--lh-text)}
.lead, .pp-lead, .nh-ltr__body p, .nh-chal__sub, .nh-how__sub, .nh-access__sub, .nh-close__sub, .nh-faq__sub{font-size:var(--role-lead);line-height:var(--lh-text)}
#main{--t-lead:clamp(1rem, 0.9452rem + 0.2247vw, 1.125rem)}  /* course pages reuse --t-lead; this keeps it valid */

/* legal and article prose: 16 on phones (the one exception to mobile body 14) */
.prose p, .prose li{font-size:var(--t-lead)}

/* SMALL card copy */
.tile p, .course p, .course li, .dmode p, .rcard p, .pp-plan__for, .pp-plan__fine, .pp-plan__note{font-size:var(--t-small);line-height:var(--lh-small)}

/* EYEBROWS: one style everywhere (plain, no outlined pill, no flanking lines) */
.eyebrow, .pp-eyebrow, .lh-eyebrow, .nh-eyebrow, .ovpill__in, .evp2__mark, .chero__k, .prereq__k, .trkcard__k,
.aspine__k, .ceil__k, .gstage__tag, .alane__k, .cch__k, .nacc__k, .rost__k, .bcell__k, .pp-plan__k, .pp-plan__plus,
.nh-chal__k, .nh-how__k, .nh-access__k, .nh-ltr__k, .nh-faq__k, .nh-close__k{  /* named: data-reveal appends "in" */
  font:500 var(--t-meta)/var(--lh-meta) var(--font-mono);letter-spacing:var(--tr-label);text-transform:uppercase}
.ovpill{border:0;padding:0;background:none;border-radius:0;overflow:visible}   /* the outlined pill becomes the plain eyebrow */
.ovpill::before{content:none;animation:none}
.ovpill__in{padding:0;background:none;border-radius:0}

/* MICRO: badges and tags (lift the 9.9px and 10.9px ones) */
.dmode__tag, .lvl-badge, .tag, .rcard__lv, .pp-ticks small{font:500 var(--t-micro)/var(--lh-micro) var(--font-mono);letter-spacing:var(--tr-label);text-transform:uppercase}

/* STATS AND PRICES */
.statrow dt, .statrow strong, .benchcard__k, .figures dt, .rtile__k, .proofstrip__stat strong, .stat-tile strong,
.rolemetric__k, .impact__big strong, .moat2__big, .proofstat b{font:500 var(--role-stat)/1.05 var(--font-mono);letter-spacing:var(--tr-title);font-variant-numeric:tabular-nums}
.pp-plan__price b, .tier__price strong, .price__cur, main .b2b-card .b2b-card__price{  /* .valuecard__total strong is copy, not a price: left alone */
  font:500 var(--role-price)/1.05 var(--font-mono);letter-spacing:var(--tr-title);font-variant-numeric:tabular-nums}

/* QUOTES */
.gradquote blockquote, .quoteblock blockquote{font-size:var(--t-h2);line-height:1.3;letter-spacing:var(--tr-title)}

/* ARABIC on the role map: Almarai on every heading and label, no negative tracking, no forced caps,
   and the brand heading line-height so Arabic ascenders are not clipped. Numerals stay Plex Mono. */
:lang(ar) :is(h1,h2,h3,h4){font-family:var(--font-ar);letter-spacing:0}
:lang(ar) :is(.eyebrow,.pp-eyebrow,.lh-eyebrow,.nh-eyebrow,.ovpill__in,.evp2__mark,.chero__k,.prereq__k,.trkcard__k,
  .aspine__k,.ceil__k,.gstage__tag,.alane__k,.cch__k,.nacc__k,.rost__k,.bcell__k,.pp-plan__k,.pp-plan__plus,
  .dmode__tag,.lvl-badge,.tag,.rcard__lv,.pp-ticks small,
  .nh-chal__k,.nh-how__k,.nh-access__k,.nh-ltr__k,.nh-faq__k,.nh-close__k){
  font-family:var(--font-ar);letter-spacing:0;text-transform:none}
:lang(ar) :is(.nh-hero h1,.phero h1,.display,.h1,main.pdp .pdp-h1,.pp-h1,.ovhero h1,.evhero h1,.evp2 h1,.lh-title,
  #main h1,.nh-close h2,.nh-access h2){line-height:var(--lh-head)}
