/* GENERATED by thethingsnetwork-v2 platform/scripts/export-brand-tokens.mjs — do not edit here.
   Sources: app/styles/colors_and_type.css (fonts, tokens, eyebrow, motion), app/styles/site.css (.tn-wrap),
   app/styles/page-header.css (page header). Contract: docs/brand-page-header.md. */

/* ---------- 1. Fonts ---------- */
@font-face {
  font-family: 'Inter';
  font-weight: 300;
  font-style: normal;
  font-display: swap;
  src: url('/device-repository/assets/fonts/Inter-Light.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url('/device-repository/assets/fonts/Inter-Regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  src: url('/device-repository/assets/fonts/Inter-Medium.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  src: url('/device-repository/assets/fonts/Inter-SemiBold.woff2') format('woff2');
}
@font-face {
  font-family: 'Poppins';
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  src: url('/device-repository/assets/fonts/Poppins-SemiBold.woff2') format('woff2');
}

/* ---------- 2. Tokens ---------- */
:root {
  /* ===== TTI BRAND BLUE (primary scale, 2024 palette) ===== */
  --tti-025: #F8FCFF;
  --tti-050: #F0F7FF;
  --tti-075: #E8F1FF;
  --tti-100: #D8E7FF;
  --tti-200: #99BEFF;
  --tti-300: #6699FF;
  --tti-400: #3F7AFF;
  --tti-500: #0047FF;  /* primary */
  --tti-600: #0036DB;
  --tti-700: #0028B7;
  --tti-800: #001C93;
  --tti-900: #00147A;
  --tti-1000: #00095C;
  --tti-1025: #00064B;
  --tti-1050: #000536;  /* colors.md 2026-10-14: the midpoint of 1025 and 1075 (was #000338) */
  --tti-1075: #000321;

  /* ===== THE THINGS NETWORK — ttn scale (colors.md). The site's own TTN tokens below
     (--ttn-primary*, --tn-*) predate the scale and keep their values; new work picks steps from
     here. --ttn-500 = --ttn-primary. ===== */
  --ttn-025: #F7FDFF;
  --ttn-050: #EAFAFF;
  --ttn-075: #DEF8FF;
  --ttn-100: #CBF3FF;
  --ttn-200: #A8E7FF;
  --ttn-300: #7CD4FF;
  --ttn-400: #5CC0FF;
  --ttn-500: #26A0FF;  /* primary */
  --ttn-600: #1B7CDB;
  --ttn-700: #135DB7;
  --ttn-800: #0C4193;
  --ttn-900: #012B6B;
  --ttn-1000: #011B4D;
  --ttn-1025: #00123D;
  --ttn-1050: #020D2D;
  --ttn-1075: #00091A;

  /* ===== NEUTRALS (grey scale) ===== */
  --grey-025: #FBFCFD;
  --grey-050: #F3F5F8;
  --grey-075: #EBEEF3;
  --grey-100: #DEE3EA;
  --grey-200: #D2D7E0;
  --grey-300: #C3C9D4;
  --grey-400: #B2BAC8;
  --grey-500: #98A4B6;
  --grey-600: #7887A1;
  --grey-700: #536482;
  --grey-800: #354661;
  --grey-900: #1C293F;
  --grey-1000: #0C1525;
  --grey-1025: #09101B;
  --grey-1050: #080D15;
  --grey-1075: #06090D;

  /* ===== SEMANTIC — info / success / error / warning / caution (colors.md, full scales).
     025–100 surfaces, 500 fills and icons, 700–900 text on a light surface. ===== */
  --info-025: #F7FCFF;
  --info-050: #EFFAFF;
  --info-075: #E3F6FF;
  --info-100: #CCEEFF;
  --info-200: #99D8FF;
  --info-300: #66BDFF;
  --info-400: #3FA4FF;
  --info-500: #007AFF;
  --info-600: #005EDB;
  --info-700: #0046B7;
  --info-800: #003193;
  --info-900: #002074;
  --info-1000: #000F4F;
  --info-1025: #000B3A;
  --info-1050: #00082A;
  --info-1075: #00051F;

  --success-025: #F7FFF7;
  --success-050: #EAFFEA;
  --success-075: #DEFFD4;
  --success-100: #CFFFC2;
  --success-200: #B3FAA9;
  --success-300: #7EF07B;
  --success-400: #58E160;
  --success-500: #27CD41;
  --success-600: #1CB041;
  --success-700: #13933F;
  --success-800: #0C763B;
  --success-900: #00572E;
  --success-1000: #002C17;
  --success-1025: #001C0E;
  --success-1050: #00130A;
  --success-1075: #000D07;

  --error-025: #FFFAFA;
  --error-050: #FFF5F5;
  --error-075: #FFEEEE;
  --error-100: #FFE2DE;
  --error-200: #FFD1CA;
  --error-300: #FFA497;
  --error-400: #FF6C63;
  --error-500: #FF3B30;
  --error-600: #DB2328;
  --error-700: #B7182A;
  --error-800: #930F29;
  --error-900: #6E071B;
  --error-1000: #45030F;
  --error-1025: #2D0109;
  --error-1050: #1D0003;
  --error-1075: #110002;

  --warning-025: #FFFCF3;
  --warning-050: #FFF9E6;
  --warning-075: #FFF4D4;
  --warning-100: #FFEEBC;
  --warning-200: #FFE096;
  --warning-300: #FFCC66;
  --warning-400: #FFB73F;
  --warning-500: #FF9500;
  --warning-600: #DB7600;
  --warning-700: #B75B00;
  --warning-800: #934300;
  --warning-900: #6E2D00;
  --warning-1000: #391700;
  --warning-1025: #210D00;
  --warning-1050: #160900;
  --warning-1075: #0D0500;

  --caution-025: #FFFDEC;
  --caution-050: #FFFAD9;
  --caution-075: #FFF5B7;
  --caution-100: #FFF09C;
  --caution-200: #FFEC7D;
  --caution-300: #FFE666;
  --caution-400: #FFDC3F;
  --caution-500: #FFCC00;  /* fill only: caution-300…500 never carry text */
  --caution-600: #DBAA00;
  --caution-700: #B78B00;
  --caution-800: #936D00;
  --caution-900: #755400;
  --caution-1000: #3B2A00;
  --caution-1025: #281D00;
  --caution-1050: #161100;
  --caution-1075: #0E0C00;

  /* ===== SIBLING BRANDS ===== */
  --ttn-primary:   #26A0FF;   /* The Things Network */
  --ttn-primary-600: #008DF9;
  --ttn-primary-dark: #001859;
  --tts-primary:   #1E5DFF;   /* The Things Stack */
  --tts-primary-600: #194FDA;
  --ttc-primary:   #0001FF;   /* The Things Conference */
  --gn-primary:    #6514FF;   /* Generic Node */

  --bone: #F7F6F1; /* 'secret' off-white from the brand palette */

  /* ===== TTN SURFACE ALIASES (were scoped to .tn-site in site.css; on :root since the brand
     harmonization so page-header.css and the exported ttn-tokens.css need no .tn-site scope).
     Values unchanged. ===== */
  --tn-blue: var(--ttn-primary);          /* buttons, fills, card hover borders */
  --tn-blue-600: var(--ttn-primary-600);  /* button hover */
  --tn-blue-700: #0071c7;                 /* eyebrow, badge and tile text on the --tti-050 band (4.65:1);
                                             only 4.48:1 on --tn-tint, so not for small text there */
  --tn-navy: var(--ttn-primary-dark);     /* headings, dark chapters */
  --tn-navy-900: #00103f;
  --tn-ink: #000e36;                      /* footer */
  --tn-tint: #e6f4ff;
  --tn-muted-invert: #aebbd3;             /* secondary text on navy/ink */
  /* The one highlighted word of a display title on a light surface (page header <em>). --ttn-500 is
     2.6:1 on the --tti-050 band and fails WCAG AA even for large text; --ttn-600 is 3.9:1 (AA large
     text needs 3:1; the title is 32px+ SemiBold). */
  --tn-highlight: var(--ttn-600);

  /* ===== LINKS (colors.md "Usage rules", owner 2026-10-14) =====
     Text links only: tti-500 on light surfaces (6.3:1 on white, 5.8:1 on --tti-050, 5.8:1 on
     --grey-050), tti-300 on dark ones (5.9:1 on --tn-navy, 6.8:1 on --tn-ink). Buttons and fills keep
     the ttn palette; navigation (header, footer columns, tabs, breadcrumbs) is not a text link and
     stays neutral. */
  --link: var(--tti-500);
  --link-hover: var(--tti-600);           /* 8.2:1 on white */
  --link-on-dark: var(--tti-300);
  --link-on-dark-hover: var(--tti-200);   /* 8.8:1 on --tn-navy */

  /* ===== FOCUS (owner 2026-10-14: one ring everywhere, exported to the docs and device repository) =====
     A 2px white gap + a 2px tti-500 ring: 5.8:1 on the --tti-050 band, 6.3:1 on white, and the white gap
     keeps it visible next to a --tn-blue fill (tti-500 alone is 2.3:1 there). WCAG 1.4.11 needs 3:1.
     On dark surfaces (navy, ink): the surface-coloured gap + a tti-300 ring (5.9:1 on --tn-navy). */
  --focus-ring: 0 0 0 2px #fff, 0 0 0 4px var(--tti-500);
  --focus-ring-on-dark: 0 0 0 2px var(--tn-navy), 0 0 0 4px var(--tti-300);

  /* ===== SEMANTIC TOKENS (TTI brand defaults) ===== */
  /* Text */
  --c-text-heavy:     var(--grey-900);  /* default body text */
  --c-text-semilight: var(--grey-700);
  --c-text-light:     var(--grey-600);  /* lower hierarchy */
  --c-text-extralight: var(--grey-400);
  --c-text-invert:    #ffffff;
  --c-text-brand:     var(--tti-500);
  --c-text-brand-hover: var(--tti-600);
  --c-text-brand-active: var(--tti-700);
  --c-text-success:   var(--success-700);
  --c-text-warning:   var(--warning-700);
  --c-text-error:     var(--error-600);
  --c-text-info:      var(--info-600);

  /* Backgrounds */
  --c-bg-page:         #ffffff;
  --c-bg-subtle:       var(--grey-025);
  --c-bg-neutral-light: var(--grey-050);
  --c-bg-neutral-semilight: var(--grey-075);
  --c-bg-brand-extralight: var(--tti-025);
  --c-bg-brand-light:  var(--tti-050);
  --c-bg-brand-semilight: var(--tti-075);
  --c-bg-brand:        var(--tti-500);
  --c-bg-brand-hover:  var(--tti-600);
  --c-bg-brand-dark:   var(--tti-1050);
  --c-bg-inverse:      var(--grey-1000);

  /* Borders */
  --c-border-extralight: var(--grey-050);
  --c-border-light:      var(--grey-100);
  --c-border-normal:     var(--grey-200);
  --c-border-semibold:   var(--grey-500);
  --c-border-bold:       var(--grey-700);
  --c-border-brand:      var(--tti-500);

  /* ===== TYPOGRAPHY ===== */
  --font-display: 'Poppins', -apple-system,
    BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
    'Liberation Mono', monospace;

  /* Font scale (rem-based, base 15px) */
  --fs-xxs: 0.5rem;    /* 7.5 */
  --fs-xs:  0.75rem;   /* 11.25 */
  --fs-s:   0.875rem;  /* 13.125 */
  --fs-m:   1rem;      /* 15 */
  --fs-l:   1.25rem;   /* 18.75 */
  --fs-xl:  1.563rem;  /* 23.4 */
  --fs-xxl: 1.875rem;  /* 28 */
  --fs-xl3: 2.5rem;    /* 37.5 */
  --fs-xl4: 3rem;      /* 45 */
  --fs-xl5: 4rem;      /* 60 */
  --fs-xl6: 5rem;      /* 75 */

  /* Responsive page-hero display sizes (clamp-based) — keep tool heroes the
     same size so the title doesn't jump when navigating between tools. */
  --fs-display:    clamp(2.4rem, 5.5vw, 4rem);    /* standard tool-landing hero H1 */
  --fs-display-lg: clamp(3rem, 8vw, 6rem);        /* flagship hero (Community front door) */
  --fs-lede:       clamp(1.05rem, 1.6vw, 1.3rem); /* hero sub-headline */

  /* Line-heights: typography.md (brand 2026-10). No element inherits more than 1.5; only
     deliberate long-form copy (article and help bodies) sets its own looser value. */
  --lh-xxs: 1.1;   /* display, H1 */
  --lh-xs:  1.2;   /* labels, buttons; Label / Small 13/16, Label / Medium 14/17. Card titles use
                      H4 24/34 or H5 21/29, not this token */
  --lh-s:   1.5;   /* Body / Small 14/21 */
  --lh-m:   1.4;   /* Body / Default 15/21 (was 1.687) */
  --lh-l:   1.4;   /* Body / Large 17/24, Body / XL 18/25 (was 1.875) */
  --lh-xl:  1.5;   /* Body / XS 13/20, capped at 1.5 (was 2) */

  /* Font weights. 600 is the heaviest weight in the system (typography.md): headings are Poppins
     SemiBold 600, inline emphasis Inter SemiBold 600. There is no 700. */
  --fw-light: 300;
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-bold: 600;
  --fw-heading: 600;

  /* Type styles (typography.md, brand 2026-10), in px: the root font-size is 15px (14px on phones), so
     rem would fall off the scale. Display and H2 step down at the tablet (≤ 1200px) and mobile
     (≤ 700px) breakpoints in the @media blocks after this :root. Display = the page's h1 (hero, page
     header); headings are Poppins 600, body and labels Inter, tracking 0 on everything in Inter. */
  --type-display-size: 68px;
  --type-display-lh: 68px;
  --type-display-track: -0.03em;
  --type-h2-size: 48px;
  --type-h2-lh: 58px;
  --type-h2-track: -0.02em;
  --type-h3-size: 30px;
  --type-h3-lh: 36px;
  --type-h3-track: -0.02em;
  --type-h4-size: 24px;      /* card titles */
  --type-h4-lh: 34px;
  --type-h4-track: -0.05em;
  --type-h5-size: 21px;      /* card titles */
  --type-h5-lh: 29px;
  --type-h5-track: 0em;
  --type-h6-size: 16px;
  --type-h6-lh: 21px;
  --type-h6-track: 0em;
  --type-body-xl-size: 18px; /* ledes */
  --type-body-xl-lh: 25px;
  --type-body-l-size: 17px;
  --type-body-l-lh: 24px;
  --type-body-m-size: 16px;
  --type-body-m-lh: 22px;
  --type-body-size: 15px;    /* Body / Default, Medium 500 */
  --type-body-lh: 21px;
  --type-body-s-size: 14px;
  --type-body-s-lh: 21px;
  --type-body-xs-size: 13px;
  --type-body-xs-lh: 20px;
  --type-label-l-size: 15px; /* buttons */
  --type-label-l-lh: 21px;
  --type-label-m-size: 14px; /* nav, tabs */
  --type-label-m-lh: 17px;
  --type-label-s-size: 13px; /* eyebrows, tags, stat labels, breadcrumbs */
  --type-label-s-lh: 16px;

  /* Letter spacing */
  --lsp-s: -0.03em;
  --lsp-m: -0.02em;
  --lsp-l: 0em;

  /* ===== SPACING (component + layout) ===== */
  --cs-xxs: 0.25rem;
  --cs-xs:  0.5rem;
  --cs-s:   0.75rem;
  --cs-m:   1rem;
  --cs-l:   1.25rem;
  --cs-xl:  1.5rem;
  --cs-xxl: 2rem;
  --cs-xl3: 3rem;

  --ls-xxs: 1rem;
  --ls-xs:  1.25rem;
  --ls-s:   2rem;
  --ls-m:   3rem;
  --ls-l:   5rem;
  --ls-xl:  6.25rem;
  --ls-xxl: 10rem;
  --ls-xl3: 12.5rem;

  /* ===== RADII ===== brand guidelines §11, on the 8px grid. In px on purpose: the root
     font-size is 15px (14px on phones), so rem values would fall off the grid.
     8px is the default for buttons, inputs, cards and controls; 16px only for large panels,
     banners and dialogs. Buttons are never pill-shaped. --br-full ONLY for badges, tags,
     status dots, avatars, progress bars and scrollbar thumbs. */
  --br-s: 8px;         /* small controls, icon tiles, menu items (was 4.5px) */
  --br-m: 8px;         /* buttons, inputs, segmented controls (was 9px) */
  --br-l: 8px;         /* cards (was 13.5px) */
  --br-xl: 16px;       /* large panels, banners, dialogs (was 18.75px) */
  --br-xxl: 16px;      /* large panels, banners (was the 45px CTA pill) */
  --br-full: 999px;    /* badges, tags, status dots, avatars, progress bars, scrollbar thumbs */

  /* ===== SHADOWS ===== */
  --bs-s: 0 0.2rem 1rem 0 rgba(0, 0, 0, 0.05);
  --bs-m: 0 0 1rem 0 rgba(0, 0, 0, 0.1);
  --bs-l: 0 0 2.5rem 0 rgba(0, 0, 0, 0.1);
  --bs-xl: 0 0 5rem 0 rgba(0, 0, 0, 0.1);

  /* ===== MOTION ===== */
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --dur-instant: 80ms;
  --dur-fast: 140ms;
  --dur-base: 220ms;
  --dur-slow: 400ms;
}

/* ---------- 3. Responsive type steps ---------- */
@media (max-width: 1200px) {
  :root {
    --type-display-size: 56px;
    --type-display-lh: 56px;
    --type-h2-size: 40px;
    --type-h2-lh: 48px;
  }
}

@media (max-width: 700px) {
  :root {
    --type-display-size: 32px;
    --type-display-lh: 34px;
    --type-display-track: -0.025em;
    --type-h2-size: 32px;
    --type-h2-lh: 38px;
  }
}

/* ---------- 4. Content column ---------- */
.tn-wrap {
  max-width: 1200px;
  margin-inline: auto;
  padding-inline: 24px;
}

/* ---------- 5. Eyebrow (Inter Label / Small 13/16 600, sentence case; at most one per view) ---------- */
.tn-eyebrow {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--type-label-s-size);
  font-weight: 600;
  line-height: var(--type-label-s-lh);
  letter-spacing: 0;
  color: var(--tn-blue-700);
}

/* ---------- 6. Text links (zero specificity: point the host's own link rules at --link too) ---------- */
:where(a) {
  color: var(--link);
}

:where(a:hover) {
  color: var(--link-hover);
}

/* ---------- 7. Motion ---------- */
:where(a, button, summary, select, input, textarea, label[for], [role="button"], [role="tab"]) {
  transition-property: color, background-color, border-color, box-shadow;
  transition-duration: var(--dur-fast);
  transition-timing-function: var(--ease-standard);
}

:where([role="tab"]) {
  transition-duration: var(--dur-base);
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto !important;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition-property: color, background-color, border-color, box-shadow, opacity !important;
  }
}

/* ---------- 8. Page header (app/styles/page-header.css) ---------- */
/* Page header (tn-ph): the top band of every page except the homepage hero, modelled on /community.
   ONE source for three platforms: the app (app/components/site/PageHeader.tsx imports this file) and,
   copied byte-for-byte by scripts/export-brand-tokens.mjs into ttn-tokens.css, the Hugo docs and device
   repository. The contract (markup, variants, which page uses which) is docs/brand-page-header.md.
   Depends ONLY on the tokens in colors_and_type.css (:root) and .tn-wrap; no .tn-site scope, no host
   styles. Every class is prefixed tn-ph. Spacing is on the 8px grid. */

/* ---------- Band ---------- */
.tn-ph {
  border-bottom: 1px solid var(--grey-100);
  background: var(--tti-050);
  color: var(--grey-900);
  font-family: var(--font-body);
}

/* Host resets: the elements inside never inherit a host's margins (Hugo themes, the app's global p),
   and no host `a:hover { text-decoration: underline }` reaches the header's links. */
.tn-ph :where(p, h1, ol, ul, dl, dd, figure) {
  margin: 0;
}

.tn-ph a,
.tn-ph a:hover,
.tn-ph-subnav a,
.tn-ph-subnav a:hover {
  text-decoration: none;
}

/* Sits on .tn-wrap (1200px, 24px gutters). Stack: crumbs → body (main [+ aside]) → stats → tabs, 24px apart. */
.tn-ph__inner {
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding-block: 56px 48px;
}

/* ---------- Breadcrumbs ---------- */
.tn-ph__crumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 0;
  list-style: none;
  color: var(--grey-700);
  font-size: var(--type-label-s-size);
  font-weight: 500;
  line-height: var(--type-label-s-lh);
}

.tn-ph__crumbs li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.tn-ph__crumbs li + li::before {
  content: "/";
  color: var(--grey-400);
}

/* Breadcrumbs are navigation: neutral, the link colour only on hover. */
.tn-ph__crumbs a {
  color: var(--grey-700);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-standard);
}

.tn-ph__crumbs a:hover {
  color: var(--link);
}

.tn-ph__crumbs [aria-current="page"] {
  overflow: hidden;
  color: var(--grey-900);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- Body: main column (+ optional aside) ---------- */
.tn-ph--aside .tn-ph__body {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  align-items: center;
  gap: 48px;
}

/* Media → eyebrow → title → lede → meta → actions → note, 16px apart (24px before the actions). */
.tn-ph__main {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  min-width: 0;
}

/* A logo, monogram or vendor mark above the title, at its own size. */
.tn-ph__media {
  max-width: 100%;
}

.tn-ph__media img {
  display: block;
  max-width: 100%;
  height: auto;
}

/* A cover image (community hub): the full column width, 4:1, large-panel radius. */
.tn-ph__media--cover {
  align-self: stretch;
}

.tn-ph__media--cover img {
  width: 100%;
  aspect-ratio: 4 / 1;
  border-radius: var(--br-xl);
  object-fit: cover;
}

/* The eyebrow is the merged .tn-eyebrow (Inter 13/16 600, sentence case); this adds the status dot. */
.tn-ph__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.tn-ph__dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: var(--br-full);
  background: var(--success-500);
  box-shadow: 0 0 0 4px rgb(39 205 65 / 18%);
}

/* Display (typography.md): Poppins SemiBold 600, 68/68 → 56/56 → 32/34 via the --type-display-* tokens.
   The page's only h1. One word may be highlighted with <em>. */
.tn-ph__title {
  max-width: 100%;
  color: var(--tn-navy);
  font-family: var(--font-display);
  font-size: var(--type-display-size);
  font-style: normal;
  font-weight: 600;
  line-height: var(--type-display-lh);
  letter-spacing: var(--type-display-track);
  text-wrap: balance;
  overflow-wrap: break-word;
}

.tn-ph__title em {
  color: var(--tn-highlight);
  font-style: normal;
}

/* A trademark sign (LoRaWAN®) in a title: small and raised, never at Display size, and without
   stretching the line box. */
.tn-ph__title sup {
  font-size: 0.4em;
  line-height: 0;
  vertical-align: 0.9em;
}

/* Body / XL 18/25 Regular. */
.tn-ph__lede {
  max-width: 60ch;
  color: var(--grey-700);
  font-size: var(--type-body-xl-size);
  font-weight: 400;
  line-height: var(--type-body-xl-lh);
  text-wrap: pretty;
}

/* A link inside the lede is underlined (WCAG 1.4.1: never colour alone), also on hover. */
.tn-ph__lede a,
.tn-ph__lede a:hover {
  color: var(--link);
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.tn-ph__lede a:hover {
  color: var(--link-hover);
}

/* Badges, tags or quick facts. */
.tn-ph__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

/* Buttons, or a search form (which may take the full column width). */
.tn-ph__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-self: stretch;
  gap: 16px;
  margin-top: 8px;
}

/* One short line under the actions: a hint, a source, an "as of" date. Body / Small. */
.tn-ph__note {
  color: var(--grey-700);
  font-size: var(--type-body-s-size);
  line-height: var(--type-body-s-lh);
}

.tn-ph__note a {
  color: var(--link);
  font-weight: 600;
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-standard);
}

.tn-ph__note a:hover {
  color: var(--link-hover);
}

/* A right-hand visual (device photo, illustration). Stacks under the main column at ≤ 960px. */
.tn-ph__aside {
  min-width: 0;
}

.tn-ph__aside img {
  display: block;
  max-width: 100%;
  height: auto;
}

/* ---------- Stat tiles ---------- */
.tn-ph__stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 140px), 1fr));
  gap: 16px;
}

/* dt before dd in the markup (valid HTML), value above label on screen. */
.tn-ph__stat {
  position: relative;
  display: flex;
  flex-direction: column-reverse;
  justify-content: flex-end;
  gap: 4px;
  padding: 16px;
  border: 1px solid var(--grey-100);
  border-radius: var(--br-l);
  background: #fff;
  transition:
    border-color var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard);
}

/* Label / Small 13/16 Medium. */
.tn-ph__stat dt {
  color: var(--grey-700);
  font-size: var(--type-label-s-size);
  font-weight: 500;
  line-height: var(--type-label-s-lh);
}

/* H3 30/36 Poppins SemiBold, tabular figures. */
.tn-ph__stat dd {
  color: var(--tn-navy);
  font-family: var(--font-display);
  font-size: var(--type-h3-size);
  font-weight: 600;
  line-height: var(--type-h3-lh);
  letter-spacing: var(--type-h3-track);
  font-variant-numeric: tabular-nums;
}

/* A stat that is not a number ("EU868", "Free"): Body / XL in Inter, so it doesn't pose as a count. */
.tn-ph__stat dd.tn-ph__stat-text {
  font-family: var(--font-body);
  font-size: var(--type-body-xl-size);
  font-weight: 600;
  line-height: 36px;
  letter-spacing: 0;
}

/* A linked stat: the value is the link, stretched over the whole tile. */
.tn-ph__stat a {
  color: inherit;
  text-decoration: none;
}

.tn-ph__stat a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.tn-ph__stat:has(a:hover) {
  border-color: var(--tn-blue);
  box-shadow: var(--bs-m);
}

.tn-ph__stat a:focus-visible {
  outline: none;
}

.tn-ph__stat:has(a:focus-visible) {
  box-shadow: var(--focus-ring);
}

/* ---------- Tabs (sections of the same page family, e.g. a hub's Overview / Posts) ---------- */
.tn-ph--tabs .tn-ph__inner {
  padding-bottom: 0;
}

/* -1px: the current tab's underline sits on the band's bottom border. */
.tn-ph__tabs {
  display: flex;
  gap: 8px;
  margin-bottom: -1px;
  overflow-x: auto;
  scrollbar-width: none;
}

.tn-ph__tab {
  padding: 12px 16px;
  border-bottom: 2px solid transparent;
  color: var(--grey-700);
  font-size: var(--type-label-m-size);
  font-weight: 500;
  line-height: var(--type-label-m-lh);
  text-decoration: none;
  white-space: nowrap;
  transition:
    color var(--dur-base) var(--ease-standard),
    border-color var(--dur-base) var(--ease-standard);
}

.tn-ph__tab:hover {
  color: var(--grey-900);
}

.tn-ph__tab[aria-current="page"] {
  border-bottom-color: var(--tn-highlight);
  color: var(--tn-navy);
  font-weight: 600;
}

/* ---------- Inset variant: a header inside a content column (docs articles beside the sidebar) ----------
   No band, no wrap, no outer padding; the title takes the H2 style (48/58 → 40/48 → 32/38), because
   Display is reserved for a page's hero (typography.md "Usage rules"). */
.tn-ph--inset {
  border-bottom: 0;
  background: none;
}

.tn-ph--inset .tn-ph__inner {
  padding-block: 0 32px;
}

.tn-ph--inset .tn-ph__title {
  font-size: var(--type-h2-size);
  line-height: var(--type-h2-lh);
  letter-spacing: var(--type-h2-track);
}

/* ---------- Sub-navigation bar above the band (a section's own nav, e.g. the device repository) ---------- */
.tn-ph-subnav {
  border-bottom: 1px solid var(--grey-100);
  background: #fff;
  color: var(--grey-900);
  font-family: var(--font-body);
}

.tn-ph-subnav__bar {
  display: flex;
  align-items: center;
  gap: 32px;
  min-height: 56px;
}

.tn-ph-subnav__title {
  flex: none;
  color: var(--tn-navy);
  font-size: var(--type-label-l-size);
  font-weight: 600;
  line-height: var(--type-label-l-lh);
  text-decoration: none;
}

.tn-ph-subnav__title:hover {
  color: var(--tn-navy);
}

.tn-ph-subnav__nav {
  display: flex;
  align-self: stretch;
  gap: 8px;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}

.tn-ph-subnav__link {
  display: inline-flex;
  align-items: center;
  margin-bottom: -1px;
  padding-inline: 8px;
  border-bottom: 2px solid transparent;
  color: var(--grey-700);
  font-size: var(--type-label-m-size);
  font-weight: 500;
  line-height: var(--type-label-m-lh);
  text-decoration: none;
  white-space: nowrap;
  transition:
    color var(--dur-base) var(--ease-standard),
    border-color var(--dur-base) var(--ease-standard);
}

.tn-ph-subnav__link:hover {
  color: var(--grey-900);
}

.tn-ph-subnav__link[aria-current="page"] {
  border-bottom-color: var(--tn-highlight);
  color: var(--tn-navy);
  font-weight: 600;
}

.tn-ph-subnav__tools {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  .tn-ph--aside .tn-ph__body {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }
}

@media (max-width: 700px) {
  /* The counts step down with the title (Display 32px here), so they never rival it. */
  .tn-ph__stat dd,
  .tn-ph__stat dd.tn-ph__stat-text {
    line-height: 32px;
  }

  .tn-ph__stat dd {
    font-size: var(--type-h4-size);
  }

  /* Phones: title, tabs and tools wrap onto their own rows, with room between them; the tab text lines
     up with the title and each tab stays a 40px target. */
  .tn-ph-subnav__bar {
    flex-wrap: wrap;
    gap: 4px 16px;
    padding-block: 12px 0;
  }

  .tn-ph-subnav__nav {
    margin-inline-start: -8px;
  }

  .tn-ph-subnav__link {
    min-height: 40px;
  }

  .tn-ph-subnav__tools {
    flex-basis: 100%;
    margin-left: 0;
    padding-block: 8px 12px;
  }
}
