/* public.css — the shell styles for the public marketing site.
 *
 * Scope: the page frame only — reset, type defaults, header, footer, the
 * shared layout container. Per-page composition (the hero, the match readout,
 * the county lattice) lives with its page, so this file stays the thing every
 * public page can rely on without reading it.
 *
 * Loads AFTER tokens.css and uses only its custom properties: no raw hex
 * anywhere below this line. A colour that is not a token is a colour nobody can
 * find later.
 */

/* --- Reset (the useful subset) ------------------------------------------ */
*,
*::before,
*::after { box-sizing: border-box; }

body,
h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }

img, picture, svg { display: block; max-width: 100%; }

/* --- Page --------------------------------------------------------------- */
body.pm {
  background: var(--pm-paper-page);
  color: var(--pm-graphite);
  font-family: var(--pm-body);
  font-size: var(--pm-body-m);
  line-height: var(--pm-lh-body);
  /* The design's optical spacing assumes real Archivo/Public Sans metrics; ask
     the browser for the same kerning + ligatures the design tool applied. */
  font-kerning: normal;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  /* Push the footer to the bottom on pages shorter than the viewport. Without
     this the 404 ends its footer some 190px up a 900px window, with page
     background below it, which reads as a page that failed to finish loading.
     `dvh` rather than `vh` so a phone's collapsing URL bar does not leave a gap.
     `main` takes the slack; the footer keeps its own margin. */
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

body.pm > main { flex: 1 0 auto; }

h1, h2, h3, h4 {
  font-family: var(--pm-display);
  font-weight: 600;
  color: var(--pm-ink);
  line-height: var(--pm-lh-head);
  text-wrap: balance;
}

p { text-wrap: pretty; }

a { color: var(--pm-signal); text-decoration: none; }
a:hover { color: var(--pm-signal-hover); text-decoration: underline; }

/* One visible focus style for everything, and never `outline: none`. The site
 * is bilingual, server-rendered and keyboard-navigable by default; the focus
 * ring is what keeps that true. Signal blue at 2px clears contrast on paper. */
:where(a, button, input, textarea, select, summary):focus-visible {
  outline: 2px solid var(--pm-signal);
  outline-offset: 3px;
  border-radius: 1px;
}

/* --- Skip link ----------------------------------------------------------- */
.pm-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.75rem 1rem;
  background: var(--pm-ink);
  color: var(--pm-paper-page);
  font-size: var(--pm-body-s);
}
.pm-skip:focus {
  left: 0;
  text-decoration: none;
  color: var(--pm-paper-page);
}

/* --- Shared container ---------------------------------------------------- */
.pm-wrap {
  width: 100%;
  max-width: var(--pm-maxw);
  margin-inline: auto;
  padding-inline: var(--pm-gutter);
}

/* --- Header -------------------------------------------------------------- */
.pm-header {
  border-bottom: 1px solid var(--pm-rule);
  background: var(--pm-paper-page);
}
.pm-header__inner {
  width: 100%;
  max-width: var(--pm-maxw);
  margin-inline: auto;
  padding: 1.375rem var(--pm-gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.pm-wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  color: var(--pm-ink);
}
.pm-wordmark:hover { color: var(--pm-ink); text-decoration: none; }
.pm-wordmark__text {
  font-family: var(--pm-display);
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: -0.01em;
  margin-left: 0.375rem;
}
/* The mark: the two squares, ink then signal. The pair IS the match — one
 * square would be a logo, two are an argument. */
.pm-mark { display: inline-flex; gap: 0.25rem; }
.pm-mark i {
  width: 13px;
  height: 13px;
  display: block;
}
.pm-mark i:first-child { background: var(--pm-ink); }
.pm-mark i:last-child  { background: var(--pm-signal); }

.pm-nav {
  display: flex;
  align-items: center;
  gap: 2.125rem;
  flex-wrap: wrap;
  font-size: 0.84375rem;
  font-weight: 500;
  color: var(--pm-graphite);
}
.pm-nav__link { color: var(--pm-graphite); }
.pm-nav__link:hover { color: var(--pm-ink); text-decoration: none; }
.pm-nav__link.is-current { color: var(--pm-ink); }

.pm-langs {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-family: var(--pm-body);
  font-size: var(--pm-label-s);
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--pm-muted);
}
.pm-langs__current { color: var(--pm-ink); }
.pm-langs__link { color: var(--pm-muted); }
.pm-langs__link::before { content: "/"; margin-right: 0.375rem; color: var(--pm-rule); }
.pm-langs__link:hover { color: var(--pm-ink); text-decoration: none; }

/* The one CTA. A square-cornered outline that inverts on hover: the design's
 * instrument register, where a filled pill would read as a consumer app. */
.pm-cta {
  /* INLINE-BLOCK, and it is load-bearing rather than tidiness. An `<a>` is
   * inline by default, and vertical padding on an inline box does not take part
   * in line height — it just bleeds over whatever sits above. In the header the
   * button is a flex item, which blockifies it and hides the problem; standing
   * on its own between two paragraphs (the journalist page's hero) it overlapped
   * the lede's last line by 11px at 1440. Blockifying it here fixes every such
   * use at once and changes nothing in flex, where the value is ignored. */
  display: inline-block;
  padding: 0.625rem 1rem;
  border: 1px solid var(--pm-ink);
  color: var(--pm-ink);
  font-size: var(--pm-label);
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--pm-dur) var(--pm-ease),
              color var(--pm-dur) var(--pm-ease);
}
/* A button standing on its own after a paragraph needs its own space; in the
 * header the flex gap provides it, which is why this is scoped to that case. */
p + .pm-cta { margin-top: 1.25rem; }

.pm-cta:hover {
  background: var(--pm-ink);
  color: var(--pm-paper-page);
  text-decoration: none;
}

/* The PRIMARY page button — the signal-blue one the homepage sketch settled on
 * (varv 8-37). It lived in home.css until 2026-09-06, which meant /testa asked
 * for it in four places and got the browser's default grey button and a bare
 * blue link instead: home.css is loaded by the homepage alone. A component more
 * than one page uses belongs to the shell.
 *
 * Works on `<a>` AND on `<button>` — /testa's submit is a real button, which
 * carries a user-agent border, font and cursor that an anchor does not. Its
 * full-width-on-a-phone rule stays in home.css, where it is a homepage layout
 * decision rather than part of the component. */
.pm-btn {
  font-family: var(--pm-display);
  font-weight: 600;
  font-size: var(--pm-body-m);
  background: var(--pm-signal);
  color: var(--pm-paper-sheet);
  text-decoration: none;
  padding: 0.9375rem 1.875rem;
  border: 0;
  border-radius: 3px;
  cursor: pointer;
  display: inline-block;
  transition: background var(--pm-dur) var(--pm-ease);
}
.pm-btn:hover { background: var(--pm-signal-hover); color: var(--pm-paper-sheet); text-decoration: none; }
.pm-btn:focus-visible { outline: 2px solid var(--pm-signal); outline-offset: 3px; }

/* --- Footer -------------------------------------------------------------- */
/* The site footer (homepage sketch, varv 36): wordmark + one line from the phrase
 * family, the standing links, and the company row. Three columns on a wide
 * screen, stacked on a narrow one. No social icons — we hold no accounts, and a
 * row of dead icons is worse than none. */
.pm-footer {
  margin-top: var(--pm-section-y);
  border-top: 1px solid var(--pm-rule);
  background: var(--pm-paper-deep);
}
.pm-footer__inner {
  width: 100%;
  max-width: var(--pm-maxw);
  margin-inline: auto;
  padding: 3rem var(--pm-gutter) 2.5rem;
  display: grid;
  grid-template-columns: 1.2fr 1fr 1.2fr;
  align-items: start;
  gap: 2.5rem;
}
.pm-footer__line {
  font-size: var(--pm-body-s);
  color: var(--pm-graphite);
  margin-top: 0.625rem;
  max-width: 22em;
}
.pm-footer__nav {
  display: grid;
  gap: 0.625rem;
  justify-self: start;
  font-size: var(--pm-body-s);
}
.pm-footer__nav a { color: var(--pm-graphite); }
.pm-footer__nav a:hover { color: var(--pm-ink); }

/* The company row. One source for who we are — the same four settings the
 * art. 14 mail footer and the privacy page render. */
.pm-footer__legal {
  font-family: var(--pm-mono);
  font-size: var(--pm-label);
  color: var(--pm-muted);
  display: grid;
  gap: 0.375rem;
  justify-self: end;
  text-align: right;
}

@media (max-width: 54rem) {
  .pm-footer__inner { grid-template-columns: 1fr; gap: 1.5rem; }
  .pm-footer__legal { justify-self: start; text-align: left; }
}

/* --- Page furniture ------------------------------------------------------ */
.pm-section { padding-block: var(--pm-section-y); }

/* The eyebrow: mono, tracked, uppercase — labels a section the way a data
 * column labels a value. Reserved for genuine labels; it is not a small
 * heading. */
.pm-eyebrow {
  font-family: var(--pm-mono);
  font-size: var(--pm-label-s);
  font-weight: 500;
  letter-spacing: var(--pm-tr-label);
  text-transform: uppercase;
  color: var(--pm-muted);
}

/* The ONE step in a sequence that is this page's own subject (the product page's
 * "02 — Match"). Blue, never green: the owner is red/green colour-blind, and the
 * emphasis is carried by contrast against four muted siblings as well as by hue.
 * The templates asked for this with `pm-label--signal` from the first build and
 * no stylesheet implemented it, so the step rendered as body text like the rest. */
.pm-eyebrow--signal { color: var(--pm-signal); }

.pm-lede {
  font-size: var(--pm-body-l);
  max-width: 34em;
}

/* A note the visitor should read as OUR editorial state, not as page content:
 * the in-progress marker on a draft page. Lightness-separated from the page,
 * never a colour-coded warning — the owner is red/green colour-blind and the
 * palette carries no red anyway. */
.pm-note {
  margin-block: 1.5rem;
  padding: 1rem 1.25rem;
  background: var(--pm-paper-deep);
  border-left: 3px solid var(--pm-muted);
  font-size: var(--pm-body-s);
  color: var(--pm-graphite);
}
.pm-note strong { color: var(--pm-ink); }

/* --- Forms ---------------------------------------------------------------
 * One column, generous targets, no placeholder-as-label. A placeholder that
 * doubles as a label disappears the moment someone types, which is exactly
 * when they need it — and it fails every accessibility check besides. */
.pm-form-page { max-width: 40rem; }

/* The same page when it stops being a form and becomes a READOUT. 40rem is the
 * right measure for one column of fields and the wrong one for a five-column
 * table: /testa's result scrolled sideways inside it and wrapped "Försvar &
 * säkerhet" onto three lines, so every such row stood three times as tall. The
 * step to ~62rem is the prose/content measure — wide enough that the table fits
 * without a horizontal scrollbar at 1440, narrow enough that the headline and
 * the lede above it keep a readable line length. */
.pm-form-page--wide { max-width: 62rem; }

/* A note that lists what is missing, one line per field. Bullets removed: the
 * lines are sentences, and at one or two of them a bullet list reads as
 * decoration. */
.pm-note__list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.pm-note__list li + li { margin-top: 0.375rem; }

.pm-form-page__title {
  margin-top: 0.75rem;
  font-size: var(--pm-d2);
  letter-spacing: var(--pm-tr-d4);
}

.pm-form { margin-top: 2.5rem; }

.pm-field { margin-bottom: 1.5rem; }

.pm-field__label {
  display: block;
  margin-bottom: 0.375rem;
  font-size: var(--pm-body-s);
  font-weight: 600;
  color: var(--pm-ink);
}

/* "optional" as a quiet suffix rather than "required" markers everywhere: three
 * of six fields are required, so marking the exceptions is the smaller mark. */
.pm-field__optional {
  font-weight: 400;
  color: var(--pm-muted);
}

.pm-field__hint {
  margin-bottom: 0.375rem;
  font-size: var(--pm-body-s);
  color: var(--pm-muted);
}

.pm-field__input {
  width: 100%;
  padding: 0.75rem 0.875rem;
  background: var(--pm-paper-sheet);
  border: 1px solid var(--pm-rule);
  border-radius: 0;
  font-family: var(--pm-body);
  font-size: var(--pm-body-m);
  color: var(--pm-ink);
  transition: border-color var(--pm-dur) var(--pm-ease);
}
.pm-field__input:hover { border-color: var(--pm-muted); }
.pm-field__input--area { resize: vertical; line-height: 1.55; }

/* A missing required field is marked by a thicker DARK border and a label
 * change — never by colour alone. The owner is red/green colour-blind and the
 * palette has no red in it anyway; lightness and weight do the work. */
.pm-field.is-missing .pm-field__input {
  border-color: var(--pm-ink);
  border-width: 2px;
}

.pm-check {
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  margin: 1.75rem 0;
  font-size: var(--pm-body-s);
}
.pm-check input { margin-top: 0.25rem; flex: none; }

.pm-form__legal {
  margin-bottom: 1.75rem;
  font-size: var(--pm-body-s);
  color: var(--pm-muted);
}

/* The submit button: the CTA, filled rather than outlined, because on a form
 * page it is the only action and hierarchy is not in question. */
.pm-cta--solid {
  background: var(--pm-ink);
  color: var(--pm-paper-page);
  border: 1px solid var(--pm-ink);
  cursor: pointer;
  font-family: var(--pm-body);
}
.pm-cta--solid:hover {
  background: var(--pm-signal);
  border-color: var(--pm-signal);
  color: var(--pm-paper-sheet);
}

/* The page-level size, for a CTA that is the reason the page exists rather than
 * a control in the corner of it. Size and nothing else — it stacks on .pm-cta
 * and .pm-cta--solid so the site has ONE button, not a header button and a
 * separate page button that drift apart a release at a time. */
.pm-cta--lg {
  padding: 1rem 1.875rem;
  font-size: var(--pm-body-s);
  line-height: 1;
}

/* A CTA whose destination the view has not supplied yet. Keeps the look, drops
 * the affordance: no pointer, no hover, and it is a <span> in the markup — so
 * assistive tech reads text instead of announcing a control that answers a
 * click with nothing. Every use of this is a page waiting for an increment. */
.pm-cta.is-pending {
  cursor: default;
}
.pm-cta.is-pending:hover {
  background: var(--pm-ink);
  border-color: var(--pm-ink);
  color: var(--pm-paper-page);
}

/* The honeypot. Positioned off-screen rather than display:none — a bot that
 * respects display:none would skip it, and skipping it is the one thing we do
 * not want. aria-hidden + tabindex="-1" keep it away from screen readers and
 * the keyboard, so no real person can reach it by accident. */
.pm-honeypot {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --- Legal pages ---------------------------------------------------------
 * Long-form prose: a privacy policy is read, not skimmed, so the measure is
 * narrow and the vertical rhythm generous. Set in the BODY face throughout —
 * the display face is for the marketing pages, and a legal document that
 * shouts is a legal document nobody finishes. */
.pm-legal { max-width: 46rem; }

.pm-legal__title {
  margin-top: 0.75rem;
  font-size: var(--pm-d2);
  letter-spacing: var(--pm-tr-d4);
}

.pm-legal__draft { margin-block: 1.75rem; }

.pm-legal__lede {
  font-size: var(--pm-body-l);
  color: var(--pm-graphite);
}

.pm-legal__body h2 {
  margin-top: 2.75rem;
  margin-bottom: 0.75rem;
  font-family: var(--pm-body);
  font-size: var(--pm-d5);
  letter-spacing: -0.008em;
}

.pm-legal__body p { margin-top: 0.875rem; }
.pm-legal__body ul { margin: 0.875rem 0 0; padding-left: 1.25rem; }
.pm-legal__body li { margin-top: 0.5rem; }

/* Definition lists carry the data/purpose/legal-basis structure. The term sits
 * in the label register (tracked, uppercase, muted) so the structure is legible
 * at a glance without a second heading level competing with the sections. */
.pm-legal__body dl { margin-top: 1.25rem; }
.pm-legal__body dt {
  margin-top: 1.125rem;
  font-family: var(--pm-mono);
  font-size: var(--pm-label-s);
  font-weight: 500;
  letter-spacing: var(--pm-tr-label);
  text-transform: uppercase;
  color: var(--pm-muted);
}
.pm-legal__body dd { margin: 0.375rem 0 0; }

.pm-legal__body strong { color: var(--pm-ink); }

.pm-legal__body .pm-note ul { margin-top: 0.625rem; }
.pm-legal__body .pm-note p:first-child { margin-top: 0; }

/* --- Hero ----------------------------------------------------------------
 * The question, its echo in the other language, and the standfirst. The
 * display step is fluid (see tokens.css) because the design's 84px is an
 * artboard value, not a phone value. */
.pm-hero { padding-block: clamp(3.5rem, 1.5rem + 8vw, 7.875rem) 0; }

.pm-hero__h1 {
  font-size: var(--pm-d1);
  line-height: var(--pm-lh-display);
  letter-spacing: var(--pm-tr-d1);
  max-width: 15em;
}
/* Swedish compounds are longer than a phone is wide. --pm-d1 bottoms out at
 * 44px, and "Pressmeddelandet" sets 357px there — wider than a 360px phone's
 * content column. An unbreakable word does not wrap, it overhangs, and the
 * whole document then scrolls sideways (measured 2026-07-30: 377px of content
 * in a 345px viewport, with the headline as the entire remainder).
 *
 * `hyphens: auto` is asked for first and is not relied on: it needs a
 * hyphenation dictionary for the document language, and a browser without the
 * sv patterns silently does nothing — which is exactly what was measured here.
 * The size ramp is what actually guarantees the fit. It continues the token's
 * own scale downward instead of stepping, so nothing jumps at the breakpoint:
 * 44px at 480px, 36px at 360px, and the longest word stays whole the whole way.
 * break-word is deliberately not used — it would split the compound at no
 * meaningful place and leave no hyphen to explain the break. */
@media (max-width: 30rem) {
  .pm-hero__h1 {
    hyphens: auto;
    font-size: clamp(2rem, 0.75rem + 6.67vw, 2.75rem);
  }
}

/* The second language: same display face, lighter weight and muted, so it
 * reads as an echo rather than a competing headline. */
.pm-hero__echo {
  margin-top: 1.25rem;
  max-width: 18em;
  font-family: var(--pm-display);
  font-weight: 400;
  font-size: var(--pm-d4);
  line-height: var(--pm-lh-head);
  letter-spacing: var(--pm-tr-d4);
  color: var(--pm-muted);
  text-wrap: balance;
}

.pm-hero__lede {
  margin-top: 2.125rem;
  max-width: 31em;
  font-size: var(--pm-body-l);
  line-height: 1.6;
  color: var(--pm-graphite);
}

/* --- Entry motion --------------------------------------------------------
 * The 12px rise from the design, on the first block of a page only. The whole
 * motion budget is three cues; tokens.css already disables all of it under
 * prefers-reduced-motion. Nothing here may imply the page is doing work it is
 * not doing — no ticking counters, no self-sorting lists. */
.pm-rise { animation: pm-rise 420ms var(--pm-ease) both; }

/* --- Pricing (LAUNCH-PLAN §3.3) -----------------------------------------
 * Three tiers, then a comparison table. No amount is written here or in the
 * template; they all come from app/pricing_catalog.py.
 *
 * The recommended tier is marked with the SIGNAL blue, not gold: gold is spent
 * once, on the county lattice, and this file's tokens forbid it as text. Blue
 * also survives the owner's red/green colour blindness, which rules out the
 * usual green "recommended" badge. The mark is carried by border weight and a
 * label as well as by hue, so it does not depend on colour at all. */
.pm-tiers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.25rem;
  margin-top: 3rem;
}

.pm-tier {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1.75rem 1.5rem;
  background: var(--pm-paper-card);
  border: 1px solid var(--pm-rule);
  border-radius: 3px;
}

.pm-tier.is-featured {
  border-color: var(--pm-signal);
  border-width: 2px;
  /* Compensate the extra border so the cards' contents stay on one baseline. */
  padding: 1.6875rem 1.4375rem;
}

.pm-tier__flag {
  font-family: var(--pm-mono);
  font-size: var(--pm-label-s);
  letter-spacing: var(--pm-tr-label);
  text-transform: uppercase;
  color: var(--pm-signal);
}

.pm-tier__name {
  font-family: var(--pm-display);
  font-size: var(--pm-d4);
  line-height: var(--pm-lh-head);
  color: var(--pm-ink);
}

.pm-tier__price {
  font-family: var(--pm-display);
  font-size: var(--pm-d3);
  line-height: var(--pm-lh-tight);
  color: var(--pm-ink);
}

.pm-tier__audience {
  flex: 1;
  font-size: var(--pm-body-s);
  line-height: 1.55;
  color: var(--pm-graphite);
}

.pm-tier .pm-cta { margin-top: 1rem; align-self: flex-start; }

.pm-tiers__terms {
  margin-top: 1.25rem;
  font-size: var(--pm-body-s);
  color: var(--pm-muted);
}

/* The table scrolls inside itself. Three price columns do not fit a 360px
 * phone, and the page body must never scroll sideways. */
.pm-compare__scroll {
  margin-top: 3.5rem;
  overflow-x: auto;
  /* A focusable scroll container: keyboard users must be able to reach the
   * columns that are off-screen without a pointer. */
}
.pm-compare__scroll:focus-visible { outline: 2px solid var(--pm-signal); outline-offset: 2px; }

.pm-compare {
  width: 100%;
  min-width: 34rem;
  border-collapse: collapse;
  text-align: left;
}

.pm-compare__caption {
  margin-bottom: 1rem;
  font-family: var(--pm-display);
  font-size: var(--pm-d4);
  line-height: var(--pm-lh-head);
  color: var(--pm-ink);
  text-align: left;
}

.pm-compare th,
.pm-compare td {
  padding: 0.75rem 1rem 0.75rem 0;
  border-bottom: 1px solid var(--pm-rule);
  font-size: var(--pm-body-s);
  vertical-align: top;
}

.pm-compare thead th {
  font-family: var(--pm-mono);
  font-size: var(--pm-label-s);
  letter-spacing: var(--pm-tr-label);
  text-transform: uppercase;
  color: var(--pm-muted);
}

.pm-compare tbody th {
  font-weight: 600;
  color: var(--pm-ink);
}

.pm-compare td { color: var(--pm-graphite); }

/* The featured column, tinted so faintly it reads as emphasis rather than as a
 * state. It repeats what the card and the header label already say. */
.pm-compare .is-featured { background: var(--pm-paper-sheet); }

.pm-compare__group th {
  padding-top: 2rem;
  border-bottom-color: var(--pm-ink);
  font-family: var(--pm-mono);
  font-size: var(--pm-label-s);
  letter-spacing: var(--pm-tr-label);
  text-transform: uppercase;
  color: var(--pm-ink);
}

.pm-compare__note {
  display: block;
  margin-top: 0.25rem;
  font-weight: 400;
  font-size: var(--pm-label);
  color: var(--pm-muted);
}

/* ✓ and — carry no meaning on their own: each is paired with .pm-sr text, so a
 * screen reader hears "Included" rather than a check mark or a dash. */
.pm-compare__yes { color: var(--pm-signal); }
.pm-compare__no  { color: var(--pm-muted); }

.pm-pricing__close {
  margin-top: 4rem;
  padding-top: 2.5rem;
  border-top: 1px solid var(--pm-rule);
}
.pm-pricing__close h2 {
  font-family: var(--pm-display);
  font-size: var(--pm-d3);
  line-height: var(--pm-lh-head);
  color: var(--pm-ink);
}
.pm-pricing__close p {
  margin-top: 0.75rem;
  max-width: 34em;
  font-size: var(--pm-body-l);
  line-height: 1.6;
  color: var(--pm-graphite);
}
.pm-pricing__close .pm-cta { margin-top: 1.75rem; }

/* Visually hidden, still announced — and deliberately IN FLOW.
 *
 * The usual recipe for this starts with `position: absolute`, and that is what
 * shipped first. Inside the comparison table it made the pricing page scroll
 * sideways by 53px on a 360px phone: an absolutely positioned element whose
 * containing block is the BODY (no positioned ancestor between) is not clipped
 * by an intervening `overflow: auto` scroller, so seventeen hidden "Included"
 * labels sitting at the table's full 544px width leaked straight past the
 * scroll container and widened the document.
 *
 * The tell was that `overflow-x: hidden` on the scroller changed nothing while
 * `contain: paint` fixed it — containment makes the scroller a containing block
 * for absolute descendants, which is the same thing said a harder way.
 *
 * A 1px in-flow box cannot escape anything. Keeping it in flow costs one pixel
 * next to a check mark and removes the whole failure class, which matters
 * because this is a utility: the next person uses it inside some other
 * scroller without thinking about containing blocks, and should be right. */
.pm-sr {
  display: inline-block;
  width: 1px; height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- Product page (LAUNCH-PLAN §3.2) ------------------------------------
 * One section per capability, with anchors. Phase 2 splits these into pages;
 * the anchors are the seam, so the links keep working when it does. */
.pm-jump {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.5rem;
  margin-top: 2.5rem;
  padding: 0.875rem 0;
  border-top: 1px solid var(--pm-rule);
  border-bottom: 1px solid var(--pm-rule);
  font-family: var(--pm-mono);
  font-size: var(--pm-label-s);
  letter-spacing: var(--pm-tr-label);
  text-transform: uppercase;
}
.pm-jump a { color: var(--pm-muted); text-decoration: none; }
.pm-jump a:hover { color: var(--pm-signal); }

.pm-cap {
  margin-top: 4rem;
  /* An anchored heading must not land under the header when jumped to. */
  scroll-margin-top: 5rem;
}

.pm-cap__head {
  margin-top: 0.5rem;
  max-width: 20em;
  font-family: var(--pm-display);
  font-size: var(--pm-d3);
  line-height: var(--pm-lh-head);
  letter-spacing: var(--pm-tr-d4);
  color: var(--pm-ink);
  text-wrap: balance;
}

.pm-cap__body {
  margin-top: 1.125rem;
  max-width: 36em;
  font-size: var(--pm-body-l);
  line-height: 1.65;
  color: var(--pm-graphite);
}

/* The cost argument. Set apart because it answers a question the reader is
 * already asking, not because it is a warning — no alarm colour, no icon. */
.pm-cap__aside {
  margin-top: 2rem;
  max-width: 38em;
  padding: 1.5rem 1.75rem;
  background: var(--pm-paper-sheet);
  border-left: 2px solid var(--pm-ink);
}
.pm-cap__aside h3 {
  font-family: var(--pm-display);
  font-size: var(--pm-d5);
  line-height: var(--pm-lh-head);
  color: var(--pm-ink);
}
.pm-cap__aside p {
  margin-top: 0.75rem;
  font-size: var(--pm-body-s);
  line-height: 1.6;
  color: var(--pm-graphite);
}

/* --- Journalist page (LAUNCH-PLAN §3.4) ---------------------------------- */
.pm-hero__note {
  margin-top: 1.25rem;
  max-width: 34em;
  font-size: var(--pm-body-s);
  line-height: 1.6;
  color: var(--pm-muted);
}

.pm-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1rem;
  margin-top: 1.75rem;
}
.pm-card {
  padding: 1.375rem 1.5rem;
  background: var(--pm-paper-card);
  border: 1px solid var(--pm-rule);
  border-radius: 3px;
}
.pm-card h3 {
  font-family: var(--pm-display);
  font-size: var(--pm-d5);
  line-height: var(--pm-lh-head);
  color: var(--pm-ink);
}
.pm-card p {
  margin-top: 0.5rem;
  font-size: var(--pm-body-s);
  line-height: 1.55;
  color: var(--pm-graphite);
}

.pm-defs { margin-top: 1.75rem; max-width: 38em; }
.pm-defs dt {
  margin-top: 1.25rem;
  font-family: var(--pm-display);
  font-size: var(--pm-d5);
  line-height: var(--pm-lh-head);
  color: var(--pm-ink);
}
.pm-defs dd {
  margin-top: 0.375rem;
  font-size: var(--pm-body-s);
  line-height: 1.6;
  color: var(--pm-graphite);
}

.pm-cap .pm-cta { margin-top: 1.5rem; }

/* ==========================================================================
   The match teaser (/try) — LAUNCH-SPEC-match-teaser, decisions K, O, P.

   Two rules govern everything here and both are about restraint:

   Decision O — a row carries NO quality signal. No accent colour per row, no
   score, no bar. The order is the rank, and the "matched on" cell is the only
   label. A colour that said "strong match" would read as a verdict on the
   person, which is the one thing this site must never print.

   The owner is red/green colour-blind: nothing in here encodes meaning in hue.
   ========================================================================== */

/* The line under the headline that says how many of the matches are on screen.
 * Quiet: it qualifies the count, it is not a second claim. */
.pm-teaser__cap {
  margin-top: 0.625rem;
  font-size: var(--pm-body-s);
  color: var(--pm-muted);
}

/* The second door, above the table (owner 2026-09-05: the beta button must be
 * reachable without scrolling past every row). */
.pm-teaser__door {
  margin-top: 1.75rem;
  max-width: 34em;
  font-size: var(--pm-body-l);
  color: var(--pm-graphite);
}
.pm-teaser__door + p { margin-top: 1.125rem; }

/* Positioned, so the visually hidden toggle below cannot escape into the page
 * the way an absolutely positioned box with no positioned ancestor does — the
 * failure `.pm-sr` documents further up this file. */
.pm-teaser__frame { position: relative; }

.pm-teaser__scroll {
  margin-top: 2.5rem;
  overflow-x: auto;
}
.pm-teaser__scroll:focus-visible { outline: 2px solid var(--pm-signal); outline-offset: 2px; }

/* --- "Show N more", without JavaScript -----------------------------------
 * Every row is already in the response, so revealing the rest must not cost a
 * request — and the public site ships no JavaScript of its own (only the
 * cookieless analytics tag, when it is configured). So the control is a
 * checkbox: hidden from sight, still focusable and still operable from the
 * keyboard, with the visible `<label>` as its button. `:checked` reveals the
 * second `<tbody>` and removes the button, because a "show more" that stays
 * after everything is shown is a control that lies.
 *
 * The owner rejected the alternative (a scroll box inside the page): it behaves
 * differently on a phone, where the outer page scrolls too. With CSS off, every
 * row is simply visible — the honest fallback, not a broken one. */
.pm-teaser__toggle {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}
.pm-teaser__toggle:not(:checked) ~ .pm-teaser__scroll .pm-teaser__rest {
  display: none;
}
.pm-teaser__toggle:checked ~ .pm-teaser__more { display: none; }
/* The focus ring belongs on the thing you can see. */
.pm-teaser__toggle:focus-visible ~ .pm-teaser__more .pm-cta {
  outline: 2px solid var(--pm-signal);
  outline-offset: 3px;
}

.pm-teaser__more { margin-top: 1.5rem; }
.pm-teaser__more .pm-cta { cursor: pointer; }

.pm-teaser {
  width: 100%;
  min-width: 34rem;
  border-collapse: collapse;
  font-size: var(--pm-body-s);
}

.pm-teaser__caption {
  caption-side: bottom;
  margin-top: 1rem;
  text-align: left;
  color: var(--pm-muted);
  font-size: var(--pm-body-s);
}

.pm-teaser th {
  text-align: left;
  padding: 0 1rem 0.6rem 0;
  border-bottom: 1px solid var(--pm-rule);
  /* `font-size`, not `font`. The shorthand requires a size AND a family, so
     `font: var(--pm-label-s)` is invalid and the browser drops the WHOLE
     declaration — the column headers were rendering at the table's body size
     with the label's tracking, which is why they read as a second row of data
     rather than as labels. Same slip in `.pm-coach__heading` below. */
  font-family: var(--pm-mono);
  font-size: var(--pm-label-s);
  font-weight: 500;
  letter-spacing: var(--pm-tr-label);
  text-transform: uppercase;
  color: var(--pm-muted);
  white-space: nowrap;
}

.pm-teaser td {
  padding: 0.7rem 1rem 0.7rem 0;
  border-bottom: 1px solid var(--pm-rule);
  vertical-align: top;
}

/* The dimension label. Muted and small: it explains the row, it does not rate
 * it — see decision O above. */
.pm-teaser__dims {
  color: var(--pm-muted);
  white-space: nowrap;
}

/* --- The coach's sample (decision P) ------------------------------------- */
.pm-coach {
  margin-top: 3rem;
  padding: 1.75rem;
  background: var(--pm-paper-card);
  border: 1px solid var(--pm-rule);
}

.pm-coach__heading {
  margin: 0;
  /* See `.pm-teaser th`: the `font` shorthand needs a family too, so the single
     custom property was silently discarded and this heading inherited h2 sizing
     from the shell. */
  font-family: var(--pm-mono);
  font-size: var(--pm-label-s);
  font-weight: 500;
  letter-spacing: var(--pm-tr-label);
  text-transform: uppercase;
  color: var(--pm-muted);
}

.pm-coach__tip {
  margin: 0.85rem 0 0;
  font-size: var(--pm-body-l);
  line-height: var(--pm-lh-body);
  color: var(--pm-ink);
}

/* The potential row. Deliberately quiet: it is an invitation, and a loud one
 * would read as the list of faults decision P forbids. */
.pm-coach__more {
  margin: 1rem 0 0;
  color: var(--pm-muted);
  font-size: var(--pm-body-s);
}

.pm-coach__door {
  margin: 1.25rem 0 1.5rem;
  color: var(--pm-graphite);
  line-height: var(--pm-lh-body);
}
