/* ==========================================================================
   dressagetestcalc.com
   Design system, carried over from bitlith.co.uk. Hand-written, no build
   step, no external dependencies. Fonts are system-native by design: no
   third-party font request is made, which keeps the site consistent with
   its own privacy stance.
   ========================================================================== */

/* --- Design tokens -------------------------------------------------------- */
:root {
  color-scheme: light;

  /* Brand: graphite + a single confident accent. "bit" + "monolith". */
  --ink:            #0d1117;
  --text:           #1c2430;
  --text-muted:     #57647a;
  --text-faint:     #7d8a9c;

  --surface:        #ffffff;
  --surface-sunk:   #f6f8fb;
  --surface-raised: #ffffff;

  --border:         #e2e8f0;
  --border-strong:  #cbd5e1;

  --accent:         #2f5fd0;
  --accent-hover:   #244bab;
  --accent-soft:    #eef3fe;
  --accent-border:  #c4d5f7;

  --focus:          #2f5fd0;

  /* Type scale - 1.25 ratio, clamped for fluid response */
  --step--1: clamp(0.83rem, 0.80rem + 0.12vw, 0.89rem);
  --step-0:  clamp(1.00rem, 0.96rem + 0.18vw, 1.09rem);
  --step-1:  clamp(1.20rem, 1.12rem + 0.36vw, 1.42rem);
  --step-2:  clamp(1.44rem, 1.30rem + 0.66vw, 1.86rem);
  --step-3:  clamp(1.73rem, 1.50rem + 1.10vw, 2.44rem);
  --step-4:  clamp(2.07rem, 1.70rem + 1.75vw, 3.20rem);

  --font-sans: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
               "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "SF Mono", Menlo,
               Consolas, "Liberation Mono", monospace;

  /* The wordmark's face is deliberately separate from body text, so the logo
     can be tuned (narrower capitals) without touching anything else.
     Change this one value to restyle the logo everywhere. */
  --font-wordmark: var(--font-sans);

  /* Space and shape */
  --measure: 68ch;
  --wrap: 1120px;
  --radius: 10px;
  --radius-sm: 6px;

  --shadow-sm: 0 1px 2px rgba(13, 17, 23, .06);
  --shadow-md: 0 4px 16px -4px rgba(13, 17, 23, .10), 0 1px 3px rgba(13, 17, 23, .05);
}

/* Theme. Light is the default; the browser's own preference decides unless
   the visitor overrides it with the header toggle, which sets data-theme on
   <html> (site.js). The dark tokens appear twice on purpose: once behind the
   media query for the "follow the browser" default, once behind the
   data-theme attribute so an explicit choice wins in both directions. Keep
   the two blocks identical. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ink:            #f2f5f9;
    --text:           #d3dbe6;
    --text-muted:     #98a5b7;
    --text-faint:     #7d8a9c;
    --surface:        #0d1117;
    --surface-sunk:   #151b23;
    --surface-raised: #1a212b;
    --border:         #2a3340;
    --border-strong:  #3b4655;
    --accent:         #85a8ee;
    --accent-hover:   #a4bff3;
    --accent-soft:    #1b2740;
    --accent-border:  #31477a;
    --focus:          #85a8ee;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
    --shadow-md: 0 4px 16px -4px rgba(0, 0, 0, .5), 0 1px 3px rgba(0, 0, 0, .3);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --ink:            #f2f5f9;
  --text:           #d3dbe6;
  --text-muted:     #98a5b7;
  --text-faint:     #7d8a9c;
  --surface:        #0d1117;
  --surface-sunk:   #151b23;
  --surface-raised: #1a212b;
  --border:         #2a3340;
  --border-strong:  #3b4655;
  --accent:         #85a8ee;
  --accent-hover:   #a4bff3;
  --accent-soft:    #1b2740;
  --accent-border:  #31477a;
  --focus:          #85a8ee;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
  --shadow-md: 0 4px 16px -4px rgba(0, 0, 0, .5), 0 1px 3px rgba(0, 0, 0, .3);
}

/* --- Reset ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

/* The `hidden` attribute is a UA style, so any author rule that sets `display`
   silently beats it. `.calc__field { display: flex }` did exactly that and left
   supposedly hidden fields on screen. Make the attribute mean what it says. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  font-family: var(--font-sans);
  font-size: var(--step-0);
  line-height: 1.65;
  color: var(--text);
  background: var(--surface);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

img, svg, video { display: block; max-width: 100%; height: auto; }

h1, h2, h3, h4 { color: var(--ink); line-height: 1.2; text-wrap: balance; font-weight: 640; letter-spacing: -0.017em; }
p, li { text-wrap: pretty; }

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--accent-hover); }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 3px;
}

/* --- Skip link ------------------------------------------------------------ */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--accent); color: #fff; padding: .7rem 1.1rem;
  border-radius: 0 0 var(--radius-sm) 0; font-weight: 600;
}
.skip:focus { left: 0; color: #fff; }

/* --- Layout --------------------------------------------------------------- */
.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }
@media (max-width: 40rem) { .wrap { width: min(100% - 2rem, var(--wrap)); } }

main { flex: 1 0 auto; }

/* --- Site header ---------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: saturate(1.6) blur(10px);
  border-bottom: 1px solid var(--border);
}
.site-header__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; min-height: 4.25rem;
}

/* Wordmark: "BitLith", set clean in a single weight. Deliberately NOT
   micro-manipulated: per-letter scaling and negative margins were tried and
   read as distorted. Modest tracking only. */
.wordmark {
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: var(--font-wordmark);
  font-size: 1.2rem; letter-spacing: -0.03em;
  color: var(--ink); text-decoration: none; font-weight: 700;
}
.wordmark:hover { color: var(--ink); }
.wordmark__mark { flex: none; color: var(--accent); }

.nav { display: flex; align-items: center; gap: 1.75rem; }
.nav a {
  color: var(--text-muted); text-decoration: none;
  font-size: var(--step--1); font-weight: 550; letter-spacing: -0.005em;
  padding-block: .35rem; border-bottom: 2px solid transparent;
}
.nav a:hover { color: var(--ink); }
.nav a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--accent); }

/* Light/dark toggle. One button, two icons; the theme decides which shows.
   With no JavaScript the button never wires up, so it stays hidden until
   site.js reveals it: the page must not offer a control that does nothing. */
.theme-toggle {
  display: none; align-items: center; justify-content: center;
  width: 2.1rem; height: 2.1rem; flex: none;
  border: 1px solid var(--border); border-radius: 50%;
  background: transparent; color: var(--text-muted); cursor: pointer;
  padding: 0;
}
.theme-toggle.is-ready { display: inline-flex; }
.theme-toggle:hover { color: var(--ink); border-color: var(--border-strong); }
.theme-toggle svg { display: none; }
.theme-toggle .theme-toggle__moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .theme-toggle__moon { display: none; }
  :root:not([data-theme="light"]) .theme-toggle .theme-toggle__sun { display: block; }
}
:root[data-theme="dark"] .theme-toggle .theme-toggle__moon { display: none; }
:root[data-theme="dark"] .theme-toggle .theme-toggle__sun { display: block; }
@media (max-width: 46rem) {
  .nav { gap: 1.1rem; }
  .nav a { font-size: .82rem; }
  .site-header__inner { gap: .75rem; }
  .wordmark { font-size: 1.02rem; }
}

/* --- Nav dropdown --------------------------------------------------------- */
/* <details>/<summary> rather than a hover menu: this site ships no JavaScript,
   and a CSS hover menu is unusable on touch. A disclosure works with a tap, a
   click and a keyboard, natively. */
.nav-dd { position: relative; }
.nav-dd > summary {
  list-style: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: .35rem;
  color: var(--text-muted); font-size: var(--step--1); font-weight: 550;
  letter-spacing: -0.005em; padding-block: .35rem;
  border-bottom: 2px solid transparent;
}
.nav-dd > summary::-webkit-details-marker { display: none; }
.nav-dd > summary::marker { content: ""; }
.nav-dd > summary::after {
  content: ""; width: .38rem; height: .38rem; margin-top: -.18rem;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); transition: transform .15s ease;
}
.nav-dd[open] > summary::after { transform: rotate(-135deg); margin-top: .1rem; }
.nav-dd > summary:hover,
.nav-dd[open] > summary { color: var(--ink); }
.nav-dd > summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.nav-dd.is-active > summary { color: var(--ink); border-bottom-color: var(--accent); }

.nav-dd__panel {
  position: absolute; top: calc(100% + .55rem); right: 0; z-index: 60;
  display: flex; flex-direction: column; gap: .1rem;
  min-width: 12rem; padding: .4rem;
  background: var(--surface-raised);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}
.nav-dd__panel a {
  padding: .5rem .7rem; border-radius: var(--radius-sm);
  border-bottom: 0; white-space: nowrap; color: var(--text-muted);
}
.nav-dd__panel a:hover { background: var(--surface-sunk); color: var(--ink); }
.nav-dd__panel a[aria-current="page"] { color: var(--accent); background: var(--accent-soft); }
@media (max-width: 30rem) {
  .nav-dd__panel { right: auto; left: 50%; transform: translateX(-50%); }
}

/* --- Page head ------------------------------------------------------------ */
.page-head { padding-block: clamp(2.75rem, 6vw, 4.5rem) clamp(1.75rem, 3vw, 2.5rem); }
.page-head__eyebrow {
  display: inline-block; font-size: var(--step--1); font-weight: 640;
  letter-spacing: .06em; text-transform: uppercase; color: var(--accent);
  margin-bottom: .85rem;
}
.page-head h1 { font-size: var(--step-4); max-width: 26ch; }
.page-head__lede {
  font-size: var(--step-1); color: var(--text-muted);
  max-width: 56ch; margin-top: 1.1rem; line-height: 1.5;
}
.page-head__meta {
  margin-top: 1.75rem; display: flex; flex-wrap: wrap; gap: .5rem 2rem;
  font-size: var(--step--1); color: var(--text-faint);
}
.page-head__meta dt { font-weight: 620; color: var(--text-muted); }
.page-head__meta dd { margin-left: 0; }
.page-head__meta > div { display: flex; gap: .4rem; }

/* --- Notice callout ------------------------------------------------------- */
.notice {
  border: 1px solid var(--accent-border);
  background: var(--accent-soft);
  border-radius: var(--radius);
  padding: 1.1rem 1.35rem;
  margin-block: 2rem;
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--text);
}
.notice > * + * { margin-top: .6rem; }
.notice strong { color: var(--ink); }
.notice--plain { background: var(--surface-sunk); border-color: var(--border); }

/* --- Prose (legal documents, articles) ------------------------------------ */
.prose { max-width: var(--measure); padding-bottom: clamp(3rem, 7vw, 5rem); }
.prose > * + * { margin-top: 1.15rem; }

.prose h2 {
  font-size: var(--step-2);
  margin-top: 3.25rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--border);
  scroll-margin-top: 6rem;
}
.prose h2:first-of-type { margin-top: 2.5rem; }
.prose h3 { font-size: var(--step-1); margin-top: 2.25rem; scroll-margin-top: 6rem; }

.prose ul, .prose ol { padding-left: 1.35rem; }
.prose li + li { margin-top: .5rem; }
.prose li::marker { color: var(--text-faint); }

.prose strong { color: var(--ink); font-weight: 650; }
.prose em { color: var(--text-muted); }

.prose hr { border: 0; border-top: 1px solid var(--border); margin-block: 2.5rem; }

/* Numbered legal clauses: 1.1, 4.3 - hanging indent keeps the number in the gutter */
.clause { display: grid; grid-template-columns: 3.1rem 1fr; align-items: baseline; }
.clause + .clause { margin-top: .9rem; }
.clause__n {
  font-variant-numeric: tabular-nums; font-weight: 640;
  color: var(--text-faint); font-size: var(--step--1);
}
@media (max-width: 34rem) {
  .clause { grid-template-columns: 2.6rem 1fr; }
}

/* Placeholder token: [Club] etc. - visibly a slot to be filled */
.ph {
  font-family: var(--font-mono); font-size: .86em; font-weight: 600;
  color: var(--accent); background: var(--accent-soft);
  border: 1px dashed var(--accent-border);
  border-radius: var(--radius-sm);
  padding: .1em .45em; white-space: nowrap;
}
.ph--wide { white-space: normal; }

/* --- Tables --------------------------------------------------------------- */
.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  margin-block: 1.75rem;
  -webkit-overflow-scrolling: touch;
}
.table-scroll table { border-collapse: collapse; width: 100%; min-width: 32rem; font-size: var(--step--1); }
.table-scroll th, .table-scroll td {
  text-align: left; padding: .8rem 1.1rem; vertical-align: top;
  border-bottom: 1px solid var(--border);
}
.table-scroll thead th {
  background: var(--surface-sunk); color: var(--ink);
  font-weight: 640; font-size: .82rem; letter-spacing: .03em; text-transform: uppercase;
  white-space: nowrap;
}
.table-scroll tbody tr:last-child td { border-bottom: 0; }
.table-scroll tbody td:first-child { color: var(--ink); font-weight: 540; }

/* --- Table of contents ---------------------------------------------------- */
.toc {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-sunk);
  padding: 1.25rem 1.5rem; margin-block: 2rem;
}
.toc h2 {
  font-size: .78rem !important; text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-faint); margin: 0 0 .85rem !important;
  border: 0 !important; padding: 0 !important;
}
.toc ol { list-style: none; padding: 0; margin: 0; columns: 2; column-gap: 2rem; }
.toc li { margin: 0 0 .5rem; break-inside: avoid; font-size: var(--step--1); }
.toc a { color: var(--text-muted); text-decoration: none; }
.toc a:hover { color: var(--accent); text-decoration: underline; }
.toc__n { font-variant-numeric: tabular-nums; color: var(--text-faint); margin-right: .45rem; }
@media (max-width: 34rem) { .toc ol { columns: 1; } }

/* --- Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .7rem 1.3rem; border-radius: var(--radius-sm);
  font-size: var(--step--1); font-weight: 600; text-decoration: none;
  border: 1px solid transparent; cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.btn--primary { background: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-hover); color: #fff; }
.btn--ghost { border-color: var(--border-strong); color: var(--ink); background: transparent; }
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }

/* --- Site footer ---------------------------------------------------------- */
.site-footer {
  flex: none;
  border-top: 1px solid var(--border);
  background: var(--surface-sunk);
  padding-block: 2.75rem 2.25rem;
  font-size: var(--step--1);
  color: var(--text-muted);
}
/* Stacks on narrow screens. min(100%, ...) lets a track shrink below its
   preferred floor rather than forcing the page to scroll sideways. */
.site-footer__grid {
  display: grid; gap: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  padding-bottom: 2rem;
}
@media (min-width: 52rem) {
  .site-footer__grid {
    grid-template-columns: minmax(14rem, 1.5fr) repeat(auto-fit, minmax(9rem, 1fr));
  }
}
.site-footer h2 {
  font-size: .74rem; text-transform: uppercase; letter-spacing: .08em;
  color: var(--text-faint); font-weight: 640; margin-bottom: .9rem;
}
.site-footer ul { list-style: none; padding: 0; }
.site-footer li + li { margin-top: .5rem; }
.site-footer a { color: var(--text-muted); text-decoration: none; }
.site-footer a:hover { color: var(--accent); text-decoration: underline; }
.site-footer__blurb { max-width: 34ch; margin-top: .9rem; color: var(--text-faint); line-height: 1.6; }

.site-footer__legal {
  border-top: 1px solid var(--border);
  padding-top: 1.5rem;
  display: flex; flex-wrap: wrap; gap: .4rem 1.5rem;
  justify-content: space-between; align-items: baseline;
  font-size: .8rem; color: var(--text-faint);
}
.site-footer__legal p { max-width: 62ch; }

/* --- Hero ----------------------------------------------------------------- */
.hero { padding-block: clamp(2.25rem, 5vw, 3.75rem) clamp(2.5rem, 5vw, 3.5rem); }
/* 17ch forced a 58-character headline onto four lines on a 1120px canvas. */
.hero h1 { font-size: var(--step-4); max-width: 32ch; }
/* Wide enough for the one-sentence lede to hold a single line on a desktop
   width; it still wraps naturally on a phone. */
.hero__lede {
  font-size: var(--step-1); color: var(--text-muted);
  max-width: 80ch; margin-top: 1.25rem; line-height: 1.5;
}
.hero__actions { margin-top: 2.25rem; display: flex; gap: .75rem; flex-wrap: wrap; align-items: center; }
.hero__note { font-size: var(--step--1); color: var(--text-faint); }

/* --- Section rhythm ------------------------------------------------------- */
.section { padding-block: clamp(3rem, 7vw, 5rem); }
/* A band that opens with a working control rather than a heading. The full
   padding is sized for a section head and leaves a dead strip above a panel. */
.section--tight-top { padding-block-start: clamp(1.25rem, 3vw, 2rem); }
/* Before a test is chosen the calculator band holds only the two pickers, and
   the full band padding under them reads as a hole. Tighten it until the sheet
   is showing. (:has is fine here: older browsers just keep the space.) */
.section--tight-top:has(#sheet-body[hidden]) {
  padding-block-end: clamp(1.5rem, 3.5vw, 2.25rem);
}
.section--ruled { border-top: 1px solid var(--border); }
.section--sunk { background: var(--surface-sunk); border-block: 1px solid var(--border); }
/* Heading and body want different measures: a heading can run wider before it
   hurts, body copy should stay near 60ch. Capping the whole block at 60ch made
   short headings wrap for no reason. */
.section__head { margin-bottom: clamp(1.75rem, 4vw, 2.75rem); }
.section__eyebrow {
  display: block; font-size: var(--step--1); font-weight: 640;
  letter-spacing: .06em; text-transform: uppercase; color: var(--accent);
  margin-bottom: .75rem;
}
.section__head h2 { font-size: var(--step-3); max-width: 40ch; }
.section__head > p {
  font-size: var(--step-1); color: var(--text-muted);
  margin-top: .9rem; line-height: 1.5; max-width: 62ch;
}

/* --- Highlights strip ----------------------------------------------------- */
/* An at-a-glance scope summary for the top of a product page. Deliberately
   lighter than .feature cards further down the page: a top rule instead of a
   full border, so a reader scans it rather than reads it. */
.highlights__lead {
  font-size: var(--step-0); color: var(--text-muted);
  max-width: 68ch; margin: 0 0 1.75rem; line-height: 1.6;
}
.highlights__lead strong { color: var(--ink); font-weight: 620; }

.highlights {
  list-style: none; padding: 0;
  margin: 0 0 clamp(2.5rem, 5vw, 3.75rem);
  display: grid; gap: 1.75rem 2.25rem;
  /* 20rem yields exactly 3 columns at the 1120px wrap, so six items land as a
     clean 3x2 rather than 4 + 2 with a hole in the second row. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}
.highlights > div { border-top: 2px solid var(--accent); padding-top: .85rem; }
.highlights dt {
  font-size: 1rem; margin-bottom: .35rem; color: var(--ink);
  letter-spacing: -0.01em; font-weight: 640;
}
.highlights dd {
  margin: 0; font-size: var(--step--1);
  color: var(--text-muted); line-height: 1.55;
}

/* --- Feature grid --------------------------------------------------------- */
.features {
  display: grid; gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}
.feature {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-raised); padding: 1.35rem 1.45rem;
}
.feature h3 { font-size: 1.02rem; margin-bottom: .45rem; letter-spacing: -0.01em; }
.feature p { font-size: var(--step--1); color: var(--text-muted); line-height: 1.6; }

/* --- Tick list ------------------------------------------------------------ */
.checks {
  list-style: none; padding: 0; display: grid; gap: .9rem 2rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
}
.checks li { position: relative; padding-left: 1.9rem; font-size: var(--step--1); line-height: 1.6; }
.checks li::before {
  content: ""; position: absolute; left: 0; top: .38em;
  width: 1.1rem; height: 1.1rem; border-radius: 50%;
  background: var(--accent-soft); border: 1px solid var(--accent-border);
}
.checks li::after {
  content: ""; position: absolute; left: .33rem; top: .68em;
  width: .28rem; height: .5rem; border: solid var(--accent);
  border-width: 0 1.5px 1.5px 0; transform: rotate(45deg);
}
.checks strong { color: var(--ink); font-weight: 620; }

/* --- Split columns -------------------------------------------------------- */
.split {
  display: grid; gap: clamp(1.75rem, 4vw, 3.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 21rem), 1fr));
  align-items: start;
}
.split p + p { margin-top: 1rem; }
.split h3 { font-size: var(--step-1); margin-bottom: .75rem; }
.split p { color: var(--text-muted); }
.split p + h3 { margin-top: 1.75rem; }

/* Federation grid on the calculator. Names on cards rather than each body's
   logo: those are other organisations' marks, and reproducing them would imply
   an endorsement this tool does not have and has not asked for. */
.feds__lead { color: var(--text-muted); margin-bottom: 1.5rem; max-width: 60ch; }
.feds__lead strong { color: var(--ink); font-weight: 620; }
.feds {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: .75rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr));
}
.fed {
  display: flex; flex-direction: column; gap: .15rem; height: 100%;
  padding: .8rem 1rem; text-decoration: none;
  background: var(--surface-raised);
  border: 1px solid var(--border); border-radius: var(--radius);
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.fed:hover, .fed:focus-visible {
  border-color: var(--accent-border);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}
.fed__name { color: var(--ink); font-weight: 620; font-size: var(--step--1); }
.fed__meta { color: var(--text-faint); font-size: .8rem; }

/* --- Product cards -------------------------------------------------------- */
.products {
  display: grid; gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
}
.product {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-raised); box-shadow: var(--shadow-sm);
  padding: clamp(1.5rem, 3vw, 2.1rem);
  display: flex; flex-direction: column;
}
.product__badge {
  align-self: flex-start;
  font-size: .74rem; font-weight: 640; letter-spacing: .06em; text-transform: uppercase;
  padding: .3rem .7rem; border-radius: 100px; margin-bottom: 1rem;
  background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent-border);
}
.product__badge--soon {
  background: var(--surface-sunk); color: var(--text-faint); border-color: var(--border-strong);
}
.product h3 { font-size: var(--step-2); margin-bottom: .3rem; }
.product__tag {
  font-size: var(--step--1); color: var(--text-faint);
  margin-bottom: 1rem; font-weight: 550;
}
.product > p { color: var(--text-muted); }
.product > p + p { margin-top: .85rem; }
.product__shot {
  display: block; margin: 0 0 1.35rem;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  overflow: hidden; background: var(--surface-sunk);
}
/* Crop to a band rather than showing the whole 2400x1520 frame. At card width
   the full screenshot dominates, and the top strip (chrome, nav, first tiles)
   is the part that reads as "this is a real application" anyway. */
.product__shot img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 7;
  object-fit: cover; object-position: top left;
}

.product__list { list-style: none; padding: 0; margin: 1.25rem 0 0; }
.product__list li {
  font-size: var(--step--1); color: var(--text-muted);
  padding-left: 1.1rem; position: relative; line-height: 1.55;
}
.product__list li + li { margin-top: .45rem; }
.product__list li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: .3rem; height: .3rem; border-radius: 50%; background: var(--accent);
}
.product__foot { margin-top: auto; padding-top: 1.6rem; display: flex; gap: .6rem; flex-wrap: wrap; }

/* --- Stat row ------------------------------------------------------------- */
.stats {
  display: grid; gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
}
.stat { border-left: 2px solid var(--accent); padding-left: 1.1rem; }
.stat__n { display: block; font-size: var(--step-2); font-weight: 660; color: var(--ink); letter-spacing: -0.02em; }
.stat__l { display: block; font-size: var(--step--1); color: var(--text-muted); margin-top: .3rem; line-height: 1.5; }

/* --- Pull quote ----------------------------------------------------------- */
/* For showing the product's own output as evidence, rather than describing it. */
.pullquote {
  margin: 1.75rem 0 0;
  padding: 1.35rem 1.6rem;
  border-left: 3px solid var(--accent);
  background: var(--surface-sunk);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.pullquote p {
  font-size: var(--step-0); line-height: 1.6;
  color: var(--text); font-style: italic;
}
.pullquote cite {
  display: block; margin-top: .8rem; font-style: normal;
  font-size: var(--step--1); color: var(--text-faint);
}

/* --- Fine print ----------------------------------------------------------- */
.fineprint {
  font-size: .8rem; line-height: 1.6; color: var(--text-faint);
  padding-block: clamp(1.25rem, 3vw, 2rem) clamp(2rem, 5vw, 3rem);
}
.fineprint a { color: var(--text-muted); }

/* --- Product screenshots -------------------------------------------------- */
.shot { margin: 0; }
.shot img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  background: var(--surface-raised);
}
.shot figcaption {
  font-size: var(--step--1); color: var(--text-faint);
  margin-top: .9rem; line-height: 1.55; max-width: 68ch;
}
.shot figcaption strong { color: var(--text-muted); font-weight: 620; }

/* --- Call to action panel ------------------------------------------------- */
.cta {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-raised); box-shadow: var(--shadow-sm);
  padding: clamp(1.75rem, 4vw, 2.75rem);
}
.cta h2 { font-size: var(--step-2); max-width: 34ch; }
.cta p { color: var(--text-muted); max-width: 52ch; margin-top: .85rem; }
.cta__actions { margin-top: 1.75rem; display: flex; gap: .75rem; flex-wrap: wrap; }

/* --- Dressage calculator -------------------------------------------------- */
/* No top margin. The calculator is the first thing in its band, so the section's
   own padding is the whole gap; anything here is added on top of it and leaves a
   dead strip above the setup panel that no other band has. */

.calc__setup {
  --calc-row-gap: 1.25rem;
  display: flex; flex-wrap: wrap; gap: var(--calc-row-gap) 1.75rem; align-items: flex-end;
  padding: 1.25rem 1.5rem; margin-bottom: 1.5rem;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-raised);
}
/* The second control strip, under the sheet: errors of course are recorded once
   the test has been ridden, not while setting the sheet up. */
.calc__setup--after { margin-top: 1.5rem; margin-bottom: 0; }

/* Forces the fields after it onto a new line inside the flex row, so rider and
   horse sit under the pickers rather than trailing off the end of them.

   It is a flex item on a line of its own, so it collects a row gap above AND
   below and silently doubles the space between the two rows. The negative
   margin takes one of those back and trims a little more. */
.calc__break {
  flex-basis: 100%; height: 0;
  margin: calc(var(--calc-row-gap) * -1 - 0.35rem) 0 0;
}
.calc__opt { font-weight: 400; font-size: .74rem; color: var(--text-faint); }

/* Sheet identity: what has been chosen on the left, what you can do with it on
   the right. This is also the top of what Print and Save put on paper. */
.calc__head {
  display: flex; flex-wrap: wrap; gap: .75rem 1.5rem;
  align-items: flex-end; justify-content: space-between;
  margin-bottom: 1rem;
}
.calc__title { font-size: var(--step-2); }
.calc__who { font-size: var(--step-0); color: var(--text-muted); margin-top: .15rem; }
.calc__head-actions { display: flex; gap: .6rem; }
.calc__head-actions .btn[disabled] { opacity: .45; cursor: not-allowed; }

/* Built on demand by the Print and Save buttons. Hidden on screen; the print
   rule below is what reveals it, and only when a button asked for it. */
#sheet-print { display: none; }

@media print {
  /* Deliberately scoped to the class the buttons add. A plain @media print rule
     would also hijack the browser's own Ctrl+P, and printing the whole page is
     supposed to stay the browser's job. */
  body.printing-sheet > * { display: none !important; }
  body.printing-sheet > #sheet-print { display: block !important; }
}
.calc__field { display: flex; flex-direction: column; gap: .35rem; }
.calc__field label { font-size: var(--step--1); font-weight: 620; color: var(--text-muted); }
.calc__field input, .calc__field select {
  font: inherit; font-size: var(--step--1);
  padding: .45rem .6rem; min-width: 6rem;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text);
}
.calc__field select { min-width: 12rem; }

/* Totals follow you down a long sheet, which is the whole point of them. */
/* Sticks below the sticky header. The header's real height depends on how the
   title wraps on a narrow screen, so site.js measures it into --header-h; the
   fallback covers the single-line desktop header if that script never runs. */
.calc__totals {
  position: sticky; top: calc(var(--header-h, 4.35rem) + .35rem); z-index: 40;
  display: flex; flex-wrap: wrap; gap: .3rem 1.5rem; align-items: baseline;
  padding: .8rem 1.1rem; margin-bottom: 1.5rem;
  border: 1px solid var(--accent-border); border-radius: var(--radius);
  background: var(--accent-soft);
}
.calc__pct { font-size: var(--step-2); font-weight: 680; color: var(--ink); letter-spacing: -0.02em; }
.calc__stat { font-size: var(--step--1); color: var(--text-muted); }
.calc__stat strong { color: var(--ink); font-weight: 640; }
.calc__stat--bad strong, .calc__stat--bad { color: #b4232f; }

.calc__note { font-size: var(--step--1); color: var(--text-muted); margin-top: .3rem; width: 100%; }
.calc__note--good { color: #1c6b3f; }
.calc__note--bad { color: #b4232f; font-weight: 620; }

/* Test preset picker and the line that confirms what it built. Showing the
   expected maximum lets someone catch a wrong selection against their paper. */
.calc__field--wide select,
.calc__field--wide input[type="text"] { min-width: 16rem; }
.calc__preset-note {
  /* Sits under the sheet now, so the margin goes on top. The control strip
     below carries its own 1.5rem and the two collapse to one gap. */
  margin: 1.5rem 0 0; max-width: 74ch;
  font-size: var(--step--1); color: var(--text-muted);
  background: var(--accent-soft); border: 1px solid var(--accent-border);
  border-left: 3px solid var(--accent);
  padding: .65rem .9rem; border-radius: 6px;
}
.calc__preset-note--bad {
  background: #fdf2f2; border-color: #f0c4c4; border-left-color: #b4232f;
  color: #b4232f;
}

/* Locked while a test is chosen, because the test decides the shape of the
   sheet. Errors of course stays live: that is the ride, not the test. */
.calc__field input:disabled,
.calc__field select:disabled {
  background: var(--surface-sunk); color: var(--text-faint);
  border-color: var(--border); cursor: not-allowed;
}
.calc__field:has(input:disabled) label,
.calc__field:has(select:disabled) label { color: var(--text-faint); }
/* Doubled up on purpose: .calc__coeff sets cursor: pointer further down the
   file and would win the tie at equal specificity. */
.calc__coeff.calc__coeff--locked { opacity: .45; cursor: not-allowed; }
.calc__coeff.calc__coeff--locked input { cursor: not-allowed; }

.calc__grids { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }
.calc h2, .calc h3 { font-size: var(--step-1); margin-bottom: .75rem; }

.calc table { border-collapse: collapse; width: 100%; font-size: var(--step--1); }
.calc thead th {
  text-align: left; padding: .5rem .6rem; white-space: nowrap;
  font-size: .78rem; letter-spacing: .03em; text-transform: uppercase;
  color: var(--text-faint); border-bottom: 1px solid var(--border-strong);
}
.calc tbody th, .calc tbody td {
  padding: .3rem .6rem; border-bottom: 1px solid var(--border); vertical-align: middle;
}
.calc tbody th { font-weight: 620; color: var(--text); text-align: left; }
.calc__rowtotal { text-align: right; font-variant-numeric: tabular-nums; color: var(--text-muted); }

/* Editable collective name, custom sheets only. Sized to sit in the row without
   making it taller than the marks beside it. */
.calc__cname {
  width: 100%; min-width: 5rem;
  font: inherit; font-size: var(--step--1); font-weight: 620; color: var(--text);
  padding: .2rem .4rem;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.calc__cname:hover { border-color: var(--border-strong); }
.calc__cname:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }

.calc__mark {
  font: inherit; font-size: var(--step--1); width: 5rem;
  padding: .3rem .45rem; text-align: center;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text);
}
.calc__coeff { display: inline-flex; align-items: center; gap: .3rem; font-size: var(--step--1); color: var(--text-muted); cursor: pointer; }

/* Any click on a row lands in its mark box (wired in dressage.js). */
.calc tbody tr { cursor: pointer; }

/* The same heat tint scorers see in the app: insufficient through to blue at 7.5. */
.calc tbody tr.is-h1 { background: #f6d0d5; }
.calc tbody tr.is-h2 { background: #fcecc5; }
.calc tbody tr.is-h3 { background: #f0f3c0; }
.calc tbody tr.is-h4 { background: #d9edc0; }
.calc tbody tr.is-h5 { background: #c4e4ad; }
.calc tbody tr.is-h6 { background: #cfe2ff; }

.calc__actions { margin-top: 1.5rem; display: flex; gap: .75rem; flex-wrap: wrap; align-items: center; }

.hero__install-note {
  margin-top: .75rem; font-size: var(--step--1); color: var(--text-muted);
  max-width: 55ch;
}

/* The one-line instruction above the federation and test pickers. */
.calc__intro {
  margin: 0 0 1.1rem; color: var(--text-muted); max-width: 68ch;
}

/* Sits beside the rider and horse name boxes, explaining what they are for. */
.calc__names-note {
  align-self: flex-end; margin: 0 0 .6rem;
  font-size: var(--step--1); color: var(--text-faint);
}

/* Names the error-of-course rule in force, under the errors dropdown. */
.calc__errors-note {
  margin: .6rem 0 0; font-size: var(--step--1); color: var(--text-muted);
  max-width: 68ch;
}

.calc__noscript {
  border: 1px solid var(--accent-border); background: var(--accent-soft);
  border-radius: var(--radius); padding: 1.1rem 1.35rem; font-size: var(--step--1);
}

@media (max-width: 40rem) {
  .calc__mark { width: 4rem; }
  /* A phone has no height to spare: the header scrolls away instead of
     sticking, and the score box compacts and pins near the very top. */
  .site-header { position: static; }
  .calc__totals {
    top: .4rem; gap: .15rem 1rem; padding: .55rem .85rem;
    margin-bottom: 1rem;
  }
  .calc__pct { font-size: 1.4rem; }
  .calc__note { font-size: .78rem; }
}

/* --- Utilities ------------------------------------------------------------ */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.text-muted { color: var(--text-muted); }
.mt-0 { margin-top: 0 !important; }

/* --- Dark theme, hard-coded colours --------------------------------------- */
/* Everything token-driven recolours itself; these are the few literals. The
   same duplication rule as the tokens applies: media-query block and
   data-theme block must stay identical. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .calc tbody tr.is-h1 { background: #4a2329; }
  :root:not([data-theme="light"]) .calc tbody tr.is-h2 { background: #4a3a17; }
  :root:not([data-theme="light"]) .calc tbody tr.is-h3 { background: #3f421c; }
  :root:not([data-theme="light"]) .calc tbody tr.is-h4 { background: #2d4322; }
  :root:not([data-theme="light"]) .calc tbody tr.is-h5 { background: #2c5024; }
  :root:not([data-theme="light"]) .calc tbody tr.is-h6 { background: #223c63; }
  :root:not([data-theme="light"]) .calc__stat--bad,
  :root:not([data-theme="light"]) .calc__stat--bad strong { color: #f0919b; }
  :root:not([data-theme="light"]) .calc__note--good { color: #82d3a4; }
  :root:not([data-theme="light"]) .calc__note--bad { color: #f0919b; }
  :root:not([data-theme="light"]) .calc__preset-note--bad {
    background: #3a1d21; border-color: #5c2e35; border-left-color: #f0919b;
    color: #f0919b;
  }
}
:root[data-theme="dark"] .calc tbody tr.is-h1 { background: #4a2329; }
:root[data-theme="dark"] .calc tbody tr.is-h2 { background: #4a3a17; }
:root[data-theme="dark"] .calc tbody tr.is-h3 { background: #3f421c; }
:root[data-theme="dark"] .calc tbody tr.is-h4 { background: #2d4322; }
:root[data-theme="dark"] .calc tbody tr.is-h5 { background: #2c5024; }
:root[data-theme="dark"] .calc tbody tr.is-h6 { background: #223c63; }
:root[data-theme="dark"] .calc__stat--bad,
:root[data-theme="dark"] .calc__stat--bad strong { color: #f0919b; }
:root[data-theme="dark"] .calc__note--good { color: #82d3a4; }
:root[data-theme="dark"] .calc__note--bad { color: #f0919b; }
:root[data-theme="dark"] .calc__preset-note--bad {
  background: #3a1d21; border-color: #5c2e35; border-left-color: #f0919b;
  color: #f0919b;
}

@media print {
  .site-header, .site-footer, .toc, .skip { display: none !important; }
  body { color: #000; background: #fff; }
  .prose { max-width: none; }
  .prose h2 { break-after: avoid; }
  .table-scroll { overflow: visible; }
}
