/* ==========================================================================
   Mohamed Hussein — CV · Charcoal + Emerald theme
   ========================================================================== */

:root {
  --font-display: "Fraunces", Georgia, serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-display-ar: "Kufam", var(--font-body);
  --font-body-ar: "Kufam", var(--font-body);

  --radius-sm: 8px;
  --radius-md: 16px;
  --radius-lg: 28px;

  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);

  --container: 1120px;
}

[data-theme="dark"] {
  --bg: #0b100e;
  --bg-alt: #0f1613;
  --surface: #141d19;
  --surface-2: #182420;
  --border: rgba(230, 245, 238, 0.09);
  --border-strong: rgba(230, 245, 238, 0.18);
  --text: #eaf2ee;
  --text-muted: #98aca3;
  --text-dim: #6c8079;
  --accent: #22c98c;
  --accent-2: #6ee8b8;
  --accent-soft: rgba(34, 201, 140, 0.12);
  --accent-contrast: #06120d;
  --shadow-color: 150 40% 2%;
}

[data-theme="light"] {
  --bg: #f6f8f6;
  --bg-alt: #eef3ef;
  --surface: #ffffff;
  --surface-2: #f0f5f1;
  --border: rgba(15, 30, 22, 0.09);
  --border-strong: rgba(15, 30, 22, 0.16);
  --text: #10201a;
  --text-muted: #48594f;
  --text-dim: #6f8078;
  --accent: #0b8f5e;
  --accent-2: #067a4f;
  --accent-soft: rgba(11, 143, 94, 0.1);
  --accent-contrast: #f6fff9;
  --shadow-color: 150 30% 60%;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* The gutter is reserved whether or not a scrollbar is showing, so locking
   the page for a modal below cannot shift the layout sideways. */
html { scrollbar-gutter: stable; }
/* Page frozen while the command palette is open: a drag on the scrim
   otherwise scrolls the document behind it and you lose your place. */
html.cmdk-open { overflow: hidden; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  transition: background-color .4s var(--ease-out), color .4s var(--ease-out);
  overflow-x: hidden;
}

html[dir="rtl"] body { font-family: var(--font-body-ar); }
html[dir="rtl"] h1, html[dir="rtl"] h2, html[dir="rtl"] h3 { font-family: var(--font-display-ar); font-style: normal; }
/* Arabic has no italic; leaving it on makes the browser synthesise a slant.
   Kufam also sets حسين wider than محمد, inverting the width hierarchy the
   Latin name has (Hussein is ~0.78 of Mohamed). Scaling the family name back
   to ~0.7em restores that same relationship. */
html[dir="rtl"] .accent-text { font-style: normal; font-size: .7em; }
/* The hero's .96 leading is set for Latin caps, which have no descenders here.
   Arabic does (the ح bowl, the ن tail) and .split-line clips overflow for the
   reveal, so give the RTL name room rather than shearing its tails off. */
html[dir="rtl"] .hero-name { line-height: 1.2; }
html[dir="rtl"] .hero-eyebrow,
html[dir="rtl"] .hero-role,
html[dir="rtl"] .section-kicker,
html[dir="rtl"] .timeline-date,
html[dir="rtl"] .edu-meta,
html[dir="rtl"] .contact-label { font-family: var(--font-body-ar); }

.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: 24px;
}

h1, h2, h3 { font-family: var(--font-display); font-weight: 600; margin: 0; letter-spacing: -0.01em; }
p { margin: 0; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

/* hidden via clip rather than an off-screen offset, which would create
   thousands of pixels of scrollable overflow once dir="rtl" is applied */
.skip-link {
  position: absolute; top: 0; left: 0;
  width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  background: var(--accent); color: var(--accent-contrast);
  padding: 12px 20px; border-radius: var(--radius-sm); z-index: 1000;
}
.skip-link:focus {
  width: auto; height: auto; overflow: visible;
  clip: auto; clip-path: none;
  inset-inline-start: 24px; top: 24px;
}

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

/* Texture + progress + cursor ---------------------------------------- */

.noise-overlay {
  position: fixed; inset: 0; pointer-events: none; z-index: 2;
  opacity: .035; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* inset-inline-start, not left: the bar tracks reading progress, so in
   Arabic it has to grow from the right edge like the text it measures */
.progress-bar {
  position: fixed; top: 0; inset-inline-start: 0; height: 3px; width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  z-index: 1000; transition: width .12s linear;
  box-shadow: 0 0 12px var(--accent);
}

.cursor-glow {
  position: fixed; width: 420px; height: 420px; border-radius: 50%;
  pointer-events: none; z-index: 1;
  background: radial-gradient(circle, var(--accent-soft) 0%, transparent 70%);
  transform: translate(-50%, -50%);
  opacity: 0; transition: opacity .4s ease;
  will-change: transform;
}
@media (hover: hover) and (pointer: fine) {
  .cursor-glow.active { opacity: 1; }
}
@media (hover: none), (pointer: coarse), (prefers-reduced-motion: reduce) {
  .cursor-glow { display: none; }
}

/* Header --------------------------------------------------------------- */

.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  padding: 18px 0;
  transition: background-color .4s var(--ease-out), backdrop-filter .4s var(--ease-out), box-shadow .4s var(--ease-out), padding .3s var(--ease-out);
}
.site-header.scrolled {
  padding: 12px 0;
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter: blur(14px) saturate(140%);
  box-shadow: 0 1px 0 var(--border), 0 12px 30px -20px hsl(var(--shadow-color) / .6);
}

.nav {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: 24px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px;
}

.brand {
  display: inline-flex; align-items: center;
  color: var(--text);
}
/* The lockup is traced artwork — ~80KB of path data — so it is delivered as two
   mask layers rather than inlined. Each layer is painted by a background colour
   the theme already owns, which is what keeps it on-theme without duplicating
   the artwork per theme: letterforms take the text colour, harakat and the
   English name take the accent, exactly the reference's two-colour split. */
.brand-logo {
  position: relative; display: block; flex-shrink: 0;
  height: 54px; width: 65px;            /* traced lockup is 1.20 : 1 */
  transition: transform .5s var(--ease-spring);
}
.brand-logo::before,
.brand-logo::after {
  content: ""; position: absolute; inset: 0;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;   /* same viewBox = registered */
}
.brand-logo::before {
  background: currentColor;
  -webkit-mask-image: url(../img/logo-ink.svg); mask-image: url(../img/logo-ink.svg);
}
.brand-logo::after {
  background: var(--accent);
  -webkit-mask-image: url(../img/logo-mark.svg); mask-image: url(../img/logo-mark.svg);
}
.brand:hover .brand-logo { transform: translateY(-2px) scale(1.04); }

.nav-links { display: flex; gap: 32px; }
.nav-link {
  position: relative; font-size: .92rem; font-weight: 500; color: var(--text-muted);
  padding: 6px 2px; transition: color .25s ease;
}
.nav-link::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 0; height: 2px;
  background: var(--accent); transition: right .3s var(--ease-out);
  border-radius: 2px;
}
.nav-link:hover, .nav-link.active { color: var(--text); }
.nav-link:hover::after, .nav-link.active::after { right: 0; }

/* One height for every control in the bar. Each of these used to be sized by
   its own content — the chip by its dot, the language button by its icon,
   the switch and the burger by hard-coded pixels — which put four different
   heights (27 / 30 / 35 / 38px) in a row that reads as one unit. */
.nav-actions {
  position: relative; z-index: 101;
  display: flex; align-items: center; gap: 10px;
  --control-h: 38px;
}

.lang-toggle {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: var(--control-h);
  padding-inline: 13px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface-2);
  font-size: .8rem; font-weight: 600; color: var(--text-muted);
  transition: border-color .3s ease, color .3s ease, transform .3s var(--ease-spring);
}
.lang-toggle .icon { width: 15px; height: 15px; }
.lang-toggle:hover { color: var(--accent); border-color: var(--accent); transform: translateY(-2px); }

/* Sized off --control-h so the switch always matches its neighbours. The
   track carries exactly two thumb-widths of content, which is what makes
   `space-around` drop each icon on a thumb position: at rest the thumb
   centre is pad + thumb/2 and so is the sun's; after travelling one thumb
   width both are pad + 3·thumb/2. That identity holds at any height, so the
   alignment cannot drift when --control-h changes. */
.theme-toggle-track {
  --pad: 4px;
  --thumb: calc(var(--control-h) - 2px - (2 * var(--pad)));   /* 2px = the borders */
  position: relative; display: flex; align-items: center; justify-content: space-around;
  width: calc((2 * var(--thumb)) + (2 * var(--pad)) + 2px);
  height: var(--control-h);
  border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border-strong);
  padding: var(--pad);
  /* The switch is a control, not language content. Pinning it to LTR keeps the
     sun on the left and the moon on the right in both directions, so the
     thumb's physical offset below always lands on the icon it means to. */
  direction: ltr;
}
.theme-toggle-thumb {
  position: absolute; top: var(--pad); left: var(--pad);
  width: var(--thumb); height: var(--thumb); border-radius: 50%;
  background: linear-gradient(145deg, var(--accent-2), var(--accent));
  transition: transform .4s var(--ease-spring);
  box-shadow: 0 2px 6px rgba(0,0,0,.25);
}
/* thumb sits over the icon matching the ACTIVE theme: sun = light, moon = dark */
[data-theme="dark"] .theme-toggle-thumb { transform: translateX(var(--thumb)); }
[data-theme="light"] .theme-toggle-thumb { transform: translateX(0); }
.theme-toggle .icon {
  width: 15px; height: 15px; color: var(--text-dim); position: relative; z-index: 1;
  transition: color .3s ease, opacity .3s ease;
}
/* the active icon rides on the emerald thumb, so it goes light to read against
   it; the inactive one stays dim on the track */
[data-theme="dark"] .icon-moon,
[data-theme="light"] .icon-sun { color: #f4fbf8; opacity: 1; }
[data-theme="dark"] .icon-sun,
[data-theme="light"] .icon-moon { opacity: .5; }

.menu-toggle {
  display: none; flex-direction: column; justify-content: center; gap: 5px;
  width: var(--control-h); height: var(--control-h);
}
.menu-toggle span {
  display: block; width: 20px; height: 2px; background: var(--text);
  margin-inline: auto; transition: transform .3s var(--ease-out), opacity .3s ease;
}
.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Hero ------------------------------------------------------------------ */

.hero {
  position: relative;
  min-height: 100svh;
  display: flex; align-items: center;
  overflow: hidden;
  isolation: isolate;
}

.hero-canvas { position: absolute; inset: 0; z-index: -2; opacity: .85; }

.hero-grid {
  position: absolute; inset: -1px; z-index: -3;
  background-image:
    linear-gradient(var(--border) 1px, transparent 1px),
    linear-gradient(90deg, var(--border) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(ellipse 70% 60% at 50% 30%, black 10%, transparent 75%);
}
/* The lattice canvas draws its own grid; running both doubles every line.
   The static backdrop stays for reduced-motion visitors, who get no canvas. */
.lattice-on .hero-grid { display: none; }

.hero-blob {
  position: absolute; z-index: -3; border-radius: 50%;
  filter: blur(90px); opacity: .5;
  animation: float 16s ease-in-out infinite;
}
.blob-a {
  width: 480px; height: 480px; top: -160px; right: -120px;
  background: radial-gradient(circle, var(--accent) 0%, transparent 70%);
}
.blob-b {
  width: 380px; height: 380px; bottom: -140px; left: -100px;
  background: radial-gradient(circle, var(--accent-2) 0%, transparent 70%);
  animation-delay: -8s; animation-direction: reverse;
}
@keyframes float {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(-30px, 40px) scale(1.08); }
}

.hero-inner { padding-block: 140px 100px; width: 100%; }

.hero-eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-mono); font-size: .78rem; letter-spacing: .03em;
  color: var(--text-muted);
  padding: 7px 14px 7px 10px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface);
  margin-bottom: 28px;
}
.status-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 0 var(--accent-soft);
  animation: pulse 2.2s ease-out infinite;
}
/* keyed off --accent rather than the emerald literal: every variant
   redefines that token, and a hardcoded green would ring the status dot in
   the wrong colour in three of the four */
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  70% { box-shadow: 0 0 0 9px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

.hero-name {
  font-size: clamp(3rem, 9vw, 6.4rem);
  line-height: .96;
  margin-bottom: 28px;
}
.split-line { display: block; overflow: hidden; }
.split-line span { display: inline-block; }
.accent-text { color: var(--accent); font-style: italic; }

.hero-role {
  font-family: var(--font-mono);
  font-size: clamp(1.05rem, 2.2vw, 1.4rem);
  color: var(--text);
  min-height: 1.6em;
  margin-bottom: 18px;
}
.caret {
  display: inline-block; width: 2px; height: 1em; background: var(--accent);
  margin-left: 3px; vertical-align: -2px;
  animation: blink 1s step-end infinite;
}
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }

.hero-meta { color: var(--text-muted); font-size: 1rem; margin-bottom: 42px; }

.hero-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; }

/* One height for the whole CTA row. The text buttons were 49px and the icon
   buttons 44px, because each was sized by its own padding and content — a
   5px step that reads as sloppiness when they sit side by side. */
.hero-cta { --btn-h: 48px; }

.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  height: var(--btn-h);
  padding-inline: 24px; border-radius: 999px;
  font-weight: 600; font-size: .94rem; white-space: nowrap;
  transition: transform .35s var(--ease-spring), box-shadow .35s ease, background-color .3s ease, border-color .3s ease, color .3s ease;
}
.btn svg { width: 17px; height: 17px; transition: transform .3s var(--ease-out); }
.btn-primary {
  background: linear-gradient(135deg, var(--accent-2), var(--accent));
  color: var(--accent-contrast);
  box-shadow: 0 10px 30px -12px color-mix(in srgb, var(--accent) 55%, transparent);
}
.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 34px -12px color-mix(in srgb, var(--accent) 70%, transparent);
}
.btn-primary:hover svg { transform: translateX(3px); }

.btn-ghost { border: 1px solid var(--border-strong); color: var(--text); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-2px); }

.btn-icon {
  width: var(--btn-h); padding-inline: 0;      /* square, same height as the rest */
  border: 1px solid var(--border-strong); border-radius: 50%;
}
.btn-icon svg { width: 18px; height: 18px; }
.btn-icon:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-2px) rotate(-6deg); }

.scroll-cue {
  position: absolute; bottom: 36px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  color: var(--text-dim); font-family: var(--font-mono); font-size: .72rem;
  letter-spacing: .1em; text-transform: uppercase;
}
.scroll-cue-line {
  width: 1px; height: 40px; background: linear-gradient(var(--text-dim), transparent);
  position: relative; overflow: hidden;
}
.scroll-cue-line::after {
  content: ""; position: absolute; top: -100%; left: 0; width: 100%; height: 100%;
  background: linear-gradient(var(--accent), transparent);
  animation: scrollcue 2s ease-in-out infinite;
}
@keyframes scrollcue { 0% { top: -100%; } 100% { top: 100%; } }

/* Sections --------------------------------------------------------------- */

.section { padding-block: 120px; position: relative; }
.section-alt { background: var(--bg-alt); }

.section-kicker {
  font-family: var(--font-mono); font-size: .82rem; letter-spacing: .08em;
  color: var(--accent); margin-bottom: 18px; text-transform: uppercase;
}
.section-title {
  font-size: clamp(1.9rem, 3.6vw, 2.9rem); line-height: 1.15; max-width: 720px;
  margin-bottom: 56px;
}

/* Reveal-on-scroll --------------------------------------------------------- */

.reveal {
  opacity: 0; transform: translateY(28px);
  transition: opacity .8s var(--ease-out), transform .8s var(--ease-out);
  transition-delay: calc(var(--d, 0) * 90ms);
}
.reveal.is-visible { opacity: 1; transform: translateY(0); }

/* About -------------------------------------------------------------------- */

.about-grid {
  display: grid; grid-template-columns: 1.5fr 1fr; gap: 56px;
  margin-bottom: 72px;
}
.about-copy { font-size: 1.15rem; color: var(--text-muted); max-width: 60ch; }
.about-copy strong { color: var(--text); font-weight: 600; }

.about-facts { display: grid; gap: 18px; align-content: start; }
.about-facts > div {
  display: flex; justify-content: space-between; gap: 16px;
  padding-bottom: 16px; border-bottom: 1px solid var(--border);
}
.about-facts dt { color: var(--text-dim); font-size: .85rem; }
.about-facts dd { margin: 0; font-weight: 600; text-align: end; }

.stat-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px;
}
.stat-card {
  padding: 30px 24px; border-radius: var(--radius-md);
  background: var(--surface); border: 1px solid var(--border);
  transition: transform .35s var(--ease-spring), border-color .35s ease, box-shadow .35s ease;
}
.stat-card:hover {
  transform: translateY(-6px);
  border-color: var(--border-strong);
  box-shadow: 0 20px 40px -24px hsl(var(--shadow-color) / .5);
}
.stat-number {
  display: block; font-family: var(--font-display); font-weight: 700;
  font-size: 2.6rem; color: var(--accent); line-height: 1;
  margin-bottom: 10px;
}
.stat-label { color: var(--text-muted); font-size: .9rem; }

/* Timeline ------------------------------------------------------------------ */

.timeline { position: relative; max-width: 860px; }
.timeline::before {
  content: ""; position: absolute; left: 9px; top: 10px; bottom: 10px; width: 2px;
  background: linear-gradient(var(--border-strong), var(--border) 90%);
}
.timeline-item { position: relative; padding-left: 44px; margin-bottom: 40px; }
.timeline-item:last-child { margin-bottom: 0; }

.timeline-marker {
  position: absolute; left: 0; top: 6px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--accent);
  display: grid; place-items: center;
}
.timeline-marker::after {
  content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--accent);
}

.timeline-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: 28px 30px;
  transition: transform .35s var(--ease-spring), border-color .3s ease, box-shadow .35s ease;
}
.timeline-card:hover {
  transform: translateX(6px);
  border-color: var(--border-strong);
  box-shadow: 0 20px 40px -28px hsl(var(--shadow-color) / .55);
}
.timeline-head {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline;
  gap: 10px; margin-bottom: 6px;
}
.timeline-head h3 { font-size: 1.25rem; }
.timeline-date {
  font-family: var(--font-mono); font-size: .78rem; color: var(--accent);
  white-space: nowrap;
}
.timeline-org { color: var(--text-muted); font-weight: 500; margin-bottom: 16px; }
.timeline-org .dim { color: var(--text-dim); font-weight: 400; }
.timeline-card ul { display: grid; gap: 10px; }
.timeline-card li {
  position: relative; padding-left: 20px; color: var(--text-muted); font-size: .96rem;
}
.timeline-card li::before {
  content: ""; position: absolute; left: 0; top: .6em; width: 6px; height: 6px;
  border-radius: 1px; background: var(--accent); transform: rotate(45deg);
}
.timeline-card li strong { color: var(--text); }

/* Skills ------------------------------------------------------------------- */

.skills-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;
}
.skill-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: 28px;
  transition: transform .35s var(--ease-spring), border-color .3s ease;
}
.skill-card:hover { transform: translateY(-5px); border-color: var(--border-strong); }
.skill-card h3 { font-size: 1.05rem; margin-bottom: 18px; color: var(--text); }
.tag-cloud { display: flex; flex-wrap: wrap; gap: 9px; }
.tag {
  font-size: .82rem; font-weight: 500; padding: 7px 13px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); border: 1px solid transparent;
  transition: transform .25s var(--ease-spring), background-color .25s ease, border-color .25s ease;
}
.tag:hover {
  transform: translateY(-3px) scale(1.04);
  border-color: var(--accent);
}


/* Portfolio ------------------------------------------------------------------ */

.portfolio-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px;
}
.work-card {
  position: relative; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); overflow: hidden;
  transition: transform .35s var(--ease-spring), border-color .3s ease, box-shadow .35s ease;
}
.work-card:hover {
  transform: translateY(-5px); border-color: var(--accent);
  box-shadow: 0 22px 44px -28px hsl(var(--shadow-color) / .55);
}

/* The thumbnail is a designed tile by default and a screenshot when one exists.
   The monogram sits underneath; a loaded image simply covers it, so a missing
   file degrades to something deliberate instead of a broken-image icon. */
.work-thumb {
  position: relative; display: block; aspect-ratio: 5 / 2; overflow: hidden;
  background:
    radial-gradient(120% 140% at 15% 0%, hsl(var(--work-hue) 55% 42% / .55) 0%, transparent 60%),
    linear-gradient(135deg, hsl(var(--work-hue) 45% 20%) 0%, hsl(var(--work-hue) 40% 11%) 100%);
  border-bottom: 1px solid var(--border);
}
[data-theme="light"] .work-thumb {
  background:
    radial-gradient(120% 140% at 15% 0%, hsl(var(--work-hue) 50% 72% / .6) 0%, transparent 60%),
    linear-gradient(135deg, hsl(var(--work-hue) 40% 88%) 0%, hsl(var(--work-hue) 35% 80%) 100%);
}
.work-thumb::after {
  content: attr(data-mark);
  position: absolute; inset: 0; display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 700; font-size: 1.35rem;
  letter-spacing: .02em; color: hsl(var(--work-hue) 60% 88%);
  text-shadow: 0 2px 14px hsl(var(--work-hue) 60% 8% / .5);
}
[data-theme="light"] .work-thumb::after { color: hsl(var(--work-hue) 55% 22%); }
.work-thumb img {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; object-fit: cover; object-position: top center;
}
/* main.js strips images that fail to load, exposing the monogram tile */

.work-body { display: flex; flex-direction: column; gap: 4px; padding: 13px 15px 15px; }
.work-title { font-family: var(--font-display); font-weight: 600; font-size: .96rem; line-height: 1.25; }
.work-domain {
  font-family: var(--font-mono); font-size: .74rem; color: var(--accent);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* clamp so one long blurb cannot make its row taller than the others */
.work-desc {
  color: var(--text-muted); font-size: .84rem; line-height: 1.45;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; overflow: hidden;
}
.work-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.work-tags span {
  font-size: .68rem; font-weight: 500; padding: 3px 8px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent);
}
.work-go {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  width: 26px; height: 26px; display: grid; place-items: center;
  border-radius: 50%; font-size: .82rem;
  background: color-mix(in srgb, var(--bg) 70%, transparent);
  color: var(--accent); opacity: 0; transform: translateY(-4px);
  transition: opacity .25s ease, transform .25s ease;
}
.work-card:hover .work-go { opacity: 1; transform: translateY(0); }
.work-card-static { cursor: default; }
.work-card-static:hover { transform: none; border-color: var(--border); box-shadow: none; }

html[dir="rtl"] .work-go { right: auto; left: 12px; }

@media (max-width: 980px) { .portfolio-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .portfolio-grid { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------------------
   Portfolio spotlight — index + case-study viewer, desktop only.
   Every rule is gated on .pf-on, the class script adds after building the
   index: without JS the .pf wrapper is inert and the grid above renders
   exactly as it always did.
------------------------------------------------------------------------ */
/* hidden everywhere by default: narrow viewports and no-JS use the grid,
   and only the desktop spotlight block below ever shows the index */
.pf-index { display: none; }

@media (min-width: 981px) {
  .pf.pf-on {
    display: grid;
    grid-template-columns: minmax(290px, 350px) 1fr;
    gap: 30px;
    align-items: start;
  }
  .pf.pf-on .portfolio-grid { display: block; }
  .pf.pf-on .work-card { display: none; }
  .pf.pf-on .work-card.is-active { display: flex; }

  .pf.pf-on .pf-index { display: flex; flex-direction: column; }
  .pf-row {
    position: relative;
    display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto;
    column-gap: 14px; row-gap: 2px;
    padding: 13px 16px;
    background: none; border: 0;
    border-inline-start: 2px solid var(--border);
    text-align: start; cursor: pointer;
    color: var(--text-muted);
    transition: color .25s ease, border-color .25s ease, background .25s ease;
  }
  .pf-row:hover { color: var(--text); background: var(--surface); }
  .pf-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  .pf-row[aria-selected="true"] {
    color: var(--text);
    background: var(--surface);
    border-inline-start-color: var(--accent);
  }
  .pf-num {
    grid-row: 1 / span 2; align-self: center;
    font-family: var(--font-mono); font-size: .78rem;
    color: var(--text-muted);
  }
  .pf-row[aria-selected="true"] .pf-num { color: var(--accent); }
  .pf-t { font-family: var(--font-display); font-weight: 600; font-size: .98rem; line-height: 1.25; }
  .pf-d {
    font-family: var(--font-mono); font-size: .72rem; color: var(--text-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* auto-advance keyline: fills over one cycle, gone after first interaction.
     Re-selecting re-matches the selector, which is what restarts the fill. */
  .pf.pf-on:not(.pf-engaged) .pf-row[aria-selected="true"]::after {
    content: "";
    position: absolute; inset-inline-start: 0; bottom: 0;
    height: 1px; width: 100%;
    background: var(--accent);
    transform-origin: 0 50%;
    animation: pfProgress 6.5s linear both; /* keep in step with PF_CYCLE */
  }
  html[dir="rtl"] .pf.pf-on:not(.pf-engaged) .pf-row[aria-selected="true"]::after {
    transform-origin: 100% 50%;
  }

  /* the card on stage grows from grid tile to case study */
  .pf.pf-on .work-card.is-active .work-body { padding: 18px 22px 22px; gap: 6px; }
  .pf.pf-on .work-card.is-active .work-title { font-size: 1.3rem; }
  .pf.pf-on .work-card.is-active .work-domain { font-size: .8rem; }
  .pf.pf-on .work-card.is-active .work-desc {
    font-size: .95rem; line-height: 1.6; -webkit-line-clamp: unset; display: block;
  }
  .pf.pf-on .work-card.is-active .work-tags span { font-size: .74rem; padding: 4px 10px; }
  .pf.pf-on .work-card.pf-enter { animation: pfEnter .5s cubic-bezier(.22, .8, .3, 1) both; }
  .pf.pf-on .work-card.is-active .work-thumb img {
    animation: pfDrift 14s ease-in-out infinite alternate;
  }
}

@keyframes pfProgress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes pfEnter {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes pfDrift {
  from { transform: scale(1); }
  to { transform: scale(1.045); }
}

/* Education ------------------------------------------------------------------ */

.edu-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.edu-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: 30px;
  transition: transform .35s var(--ease-spring), border-color .3s ease, box-shadow .35s ease;
}
.edu-card:hover {
  transform: translateY(-6px);
  border-color: var(--border-strong);
  box-shadow: 0 20px 40px -28px hsl(var(--shadow-color) / .5);
}
.edu-icon {
  display: inline-grid; place-items: center; width: 46px; height: 46px;
  border-radius: 50%; background: var(--accent-soft); color: var(--accent);
  margin-bottom: 20px;
}
.edu-icon svg { width: 22px; height: 22px; }
.edu-card h3 { font-size: 1.08rem; margin-bottom: 8px; line-height: 1.35; }
.edu-sub { color: var(--text-muted); font-size: .92rem; margin-bottom: 10px; }
.edu-meta { font-family: var(--font-mono); font-size: .8rem; color: var(--text-dim); }

/* Contact --------------------------------------------------------------------- */

.contact-section { overflow: hidden; }
.contact-intro { color: var(--text-muted); max-width: 62ch; margin-bottom: 48px; font-size: 1.05rem; }

.contact-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }

.contact-card {
  position: relative;
  display: flex; align-items: center; gap: 18px;
  padding: 22px 24px; text-align: start; width: 100%;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md);
  transition: transform .35s var(--ease-spring), border-color .3s ease, box-shadow .35s ease;
  overflow: hidden;
}
.contact-card::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(120deg, transparent, var(--accent-soft), transparent);
  transform: translateX(-120%);
  transition: transform .6s var(--ease-out);
}
.contact-card:hover::before { transform: translateX(120%); }
.contact-card:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
  box-shadow: 0 20px 40px -28px hsl(var(--shadow-color) / .55);
}
.contact-icon {
  position: relative; z-index: 1;
  flex-shrink: 0; display: grid; place-items: center;
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
}
.contact-icon svg { width: 20px; height: 20px; }
.contact-body { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.contact-label { font-family: var(--font-mono); font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; color: var(--text-dim); }
.contact-value { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.contact-copy-hint {
  position: relative; z-index: 1; margin-left: auto; flex-shrink: 0;
  font-size: .78rem; font-weight: 600; color: var(--accent);
  opacity: 0; transform: translateX(-6px);
  transition: opacity .25s ease, transform .25s ease;
}
.contact-card:hover .contact-copy-hint { opacity: 1; transform: translateX(0); }
.contact-card.copied { border-color: var(--accent); }
.contact-card.copied .contact-copy-hint { opacity: 1; transform: translateX(0); }

/* Footer ------------------------------------------------------------------------ */

.site-footer { padding-block: 36px; border-top: 1px solid var(--border); }
.footer-inner { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.footer-inner p { color: var(--text-dim); font-size: .88rem; }
/* Visibility lives here rather than in inline styles written on every
   scroll tick. The old code assigned `style.transition = "opacity .3s"`,
   which REPLACED this declaration wholesale — so the hover lift and colour
   change had no transition at all and snapped. It also left the button
   painted at full opacity until the first scroll event ran. */
.to-top {
  width: 42px; height: 42px; border-radius: 50%; border: 1px solid var(--border-strong);
  display: grid; place-items: center;
  opacity: 0; pointer-events: none;
  transition: opacity .3s ease, transform .3s var(--ease-spring), border-color .3s ease, color .3s ease;
}
.to-top.is-visible { opacity: 1; pointer-events: auto; }
.to-top svg { width: 18px; height: 18px; }
.to-top:hover { transform: translateY(-4px); border-color: var(--accent); color: var(--accent); }

/* Toast --------------------------------------------------------------------------- */

.toast {
  position: fixed; left: 50%; bottom: 32px; transform: translate(-50%, 20px);
  background: var(--text); color: var(--bg);
  padding: 13px 22px; border-radius: 999px; font-size: .88rem; font-weight: 600;
  opacity: 0; pointer-events: none; z-index: 1200;
  transition: opacity .3s var(--ease-out), transform .3s var(--ease-out);
  box-shadow: 0 14px 30px -10px rgba(0,0,0,.4);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ==========================================================================
   Variant chrome — the chip and the ⌘K palette.

   Deliberately built from the same semantic tokens as everything else
   (--surface, --border-strong, --accent…). Each variant redefines those
   tokens, so the switcher restyles itself into every variant without a
   single variant-specific rule here.
   ========================================================================== */

.variant-chip {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: var(--control-h);
  padding-inline: 11px 10px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface-2);
  font-size: .8rem; font-weight: 600; color: var(--text-muted);
  transition: border-color .3s ease, color .3s ease, transform .3s var(--ease-spring);
}
.variant-chip:hover { color: var(--accent); border-color: var(--accent); transform: translateY(-2px); }
/* an author `display` outranks the UA rule for [hidden], so the chip needs
   this or it flashes into the header before script reveals it */
.variant-chip[hidden] { display: none; }
.variant-chip-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
  flex-shrink: 0;
}
.variant-chip-name { white-space: nowrap; }
.variant-chip-key {
  font-family: var(--font-mono); font-size: .68rem; line-height: 1;
  padding: 3px 5px; border-radius: 5px;
  border: 1px solid var(--border-strong); color: var(--text-dim);
  /* a keycap is a glyph, not prose: it must not reorder in Arabic */
  direction: ltr;
}
/* the shortcut is meaningless without a hardware keyboard */
@media (hover: none), (pointer: coarse) { .variant-chip-key { display: none; } }

/* Palette ------------------------------------------------------------------ */

.cmdk {
  position: fixed; inset: 0; z-index: 1500;
  display: grid; place-items: start center;
  padding: clamp(16px, 12vh, 140px) 16px 16px;
}
.cmdk[hidden] { display: none; }
.cmdk-scrim {
  position: absolute; inset: 0;
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  backdrop-filter: blur(6px);
  animation: cmdkFade .18s var(--ease-out) both;
}
.cmdk-panel {
  position: relative; width: min(560px, 100%);
  display: flex; flex-direction: column;
  /* dvh, not vh: when the software keyboard opens it takes the bottom of
     the screen but not a single vh unit with it, so a vh-sized panel would
     run underneath it. The vh line stays as the fallback. */
  max-height: min(560px, 76vh);
  max-height: min(560px, 76dvh);
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius-md); overflow: hidden;
  box-shadow: 0 40px 80px -30px hsl(var(--shadow-color) / .7);
  animation: cmdkRise .22s var(--ease-out) both;
}
.cmdk-panel:focus-visible { outline: none; }   /* it only takes focus to host the trap */
@keyframes cmdkFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes cmdkRise {
  from { opacity: 0; transform: translateY(-10px) scale(.985); }
  to { opacity: 1; transform: none; }
}

.cmdk-field { display: flex; align-items: center; gap: 11px; padding: 15px 18px; border-bottom: 1px solid var(--border); }
.cmdk-field svg { width: 17px; height: 17px; color: var(--text-dim); flex-shrink: 0; }
.cmdk-input {
  flex: 1; min-width: 0; font: inherit; font-size: .98rem;
  background: none; border: 0; color: var(--text); padding: 0;
}
.cmdk-input:focus { outline: none; }
.cmdk-input::placeholder { color: var(--text-dim); }

.cmdk-list { overflow-y: auto; padding: 8px; overscroll-behavior: contain; }
.cmdk-group {
  font-family: var(--font-mono); font-size: .68rem; letter-spacing: .09em;
  text-transform: uppercase; color: var(--text-dim);
  padding: 12px 12px 6px;
}
.cmdk-item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 10px 12px; border-radius: var(--radius-sm);
  text-align: start; color: var(--text-muted);
  transition: background-color .15s ease, color .15s ease;
}
.cmdk-item:hover { color: var(--text); }
/* selection is driven by the roving index, not :hover — a stray pointer
   resting over the list must not fight the arrow keys for what Enter runs */
.cmdk-item[aria-selected="true"] { background: var(--accent-soft); color: var(--text); }
.cmdk-glyph {
  flex-shrink: 0; display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: .8rem; color: var(--accent);
}
.cmdk-glyph svg { width: 15px; height: 15px; }   /* matches the header switch */
.cmdk-item[aria-selected="true"] .cmdk-glyph { border-color: var(--accent); }
.cmdk-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cmdk-label { font-size: .92rem; font-weight: 600; }
.cmdk-hint { font-size: .76rem; color: var(--text-dim); }
.cmdk-badge {
  margin-inline-start: auto; flex-shrink: 0;
  font-family: var(--font-mono); font-size: .68rem; color: var(--accent);
  padding: 3px 7px; border-radius: 999px; background: var(--accent-soft);
}
.cmdk-empty { padding: 26px 14px; text-align: center; color: var(--text-dim); font-size: .9rem; }

.cmdk-foot {
  display: flex; flex-wrap: wrap; gap: 14px;
  padding: 11px 18px; border-top: 1px solid var(--border);
  font-size: .74rem; color: var(--text-dim);
}
.cmdk-foot kbd {
  font-family: var(--font-mono); font-size: .7rem;
  padding: 2px 5px; border-radius: 4px;
  border: 1px solid var(--border-strong); color: var(--text-muted);
  direction: ltr;
}

/* Phones: sit the panel near the top so the keyboard has somewhere to go,
   give the rows a thumb-sized target, and drop the keycap legend, which
   means nothing without keys and costs the list ~45px.
   Must come after .cmdk-foot's own `display`, or it loses the tie. */
@media (max-width: 640px) {
  .cmdk { padding: 12px; }
  .cmdk-item { padding: 13px 12px; }
  .cmdk-foot { display: none; }
}

/* The swap itself. Only the root gets a transition: naming sub-elements as
   view-transition targets would ask the browser to tween between two totally
   different layouts, which reliably looks worse than a clean cross-fade. */
::view-transition-old(root),
::view-transition-new(root) { animation-duration: .32s; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; }
}

/* RTL (Arabic) overrides --------------------------------------------------------------- */

html[dir="rtl"] .timeline::before { left: auto; right: 9px; }
html[dir="rtl"] .timeline-marker { left: auto; right: 0; }
html[dir="rtl"] .timeline-item { padding-left: 0; padding-right: 44px; }
html[dir="rtl"] .timeline-card:hover { transform: translateX(-6px); }
html[dir="rtl"] .timeline-card li { padding-left: 0; padding-right: 20px; }
html[dir="rtl"] .timeline-card li::before { left: auto; right: 0; }

/* emails, URLs and phone numbers are LTR data — bidi would reorder the digits */
html[dir="rtl"] .contact-value { direction: ltr; text-align: right; }

html[dir="rtl"] .contact-copy-hint { margin-left: 0; margin-right: auto; }
html[dir="rtl"] .contact-card:hover .contact-copy-hint,
html[dir="rtl"] .contact-card.copied .contact-copy-hint { transform: translateX(6px); }

/* In Arabic the hero name is Arabic too, so it takes the document's own
   direction — forcing LTR here would fight the script. It only needs to sit
   against the RTL edge. */
html[dir="rtl"] .hero-name,
html[dir="rtl"] .split-line { text-align: right; }

/* mirror only the directional arrow, never the brand logos */
html[dir="rtl"] .btn-primary svg { transform: scaleX(-1); }
html[dir="rtl"] .btn-primary:hover svg { transform: scaleX(-1) translateX(3px); }

html[dir="rtl"] .scroll-cue { letter-spacing: 0; }
html[dir="rtl"] .scroll-cue-text { text-transform: none; }


/* Responsive ------------------------------------------------------------------------ */

@media (max-width: 980px) {
  .about-grid { grid-template-columns: 1fr; gap: 32px; }
  .skills-grid { grid-template-columns: repeat(2, 1fr); }
  .edu-grid { grid-template-columns: repeat(2, 1fr); }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .contact-grid { grid-template-columns: 1fr; }
}

@media (max-width: 760px) {
  .lg-only { display: none; }
  /* Roomier targets for thumbs, and every control still one height. */
  .nav-actions { --control-h: 42px; }
  .lang-toggle span { display: none; }
  /* the header runs out of room before the chip does: keep the dot as the
     tap target and let the palette itself name the active variant */
  .variant-chip-name { display: none; }
  /* with their labels gone these two are icon-only, so they go square
     rather than keeping label-width padding */
  .lang-toggle, .variant-chip { width: var(--control-h); padding-inline: 0; }
  .nav-links {
    position: fixed; top: 0; right: 0; height: 100vh; width: min(78vw, 320px);
    background: var(--bg); border-left: 1px solid var(--border);
    flex-direction: column; justify-content: center; align-items: flex-start;
    gap: 28px; padding-inline: 40px;
    transform: translateX(100%); transition: transform .4s var(--ease-out);
    z-index: 99;
  }
  .nav-links.open { transform: translateX(0); }
  html[dir="rtl"] .nav-links {
    right: auto; left: 0;
    border-left: none; border-right: 1px solid var(--border);
    transform: translateX(-100%);
  }
  html[dir="rtl"] .nav-links.open { transform: translateX(0); }
  .nav-link { font-size: 1.2rem; }
  .menu-toggle { display: flex; }
  .skills-grid, .edu-grid { grid-template-columns: 1fr; }
  .section { padding-block: 84px; }
  .hero-inner { padding-block: 120px 80px; }
  .timeline-head { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 520px) {
  .stat-grid { grid-template-columns: 1fr 1fr; }
  /* `flex: 1 1 auto` let the labelled buttons grow to fill whatever space a
     row had left, so they wrapped into ragged pairs and stranded one icon
     button on a line of its own. A row each for the labelled buttons, and
     the icons together on the last line, is the same set read as a list. */
  .hero-cta { gap: 10px; }
  .btn-primary, .btn-ghost { flex: 1 0 100%; }
  .btn-icon { flex: 0 0 auto; }
}

/* Print (clean, resume-friendly) --------------------------------------------------- */

.print-only { display: none; }

/* The page is a site on screen and a CV on paper. Printing it unchanged gave
   eight pages: the hero filled one on its own, dark tokens carried onto white,
   and the CTA row printed as dead UI. This block restructures it into an A4
   document off the same markup, so the PDF can never drift from the site. */
@media print {
  @page { size: A4; margin: 13mm 14mm; }

  /* The visitor may print from dark mode, so pin the light token set rather
     than trusting whichever theme happens to be active. */
  :root, [data-theme="dark"], [data-theme="light"] {
    --bg: #fff; --bg-alt: #fff; --surface: #fff; --surface-2: #fff;
    --border: #d5ded8; --border-strong: #b4c2ba;
    --text: #0f1a15; --text-muted: #39453e; --text-dim: #5b6862;
    --accent: #0a6b47; --accent-2: #0a6b47; --accent-soft: #eef5f1;
  }
  body { background: #fff !important; color: #0f1a15 !important; }

  /* chrome, decoration and anything interactive */
  .site-header, .site-footer, .hero-canvas, .hero-blob, .hero-grid,
  .noise-overlay, .cursor-glow, .progress-bar, .scroll-cue, .hero-eyebrow,
  .hero-cta, .theme-toggle, .lang-toggle, .menu-toggle, .to-top, .toast,
  .contact-copy-hint, .skip-link, .caret, #typedRole,
  .variant-chip, .cmdk { display: none !important; }
  .print-only { display: inline !important; }
  .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }

  /* Contact belongs near the top of a CV, not after the education history. */
  main { display: flex; flex-direction: column; }
  #top { order: -2; } #contact { order: -1; }

  .hero { min-height: 0; display: block; }
  .hero-inner { padding: 0 0 6px; }
  .hero-name { font-size: 30pt; line-height: 1.05; margin-bottom: 4px; }
  .hero-role { font-size: 11pt; margin-bottom: 2px; }
  .hero-meta { font-size: 9.5pt; margin-bottom: 0; }
  .container { padding-inline: 0; max-width: none; }

  .section { padding-block: 10px 4px; }
  /* the kickers are numbered 01–05 in DOM order, which the reorder above makes
     wrong, and numbered sections read oddly on a CV regardless */
  .section-kicker { display: none; }
  .section-title { font-size: 13pt; margin-bottom: 8px; max-width: none; }
  /* the contact details sit under the name and speak for themselves */
  #contact .section-title { display: none; }
  .lg-only { display: none; }

  /* cards become plain document blocks */
  .timeline-card, .skill-card, .edu-card, .contact-card, .stat-card {
    background: none !important; border: none !important; box-shadow: none !important;
    padding: 0 !important; transform: none !important;
  }
  .about-grid { display: block; }
  .about-copy { font-size: 10pt; max-width: none; margin-bottom: 8px; }
  .about-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 24px; }
  .about-facts > div { border-bottom: none; padding-bottom: 0; font-size: 9pt; }

  .stat-grid { display: none; }
  /* print never sees the spotlight: index gone, every card back in the grid.
     These outrank the desktop spotlight rules by source order, which matters
     when the paper is wide enough for the min-width query to match. */
  .pf.pf-on { display: block; }
  .pf.pf-on .pf-index { display: none; }
  .pf.pf-on .portfolio-grid { display: grid; }
  .pf.pf-on .work-card { display: flex; }
  .portfolio-grid { grid-template-columns: 1fr 1fr; gap: 6px 24px; }
  .work-card { break-inside: avoid; }
  .work-thumb, .work-go { display: none; }
  .work-body { padding: 0; gap: 1px; }
  .work-title { font-size: 10pt; }
  .work-domain { font-size: 8.5pt; }
  .work-desc { font-size: 9pt; }
  .work-tags { display: none; }              /* the figures are all in the prose */

  .timeline { max-width: none; }
  .timeline::before, .timeline-marker { display: none; }
  .timeline-item { padding-left: 0; margin-bottom: 9px; break-inside: avoid; }
  .timeline-head h3 { font-size: 11pt; }
  .timeline-date { font-size: 9pt; }
  .timeline-org { font-size: 9.5pt; margin-bottom: 3px; }
  .timeline-card li { font-size: 9.5pt; padding-left: 12px; margin: 0; }
  .timeline-card ul { gap: 2px; }

  .skills-grid { grid-template-columns: 1fr 1fr; gap: 6px 24px; }
  .skill-card { break-inside: avoid; }
  .skill-card h3 { font-size: 10pt; margin-bottom: 4px; }
  .tag { background: none !important; border: none !important; padding: 0 !important;
         font-size: 9.5pt; color: var(--text-muted) !important; }
  .tag:not(:last-child)::after { content: " ·"; color: var(--text-dim); }
  .tag-cloud { gap: 0 6px; }

  .edu-grid { grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
  .edu-card { break-inside: avoid; }
  .edu-icon { display: none; }
  .edu-card h3 { font-size: 10pt; }
  .edu-sub { font-size: 9pt; margin-bottom: 2px; }
  .edu-meta { font-size: 8.5pt; }

  .contact-intro { display: none; }
  .contact-grid { display: flex; flex-wrap: wrap; gap: 4px 18px; }
  .contact-card { width: auto; }
  .contact-icon { display: none; }
  .contact-label { display: none; }
  .contact-value { font-size: 9.5pt; }

  a { text-decoration: none; color: inherit; }
  h1, h2, h3 { break-after: avoid; }
}
