/* Shared site chrome: design tokens, header, footer, and buttons.
   Loaded first by every page — landings included — so the nav, header height,
   font stack and spacing stay identical as you click between them.

   Everything visual on this site resolves to a token declared below. That is
   enforced, not encouraged: tools/verify-layout.mjs reads these custom
   properties, resolves them at each viewport, and fails the run if any painted
   element renders a font size, radius, spacing step or family that is not one
   of them. Before this file had a scale the 26 pages rendered 19 font sizes,
   28 spacing values and 7 radii; adding a raw `font-size: 27px` now breaks CI
   rather than quietly widening the set again. */

/* ==========================================================================
   THE TYPEFACES, AND WHY THEY ARE HERE RATHER THAN ON A CDN

   Three files, same origin, 208 KB in total. They used to come from
   fonts.googleapis.com, which is a second DNS lookup, a second TLS handshake
   and a third party in the request path of a site whose privacy page makes
   promises about third parties. Nothing about the type needed that.

   Each file is one variable font subset to the repertoire this site actually
   sets: ASCII, the Latin-1 letters, the Turkish set, and the punctuation and
   currency signs the copy uses — `₺` (U+20BA) among them. The declared
   `unicode-range` below is the whole contract, and `test/font-hosting.test.js`
   reads it out of this file and asserts that every character on all 26 pages
   in both languages falls inside it. A subset that stops covering the copy is
   therefore a red test rather than a paragraph that silently changes typeface
   halfway through a Turkish word.

   The two `fallback` faces are not decoration either. A fallback of the wrong
   width gives a different line box, so text reflows when the real font lands —
   the "every click changes the layout" complaint, arriving on first paint. The
   overrides below were measured (Archivo against Arial, Literata against
   Georgia, on the same string) so the fallback occupies the same space the
   real face will.

   `font-display: block` rather than `swap`, and the reason is measured. Even
   with the overrides the match is close, not exact: size-adjust equalises a
   whole string but not the individual advances, so a paragraph sitting near a
   line-break boundary can wrap to four lines in the fallback and three in the
   real face. Under `swap` that reflow paints, and `tools/verify-landing.mjs`
   scored it at 0.0666 on a 400ms font delay — one 42px line of body copy
   dragging everything below it. Under `block` the same reflow happens while
   the text is still unpainted, so the layout is final by the time anything is
   legible: the same measurement scores 0.0003. The cost of `block` is up to
   3s of invisible text, and it is bought down to near zero here — the faces
   are same-origin, preloaded in the document head, and 208KB subsetted for
   all three. That trade is the right way round for this page: a reader who
   waits 30ms longer for the first paint has lost nothing, and a reader whose
   text reflows under their eyes has lost the argument the page is making.
   ========================================================================== */
@font-face {
  font-family: Archivo;
  src: url("./fonts/archivo.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: block;
  unicode-range: U+20-7e, U+a0, U+a3, U+a5, U+a9, U+ab, U+ad-ae, U+b0-b1, U+b7, U+bb, U+c0-c2, U+c4-c9,
    U+cb, U+cd-cf, U+d1, U+d3, U+d6-d8, U+da-dc, U+df-e2, U+e4-e9, U+eb, U+ed-ef, U+f1, U+f3, U+f6-f8,
    U+fa-fc, U+11e-11f, U+130-131, U+15e-15f, U+2011, U+2013-2014, U+2018-2019, U+201c-201e, U+2020-2022,
    U+2026, U+2030, U+2039-203a, U+20ac, U+20b4, U+20ba, U+20bd, U+2122, U+2190-2193, U+2248, U+2260,
    U+2264-2265;
}
@font-face {
  font-family: Literata;
  src: url("./fonts/literata.woff2") format("woff2");
  font-weight: 200 900;
  font-style: normal;
  font-display: block;
  unicode-range: U+20-7e, U+a0, U+a3, U+a5, U+a9, U+ab, U+ad-ae, U+b0-b1, U+b7, U+bb, U+c0-c2, U+c4-c9,
    U+cb, U+cd-cf, U+d1, U+d3, U+d6-d8, U+da-dc, U+df-e2, U+e4-e9, U+eb, U+ed-ef, U+f1, U+f3, U+f6-f8,
    U+fa-fc, U+11e-11f, U+130-131, U+15e-15f, U+2011, U+2013-2014, U+2018-2019, U+201c-201e, U+2020-2022,
    U+2026, U+2030, U+2039-203a, U+20ac, U+20b4, U+20ba, U+20bd, U+2122, U+2190-2193, U+2248, U+2260,
    U+2264-2265;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("./fonts/plex-mono.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
  unicode-range: U+20-7e, U+a0, U+a3, U+a5, U+a9, U+ab, U+ad-ae, U+b0-b1, U+b7, U+bb, U+c0-c2, U+c4-c9,
    U+cb, U+cd-cf, U+d1, U+d3, U+d6-d8, U+da-dc, U+df-e2, U+e4-e9, U+eb, U+ed-ef, U+f1, U+f3, U+f6-f8,
    U+fa-fc, U+11e-11f, U+130-131, U+15e-15f, U+2011, U+2013-2014, U+2018-2019, U+201c-201e, U+2020-2022,
    U+2026, U+2030, U+2039-203a, U+20ac, U+20b4, U+20ba, U+20bd, U+2122, U+2190-2193, U+2248, U+2260,
    U+2264-2265;
}
/* ==========================================================================
   THE METRIC-MATCHED STAND-INS — ONE FACE PER WEIGHT, AND PER WIDTH

   Measured, not guessed: 100px of each real face against 100px of the bare
   local stand-in, on this page's own Turkish sentence, in Chromium.
   tools/verify-font.mjs re-measures every pair below and fails the run if one
   stops standing in for the same space.

   Why there are eleven of these and not two. The local stand-ins do not cover
   the weights the shipped families do — Georgia has no semibold, Helvetica has
   no medium — so the browser synthesises them, and a synthesised weight does
   not widen the way a real one does. Measured on the same string, Helvetica
   returns exactly 2612.8px at every weight from 400 to 800, while Archivo runs
   from 2557px at 400 to 2853px at 800. One `size-adjust` cannot describe that:
   at 97.8%, which is right for Archivo 400, the 800 headline stands in 10.4%
   too narrow, and at 104.8% Literata's 300 stand-in is 5% too wide. Both of
   those are several times the 2% tolerance the shift tool enforces.
   `font-weight` on the face is what lets each one be right.

   Width is the same problem again. The headline sets Archivo at 88% of normal
   width and the section heads at 92%; the stand-ins have no width axis at all,
   so `font-stretch: 88%` on a Helvetica face changes nothing and the ratio has
   to absorb the whole condensation. CSS matches `font-stretch` before
   `font-weight`, so a face per (width, weight) pair resolves exactly.

   Helvetica and Arial measure identically here, so one src covers macOS and
   Windows. Georgia only for the serif: Times New Roman is 14% narrower and
   would need its own set. If Georgia is absent the stack falls through to the
   plain families, which is the behaviour this replaces rather than breaks.

   Under `font-display: block` none of this is normally painted — that is the
   point of `block`, and it is why the CLS measurement is 0. These faces are
   what the page falls back to when a woff2 does not arrive at all, and what
   holds the layout in the three seconds before `block` gives up. They are the
   floor, not the common case, and a floor that is 10% out is still a page that
   reflows in front of a reader who is having a bad network day.
   ========================================================================== */
@font-face {
  font-family: "Archivo fallback";
  src: local("Helvetica"), local("Arial");
  font-weight: 400;
  size-adjust: 97.9%;
  ascent-override: 87.8%;
  descent-override: 21%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Archivo fallback";
  src: local("Helvetica"), local("Arial");
  font-weight: 500;
  size-adjust: 99.4%;
  ascent-override: 87.8%;
  descent-override: 21%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Archivo fallback";
  src: local("Helvetica"), local("Arial");
  font-weight: 600;
  size-adjust: 101.1%;
  ascent-override: 87.8%;
  descent-override: 21%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Archivo fallback";
  src: local("Helvetica"), local("Arial");
  font-weight: 700 900;
  size-adjust: 104.3%;
  ascent-override: 87.8%;
  descent-override: 21%;
  line-gap-override: 0%;
}
/* The three condensed cuts. `.tanim dt` sets 94%, the section heads 92%, and
   the masthead 88%; each is a different amount of narrowing for the stand-in
   to make up, and each is measured at the weight it is actually used at. */
@font-face {
  font-family: "Archivo fallback";
  src: local("Helvetica"), local("Arial");
  font-stretch: 94%;
  font-weight: 500 600;
  size-adjust: 96.2%;
  ascent-override: 87.8%;
  descent-override: 21%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Archivo fallback";
  src: local("Helvetica"), local("Arial");
  font-stretch: 92%;
  font-weight: 700;
  size-adjust: 97.4%;
  ascent-override: 87.8%;
  descent-override: 21%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Archivo fallback";
  src: local("Helvetica"), local("Arial");
  font-stretch: 88%;
  font-weight: 800 900;
  size-adjust: 98.1%;
  ascent-override: 87.8%;
  descent-override: 21%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Literata fallback";
  src: local("Georgia");
  font-weight: 100 300;
  size-adjust: 99.8%;
  ascent-override: 117.7%;
  descent-override: 30.8%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Literata fallback";
  src: local("Georgia");
  font-weight: 400;
  size-adjust: 103.7%;
  ascent-override: 117.7%;
  descent-override: 30.8%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Literata fallback";
  src: local("Georgia");
  font-weight: 500;
  size-adjust: 105.9%;
  ascent-override: 117.7%;
  descent-override: 30.8%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Literata fallback";
  src: local("Georgia");
  font-weight: 600 900;
  size-adjust: 107.8%;
  ascent-override: 117.7%;
  descent-override: 30.8%;
  line-gap-override: 0%;
}

:root {
  /* ---- surfaces. Newsprint, not cream.

          The old ground was #f6f1e8 — a warm cream at 95% lightness, which is
          the default background of every generated landing page of the last
          two years. This one is the stock a price list is actually printed on:
          the same warmth, four points darker and pulled off the yellow, so
          that a sheet laid on it (--card) and a rule drawn on it (--ink) both
          read as separate things rather than as a tint of the paper. On cream
          the hairlines had to be dark to be seen at all; here they can stay
          light, which is what lets a page be built out of rules. ---------- */
  --paper: #eae7dd;
  --card: #f8f6f0;
  --sand: #dbd5c4;

  /* ---- text. Every pairing below was recomputed against the new ground
          rather than carried over, and the worst of them is 4.85:1. ------ */
  --ink: #161410; /* 14.9:1  AAA */
  --muted: #5f574c; /*  5.8:1  AA  */

  /* ---- lines. --line is structural here rather than decorative — the grid
          is drawn with it — so it went from 1.5:1 to 1.8:1, dark enough to
          hold a column edge and still light enough not to read as a box.
          Any control edge a user must perceive uses --control-line (3.2:1),
          which clears the 3:1 floor in WCAG 1.4.11. A rule that carries
          hierarchy rather than separation is --ink at 14.9:1. ----------- */
  --line: #b7ae9b;
  --control-line: #8a7f6d;

  /* ---- brand and semantics.

          Untouched, and that is the palette's argument. On this site colour
          is vocabulary: --buy means the price fell and --cactus means this is
          the thing to press, --wait means hold off. A page that also spends
          green on a badge, a step number, a tinted card and a border is
          spending the product's only words on decoration, and by the fourth
          use the shopper has stopped reading it as meaning anything. So the
          page below is ink on paper, and colour appears where Kelly speaks.
          ------------------------------------------------------------------ */
  --cactus: #1d5c45; /*  6.4:1 on --paper */
  --cactus-deep: #134233;
  --cactus-tint: #e2efe6;
  --on-cactus: #f7f3ea; /*  7.1:1 on --cactus */
  --gold: #f4c95d;
  --buy: #166534; /*  5.8:1  the price fell — good for the shopper */
  --wait: #9a3412; /*  5.9:1  the price rose — hold off */
  --wait-tint: #f6e6dd;

  /* ---- type. Two faces and a mono, each with a job.

          --font-sans is Archivo (Omnibus-Type): a grotesque with a real width
          axis, 62% to 125%. Turkish headline setting is condensed grotesk —
          look at any newspaper on any pavement in Istanbul — and a width axis
          is how you get that from the same file that sets the nav, rather than
          by tracking a normal-width face until it looks wrong. It runs the
          furniture and the data.

          --font-serif is Literata (TypeTogether): a text serif with an optical
          size axis, 7pt to 72pt, so the 100px figure and the 17px paragraph
          are genuinely different cuts of one face instead of one outline
          scaled. It does the reading and the numbers.

          --font-mono stays IBM Plex Mono. It sets machine strings — an ASIN,
          a code block — and it is the only face here whose job is to look
          typed. It carries ₺ and the Turkish set, measured, so there was no
          reason to replace it except novelty.

          All three drew ₺ (U+20BA) and ı İ ğ Ğ ş Ş ç Ç ö ü themselves rather
          than through a fallback, and all three keep figures tabular, both
          proven by measurement in tools/verify-font.mjs. Fraunces was the
          first choice for the serif and lost there: it has the lira sign but
          no `tnum` feature at all, so a column of prices in it cannot be made
          to line up. --------------------------------------------------- */
  --font-sans: Archivo, "Archivo fallback", ui-sans-serif, system-ui, sans-serif;
  --font-serif: Literata, "Literata fallback", Georgia, serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  /* ---- type scale: 12 names, 11 rendered sizes at any one viewport.
          --t-display is the marketing hero and nothing else; --t-h1 is the
          title on the other 24 pages, which are dense and do not want 68px
          of serif above a data table.

          --t-display was clamp(38px, 5.4vw, 62px). 62px is a large heading;
          it is not a display size, and at 1920px it left the hero looking
          like a page that had been told to be bold rather than one that was.
          It now reaches 104px, which on a 1120px measure is a headline that
          sets "Pahalıya alma." in two words across seven columns and does the
          work the pill badge and the four value-prop boxes used to. ------ */
  --t-display: clamp(46px, 8vw, 104px);
  --t-h1: clamp(30px, 3.4vw, 40px);
  --t-h2: clamp(24px, 2.4vw, 30px);
  --t-price: 44px; /* a plan price, the one number sold as a headline */
  --t-stat: 30px; /* metric and stat-band values */
  --t-brand: 20px; /* the wordmark */
  --t-lg: 18px; /* lede, h3, card title */
  --t-body: 16px;
  --t-sm: 14px; /* dense UI: buttons, nav, table cells */
  --t-caption: 13px; /* notes, field labels, footer */
  --t-micro: 12px; /* column heads, row meta */
  --t-nano: 11px; /* pills, chart labels */

  /* ---- spacing: one 4px grid, 11 steps, no exceptions. --------------- */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 20px;
  --s-6: 24px;
  --s-8: 32px;
  --s-10: 40px;
  --s-12: 48px;
  --s-16: 64px;
  --s-20: 80px;

  /* ---- radii: 4 steps. sm = controls, md = cards, lg = the big mock,
          full = pills. The focus ring deliberately declares no radius of its
          own so the outline follows whatever it is drawn around.

          These were 8 / 12 / 16px, and at those values the corner radius was
          itself a design theme: every surface on the site was the same softly
          rounded rectangle, which is most of what makes a page read as
          assembled from a kit. They are now 2 / 3 / 4px — enough that nothing
          looks accidentally sharp, not enough to be a style. --r-full stays,
          because the two things using it are a language toggle and a
          price-drop chip, and both are genuinely capsules. -------------- */
  --r-sm: 2px;
  --r-md: 3px;
  --r-lg: 4px;
  --r-full: 999px;

  /* ---- elevation: 3 steps ------------------------------------------- */
  --shadow-sm: 0 1px 2px rgba(22, 20, 16, 0.05);
  --shadow-md: 0 4px 20px rgba(22, 20, 16, 0.06);
  --shadow-lg: 0 24px 60px rgba(22, 20, 16, 0.1);

  /* Drawn with box-shadow rather than a border so marking the current page
     adds no height and shifts nothing. It is a rule, not elevation, which is
     why it is named apart from the three steps above. */
  --marker-current: inset 0 -2px 0 var(--cactus);

  /* ---- layout: one container and one gutter at every width ---------- */
  --container: 1120px;
  --gutter: 20px;
  --header-h: 64px;
  --measure: 68ch;

  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

/* --------------------------------------------------------------------------
   Form controls and buttons are styled on the ELEMENT, not on a wrapper class.
   Three of the leaks in the audit — Arial, 13.3333px and a 4px radius — were
   all the same accident: a control that happened to sit outside a `.field`
   wrapper fell through to the user-agent stylesheet, which does not inherit
   font on form elements. Keying to the element means a control cannot end up
   unstyled however the markup around it is rearranged.
   -------------------------------------------------------------------------- */
input,
select,
textarea,
button {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  color: inherit;
  letter-spacing: inherit;
}

.wrap {
  width: min(var(--container), calc(100% - var(--gutter) * 2));
  margin: 0 auto;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  border-bottom: 1px solid var(--line);
  background: rgba(234, 231, 221, 0.88);
  backdrop-filter: blur(10px);
}
/* Fixed height at every breakpoint. The nav never wraps, so clicking between
   pages cannot shift the content down — see chrome-sync.test.js and the
   header-height check in tools/verify-layout.mjs, which asserts 64px on all
   26 pages at five widths. The border is inside the budget: 63 + 1 = 64.
   It used to be 64 + 1 = 65 on every page, one pixel over its own contract. */
.nav {
  display: flex;
  align-items: center;
  gap: var(--s-6);
  height: calc(var(--header-h) - 1px);
  min-height: calc(var(--header-h) - 1px);
}
.brand {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex: 0 0 auto;
  /* The wordmark is a link home on all 26 pages and was 28px tall — the
     height of the logo image — so it missed the 44px target everywhere. */
  min-height: 44px;
  color: var(--ink);
  text-decoration: none;
  /* The nameplate is the one place the serif is allowed to be a logotype
     rather than a reading face: a newspaper's own name is always set in its
     text serif, and Literata's optical size axis gives it the tighter,
     higher-contrast cut at 20px that a masthead wants. */
  font-family: var(--font-serif);
  font-size: var(--t-brand);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1;
  white-space: nowrap;
}
.brand img {
  display: block;
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
}
.nav-links {
  align-items: center;
  gap: var(--s-5);
  min-width: 0;
  flex-wrap: nowrap;
  font-family: var(--font-sans);
  font-size: var(--t-sm);
  color: var(--muted);
}
.nav-links a {
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s var(--ease);
}
.nav-links a:hover { color: var(--ink); }
/* Current page gets a marker, not just a weight change: a colour-and-weight
   difference alone is invisible to anyone who cannot separate --muted from --ink. */
.nav-links a[aria-current="page"] {
  color: var(--ink);
  font-weight: 600;
  box-shadow: var(--marker-current);
}
.mobile-nav a[aria-current="page"] {
  font-weight: 600;
  box-shadow: var(--marker-current);
}
.nav-end {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-left: auto;
  flex: 0 0 auto;
}
.langswitch {
  display: flex;
  flex: 0 0 auto;
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  background: var(--card);
  font-family: var(--font-sans);
  font-size: var(--t-nano);
  font-weight: 600;
}
.langswitch a,
.langswitch span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  min-height: 44px;
  padding: 0 var(--s-2);
  border-radius: var(--r-full);
  color: var(--muted);
  text-decoration: none;
  letter-spacing: 0.04em;
  line-height: 1;
  transition: color 0.15s var(--ease);
}
.langswitch a:hover { color: var(--ink); }
.langswitch [aria-current="true"] {
  background: var(--cactus);
  color: var(--on-cactus);
}
/* Nav links, the login link and the language pill all need to clear 44px on a
   phone; they are not <button>s so .btn's min-height does not reach them. */
.nav-links a,
.nav-login {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.nav-login {
  color: var(--muted);
  text-decoration: none;
  font-family: var(--font-sans);
  font-size: var(--t-sm);
  padding: 0 var(--s-1);
  white-space: nowrap;
}
.nav-login:hover { color: var(--ink); }

.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card);
  cursor: pointer;
}
.menu-toggle svg { display: block; stroke: var(--ink); }
.mobile-nav {
  display: grid;
  gap: var(--s-1);
  padding: var(--s-3) 0 var(--s-5);
  border-top: 1px solid var(--line);
  font-family: var(--font-sans);
  font-size: var(--t-body);
  max-height: calc(100vh - var(--header-h));
  overflow-y: auto;
}
.mobile-nav a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--s-2);
  border-radius: var(--r-sm);
  color: var(--ink);
  text-decoration: none;
}
.mobile-nav a:active { background: var(--sand); }
.mobile-nav a[aria-current="page"] { background: var(--cactus-tint); }
.mobile-nav .btn { justify-self: stretch; margin-top: var(--s-2); }

/* Set while the drawer is open so the page behind it cannot scroll. */
body.menu-open { overflow: hidden; }

/* --------------------------------------------------------------------------
   RESPONSIVE VISIBILITY — deliberately at two-class specificity.

   The install CTA was once invisible on phones because `.nav-install {
   display: none }` and `.btn { display: inline-flex }` are both 0-1-0, so the
   one written later silently won and which that was depended on the order of
   two blocks hundreds of lines apart. Every show/hide below is written as
   `parent > child`, which is 0-2-0 and therefore beats any single-class
   `display` rule no matter where it sits in the file. The bug is not fixed
   here so much as made unrepresentable.
   -------------------------------------------------------------------------- */
.nav > .nav-links { display: none; }
.nav-end > .nav-login { display: none; }
.nav-end > .menu-toggle { display: inline-flex; }

@media (min-width: 1024px) {
  .nav > .nav-links { display: flex; }
  .nav-end > .nav-login { display: inline-flex; }
  .nav-end > .menu-toggle { display: none; }
  .site-header .mobile-nav { display: none; }
}

/* `hidden` is an attribute the drawer script owns; it has to win over the
   grid display above, and does so on specificity rather than on order. */
.site-header .mobile-nav[hidden] { display: none; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 44px;
  padding: 0 var(--s-4);
  border: 1px solid var(--ink);
  border-radius: var(--r-sm);
  background: none;
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-sans);
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  transition: background-color 0.15s var(--ease), border-color 0.15s var(--ease), color 0.15s var(--ease);
}
.btn.primary {
  background: var(--cactus);
  border-color: var(--cactus);
  color: var(--on-cactus);
}
.btn.primary:hover { background: var(--cactus-deep); border-color: var(--cactus-deep); }
.btn.ghost { background: transparent; border-color: var(--line); color: var(--muted); }
.btn.ghost:hover { color: var(--ink); border-color: var(--control-line); }
.btn.secondary {
  background: var(--card);
  border-color: var(--control-line);
}
.btn.secondary:hover { background: var(--sand); }
.btn.lg { min-height: 48px; padding: 0 var(--s-5); font-size: var(--t-body); }
.btn[disabled],
.btn[aria-disabled="true"] { opacity: 0.45; pointer-events: none; }
button.btn {
  justify-self: start;
  cursor: pointer;
}
.btn[hidden],
button.btn[hidden] {
  display: none;
}

/* The install CTA stays reachable at every width, including on a phone, where
   it used to be hidden behind `sm:inline-flex` and so was simply absent.
   It must not wrap: the header is a fixed 64px. */
.nav-install {
  white-space: nowrap;
  flex: 0 0 auto;
}

/* Below 560px the header can hold the mark, the language pill, the CTA and the
   menu — but not the wordmark as well. The name is hidden by its own element
   rather than by `font-size: 0` on the link, which used to leave a 0px font
   size in the type census and shrink the logo's tap target to 24×32. */
@media (max-width: 560px) {
  .nav { gap: var(--s-2); }
  .brand {
    /* The 44px target is made of padding rather than min-width, and an equal
       negative margin pulls the box back so the mark's left edge lands on the
       page gutter instead of 6px inside it. The logo is the first thing on the
       page and every heading below it starts at the gutter. */
    justify-content: center;
    padding-inline: var(--s-2);
    margin-inline-start: calc(var(--s-2) * -1);
    min-height: 44px;
  }
  .brand-name { display: none; }
  .brand img { width: 32px; height: 32px; }
  .nav-install { padding: 0 var(--s-3); font-size: var(--t-caption); }
  .langswitch a,
  .langswitch span { min-width: 30px; padding: 0 var(--s-1); }
}

.foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s-4) var(--s-8);
  margin-top: var(--s-8);
  padding: var(--s-6) 0 var(--s-10);
  border-top: 1px solid var(--line);
  font-family: var(--font-sans);
  color: var(--muted);
  font-size: var(--t-caption);
}
.foot p { margin: 0; display: inline-flex; align-items: center; min-height: 44px; }
.foot a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: inherit;
  text-decoration: none;
}
.foot a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
.foot-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--s-5);
}

.signed-in {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-sans);
  font-size: var(--t-caption);
  color: var(--muted);
}
.signed-in .btn {
  min-height: 36px;
  padding: 0 var(--s-3);
  font-size: var(--t-micro);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* First tab stop on every page: jump past 5–11 repeated nav links. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 60;
  padding: var(--s-3) var(--s-4);
  background: var(--cactus);
  color: var(--on-cactus);
  font-family: var(--font-sans);
  font-size: var(--t-sm);
  font-weight: 600;
  text-decoration: none;
  border-radius: 0 0 var(--r-sm) 0;
}
.skip-link:focus { left: 0; }

/* The design owns its focus ring rather than inheriting Chrome's blue one,
   which clashes with the cream and forest palette and varies by browser.
   No radius is declared: the outline follows the radius of whatever it
   surrounds, so a pill is ringed as a pill and a link as a rectangle. */
:focus-visible {
  outline: 2px solid var(--cactus);
  outline-offset: 2px;
}
#main:focus { outline: none; }

/* Phones have no hover, so presses need their own acknowledgement. */
.btn:active,
.menu-toggle:active,
.langswitch a:active { transform: translateY(1px); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .btn:active,
  .menu-toggle:active,
  .langswitch a:active { transform: none; }
}
