@font-face {
  /* Non-Apple fallback for the Arabic name. Cairo (SIL OFL) is a modern
     low-contrast sans, closest in feel to SF Arabic, so the mark looks
     consistent off Apple platforms instead of switching style entirely. */
  font-family: "Arabic Fallback";
  src: url("assets/fonts/Cairo.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF;
}

/* ============================================================
   Dania Abdulhamid — portfolio
   Built with international layout designed in, not retrofitted:
   every directional value uses CSS logical properties, so the
   entire page mirrors correctly under dir="rtl".
   ============================================================ */

:root {
  /* Type. A multi-script stack: the Latin face is chosen first,
     then faces with real coverage for Arabic, Hebrew, CJK and
     Indic, so text never falls back to tofu or a mismatched face. */
  --font-sans:
    ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", "Noto Sans", "Noto Sans Arabic", "Noto Sans Hebrew",
    "Noto Sans JP", "Noto Sans KR", "Noto Sans Devanagari",
    "Apple Color Emoji", sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;

  /* Modular scale, 1.25 ratio, clamped for fluid sizing. */
  --step--2: clamp(0.72rem, 0.70rem + 0.08vw, 0.78rem);
  --step--1: clamp(0.82rem, 0.80rem + 0.09vw, 0.875rem);
  --step-0:  clamp(1rem, 0.975rem + 0.12vw, 1.0625rem);
  --step-1:  clamp(1.15rem, 1.10rem + 0.25vw, 1.3rem);
  --step-2:  clamp(1.35rem, 1.26rem + 0.42vw, 1.65rem);
  --step-3:  clamp(1.75rem, 1.55rem + 0.9vw, 2.35rem);
  --step-4:  clamp(2.2rem, 1.88rem + 1.6vw, 3.15rem);

  /* Spacing */
  --space-xs: 0.5rem;
  --space-s:  1rem;
  --space-m:  1.75rem;
  --space-l:  3rem;
  --space-xl: 5rem;
  --space-2xl: 8rem;

  /* Measure */
  --measure: 34rem;
  --page-max: 68rem;

  /* Colour — light */
  --ink:        #16161a;
  --ink-muted:  #55555f;
  --ink-faint:  #6c6c76;   /* was #8a8a94 at 3.3:1 — below AA */
  --namemark-2: #8a8a94;   /* the Arabic name: 3.3:1, large display text */
  --rule:       #e4e4e8;
  --bg:         #fbfbfc;   /* neutral; was #fbfbfa, warm enough to tint
                              any card that inherits it inside a panel */
  --bg-raised:  #ffffff;
  --panel:      #f0f0f3;   /* neutral grey; was #f2f2ef, which read warm
                              against the cool --rule and --bg-raised */
  --accent:     #1f5fd0;
  --accent-purple: #af52de;  /* systemPurple, light */
  --card-shadow: 0 6px 20px rgba(20, 20, 30, 0.10);
  --shot-shadow: 0 8px 18px rgba(20, 20, 30, 0.14);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* Apple's iOS dark-mode system colours, so dark follows the platform
       rather than a value I picked. */
    --ink:        #ffffff;   /* label                     17.0:1 */
    --ink-muted:  #98989f;   /* secondaryLabel             5.9:1 */
    --ink-faint:  #8d8d93;   /* lifted off tertiaryLabel   5.2:1
                                Apple's own tertiaryLabel is 2.5:1,
                                which is decorative, not readable.  */
    --rule:       #38383a;   /* opaqueSeparator                  */
    --bg:         #1c1c1e;   /* secondarySystemBackground        */
    --bg-raised:  #2c2c2e;   /* tertiarySystemBackground         */
    --panel:      #2c2c2e;
    --accent:     #0a84ff;   /* systemBlue, dark                 */
    --accent-purple: #bf5af2; /* systemPurple, dark              */
    --namemark-2: #98989f;   /* dark already separates clearly          */
    --card-shadow: 0 6px 22px rgba(0, 0, 0, 0.45);
    --shot-shadow: 0 18px 38px rgba(0, 0, 0, 0.62);
  }
}

:root[data-theme="dark"] {
  --ink:        #ffffff;   /* label                     17.0:1 */
  --ink-muted:  #98989f;   /* secondaryLabel             5.9:1 */
  --ink-faint:  #8d8d93;   /* lifted off tertiaryLabel   5.2:1 */
  --rule:       #38383a;   /* opaqueSeparator                  */
  --bg:         #1c1c1e;   /* secondarySystemBackground        */
  --bg-raised:  #2c2c2e;   /* tertiarySystemBackground         */
  --panel:      #2c2c2e;
  --accent:     #0a84ff;   /* systemBlue, dark                 */
  --accent-purple: #bf5af2; /* systemPurple, dark              */
  --namemark-2: #98989f;
  --card-shadow: 0 6px 22px rgba(0, 0, 0, 0.45);
  --shot-shadow: 0 18px 38px rgba(0, 0, 0, 0.62);
}

/* ---------- base ---------- */

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

html {
  /* 106.25% of the browser default, so the whole rem-based system —
     type, spacing and measure alike — scales together. A percentage,
     not a px value, so a reader who has raised their own default
     font size still gets it honoured proportionally. */
  font-size: 106.25%;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--step-0);
  line-height: 1.6;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  line-height: 1.15;
  font-weight: 560;
  letter-spacing: -0.015em;
  text-wrap: balance;
  margin: 0;
}

p { margin: 0; text-wrap: pretty; }

/* Links carry a visible underline at rest, not just a colour. WCAG
   1.4.1 and Apple's "don't rely on colour alone" guidance both mean a
   reader with any colour vision deficiency has to be able to find a
   link without seeing the hue. Hover adds colour on top of the
   underline rather than replacing it. */
a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  text-decoration-color: var(--ink-faint);
  transition: text-decoration-color 150ms ease, text-decoration-thickness 120ms ease, color 150ms ease;
}
a:hover {
  color: var(--ink);
  text-decoration-color: currentColor;
  text-decoration-thickness: 2px;
}

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---------- layout ---------- */

.page {
  max-inline-size: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--space-m);
}

.prose { max-inline-size: var(--measure); }

section { padding-block: var(--space-xl); }

.rule {
  border: 0;
  border-block-start: 1px solid var(--rule);
  margin-block: 0;
}

/* ---------- skip link ---------- */

.skip {
  position: absolute;
  inset-inline-start: var(--space-m);
  inset-block-start: -4rem;
  background: var(--bg-raised);
  color: var(--ink);
  padding: var(--space-xs) var(--space-s);
  border: 1px solid var(--rule);
  border-radius: 6px;
  z-index: 10;
  transition: inset-block-start 150ms ease;
}
.skip:focus { inset-block-start: var(--space-s); }

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

.masthead {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s);
  align-items: baseline;
  justify-content: space-between;
  padding-block: var(--space-m);
}

.masthead__name {
  font-size: var(--step-0);
  font-weight: 560;
  letter-spacing: -0.01em;
  text-decoration: none;
}

.masthead__nav {
  display: flex;
  gap: var(--space-m);
  font-size: var(--step--1);
  color: var(--ink-muted);
}

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

.hero { padding-block: var(--space-xl) 0; }

.hero__lede {
  font-size: var(--step-4);
  font-weight: 560;
  letter-spacing: -0.03em;
  max-inline-size: 22ch;
  margin-block-end: var(--space-m);
}

.hero__body {
  font-size: var(--step-1);
  color: var(--ink-muted);
  max-inline-size: var(--measure);
  line-height: 1.5;
}

.hero__meta {
  margin-block-start: var(--space-m);
  font-size: var(--step--1);
  color: var(--ink-faint);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-s);
}

/* ---------- section heading ---------- */

.eyebrow {
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-block-end: var(--space-m);
}

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

.work { display: grid; gap: 0; }

.work__item {
  display: grid;
  gap: var(--space-xs) var(--space-l);
  grid-template-columns: 1fr;
  padding-block: var(--space-l);
  border-block-start: 1px solid var(--rule);
  text-decoration: none;
}

@media (min-width: 48rem) {
  .work__item {
    grid-template-columns: 9rem 1fr;
    align-items: start;
  }
}

/* Row links signal hover by underlining the title and moving the
   arrow, not by changing hue — the cue survives any colour vision. */
.work__item:hover .work__title,
.work__item:focus-visible .work__title {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.16em;
}

.work__index {
  display: block;
  font-size: var(--step-0);
  /* Line box matched to the title's, so both text boxes start together and
     only the small cap-ascent difference remains to correct for. */
  line-height: calc(var(--step-2) * 1.15);
  font-weight: 500;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  /* Residual cap-ascent difference between the two sizes, in em so it
     scales with the type rather than breaking at other viewport widths. */
  margin-block-start: -0.07em;
}

.work__title {
  display: block;
  font-size: var(--step-2);
  font-weight: 560;
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-wrap: balance;
  transition: color 150ms ease;
}

.work__summary {
  display: block;
  margin-block-start: var(--space-s);
  color: var(--ink-muted);
  max-inline-size: var(--measure);
  text-wrap: pretty;
}

.work__tags {
  margin-block-start: var(--space-s);
  font-size: var(--step--1);
  color: var(--ink-faint);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-s);
}

/* ---------- notes / secondary work ---------- */

.notes {
  display: grid;
  gap: var(--space-m);
}

@media (min-width: 48rem) {
  .notes { grid-template-columns: repeat(2, 1fr); gap: var(--space-l); }
}

.note__title {
  font-size: var(--step-0);
  font-weight: 560;
  margin-block-end: var(--space-xs);
}

.note__body {
  color: var(--ink-muted);
  font-size: var(--step--1);
  line-height: 1.65;
}

/* ---------- quote ---------- */

blockquote {
  margin: 0;
  padding-inline-start: var(--space-m);
  border-inline-start: 2px solid var(--rule);
  max-inline-size: var(--measure);
}

blockquote p {
  font-size: var(--step-1);
  line-height: 1.45;
  letter-spacing: -0.012em;
}

blockquote cite {
  display: block;
  margin-block-start: var(--space-s);
  font-style: normal;
  font-size: var(--step--1);
  color: var(--ink-faint);
}

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

.footer {
  padding-block: var(--space-l) var(--space-xl);
  border-block-start: 1px solid var(--rule);
  font-size: var(--step--1);
  color: var(--ink-muted);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s) var(--space-m);
  justify-content: space-between;
}

/* ---------- direction toggle ---------- */

/* Parked until the Arabic translation ships. The toggle only mirrors the
   layout today, so offering it would promise something the site cannot do.
   Delete this one rule to bring it back. */
.dirtoggle { display: none; }

.dirtoggle {
  font: inherit;
  font-size: var(--step--1);
  color: var(--ink-muted);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.3em 0.9em;
  cursor: pointer;
  transition: border-color 150ms ease, color 150ms ease;
}
.dirtoggle:hover { border-color: var(--ink-faint); color: var(--ink); }

/* ============================================================
   Case study pages
   ============================================================ */

.case__header { padding-block: var(--space-l) var(--space-m); }

.case__title {
  font-size: var(--step-3);
  letter-spacing: -0.025em;
  max-inline-size: 20ch;
  margin-block-end: var(--space-m);
}

.case__standfirst {
  font-size: var(--step-1);
  color: var(--ink-muted);
  max-inline-size: var(--measure);
  line-height: 1.5;
}

.case__facts {
  display: grid;
  gap: var(--space-m);
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  /* was --space-l on all three, which put 113px of padding around two
     lines of text */
  padding-block: var(--space-m);
  border-block: 1px solid var(--rule);
  margin-block-start: var(--space-m);
}

.fact__label {
  font-size: var(--step--1);
  color: var(--ink-faint);
  margin-block-end: 0.35rem;
}

.fact__value { font-size: var(--step--1); }

.case__body { max-inline-size: var(--measure); }

.case__body h2 {
  font-size: var(--step-2);
  margin-block: var(--space-l) var(--space-s);
  letter-spacing: -0.02em;
}

.case__body h3 {
  font-size: var(--step-0);
  margin-block: var(--space-m) var(--space-xs);
}

/* Prose paragraphs only. This used to match every <p> on the page,
   including the ones inside diagrams, which gave a 52px gap under a
   stat figure and 20px under every cut name. */
.case__body > p,
.case__body > blockquote p { margin-block-end: 1.35em; }

.case__body ul {
  margin-block: 0 var(--space-s);
  padding-inline-start: 1.1rem;
}
.case__body li { margin-block-end: var(--space-xs); }

/* A marker for content only Dania can supply. Delete the class
   and the note when the real content goes in. */
.todo {
  display: block;
  border-inline-start: 2px solid #d9a441;
  padding: var(--space-s) var(--space-m);
  margin-block-end: var(--space-s);
  background: color-mix(in srgb, #d9a441 7%, transparent);
  font-size: var(--step--1);
  color: var(--ink-muted);
  border-radius: 0 4px 4px 0;
}
.todo strong { color: var(--ink); }

.backlink {
  display: inline-block;
  font-size: var(--step--1);
  color: var(--ink-muted);
  padding-block: var(--space-m);
  text-decoration: none;
}
.backlink:hover,
.backlink:focus-visible { color: var(--ink); }

/* underline the label, not the arrow: text-decoration propagates to
   children, so the arrow has to sit outside the underlined element */
.backlink span {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: transparent;
  text-underline-offset: 0.18em;
  transition: text-decoration-color 150ms ease, text-decoration-thickness 120ms ease;
}
.backlink:hover span,
.backlink:focus-visible span {
  text-decoration-color: currentColor;
  text-decoration-thickness: 2px;
}


/* ============================================================
   Case study — reading layout

   A single centred column. Text, headings and diagrams all share
   named grid so prose, figures and diagrams share one rhythm and
   the whole thing still mirrors under dir="rtl".
   ============================================================ */

.case { --read: 52rem; --wide: 52rem; }   /* 40rem + 30% */

/* A single column, centred on the page, with everything inside it
   left-aligned. Diagrams share the column rather than breaking out
   of it, so the page has exactly one left edge and one right edge. */
.case__body {
  display: block;
  max-inline-size: var(--read);
  margin-inline: auto;
  font-size: 1.0625rem;  /* 17px */
  line-height: 1.62;
}

/* .breakout is kept on the markup but no longer widens anything —
   figures, cut grids and spoke lists all sit on the column. */
.case__body > .breakout { max-inline-size: 100%; }

.case__header,
.contents { max-inline-size: var(--read); margin-inline: auto; }

.case .backlink {
  display: block;
  max-inline-size: var(--read);
  margin-inline: auto;
}
.case__header > * { max-inline-size: 100%; margin-inline: 0; }
.case__header > .case__facts { max-inline-size: 100%; }

.case__body h2 {
  font-size: var(--step-2);
  margin-block: var(--space-l) var(--space-s);
  letter-spacing: -0.018em;
}

.case__body h3 {
  font-size: var(--step-0);
  margin-block: var(--space-l) var(--space-xs);
  color: var(--ink);
}

/* Prose paragraphs only. This used to match every <p> on the page,
   including the ones inside diagrams, which gave a 52px gap under a
   stat figure and 20px under every cut name. */
.case__body > p,
.case__body > blockquote p { margin-block-end: 1.35em; }
.case__body ul { margin-block: 0 var(--space-s); padding-inline-start: 1.15rem; }
.case__body li { margin-block-end: var(--space-xs); }
.case__body > .todo { max-inline-size: 100%; }

/* ============================================================
   Diagrams — drawn in the page's own type and colour, not pasted
   ============================================================ */

.dgrm {
  margin-block: var(--space-l);
  margin-inline: 0; /* figure carries a UA inline margin of 40px */
}

.dgrm__panel {
  background: var(--panel);
  border-radius: 10px;
  padding: var(--space-m);
}
@media (min-width: 46rem) {
  .dgrm__panel { padding: var(--space-l); }
}

.dgrm__cap {
  margin-block-start: var(--space-m);
  font-size: var(--step--1);
  color: var(--ink-muted);
  line-height: 1.55;
  max-inline-size: var(--read);
}
.dgrm__cap b { color: var(--ink); font-weight: 560; }

.dgrm__label {
  font-size: var(--step--2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-block-end: var(--space-s);
}

/* --- pillars --- */

/* Equal columns, equal gutters. minmax(0, 1fr) stops a long word like
   "Understandability" widening its own track, and the rules live in the
   gutters as pseudo-elements so no column carries asymmetric padding. */
.pillars {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--space-m);
  row-gap: var(--space-m);
}
@media (min-width: 46rem) {
  /* Columns size to their own text rather than splitting the width
     evenly: an equal grid left "Trust" with a 47px gap before its rule
     because "Google Photos" cannot break, while the others ran to the
     edge. Sizing to content keeps the space beside each rule constant. */
  .pillars {
    grid-template-columns: repeat(4, auto);
    justify-content: space-between;
    row-gap: 0;
  }
  /* 19ch is the one measure where all four questions wrap to the same
     three lines, so the blocks match in height as well as in width. */
  .pillar__q { max-inline-size: 19ch; }
}

.pillar {
  position: relative;
  overflow-wrap: break-word;
  hyphens: auto;
}

/* divider centred in the gutter, on every item except the row's first */
.pillar::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: calc(var(--space-m) / -2);
  border-inline-start: 1px solid var(--rule);
}
.pillar:nth-child(2n+1)::before { content: none; }

@media (min-width: 46rem) {
  .pillar:nth-child(2n+1)::before { content: ""; }
  .pillar:nth-child(4n+1)::before { content: none; }
}

.pillar__name {
  font-size: var(--step-0);
  font-weight: 560;
  margin-block-end: var(--space-xs);
}
.pillar__q {
  font-size: var(--step--1);
  color: var(--ink-muted);
  line-height: 1.5;
}

.pillars__foot {
  grid-column: 1 / -1;
  margin-block-start: var(--space-m);
  font-size: var(--step--1);
  color: var(--ink-muted);
  max-inline-size: 46rem;
}
.pillars__foot b { color: var(--ink); font-weight: 560; }

/* --- state row --- */

.states {
  display: grid;
  gap: var(--space-s);
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
}

.state {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: var(--space-s) var(--space-m) var(--space-m);
}
.state--broken { border-color: color-mix(in srgb, #d9a441 55%, var(--rule)); }

.state__tag {
  font-size: var(--step--2);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-block-end: var(--space-xs);
}
.state--broken .state__tag { color: #b8862c; }

.state__name { font-weight: 560; margin-block-end: 0.3rem; }
.state__note { font-size: var(--step--1); color: var(--ink-muted); line-height: 1.5; }

/* --- gaps --- */

.gaps { display: grid; gap: 0; grid-template-columns: 1fr; }
@media (min-width: 46rem) { .gaps { grid-template-columns: repeat(3, 1fr); } }

.gap {
  padding: var(--space-m) var(--space-m) var(--space-m) 0;
  border-block-start: 2px solid var(--ink);
  margin-inline-end: var(--space-m);
}
.gap__name { font-weight: 560; margin-block: var(--space-xs) var(--space-xs); }
.gap__body { font-size: var(--step--1); color: var(--ink-muted); line-height: 1.55; }

/* --- spectrum (inline svg) --- */

.spectrum { inline-size: 100%; block-size: auto; overflow: visible; }
.spectrum text { font-family: var(--font-sans); fill: var(--ink); }
.spectrum .sp-axis { stroke: var(--rule); stroke-width: 1; }
.spectrum .sp-node { fill: var(--bg); stroke: var(--ink); stroke-width: 1.5; }
.spectrum .sp-node--held { stroke-dasharray: 3 3; stroke: #b8862c; }
.spectrum .sp-name { font-size: 13px; font-weight: 560; letter-spacing: -0.01em; }
.spectrum .sp-note { font-size: 11px; fill: var(--ink-muted); }
.spectrum .sp-end { font-size: 10px; fill: var(--ink-faint); letter-spacing: 0.07em; text-transform: uppercase; }
.spectrum .sp-held { font-size: 10px; fill: #b8862c; letter-spacing: 0.06em; text-transform: uppercase; }

/* --- cut list --- */

.cuts { border-block-start: 1px solid var(--rule); }

.cut {
  display: grid;
  gap: 0.15rem var(--space-m);
  grid-template-columns: 1fr;
  padding-block: var(--space-s);
  border-block-end: 1px solid var(--rule);
}
@media (min-width: 46rem) { .cut { grid-template-columns: 4.5rem 13rem 1fr; align-items: baseline; } }

.cut__verdict {
  font-size: var(--step--2);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.cut__verdict--kept { color: var(--ink); }
.cut__name { font-weight: 560; font-size: var(--step--1); }
.cut__why { font-size: var(--step--1); color: var(--ink-muted); line-height: 1.5; }

/* --- image plates (real UI, not redrawn) --- */

.plates {
  display: grid;
  gap: var(--space-m);
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  align-items: start;
}

.plate img {
  display: block;
  inline-size: 100%;
  block-size: auto;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: #fff;
}

.plate__name {
  margin-block-start: var(--space-s);
  font-size: var(--step--1);
  font-weight: 560;
}
.plate__note {
  font-size: var(--step--1);
  color: var(--ink-muted);
  line-height: 1.5;
}
.plate--held .plate__name { color: #b8862c; }

/* --- artefact plate: a tall document, scrollable in place, openable full size --- */

/* Shown at full length. The map is portrait (1800x2387), so at the
   column width it lands around 1040px tall — long, but a reader can
   take it in by scrolling the page rather than a frame inside it. */
.artefact {
  border-radius: 6px;
  background: #fff;
  border: 1px solid var(--rule);
}
.artefact img { display: block; inline-size: 100%; block-size: auto; }

.artefact__open {
  display: inline-block;
  margin-block-start: var(--space-s);
  font-size: var(--step--1);
  color: var(--ink-muted);
}

/* --- lineage: what the workshop clusters became --- */

.lineage { display: grid; }

.lin {
  display: grid;
  gap: 0.2rem var(--space-m);
  grid-template-columns: 1fr;
  padding-block: var(--space-s);
  border-block-end: 1px solid var(--rule);
}
.lin:last-child { border-block-end: 0; }
@media (min-width: 46rem) {
  .lin { grid-template-columns: 16rem 1fr; align-items: baseline; }
}

.lin__cluster {
  font-size: var(--step--1);
  font-weight: 560;
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
}

.lin__dot {
  inline-size: 0.6rem;
  block-size: 0.6rem;
  border-radius: 2px;
  flex: none;
  translate: 0 0.05rem;
}
.lin__dot--terminology { background: #d9c9f0; }
.lin__dot--status      { background: #bfdcf5; }
.lin__dot--value       { background: #f6c9da; }
.lin__dot--other       { background: #d6d6d8; }

.lin__became { font-size: var(--step--1); color: var(--ink-muted); line-height: 1.55; }
.lin__became b { color: var(--ink); font-weight: 560; }

/* --- project spokes, linked from a hub case study --- */

.spokes { display: grid; gap: 0; margin-block-start: var(--space-m); }

.spoke {
  display: grid;
  gap: 0.2rem var(--space-m);
  grid-template-columns: 1fr;
  padding-block: var(--space-m);
  border-block-start: 1px solid var(--rule);
  text-decoration: none;
}
.spoke:last-child { border-block-end: 1px solid var(--rule); }
@media (min-width: 46rem) {
  /* 9.75rem, not 8: "UNDERSTANDABILITY" is the longest pillar name and
     letterspaced uppercase pushes it past 8rem with nowhere to break. */
  .spoke { grid-template-columns: 9.75rem 1fr auto; align-items: baseline; }
}

.spoke__pillar {
  font-size: var(--step--2);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.spoke__name {
  font-size: var(--step-1);
  font-weight: 560;
  letter-spacing: -0.015em;
  transition: color 150ms ease;
}
.spoke:hover .spoke__name,
.spoke:focus-visible .spoke__name {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.16em;
}
.spoke { transition: none; }
.spoke__arrow { transition: transform 150ms ease; }
.spoke:hover .spoke__arrow { transform: translateX(0.2rem); }
.spoke__note {
  display: block;
  margin-block-start: 0.25rem;
  font-size: var(--step--1);
  color: var(--ink-muted);
  line-height: 1.55;
  max-inline-size: 34rem;
}
.spoke__arrow { color: var(--ink-faint); font-size: var(--step--1); }

/* a spoke that has no page yet reads as pending, not broken */
.spoke--pending { opacity: 0.55; }
.spoke--pending .spoke__arrow { font-size: var(--step--2); letter-spacing: 0.06em; text-transform: uppercase; }

/* --- bilingual name mark ---
   Two scripts as one lockup: the Latin sets the width, the Arabic is
   aligned to its trailing edge and tucked up underneath. Because the
   alignment is logical rather than left/right, the whole mark mirrors
   correctly when the document direction flips. --- */

.namemark {
  display: inline-grid;
  justify-items: end;
  text-decoration: none;
  line-height: 1;
  padding-block-end: 0.55em; /* room for the tucked-under script */
}

.namemark__latin {
  font-size: var(--step-1);
  font-weight: 560;
  letter-spacing: -0.02em;
}

.namemark__arabic {
  /* Apple's SF Arabic is a hidden system font (".SF Arabic") and cannot be
     named directly, so it is reached through the system stack — which is what
     macOS and iOS resolve Arabic glyphs to. Non-Apple platforms fall through
     to a self-hosted face so the name never renders as tofu. */
  font-family: -apple-system, system-ui, "Arabic Fallback", "Geeza Pro", sans-serif;
  font-weight: 600;
  /* Arabic sits smaller in its em box than Latin, so it is set larger
     here to match optically rather than numerically. */
  font-size: 1.15em;
  line-height: 1;
  color: var(--namemark-2);
  margin-block-start: -0.22em;
  transition: color 160ms ease;
}

.namemark:hover .namemark__arabic { color: var(--ink); }

/* work items whose case study isn't written yet — visibly pending, not broken */
.work__item--pending { cursor: default; }
.work__item--pending .work__title { color: var(--ink-muted); }
.work__soon {
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.1em 0.7em;
}

/* --- name mark at display size, used as the homepage headline --- */

.namemark--display {
  display: inline-grid;
  padding-block-end: 0.3em;
  margin-block-end: var(--space-m);
}
.namemark--display .namemark__latin {
  font-size: var(--step-4);
  letter-spacing: -0.035em;
}
.namemark--display .namemark__arabic {
  color: var(--ink-faint);
  margin-block-start: -0.26em;
}

/* the homepage carries the name in the hero, so the masthead is nav only */
.masthead--navonly { justify-content: flex-end; }

/* hero set as a sentence rather than a headline */
/* The hero sentence and the illustration under it share one width, so the
   drawing always ends exactly where the sentence does. */
.hero { --hero-measure: 35rem; }

.hero__lede--sentence {
  font-size: var(--step-3);
  font-weight: 560;
  letter-spacing: -0.025em;
  line-height: 1.2;
  max-inline-size: var(--hero-measure);
  margin-block-end: 0;
}
code { font-family: var(--font-mono); font-size: 0.9em; color: var(--ink); }

/* company name inside a project title */
.work__org { color: var(--ink-faint); font-weight: 500; }
.work__item:hover .work__org { color: inherit; }

/* --- hero mark: drawn illustration, traced to vector so it takes the
       page's colour and stays sharp at any size --- */

.tangle {
  display: block;
  inline-size: min(100%, var(--hero-measure));
  block-size: auto;
  /* same grey as the org names in the work list, so the drawing sits
     at the same weight as the quietest type on the page */
  color: var(--ink-faint);
  margin-block-start: var(--space-s);

  /* Soft left-to-right reveal: a gradient mask slides across, so the
     drawing appears to resolve rather than being wiped in. */
  -webkit-mask-image: linear-gradient(90deg, #000 38%, rgba(0,0,0,0) 62%);
          mask-image: linear-gradient(90deg, #000 38%, rgba(0,0,0,0) 62%);
  -webkit-mask-size: 260% 100%;
          mask-size: 260% 100%;
  -webkit-mask-position: 100% 0;
          mask-position: 100% 0;
          mask-position: 100% 0;
  animation: tangle-draw 2.2s cubic-bezier(0.32, 0.72, 0.28, 1) 0.3s forwards;
}

@keyframes tangle-draw {
  to { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .tangle { animation: none; -webkit-mask-image: none; mask-image: none; }
}

/* --- results row --- */

.stats {
  display: grid;
  gap: var(--space-m);
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
}

.stat__figure {
  font-size: var(--step-3);
  font-weight: 560;
  letter-spacing: -0.03em;
  line-height: 1.05;
  margin-block-end: 0.35rem;
}
.stat__label {
  font-size: var(--step--1);
  color: var(--ink-muted);
  line-height: 1.5;
}

/* wider label column, for when the left cell holds a pillar name rather than a verdict */
@media (min-width: 46rem) {
  .cuts--wide .cut { grid-template-columns: 9.5rem 13rem 1fr; }
}

/* --- state spectrum: two clear states with an ambiguous middle --- */

.spectrum-states {
  display: grid;
  gap: var(--space-s);
  grid-template-columns: 1fr;
  align-items: stretch;
}
@media (min-width: 46rem) {
  .spectrum-states { grid-template-columns: 1fr 1.6fr 1fr; gap: var(--space-m); }
}

.sstate {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: var(--space-m);
}
.sstate__name { font-weight: 560; margin-block-end: 0.3rem; }
.sstate__note { font-size: var(--step--1); color: var(--ink-muted); line-height: 1.5; }

.sstate--murky {
  border-style: dashed;
  border-color: color-mix(in srgb, #d9a441 55%, var(--rule));
  background: color-mix(in srgb, #d9a441 5%, transparent);
}
.sstate--murky .sstate__name { color: #b8862c; }
.sstate__list {
  margin: var(--space-s) 0 0;
  padding-inline-start: 1.05rem;
  font-size: var(--step--1);
  color: var(--ink-muted);
  line-height: 1.5;
}
.sstate__list li { margin-block-end: 0.3rem; }

/* the ideal state, stated inline */
.ideal {
  display: inline-block;
  font-weight: 560;
  letter-spacing: 0.01em;
  padding: 0.45em 1em;
  border: 1px solid var(--rule);
  border-radius: 999px;
  margin-block: var(--space-s) var(--space-m);
}

/* --- audit table: many variants of one thing, a few of them broken --- */

.audit {
  inline-size: 100%;
  border-collapse: collapse;
  font-size: var(--step--1);
  text-align: start;
}
.audit caption {
  text-align: start;
  font-size: var(--step--2);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-block-end: var(--space-s);
}
.audit th {
  font-weight: 560;
  color: var(--ink-faint);
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding-block: 0.5rem;
  border-block-end: 1px solid var(--rule);
}
.audit td {
  padding-block: 0.5rem;
  padding-inline-end: var(--space-m);
  border-block-end: 1px solid var(--rule);
  color: var(--ink-muted);
  vertical-align: top;
}
.audit td:first-child { color: var(--ink); }
.audit tr:last-child td { border-block-end: 0; }
.audit .dead { color: #b8862c; font-weight: 560; }
.audit tr.is-broken td:first-child { color: #b8862c; }

/* ============================================================
   Deck view — the original slides, in order
   ============================================================ */

.deck .case__header { padding-block-end: var(--space-m); }

.deck__controls {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  padding-block: var(--space-m);
  border-block: 1px solid var(--rule);
  position: sticky;
  inset-block-start: 0;
  background: var(--bg);
  z-index: 5;
}

.deckbtn {
  font: inherit;
  font-size: var(--step--1);
  color: var(--ink-muted);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 999px;
  inline-size: 2.2rem;
  block-size: 2.2rem;
  cursor: pointer;
  transition: border-color 150ms ease, color 150ms ease;
}
.deckbtn:hover { border-color: var(--ink-faint); color: var(--ink); }

.deck__count {
  font-size: var(--step--1);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.deck__hint {
  margin-inline-start: auto;
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.deck__track {
  display: grid;
  gap: var(--space-xl);
  padding-block: var(--space-xl);
}

.slide { margin: 0; scroll-margin-block: 5rem; }

.slide img {
  display: block;
  inline-size: 100%;
  block-size: auto;
  aspect-ratio: 2400 / 1350;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: #fff;
}

.slide figcaption {
  display: flex;
  gap: var(--space-s);
  margin-block-start: var(--space-s);
  font-size: var(--step--1);
  color: var(--ink-muted);
}
.slide__num {
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.deck__link { margin-block-start: var(--space-l); font-size: var(--step--1); }

/* prominent link out to a deck, sitting under the standfirst */
.deck__promo {
  max-inline-size: var(--read);
  margin-block: var(--space-m) 0;
  font-size: var(--step--1);
}
.deck__promo a {
  display: inline-block;
  padding: 0.5em 1.1em;
  border: 1px solid var(--rule);
  border-radius: 999px;
  text-decoration: none;
  color: var(--ink);
  transition: border-color 150ms ease;
}
.deck__promo a:hover { border-color: var(--ink-faint); }

/* a caption only appears on slides that need one, so it reads as a note rather than a label */
.slide figcaption {
  display: block;          /* overrides an older flex rule further up the file */
  max-inline-size: var(--read);
  margin-block-start: var(--space-s);
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--ink-muted);
  padding-inline-start: var(--space-s);
  border-inline-start: 2px solid var(--rule);
}
.slide figcaption b { color: var(--ink); font-weight: 560; }
/* each definition on its own line when a caption carries more than one */
.slide figcaption span { display: block; }
.slide figcaption span + span { margin-block-start: 0.35rem; }

/* a short glossary, for decks that use internal shorthand on the slides */
/* On a deck the header's bottom padding and the glossary's top margin
   both applied, stacking to 60px. The glossary's margin is enough. */
.deck .case__header { padding-block-end: 0; }

.deck__terms {
  max-inline-size: var(--read);
  margin-inline: auto;          /* line up with the title and standfirst */
  margin-block: var(--space-m) var(--space-l);
  padding: var(--space-s) var(--space-m);
  background: var(--panel);
  border-radius: 8px;
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--ink-muted);
  display: grid;
  gap: 0.4rem;                  /* one definition per line */
}
.deck__terms p { margin: 0; }
.deck__terms b { color: var(--ink); font-weight: 560; }
.deck__terms .deck__terms-label {
  display: block;
  font-size: var(--step--2);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-block-end: 0.1rem;
}


/* Section contents. Makes the shape of the argument visible in one
   glance without touching a word of the prose, and gives a reader
   who is skimming somewhere to jump to. Numbers come from the <ol>,
   so they stay correct if a section is added or dropped. */
.contents {
  margin-block-start: var(--space-l);
  max-inline-size: var(--read);
}

.contents__label {
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-block-end: var(--space-s);
}

.contents__list {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: sec;
  display: grid;
  gap: 0;
}

.contents__list li {
  counter-increment: sec;
  border-block-start: 1px solid var(--rule);
}
.contents__list li:last-child { border-block-end: 1px solid var(--rule); }

.contents__list a {
  display: grid;
  grid-template-columns: 2.25rem 1fr auto;
  gap: var(--space-s);
  align-items: baseline;
  padding-block: 0.7rem;
  font-size: var(--step-0);
  color: var(--ink-muted);
  text-decoration: none;
  transition: color 150ms ease;
}

/* The number is part of the row, not a separate control, so it takes
   the row's colour rather than highlighting on its own. */
.contents__list a::before {
  content: counter(sec) ".";
  color: inherit;
  opacity: 0.65;
  font-variant-numeric: tabular-nums;
}

/* Arrow is the non-colour affordance: it appears and moves on hover
   and on keyboard focus, so the row reads as actionable without
   relying on the colour change alone. */
.contents__list a::after {
  content: "\2192";
  opacity: 0;
  transform: translateX(-0.35rem);
  transition: opacity 150ms ease, transform 150ms ease;
}

/* The underline goes on the title span, not the anchor: text-decoration
   propagates to pseudo-elements and children cannot opt out, so
   underlining the row would drag in the counter and the arrow. */
.contents__list a:hover,
.contents__list a:focus-visible { color: var(--ink); }

.contents__list a span {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: transparent;
  text-underline-offset: 0.16em;
  transition: text-decoration-color 150ms ease, text-decoration-thickness 120ms ease;
}

.contents__list a:hover span,
.contents__list a:focus-visible span {
  text-decoration-color: currentColor;
  text-decoration-thickness: 2px;
}

.contents__list a:hover::after,
.contents__list a:focus-visible::after {
  opacity: 1;
  transform: translateX(0);
}

/* The arrow points the other way under dir="rtl". */
[dir="rtl"] .contents__list a::after { content: "\2190"; }

/* The anchors sit under nothing sticky here, but give the target a
   little air so a jumped-to heading is not flush against the top. */
.case__body h2 { scroll-margin-block-start: var(--space-l); }

/* On case-study pages the masthead and footer align to the reading
   column too, so the page has a single left edge from the name mark
   at the top to the copyright line at the bottom. `.case` sits on the
   <body>, so this scopes cleanly and leaves the homepage alone. */
.case .masthead,
.case .footer {
  max-inline-size: var(--read);
  margin-inline: auto;
}

/* ============================================================
   Homepage — same single centred column as the case studies
   ============================================================ */

.column { --read: 52rem; }

/* Constrain the children of .page rather than .page itself, so the
   column measures 52rem of content and lands on exactly the same
   left edge as a case study rather than 52rem minus page padding. */
.column .masthead,
.column .hero,
.column #work,
.column #about,
.column .footer {
  max-inline-size: var(--read);
  margin-inline: auto;
}

/* The lede and intro were measured against the old narrower page.
   Let them use the column so the homepage has one left edge and one
   right edge, like every other page. */
.column .hero__lede { max-inline-size: 22ch; }
.column .hero__body { max-inline-size: var(--read); }

/* ---------- about portrait ---------- */

.portrait {
  max-inline-size: var(--read);
  margin-inline: auto;
  margin-block: var(--space-l) 0;
}

.portrait img {
  display: block;
  inline-size: 100%;
  max-inline-size: 24rem;   /* left-aligned in the column, not full bleed */
  block-size: auto;
  border-radius: 10px;
  background: var(--panel);
}

.portrait figcaption {
  margin-block-start: var(--space-s);
  font-size: var(--step--1);
  color: var(--ink-faint);
}

/* ---------- deck list on a project page ---------- */

.decks {
  max-inline-size: var(--read);
  margin-inline: auto;
  margin-block-start: var(--space-l);
}

.decks__label {
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-block-end: var(--space-s);
}

.decks .spoke:last-child { border-block-end: 1px solid var(--rule); }

/* A slide lifted from a deck, used where it explains the prose better
   than a redrawn diagram would. Links through to the same slide in
   its deck, so the figure is a way in rather than a dead end. */
.dgrm--slide .dgrm__panel { padding: var(--space-s); }

.slidefig {
  display: block;
  border-radius: 6px;
  overflow: hidden;
  background: #fff;
  text-decoration: none;
  transition: outline-color 150ms ease;
  outline: 1px solid var(--rule);
  outline-offset: -1px;
}
.slidefig img { display: block; inline-size: 100%; block-size: auto; }
.slidefig:hover { outline-color: var(--ink-faint); }

.dgrm--slide .dgrm__cap a { color: var(--ink-muted); white-space: nowrap; }

/* --- the storage journey, split across three teams --- */

.jstages {
  display: grid;
  gap: var(--space-s);
  grid-template-columns: 1fr;
}
@media (min-width: 46rem) {
  .jstages { grid-template-columns: repeat(3, 1fr); align-items: stretch; }
}

.jstage {
  position: relative;
  padding: var(--space-m);
  border-radius: 8px;
  background: var(--bg);
  border: 1px solid var(--rule);
}

/* The middle stage is hers. The tag is corner-mounted out of flow, so
   all three cards keep the same first baseline. */
/* The stage Dania owned: dotted blue outline and a lift off the panel.
   The written text names it, so the card carries no label of its own. */
.jstage--mine {
  background: var(--bg-raised);
  box-shadow: var(--card-shadow);
  /* outline, not border: a 2px border would occupy layout space and
     push this card's text 1px below the other two. */
  border-color: transparent;
  outline: 2px solid var(--ink-faint);
  outline-offset: -2px;
}



.jstage__name {
  font-size: var(--step-1);
  font-weight: 560;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.jstage__goal {
  font-size: var(--step--2);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-block: 0.2rem var(--space-xs);
}

.jstage__note {
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--ink-muted);
}


}

/* The header's bottom padding and the first heading's top margin do not
   collapse (different boxes), so they stacked to 136px. Both trimmed. */
.case__body > h2:first-child { margin-block-start: var(--space-m); }

/* A back link at the top of the page as well as the bottom, so it is
   reachable without scrolling to the end of a long deck. */
.backlink--top {
  /* sits with the page content, not tucked under the masthead */
  padding-block: 0;
  margin-block-start: var(--space-l);
}
/* the back link groups with the eyebrow and title, not the masthead */
.backlink--top + .case__header { padding-block-start: var(--space-xs); }

/* The deck shares the reading column, so the slides and their controls
   line up with the title, standfirst and glossary above them. */
.deck__controls,
.deck__track {
  max-inline-size: var(--read);
  margin-inline: auto;
}

/* A deck embedded inside a written case study, rather than on its own
   page. Shares the reading column like every other block. */
.deckblock {
  max-inline-size: var(--read);
  margin-inline: auto;
  margin-block: var(--space-l);
}
.deckblock .dgrm__label { margin-block-end: var(--space-s); }
.deckblock .deck__track { padding-block: var(--space-l) 0; gap: var(--space-l); }

/* A product shot rather than a drawn diagram: the image carries its own
   frame and shadow, so the panel just centres it. */
.dgrm--shot { display: grid; justify-items: center; }
.dgrm--shot .dgrm__label { justify-self: start; }
.dgrm--shot img {
  display: block;
  inline-size: auto;
  max-inline-size: min(100%, 22rem);
  block-size: auto;
  margin-block-start: var(--space-s);
}

/* The name mark aligns both scripts to the edge the reader starts from.
   `justify-items: end` resolves to the left under dir="rtl", which drops
   the Arabic away from the right edge, so it flips here. */
[dir="rtl"] .namemark { justify-items: start; }

/* Product shot alongside the case title. The shot fills the height of
   the text beside it and is cut off by a rule at the bottom, so it
   reads as sitting in a pocket rather than floating. */
.hero-shot { display: grid; gap: var(--space-m); }

@media (min-width: 52rem) {
  .hero-shot {
    grid-template-columns: minmax(0, 1fr) 14.25rem;
    gap: var(--space-m);
    align-items: stretch;      /* the shot matches the text column's height */
  }
}

.hero-shot__img {
  position: relative;
  /* clip only the bottom: overflow:hidden would also slice the drop
     shadow at the sides, which reads as the image being cut off */
  clip-path: inset(-80px -80px 0 -80px);
  padding-inline: 0;
  max-block-size: 20rem;       /* narrow screens: stack below, keep it modest */
  margin-inline: auto;
  inline-size: min(100%, 17rem);
}

@media (min-width: 52rem) {
  .hero-shot__img {
    max-block-size: none;
    inline-size: auto;
    margin-inline: 0;
    min-block-size: 14rem;
  }
  /* Absolute, so the shot cannot set the row height. The row is as tall
     as the text, and the shot is cut off there. */
  .hero-shot__img img {
    position: absolute;
    inset-block-start: 0;
    inset-inline: 0;
    inline-size: 100%;
  }
}

.hero-shot__img img {
  display: block;
  inline-size: 100%;
  block-size: auto;
  filter: drop-shadow(var(--shot-shadow));
}

/* the pocket: a rule slightly wider than the device, casting up onto it */
.hero-shot__img::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 1px;
  background: var(--rule);
  /* just enough haze to read as "behind the line". The spread and a
     long blur put a ~20px band of page colour over the screen, which is
     harsh on dark where that colour is near-black. */
  box-shadow: 0 -2px 7px 0 var(--bg);
}

/* About: the portrait sits beside the text, not between it */
.about {
  max-inline-size: var(--read);
  margin-inline: auto;
  /* the header already supplies its own bottom padding; adding a margin
     here stacked the two into an 81px gap */
  margin-block-start: 0;
  display: grid;
  gap: var(--space-l);
}

@media (min-width: 46rem) {
  .about { grid-template-columns: minmax(0, 1fr) 17rem; align-items: stretch; }
}

.about__text > p { margin-block-end: 1.35em; }
.about__text > p:last-child { margin-block-end: 0; }
.about__contact { line-height: 2; }

/* The frame takes its height from the text beside it and the photo
   fills it, cropped from the top so the bottom of the picture and the
   bottom of the text land together. */
/* Mobile: the whole photo, uncropped. There is no text beside it to
   match, so cropping only loses her head. */
.about .portrait { margin: 0; max-inline-size: none; }

.about .portrait__frame {
  display: block;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: var(--card-shadow);
}

.about .portrait img {
  display: block;
  inline-size: 100%;
  max-inline-size: none;
  block-size: auto;
}

/* Two-column only: the frame takes its height from the text beside it
   and the photo is cropped from the top to match. */
@media (min-width: 46rem) {
  .about .portrait {
    display: grid;
    grid-template-rows: minmax(0, 1fr) auto;
    min-block-size: 0;
  }
  .about .portrait__frame { position: relative; min-block-size: 11rem; }
  .about .portrait img {
    position: absolute;
    inset: 0;
    block-size: 100%;
    object-fit: cover;
    object-position: 50% 35%;   /* keep her face in frame, trim below */
  }
}

.about .portrait figcaption {
  margin-block-start: var(--space-xs);
  font-size: var(--step--1);
  color: var(--ink-faint);
}

/* ============================================================
   Résumé — reads as part of the site on screen, prints as a
   plain one-page document
   ============================================================ */

.cv {
  max-inline-size: var(--read);
  margin-inline: auto;
  margin-block: var(--space-m) var(--space-l);
}

.cv__print-hint {
  max-inline-size: var(--read);
  margin-inline: auto;
  margin-block-start: var(--space-m);
  font-size: var(--step--1);
  color: var(--ink-muted);
}
.cv__print-hint b { color: var(--ink); font-weight: 560; }

.cv__head { margin-block-end: var(--space-m); }

.cv__name {
  font-size: var(--step-3);
  font-weight: 560;
  letter-spacing: -0.025em;
  margin-block-end: var(--space-xs);
}

.cv__contact {
  font-size: var(--step--1);
  color: var(--ink-muted);
  line-height: 1.6;
}
.cv__sep { color: var(--ink-faint); margin-inline: 0.35em; }

/* the global `section { padding-block: --space-xl }` was adding 85px to
   every section here on top of these margins */
.cv__section { padding-block: 0; margin-block-end: var(--space-m); }
.cv__section--last { margin-block-end: 0; }

.cv__h {
  font-size: var(--step--2);
  font-weight: 560;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-block-end: 0.35rem;
  border-block-end: 1px solid var(--rule);
  margin-block-end: var(--space-s);
}

.cv__role { margin-block-end: var(--space-s); }
.cv__role:last-child { margin-block-end: 0; }

.cv__roleline {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem var(--space-s);
  align-items: baseline;
  justify-content: space-between;
}

.cv__org { font-weight: 560; color: var(--ink); }
.cv__when { font-size: var(--step--1); color: var(--ink-faint); font-variant-numeric: tabular-nums; }

.cv__title {
  font-size: var(--step--1);
  color: var(--ink-muted);
  margin-block-end: 0.4rem;
}
.cv__where { color: var(--ink-faint); }
.cv__where::before { content: "\00b7"; margin-inline: 0.4em; }

.cv ul { margin: 0; padding-inline-start: 1.05rem; }
.cv li {
  font-size: var(--step--1);
  line-height: 1.45;
  color: var(--ink-muted);
  margin-block-end: 0.15rem;
}
.cv li:last-child { margin-block-end: 0; }

.cv__meta {
  display: grid;
  grid-template-columns: 6.5rem 1fr;
  gap: 0.35rem var(--space-s);
  margin: 0;
  font-size: var(--step--1);
}
.cv__meta dt { color: var(--ink-faint); }
.cv__meta dd { margin: 0; color: var(--ink-muted); }

/* ---------- print ---------- */

@media print {
  @page { size: A4; margin: 13mm 14mm; }

  .no-print { display: none !important; }

  /* force a plain document regardless of the reader's theme */
  :root {
    --ink: #000;
    --ink-muted: #1f1f24;
    --ink-faint: #55555c;
    --rule: #bfbfc6;
    --bg: #fff;
    --bg-raised: #fff;
    --panel: #fff;
  }
  html, body { background: #fff !important; font-size: 100%; }

  .page { max-inline-size: none; padding: 0; }
  .cv { max-inline-size: none; margin: 0; }

  .cv__name { font-size: 20pt; }
  .cv__h { font-size: 7.5pt; margin-block-end: 5pt; padding-block-end: 2.5pt; }
  .cv__contact, .cv__title, .cv li, .cv__when, .cv__meta { font-size: 8.6pt; }
  .cv__org { font-size: 10pt; }

  .cv__section { margin-block-end: 8pt; }
  .cv__role { margin-block-end: 6pt; }
  .cv li { margin-block-end: 1pt; line-height: 1.32; }

  /* never split a job across pages */
  .cv__role, .cv__section { break-inside: avoid; }
  a { text-decoration: none; color: inherit; }
}


}

/* A standing note to the reader — not a to-do. Quieter than body copy,
   set off by a rule rather than a highlight. */
.casenote {
  font-size: var(--step--1);
  color: var(--ink-muted);
  padding-inline-start: var(--space-s);
  border-inline-start: 2px solid var(--rule);
  margin-block-end: var(--space-l);
}

/* the shipped-product shot sits on the panel like the backup one */
.dgrm--shot img { max-inline-size: 100%; border-radius: 6px; }
