/* ==========================================================================
   salam-portfolio — base
   Element defaults and document mechanics. Consumes tokens; declares none.
   No colour literal may appear in this file.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Reset, kept minimal
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

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

/* Honour the OS setting rather than animating regardless. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  margin: 0;
  background-color: var(--sn-canvas);
  color: var(--sn-ink);
  font-family: var(--sn-font-sans);
  font-size: var(--sn-fs-md);
  line-height: var(--sn-lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-synthesis-weight: none;
}

/* --------------------------------------------------------------------------
   Arabic script compensation
   Plex Sans Arabic runs optically smaller than Plex Sans at the same px and
   needs more leading. The scale factors are redeclared here rather than
   multiplied at :root, because a var() inside a custom property resolves on
   the element that DECLARES it — a multiplier referenced from :root would
   never see :lang(ar). See DESIGN-SYSTEM-SPEC section 2.4.
   -------------------------------------------------------------------------- */
:lang(ar) {
  --sn-script-scale:   1.06;
  --sn-script-leading: 0.12;
  --sn-track-scale:    0;

  --sn-fs-2xs: calc(var(--sn-fs-2xs--raw) * 1.06);
  --sn-fs-xs:  calc(var(--sn-fs-xs--raw)  * 1.06);
  --sn-fs-sm:  calc(var(--sn-fs-sm--raw)  * 1.06);
  --sn-fs-md:  calc(var(--sn-fs-md--raw)  * 1.06);
  --sn-fs-lg:  calc(var(--sn-fs-lg--raw)  * 1.06);
  --sn-fs-xl:  calc(var(--sn-fs-xl--raw)  * 1.06);
  --sn-fs-2xl: calc(var(--sn-fs-2xl--raw) * 1.06);
  --sn-fs-3xl: calc(var(--sn-fs-3xl--raw) * 1.06);
  --sn-fs-4xl: calc(var(--sn-fs-4xl--raw) * 1.06);
  --sn-fs-5xl: calc(var(--sn-fs-5xl--raw) * 1.06);
  --sn-fs-6xl: calc(var(--sn-fs-6xl--raw) * 1.06);

  --sn-lh-tight:   calc(var(--sn-lh-tight--raw)   + 0.12);
  --sn-lh-snug:    calc(var(--sn-lh-snug--raw)    + 0.12);
  --sn-lh-heading: calc(var(--sn-lh-heading--raw) + 0.12);
  --sn-lh-normal:  calc(var(--sn-lh-normal--raw)  + 0.12);
  --sn-lh-body:    calc(var(--sn-lh-body--raw)    + 0.12);
  --sn-lh-loose:   calc(var(--sn-lh-loose--raw)   + 0.12);

  /* Negative tracking damages Arabic joining. Zeroed structurally, so no
     component can reintroduce it by using the token. */
  --sn-track-tight: 0em;
  --sn-track-snug:  0em;
  --sn-track-wide:  0em;
}

/* Arabic never uses the two lightest weights: at small sizes the joins break. */
:lang(ar) { font-synthesis: none; }
:lang(ar) :is(h1, h2, h3, h4, h5, h6) { font-weight: var(--sn-wt-semibold); }

/* Latin numerals inside Arabic text keep LTR order without a wrapper element. */
:lang(ar) { font-variant-numeric: lining-nums; }

/* --------------------------------------------------------------------------
   Typography defaults
   -------------------------------------------------------------------------- */
:is(h1, h2, h3, h4, h5, h6) {
  margin-block: 0 var(--sn-space-sm);
  text-wrap: balance;
}

p, li, dd, dt, blockquote, figcaption { text-wrap: pretty; }

p { margin-block: 0 var(--sn-space-sm); }
p:last-child { margin-block-end: 0; }

/* --------------------------------------------------------------------------
   Links and focus
   A single focus ring is not enough: a brand-coloured ring vanishes against a
   brand-coloured fill. Two rings — ink against halo — stay visible on every
   surface the theme can produce, including inside .sn-invert.
   -------------------------------------------------------------------------- */
a { color: var(--sn-brand); text-underline-offset: 0.18em; }
a:hover { color: var(--sn-brand-hover); }

:focus-visible {
  outline: var(--sn-border-thick) solid var(--sn-focus);
  outline-offset: var(--sn-border-thick);
  box-shadow: 0 0 0 calc(var(--sn-border-thick) * 2) var(--sn-focus-halo);
  border-radius: var(--sn-radius-xs);
}

/* Remove the ring for pointer users only, never for keyboard users. */
:focus:not(:focus-visible) { outline: none; }

::selection {
  background-color: var(--sn-selection-bg);
  color: var(--sn-selection-ink);
}

/* Skip link — visible the moment it receives focus. */
.sn-skip-link {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  z-index: 999;
  padding: var(--sn-space-2xs) var(--sn-space-sm);
  background-color: var(--sn-brand);
  color: var(--sn-on-brand);
  text-decoration: none;
  transform: translateY(-120%);
}
.sn-skip-link:focus-visible { transform: translateY(0); }

/* --------------------------------------------------------------------------
   Media
   -------------------------------------------------------------------------- */
img, picture, video, canvas, svg { display: block; max-inline-size: 100%; height: auto; }
img { background-color: var(--sn-surface); }

/* --------------------------------------------------------------------------
   Forms — one boundary token, so every control reads as the same system
   -------------------------------------------------------------------------- */
input, textarea, select, button { font: inherit; color: inherit; }

:is(input, textarea, select):not([type="checkbox"], [type="radio"]) {
  inline-size: 100%;
  padding: var(--sn-space-2xs) var(--sn-space-xs);
  background-color: var(--sn-canvas);
  border: var(--sn-border-hair) solid var(--sn-line-input);
  border-radius: var(--sn-radius-sm);
}

/* --------------------------------------------------------------------------
   Tables — must scroll inside their own container, never the page
   -------------------------------------------------------------------------- */
table { inline-size: 100%; border-collapse: collapse; }
th, td {
  padding: var(--sn-space-2xs) var(--sn-space-xs);
  border-block-end: var(--sn-border-hair) solid var(--sn-line);
  text-align: start;
}
th { font-weight: var(--sn-wt-semibold); }
.wp-block-table { overflow-x: auto; }

/* --------------------------------------------------------------------------
   Layout mechanics
   Logical properties throughout, so RTL mirrors without a second stylesheet.
   -------------------------------------------------------------------------- */
.sn-prose { max-inline-size: var(--sn-w-prose); }
.sn-text  { max-inline-size: var(--sn-w-text); }

/* WordPress's constrained layout centres any child carrying a max-width:

     .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {
       margin-left: auto !important; margin-right: auto !important;
     }

   For a measure-limited paragraph that reads as an accidental indent — the text
   drifts away from the heading it belongs to.

   !important here is not laziness. WordPress ships that declaration with
   !important, so there is no lower-force way to opt a block out of it; matching
   it is the only mechanism available. Scoped to two opt-in classes so it can
   never leak into ordinary block layout.

   Logical properties are used so RTL mirrors, and they are !important too:
   a physical `margin-left: auto !important` otherwise beats a logical
   `margin-inline-start: 0` that is not. */
.is-layout-constrained > .sn-prose,
.is-layout-constrained > .sn-text,
.sn-prose,
.sn-text {
  margin-inline-start: 0 !important;
  margin-inline-end: auto !important;
}

hr, .wp-block-separator {
  border: 0;
  border-block-start: var(--sn-border-hair) solid var(--sn-line);
  margin-block: var(--sn-space-xl);
}

/* Never let the page itself scroll sideways. */
html, body { overflow-x: clip; }
