/* ============================================================
   FONTS — self-hosted, variable weight 400–700
   ------------------------------------------------------------
   Latin base (Inter Tight + JetBrains Mono) + per-script Noto Sans
   subsets for non-Latin locales (task 0193). Every script font carries
   `unicode-range` so the browser only fetches a script WOFF2 when a
   codepoint in that range is actually painted — a global --font-sans
   can therefore list all script fonts without forcing downloads on
   pages that don't use them.

   Locale → script map:
     bn         → Bengali
     hi, mr     → Devanagari
     te         → Telugu
     ta         → Tamil
     ml         → Malayalam
     ar, ur, fa → Perso-Arabic
     th         → Thai
     zh, zh-TW, ja, ko → CJK (OS fallback only — not self-hosted in v1;
                              CJK on Google Fonts ships as ~120 numerical
                              subsets per family and a single-WOFF2 mirror
                              would add 2+ MB to the repo. Falls back to
                              the OS-installed CJK fonts listed in
                              --font-sans below.)
   ============================================================ */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/InterTight-VariableFont_wght.83d548cd.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/JetBrainsMono-VariableFont_wght.2c32b9b3.woff2') format('woff2');
}
@font-face {
  font-family: 'Noto Sans Bengali';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/NotoSansBengali-VariableFont_wght.d8cebde0.woff2') format('woff2');
  unicode-range: U+0951-0952, U+0964-0965, U+0980-09FE, U+1CD0, U+1CD2, U+1CD5-1CD6, U+1CD8, U+1CE1, U+1CEA, U+1CED, U+1CF2, U+1CF5-1CF7, U+200C-200D, U+20B9, U+25CC, U+A8F1;
}
@font-face {
  font-family: 'Noto Sans Devanagari';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/NotoSansDevanagari-VariableFont_wght.12223f2b.woff2') format('woff2');
  unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B09;
}
@font-face {
  font-family: 'Noto Sans Telugu';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/NotoSansTelugu-VariableFont_wght.58649143.woff2') format('woff2');
  unicode-range: U+0951-0952, U+0964-0965, U+0C00-0C7F, U+1CDA, U+1CF2, U+200C-200D, U+25CC;
}
@font-face {
  font-family: 'Noto Sans Tamil';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/NotoSansTamil-VariableFont_wght.638b6415.woff2') format('woff2');
  unicode-range: U+0964-0965, U+0B82-0BFA, U+200C-200D, U+20B9, U+25CC;
}
@font-face {
  font-family: 'Noto Sans Malayalam';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/NotoSansMalayalam-VariableFont_wght.2acce70e.woff2') format('woff2');
  unicode-range: U+0307, U+0323, U+0951-0952, U+0964-0965, U+0D00-0D7F, U+1CDA, U+1CF2, U+200C-200D, U+20B9, U+25CC, U+A830-A832;
}
@font-face {
  font-family: 'Noto Sans Arabic';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/NotoSansArabic-VariableFont_wght.69cdf0bf.woff2') format('woff2');
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, 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-10EC4, U+10EFC-10EFF, 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;
}
@font-face {
  font-family: 'Noto Sans Thai';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/NotoSansThai-VariableFont_wght.0558c764.woff2') format('woff2');
  unicode-range: U+02D7, U+0303, U+0331, U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: 'Noto Sans Gujarati';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/NotoSansGujarati-VariableFont_wght.dc3754ae.woff2') format('woff2');
  unicode-range: U+0951-0952, U+0964-0965, U+0A80-0AFF, U+200C-200D, U+20B9, U+25CC, U+A830-A839;
}
@font-face {
  font-family: 'Noto Sans Kannada';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/NotoSansKannada-VariableFont_wght.22c2991d.woff2') format('woff2');
  unicode-range: U+0951-0952, U+0964-0965, U+0C80-0CF3, U+1CD0, U+1CD2-1CD3, U+1CDA, U+1CF2, U+1CF4, U+200C-200D, U+20B9, U+25CC, U+A830-A835;
}
@font-face {
  font-family: 'Noto Sans Gurmukhi';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/NotoSansGurmukhi-VariableFont_wght.51729fe1.woff2') format('woff2');
  unicode-range: U+0951-0952, U+0964-0965, U+0A01-0A76, U+200C-200D, U+20B9, U+25CC, U+262C, U+A830-A839;
}

/* ============================================================
   TOKENS — Workshop Terminal palette (light)
   ============================================================ */
:root {
  --color-bg:             #f4efe6;
  --color-bg-elevated:    #fbf8f1;
  --color-surface-sunken: #ebe4d6;
  --color-ink:            #14110d;
  --color-ink-muted:      #6b6358;
  --color-ink-faint:      #a39684;
  --color-rule:           #d8cdb7;
  --color-rule-strong:    #b8a98d;
  --color-signal:         #d2511a;
  --color-signal-hover:   #b8420f;
  --color-signal-soft:    #f4d8c4;
  --color-success:        #2f6b3a;
  --color-success-soft:   #d6e6d0;
  --color-danger:         #a8321a;
  --color-danger-soft:    #f0d4cb;
  --color-code-bg:        #efe9dc;
  --color-code-fg:        #14110d;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  --radius-0: 0;
  --radius-1: 2px;
  --radius-2: 4px;

  --text-xs:   12px;
  --text-sm:   14px;
  --text-base: 16px;
  --text-md:   18px;
  --text-lg:   22px;
  --text-xl:   28px;
  --text-2xl:  36px;

  --leading-tight:  1.2;
  --leading-snug:   1.35;
  --leading-normal: 1.6;

  /* Inter Tight covers Latin; each Noto Sans <script> covers its own
     unicode-range so listing them all here is safe — the browser
     downloads a script font only when a glyph in its range is painted
     (task 0193). CJK families are OS-installed fallbacks, NOT self-hosted
     in v1 (see @font-face header above for rationale). */
  --font-sans: 'Inter Tight',
               'Noto Sans Bengali', 'Noto Sans Devanagari', 'Noto Sans Telugu',
               'Noto Sans Tamil', 'Noto Sans Malayalam', 'Noto Sans Arabic',
               'Noto Sans Thai', 'Noto Sans Gujarati', 'Noto Sans Kannada',
               'Noto Sans Gurmukhi',
               'PingFang SC', 'Hiragino Sans', 'Hiragino Kaku Gothic ProN',
               'Apple SD Gothic Neo', 'Noto Sans CJK SC', 'Noto Sans CJK JP',
               'Noto Sans CJK KR', 'Microsoft YaHei', 'Microsoft JhengHei',
               'Yu Gothic', 'Malgun Gothic',
               'IBM Plex Sans', -apple-system, BlinkMacSystemFont,
               'Segoe UI', 'Helvetica Neue', sans-serif;
  --font-mono: 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, 'SF Mono',
               Menlo, Consolas, 'Liberation Mono', monospace;

  --container-max: 1180px;
}

/* Dark tokens — explicit selection via [data-theme="dark"] on <html>. */
[data-theme="dark"] {
  --color-bg:             #161310;
  --color-bg-elevated:    #1d1916;
  --color-surface-sunken: #0f0d0b;
  --color-ink:            #ece4d3;
  --color-ink-muted:      #9e9484;
  --color-ink-faint:      #5f574b;
  --color-rule:           #2f2924;
  --color-rule-strong:    #4a4239;
  --color-signal:         #f08a4a;
  --color-signal-hover:   #ffa46b;
  --color-signal-soft:    #3a2517;
  --color-success:        #6ab97a;
  --color-success-soft:   #1d3022;
  --color-danger:         #e26a4d;
  --color-danger-soft:    #3a1c14;
  --color-code-bg:        #11100e;
  --color-code-fg:        #ece4d3;
}

/* OS preference fallback — only applies on first visit before the FOUC
   script sets data-theme. Once data-theme is on <html>, the rule above
   wins (more specific selector). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --color-bg:             #161310;
    --color-bg-elevated:    #1d1916;
    --color-surface-sunken: #0f0d0b;
    --color-ink:            #ece4d3;
    --color-ink-muted:      #9e9484;
    --color-ink-faint:      #5f574b;
    --color-rule:           #2f2924;
    --color-rule-strong:    #4a4239;
    --color-signal:         #f08a4a;
    --color-signal-hover:   #ffa46b;
    --color-signal-soft:    #3a2517;
    --color-success:        #6ab97a;
    --color-success-soft:   #1d3022;
    --color-danger:         #e26a4d;
    --color-danger-soft:    #3a1c14;
    --color-code-bg:        #11100e;
    --color-code-fg:        #ece4d3;
  }
}

/* ============================================================
   RESET + BASE
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-mono);
  font-size: var(--text-base);
  line-height: var(--leading-snug);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a {
  color: var(--color-ink);
  text-decoration: underline;
  text-decoration-color: var(--color-signal);
  text-underline-offset: 3px;
}
a:hover { color: var(--color-signal); }
:focus-visible {
  outline: 2px solid var(--color-signal);
  outline-offset: 2px;
}
button { font: inherit; cursor: pointer; }
h1, h2, h3, h4 {
  font-family: var(--font-mono);
  font-weight: 600;
  line-height: var(--leading-tight);
  margin: 0;
}

html[lang="ar"],
html[lang="ur"] {
  direction: rtl;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   LAYOUT
   ============================================================ */
.page {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--space-4);
}

/* ============================================================
   HEADER STRIP
   ============================================================ */
.site-header {
  border-bottom: 1px solid var(--color-rule);
  background: var(--color-bg);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  flex-wrap: wrap;
}
.logo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
  color: var(--color-ink);
}
.logo strong { font-weight: 700; }
.logo__slash { color: var(--color-signal); }
.logo__sub { color: var(--color-ink-muted); font-weight: 400; text-transform: uppercase; }
/* SVG wordmark — height drives the size, viewBox is cropped to the actual mark
   extents (about 296:46, roughly 6.4:1) so it sits tight against the slash. */
.logo__mark {
  height: 22px;
  width: auto;
  display: block;
  flex: 0 0 auto;
}

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

/* ------- tool switcher trigger chip (task 0188 — command palette) -------
   The flat <details> dropdown is gone. The chip is now a plain button that
   opens the modal command palette below. Keeps the [ cd ./<slug> ] visual
   identity but adds a ⌘K hint and an aria-haspopup="dialog" relationship. */
.tool-switcher { position: relative; }
.tool-switcher__trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-rule-strong);
  background: var(--color-bg-elevated);
  color: var(--color-ink);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  cursor: pointer;
  border-radius: var(--radius-0);
  user-select: none;
  transition: border-color 100ms ease-out, background 100ms ease-out;
}
.tool-switcher__trigger::before {
  content: "[";
  color: var(--color-signal);
  font-weight: 700;
}
.tool-switcher__trigger::after {
  content: "]";
  color: var(--color-signal);
  font-weight: 700;
}
.tool-switcher__trigger:hover { border-color: var(--color-signal); }
.tool-switcher__trigger:focus-visible {
  outline: 2px solid var(--color-signal);
  outline-offset: 2px;
}
.tool-switcher__prefix { color: var(--color-ink-faint); }
.tool-switcher__current { color: var(--color-ink); }
.tool-switcher__kbd-hint {
  margin-inline-start: var(--space-2);
  padding: 2px 6px;
  border: 1px solid var(--color-rule);
  border-radius: 4px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
  background: var(--color-bg);
}

/* ------- command palette modal (task 0188) ------- */
.tool-palette {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 10vh 16px 16px;
}
.tool-palette[hidden] { display: none; }
.tool-palette__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(31, 27, 22, 0.5);
  cursor: pointer;
}
.tool-palette__panel {
  position: relative;
  width: 640px;
  max-width: 100%;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-rule-strong);
  border-radius: var(--radius-1, 12px);
  box-shadow: 0 24px 64px -16px rgba(31, 27, 22, 0.35),
              0 8px 24px -8px rgba(31, 27, 22, 0.18);
  display: flex;
  flex-direction: column;
  max-height: 75vh;
  overflow: hidden;
}
.tool-palette__search {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 14px var(--space-4);
  border-bottom: 1px solid var(--color-rule);
}
.tool-palette__search-icon {
  color: var(--color-ink-muted);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.tool-palette__input {
  flex: 1;
  border: 0;
  outline: 0;
  font-family: var(--font-mono);
  font-size: var(--text-md, 15px);
  color: var(--color-ink);
  background: transparent;
  min-width: 0;
}
.tool-palette__input::placeholder { color: var(--color-ink-muted); }
.tool-palette__results {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-2) 0;
  margin: 0;
  list-style: none;
}
.tool-palette__category {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  color: var(--color-ink-muted);
  padding: var(--space-3) var(--space-4) 4px;
  text-transform: uppercase;
}
.tool-palette__item {
  display: grid;
  grid-template-columns: 180px 1fr auto;
  align-items: center;
  gap: var(--space-3);
  padding: 10px var(--space-4);
  cursor: pointer;
  border-inline-start: 3px solid transparent;
  font-size: var(--text-sm);
}
.tool-palette__item--selected,
.tool-palette__item[aria-selected="true"] {
  background: var(--color-signal-soft, rgba(210, 81, 26, 0.12));
  border-inline-start-color: var(--color-signal);
}
.tool-palette__item--selected .tool-palette__slug,
.tool-palette__item[aria-selected="true"] .tool-palette__slug {
  color: var(--color-signal);
}
.tool-palette__slug {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tool-palette__meta { min-width: 0; }
.tool-palette__name {
  display: block;
  font-weight: 600;
  color: var(--color-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tool-palette__tagline {
  display: block;
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tool-palette__active-pill {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--color-signal);
  border: 1px solid var(--color-signal);
  padding: 2px 6px;
  border-radius: 4px;
  margin-inline-start: 6px;
  font-weight: normal;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.tool-palette__badge {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border: 1px solid var(--color-rule);
  border-radius: 999px;
  color: var(--color-ink-muted);
  text-transform: uppercase;
  white-space: nowrap;
}
.tool-palette__footer {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--color-rule);
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
  background: var(--color-bg);
  flex-wrap: wrap;
}
.tool-palette__footer kbd {
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 2px 6px;
  border: 1px solid var(--color-rule);
  border-bottom-width: 2px;
  border-radius: 3px;
  background: var(--color-bg-elevated);
  color: var(--color-ink);
  margin-inline-end: 4px;
}
.tool-palette__empty {
  padding: var(--space-5) var(--space-4);
  color: var(--color-ink-muted);
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  list-style: none;
}
@media (max-width: 640px) {
  .tool-palette__panel { max-height: calc(100vh - 80px); }
  .tool-palette__item {
    grid-template-columns: 100px 1fr auto;
    font-size: var(--text-xs);
  }
  .tool-palette__slug { font-size: 11px; }
}

/* ------- hub categorized card grid (task 0188) ------- */
.hub-categories,
.hub-category { display: block; }
.hub-category + .hub-category { margin-top: var(--space-6); }
.hub-category__heading {
  font-family: var(--font-mono);
  font-size: var(--text-md);
  color: var(--color-ink);
  margin: 0 0 var(--space-3);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 600;
  border-bottom: 1px solid var(--color-rule);
  padding-bottom: var(--space-2);
}
.hub-category__heading::before {
  content: "// ";
  color: var(--color-ink-faint);
  font-weight: 400;
}
.hub-category__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--space-3);
}

/* ------- language picker (kept compact) ------- */
.language-picker {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.language-picker__icon { color: var(--color-ink-muted); }
.language-picker select {
  font: inherit;
  padding: var(--space-2) var(--space-3);
  background: var(--color-bg-elevated);
  color: var(--color-ink);
  border: 1px solid var(--color-rule-strong);
  border-radius: var(--radius-0);
  cursor: pointer;
}
.language-picker select:focus { border-color: var(--color-signal); }

/* ------- theme toggle ------- */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--color-rule-strong);
  background: var(--color-bg-elevated);
  color: var(--color-ink);
  cursor: pointer;
  border-radius: var(--radius-0);
}
.theme-toggle:hover { border-color: var(--color-signal); color: var(--color-signal); }
.theme-toggle__icon { display: none; }
.theme-toggle__icon--sun { display: inline; }
[data-theme="dark"] .theme-toggle__icon--sun { display: none; }
[data-theme="dark"] .theme-toggle__icon--moon { display: inline; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .theme-toggle__icon--sun { display: none; }
  :root:not([data-theme]) .theme-toggle__icon--moon { display: inline; }
}

.header-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-rule);
  color: var(--color-ink);
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}
.header-link:hover {
  border-color: var(--color-signal);
  color: var(--color-signal);
}

/* ============================================================
   BREADCRUMB
   ============================================================ */
.breadcrumb {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: var(--space-4) 0 var(--space-2);
}
.breadcrumb a { color: var(--color-ink-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--color-signal); }
/* Each breadcrumb segment is bidi-isolated so mixed-script content
   (e.g. "Base64 مُرمِّز") renders as one unit instead of getting
   shredded across the trail by the Unicode Bidi Algorithm. */
.breadcrumb a,
.breadcrumb [aria-current] { unicode-bidi: isolate; }
.breadcrumb__sep { margin: 0 var(--space-2); color: var(--color-ink-faint); unicode-bidi: isolate; }

/* ============================================================
   MAIN GRID — left ad rail + main column
   ============================================================ */
.layout {
  /* Flex (not grid) so that when ad-blockers `display: none` the
     .ad-rail aside (EasyList rule `##.ad-rail`), the remaining
     .main-content child naturally absorbs the freed space. CSS Grid's
     `:has()` selector doesn't help here: it matches on DOM presence,
     not computed style, so a display:none child still satisfies it.
     Flex layout ignores display:none items at the layout-math level. */
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding-bottom: var(--space-7);
}
@media (min-width: 1024px) {
  .layout { flex-direction: row; align-items: flex-start; }
  .layout > .ad-rail { flex: 0 0 160px; }
  .layout > .main-content { flex: 1 1 0; min-width: 0; }
}

.ad-rail {
  width: 160px;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}
/* Reserve vertical space for rail ad slots so AdSense fill does not cause
   Cumulative Layout Shift (task 0123, extends 0091). Inline style="..." on
   the <ins> elements is kept as belt-and-suspenders. */
.ad-rail__slot {
  width: 160px;
  min-height: 600px;
  display: block;
}
.ad-rail__slot--secondary {
  width: 160px;
  min-height: 250px;
  display: block;
}
/* If AdSense never fills the slot (ad-blocker or no-fill), collapse it
   instead of leaving a tall gap. AdSense injects child nodes as soon as
   it fills, so :empty matches only the truly-unfilled state. */
.ad-rail__slot:empty,
.ad-rail__slot--secondary:empty {
  min-height: 0;
}
@media (max-width: 1023px) {
  .ad-rail { display: none; }
}

.ad-banner {
  width: 100%;
  max-width: 100%;
  overflow-x: clip;
  display: block;
  margin: var(--space-4) 0;
  /* Reserve vertical space up front so AdSense fill does not cause
     Cumulative Layout Shift (task 0091). 100px is a safe lower bound
     for AdSense responsive `data-ad-format="auto"` slots, which
     typically render 90-280px on desktop and 50-250px on mobile. */
  min-height: 100px;
}
.ad-banner > * {
  max-width: 100% !important;
}
/* If AdSense never fills the slot (ad-blocker or unsold inventory),
   collapse it instead of leaving a 100px gap. AdSense injects child
   nodes (iframe or fallback) as soon as it fills, so :empty matches
   only the truly-unfilled state. */
.ad-banner:empty {
  min-height: 0;
  margin: 0;
}

/* ============================================================
   PANELS — § section blocks
   ============================================================ */
.panel {
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-rule);
  padding: var(--space-5);
  margin-bottom: var(--space-5);
}
.panel__header {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--color-rule);
}
.panel__glyph {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-signal);
  font-weight: 700;
}
.panel__title {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-ink);
  font-weight: 700;
}
.panel__hint {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-ink-faint);
}
[dir="rtl"] .panel__hint { margin-left: 0; margin-right: auto; }

/* ============================================================
   HEADLINE
   ============================================================ */
.page-headline {
  font-family: var(--font-mono);
  font-size: var(--text-2xl);
  letter-spacing: -0.01em;
  margin: var(--space-3) 0 var(--space-2);
}
.page-headline .accent { color: var(--color-signal); }
.page-lede {
  font-family: var(--font-sans);
  font-size: var(--text-md);
  color: var(--color-ink-muted);
  line-height: var(--leading-normal);
  max-width: 75ch;
  margin: 0 0 var(--space-6);
}
/* Per-locale regional-context paragraph (task 0147 — Bing §6 differentiation).
   Renders below the canonical definition + feature lede; carries an 80–120-word
   native-context block whose copy varies by locale. Empty stub class — visual
   differentiation (muted color, italic, etc.) can be tuned in a future design
   pass without re-touching every tool template. */
.page-lede--flavor {
  /* intentionally empty — design hook for future locale-flavor styling */
}

/* ============================================================
   TRUST BADGES (task 0100) — above-fold row directly under H1.
   Rendered in final form on initial paint (no display: none →
   display: flex transition) and uses min-height to reserve
   vertical space, so the row contributes 0 to CLS.
   ============================================================ */
.trust-badges {
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  min-height: 1.75rem;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.trust-badges__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  line-height: 1.4;
}
.trust-badges__icon {
  flex: 0 0 auto;
  color: var(--color-signal);
}
@media (max-width: 600px) {
  .trust-badges {
    flex-direction: column;
    gap: var(--space-1);
    min-height: 5.25rem;
  }
}

/* ============================================================
   INPUT / OUTPUT TEXTAREAS
   ============================================================ */
textarea {
  width: 100%;
  min-height: 220px;
  padding: var(--space-3) var(--space-4);
  background: var(--color-code-bg);
  color: var(--color-code-fg);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-0);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  resize: vertical;
}
textarea::placeholder { color: var(--color-ink-faint); }
textarea:focus {
  outline: none;
  border-color: var(--color-signal);
  box-shadow: inset 0 0 0 1px var(--color-signal);
}
.panel__caption {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-ink-faint);
  margin-top: var(--space-2);
  letter-spacing: 0.02em;
}

/* ============================================================
   OPTION ROWS
   ============================================================ */
.options {
  display: grid;
  gap: var(--space-3);
}
.option {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-ink);
}
.option input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  border: 1px solid var(--color-rule-strong);
  background: var(--color-bg);
  display: inline-grid;
  place-content: center;
  cursor: pointer;
  margin: 0;
}
.option input[type="checkbox"]:checked {
  background: var(--color-signal);
  border-color: var(--color-signal);
}
.option input[type="checkbox"]:checked::after {
  content: "";
  width: 8px;
  height: 4px;
  border-left: 1.5px solid #fff;
  border-bottom: 1.5px solid #fff;
  transform: rotate(-45deg) translate(0, -1px);
}
.option select {
  font: inherit;
  padding: 4px 8px;
  background: var(--color-bg);
  color: var(--color-ink);
  border: 1px solid var(--color-rule-strong);
  border-radius: var(--radius-0);
}

.actions-row {
  margin-top: var(--space-5);
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
}

/* ============================================================
   BUTTONS
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  background: var(--color-ink);
  color: var(--color-bg);
  border: 1px solid var(--color-ink);
  border-radius: var(--radius-0);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  text-decoration: none;
}
.btn:hover {
  background: var(--color-signal);
  border-color: var(--color-signal);
  color: #fff;
}
.btn--primary {
  background: var(--color-signal);
  border-color: var(--color-signal);
  color: #fff;
}
.btn--primary:hover {
  background: var(--color-signal-hover);
  border-color: var(--color-signal-hover);
}
.btn--ghost {
  background: transparent;
  color: var(--color-ink);
  border-color: var(--color-rule-strong);
}
.btn--ghost:hover {
  background: transparent;
  color: var(--color-signal);
  border-color: var(--color-signal);
}

.btn--live {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
}
.btn--live[data-state="on"] {
  background: var(--color-signal-soft);
  color: var(--color-signal);
  border-color: var(--color-signal);
}
.btn--live[data-state="on"] .btn--live__dot {
  background: var(--color-signal);
  animation: blink 1s steps(2, end) infinite;
}
.btn--live__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-ink-faint);
  display: inline-block;
}
@keyframes blink { 50% { opacity: 0.25; } }

/* ============================================================
   FILE DROPZONE
   ============================================================ */
.dropzone {
  border: 1.5px dashed var(--color-rule-strong);
  background: var(--color-surface-sunken);
  padding: var(--space-6);
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  cursor: pointer;
  transition: border-color 120ms ease-out, background 120ms ease-out;
  position: relative;
}
.dropzone:hover,
.dropzone:focus-within {
  border-color: var(--color-signal);
  color: var(--color-ink);
}
.dropzone input[type="file"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}

/* ============================================================
   FILE STATUS (progress / success / error)
   ============================================================ */
.file-progress,
.file-success,
.file-error {
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  border: 1px solid var(--color-rule);
}
.file-success {
  border-color: var(--color-success);
  background: var(--color-success-soft);
  color: var(--color-success);
}
.file-error {
  border-color: var(--color-danger);
  background: var(--color-danger-soft);
  color: var(--color-danger);
}
.file-progress progress {
  width: 100%;
  height: 6px;
  margin-top: var(--space-2);
}
.download-link {
  display: inline-block;
  margin-top: var(--space-2);
  font-family: var(--font-mono);
  color: var(--color-signal);
}

/* ============================================================
   RELATED TOOLS CARDS
   ============================================================ */
.related-tools { margin-top: var(--space-7); }
.related-tools__header {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--color-ink-muted);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--color-rule);
}
.card-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}
@media (min-width: 600px) {
  .card-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .card-grid { grid-template-columns: repeat(3, 1fr); }
}
.card {
  display: block;
  border: 1px solid var(--color-rule);
  background: var(--color-bg-elevated);
  padding: var(--space-4);
  text-decoration: none;
  color: var(--color-ink);
  transition: border-color 120ms ease-out;
}
.card:hover {
  border-color: var(--color-signal);
  color: var(--color-ink);
}
.card__path {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-ink-faint);
  margin-bottom: var(--space-2);
}
.card__title {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: var(--text-base);
  margin-bottom: var(--space-1);
}
.card__desc {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  line-height: var(--leading-normal);
}
.card__arrow {
  display: inline-block;
  margin-top: var(--space-3);
  color: var(--color-signal);
  font-family: var(--font-mono);
}
[dir="rtl"] .card__arrow { transform: scaleX(-1); display: inline-block; }

/* ============================================================
   PROSE
   ============================================================ */
.prose {
  max-width: 70ch;
  margin-top: var(--space-8);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-ink);
}
.prose h2 {
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  letter-spacing: -0.01em;
  margin-top: var(--space-7);
  margin-bottom: var(--space-3);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-rule);
}
.prose h3 {
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  margin-top: var(--space-5);
  margin-bottom: var(--space-2);
}
.prose p,
.prose ul,
.prose ol { margin: 0 0 var(--space-4); }
.prose ul,
.prose ol { padding-left: var(--space-5); }
[dir="rtl"] .prose ul,
[dir="rtl"] .prose ol { padding-left: 0; padding-right: var(--space-5); }
.prose code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  background: var(--color-code-bg);
  padding: 1px 6px;
  border-radius: var(--radius-1);
}
.prose strong { font-weight: 600; }
.prose .note {
  border-left: 2px solid var(--color-signal);
  padding: var(--space-3) var(--space-4);
  background: var(--color-bg-elevated);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
}
[dir="rtl"] .prose .note {
  border-left: 0;
  border-right: 2px solid var(--color-signal);
}

/* Long unbreakable example strings (e.g. JWT canonical token, future
   tool example_text) must wrap so they cannot push the layout wider
   than the viewport. Shared so any future tool inherits the guardrail. */
.example-token {
  overflow-wrap: anywhere;
  word-break: break-all;
  white-space: pre-wrap;
  max-width: 100%;
}

/* ============================================================
   FOOTER
   ============================================================ */
.site-footer {
  border-top: 1px solid var(--color-rule);
  padding: var(--space-5) 0;
  margin-top: var(--space-8);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-ink-faint);
  letter-spacing: 0.04em;
}
.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: space-between;
  align-items: center;
}
.site-footer a { color: var(--color-ink-muted); text-decoration: none; }
.site-footer a:hover { color: var(--color-signal); }
.site-footer__links {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
}

/* ============================================================
   RTL TWEAKS
   ============================================================ */
[dir="rtl"] body { direction: rtl; }
[dir="rtl"] .breadcrumb__sep { display: inline-block; transform: scaleX(-1); }

/* ============================================================
   MOBILE
   ============================================================ */
@media (max-width: 600px) {
  .site-header__inner { gap: var(--space-2); }
  .tool-switcher__trigger { font-size: var(--text-xs); }
  .tool-switcher__kbd-hint { display: none; }
  .panel { padding: var(--space-4); }
  .page-headline { font-size: var(--text-xl); }
}

/* ============================================================
   TOAST (task 0090) — non-blocking replacement for alert().
   Container is fixed-position so it never participates in layout
   (no CLS). Toasts animate via transform + opacity only.
   ============================================================ */
#ot-toast-container {
  position: fixed;
  inset: auto 0 var(--space-5) 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-4);
  pointer-events: none;
  z-index: 9999;
}
.ot-toast {
  pointer-events: auto;
  max-width: min(420px, 100%);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-2);
  border: 1px solid var(--color-rule-strong);
  background: var(--color-bg-elevated);
  color: var(--color-ink);
  font-size: var(--text-sm);
  line-height: 1.4;
  box-shadow: 0 6px 18px rgba(20, 17, 13, 0.18);
  opacity: 0;
  transform: translateY(8px);
}
.ot-toast--visible {
  opacity: 1;
  transform: translateY(0);
}
.ot-toast--success {
  border-color: var(--color-success);
  background: var(--color-success-soft);
  color: var(--color-success);
}
.ot-toast--error {
  border-color: var(--color-danger);
  background: var(--color-danger-soft);
  color: var(--color-danger);
}
@media (prefers-reduced-motion: no-preference) {
  .ot-toast {
    transition: opacity 180ms ease-out, transform 180ms ease-out;
  }
}
