/*
 * Desk Fabrika Kalıp microsite — single stylesheet.
 *
 * HARD RULE: logical properties only. No margin-left, padding-right, left:,
 * right:, text-align: left/right, border-left, float: left. Use
 * margin-inline-start, padding-inline-end, inset-inline-start,
 * text-align: start/end, border-inline-start. One physical direction leaking
 * in breaks the Arabic layout and stays invisible unless someone opens the
 * RTL build.
 *
 * Palette, radius and type scale are copied from the main site's
 * `src/styles/tokens.css` (read-only for this microsite). Values are
 * duplicated rather than imported because this site ships as standalone
 * static HTML with no build pipeline into the Next.js app. If the brand
 * palette changes there, the primitive block below is the only place to
 * change here.
 *
 * Palette rule carried over from the main site and NOT negotiable:
 * acid yellow is never text and never a hairline — it measures 1.9:1 on a
 * light ground. It is fill and marker only. Ink carries, acid points.
 */

/* ── Self-hosted faces ───────────────────────────────────────────────
   Same files the main site serves through next/font. Self-hosted on
   purpose: a Google Fonts <link> sends the visitor's IP to a third party
   on every page view, which is the exact call the main site removed for
   GDPR reasons (docs/08 PRIV-21a). Both faces are OFL licensed.
   Subsets kept: latin + latin-ext (Turkish ğ ı ş İ and German ß live in
   latin-ext, not in base latin) and arabic for Noto. */

@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('./fonts/space-grotesk-latin.woff2') format('woff2');
  unicode-range: U+00??, U+131, U+152-153, U+2BB-2BC, U+2C6, U+2DA, U+2DC,
    U+304, U+308, U+329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('./fonts/space-grotesk-latin-ext.woff2') format('woff2');
  unicode-range: U+100-2BA, U+2BD-2C5, U+2C7-2CC, U+2CE-2D7, U+2DD-2FF,
    U+304, U+308, U+329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Noto Sans Arabic';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url('./fonts/noto-sans-arabic-latin.woff2') format('woff2');
  unicode-range: U+00??, U+131, U+152-153, U+2BB-2BC, U+2C6, U+2DA, U+2DC,
    U+304, U+308, U+329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Noto Sans Arabic';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url('./fonts/noto-sans-arabic-latin-ext.woff2') format('woff2');
  unicode-range: U+100-2BA, U+2BD-2C5, U+2C7-2CC, U+2CE-2D7, U+2DD-2FF,
    U+304, U+308, U+329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Noto Sans Arabic';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url('./fonts/noto-sans-arabic-arabic.woff2') format('woff2');
  unicode-range: U+06??, U+750-77F, U+870-891, U+897-8E1, U+8E3-8FF,
    U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74,
    U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC7,
    U+10EC9-10EEE, U+10EF?, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22,
    U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B,
    U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52,
    U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62,
    U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C,
    U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9,
    U+1EEAB-1EEBB, U+1EEF0-1EEF1;
}

/* ── Tokens ──────────────────────────────────────────────────────────
   Three theme states, not two — same structure as the main site:
     1) :root                                           → DARK (unstamped)
     2) @media (prefers-color-scheme: light) :root:not([data-theme=dark])
     3) :root[data-theme=light]                          → toggle wins
   Defining only one leaves an unstamped page with one theme's text on the
   other theme's ground. */

:root {
  /* primitive · dark ground. The neutrals lean warm toward the acid;
     pure grey reads as "unselected" next to this yellow. */
  --tf-ground: #0b0b0a;
  --tf-raised: #131312;
  --tf-sunken: #060605;
  --tf-line: #232320;
  --tf-line-strong: #3a3a34;
  --tf-control-line: #6a695c;
  --tf-ink: #f4f2e9;
  --tf-ink-soft: #b9b6a8;
  --tf-ink-mute: #8b8879;
  --tf-accent: #e2ff2e;
  --tf-accent-ink: #0b0b0a;
  --tf-scene: #46e0ff;

  /* primitive · type. One family across the whole site (the logo's family).
     The machine voice comes from tracking, caps and scale — not a second
     face. Arabic swaps the family only; direction comes from <html dir>. */
  --tf-font-body: 'Space Grotesk', ui-sans-serif, system-ui, sans-serif;
  --tf-font-arabic: 'Noto Sans Arabic', Tahoma, sans-serif;

  --font-heading: var(--tf-font-body);
  --font-text: var(--tf-font-body);
  --font-mono: var(--tf-font-body);

  /* primitive · 8pt spacing scale */
  --tf-space-1: 0.25rem;
  --tf-space-2: 0.5rem;
  --tf-space-3: 0.75rem;
  --tf-space-4: 1rem;
  --tf-space-6: 1.5rem;
  --tf-space-8: 2rem;
  --tf-space-12: 3rem;
  --tf-space-16: 4rem;
  --tf-space-24: 6rem;

  /* primitive · motion. All out-ease: fast start, long soft settle. */
  --tf-ease: cubic-bezier(0.2, 0.7, 0.3, 1);
  --tf-dur-fast: 0.18s;
  --tf-dur: 0.3s;

  /* primitive · radius — pick from the scale, never write pixels */
  --tf-radius-sm: 6px;
  --tf-radius: 10px;
  --tf-radius-lg: 14px;

  --tf-header-h: 64px;
  --tf-header-gap: 18px;
  --tf-header-offset: calc(var(--tf-header-gap) + var(--tf-header-h));
  --tf-measure: 62ch;
  --tf-container: 1340px;
  --tf-gutter: clamp(1.25rem, 4vw, 4rem);
  --tf-rule: 1px;

  /* semantic · DARK (unstamped default) */
  color-scheme: dark light;

  --color-surface-page: var(--tf-ground);
  --color-surface-raised: var(--tf-raised);
  --color-surface-sunken: var(--tf-sunken);
  --color-border-subtle: var(--tf-line);
  --color-border-strong: var(--tf-line-strong);
  --color-border-control: var(--tf-control-line);
  --color-content-primary: var(--tf-ink);
  --color-content-secondary: var(--tf-ink-soft);
  --color-content-muted: var(--tf-ink-mute);

  --color-accent: var(--tf-accent);
  --color-on-accent: var(--tf-accent-ink);
  /* On a dark ground the acid reads as text (17:1), so there it may carry
     the link and hairline role itself. On light this inverts — see below. */
  --color-accent-text: var(--tf-accent);
  --color-accent-line: var(--tf-accent);
  --color-accent-soft: color-mix(in srgb, var(--tf-accent) 14%, transparent);

  --color-scene: var(--tf-scene);
  --color-glass: rgb(11 11 10 / 80%);
  --color-focus-ring: var(--tf-accent);

  --color-warn: #ffc861;
  --color-warn-soft: #3a2a06;

  /*
   * Chart fills for the three hours (quote · CAM · actual).
   *
   * Defined PER THEME, not once. The first attempt used the scene colour
   * for CAM, which is cyan on dark but grey on light — and on light it
   * landed at #7a7a71 next to a #696961 quote bar, two greys nobody could
   * tell apart. Each theme now picks three fills that separate by
   * lightness as well as hue. The row is labelled with its three numbers
   * anyway, so colour is never the only carrier (WCAG 1.4.1).
   */
  --bar-q: var(--tf-ink-soft);
  --bar-c: var(--tf-scene);
  --bar-a: var(--tf-accent);
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme='dark']) {
    color-scheme: light dark;

    --color-surface-page: #fbfbf8;
    --color-surface-raised: #fff;
    --color-surface-sunken: #f1f1ec;
    --color-border-subtle: #e6e6df;
    --color-border-strong: #c4c4b9;
    --color-border-control: #8a8a7e;
    --color-content-primary: #0d0d0b;
    --color-content-secondary: #44443d;
    --color-content-muted: #696961;

    --color-accent: #d9f000;
    --color-on-accent: #14140f;
    /* Acid yellow is NOT readable as text on a light ground (1.9:1), so
       here ink takes over the text and line role. Not a compromise — the
       palette rule. */
    --color-accent-text: #0d0d0b;
    --color-accent-line: #0d0d0b;
    --color-accent-soft: color-mix(in srgb, #d9f000 24%, transparent);

    /* On light the scene is grey, not cyan: cyan reads as a coloured stain
       on a white ground. */
    --color-scene: #7a7a71;
    --color-glass: rgb(251 251 248 / 86%);
    --color-focus-ring: #0d0d0b;

    --color-warn: #8f630b;
    --color-warn-soft: #fdf0d5;
    /* ink · mid grey · acid — three steps of lightness, see the dark block */
    --bar-q: #0d0d0b;
    --bar-c: #b4b4a9;
    --bar-a: #d9f000;
  }
}

:root[data-theme='light'] {
  color-scheme: light dark;

  --color-surface-page: #fbfbf8;
  --color-surface-raised: #fff;
  --color-surface-sunken: #f1f1ec;
  --color-border-subtle: #e6e6df;
  --color-border-strong: #c4c4b9;
  --color-border-control: #8a8a7e;
  --color-content-primary: #0d0d0b;
  --color-content-secondary: #44443d;
  --color-content-muted: #696961;

  --color-accent: #d9f000;
  --color-on-accent: #14140f;
  --color-accent-text: #0d0d0b;
  --color-accent-line: #0d0d0b;
  --color-accent-soft: color-mix(in srgb, #d9f000 24%, transparent);

  --color-scene: #7a7a71;
  --color-glass: rgb(251 251 248 / 86%);
  --color-focus-ring: #0d0d0b;

  --color-warn: #8f630b;
  --color-warn-soft: #fdf0d5;
    /* ink · mid grey · acid — three steps of lightness, see the dark block */
    --bar-q: #0d0d0b;
    --bar-c: #b4b4a9;
    --bar-a: #d9f000;
}

/*
 * Below 1100px the bar wraps onto a second row, so the allowance an anchor
 * target needs to clear it grows too. Only `--tf-header-h` changes; every
 * consumer derives from it (WCAG 2.2 · 2.4.11).
 */
@media (width <= 1100px) {
  :root {
    --tf-header-h: 118px;
  }
}

/* Arabic swaps the FAMILY only. Direction comes from <html dir>, never here. */
:root:lang(ar) {
  --font-heading: var(--tf-font-arabic);
  --font-text: var(--tf-font-arabic);
  --font-mono: var(--tf-font-arabic);
}

/* ── Base ────────────────────────────────────────────────────────── */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* The bar is sticky; without scroll padding an element brought to the top
     of the viewport by an in-page anchor or by Tab sits under it and its
     focus ring is invisible — WCAG 2.2 · 2.4.11 Focus Not Obscured. */
  scroll-padding-block-start: calc(var(--tf-header-offset) + 1rem);

  /* iOS Safari still needs the prefixed form; dropping it lets Safari
     inflate text on orientation change. Disabled deliberately, exactly as
     the main site does in globals.css. */
  /* stylelint-disable-next-line property-no-vendor-prefix */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  /* Stated explicitly from the token: without this the page keeps the UA
     white while the text has already gone light. */
  background-color: var(--color-surface-page);
  color: var(--color-content-primary);
  font-family: var(--font-text);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* Belt and braces against a stray wide child on a phone. The real fix is
     per-component (every table sits in its own scroll box); this only stops
     one mistake from scrolling the whole document. */
  overflow-x: clip;
}

/* Arabic renders smaller at the same px size and needs more leading.
   Letter-spacing is never applied — it severs the cursive joins. */
html[dir='rtl'] body {
  font-size: clamp(1.0625rem, 1rem + 0.25vw, 1.125rem);
  line-height: 1.85;
  letter-spacing: normal;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-heading);
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: -0.035em;
  text-wrap: balance;
  margin-block: 0 var(--tf-space-4);
}

h1 {
  font-size: clamp(2.1rem, 1.35rem + 2.6vw, 3.6rem);
}

h2 {
  font-size: clamp(1.5rem, 1.15rem + 1.5vw, 2.25rem);
}

h3 {
  font-size: clamp(1.1rem, 1rem + 0.55vw, 1.3rem);
  font-weight: 600;
}

/* Arabic headings need a heavier weight for the same optical colour, and
   no negative tracking. */
html[dir='rtl'] h1,
html[dir='rtl'] h2,
html[dir='rtl'] h3,
html[dir='rtl'] h4 {
  font-weight: 600;
  letter-spacing: normal;
  line-height: 1.4;
}

/* German compound nouns overflow narrow containers; this is the single most
   common layout break in a de/tr site. Break rather than clip — clipping
   loses information. */
html[lang='de'] h1,
html[lang='de'] h2,
html[lang='de'] h3,
html[lang='de'] h4 {
  hyphens: auto;
  overflow-wrap: break-word;
}

p {
  max-inline-size: var(--tf-measure);
  margin-block: 0 var(--tf-space-4);
}

p:last-child {
  margin-block-end: 0;
}

a {
  color: var(--color-accent-text);
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}

a:hover {
  text-decoration-thickness: 2px;
}

:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
  scroll-margin-block-start: calc(var(--tf-header-offset) + 1rem);
}

:target {
  scroll-margin-block-start: calc(var(--tf-header-offset) + 1rem);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Layout ──────────────────────────────────────────────────────── */

/* Page box — same formula as the main site's `.container` so the text
   column starts where the bar's own text starts. */
.container {
  inline-size: min(100% - (var(--tf-gutter) * 2), var(--tf-container));
  margin-inline: auto;
  padding-inline: calc(var(--tf-space-4) + var(--tf-rule));
}

section {
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
}

/* Breathing gap between the bar and the page title. Single source — pages
   never write their own clamp. The bar's own height is handled by it being
   sticky and therefore in flow; this is only the space on top of that. */
.hero {
  padding-block: clamp(1.75rem, 4vw, 3rem) clamp(2rem, 5vw, 3.5rem);
}

.stack {
  display: grid;
  gap: var(--tf-space-4);
  align-content: start;
}

.stack.g8 {
  gap: var(--tf-space-2);
}

.stack.g20 {
  gap: 1.25rem;
}

.stack.g24 {
  gap: var(--tf-space-6);
}

/* `minmax(0, 1fr)` is not optional: a grid item's implicit min-width: auto
   blows the container out on a narrow screen. */
.grid2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.75rem, 4vw, 3.5rem);
  align-items: start;
}

.row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tf-space-3);
  align-items: center;
}

.row.sb {
  justify-content: space-between;
}

@media (width <= 900px) {
  .grid2 {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── Type helpers ────────────────────────────────────────────────── */

/* Measurement label — tracked, uppercase, muted. The vernacular of a spec
   sheet, used for eyebrows and data captions. */
.eyebrow {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-content-muted);
  margin-block: 0;
}

/* Tracking severs Arabic cursive joins; uppercase is a no-op in Arabic
   (the script has no case). */
html[dir='rtl'] .eyebrow,
html[dir='rtl'] .mono,
html[dir='rtl'] .st,
html[dir='rtl'] th,
html[dir='rtl'] .filter button {
  letter-spacing: normal;
}

.mono {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  /* Any rule that sets a column of numbers must ask for tabular figures;
     the family is proportional by default. */
  font-variant-numeric: tabular-nums;
  color: var(--color-content-secondary);
}

.lead {
  font-size: clamp(1.05rem, 1rem + 0.45vw, 1.3rem);
  font-weight: 300;
  line-height: 1.5;
  color: var(--color-content-secondary);
  max-inline-size: 58ch;
}

html[dir='rtl'] .lead {
  font-weight: 400;
  line-height: 1.8;
}

.sm {
  font-size: 0.875rem;
}

.m {
  color: var(--color-content-muted);
}

.skip-link {
  position: absolute;
  inset-block-start: var(--tf-space-2);
  inset-inline-start: var(--tf-space-2);
  z-index: 100;
  padding: var(--tf-space-2) var(--tf-space-4);
  background-color: var(--color-surface-raised);
  color: var(--color-content-primary);
  border: var(--tf-rule) solid var(--color-border-strong);
  border-radius: var(--tf-radius);
  text-decoration: none;
  transform: translateY(-250%);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

/* ── Status chips ────────────────────────────────────────────────────
   The honesty contract of this site renders here. Every chip carries its
   own words, so the state never depends on colour alone (WCAG 1.4.1).
   `k` is the only filled one — acid as FILL, which is the one role it is
   allowed to play. */

.st {
  display: inline-flex;
  align-items: center;
  flex: none;
  gap: 0.35em;
  padding: 0.3em 0.6em;
  border: var(--tf-rule) solid transparent;
  border-radius: var(--tf-radius-sm);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  white-space: nowrap;
}

.st.k {
  background-color: var(--color-accent);
  color: var(--color-on-accent);
}

.st.g {
  border-color: var(--color-border-control);
  color: var(--color-content-primary);
}

.st.y {
  background-color: var(--color-surface-sunken);
  border-color: var(--color-border-subtle);
  color: var(--color-content-muted);
}

.legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--tf-space-2) var(--tf-space-3);
  font-size: 0.85rem;
  color: var(--color-content-muted);
}

.statusline {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--tf-space-2);
  font-size: 0.92rem;
  color: var(--color-content-secondary);
  padding-block: var(--tf-space-1);
}

/* ── Header ──────────────────────────────────────────────────────── */

/*
 * Sticky, NOT fixed — measured, not stylistic.
 *
 * With `position: fixed` the bar is out of flow, so every page has to pay
 * for its height with a hand-written top padding. That number is only
 * right in one language at one width: at 360px the bar wraps onto two
 * rows (and three in German), grows to ~120px, and the eyebrow and first
 * table rows disappear underneath it. Sticky keeps the bar in flow, so it
 * reserves exactly its own height in every language and at every width,
 * and still pins to the top on scroll.
 */
.top {
  position: sticky;
  inset-block-start: var(--tf-header-gap);
  z-index: 50;
  margin-block-start: var(--tf-header-gap);
}

.top .inner {
  display: flex;
  align-items: center;
  gap: var(--tf-space-4);
  min-block-size: var(--tf-header-h);
  padding-block: var(--tf-space-2);
  background-color: var(--color-glass);
  backdrop-filter: blur(14px);
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  flex: none;
  font-family: var(--font-heading);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--color-content-primary);
  text-decoration: none;
}

.brand .mark {
  inline-size: 9px;
  block-size: 9px;
  border-radius: 2px;
  background-color: var(--color-accent);
  flex: none;
}

.brand span {
  color: var(--color-content-muted);
}

nav.main {
  display: flex;
  flex-wrap: wrap;
  gap: var(--tf-space-1) var(--tf-space-4);
  margin-inline-end: auto;
}

nav.main a {
  font-size: 0.875rem;
  color: var(--color-content-secondary);
  text-decoration: none;
  padding-block: 0.3rem;
  border-block-end: 2px solid transparent;
}

nav.main a:hover {
  color: var(--color-content-primary);
}

/* The current page is marked with a rule, not with the acid as text. */
nav.main a[aria-current='page'] {
  color: var(--color-content-primary);
  border-block-end-color: var(--color-accent-line);
}

.tools {
  display: flex;
  align-items: center;
  gap: var(--tf-space-2);
  flex: none;
}

.langs {
  display: flex;
  align-items: center;
  gap: 1px;
  padding: 2px;
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius-sm);
}

.langs a {
  padding: 0.25rem 0.45rem;
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-content-muted);
  text-decoration: none;
}

.langs a:hover {
  color: var(--color-content-primary);
}

.langs a[aria-current='true'] {
  background-color: var(--color-accent);
  color: var(--color-on-accent);
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 34px;
  block-size: 34px;
  padding: 0;
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius-sm);
  background-color: transparent;
  color: var(--color-content-secondary);
  cursor: pointer;
}

.icon-btn:hover {
  color: var(--color-content-primary);
  border-color: var(--color-border-control);
}

.icon-btn svg {
  inline-size: 17px;
  block-size: 17px;
}

/*
 * The UA rule for `[hidden]` is namespaced to HTML, so it does NOT match an
 * <svg> element. Without this line both theme icons paint at once and the
 * 34px button overflows — the attribute is set correctly and looks fine in
 * the DOM, which is why it only shows up on screen.
 */
.icon-btn svg[hidden] {
  display: none;
}

.menu-btn {
  display: none;
}

@media (width <= 1100px) {
  .top .inner {
    flex-wrap: wrap;
    row-gap: var(--tf-space-2);
  }

  .menu-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-inline-start: auto;
    padding: 0.5rem 0.8rem;
    border: var(--tf-rule) solid var(--color-border-control);
    border-radius: var(--tf-radius-sm);
    background-color: transparent;
    color: var(--color-content-primary);
    font-family: var(--font-text);
    font-size: 0.85rem;
    cursor: pointer;
  }

  nav.main {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    gap: 0;
    margin-inline-end: 0;
    padding-block-start: var(--tf-space-2);
    border-block-start: var(--tf-rule) solid var(--color-border-subtle);
  }

  nav.main.open {
    display: flex;
  }

  nav.main a {
    padding-block: 0.6rem;
    border-block-end: var(--tf-rule) solid var(--color-border-subtle);
  }

  nav.main a[aria-current='page'] {
    border-block-end-color: var(--color-accent-line);
  }

  .tools {
    flex-wrap: wrap;
  }

  /* `.tools` prefix is load-bearing: a bare `.hide-m` ties on specificity
     with `.btn` and loses on source order, so the CTA stayed visible and
     pushed the bar past the viewport edge at 360px. */
  .tools .hide-m {
    display: none;
  }
}

/* ── Buttons ─────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.9rem 1.5rem;
  border: var(--tf-rule) solid transparent;
  border-radius: var(--tf-radius);
  font-family: var(--font-heading);
  font-size: 0.95rem;
  font-weight: 500;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform var(--tf-dur) var(--tf-ease),
    background-color var(--tf-dur-fast),
    border-color var(--tf-dur-fast);
}

.btn.sm {
  padding: 0.6rem 1rem;
  font-size: 0.85rem;
}

.btn svg {
  inline-size: 1.05em;
  block-size: 1.05em;
  flex: none;
}

/* Only direction-bearing icons mirror in Arabic. A mirrored download arrow
   would be nonsense, so this is opt-in per icon. */
html[dir='rtl'] .btn svg[data-mirror='true'] {
  transform: scaleX(-1);
}

.btn.primary {
  background-color: var(--color-accent);
  color: var(--color-on-accent);
}

.btn.primary:hover {
  transform: translateY(-2px);
}

.btn.ghost {
  border-color: var(--color-border-control);
  color: var(--color-content-primary);
}

.btn.ghost:hover {
  border-color: var(--color-content-primary);
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
  .btn:hover {
    transform: none;
  }
}

/* ── Panels, notices ─────────────────────────────────────────────── */

.panel {
  padding: clamp(1.1rem, 2.5vw, 1.6rem);
  background-color: var(--color-surface-raised);
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius-lg);
}

.notice {
  padding: var(--tf-space-4);
  background-color: var(--color-accent-soft);
  /* The hairline is ink, not acid: a 1px acid line fails contrast. */
  border-inline-start: 3px solid var(--color-accent-line);
  border-radius: var(--tf-radius-sm);
  font-size: 0.95rem;
  color: var(--color-content-primary);
  max-inline-size: var(--tf-measure);
}

/* ── Hero title block ────────────────────────────────────────────────
   A drawing title block: identity cells on top, the three totals under
   them, then one row per mould component. */

.tb {
  background-color: var(--color-surface-raised);
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius-lg);
  /* Radius goes on the grid, not on the cell: the hairlines inside are
     clipped by the parent instead of each cell rounding its own corner. */
  overflow: clip;
}

.tb-head,
.tb-tot {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.tb-head > div,
.tb-tot > div {
  padding: var(--tf-space-3) var(--tf-space-4);
  border-block-end: var(--tf-rule) solid var(--color-border-subtle);
}

.tb-head > div + div,
.tb-tot > div + div {
  border-inline-start: var(--tf-rule) solid var(--color-border-subtle);
}

.tb-head small,
.tb-tot small {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-content-muted);
  margin-block-end: 0.3rem;
}

html[dir='rtl'] .tb-head small,
html[dir='rtl'] .tb-tot small {
  letter-spacing: normal;
}

.tb-head b {
  font-size: 0.95rem;
  font-weight: 500;
}

.tb-tot strong {
  font-size: 1.25rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.tb-tot small i {
  inline-size: 10px;
  block-size: 10px;
  border-radius: 2px;
  flex: none;
}

.tb-tot small i.kq {
  background-color: var(--bar-q);
}

.tb-tot small i.kc {
  background-color: var(--bar-c);
}

.tb-tot small i.ka {
  background-color: var(--bar-a);
}

.tb-rows {
  padding: var(--tf-space-2) var(--tf-space-4);
}

.tb-r {
  display: grid;
  grid-template-columns: minmax(0, 7.5rem) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--tf-space-3);
  padding-block: 0.45rem;
}

.tb-r > span {
  font-size: 0.82rem;
  color: var(--color-content-secondary);
  overflow-wrap: anywhere;
}

.tb-r em {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-style: normal;
  font-variant-numeric: tabular-nums;
  color: var(--color-content-muted);
  white-space: nowrap;
}

.bars {
  display: grid;
  gap: 2px;
  min-inline-size: 0;
}

.bars > div {
  block-size: 5px;
  border-radius: 2px;
  min-inline-size: 2px;
}

.bars .q {
  background-color: var(--bar-q);
}

.bars .c {
  background-color: var(--bar-c);
}

.bars .a {
  background-color: var(--bar-a);
}

.tb-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--tf-space-2);
  padding: var(--tf-space-3) var(--tf-space-4);
  border-block-start: var(--tf-rule) solid var(--color-border-subtle);
  background-color: var(--color-surface-sunken);
  font-size: 0.82rem;
  color: var(--color-content-secondary);
}

.tb-foot span:last-child {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-content-muted);
}

html[dir='rtl'] .tb-foot span:last-child {
  letter-spacing: normal;
}

/* ── Capacity bars ───────────────────────────────────────────────── */

.cap {
  display: grid;
  gap: var(--tf-space-2);
}

.cap-r {
  display: grid;
  grid-template-columns: minmax(0, 8rem) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--tf-space-3);
  font-size: 0.85rem;
}

.cap-t {
  position: relative;
  block-size: 9px;
  background-color: var(--color-surface-sunken);
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: 3px;
  overflow: clip;
}

/* The 100% mark. At 130% full scale it sits at 76.9% of the track. */
.cap-t::after {
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-start: 76.9%;
  inline-size: var(--tf-rule);
  background-color: var(--color-border-control);
}

.cap-t i {
  display: block;
  block-size: 100%;
  background-color: var(--color-accent);
}

/* Over capacity is a warning, not a brand moment — semantic colour, and the
   percentage is written next to it in text. */
.cap-t i.over {
  background-color: var(--color-warn);
}

.cap-r .mono {
  font-size: 0.75rem;
  white-space: nowrap;
}

.cap-note {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-content-muted);
}

html[dir='rtl'] .cap-note {
  letter-spacing: normal;
}

/* ── Timeline ────────────────────────────────────────────────────── */

.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
}

.timeline li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--tf-space-3);
  padding-block: 0.55rem;
  font-size: 0.9rem;
  color: var(--color-content-muted);
  border-block-end: var(--tf-rule) solid var(--color-border-subtle);
}

.timeline li:last-child {
  border-block-end: 0;
}

.timeline li::before {
  content: '';
  inline-size: 8px;
  block-size: 8px;
  border-radius: 50%;
  border: var(--tf-rule) solid var(--color-border-control);
  flex: none;
}

/* Done and current are also readable from the date column ("ongoing",
   "estimated 7 Nov"), so the dot is a shorthand, not the only carrier. */
.timeline li.done::before {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
}

.timeline li.now::before {
  box-shadow: 0 0 0 3px var(--color-accent-soft);
  background-color: var(--color-content-primary);
  border-color: var(--color-content-primary);
}

.timeline li.done,
.timeline li.now {
  color: var(--color-content-primary);
}

.timeline li .mono {
  font-size: 0.72rem;
  white-space: nowrap;
}

/* ── Pain cards ──────────────────────────────────────────────────── */

/* 22rem caps the track count at three on a wide screen. At 17rem the five
   cards became 4 + 1 and the orphan looked like a mistake; 3 + 2 reads as
   a deliberate grid. */
.pain {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: var(--tf-space-4);
}

.pain > div {
  display: grid;
  gap: var(--tf-space-3);
  align-content: start;
  padding: var(--tf-space-4);
  background-color: var(--color-surface-raised);
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius);
}

.pain q {
  font-size: 1rem;
  font-weight: 500;
  color: var(--color-content-primary);
  line-height: 1.35;
}

.pain p {
  margin: 0;
  font-size: 0.9rem;
  color: var(--color-content-secondary);
  max-inline-size: none;
}

/* ── Steps ───────────────────────────────────────────────────────── */

/*
 * Hairline grid: the radius goes on the GRID and the cells are clipped by
 * it, never rounded one by one.
 *
 * The container ground is the RAISED surface, not the hairline colour. The
 * obvious version — paint the container with the line colour and let 1px
 * gaps show through — leaves the unfilled cells of the last row showing as
 * empty grey boxes, and there are always unfilled cells here: seven steps
 * never divide evenly into a responsive column count. The lines are drawn
 * by each cell's own ring instead, so they exist only where a cell does.
 */
.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--tf-rule);
  background-color: var(--color-surface-raised);
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius);
  overflow: clip;
}

.steps.one {
  grid-template-columns: minmax(0, 1fr);
}

.steps li {
  display: grid;
  gap: var(--tf-space-2);
  align-content: start;
  padding: var(--tf-space-4);
  background-color: var(--color-surface-raised);
  /* The ring is the divider. Adjacent rings meet inside the 1px gap and
     read as one hairline; the outer ones are clipped by the grid. */
  box-shadow: 0 0 0 var(--tf-rule) var(--color-border-subtle);
}

.steps .n {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  font-variant-numeric: tabular-nums;
  color: var(--color-content-muted);
}

html[dir='rtl'] .steps .n {
  letter-spacing: normal;
}

.steps li b {
  font-family: var(--font-heading);
  font-size: 1rem;
  font-weight: 500;
  overflow-wrap: break-word;
}

.steps li > span:last-child {
  font-size: 0.88rem;
  color: var(--color-content-secondary);
}

/* ── Tiers ───────────────────────────────────────────────────────── */

.tiers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: var(--tf-space-4);
}

.tiers > div {
  display: grid;
  gap: var(--tf-space-2);
  align-content: start;
  justify-items: start;
  padding: var(--tf-space-4);
  background-color: var(--color-surface-raised);
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius);
}

.tiers h3 {
  margin: 0;
}

.tiers p {
  margin: 0;
  font-size: 0.9rem;
  color: var(--color-content-secondary);
  max-inline-size: none;
}

/* ── Feature list ────────────────────────────────────────────────── */

.fl {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
}

.fl.mw {
  max-inline-size: 48rem;
}

.fl li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--tf-space-2) var(--tf-space-4);
  padding-block: 0.7rem;
  border-block-end: var(--tf-rule) solid var(--color-border-subtle);
}

.fl li:last-child {
  border-block-end: 0;
}

/*
 * The status filter hides items with the `hidden` attribute, and the UA
 * rule that honours it is a plain author-beatable `[hidden]{display:none}`.
 * `.fl li { display: flex }` above overrides it, so without this line the
 * filter changed aria-pressed and the group visibility but every item
 * stayed on screen. Same trap as `.tools .hide-m`.
 */
.fl li[hidden] {
  display: none;
}

.fl li > div {
  min-inline-size: 0;
  flex: 1 1 14rem;
}

.fl li b {
  display: block;
  font-size: 0.95rem;
  font-weight: 500;
  overflow-wrap: break-word;
}

.fl li small {
  display: block;
  margin-block-start: 0.15rem;
  font-size: 0.84rem;
  color: var(--color-content-muted);
}

.feat {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
}

.feat > div {
  min-inline-size: 0;
  padding: var(--tf-space-4);
  background-color: var(--color-surface-raised);
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius);
}

.feat h3 {
  margin-block-end: var(--tf-space-1);
}

.feat .sub {
  margin-block-end: var(--tf-space-3);
  font-size: 0.86rem;
  color: var(--color-content-muted);
  max-inline-size: none;
}

.filter {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  padding: 2px;
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius-sm);
}

.filter button {
  padding: 0.4rem 0.7rem;
  border: 0;
  border-radius: 4px;
  background-color: transparent;
  color: var(--color-content-secondary);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}

.filter button:hover {
  color: var(--color-content-primary);
}

.filter button[aria-pressed='true'] {
  background-color: var(--color-accent);
  color: var(--color-on-accent);
}

/* ── Tables ──────────────────────────────────────────────────────────
   Every table lives in its own scroll box. A wide table must scroll
   itself, never the document — that is the difference between a readable
   phone page and a page that drifts sideways. */

.tablewrap {
  overflow-x: auto;
  border: var(--tf-rule) solid var(--color-border-subtle);
  border-radius: var(--tf-radius);
  /* Keeps a long table from stretching the grid column it sits in. */
  max-inline-size: 100%;
}

table {
  inline-size: 100%;
  min-inline-size: 30rem;
  border-collapse: collapse;
  font-size: 0.9rem;
}

th {
  padding: var(--tf-space-3) var(--tf-space-4);
  background-color: var(--color-surface-sunken);
  border-block-end: var(--tf-rule) solid var(--color-border-subtle);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-content-muted);
  text-align: start;
  white-space: nowrap;
}

td {
  padding: var(--tf-space-3) var(--tf-space-4);
  border-block-end: var(--tf-rule) solid var(--color-border-subtle);
  color: var(--color-content-secondary);
  vertical-align: top;
}

tbody tr:last-child td {
  border-block-end: 0;
}

td b {
  color: var(--color-content-primary);
  font-weight: 500;
}

td small {
  display: block;
  margin-block-start: 0.2rem;
  font-size: 0.84rem;
}

td.mono {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  white-space: nowrap;
}

td.num {
  text-align: end;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

th.num {
  text-align: end;
}

.w26 {
  inline-size: 26%;
}

.w24 {
  inline-size: 24%;
}

.w140 {
  inline-size: 140px;
}

.w150 {
  inline-size: 150px;
}

/* ── Demo hand-off ───────────────────────────────────────────────── */

/* The hand-off panel holds one button, so it does not need half the page.
   Narrower second track keeps the demo copy at a readable measure. */
.grid2.demo-grid {
  grid-template-columns: minmax(0, 1fr) minmax(0, 21rem);
}

@media (width <= 900px) {
  .grid2.demo-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

.handoff {
  display: grid;
  gap: var(--tf-space-3);
  justify-items: start;
}

.handoff .host {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: var(--color-content-muted);
  font-variant-numeric: tabular-nums;
}

html[dir='rtl'] .handoff .host {
  letter-spacing: normal;
}

/* ── CTA band and footer ─────────────────────────────────────────── */

.cta {
  background-color: var(--color-surface-raised);
  border-block: var(--tf-rule) solid var(--color-border-subtle);
}

.cta .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--tf-space-6);
}

.cta h2 {
  margin: 0;
}

.cta p {
  margin: 0;
  color: var(--color-content-secondary);
}

footer {
  padding-block: var(--tf-space-8);
  border-block-start: var(--tf-rule) solid var(--color-border-subtle);
}

footer .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--tf-space-3);
  font-size: 0.85rem;
  color: var(--color-content-muted);
}

/* ── Root language chooser ───────────────────────────────────────── */

.chooser {
  min-block-size: 100svh;
  display: grid;
  place-content: center;
  gap: var(--tf-space-8);
  padding: var(--tf-space-8) var(--tf-gutter);
  justify-items: center;
  text-align: center;
}

.chooser-brand {
  font-size: 1.3rem;
}

.chooser ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--tf-space-3);
}

.chooser a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.8rem 1.3rem;
  border: var(--tf-rule) solid var(--color-border-control);
  border-radius: var(--tf-radius);
  color: var(--color-content-primary);
  text-decoration: none;
}

.chooser a:hover {
  border-color: var(--color-content-primary);
}

.chooser a .code {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-content-muted);
}
