/* ============================================================================
   ui.css — badge · tag · avatar · tooltip · popover · modal · drawer ·
            accordion · tabs · pagination · breadcrumb · toast · skeleton ·
            progress · empty-state · error-state · table · index-row · card
   ========================================================================= */

/* --- badge / tag --------------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding-inline: var(--sp-3); padding-block: 3px;
  border-radius: var(--r-input);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  font-weight: var(--weight-medium);
  border: 1px solid var(--border-strong);
  color: var(--fg-muted);
  background: transparent;
  white-space: nowrap;
}
.badge svg { inline-size: 12px; block-size: 12px; }
.badge--good     { color: var(--good);     border-color: color-mix(in oklab, var(--good) 45%, transparent); }
.badge--warning  { color: var(--warning);  border-color: color-mix(in oklab, var(--warning) 45%, transparent); }
.badge--serious  { color: var(--serious);  border-color: color-mix(in oklab, var(--serious) 45%, transparent); }
.badge--critical { color: var(--critical); border-color: color-mix(in oklab, var(--critical) 45%, transparent); }
.badge--solid    { background: var(--ink); color: var(--fg-on-dark); border-color: var(--ink); }
.badge--ember    { color: var(--ember-deep); border-color: var(--ember); }

.tag {
  display: inline-flex; align-items: center;
  min-block-size: 32px;
  padding-inline: var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--r-input);
  font-size: var(--fs-small);
  color: var(--fg-muted);
  text-decoration: none;
  transition: border-color var(--dur-hover) var(--ease-out), color var(--dur-hover) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .tag:hover { border-color: var(--fg); color: var(--fg); } }

/* --- avatar -------------------------------------------------------------- */
.avatar {
  inline-size: 40px; block-size: 40px; border-radius: 50%;
  object-fit: cover; background: var(--mist); flex: none;
  display: grid; place-content: center;
  font-family: var(--font-mono); font-size: var(--fs-label); color: var(--fg-muted);
}
.avatar--lg { inline-size: 56px; block-size: 56px; }

/* --- icon-tile -------------------------------------------------------------
   Replaces the ordinal counters (01, SVC-A, SEC-01 …) that used to carry the
   visual rhythm of every list and grid. The counter stays in the DOM as
   .visually-hidden where it was a label a screen reader could use; the tile
   itself is decorative and its <svg> is always aria-hidden.

   Logical properties throughout, so the tile sits on the correct side under
   RTL without a second rule. None of the mapped glyphs are directional, so
   none are mirrored.
   ------------------------------------------------------------------------- */
.icon-tile {
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  inline-size: var(--icon-tile);
  block-size: var(--icon-tile);
  border-radius: var(--r-card);
  background: var(--icon-tile-bg);
  color: var(--icon-tile-fg);
}

.icon-tile > svg {
  inline-size: var(--icon-tile-glyph);
  block-size: var(--icon-tile-glyph);
}

.icon-tile--sm { inline-size: var(--icon-tile-sm); block-size: var(--icon-tile-sm); }
.icon-tile--sm > svg { inline-size: 18px; block-size: 18px; }

/* On a dark ground the wash is too close to the surface to read as a tile, so
   the border does the separating instead of a heavier fill. */
:root[data-theme="dark"] .icon-tile { border: 1px solid color-mix(in oklab, var(--ember) 28%, transparent); }

/* --- index-row — rules between rows. The site's dominant list device. ---- */
.index {
  border-block-start: var(--rule-strong);
}
.index__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--sp-2) var(--sp-5);
  padding-block: var(--sp-5);
  border-block-end: var(--rule);
  text-decoration: none;
  color: inherit;
  position: relative;
  transition: background-color var(--dur-hover) var(--ease-out);
}
@media (min-width: 768px) {
  .index__row {
    grid-template-columns: 5rem minmax(0, 22ch) minmax(0, 1fr) auto;
    padding-inline: var(--sp-4);
    margin-inline: calc(var(--sp-4) * -1);
  }
}
/* The tile sits in the column .index__code held. The row is baseline-aligned
   for its text cells and a tile has no baseline, so it is pinned to the top. */
.index__row > .index__icon { align-self: start; }

.index__code {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
  transition: color var(--dur-hover) var(--ease-out);
}
.index__title { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-display); line-height: var(--lh-h3); }
.index__desc { color: var(--fg-muted); font-size: var(--fs-small); max-inline-size: 56ch; }
.index__arrow { inline-size: 16px; block-size: 16px; color: var(--fg-muted); flex: none;
  transition: transform var(--dur-hover) var(--ease-out), color var(--dur-hover) var(--ease-out); }
[dir="rtl"] .index__arrow { transform: scaleX(-1); }

@media (hover: hover) and (pointer: fine) {
  a.index__row:hover { background: var(--mist); }
  a.index__row:hover /* The tile sits in the column .index__code held. The row is baseline-aligned
   for its text cells and a tile has no baseline, so it is pinned to the top. */
.index__row > .index__icon { align-self: start; }

.index__code { color: var(--ember-deep); }
  a.index__row:hover .index__arrow { transform: translateX(4px); color: var(--fg); }
  [dir="rtl"] a.index__row:hover .index__arrow { transform: scaleX(-1) translateX(4px); }
}
@media (prefers-reduced-motion: reduce) {
  a.index__row:hover .index__arrow { transform: none; }
  [dir="rtl"] a.index__row:hover .index__arrow,
  [dir="rtl"] .index__arrow { transform: scaleX(-1); }
}

/* --- card — used ONLY for genuinely discrete clickable objects. ---------- */
.card {
  display: grid;
  gap: var(--sp-4);
  padding: var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  background: var(--surface);
  text-decoration: none;
  color: inherit;
  transition: border-color var(--dur-hover) var(--ease-out),
              transform var(--dur-hover) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  a.card:hover { border-color: color-mix(in oklab, var(--ember) 40%, transparent); transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) { a.card:hover { transform: none; } }
.card--flat { border: 0; padding: 0; background: transparent; }
.card__media { border-radius: var(--r-card); overflow: hidden; background: var(--mist); aspect-ratio: 16 / 10; }
.card__media img { inline-size: 100%; block-size: 100%; object-fit: cover;
  transition: transform var(--dur-panel) var(--ease-out); }
@media (hover: hover) and (pointer: fine) { a.card:hover .card__media img { transform: scale(1.03); } }
@media (prefers-reduced-motion: reduce) { a.card:hover .card__media img { transform: none; } }
.card__title { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-display); line-height: var(--lh-h3); }
.card__excerpt { color: var(--fg-muted); font-size: var(--fs-small); }
.card__meta { display: flex; gap: var(--sp-3); align-items: center; flex-wrap: wrap; }

/* --- accordion — CSS transition on grid-template-rows, not keyframes, so
       rapid toggling retargets rather than restarting from zero. ---------- */
.accordion { border-block-start: var(--rule); }
.accordion__item { border-block-end: var(--rule); }
.accordion__trigger {
  inline-size: 100%;
  display: grid;
  grid-template-columns: minmax(0,1fr) auto;
  gap: var(--sp-4);
  align-items: center;
  text-align: start;
  padding-block: var(--sp-5);
  min-block-size: var(--tap);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-display);
  line-height: var(--lh-h3);
  color: var(--fg);
  transition: color var(--dur-hover) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .accordion__trigger:hover { color: var(--ember-deep); } }
.accordion__chevron {
  inline-size: 20px; block-size: 20px; flex: none; color: var(--fg-muted);
  transition: transform 220ms var(--ease-out);
}
.accordion__trigger[aria-expanded="true"] .accordion__chevron { transform: rotate(180deg); }
.accordion__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 220ms var(--ease-out);
}
.accordion__trigger[aria-expanded="true"] + .accordion__panel { grid-template-rows: 1fr; }
.accordion__inner { overflow: hidden; }
.accordion__inner > div { padding-block-end: var(--sp-5); }
/* Without JS, every panel is open — content is never gated behind script. */
.no-js .accordion__panel { grid-template-rows: 1fr; }

/* --- tabs — clip-path indicator so the active label's colour is exact. --- */
.tabs__list {
  display: flex; gap: var(--sp-2); position: relative;
  border-block-end: var(--rule);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs__list::-webkit-scrollbar { display: none; }
.tabs__tab {
  padding-inline: var(--sp-4); padding-block: var(--sp-3);
  min-block-size: var(--tap);
  font-size: var(--fs-small); font-weight: var(--weight-semi);
  color: var(--fg-muted); white-space: nowrap;
  border-block-end: 2px solid transparent;
  margin-block-end: -1px;
  transition: color var(--dur-hover) var(--ease-out), border-color var(--dur-hover) var(--ease-out);
}
.tabs__tab[aria-selected="true"] { color: var(--fg); border-block-end-color: var(--ember); }
@media (hover: hover) and (pointer: fine) { .tabs__tab:hover { color: var(--fg); } }
.tabs__panel[hidden] { display: none; }

/* --- pagination — numbered and linkable, never infinite scroll. ---------- */
.pagination { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; justify-content: center; }
.pagination__link {
  display: inline-flex; align-items: center; justify-content: center;
  min-inline-size: var(--tap); min-block-size: var(--tap);
  padding-inline: var(--sp-3);
  border: 1px solid transparent;
  border-radius: var(--r-btn);
  font-family: var(--font-mono); font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  color: var(--fg-muted); text-decoration: none;
  transition: background-color var(--dur-hover) var(--ease-out), color var(--dur-hover) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .pagination__link:hover { background: var(--mist); color: var(--fg); } }
.pagination__link[aria-current="page"] { background: var(--ink); color: var(--fg-on-dark); border-color: var(--ink); }
.pagination__gap { color: var(--fg-muted); padding-inline: var(--sp-2); }

/* --- breadcrumb ---------------------------------------------------------- */
.breadcrumb { font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--fg-muted); }
.breadcrumb ol { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); list-style: none; padding: 0; }
.breadcrumb a { color: inherit; text-decoration: none; border-block-end: 1px solid transparent; }
@media (hover: hover) and (pointer: fine) { .breadcrumb a:hover { border-block-end-color: var(--ember); color: var(--fg); } }
.breadcrumb__sep { opacity: .5; }
.breadcrumb [aria-current="page"] { color: var(--fg); }
[lang="ar"] .breadcrumb { text-transform: none; letter-spacing: 0; }

/* --- tooltip ------------------------------------------------------------- */
.tooltip {
  position: absolute; z-index: var(--z-dropdown);
  max-inline-size: 32ch;
  padding: var(--sp-2) var(--sp-3);
  background: var(--ink); color: var(--fg-on-dark);
  border-radius: var(--r-btn);
  font-size: var(--fs-small); line-height: 1.4;
  box-shadow: var(--shadow-raised);
  opacity: 0; transform: scale(.97);
  transform-origin: var(--origin, center bottom);
  transition: opacity var(--dur-tooltip) var(--ease-out), transform var(--dur-tooltip) var(--ease-out);
  pointer-events: none;
}
.tooltip[data-open] { opacity: 1; transform: scale(1); }
/* While another tooltip is already open, the next one appears instantly —
   this makes a whole toolbar feel fast without defeating the initial delay. */
.tooltip[data-instant] { transition: none; }

/* --- popover / dropdown — origin-aware, anchored at the trigger. --------- */
.popover {
  position: absolute; z-index: var(--z-dropdown);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-raised);
  padding: var(--sp-3);
  opacity: 0; transform: scale(.97) translateY(-4px);
  transform-origin: var(--origin, top center);
  transition: opacity var(--dur-dropdown) var(--ease-out), transform var(--dur-dropdown) var(--ease-out);
  pointer-events: none;
}
.popover[data-open] { opacity: 1; transform: scale(1) translateY(0); pointer-events: auto; }
.popover[hidden] { display: none; }

/* --- modal — transform-origin CENTER: modals are the exception to the
       origin-aware rule because they are not anchored to a trigger. ------- */
.modal { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; place-items: center;
  padding: var(--sp-5); }
.modal[hidden] { display: none; }
.modal__backdrop {
  position: absolute; inset: 0; background: rgba(20,17,15,.55);
  opacity: 0; transition: opacity var(--dur-dropdown) var(--ease-out);
}
.modal__panel {
  position: relative;
  inline-size: min(560px, 100%);
  max-block-size: min(80vh, 720px);
  overflow-y: auto;
  background: var(--surface);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-overlay);
  padding: var(--sp-6);
  /* Never from scale(0) — nothing in the real world appears from nothing. */
  opacity: 0; transform: scale(.96);
  transform-origin: center;
  transition: opacity 220ms var(--ease-out), transform 220ms var(--ease-out);
}
.modal[data-open] .modal__backdrop { opacity: 1; }
.modal[data-open] .modal__panel { opacity: 1; transform: scale(1); }

/* --- toast — transition, not keyframe, so rapid stacking retargets. ------ */
.toast-region {
  position: fixed; z-index: var(--z-toast);
  inset-block-end: var(--sp-5); inset-inline-end: var(--sp-5);
  display: grid; gap: var(--sp-3); inline-size: min(380px, calc(100vw - var(--sp-8)));
}
.toast {
  display: grid; grid-template-columns: auto minmax(0,1fr) auto; gap: var(--sp-3);
  padding: var(--sp-4);
  background: var(--ink); color: var(--fg-on-dark);
  border-radius: var(--r-card); box-shadow: var(--shadow-overlay);
  font-size: var(--fs-small);
  transform: translateY(100%); opacity: 0;
  transition: transform 400ms var(--ease-out), opacity 200ms var(--ease-out);
}
.toast[data-open] { transform: translateY(0); opacity: 1; }

/* --- skeleton — the shape of the content, not a centred spinner. --------- */
.skeleton {
  background: linear-gradient(90deg, var(--mist) 0%, color-mix(in oklab, var(--mist) 60%, var(--surface)) 50%, var(--mist) 100%);
  background-size: 200% 100%;
  border-radius: var(--r-input);
  animation: shimmer 1400ms linear infinite;
}
@keyframes shimmer { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }
.skeleton--text { block-size: 1em; margin-block: .31em; }
.skeleton--title { block-size: 1.4em; inline-size: 60%; }
.skeleton--media { aspect-ratio: 16 / 10; border-radius: var(--r-card); }

/* --- progress bar (reading progress, upload) — transform only, never width */
.progress { block-size: 2px; background: transparent; overflow: hidden; }
.progress__fill {
  block-size: 100%; background: var(--ember);
  transform-origin: left center;
  transform: scaleX(var(--progress, 0));
  will-change: transform;
}
[dir="rtl"] .progress__fill { transform-origin: right center; }

/* --- empty / error state — name what would be here, offer the action. --- */
.state {
  display: grid; gap: var(--sp-4); justify-items: start;
  padding: var(--sp-8) var(--sp-5);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-card);
  background: var(--surface-sunk);
  max-inline-size: 60ch;
}
.state--center { justify-items: center; text-align: center; margin-inline: auto; }
.state__title { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-display); }
.state__body { color: var(--fg-muted); font-size: var(--fs-small); }
.state--error { border-style: solid; border-color: color-mix(in oklab, var(--critical) 40%, transparent); }

/* --- table --------------------------------------------------------------- */
.table-wrap { overflow-x: auto; }
.table { font-size: var(--fs-small); border-radius: var(--r-flat); }
.table th {
  font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase;
  font-weight: var(--weight-medium); color: var(--fg-muted);
  padding: var(--sp-3) var(--sp-4);
  border-block-end: var(--rule-strong);
  white-space: nowrap;
  background: var(--bg);
}
.table td { padding: var(--sp-4); border-block-end: var(--rule); vertical-align: top; }
.table tbody tr { transition: background-color var(--dur-hover) var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .table tbody tr:hover { background: var(--mist); } }
.table__num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.table th[aria-sort] { cursor: pointer; }
.table th[aria-sort="ascending"], .table th[aria-sort="descending"] { color: var(--fg); }
[lang="ar"] .table th { text-transform: none; letter-spacing: 0; }

/* --- pull-quote — breaks the measure, as it should. --------------------- */
.pull-quote {
  margin-block: var(--sp-8);
  padding-inline-start: var(--sp-6);
  border-inline-start: 2px solid var(--ember);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: var(--weight-semi);
  line-height: 1.34;
  letter-spacing: var(--tracking-display);
  max-inline-size: 44ch;
}
.pull-quote cite { display: block; margin-block-start: var(--sp-4); font-style: normal;
  font-family: var(--font-mono); font-size: var(--fs-label); letter-spacing: var(--tracking-label);
  text-transform: uppercase; color: var(--fg-muted); }

/* --- figure with caption ------------------------------------------------- */
.figure { margin: 0; }
.figure img { border-radius: var(--r-card); inline-size: 100%; }
.figure figcaption {
  margin-block-start: var(--sp-3);
  font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase;
  color: var(--fg-muted); max-inline-size: 60ch;
}

/* --- Placeholder token for a figure that awaits real client input.
       Deliberately visible. Never a stock photo stand-in. ----------------- */
.needs-input {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding-inline: var(--sp-3); padding-block: 3px;
  border: 1px dashed var(--warning);
  border-radius: var(--r-input);
  font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase;
  color: var(--warning); background: transparent;
}
.needs-input--block {
  display: grid; gap: var(--sp-3); justify-items: start;
  padding: var(--sp-5); text-transform: none; letter-spacing: 0;
  font-family: var(--font-body); font-size: var(--fs-small);
  /* The marker is the token; the explanation is body copy. Warning colour is
     never applied to running text — it is a status, not a voice. */
  color: var(--fg);
  max-inline-size: 62ch;
}
.needs-input--block .needs-input__tag { color: var(--warning); }
.needs-input--block .needs-input__tag {
  font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   contact-point — the phone number and the email address, in the state they
   are actually in.

   The 2026 company profile and the live site publish different values for
   both. While that is unresolved, every call site renders both candidates with
   the source each came from, and NEITHER is a link — a tappable wrong number
   silently routes real enquiries into a dead inbox, which is worse than no
   affordance at all. Marked with the same dashed --warning token as
   .needs-input, because it is the same class of problem: a fact the build
   refuses to guess.
   ----------------------------------------------------------------------- */
.contact-point { display: inline-flex; align-items: center; gap: var(--sp-2); }
.contact-point svg { inline-size: 18px; block-size: 18px; flex: none; }

.contact-point.is-unconfirmed {
  display: grid; gap: var(--sp-1); justify-items: start;
  padding: var(--sp-2) var(--sp-3);
  border: 1px dashed var(--warning); border-radius: var(--r-input);
}
.contact-point__tag {
  font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase;
  color: var(--warning);
}
.contact-point__candidate {
  display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap;
  font-size: var(--fs-small);
}
.contact-point__source {
  font-family: var(--font-mono); font-size: var(--fs-label);
  letter-spacing: var(--tracking-label); text-transform: uppercase;
  color: var(--fg-muted);
}

/* On the ink grounds — footer, drawer foot, CTA band — the muted source label
   needs the dark-ground token or it drops under 3:1. */
.site-footer .contact-point__source,
.cta-band .contact-point__source { color: var(--fg-on-dark-muted); }
.site-footer .contact-point__candidate,
.cta-band .contact-point__candidate { color: var(--fg-on-dark); }

/* The header chip states the problem in one line and routes to the page where
   both candidates are listed. */
.site-header__phone.is-unconfirmed {
  border: 1px dashed var(--warning); border-radius: var(--r-input);
  padding-inline: var(--sp-2); color: var(--warning); gap: 2px;
  font-family: var(--font-mono); font-size: var(--fs-label);
}
.site-header__phone.is-unconfirmed svg { color: var(--warning); }
.site-header__phone-flag { font-weight: var(--weight-bold); }

/* --------------------------------------------------------------------------
   pending-prose — an Arabic string awaiting professional translation.
   The English source is shown in an LTR isolate beneath the marker, so the
   page carries real substance rather than being empty, and no fabricated
   Arabic is ever presented as if it were finished.
   ----------------------------------------------------------------------- */
.pending-prose {
  display: grid; gap: var(--sp-3); justify-items: start;
  padding: var(--sp-5);
  border: 1px dashed var(--warning);
  border-radius: var(--r-card);
  background: var(--surface);
  max-inline-size: 68ch;
}
.pending-prose--block { max-inline-size: 74ch; }
.pending-prose__heading { font-family: var(--font-display); font-size: var(--fs-h3);
  font-weight: var(--weight-semi); letter-spacing: -0.02em; }
.pending-prose__source {
  font-family: "IBM Plex Sans", system-ui, sans-serif;
  font-size: var(--fs-small); line-height: 1.62; color: var(--fg-muted);
  text-align: start; unicode-bidi: isolate;
}
.pending-prose__source > * + * { margin-block-start: var(--sp-3); }
