/* IBM Plex, self-hosted. SIL Open Font License 1.1.
   See tools/make_fonts.py for why these are not loaded from Google. */

@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/assets/fonts/IBMPlexSans-Regular.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500;
  font-display: swap; src: url("/assets/fonts/IBMPlexSans-Medium.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600;
  font-display: swap; src: url("/assets/fonts/IBMPlexSans-SemiBold.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans Condensed"; font-style: normal; font-weight: 600;
  font-display: swap; src: url("/assets/fonts/IBMPlexSansCondensed-SemiBold.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/assets/fonts/IBMPlexMono-Regular.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500;
  font-display: swap; src: url("/assets/fonts/IBMPlexMono-Medium.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans Arabic"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/assets/fonts/IBMPlexSansArabic-Regular.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans Arabic"; font-style: normal; font-weight: 500;
  font-display: swap; src: url("/assets/fonts/IBMPlexSansArabic-Medium.woff2") format("woff2"); }
@font-face { font-family: "IBM Plex Sans Arabic"; font-style: normal; font-weight: 600;
  font-display: swap; src: url("/assets/fonts/IBMPlexSansArabic-SemiBold.woff2") format("woff2"); }

/* JPA Consultancy
   Palette sampled from the logo master, not chosen:
   #0178B0 blue, #6D6E70 grey, #0A0A0A field, #F5F5F3 paper.
   Type: IBM Plex. Engineering-drawn, gridded, and the only family here with a
   genuine Arabic companion cut alongside the Latin, which is what makes the
   third locale possible rather than a fallback. */

:root {
  --ink: #0a0a0a;
  --ink-2: #141416;
  --ink-3: #1e1e21;
  --paper: #f5f5f3;
  --paper-2: #e6e6e1;
  --paper-3: #d3d3cc;
  --blue: #0178b0;
  --blue-lift: #3ba3d8;
  --grey: #6d6e70;
  --grey-lift: #a9abae;

  --sans: "IBM Plex Sans", system-ui, sans-serif;
  --cond: "IBM Plex Sans Condensed", "IBM Plex Sans", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;

  --step--1: clamp(0.79rem, 0.77rem + 0.1vw, 0.85rem);
  --step-0: clamp(0.98rem, 0.94rem + 0.2vw, 1.09rem);
  --step-1: clamp(1.18rem, 1.1rem + 0.4vw, 1.44rem);
  --step-2: clamp(1.45rem, 1.3rem + 0.75vw, 1.95rem);
  --step-3: clamp(1.85rem, 1.55rem + 1.5vw, 2.9rem);
  --step-4: clamp(2.3rem, 1.7rem + 3vw, 4.6rem);

  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --bay: clamp(4rem, 9vw, 7.5rem);
  --wrap: 1180px;
}

[lang="ar"] {
  --sans: "IBM Plex Sans Arabic", "IBM Plex Sans", system-ui, sans-serif;
  --cond: "IBM Plex Sans Arabic", "IBM Plex Sans Condensed", system-ui, sans-serif;
  /* There is no Arabic cut of Plex Mono. Keeping Mono first means Latin digits,
     dates and reference numbers still get the monospaced treatment, while the
     browser falls back per glyph to Plex Sans Arabic for the Arabic itself.
     Replacing the stack outright would lose the mono digits; omitting Arabic
     entirely leaves it on a system font with broken spacing. */
  --mono: "IBM Plex Mono", "IBM Plex Sans Arabic", ui-monospace, monospace;
}
[lang="ar"] .doc__year,
[lang="ar"] .viewer__close,
[lang="ar"] .langs a { letter-spacing: 0; }

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@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;
  }
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--grey-lift);
  font-family: var(--sans);
  font-size: var(--step-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3 { color: var(--paper); line-height: 1.08; margin: 0; text-wrap: balance; }
p { margin: 0; text-wrap: pretty; }
img { max-width: 100%; display: block; }
a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--blue-lift);
  outline-offset: 3px;
  border-radius: 2px;
}

.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }

.skip {
  position: absolute;
  inset-block-start: -100px;
  inset-inline-start: var(--gutter);
  z-index: 100;
  background: var(--blue);
  color: #fff;
  padding: 0.7rem 1.1rem;
  font-size: var(--step--1);
  text-decoration: none;
}
/* Only after a real Tab press. :focus was too eager, and :focus-visible turned
   out to be as well: Chrome restores focus to the first focusable element after
   a back-navigation and treats that as keyboard-driven, so the link flashed up
   for people who had only pressed Back. app.js sets data-tabbing on <html> the
   first time Tab is pressed, which is the only signal that actually means
   somebody is navigating by keyboard. */
[data-tabbing] .skip:focus { inset-block-start: 0.6rem; }

/* ---------- eyebrow / shared rhythm ---------- */

.eyebrow {
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blue-lift);
  margin: 0 0 1.1rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.eyebrow::after {
  content: "";
  flex: 1;
  height: 1px;
  background: currentColor;
  opacity: 0.3;
}
[lang="ar"] .eyebrow { letter-spacing: 0; }

.bay { padding-block: var(--bay); }

/* ---------- masthead ---------- */

.masthead {
  position: sticky;
  inset-block-start: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--ink) 88%, transparent);
  backdrop-filter: blur(10px);
  border-block-end: 1px solid var(--ink-3);
}
/* Three tracks: logo at the start, nav centred in the page regardless of how
   wide the logo or the language switch are, languages at the end. A flex row
   would centre the nav between its neighbours instead, which drifts. */
.masthead__in {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1.25rem;
  min-height: 62px;
}
.masthead__logo { display: flex; align-items: center; gap: 0.6rem; text-decoration: none; }
.masthead__logo img { width: 30px; height: 30px; }
.masthead__logo span {
  font-family: var(--cond);
  font-weight: 600;
  letter-spacing: 0.09em;
  font-size: var(--step--1);
  color: var(--paper);
  text-transform: uppercase;
}
.masthead nav { display: flex; justify-content: center; gap: clamp(0.9rem, 2vw, 1.8rem); }
.masthead nav a {
  font-size: var(--step--1);
  text-decoration: none;
  color: var(--grey-lift);
  padding-block: 0.4rem;
  transition: color 0.2s;
  white-space: nowrap;
}
.masthead nav a:hover { color: var(--paper); }
@media (max-width: 860px) {
  .masthead nav { display: none; }
  /* with the nav gone the middle track collapses; keep two ends */
  .masthead__in { grid-template-columns: 1fr auto; }
  .langs { grid-column: 2; }
}

.langs { display: flex; gap: 0.35rem; justify-self: end; grid-column: 3; }
.langs a {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-decoration: none;
  color: var(--grey);
  border: 1px solid var(--ink-3);
  padding: 0.25rem 0.5rem;
  text-transform: uppercase;
  transition: color 0.2s, border-color 0.2s;
}
.langs a:hover { color: var(--paper); border-color: var(--grey); }
.langs a[aria-current="true"] { color: var(--ink); background: var(--blue-lift); border-color: var(--blue-lift); }

/* ---------- hero ---------- */

.hero { position: relative; padding-block: clamp(2.5rem, 6vw, 5rem) 0; overflow: hidden; }
.hero::before {
  content: "";
  position: absolute;
  inset-block-start: -30%;
  inset-inline-start: 50%;
  width: 90vw;
  height: 90vw;
  max-width: 900px;
  max-height: 900px;
  background: radial-gradient(circle, rgba(1, 120, 176, 0.16), transparent 62%);
  transform: translateX(-50%);
  pointer-events: none;
}
.hero__grid {
  position: relative;
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
}
/* Sized as a heading, but the real H1 is the person's name in the portrait
   caption. Search engines read the H1 as the page's subject, and "Let's Talk
   Solution" is a slogan, not a subject. Nothing moves visually. */
.hero__motto {
  font-family: var(--cond);
  font-size: var(--step-4);
  font-weight: 600;
  letter-spacing: -0.015em;
  margin-block: 0.4rem 0;
}
[lang="ar"] /* Sized as a heading, but the real H1 is the person's name in the portrait
   caption. Search engines read the H1 as the page's subject, and "Let's Talk
   Solution" is a slogan, not a subject. Nothing moves visually. */
.hero__motto { letter-spacing: 0; }

/* name and role now caption the portrait rather than head the page */
.hero__portrait { margin: 0; }
.hero__portrait figcaption {
  margin-block-start: -0.35rem;
  padding-inline-start: 0.15rem;
}
.hero__portrait figcaption h1 {
  display: block;
  margin: 0;
  font-family: var(--cond);
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--paper);
  line-height: 1.15;
}
.hero__portrait figcaption span {
  display: block;
  font-family: var(--mono);
  font-size: var(--step--1);
  color: var(--blue-lift);
  margin-block-start: 0.3rem;
}
.hero__thesis {
  font-size: var(--step-1);
  line-height: 1.45;
  color: var(--paper);
  max-width: 34ch;
  margin-block-start: clamp(1.5rem, 3vw, 2.2rem);
  border-inline-start: 2px solid var(--blue);
  padding-inline-start: 1.15rem;
}
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-block-start: 2rem; }
.hero__portrait {
  position: relative;
  max-width: 420px;
  margin-inline-start: auto;
}
.hero__portrait img {
  width: 100%;
  height: auto;
  filter: grayscale(0.22) contrast(1.05);
  mask-image: linear-gradient(to bottom, #000 74%, transparent 99%);
  -webkit-mask-image: linear-gradient(to bottom, #000 74%, transparent 99%);
}
@media (max-width: 780px) {
  /* Name and thesis come first; the portrait must not eat the first screen.
     Everything below the thesis is centred on a narrow screen, where a single
     column reads better balanced than left-aligned. */
  .hero__grid { grid-template-columns: 1fr; align-items: start; }
  .hero__thesis { max-width: none; }
  .hero__actions { justify-content: center; }
  .hero__portrait { max-width: 240px; margin-inline: auto; }
  .hero__portrait figcaption { text-align: center; padding-inline-start: 0; }
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.85rem 1.5rem;
  border: 1px solid var(--blue);
  background: var(--blue);
  color: #fff;
  transition: background 0.2s, color 0.2s, border-color 0.2s;
}
.btn:hover { background: transparent; color: var(--blue-lift); }
.btn--ghost { background: transparent; border-color: var(--ink-3); color: var(--grey-lift); }
.btn--ghost:hover { border-color: var(--grey); color: var(--paper); background: transparent; }
[lang="ar"] .btn { letter-spacing: 0; }

/* ---------- stats ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-block-start: 1px solid var(--ink-3);
  margin-block-start: clamp(2rem, 5vw, 3.5rem);
}
.stats div { padding-block: 1.6rem; padding-inline-end: 1rem; }
.stats div + div { border-inline-start: 1px solid var(--ink-3); padding-inline-start: 1rem; }
.stats b {
  display: block;
  font-family: var(--cond);
  font-size: var(--step-2);
  font-weight: 600;
  color: var(--paper);
  line-height: 1;
}
.stats span {
  display: block;
  font-size: var(--step--1);
  color: var(--grey);
  margin-block-start: 0.4rem;
}
@media (max-width: 780px) {
  .stats { text-align: center; }
  .stats div { padding-inline: 0.5rem; }
}
@media (max-width: 620px) {
  .stats { grid-template-columns: repeat(2, 1fr); }
  .stats div:nth-child(3) { border-inline-start: 0; padding-inline-start: 0.5rem; }
  .stats div:nth-child(n + 3) { border-block-start: 1px solid var(--ink-3); }
}

/* ---------- the record: the page turns to paper ---------- */

.record {
  background: var(--paper);
  color: #3a3a38;
  position: relative;
}
.record h2, .record h3 { color: var(--ink); }
.record .eyebrow { color: var(--blue); }
.record__head { max-width: 62ch; }
.record__title { font-family: var(--cond); font-size: var(--step-3); font-weight: 600; }
.record__lede { margin-block-start: 1.1rem; font-size: var(--step-1); line-height: 1.5; color: #4a4a47; }
.record__note {
  font-family: var(--mono);
  font-size: var(--step--1);
  color: var(--grey);
  margin-block-start: 1.2rem;
}

.spine { margin-block-start: clamp(2.5rem, 5vw, 4rem); border-block-start: 1px solid var(--paper-3); }

.doc {
  display: grid;
  grid-template-columns: 5.5rem 1fr 10.5rem;
  gap: clamp(1rem, 3vw, 2.5rem);
  align-items: start;
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  border-block-end: 1px solid var(--paper-3);
  background: none;
  border-inline: 0;
  border-block-start: 0;
  inline-size: 100%;
  text-align: start;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: background 0.2s;
}
.doc:hover { background: var(--paper-2); }
.doc__year {
  font-family: var(--mono);
  font-size: var(--step-1);
  font-weight: 500;
  color: var(--blue);
  letter-spacing: 0.01em;
}
.doc__num {
  display: block;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--grey);
  letter-spacing: 0.14em;
  margin-block-end: 0.3rem;
}
.doc__issuer {
  display: block;
  font-family: var(--cond);
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--ink);
  line-height: 1.2;
  /* issuer and place are Latin proper nouns and a directional arrow; isolate
     them so they read correctly inside the Arabic RTL column */
  unicode-bidi: isolate;
}
.doc__place {
  display: block;
  font-family: var(--mono);
  font-size: var(--step--1);
  color: var(--grey);
  margin-block-start: 0.35rem;
  unicode-bidi: isolate;
}
.doc__desc {
  display: block;
  margin-block-start: 0.75rem;
  max-width: 58ch;
  font-size: var(--step-0);
  line-height: 1.55;
}
.doc__thumb {
  border: 1px solid var(--paper-3);
  background: #fff;
  padding: 4px;
  transition: transform 0.25s, box-shadow 0.25s;
}
.doc:hover .doc__thumb { transform: translateY(-2px); box-shadow: 0 8px 22px rgba(0, 0, 0, 0.13); }
.doc__thumb img { width: 100%; height: auto; }
@media (max-width: 720px) {
  .doc { grid-template-columns: 4.25rem 1fr; }
  .doc__thumb { display: none; }
}

/* document viewer */

dialog.viewer {
  border: 0;
  padding: 0;
  max-width: min(920px, 94vw);
  max-height: 92vh;
  width: 100%;
  background: var(--paper);
  color: #3a3a38;
  overflow: auto;
}
dialog.viewer::backdrop { background: rgba(4, 4, 5, 0.86); }
.viewer__bar {
  position: sticky;
  inset-block-start: 0;
  display: flex;
  gap: 1rem;
  align-items: baseline;
  justify-content: space-between;
  padding: 1rem clamp(1rem, 3vw, 1.75rem);
  background: var(--paper);
  border-block-end: 1px solid var(--paper-3);
}
.viewer__meta { font-family: var(--mono); font-size: var(--step--1); color: var(--grey); }
.viewer__meta b { color: var(--ink); font-weight: 500; }
.viewer__close {
  font-family: var(--mono);
  font-size: var(--step--1);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  background: none;
  border: 1px solid var(--paper-3);
  padding: 0.45rem 0.9rem;
  cursor: pointer;
  color: var(--ink);
  white-space: nowrap;
}
.viewer__close:hover { background: var(--paper-2); }
.viewer__body { padding: clamp(1rem, 3vw, 1.75rem); }
.viewer__body p { max-width: 62ch; margin-block-end: 1.1rem; }
.viewer__body img { width: 100%; border: 1px solid var(--paper-3); background: #fff; }

/* ---------- work ---------- */

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); gap: 1px; background: var(--ink-3); border: 1px solid var(--ink-3); margin-block-start: clamp(2rem, 4vw, 3rem); }
.card { background: var(--ink); padding: clamp(1.4rem, 2.5vw, 2rem); }
.card h3 { font-family: var(--cond); font-size: var(--step-1); font-weight: 600; margin-block-end: 0.75rem; }
.card p { font-size: var(--step-0); }

/* ---------- method ---------- */

.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: clamp(1.25rem, 2.5vw, 2rem); margin-block-start: clamp(2rem, 4vw, 3rem); counter-reset: step; }
.step { border-block-start: 2px solid var(--ink-3); padding-block-start: 1rem; counter-increment: step; }
.step:first-child { border-block-start-color: var(--blue); }
.step h3 { font-family: var(--cond); font-size: var(--step-1); font-weight: 600; margin-block-end: 0.5rem; }
.step h3::before {
  content: counter(step, decimal-leading-zero);
  display: block;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--blue-lift);
  letter-spacing: 0.14em;
  margin-block-end: 0.5rem;
  font-weight: 400;
}
.step p { font-size: var(--step--1); line-height: 1.55; }

/* ---------- clients ---------- */

.roster { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: clamp(1.5rem, 3vw, 2.5rem); margin-block-start: clamp(2rem, 4vw, 3rem); }
.roster h3 {
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--blue-lift);
  margin-block-end: 1rem;
}
[lang="ar"] .roster h3 { letter-spacing: 0; }
.roster ul { list-style: none; margin: 0; padding: 0; }
.roster li {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--cond);
  font-size: var(--step-0);
  color: var(--paper);
  padding-block: 0.45rem;
  border-block-end: 1px solid var(--ink-3);
}
/* Each mark sits on an identical light tile. The registered logos are
   inconsistent – some on white, some on black, some four times wider than
   tall – so a shared tile is the only way to line them up without altering
   any of them. */
.roster .chip {
  flex: none;
  inline-size: 44px;
  block-size: 30px;
  border-radius: 2px;
  object-fit: contain;
}

/* ---------- contact ---------- */

.contact { background: var(--ink-2); border-block-start: 1px solid var(--ink-3); }
.contact__grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
@media (max-width: 720px) { .contact__grid { grid-template-columns: 1fr; } }
.contact__title { font-family: var(--cond); font-size: var(--step-3); font-weight: 600; }
.contact__lede { margin-block-start: 1rem; font-size: var(--step-1); color: var(--paper); max-width: 34ch; }
.dl { display: grid; grid-template-columns: auto 1fr; gap: 0.55rem 1.5rem; margin: 0; font-size: var(--step-0); }
.dl dt {
  font-family: var(--mono);
  font-size: var(--step--1);
  color: var(--grey);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding-block-start: 0.15rem;
}
[lang="ar"] .dl dt { letter-spacing: 0; }
.dl dd { margin: 0; color: var(--paper); }
.dl a { text-decoration: none; border-block-end: 1px solid var(--grey); padding-block-end: 1px; }
.dl a:hover { border-block-end-color: var(--blue-lift); color: var(--blue-lift); }

/* ---------- footer ---------- */

.foot {
  border-block-start: 1px solid var(--ink-3);
  padding-block: 2rem;
  font-family: var(--mono);
  font-size: var(--step--1);
  color: var(--grey);
}
.foot__in { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between; align-items: center; }

/* ---------- 404 ---------- */

.oops { min-height: 68vh; display: grid; place-content: center; text-align: center; gap: 1.2rem; }
.oops h1 { font-family: var(--cond); font-size: var(--step-3); font-weight: 600; }
.oops .btn { justify-self: center; }

/* ---------- hero lockup ---------- */

.hero__lockup {
  width: clamp(200px, 22vw, 260px);
  height: auto;
  margin-block-end: clamp(1rem, 2vw, 1.5rem);
}

/* ---------- floating actions ---------- */

.floaters {
  position: fixed;
  inset-block-end: clamp(1rem, 3vw, 1.75rem);
  inset-inline-end: clamp(1rem, 3vw, 1.75rem);
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.floater {
  --size: 52px;
  inline-size: var(--size);
  block-size: var(--size);
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--ink-3);
  background: var(--ink-2);
  color: var(--blue-lift);
  cursor: pointer;
  padding: 0;
  text-decoration: none;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45);
  transition: background 0.2s, color 0.2s, border-color 0.2s, transform 0.2s;
}
.floater svg { inline-size: 24px; block-size: 24px; }
.floater:hover {
  background: var(--blue);
  color: #fff;
  border-color: var(--blue);
  transform: translateY(-2px);
}

/* the back-to-top control is not useful until there is something to go back
   to, so it is hidden and removed from the tab order until scrolled */
.floater--top {
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
}
.floaters[data-scrolled="true"] .floater--top {
  opacity: 1;
  visibility: visible;
  transform: none;
}

/* The rail is fixed to the bottom of the viewport, so at the end of the page it
   sits on top of the footer and made the privacy link unclickable. Rather than
   reserve space in the footer, stand the buttons down once the footer is in
   view: by then the contact details are on screen anyway. */
.floaters[data-atfoot="true"] {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(6px);
}
.floaters {
  transition: opacity 0.25s, visibility 0.25s, transform 0.25s;
}

/* label appears on hover on pointer devices only; the aria-label carries it
   everywhere else */
@media (hover: hover) and (min-width: 861px) {
  .floater::after {
    content: attr(data-tip);
    position: absolute;
    inset-inline-end: calc(100% + 0.6rem);
    white-space: nowrap;
    font-family: var(--mono);
    font-size: 0.72rem;
    letter-spacing: 0.06em;
    background: var(--ink-2);
    border: 1px solid var(--ink-3);
    color: var(--paper);
    padding: 0.4rem 0.7rem;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s;
  }
  .floater { position: relative; }
  .floater:hover::after, .floater:focus-visible::after { opacity: 1; }
}
[lang="ar"] .floater::after { letter-spacing: 0; }

@media (max-width: 480px) {
  .floater { --size: 46px; }
  .floater svg { inline-size: 21px; block-size: 21px; }
}

/* ---------- footer, credit ---------- */

.foot__in { align-items: center; }

.foot__places, .foot__copy { flex: 1 1 0; min-inline-size: 0; }
.foot__copy { text-align: end; }
.foot__by {
  flex: 0 0 auto;
  text-align: center;
  white-space: nowrap;
}
.foot__by a {
  color: var(--grey-lift);
  text-decoration: none;
  /* underline sits on the word only: running it under the badge made the
     monogram look like part of a form field */
  border: 0;
}
.foot__by a:hover { color: var(--blue-lift); }
/* no rule at rest and none on hover: the colour change and the mark lifting
   are enough, and an underline under a lockup that includes an icon reads as a
   mistake */
.pf-word { border: 0; text-decoration: none; }
@media (max-width: 760px) {
  .foot__in { flex-direction: column; gap: 0.7rem; text-align: center; }
  .foot__places, .foot__copy { flex: none; text-align: center; }
}

/* ---------- the car pulls away on hover ---------- */

.floater--top svg { inline-size: 21px; block-size: 30px; }
.floater--top:hover svg { animation: drive 0.5s ease; }
@keyframes drive {
  0% { transform: translateY(0); }
  45% { transform: translateY(-4px); }
  100% { transform: translateY(0); }
}
@media (max-width: 480px) {
  .floater--top svg { inline-size: 18px; block-size: 26px; }
}


/* ---------- gallery ---------- */

.gallery__group { margin-block-start: clamp(2rem, 4vw, 2.75rem); }
.gallery__heading {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--blue-lift);
  margin-block-end: 1rem;
  padding-block-end: 0.6rem;
  border-block-end: 1px solid var(--ink-3);
}
[lang="ar"] .gallery__heading { letter-spacing: 0; }
.gallery__link {
  margin-inline-start: auto;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--grey-lift);
  text-decoration: none;
  white-space: nowrap;
}
.gallery__link:hover { color: var(--paper); }
.gallery__link::after { content: " \2197"; }
[dir="rtl"] .gallery__link::after { content: " \2196"; }

/* Uniform tiles on a grid. CSS-columns masonry left the bottom of each column
   at a different height, which read as a large empty block. */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1rem;
}
@media (max-width: 620px) {
  .gallery { grid-template-columns: repeat(auto-fill, minmax(145px, 1fr)); gap: 0.7rem; }
}

.shot {
  display: flex;
  flex-direction: column;
  inline-size: 100%;
  margin: 0;
  padding: 0;
  border: 1px solid var(--ink-3);
  background: var(--ink-2);
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
  overflow: hidden;
  transition: border-color 0.2s, transform 0.2s;
}
.shot:hover { border-color: var(--grey); transform: translateY(-2px); }
.shot__frame { display: block; background: #fff; aspect-ratio: 3 / 2; overflow: hidden; }
.shot__frame img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center;
  transition: transform 0.3s;
}
/* newspaper scans: keep the masthead and headline, not the middle of a column */
.shot__frame--top img { object-position: top center; }
.shot:hover .shot__frame img { transform: scale(1.03); }
.shot__cap { display: block; padding: 0.65rem 0.8rem 0.75rem; flex: 1; }
.shot__issuer {
  display: block;
  font-family: var(--cond);
  font-size: var(--step-0);
  font-weight: 600;
  color: var(--paper);
  line-height: 1.2;
  unicode-bidi: isolate;
}
.shot__place {
  display: block;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--grey);
  margin-block-start: 0.3rem;
}
/* carried in the markup for the viewer to read, never shown in the grid */
.shot__desc, .shot__year { display: none; }

/* ---------- contact place under each number ---------- */

.dl__where {
  display: block;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--grey);
  margin-block-start: 0.2rem;
}
[lang="ar"] .dl__where { letter-spacing: 0; }

/* ---------- video tiles ---------- */

.shot__frame { position: relative; }
.shot__play {
  position: absolute;
  inset-block-end: 0.5rem;
  inset-inline-start: 0.5rem;
  inline-size: 34px;
  block-size: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 72%, transparent);
  color: var(--paper);
  transition: background 0.2s, color 0.2s;
}
.shot__play svg { inline-size: 17px; block-size: 17px; }
.shot--video:hover .shot__play { background: var(--blue); color: #fff; }

.viewer__video {
  aspect-ratio: 16 / 9;
  background: var(--ink);
  border: 1px solid var(--paper-3);
}
.viewer__video iframe { inline-size: 100%; block-size: 100%; border: 0; display: block; }
.viewer__watch { margin-block-start: 1rem; }
.viewer__watch a {
  font-family: var(--mono);
  font-size: var(--step--1);
  color: var(--blue);
  text-decoration: none;
  border-block-end: 1px solid currentColor;
}
.viewer__watch a[hidden] { display: none; }

/* ---------- contact form ---------- */

.cform { margin-block-start: 2rem; display: grid; gap: 0.9rem; max-width: 38rem; }
.cform__row { display: grid; gap: 0.35rem; }
.cform__row > span {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--grey);
}
[lang="ar"] .cform__row > span { letter-spacing: 0; }
.cform input, .cform textarea {
  font: inherit;
  font-size: var(--step-0);
  color: var(--paper);
  background: var(--ink);
  border: 1px solid var(--ink-3);
  padding: 0.65rem 0.8rem;
  inline-size: 100%;
  border-radius: 0;
}
.cform textarea { resize: vertical; min-block-size: 6rem; }
.cform input:focus, .cform textarea:focus {
  outline: none;
  border-color: var(--blue);
}
/* honeypot: off-screen rather than display:none, which some bots detect */
.cform__pot {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}
.cform button { justify-self: start; margin-block-start: 0.3rem; }
.cform button[disabled] { opacity: 0.55; cursor: default; }
.cform__note { font-size: var(--step--1); color: var(--grey); }
.cform__status { font-size: var(--step-0); }
.cform__status.is-ok { color: var(--blue-lift); }
.cform__status.is-bad { color: #e2725b; }
.cform__status:empty { display: none; }

/* ---------- contact icon row ---------- */

.contacts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.1rem, 3vw, 2rem);
}
.contacts li { display: grid; justify-items: center; gap: 0.45rem; }
@media (max-width: 720px) {
  /* the icons sit under the form here, so centre them with it */
  .contacts { justify-content: center; }
  .contact__grid > .dl, .contacts { inline-size: 100%; }
}
.cbtn {
  display: grid;
  place-items: center;
  inline-size: 52px;
  block-size: 52px;
  border: 1px solid var(--ink-3);
  border-radius: 50%;
  color: var(--grey-lift);
  background: var(--ink);
  transition: color 0.2s, border-color 0.2s, transform 0.2s;
}
.cbtn:hover { color: var(--blue-lift); border-color: var(--blue); transform: translateY(-2px); }
.cbtn svg { inline-size: 24px; block-size: 24px; }
.cbtn__flag {
  display: block;
  inline-size: 28px;
  block-size: 19px;
  border: 1px solid var(--ink-3);
  border-radius: 1px;
  overflow: hidden;
}
.cbtn__flag svg { inline-size: 100%; block-size: 100%; }
.cbtn__cap {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--grey);
}
[lang="ar"] .cbtn__cap { letter-spacing: 0; }

/* ---------- contact icon tooltip ---------- */

.cbtn { position: relative; }
.cbtn[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 0.5rem);
  /* physical left/transform on purpose: this centres the bubble over the icon
     identically in both directions, where the logical properties would not */
  left: 50%;
  transform: translateX(-50%);
  /* the number is a Latin-script run and must keep its own order inside an
     Arabic page */
  direction: ltr;
  unicode-bidi: isolate;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  background: var(--ink-2);
  border: 1px solid var(--ink-3);
  color: var(--paper);
  padding: 0.35rem 0.6rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s;
  z-index: 5;
}
.cbtn[data-tip]:hover::after,
.cbtn[data-tip]:focus-visible::after,
.cbtn[data-tip].is-tip::after { opacity: 1; }

/* ---------- prose pages ---------- */

.prose { max-width: 62ch; }
.prose__updated {
  font-family: var(--mono);
  font-size: var(--step--1);
  color: var(--grey);
  margin-block-start: 0.9rem;
}
.prose__intro {
  font-size: var(--step-1);
  color: var(--paper);
  margin-block-start: 1.4rem;
  border-inline-start: 2px solid var(--blue);
  padding-inline-start: 1.15rem;
}
.prose__block { margin-block-start: clamp(2rem, 4vw, 2.6rem); }
.prose__block h2 {
  font-family: var(--cond);
  font-size: var(--step-1);
  font-weight: 600;
  margin-block-end: 0.8rem;
}
.prose__block p + p { margin-block-start: 0.8rem; }
/* the browser's default underline was the only thing distinguishing this from
   the copyright text next to it; match the other links instead */
.foot__legal {
  margin-inline-start: 0.6rem;
  color: var(--grey-lift);
  text-decoration: none;
  transition: color 0.2s;
}
.foot__legal:hover { color: var(--blue-lift); }

/* ---------- PFcyber mark ---------- */

/* Their own icon, cut out of the white JPEG it arrived in and served from this
   site. Not hotlinked from pfcyber.com: that would add a third-party request to
   every page, which the privacy notice says does not happen. */
.pf {
  /* the global img rule sets display:block, which put a line break either side
     of the mark and broke the credit onto three lines */
  display: inline-block;
  inline-size: 1.5em;
  block-size: 1.5em;
  margin-inline-end: 0.4em;
  vertical-align: -0.36em;
  border-radius: 4px;
}
/* The mark stays put and unaltered on hover. It is somebody else's logo: it
   should not move, brighten or otherwise be restyled by this site. The word
   next to it carries the hover state. */

/* Turnstile in interaction-only mode renders nothing unless a visitor actually
   has to prove something, so it must not reserve space in the form. When it
   does appear it needs room and a little separation. */
.cf-turnstile:empty { display: none; }
.cf-turnstile { margin-block: 0.2rem; }

/* probe \xe2\x80\x94 */
