/* Design system, concatenated.
 *
 * Generated by tools/bundle-ds-css.mjs — do not edit. Edit the eleven files
 * under this directory and regenerate.
 *
 * Order is styles.css's @import order, which is what decided the cascade when
 * these were eleven separate <link> tags. reset.css therefore still applies
 * last, which is what the pages depend on for the focus ring, text-wrap and
 * img { display: block }.
 *
 * 10 files, in this order:
 *   tokens/fonts.css
 *   tokens/colors.css
 *   tokens/typography.css
 *   tokens/spacing.css
 *   tokens/radius.css
 *   tokens/elevation.css
 *   tokens/motion.css
 *   tokens/layout.css
 *   tokens/patterns.css
 *   base/reset.css
 */

/* ===== tokens/fonts.css ===== */
/* Archivo and Caveat, self-hosted from 2026-08-09.
 *
 * These were an @import of fonts.googleapis.com at the top of this file, which
 * made them the most expensive thing on the page: a third hop (HTML -> this
 * file -> googleapis -> gstatic) and, once the eleven sheets became one,
 * 750 ms of the 1,780 ms of render-blocking time for 1.3 KB of CSS.
 *
 * Google's own variable woff2, latin and latin-ext subsets only — the seven
 * other subsets it serves are for scripts this site never sets. unicode-range
 * means a visitor downloads only the subset their text needs.
 *
 * Archivo carries both axes, verified with fontTools: wght 100-900 and
 * wdth 62-125. The wdth axis is load-bearing — font-stretch: 88% appears on 87
 * elements, and against a font without that axis it silently does nothing and
 * every line of display type gets about 10% wider.
 * Descriptors below are Google's, copied exactly. The pixel harness is what
 * proves it: 0 deltas or this is wrong.
 */
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 500 900;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url("/fonts/Archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 500 900;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url("/fonts/Archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Caveat";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("/fonts/Caveat-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Caveat";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("/fonts/Caveat-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Type loading for the RamX design system.

   All four families are served from this repo. Nothing comes from a third
   party, which also removes the UK GDPR consideration that came with Google
   Fonts seeing every visitor's IP address.

   Local (see the @font-face blocks):
     Manrope        --font-core     400, 600 (plus an unreachable 300, see below)
     JetBrains Mono --font-mono     400, 700
     Archivo        --font-display  variable, wght + wdth
     Caveat         --font-script   variable, wght

   Historical note, kept because it explains the shape of this file:
     Archivo        --font-display
     Caveat         --font-script
   There is no binary for either family in fonts/, so the @import cannot be deleted yet.
   It has been trimmed to Archivo and Caveat only. Manrope and JetBrains Mono were removed
   from the URL on purpose: leaving them in would give each family two competing definitions
   and the winner would change from weight to weight. The @import must stay the first
   at-rule in this file or browsers throw it away, so every @font-face sits below it.
   Keep &display=swap on the URL, it is the only way to set font-display on remote faces.

   To go fully offline we still need four binaries:
     1. Archivo, variable, with the wdth axis (75..100) and wght 500..900. A static cut is
        not enough. The posters paint font-stretch: 88%, browsers do not synthesise width,
        and a missing width match falls back to normal width silently, with no console error.
     2. Caveat 500..700 (variable or static 400 and 700). Note the pages also use Caveat at
        an implicit 400, which the current Google URL clamps to 500. Worth fixing at source.
     3. Manrope 700.
     4. Manrope 800.
   A JetBrains Mono 600 would be a fifth nice-to-have, though the 700 we hold covers it well.

   On the format() hints. These files used to carry a .woff2 extension over raw TrueType
   bytes (00 01 00 00, not wOF2). Browsers sniff the bytes and ignore the extension, so
   nothing looked wrong — the site simply served 509 KB of uncompressed font on every cold
   visit, and the hint had to be omitted because writing it would have been a lie. They are
   now genuine woff2, 168 KB across the five, so the hint is stated and true. Rebuild them
   with tools/fonts/compress.py; the TrueType sources live in tools/fonts/src/.
   If a face is ever swapped back to an uncompressed file, drop its hint again rather than
   writing format("ttf") or format("otf"): neither is a valid keyword, and an invalid
   keyword invalidates the whole source and drops the face.

   No local() sources on purpose. Manrope 300 and 600 report their name as "Manrope Light"
   and "Manrope SemiBold" internally, so local() would resolve differently per machine.

   Next step after this, out of scope here because it means editing the token values below:
   metric-matched fallback faces (size-adjust, ascent-override) so the swap costs no layout
   shift, plus a preload for Manrope 400 and 600. */
:root {
  --font-display: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --font-core: "Manrope", "Helvetica Neue", Arial, sans-serif;
  --font-script: "Caveat", "Segoe Script", cursive;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

/* Manrope, --font-core. Variable, wght 200-800, from 2026-08-10.
 *
 * This replaces three static cuts (300, 400, 600) that between them could not
 * draw the weights the pages ask for. The 600 file was declared `font-weight:
 * 600 800`, so one SemiBold outline answered 600, 700 and 800 alike. Measured
 * against the handoff with verify-weights, which compares rasterised ink:
 * 700 came out 11% lighter than designed on 340 elements, 800 19% lighter on
 * 245. That is what flattened the heading hierarchy — the body font's bold was
 * never bold. The handoff asks for Manrope:wght@400..800, a real range, and
 * this is that range.
 *
 * Cheaper too: 39,956 B for both subsets against 91,228 B for the three cuts.
 * Google's own variable woff2, latin and latin-ext only, with Google's own
 * unicode-range so a visitor downloads just the subset their text needs.
 *
 * The latin subset is Manrope-variable.woff2, which was already in the live repo
 * and is what the other twenty pages have always used — verified identical to
 * the file Google serves today, same md5. Only these seven pages ever had the
 * static cuts, so the rest of the site has been rendering Manrope correctly the
 * whole time. Pointing at the existing name rather than a second copy keeps one
 * binary and means a visitor arriving from any other page already has it. */
@font-face {
  font-family: "Manrope";
  src: url("/fonts/Manrope-variable.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Manrope";
  src: url("/fonts/Manrope-var-latin-ext.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* JetBrains Mono, --font-mono. Variable, wght 100-800, from 2026-08-10.
 *
 * Same fix as Manrope above and for the same reason. Two static cuts covered
 * 400-500 and 600-800, so a request for 600 was answered by the 700 outline —
 * 6% heavier than the design asks for, on 27 elements. Small next to Manrope,
 * but it is the same defect: a declared range wider than the file behind it,
 * which no build and no diff can see.
 *
 * Declared 100-600, not the 100-800 the binary carries, and that ceiling is
 * deliberate. Nineteen elements ask for mono 800 by accident — a mono span
 * inside an h3 that overrides only font-family, so it inherits the h3 weight,
 * starting at ramx-pricing.dc.html:248. The handoff loads JetBrains Mono at
 * 400 and 600 only, so in the approved design those spans clamp to 600. An
 * uncapped variable face would draw a real 800 instead: more faithful to the
 * CSS, 24% heavier than the design, and honouring a weight nobody chose.
 * Capping reproduces the design exactly. The actual fix is in the markup. */
@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/JetBrainsMono-var-latin.woff2") format("woff2");
  font-weight: 100 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/JetBrainsMono-var-latin-ext.woff2") format("woff2");
  font-weight: 100 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ===== tokens/colors.css ===== */
:root {
  /* ---- Base ramp: Deep navy ---- */
  --navy-950: #0E1728;
  --navy-900: #16233A; /* brand: Deep navy */
  --navy-800: #24354F;
  --navy-700: #3A4A63;

  /* ---- Base ramp: RamX green ---- */
  --green-700: #16733F;
  --green-600: #1B8A4E;
  --green-500: #21A05B; /* brand: RamX green */
  --green-300: #7CCB9F;
  --green-100: #C7E8D5;
  --green-50: #E4F4EB;

  /* ---- Base ramp: Neutrals ---- */
  --white: #FFFFFF;
  --offwhite: #F7F8FA; /* brand: Off-white */
  --cloud: #F0EEE9;    /* brand: Cloud Dancer, Pantone 11-4201 */
  --cloud-deep: #E6E2DA;
  --grey-100: #E4E7EC;
  --grey-200: #C9CFD8;
  --grey-400: #8C95A3;
  --grey-500: #5B6678; /* brand: Ink grey */
  --grey-700: #424C5D;

  /* ---- Status ramp (Health Check verdicts) ---- */
  --amber-500: #E5A233;
  --amber-100: #FDF1DC;
  --brick-500: #CF4436;
  --brick-100: #FBE7E4;

  /* ---- Semantic: text ---- */
  --text-primary: var(--navy-900);
  --text-secondary: var(--grey-500);
  --text-muted: var(--grey-400);
  --text-accent: var(--green-600);
  --text-on-dark: var(--offwhite);
  --text-on-dark-muted: #A7B2C4;
  --text-on-accent: var(--white);

  /* ---- Semantic: surfaces ---- */
  --surface-page: var(--offwhite);
  --surface-alt: var(--cloud);
  --surface-card: var(--white);
  --surface-card-alt: var(--cloud);
  --surface-inverse: var(--navy-900);
  --surface-inverse-raised: var(--navy-800);
  --surface-accent: var(--green-500);
  --surface-accent-soft: var(--green-50);
  --surface-sunken: #EDEFF3;

  /* ---- Semantic: lines ---- */
  --border-hairline: var(--grey-100);
  --border-default: var(--grey-200);
  --border-strong: var(--navy-900);
  --border-on-dark: rgba(247, 248, 250, 0.16);
  --border-accent: var(--green-500);

  /* ---- Semantic: interactive ---- */
  --action-primary: var(--green-500);
  --action-primary-hover: var(--green-600);
  --action-primary-active: var(--green-700);
  --action-secondary: var(--navy-900);
  --action-secondary-hover: var(--navy-800);
  --action-disabled-bg: var(--grey-100);
  --action-disabled-text: var(--grey-400);
  --focus-ring: rgba(33, 160, 91, 0.38);
  --focus-ring-dark: rgba(124, 203, 159, 0.5);

  /* ---- Semantic: verdicts ---- */
  --status-pass: var(--green-500);
  --status-pass-soft: var(--green-50);
  --status-warning: var(--amber-500);
  --status-warning-soft: var(--amber-100);
  --status-fail: var(--brick-500);
  --status-fail-soft: var(--brick-100);
  --status-nodata: var(--grey-400);
  --status-nodata-soft: var(--surface-sunken);

  /* ---- Marker / highlighter inks (poster motif) ---- */
  --mark-green: rgba(33, 160, 91, 0.24);
  --mark-amber: rgba(229, 162, 51, 0.32);
  --mark-cloud: rgba(230, 226, 218, 0.9);
}

/* ===== tokens/typography.css ===== */
:root {
  /* ---- Weights ---- */
  --weight-regular: 400; /* @kind font */
  --weight-medium: 500; /* @kind font */
  --weight-semibold: 600; /* @kind font */
  --weight-bold: 700; /* @kind font */
  --weight-heavy: 800; /* @kind font */
  --weight-black: 900; /* @kind font */

  /* ---- Display (Archivo, uppercase, poster scale) ---- */
  --display-xxl-size: 88px;
  --display-xxl-line: 0.88; /* @kind font */
  --display-xxl-track: -0.03em; /* @kind font */
  --display-xl-size: 64px;
  --display-xl-line: 0.9; /* @kind font */
  --display-xl-track: -0.028em; /* @kind font */
  --display-lg-size: 48px;
  --display-lg-line: 0.94; /* @kind font */
  --display-lg-track: -0.022em; /* @kind font */
  --display-md-size: 36px;
  --display-md-line: 1; /* @kind font */
  --display-md-track: -0.018em; /* @kind font */
  --display-width: 88; /* @kind font */ /* font-stretch %, condensed poster setting */

  /* ---- Headings (Manrope) ---- */
  --head-lg-size: 28px;
  --head-lg-line: 1.16; /* @kind font */
  --head-md-size: 22px;
  --head-md-line: 1.25; /* @kind font */
  --head-sm-size: 18px;
  --head-sm-line: 1.35; /* @kind font */
  --head-track: -0.012em; /* @kind font */

  /* ---- Body (Manrope) ---- */
  --body-lg-size: 18px;
  --body-lg-line: 1.6; /* @kind font */
  --body-size: 16px;
  --body-line: 1.65; /* @kind font */
  --body-sm-size: 14px;
  --body-sm-line: 1.55; /* @kind font */

  /* ---- Labels (Manrope, uppercase, tracked) ---- */
  --label-size: 13px;
  --label-line: 1.2; /* @kind font */
  --label-track: 0.08em; /* @kind font */
  --micro-size: 11px;
  --micro-line: 1.2; /* @kind font */
  --micro-track: 0.11em; /* @kind font */

  /* ---- Script accent (Caveat) ---- */
  --script-lg-size: 34px;
  --script-size: 22px;
  --script-line: 1.15; /* @kind font */

  /* ---- Data (JetBrains Mono) ---- */
  --mono-size: 13px;
  --mono-line: 1.45; /* @kind font */
  --mono-track: -0.01em; /* @kind font */

  /* ---- Measure ---- */
  --measure-tight: 34ch; /* @kind font */
  --measure: 62ch; /* @kind font */
  --measure-wide: 76ch; /* @kind font */
}

/* ===== tokens/spacing.css ===== */
:root {
  --space-0: 0px;
  --space-05: 2px;
  --space-1: 4px;
  --space-15: 6px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;
  --space-30: 120px;
  --space-40: 160px;

  /* Semantic rhythm */
  --gap-inline: var(--space-3);   /* chips, icon + label */
  --gap-stack: var(--space-4);    /* paragraph / field stack */
  --gap-card: var(--space-6);     /* inside a card */
  --gap-grid: var(--space-6);     /* between cards */
  --gap-block: var(--space-12);   /* between blocks in a section */
  --section-y: var(--space-24);   /* section padding, desktop */
  --section-y-tight: var(--space-16);
  --section-y-mobile: var(--space-12);
}

/* ===== tokens/radius.css ===== */
:root {
  --radius-xs: 6px;
  --radius-sm: 10px;   /* inputs, chips */
  --radius-md: 14px;   /* small cards, stickers */
  --radius-lg: 20px;   /* standard card */
  --radius-xl: 28px;   /* feature panel, media frame */
  --radius-pill: 999px;
  /* Organic blob masks (poster motif behind imagery) */
  --radius-blob-a: 58% 42% 47% 53% / 46% 39% 61% 54%;
  --radius-blob-b: 42% 58% 63% 37% / 55% 48% 52% 45%;
  --border-width: 1px; /* @kind other */
  --border-width-strong: 2px; /* @kind other */
  --border-width-sticker: 3px; /* @kind other */
}

/* ===== tokens/elevation.css ===== */
:root {
  --shadow-none: none;
  --shadow-hairline: 0 1px 0 rgba(22, 35, 58, 0.06);
  --shadow-card: 0 1px 2px rgba(22, 35, 58, 0.04), 0 10px 24px -8px rgba(22, 35, 58, 0.12);
  --shadow-card-hover: 0 2px 4px rgba(22, 35, 58, 0.06), 0 20px 42px -10px rgba(22, 35, 58, 0.18);
  --shadow-sticker: 0 8px 18px -4px rgba(22, 35, 58, 0.22);
  --shadow-hard: 3px 3px 0 var(--navy-900);
  --shadow-hard-green: 3px 3px 0 var(--green-500);
  --shadow-pop: 0 24px 60px -18px rgba(22, 35, 58, 0.34);
  --shadow-inset-well: inset 0 1px 2px rgba(22, 35, 58, 0.07);
  --ring-focus: 0 0 0 3px var(--focus-ring);
  --ring-focus-dark: 0 0 0 3px var(--focus-ring-dark);
  /* Protection gradient for text over imagery (never a flat capsule over photos) */
  --scrim-bottom: linear-gradient(to top, rgba(14, 23, 40, 0.82) 0%, rgba(14, 23, 40, 0.45) 42%, rgba(14, 23, 40, 0) 100%); /* @kind color */
  --scrim-top: linear-gradient(to bottom, rgba(14, 23, 40, 0.6) 0%, rgba(14, 23, 40, 0) 70%); /* @kind color */
}

/* ===== tokens/motion.css ===== */
:root {
  --dur-instant: 90ms; /* @kind other */
  --dur-fast: 140ms; /* @kind other */
  --dur-base: 200ms; /* @kind other */
  --dur-slow: 320ms; /* @kind other */
  --dur-reveal: 520ms; /* @kind other */
  --ease-out: cubic-bezier(0.2, 0.7, 0.3, 1); /* @kind other */
  --ease-in-out: cubic-bezier(0.5, 0, 0.3, 1); /* @kind other */
  --ease-pop: cubic-bezier(0.34, 1.56, 0.64, 1); /* @kind other */ /* slight overshoot: stickers, badges */
  --transition-interactive: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-pop); /* @kind other */
  --lift-hover: translateY(-2px); /* @kind other */
  --lift-press: translateY(0) scale(0.985); /* @kind other */
  --rotate-sticker-a: -3deg; /* @kind other */
  --rotate-sticker-b: 2.5deg; /* @kind other */
}

/* ===== tokens/layout.css ===== */
:root {
  --content-max: 1200px;
  --content-narrow: 780px;
  --content-wide: 1440px;
  --gutter: 24px;
  --gutter-lg: 40px;
  --nav-height: 72px;
  --report-rail: 264px;
  --grid-columns: 12; /* @kind other */
  --bp-sm: 480px;
  --bp-md: 768px;
  --bp-lg: 1024px;
  --bp-xl: 1280px;
}

/* ===== tokens/patterns.css ===== */
:root {
  /* Dot grids — poster texture, used at 8–14% opacity behind display type */
  --pattern-dot-navy: radial-gradient(circle, rgba(22, 35, 58, 0.22) 1.5px, transparent 1.6px); /* @kind other */
  --pattern-dot-green: radial-gradient(circle, rgba(33, 160, 91, 0.35) 1.5px, transparent 1.6px); /* @kind other */
  --pattern-dot-light: radial-gradient(circle, rgba(247, 248, 250, 0.3) 1.5px, transparent 1.6px); /* @kind other */
  --pattern-dot-size: 12px 12px; /* @kind other */
  --pattern-dot-size-lg: 18px 18px; /* @kind other */

  /* Hairline rule grid — report tables and spec sheets */
  --pattern-rule: repeating-linear-gradient(to bottom, var(--grey-100) 0 1px, transparent 1px 40px); /* @kind other */

  /* Highlighter marks — sit behind a text run, never a full block */
  --mark-highlight-green: linear-gradient(180deg, transparent 56%, var(--mark-green) 56%, var(--mark-green) 94%, transparent 94%); /* @kind other */
  --mark-highlight-amber: linear-gradient(180deg, transparent 56%, var(--mark-amber) 56%, var(--mark-amber) 94%, transparent 94%); /* @kind other */
  --mark-underline-green: linear-gradient(180deg, transparent 88%, var(--green-500) 88%, var(--green-500) 96%, transparent 96%); /* @kind other */

  /* Accent band gradient — the only gradient the brand uses: navy depth, no hue shift */
  --gradient-navy-depth: linear-gradient(160deg, var(--navy-900) 0%, var(--navy-950) 100%); /* @kind color */
}

/* ===== base/reset.css ===== */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--surface-page);
  color: var(--text-primary);
  font-family: var(--font-core);
  font-size: var(--body-size);
  line-height: var(--body-line);
  font-weight: var(--weight-regular);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; }
img, svg, video { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: var(--text-accent); text-decoration: none; font-weight: var(--weight-semibold); }
a:hover { color: var(--green-700); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: none;
  box-shadow: var(--ring-focus);
  border-radius: var(--radius-xs);
}
p { text-wrap: pretty; }
h1, h2, h3 { text-wrap: balance; }
::selection { background: var(--mark-green); }
