/* TerraSystem — Master UI/UX Design System & Styling
   ---------------------------------------------------------------------------
   Aesthetic: bright liquid glass. Surfaces are translucent lenses stacked over
   a coloured light field, not flat panels over a flat page. Three things make
   it read as glass rather than as "a card with opacity":

     1. Refraction — backdrop-filter blur plus a saturation lift, so whatever
        is behind the surface bends and brightens instead of merely dimming.
     2. Specular rim — a 1px masked gradient ring (::before) that is bright
        where a light source would hit the bevel and near-invisible elsewhere.
        This is what stops a translucent box from looking like a washed sticker.
     3. Sheen — a soft highlight baked into background-image, not a pseudo
        element, so it always paints below the content sitting on top of it.

   Dark is the default theme. Light is where the material reads most as glass,
   since there is colour behind it to refract; dark keeps the same physics
   with a dimmer light field.
   --------------------------------------------------------------------------- */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=IBM+Plex+Sans+Arabic:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap');

/* ----------------------------------------------------------------- tokens */
:root, [data-theme="light"] {
  --bg: #f5f4fb;
  /* The light field. Four soft radial washes and no blur filter — radial
     gradients are already smooth, and filter: blur() on a viewport-sized
     layer is the most expensive thing you can put behind a whole site. */
  --bg-gradient:
    radial-gradient(900px 620px at 6% -6%,   rgba(124, 58, 237, 0.17), transparent 62%),
    radial-gradient(820px 540px at 94% 2%,   rgba(56, 189, 248, 0.15), transparent 64%),
    radial-gradient(780px 640px at 50% 110%, rgba(244, 114, 182, 0.14), transparent 62%),
    radial-gradient(700px 500px at 80% 74%,  rgba(167, 139, 250, 0.13), transparent 66%);
  --blob-a: rgba(124, 58, 237, 0.14);
  --blob-b: rgba(34, 211, 238, 0.13);
  --blob-c: rgba(236, 72, 153, 0.11);

  /* Surfaces. In light mode the stack runs light to dark: panel is the most
     opaque white, panel-3 a tint used for pressed and inset states. */
  --panel: rgba(255, 255, 255, 0.72);
  --panel-2: rgba(255, 255, 255, 0.48);
  --panel-3: rgba(46, 32, 92, 0.085);
  --line: rgba(23, 19, 43, 0.11);
  --line-2: rgba(23, 19, 43, 0.20);

  --text: #17132b;
  --text-2: #3d3557;
  --muted: #5f5879;
  --faint: #7c7596;

  --accent: #7c3aed;
  --accent-2: #a855f7;
  --accent-3: #22d3ee;
  --accent-glow: rgba(124, 58, 237, 0.16);
  --accent-dim: rgba(124, 58, 237, 0.10);
  --on-accent: #ffffff;
  --warn: #b45309;
  --danger: #be123c;

  /* Glass material */
  --glass: rgba(255, 255, 255, 0.62);
  --glass-2: rgba(255, 255, 255, 0.42);
  --glass-strong: rgba(255, 255, 255, 0.82);
  --glass-blur: blur(20px) saturate(180%);
  --glass-blur-lg: blur(30px) saturate(190%);
  --sheen: radial-gradient(130% 96% at 8% -22%, rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0) 58%);
  --sheen-soft: radial-gradient(120% 90% at 10% -20%, rgba(255, 255, 255, 0.45), rgba(255, 255, 255, 0) 55%);
  --rim: linear-gradient(145deg,
      rgba(255, 255, 255, 0.98) 0%,
      rgba(255, 255, 255, 0.34) 26%,
      rgba(124, 58, 237, 0.16) 56%,
      rgba(255, 255, 255, 0.80) 100%);

  /* JetBrains Mono carries no Arabic, so an Arabic run inside a mono readout
     -- a ladder row, a stat value, a unit -- used to land on whatever generic
     monospace the OS picked, which renders Arabic unjoined and evenly spaced.
     Naming the Arabic face as the next fallback fixes those runs per glyph and
     leaves Latin, digits and code on JetBrains Mono exactly as before. */
  --mono: 'JetBrains Mono', 'IBM Plex Sans Arabic', ui-monospace, "Cascadia Code", Consolas, monospace;
  --sans: 'Inter', 'IBM Plex Sans Arabic', ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --sans-ar: 'IBM Plex Sans Arabic', 'Noto Sans Arabic', ui-sans-serif, "Segoe UI", Tahoma, sans-serif;

  --shadow-e1: 0 1px 2px rgba(23, 19, 43, 0.05), 0 4px 14px rgba(23, 19, 43, 0.06);
  --shadow-e2: 0 2px 4px rgba(23, 19, 43, 0.05), 0 14px 32px rgba(23, 19, 43, 0.10);
  --shadow-e3: 0 8px 24px rgba(23, 19, 43, 0.10), 0 28px 64px rgba(23, 19, 43, 0.18);
  --lip: inset 0 1px 0 rgba(255, 255, 255, 0.85);

  --radius-sm: 10px;
  --radius: 16px;
  --radius-lg: 22px;
  --radius-pill: 999px;
  --transition-fast: 140ms cubic-bezier(.4, 0, .2, 1);
  --transition-base: 260ms cubic-bezier(.22, 1, .36, 1);
  color-scheme: light;
}

[data-theme="dark"] {
  --bg: #0a0813;
  --bg-gradient:
    radial-gradient(900px 620px at 6% -6%,   rgba(124, 58, 237, 0.30), transparent 62%),
    radial-gradient(820px 540px at 94% 2%,   rgba(14, 165, 233, 0.18), transparent 64%),
    radial-gradient(780px 640px at 50% 110%, rgba(217, 70, 239, 0.16), transparent 62%),
    radial-gradient(700px 500px at 80% 74%,  rgba(99, 102, 241, 0.18), transparent 66%);
  --blob-a: rgba(139, 92, 246, 0.20);
  --blob-b: rgba(34, 211, 238, 0.14);
  --blob-c: rgba(217, 70, 239, 0.14);

  /* Dark inverts the stack: panel is the dimmest, panel-3 the raised state. */
  --panel: rgba(255, 255, 255, 0.055);
  --panel-2: rgba(255, 255, 255, 0.085);
  --panel-3: rgba(255, 255, 255, 0.13);
  --line: rgba(255, 255, 255, 0.11);
  --line-2: rgba(255, 255, 255, 0.20);

  --text: #eceaf6;
  --text-2: #c6c0dc;
  --muted: #a49dc0;
  --faint: #7d7699;

  --accent: #a78bfa;
  --accent-2: #c4b5fd;
  --accent-3: #67e8f9;
  --accent-glow: rgba(167, 139, 250, 0.20);
  --accent-dim: rgba(167, 139, 250, 0.14);
  --on-accent: #14092b;
  --warn: #fbbf24;
  --danger: #fb7185;

  --glass: rgba(28, 22, 48, 0.55);
  --glass-2: rgba(255, 255, 255, 0.06);
  --glass-strong: rgba(20, 16, 36, 0.78);
  --sheen: radial-gradient(130% 96% at 8% -22%, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 58%);
  --sheen-soft: radial-gradient(120% 90% at 10% -20%, rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0) 55%);
  --rim: linear-gradient(145deg,
      rgba(255, 255, 255, 0.46) 0%,
      rgba(255, 255, 255, 0.06) 28%,
      rgba(167, 139, 250, 0.22) 58%,
      rgba(255, 255, 255, 0.24) 100%);

  --shadow-e1: 0 1px 2px rgba(0, 0, 0, 0.34), 0 4px 14px rgba(0, 0, 0, 0.30);
  --shadow-e2: 0 2px 4px rgba(0, 0, 0, 0.34), 0 14px 32px rgba(0, 0, 0, 0.42);
  --shadow-e3: 0 8px 24px rgba(0, 0, 0, 0.44), 0 28px 64px rgba(0, 0, 0, 0.58);
  --lip: inset 0 1px 0 rgba(255, 255, 255, 0.10);
  color-scheme: dark;
}

/* Without backdrop-filter there is no refraction to sell the material, so the
   surfaces fall back to near-opaque rather than to a grey haze over text. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root, [data-theme="light"] {
    --glass: rgba(255, 255, 255, 0.94);
    --glass-2: rgba(255, 255, 255, 0.88);
    --glass-strong: rgba(255, 255, 255, 0.97);
    --panel: rgba(255, 255, 255, 0.95);
    --panel-2: rgba(255, 255, 255, 0.88);
  }
  [data-theme="dark"] {
    --glass: rgba(18, 14, 32, 0.96);
    --glass-2: rgba(30, 24, 50, 0.94);
    --glass-strong: rgba(14, 11, 26, 0.98);
  }
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background-color: var(--bg);
  background-image: var(--bg-gradient);
  background-attachment: fixed;
  color: var(--text);
  font: 400 15.5px/1.65 var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background-color var(--transition-base), color var(--transition-base);
}

/* The slow-moving half of the light field. A negative z-index paints above the
   body background but below every in-flow child, so nothing else needs a
   stacking context of its own to stay on top. */
body::before {
  content: '';
  position: fixed; inset: -25%; z-index: -1; pointer-events: none;
  background:
    radial-gradient(closest-side, var(--blob-a), transparent) 12% 18% / 48vw 48vw no-repeat,
    radial-gradient(closest-side, var(--blob-b), transparent) 88% 10% / 42vw 42vw no-repeat,
    radial-gradient(closest-side, var(--blob-c), transparent) 56% 92% / 54vw 54vw no-repeat;
  animation: terra-drift 32s ease-in-out infinite alternate;
}
@keyframes terra-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(2.5%, -2%, 0) scale(1.08); }
}

a { color: var(--accent); text-decoration: none; transition: color var(--transition-fast); }
a:hover { color: var(--accent-2); text-decoration: none; }

code, pre, .mono { font-family: var(--mono); }

/* One visible focus treatment for everything, so a keyboard user never loses
   the caret against a translucent surface. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ------------------------------------------------------- glass primitives */
/* The specular rim: a 1px gradient ring drawn by masking the padding box out
   of the border box. This is a real gradient border, which border-image
   cannot do once a border-radius is involved. Inert to the pointer and
   transparent inside, so it never intercepts a click or covers content. */
.glass-rim::before,
.card::before,
.endpoint::before,
.statusbar::before,
.tablewrap::before,
.modal::before,
.toast::before,
.btn::before,
header.top::before,
.panel::before,
.sandbox-card::after,
.demo-card::before,
.calc-box::before,
.hero-badge::before {
  content: '';
  position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: var(--rim);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}

/* Reusable material. Applied by class where the markup allows, and restated on
   the named components below so existing pages pick it up without edits. */
.glass {
  position: relative;
  background-color: var(--glass);
  background-image: var(--sheen);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-e2), var(--lip);
}
.glass-strong {
  background-color: var(--glass-strong);
  -webkit-backdrop-filter: var(--glass-blur-lg);
          backdrop-filter: var(--glass-blur-lg);
}

/* Layout & Container */
.wrap { max-width: 1140px; margin: 0 auto; padding: 0 24px; }

/* Unified Full-Width Header Navigation Bar */
header.top {
  position: sticky; top: 0; z-index: 600; width: 100%;
  background-color: var(--glass);
  background-image: var(--sheen-soft);
  -webkit-backdrop-filter: var(--glass-blur-lg);
          backdrop-filter: var(--glass-blur-lg);
  border-bottom: 1px solid var(--line);
  box-shadow: var(--shadow-e1);
  transition: background-color var(--transition-base), border-color var(--transition-base);
}
/* A rim around a full-bleed bar would draw a ring against the viewport edge,
   so the bar keeps only the lower edge highlight. */
header.top::before {
  inset: auto 0 0 0; height: 1px; padding: 0;
  background: linear-gradient(90deg, transparent, var(--accent-glow) 30%, var(--accent-glow) 70%, transparent);
  -webkit-mask: none; mask: none;
}
header.top .wrap {
  max-width: 100%; width: 100%; padding: 0 24px; margin: 0;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  height: 64px;
}
.brand {
  font-weight: 700; font-size: 16.5px; letter-spacing: -.02em; color: var(--text);
  display: flex; align-items: center; gap: 9px; text-decoration: none; flex-shrink: 0;
}
.brand span {
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 60%, var(--accent-3) 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--accent);
}
.brand .brand-a {
  background: none; color: var(--text);
  -webkit-text-fill-color: currentColor;
}
.brand img { width: 24px; height: 24px; display: block; filter: drop-shadow(0 2px 6px var(--accent-glow)); transition: transform var(--transition-base); }
.brand:hover img { transform: scale(1.08) rotate(5deg); }

/* Header Search Bar Component */
.header-search {
  /* The suggestion list hangs off the pill instead of sitting inside it: the
     pill is a flex row and a dropdown is not one of its columns. */
  position: relative;
  display: flex; align-items: center; gap: 8px; flex: 1 1 auto; max-width: 520px;
  background-color: var(--glass-2);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
          backdrop-filter: blur(12px) saturate(160%);
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  padding: 5px 14px;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast),
              background-color var(--transition-fast);
}
.header-search:focus-within {
  border-color: var(--accent); background-color: var(--glass);
  box-shadow: 0 0 0 4px var(--accent-glow);
}
/* This is a bare input inside an already-decorated container, so it opts out
   of the default control chrome further down this file. The attribute
   selector is deliberate: `.header-search input` alone ties on specificity
   with `input[type=text]`, loses on source order, and the input grows its own
   background, border and padding inside the pill — a box within a box.
   backdrop-filter must be reset too: a transparent element still blurs and
   saturates whatever is behind it, so the input painted its own visible
   rectangle inside the pill even with no background of its own. */
.header-search input[type=text],
.header-search input[type=text]:focus {
  background: transparent; border: 0; border-radius: 0; outline: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  box-shadow: none; color: var(--text); font: 400 13.5px var(--sans);
  width: 100%; padding: 5px 0; min-width: 0; min-height: 0;
}
.header-search input::placeholder { color: var(--muted); }
.header-search .icon {
  width: 15px; height: 15px; flex: 0 0 auto; color: var(--muted);
  transition: color var(--transition-fast);
}
.header-search:focus-within .icon { color: var(--accent); }
/* The button and the shortcut hint are both children of a pill, so they are
   pills too — a 5px rounded-rect nested inside a 999px capsule reads as two
   unrelated components that happen to be adjacent. Both share one height so
   the pair sits on a single optical line. */
.header-search button,
.header-search .shortcut-tag {
  flex: 0 0 auto; height: 26px; display: inline-flex; align-items: center;
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  background: var(--panel-3);
}
.header-search button {
  color: var(--text-2); padding: 0 14px;
  font: 500 12px var(--sans); cursor: pointer;
  transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast);
}
.header-search button:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-dim); }
.header-search .shortcut-tag {
  justify-content: center; min-width: 26px; padding: 0 7px;
  font-family: var(--mono); font-size: 11px; line-height: 1; color: var(--muted);
}
/* Place suggestions. Anchored to the pill's outer edge, not the input's, so
   the list lines up with the control the user is looking at rather than with
   the text cursor inside it. `inset-inline` rather than left/right because the
   whole header flips in Arabic and a hard-coded left would strand it. */
.search-ac {
  position: absolute; inset-inline: 0; top: calc(100% + 6px); z-index: 900;
  margin: 0; padding: 4px; list-style: none;
  max-height: 320px; overflow-y: auto;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg, 0 12px 32px rgba(0,0,0,.28));
}
.search-ac[hidden] { display: none; }
.ac-item {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px;
  padding: 7px 10px; border-radius: var(--radius-sm, 7px); cursor: pointer;
}
.ac-item.on, .ac-item:hover { background: var(--accent-dim); }
.ac-name { font: 500 13px var(--sans); color: var(--text); }
.ac-kind {
  font: 500 10.5px var(--sans); letter-spacing: .04em; text-transform: uppercase;
  color: var(--accent); margin-inline-start: auto;
}
/* The parent is what tells two identically named places apart -- the province
   of Makkah and the governorate inside it -- so it always gets its own line
   rather than being truncated away next to the name. */
.ac-parent { flex: 1 0 100%; font: 400 11.5px var(--sans); color: var(--muted); }

/* The hint has done its job once you are typing. */
.header-search:focus-within .shortcut-tag { display: none; }

header.top nav { display: flex; align-items: center; gap: 6px; font-size: 13.5px; font-weight: 500; flex-shrink: 0; }
header.top nav a {
  color: var(--muted); padding: 7px 14px; border-radius: var(--radius-pill);
  transition: color var(--transition-fast), background var(--transition-fast), box-shadow var(--transition-fast);
}
header.top nav a:hover { color: var(--text); background: var(--glass-2); text-decoration: none; }
header.top nav a.on {
  color: var(--accent); font-weight: 600;
  background-color: var(--accent-dim);
  background-image: var(--sheen-soft);
  box-shadow: inset 0 0 0 1px var(--accent-glow), var(--lip);
}

.theme-btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 36px; min-width: 90px; padding: 0 16px; border-radius: var(--radius-pill);
  background-color: var(--glass-2); background-image: var(--sheen-soft);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
          backdrop-filter: blur(12px) saturate(160%);
  border: 1px solid var(--line);
  color: var(--text-2); cursor: pointer; transition: all var(--transition-fast);
  font-size: 12.5px; font-weight: 500; white-space: nowrap; flex-shrink: 0;
}
.theme-btn:hover { color: var(--text); border-color: var(--line-2); background-color: var(--glass); }

/* Premium Pill Theme Toggle Switch Component */
.theme-toggle {
  display: inline-flex; align-items: center; gap: 9px;
  background-color: var(--glass-2); background-image: var(--sheen-soft);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
          backdrop-filter: blur(12px) saturate(160%);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill); padding: 5px; padding-inline-end: 14px; min-height: 36px;
  cursor: pointer; transition: all var(--transition-fast);
  color: var(--text-2); font-size: 12px; font-weight: 500;
  -webkit-user-select: none; user-select: none; flex-shrink: 0; outline: none;
}
.theme-toggle:hover {
  border-color: var(--accent); background-color: var(--glass); color: var(--text);
  box-shadow: 0 0 0 4px var(--accent-glow);
}
.theme-toggle .toggle-track {
  position: relative; width: 30px; height: 17px; border-radius: var(--radius-pill);
  background: var(--panel-3); border: 1px solid var(--line-2);
  transition: all var(--transition-base); flex-shrink: 0;
}
[data-theme="light"] .theme-toggle .toggle-track {
  background: var(--accent-dim); border-color: var(--accent);
}
.theme-toggle .toggle-thumb {
  position: absolute; top: 1px; inset-inline-start: 1px; width: 13px; height: 13px;
  border-radius: 50%; background: var(--muted);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transition: transform var(--transition-base), background var(--transition-fast);
}
[data-theme="light"] .theme-toggle .toggle-thumb {
  transform: translateX(13px); background: var(--accent);
}
.theme-toggle .toggle-label {
  font-family: var(--sans); font-size: 12px; font-weight: 500; color: var(--text-2); min-width: 32px; text-align: start;
}

/* Every page writes <main class="wrap">, and `.wrap` outranks a bare `main`
   on specificity — so the block padding here was being dropped entirely and
   the h1 sat against the header. The combined selector restates both axes. */
main { padding: 44px 0 88px; }
main.wrap { padding: 44px 24px 88px; }

footer {
  border-top: 1px solid var(--line);
  color: var(--muted); font-size: 13px;
  padding: 32px 0 56px;
}
footer p { margin: 0 0 8px; }
footer .credits { font-size: 12px; line-height: 1.6; max-width: 760px; color: var(--faint); }

/* Typography */
h1 { font-size: 38px; font-weight: 800; line-height: 1.2; margin: 0 0 16px; letter-spacing: -.03em; }
h2 {
  font-size: 22px; font-weight: 700; margin: 44px 0 14px; padding-top: 22px;
  border-top: 1px solid var(--line); letter-spacing: -.02em;
}
h2:first-of-type { border-top: 0; padding-top: 0; }
h3 { font-size: 16.5px; font-weight: 600; margin: 26px 0 10px; letter-spacing: -.01em; }
/* 72ch keeps body copy inside the 65-75 character band that stays scannable;
   the cap is on the paragraph, not the container, so cards and tables are
   free to use the full width. */
p { margin: 0 0 14px; max-width: 72ch; }
.lead { font-size: 18px; color: var(--text-2); margin-bottom: 26px; line-height: 1.65; max-width: 70ch; }
.muted { color: var(--muted); }
ul { padding-inline-start: 20px; margin: 0 0 14px; }
li { margin-bottom: 6px; }

/* Components & Cards */
pre {
  position: relative;
  background-color: var(--glass-2);
  background-image: var(--sheen-soft);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 18px; overflow-x: auto; font-size: 13px; line-height: 1.65;
  margin: 0 0 16px; box-shadow: var(--shadow-e1), var(--lip);
}
pre code { background: none; padding: 0; border: 0; font-size: inherit; color: var(--text); }
:not(pre) > code {
  background: var(--accent-dim); border: 1px solid var(--accent-glow); border-radius: 6px;
  padding: 2px 6px; font-size: .88em; color: var(--accent); font-weight: 500;
}

.grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.card {
  position: relative;
  background-color: var(--glass);
  background-image: var(--sheen);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  border: 1px solid var(--line);
  border-radius: var(--radius); padding: 20px 22px;
  box-shadow: var(--shadow-e1), var(--lip);
  transition: transform var(--transition-base), box-shadow var(--transition-base),
              background-color var(--transition-fast);
}
/* Lift only, never scale: scaling a grid item nudges the text of its
   neighbours and the whole row appears to breathe on one hover. */
.card:hover {
  transform: translateY(-3px);
  background-color: var(--glass-strong);
  box-shadow: var(--shadow-e2), var(--lip);
}
.card h3 { margin: 0 0 6px; font-size: 14.5px; font-weight: 600; }
.card p { margin: 0; font-size: 13.5px; color: var(--muted); line-height: 1.55; }
.card .big {
  font-size: 28px; font-weight: 700; font-family: var(--mono); letter-spacing: -.03em;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--accent);
}

.note {
  display: none;
  border-inline-start: 3px solid var(--warn);
  background-color: color-mix(in srgb, var(--warn) 12%, var(--glass));
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  padding: 13px 16px; margin: 14px 0;
  border-start-start-radius: 0; border-end-start-radius: 0;
  border-start-end-radius: var(--radius); border-end-end-radius: var(--radius);
  font-size: 13px; line-height: 1.55; color: var(--text);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); border-inline-end: 1px solid var(--line);
  box-shadow: var(--shadow-e1);
}
.note.on { display: block; }
.note.danger {
  border-inline-start-color: var(--danger);
  background-color: color-mix(in srgb, var(--danger) 12%, var(--glass));
}
.note strong { color: var(--text); font-weight: 600; }

table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13.5px; margin: 0 0 18px; }
th, td { text-align: start; padding: 10px 13px; border-bottom: 1px solid var(--line); }
th {
  color: var(--muted); font-weight: 600; font-size: 11px; text-transform: uppercase;
  letter-spacing: .06em; background: var(--panel-3);
}
/* The header row rounds only when the table stands on its own — inside a
   clipping wrapper the wrapper already cuts that corner, and a second radius
   at the same spot draws a second arc just inside the first, leaving a bright
   sliver between the two. The wrapper wins because its curve is the one the
   border follows. */
th:first-child { border-start-start-radius: var(--radius-sm); }
th:last-child { border-start-end-radius: var(--radius-sm); }
.tablewrap th:first-child,
.tablewrap th:last-child { border-radius: 0; }
tbody tr:last-child td { border-bottom: 0; }
td.mono, th.mono { font-family: var(--mono); font-size: 12.5px; }
.tablewrap {
  position: relative; overflow: hidden; overflow-x: auto;
  border: 1px solid var(--line); border-radius: var(--radius);
  background-color: var(--glass);
  background-image: var(--sheen-soft);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow-e1), var(--lip);
}

/* Buttons */
.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  background-color: var(--accent);
  background-image: linear-gradient(160deg,
      color-mix(in srgb, var(--accent-2) 85%, transparent) 0%,
      var(--accent) 55%,
      color-mix(in srgb, var(--accent) 88%, #000) 100%);
  color: var(--on-accent); font-weight: 600; font-size: 13.5px;
  border: 1px solid transparent; border-radius: var(--radius-pill);
  padding: 10px 20px; min-height: 40px; cursor: pointer; text-decoration: none;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.42),
              0 6px 18px -6px var(--accent),
              var(--shadow-e1);
  transition: transform var(--transition-base), box-shadow var(--transition-base),
              background-color var(--transition-fast), color var(--transition-fast);
  white-space: nowrap;
}
.btn:hover {
  transform: translateY(-2px); color: var(--on-accent);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.52),
              0 12px 28px -8px var(--accent),
              var(--shadow-e2);
}
.btn:active { transform: translateY(0); }
/* A filled button gets its own lighter rim; the shared violet one would fight
   the highlight already baked into the fill. */
.btn::before { background: linear-gradient(160deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.04) 45%, rgba(255, 255, 255, 0.22)); }
.btn.ghost {
  background-color: var(--glass-2); background-image: var(--sheen-soft);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  color: var(--text); border-color: var(--line);
  box-shadow: var(--shadow-e1), var(--lip);
}
.btn.ghost:hover {
  border-color: var(--accent); color: var(--accent);
  background-color: var(--glass);
  box-shadow: 0 0 0 4px var(--accent-glow), var(--shadow-e1);
}
.btn.small { padding: 6px 14px; min-height: 32px; font-size: 12.5px; }
.btn.danger {
  background-color: color-mix(in srgb, var(--danger) 12%, transparent);
  background-image: none;
  color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, transparent);
  box-shadow: none;
}
.btn.danger:hover {
  background-color: color-mix(in srgb, var(--danger) 20%, transparent);
  border-color: var(--danger); color: var(--danger);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--danger) 16%, transparent);
}
.btn:disabled { opacity: .45; cursor: default; transform: none; box-shadow: none; }

/* ------------------------------------------------------------------ forms */
/* Every page that takes input — the docs sandbox, the landing demo — marks up
   fields as <label class="field"><span>Name</span><input></label>. Without
   these rules the class is inert: the label falls back to inline so the name
   sits beside the box instead of above it, and the control renders as a raw
   browser widget that ignores the theme entirely. */
/* Visible to screen readers, not on screen. For controls whose only visible
   label is a placeholder or an icon. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

label.field { display: block; margin-bottom: 14px; }
label.field > span {
  display: block; margin-bottom: 6px;
  font: 600 11px/1 var(--sans); color: var(--muted);
  text-transform: uppercase; letter-spacing: .07em;
}

input[type=text], input[type=number], input[type=password],
input[type=search], input[type=email], textarea, select {
  width: 100%;
  background-color: var(--glass-2); color: var(--text);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
          backdrop-filter: blur(12px) saturate(160%);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 10px 13px; min-height: 40px; font: 400 13.5px/1.45 var(--sans);
  box-shadow: var(--lip);
  transition: border-color var(--transition-fast), background-color var(--transition-fast),
              box-shadow var(--transition-fast);
}
input:hover:not(:disabled), textarea:hover, select:hover { border-color: var(--line-2); }
input:focus, textarea:focus, select:focus {
  outline: none; border-color: var(--accent); background-color: var(--glass);
  box-shadow: 0 0 0 4px var(--accent-glow), var(--lip);
}
/* Values are data — align them the way the API prints them. */
input[type=number], input[type=text] { font-family: var(--mono); font-size: 13px; }
textarea { font-family: var(--mono); font-size: 12.5px; resize: vertical; min-height: 78px; }
::placeholder { color: var(--faint); }

/* The native dropdown button is drawn by the OS and no colour on the <select>
   reaches it, so the arrow is replaced. currentColor is not readable inside a
   data URI, so the chevron grey is picked to read on both themes. */
select {
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  cursor: pointer; padding-inline-end: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6' fill='none' stroke='%238b83a8' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center; background-size: 10px 6px;
}

/* Fields flow side by side when there is room and stack when there is not,
   so a two-input form does not leave a full-width box holding one digit. */
.field-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 0 14px; }

.btn-action-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 12px; }
.btn-action-grid .btn { padding: 8px 12px; font-size: 12px; justify-content: center; }

.method {
  display: inline-block; font: 700 11px/1.4 var(--mono); padding: 3px 9px;
  border-radius: var(--radius-pill); margin-inline-end: 8px; vertical-align: 1px; text-transform: uppercase;
}
.method.get { background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent); }
.method.post { background: color-mix(in srgb, var(--warn) 15%, transparent); color: var(--warn); border: 1px solid color-mix(in srgb, var(--warn) 32%, transparent); }
.method.del { background: color-mix(in srgb, var(--danger) 15%, transparent); color: var(--danger); border: 1px solid color-mix(in srgb, var(--danger) 32%, transparent); }

.endpoint {
  position: relative;
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 20px 22px; margin-bottom: 18px;
  background-color: var(--glass);
  background-image: var(--sheen-soft);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow-e1), var(--lip);
  transition: background-color var(--transition-fast), box-shadow var(--transition-base);
}
.endpoint:hover { background-color: var(--glass-strong); box-shadow: var(--shadow-e2), var(--lip); }

/* Twenty-five cards in a row read as one undifferentiated wall, so the
   reference is banded by what the endpoints are for. The rule sits above the
   heading rather than under it, which is what makes it a separator between
   groups instead of an underline belonging to the one below. */
.ep-group {
  margin: 34px 0 14px; padding-top: 18px;
  border-top: 1px solid var(--line);
  font-size: 12px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
}
.ep-group:first-of-type { margin-top: 18px; }

.endpoint > .path { font-family: var(--mono); font-size: 14.5px; font-weight: 600; margin-bottom: 8px; color: var(--text); }
.endpoint p { font-size: 14px; color: var(--text-2); }

.code-block-wrap { position: relative; margin-bottom: 16px; }
.copy-btn {
  position: absolute; top: 9px; inset-inline-end: 9px; z-index: 5;
  background-color: var(--glass-strong);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
          backdrop-filter: blur(10px) saturate(160%);
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  color: var(--muted); padding: 4px 11px; font-size: 11.5px; font-weight: 500; font-family: var(--sans);
  cursor: pointer; transition: all var(--transition-fast);
}
.copy-btn:hover { color: var(--accent); border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }

.pill {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 500;
  padding: 3px 11px; border-radius: var(--radius-pill); border: 1px solid var(--line);
  color: var(--muted); background: var(--glass-2);
}
.pill.ok { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 35%, transparent); background: var(--accent-dim); }
.pill.off { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 32%, transparent); background: color-mix(in srgb, var(--danger) 10%, transparent); }

.statusbar {
  position: relative;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background-color: var(--glass);
  background-image: var(--sheen);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  border: 1px solid var(--line);
  border-radius: var(--radius); padding: 15px 20px; margin: 0 0 20px;
  box-shadow: var(--shadow-e1), var(--lip);
}
.statusbar .mono { color: var(--text); font-size: 13.5px; font-weight: 500; }
.statusbar .muted { margin-inline-start: auto; font-size: 12.5px; }

/* Toast Notifications */
#toast-container {
  position: fixed; bottom: 24px; inset-inline-end: 24px; z-index: 9999;
  display: flex; flex-direction: column; gap: 10px; pointer-events: none;
}
.toast {
  position: relative;
  pointer-events: auto;
  background-color: var(--glass-strong);
  background-image: var(--sheen);
  -webkit-backdrop-filter: var(--glass-blur-lg);
          backdrop-filter: var(--glass-blur-lg);
  color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  padding: 11px 18px; font-size: 13px; font-weight: 500;
  box-shadow: var(--shadow-e3); display: flex; align-items: center; gap: 8px;
  animation: slideUp 260ms cubic-bezier(.22, 1, .36, 1);
}
.toast-icon { color: var(--accent); font-weight: bold; }
@keyframes slideUp { from { transform: translateY(12px) scale(.96); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } }

/* Modals */
.modal-overlay {
  position: fixed; inset: 0; z-index: 900;
  background: color-mix(in srgb, var(--bg) 55%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(140%); backdrop-filter: blur(14px) saturate(140%);
  display: flex; align-items: center; justify-content: center; padding: 20px;
  opacity: 0; pointer-events: none; transition: opacity var(--transition-fast);
}
.modal-overlay.open { opacity: 1; pointer-events: auto; }
.modal {
  position: relative;
  background-color: var(--glass-strong);
  background-image: var(--sheen);
  -webkit-backdrop-filter: var(--glass-blur-lg);
          backdrop-filter: var(--glass-blur-lg);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  max-width: 520px; width: 100%; padding: 24px 26px; box-shadow: var(--shadow-e3), var(--lip);
  transform: scale(0.95) translateY(8px); transition: transform var(--transition-base);
  max-height: 85vh; overflow-y: auto;
}
.modal-overlay.open .modal { transform: scale(1) translateY(0); }
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; border-bottom: 1px solid var(--line); padding-bottom: 12px; }
.modal-head h2 { margin: 0; padding: 0; border: 0; font-size: 18px; }
.modal-close {
  background: none; border: 0; color: var(--muted); font-size: 20px; cursor: pointer;
  width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
  transition: all var(--transition-fast);
}
.modal-close:hover { color: var(--text); background: var(--panel-3); }

/* Custom Leaflet Map Controls Design Override */
.leaflet-control-zoom {
  border: 1px solid var(--line) !important;
  border-radius: var(--radius) !important;
  overflow: hidden !important;
  box-shadow: var(--shadow-e2) !important;
  margin-left: 16px !important;
  margin-bottom: 16px !important;
  -webkit-backdrop-filter: var(--glass-blur) !important;
          backdrop-filter: var(--glass-blur) !important;
}

.leaflet-control-zoom-in, .leaflet-control-zoom-out {
  background: var(--glass) !important;
  color: var(--text) !important;
  border: 0 !important;
  border-bottom: 1px solid var(--line) !important;
  width: 36px !important;
  height: 36px !important;
  line-height: 36px !important;
  font-size: 17px !important;
  font-weight: 600 !important;
  transition: all var(--transition-fast) !important;
  text-indent: 0 !important;
}

.leaflet-control-zoom-out {
  border-bottom: 0 !important;
}

.leaflet-control-zoom-in:hover, .leaflet-control-zoom-out:hover {
  background: var(--glass-strong) !important;
  color: var(--accent) !important;
}

.leaflet-control-scale {
  margin-left: 16px !important;
  margin-bottom: 16px !important;
}

.leaflet-control-scale-line {
  background: var(--glass) !important;
  -webkit-backdrop-filter: var(--glass-blur) !important;
          backdrop-filter: var(--glass-blur) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--radius-pill) !important;
  color: var(--text-2) !important;
  font-family: var(--mono) !important;
  font-size: 11.5px !important;
  font-weight: 500 !important;
  padding: 5px 12px !important;
  box-shadow: var(--shadow-e1) !important;
  text-shadow: none !important;
  line-height: 1.4 !important;
}

@media (max-width: 768px) {
  /* 16px is the floor at which mobile Safari stops zooming the page on focus
     and at which body copy stays comfortably readable. */
  body { font-size: 16px; }
  h1 { font-size: 28px; }
  header.top .wrap { padding: 0 14px; gap: 12px; }
  .header-search { display: none; }
  .wrap { padding: 0 16px; }
  main.wrap { padding: 32px 16px 72px; }
  .grid { grid-template-columns: 1fr; }
  #toast-container { left: 16px; right: 16px; bottom: 16px; }
}

/* Motion is decoration here — every animation has a static resting state that
   says the same thing, so the whole lot can be switched off at once. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .card:hover, .btn:hover { transform: none; }
}

/* ===========================================================================
   Bilingual layer — language switch + RTL
   ---------------------------------------------------------------------------
   Most of the mirroring is already done above by logical properties, which
   need no counterpart here. What is left falls into three groups:

     1. Things a physical value is genuinely the right answer for — a translate
        offset on a toggle thumb, the chevron baked into the select background.
     2. Leaflet, which is not direction-aware. The map container is pinned to
        `direction: ltr` so Leaflet's own positioning math is untouched, and
        only the prose inside popups is flipped back to RTL.
     3. Typography. The negative tracking that tightens Inter headlines closes
        the gaps Arabic letterforms need to stay joined and legible, so it is
        reset wherever the text can be Arabic.
   =========================================================================== */

/* One swap reaches everything, because every rule in this file asks for
   var(--sans) rather than naming a family. --mono is deliberately left alone:
   code, TIS strings and coordinates stay Latin in both languages. */
[dir="rtl"] { --sans: var(--sans-ar); }

/* Arabic sets taller than Latin at the same size -- ascenders, descenders and
   the dot clusters below the baseline all need room that Inter's leading does
   not leave. These are the only metric changes; nothing here resizes a box. */
[dir="rtl"] body { line-height: 1.75; }
[dir="rtl"] p, [dir="rtl"] li { line-height: 1.85; }
[dir="rtl"] .lead { line-height: 1.8; }
[dir="rtl"] h1, [dir="rtl"] h2, [dir="rtl"] h3 { line-height: 1.4; }

/* The Arabic face stops at 700, and asking for 800 gets a synthesised bold
   that smears the joins. */
[dir="rtl"] .hero-title, [dir="rtl"] .brand { font-weight: 700; }

/* The Arabic text is filled in by script, so there is a short window where
   the markup still says English. The head script opens that window and
   applyI18n() closes it. Only body's children are hidden, never body itself --
   the background keeps painting, so this reads as the page arriving rather
   than as a blank gap, and English is never shown and then swapped. */
html.i18n-wait body > * { visibility: hidden; }

/* Latin data inside Arabic prose — TIS strings, Grid Codes, coordinates, JSON,
   endpoint paths. `isolate` is the load-bearing half: without it the bidi
   algorithm reorders a trailing bracket or minus sign to the far end of the
   run, and "t108858156b1ffff8" or "-46.72" comes out visibly wrong. */
/* No text-align here on purpose: an element with direction:ltr already
   resolves text-align:start to left, which is right for a code block, an input
   or a JSON dump. The one case it gets wrong is a lone figure that should keep
   hugging the panel edge, handled where that figure lives. */
.ltr { direction: ltr; unicode-bidi: isolate; }
[dir="rtl"] code, [dir="rtl"] pre { direction: ltr; unicode-bidi: isolate; }

/* .mono is only isolated, never re-directed. Plenty of mono readouts here are
   a Latin number followed by an Arabic unit -- "1,913,839 كم²" -- and forcing
   that run LTR puts the unit on the wrong side of its figure and the ² on the
   wrong side of its unit. Isolation is all it needs: digits already run LTR
   inside an RTL line by the bidi algorithm''s own rules. Cells that really are
   all-Latin (a TIS, a grid version, a bbox) opt in with .ltr instead. */
[dir="rtl"] .mono { unicode-bidi: isolate; }

/* An .ltr table cell still belongs to an RTL column, so its box hugs the
   reading edge even though its text runs the other way. */
[dir="rtl"] td.ltr, [dir="rtl"] th.ltr { text-align: right; }

/* Language switch — same pill as the theme toggle, so the pair reads as one
   control group rather than as a button that wandered into the nav. */
.lang-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  background-color: var(--glass-2); background-image: var(--sheen-soft);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
          backdrop-filter: blur(12px) saturate(160%);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill); padding: 5px 13px; min-height: 36px;
  cursor: pointer; transition: all var(--transition-fast);
  color: var(--text-2); font-size: 12px; font-weight: 600;
  -webkit-user-select: none; user-select: none; flex-shrink: 0; outline: none;
}
.lang-toggle:hover {
  border-color: var(--accent); background-color: var(--glass); color: var(--text);
  box-shadow: 0 0 0 4px var(--accent-glow);
}
.lang-toggle:focus-visible { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-glow); }
.lang-toggle svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--muted); transition: color var(--transition-fast); }
.lang-toggle:hover svg { color: var(--accent); }
/* The label is one script or the other and never wraps; the min-width stops
   the pill resizing as it swaps between "عربي" and "EN". */
.lang-toggle .lang-label {
  min-width: 26px; text-align: center; line-height: 1.5;
  font-family: var(--sans); white-space: nowrap;
}

/* --------------------------------------------------------------- RTL fixes */

/* Inter's tracking is tuned for Latin. Arabic is cursive: pulling letters
   together breaks the joins, and pushing them apart severs the word. */
[dir="rtl"] h1, [dir="rtl"] h2, [dir="rtl"] h3, [dir="rtl"] h4,
[dir="rtl"] .lead, [dir="rtl"] .label, [dir="rtl"] th,
[dir="rtl"] .hero-badge, [dir="rtl"] .hero-title, [dir="rtl"] .brand,
[dir="rtl"] .res-meta, [dir="rtl"] .tag, [dir="rtl"] .pop dt,
[dir="rtl"] .pop-head h2, [dir="rtl"] .panel-head h1,
[dir="rtl"] label.field > span, [dir="rtl"] .swatch .cap,
[dir="rtl"] .hero .unit { letter-spacing: normal; }

/* The chevron is a background image, so no logical property reaches it. */
[dir="rtl"] select { background-position: left 13px center; }

/* Physical because the value is a distance, not an edge. */
[dir="rtl"][data-theme="light"] .theme-toggle .toggle-thumb { transform: translateX(-13px); }

/* Leaflet positions everything from `left`/`top` in pixels and its control
   corners are physical classes, so the map keeps LTR and the controls are
   moved by hand. `[dir=rtl]` sits on <html>, above the pinned container, so
   these still match. */
[dir="rtl"] .leaflet-control-zoom,
[dir="rtl"] .leaflet-control-scale {
  margin-left: 0 !important; margin-right: 16px !important;
}
/* Prose inside a popup is the one part of the map that is language, not
   geometry, so it flips back. */
[dir="rtl"] .leaflet-popup-content { direction: rtl; text-align: right; }
[dir="rtl"] .leaflet-popup-close-button { right: auto !important; left: 7px !important; }

@media (max-width: 768px) {
  [dir="rtl"] .leaflet-control-zoom,
  [dir="rtl"] .leaflet-control-scale { margin-right: 12px !important; }
}
