/* ============================================================
   Base element styles + layout utilities.
   Everything here is token-driven, so both themes inherit.
   ============================================================ */

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

/* The `hidden` attribute must win over any component display rule. A
   class selector outranks the UA's `[hidden]`, so without this a
   `display: flex` container silently ignores being hidden. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  font: var(--font-body);
  font-family: var(--font-sans);
  color: var(--text-body);
  background: var(--surface-page);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  transition: background var(--duration-slow) var(--ease-standard),
              color var(--duration-slow) var(--ease-standard);
}

h1, h2, h3, h4, h5, h6 { color: var(--text-strong); font-family: var(--font-sans); }
h1 { font: var(--font-h1); }
h2 { font: var(--font-h2); }
h3 { font: var(--font-h3); }
h4 { font: var(--font-h4); }
p  { text-wrap: pretty; }

a {
  color: var(--text-link);
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-standard);
}
a:hover { color: var(--color-primary-active); }

::selection { background: var(--color-primary-tint); color: var(--text-strong); }

/* An icon with no explicit size and no component rule sizes to the text
   around it, rather than stretching to fill whatever box it landed in.
   Component rules (.btn__icon, .iconbtn svg, …) load later and win. */
svg:not([width]) { width: 1em; height: 1em; flex: 0 0 auto; }
svg { vertical-align: middle; }

:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* Scrollbars — thin, themed, never a bright slab in dark mode. */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-default);
  border-radius: var(--radius-pill);
  border: 3px solid transparent;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--border-strong); background-clip: content-box; }

/* ---------- Type utilities ---------- */
.tx-eyebrow {
  font: var(--font-overline);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-subtle);
}
.tx-mono    { font-family: var(--font-mono); font-size: 0.92em; letter-spacing: 0; }
.tx-num     { font-variant-numeric: tabular-nums; }
.tx-muted   { color: var(--text-muted); }
.tx-subtle  { color: var(--text-subtle); }
.tx-strong  { color: var(--text-strong); font-weight: var(--weight-medium); }
.tx-caption { font: var(--font-caption); color: var(--text-muted); }
.tx-label   { font: var(--font-label); }
.tx-pos     { color: var(--status-success-fg); }
.tx-neg     { color: var(--status-danger-fg); }
.truncate   { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- Layout utilities ---------- */
.stack     { display: flex; flex-direction: column; gap: var(--space-5); }
.stack--sm { gap: var(--space-3); }
.stack--lg { gap: var(--space-7); }
.row       { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.row--between { justify-content: space-between; }
.row--end     { justify-content: flex-end; }
.row--nowrap  { flex-wrap: nowrap; }
.row--top     { align-items: flex-start; }
.grow      { flex: 1 1 auto; min-width: 0; }
.spacer    { flex: 1 1 auto; }
.hidden    { display: none !important; }

.grid { display: grid; gap: var(--space-5); }
.grid--kpi  { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.grid--2    { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3    { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4    { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid--7-5  { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
.grid--8-4  { grid-template-columns: minmax(0, 8fr) minmax(0, 4fr); }
.grid--form { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
.grid--form > .span-2 { grid-column: 1 / -1; }

@media (max-width: 1240px) {
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1024px) {
  .grid--2, .grid--3, .grid--7-5, .grid--8-4, .grid--form { grid-template-columns: 1fr; }
}

/* ---------- Print ---------- */
@media print {
  .no-print { display: none !important; }
  body { background: #fff; }
}

/* Screen-reader-only text: present to assistive tech, absent on screen. */
.u-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ════════════════════════════════════════════════════════════════
   Right-to-left.

   Nearly everything mirrors on its own: the stylesheets use logical
   properties (inset-inline, margin-inline, text-align: start), which
   follow `dir` on <html>. What is left here is the handful of things
   logical properties cannot express — transforms, which are always
   physical, and glyphs that point one way.
   ════════════════════════════════════════════════════════════════ */
[dir="rtl"] .ask { transform: translateX(-100%); }
[dir="rtl"] .ask.is-open { transform: translateX(0); }
[dir="rtl"] .drawer { transform: translateX(-100%); }
[dir="rtl"] .drawer.is-open { transform: translateX(0); }
[dir="rtl"] .ask__opener:hover { transform: translateX(-2px); }

/* Arrows and chevrons point at a direction, so they flip with the text. */
[dir="rtl"] .nav__link--out .nav__out-hint,
[dir="rtl"] .shell__rail-btn svg,
[dir="rtl"] .cmprow__arrow svg,
[dir="rtl"] .cmpstrip__pair svg,
[dir="rtl"] .ask__action--go svg,
[dir="rtl"] .btn [data-icon="arrow-right"] svg,
[dir="rtl"] .btn [data-icon="chevron-right"] svg,
[dir="rtl"] [data-icon="chevron-right"] > svg { transform: scaleX(-1); }
[dir="rtl"] .shell--collapsed .shell__rail-btn svg { transform: scaleX(-1) rotate(180deg); }

/* The marker slides along the inline axis; its own transform is vertical,
   so only the collapsed offset needs restating. */
[dir="rtl"] .signals__more > summary::before { content: '◂ '; }
[dir="rtl"] .signals__more[open] > summary::before { content: '▾ '; }
[dir="rtl"] .catrow__head::before { content: none; }

/* Latin digits inside Arabic text still read left to right; isolating the
   run stops a figure and its unit swapping places. */
[dir="rtl"] .tx-num,
[dir="rtl"] .statbig__value,
[dir="rtl"] .conc__value,
[dir="rtl"] .cmprow__a,
[dir="rtl"] .cmprow__b,
[dir="rtl"] .cmpstrip__now,
[dir="rtl"] .cmpstrip__was,
[dir="rtl"] .score__value,
[dir="rtl"] .num,
[dir="rtl"] .delta,
[dir="rtl"] .chip__n,
[dir="rtl"] .kbd { unicode-bidi: isolate; direction: ltr; }

/* A table of figures stays left-aligned in its cells even in RTL, because
   the digits themselves are Latin and column alignment is what makes a
   total scannable. */
[dir="rtl"] table td.num, [dir="rtl"] table th.num { text-align: left; }

/* Mixed-script runs. A line like "3 customers · Jan 2026" inside an RTL
   page gets reordered by the bidi algorithm and comes out as
   "customers · Jan 2026 3". `plaintext` takes the direction from the
   first strong character in the line instead, which keeps each caption
   readable whichever language wrote it. */
[dir="rtl"] .hero__sub,
[dir="rtl"] .tx-caption,
[dir="rtl"] .page-foot,
[dir="rtl"] .statbig__foot,
[dir="rtl"] .tension__legend,
[dir="rtl"] .tension__hint,
[dir="rtl"] .rowlist__meta,
[dir="rtl"] .signal__desc,
[dir="rtl"] .score__bench,
[dir="rtl"] .standout__meta,
[dir="rtl"] .catrow__stat,
[dir="rtl"] .ratenote,
[dir="rtl"] .card__bar .tx-caption,
[dir="rtl"] .section-head__note,
[dir="rtl"] .facets__note,
[dir="rtl"] .conc__note,
[dir="rtl"] .ask__sub,
[dir="rtl"] .ask__foot { unicode-bidi: plaintext; }

/* ════════════════════════════════════════════════════════════════════
   Arabic

   Arabic sets optically smaller than Latin at the same point size and
   needs more room between lines: its ascenders and descenders reach
   further, and dots below the baseline collide with the line under them
   at Latin leading. Both are corrected here rather than in each
   component, so nothing has to remember.
   ════════════════════════════════════════════════════════════════════ */
[lang="ar"] {
  --leading-normal: 1.75;
  --leading-snug: 1.6;
  --leading-tight: 1.45;
}
[lang="ar"] body { font-size: 1.02em; }
/* Arabic has no case, so an uppercase transform does nothing but strip
   the letter-spacing rules that follow it of any purpose. */
[lang="ar"] .tx-label,
[lang="ar"] .card__bar-title,
[lang="ar"] [class*="__label"],
[lang="ar"] [class*="__overline"] { text-transform: none; letter-spacing: 0; }

/* Figures, codes and identifiers stay Latin in both languages, so each
   one is isolated: an unisolated Latin run inside Arabic prose is
   reordered by the bidi algorithm and lands in the wrong place in the
   sentence. */
[dir="rtl"] .tx-mono,
[dir="rtl"] code,
[dir="rtl"] .ask__num,
[dir="rtl"] .statbig__value,
[dir="rtl"] .rfqstat__value,
[dir="rtl"] .funnel__count,
[dir="rtl"] .table .num { unicode-bidi: isolate; }

/* A paragraph whose language differs from the page — an Arabic answer in
   an English shell, or an English supplier name in an Arabic one — takes
   its direction from its own first strong character. */
.bidi-auto { unicode-bidi: plaintext; }

/* ════════════════════════════════════════════════════════════════════
   Scrolling

   One rule decides which way each scroller behaves, because getting it
   backwards is invisible until someone tries to scroll past something.

   Content that is part of the page chains: reaching the end of a table
   or a sized panel carries on scrolling the page, so a wheel travelling
   down the page is never stopped by something it passed over.

   Content that floats above the page contains: a menu, a modal or the
   assistant must not scroll the page behind them, because that page is
   not what the reader is looking at and will have moved when they close
   it.
   ════════════════════════════════════════════════════════════════════ */
.table-wrap--scroll,
.scroll-350,
.scroll-600,
.lay__cell--fixed .table-wrap { overscroll-behavior: auto; }

.modal,
.modal__body,
.drawer__body,
.menu,
.ask__thread,
.ask__history,
.palette__list { overscroll-behavior: contain; }

/* An anchored jump should land softly, unless the reader has asked for
   no motion at all. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* A toast you can act on. */
.toast--action { align-items: center; }
.toast__action {
  flex: none;
  margin-inline-start: var(--space-3);
  padding: 4px 12px;
  border: 1px solid currentColor;
  border-radius: var(--radius-pill);
  background: transparent;
  color: inherit;
  font: var(--font-label);
  cursor: pointer;
}
.toast__action:hover { background: rgba(255, 255, 255, 0.14); }
