/* ════════════════════════════════════════════════
   Marino — cream and navy, Archivo + Chivo Mono
   Every color lives in :root (light mode) and is
   redefined in html.dark (dark mode). To adjust the
   palette, change only these variables.
   ════════════════════════════════════════════════ */

:root {
  /* Colors — light mode (contrast vs. --bg in parentheses) */
  --bg:          #F6F4EC;  /* cream background */
  --surface:     #FFFFFF;  /* cards */
  --text:        #121A30;  /* body text (15.7:1) */
  --text-muted:  #4B5468;  /* secondary text (6.9:1) */
  --border:      #DEDBD0;  /* borders and dividers (decorative) */
  --heading:     #1A2766;  /* navy headings (12.5:1) */
  --accent:      #1A2766;  /* primary button, links and focus */
  --accent-hover: #2B3C8F; /* primary button on hover */
  --on-accent:   #FFFFFF;  /* text on --accent (13.8:1) */
  --soft:        #E7EAF3;  /* soft background: chips, hero status pill, hover */
  --on-soft:     #1A2766;  /* text on --soft (11.4:1) */
  --status:      #1D7A4C;  /* "in progress" dot (graphic, 4.4:1 on --soft) */
  --dash:        color-mix(in srgb, var(--text-muted) 55%, transparent); /* dashed borders and dividers (decorative) */
  --line-faint:  color-mix(in srgb, var(--heading) 30%, transparent); /* link underline at rest */
  --cover-bg:    #1A2766;  /* text-only project cover */
  --cover-fg:    #F6F4EC;  /* name on --cover-bg (12.5:1) */
  --nav-bg:      rgb(246 244 236 / 0.88);
  --scrollbar-track: #F6F4EC; /* scrollbar: track (same as --bg) */
  --scrollbar-thumb: #A8ADBC; /* the draggable part */
  --scrollbar-hover: #1A2766; /* on hover: navy */

  /* Typography */
  --font-sans: 'Archivo', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'Chivo Mono', ui-monospace, 'Cascadia Mono', Consolas, monospace;

  /* Sizes */
  --container: 1040px;
  --gutter: clamp(20px, 5vw, 48px);
  --radius-card: 18px;
  --radius-img: 12px;
  --nav-height: 64px;
  --ease: 150ms ease;
  --ease-swift: cubic-bezier(0.65, 0, 0.35, 1);   /* fast in and out: fills, underlines */
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* slight bounce: icons */

  color-scheme: light;
}

html.dark {
  --bg:          #0E1530;  /* deep navy background */
  --surface:     #151E3D;
  --text:        #F4F1E8;  /* cream (15.9:1) */
  --text-muted:  #B0B7CB;  /* (9.0:1) */
  --border:      #28325A;
  --heading:     #F4F1E8;
  --accent:      #C3CEFF;  /* (11.6:1) */
  --accent-hover: #DDE3FF;
  --on-accent:   #0E1530;
  --soft:        #1F2A55;
  --on-soft:     #DDE3FF;  /* (10.9:1 on --soft) */
  --status:      #5FD39A;
  --cover-bg:    #1F2A55;
  --cover-fg:    #DDE3FF;  /* (10.9:1) */
  --nav-bg:      rgb(14 21 48 / 0.88);
  --scrollbar-track: #0E1530;
  --scrollbar-thumb: #3A4675;
  --scrollbar-hover: #C3CEFF;

  color-scheme: dark;
}

/* ── Base ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-height) + 16px);
  -webkit-text-size-adjust: 100%;
}

/* Spanish-speaking visitor: the page stays hidden until main.js translates it
   (see the script in <head>), so the English text doesn't flash first */
html.i18n-pending body { visibility: hidden; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img, svg { display: block; max-width: 100%; }
ul, ol { list-style: none; }
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

::selection { background: var(--accent); color: var(--on-accent); }

/* Scrollbar that matches the theme.
   Chrome, Edge and Safari use ::-webkit-scrollbar (which allows shape and border);
   Firefox doesn't support it and uses scrollbar-color. They're split with @supports
   because Chrome ignores ::-webkit-scrollbar whenever scrollbar-color is set. */
@supports not selector(::-webkit-scrollbar) {
  html {
    scrollbar-width: thin;
    scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
  }
}

::-webkit-scrollbar {
  width: 12px;
  height: 12px;
}

::-webkit-scrollbar-track,
::-webkit-scrollbar-corner { background: var(--scrollbar-track); }

::-webkit-scrollbar-thumb {
  border: 3px solid var(--scrollbar-track); /* leaves room around it so the thumb looks like it floats */
  border-radius: 999px;
  background: var(--scrollbar-thumb);
}

::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-hover); }

/* The focus outline follows each control's shape (rounded buttons,
   circular icons); only text links get an extra rounded corner */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

:where(.text-link, .nav-links a, .nav-mobile-menu a, .nav-logo):focus-visible { border-radius: 4px; }

.container {
  width: 100%;
  max-width: calc(var(--container) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ── Navigation ── */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--nav-bg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.nav {
  display: flex;
  align-items: center;
  gap: 28px;
  height: var(--nav-height);
}

.nav-logo {
  margin-right: auto;
  font-size: 1.05rem;
  font-weight: 800;
  font-stretch: 125%;
  letter-spacing: -0.01em;
  color: var(--heading);
  text-decoration: none;
}

.nav-links {
  display: flex;
  gap: 24px;
}

/* Menu links: the same solid line as .text-link, without the faint base line */
.nav-links a {
  padding-block: 4px;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  background: linear-gradient(currentColor, currentColor) no-repeat 100% 100% / 0 1.5px;
  transition: color 300ms var(--ease-swift), background-size 450ms var(--ease-swift);
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Language switcher: a 36px-tall segmented control (same as the icon buttons).
   The background pill slides to the active option; main.js sets data-active="en|es". */
.lang-switcher {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  height: 36px;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
}

.lang-switcher::before {
  content: "";
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: 3px;
  width: calc(50% - 3px);
  border-radius: 999px;
  background: var(--soft);
}

.lang-switcher[data-active="es"]::before { transform: translateX(100%); }

/* No animation on page load; main.js adds .is-ready after the first render */
.lang-switcher.is-ready::before { transition: transform 300ms var(--ease-swift); }

.lang-opt {
  position: relative; /* above the pill */
  padding-inline: 9px;
  border-radius: 999px;
  color: var(--text-muted);
  transition: color var(--ease);
}

.lang-opt.active { color: var(--on-soft); }

/* Icon buttons (theme and mobile menu): 36px circles */
.icon-btn {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--heading);
  transition: border-color var(--ease), background-color var(--ease), transform var(--ease);
}

.theme-icon--sun { display: none; }
html.dark .theme-icon--sun { display: block; }
html.dark .theme-icon--moon { display: none; }

.nav-hamburger {
  display: none;
  gap: 4px;
  align-content: center;
}

.nav-hamburger span {
  display: block;
  width: 16px;
  height: 1.5px;
  background: currentColor;
  transition: transform 300ms var(--ease-swift), opacity var(--ease);
}

.nav-hamburger.open span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.nav-hamburger.open span:nth-child(2) { opacity: 0; }
.nav-hamburger.open span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

.nav-mobile-menu {
  display: flex;
  flex-direction: column;
  padding: 8px var(--gutter) 16px;
  border-top: 1px solid var(--border);
  opacity: 0;
  transition: opacity var(--ease);
}

.nav-mobile-menu.open { opacity: 1; }
.nav-mobile-menu[hidden] { display: none; }

.nav-mobile-menu a {
  padding: 12px 0;
  font-size: 1rem;
  font-weight: 600;
  font-stretch: 110%;
  color: var(--heading);
  text-decoration: none;
  border-bottom: 1px solid var(--border);
  transition: color var(--ease);
}

.nav-mobile-menu a:last-child { border-bottom: 0; }

@media (max-width: 760px) {
  .nav-links { display: none; }
  .nav-hamburger { display: grid; }
}

/* ── Buttons and links ──
   Four pieces, one visual language:
   - .btn: an action. .btn-primary (filled) for the main one in each block,
     .btn-secondary (outlined) for the alternative. One size only.
   - .text-link: a link inside the content. A faint line underneath, with a solid one drawn over it.
   - .icon-btn: navbar icon button (theme, menu). See Navigation.
   - .lang-switcher: navbar segmented control. See Navigation.
   Everything that leaves the site gets the ↗ arrow (.icon-ext).
   The motion is always the same: whatever appears comes in from the left and,
   when the mouse leaves, keeps going and exits to the right (it never goes back).
   On press, buttons and icon buttons sink in slightly. */
.btn {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 11px 22px;
  border: 1.5px solid transparent;
  border-radius: 999px;
  font-size: 0.9375rem;
  font-weight: 600;
  font-stretch: 108%;
  line-height: 1.2;
  text-decoration: none;
  /* The text color changes when the fill is halfway across (450ms total: 150 delay + 150) */
  transition: color 150ms linear 150ms, border-color 150ms linear 150ms, transform 150ms var(--ease-swift);
}

/* Fill that sweeps across the button: it grows from the left and exits to the right.
   main.js drives the states with .fx-left and .fx-on (see "Hover effects"),
   so the animation always finishes even if the mouse leaves halfway. */
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 450ms var(--ease-swift);
}

.btn-primary {
  background: var(--accent);
  color: var(--on-accent);
}

.btn-primary::before { background: var(--accent-hover); }

.btn-secondary {
  border-color: var(--heading);
  color: var(--heading);
}

.btn-secondary::before { background: var(--accent); }

/* Two background lines: the solid one (on top) is 0 wide until hover; the faint one (below) is always there.
   At rest the solid line is anchored to the right, so it exits that way when it erases.
   Like the .btn fill, it's driven by .fx-left and .fx-on from main.js. */
.text-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding-bottom: 3px;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--heading);
  text-decoration: none;
  background:
    linear-gradient(currentColor, currentColor) no-repeat 100% 100% / 0 1.5px,
    linear-gradient(var(--line-faint), var(--line-faint)) no-repeat 0 100% / 100% 1px;
  transition: background-size 450ms var(--ease-swift);
}

/* ↗ arrow: the SVG has two copies of the arrow; the second one waits outside, at the
   bottom left. On hover the group shifts diagonally: one exits through the corner and the other comes in. */
.icon-ext {
  width: 11px;
  height: 11px;
  flex: none;
  overflow: hidden;
}

.icon-ext g { transition: transform 450ms var(--ease-swift); }

/* ── Hero ── */
.hero-inner {
  display: grid;
  justify-items: start;
  gap: 20px;
  padding-block: clamp(56px, 10vw, 112px) clamp(56px, 8vw, 96px);
}

.hero-eyebrow {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-muted);
}

.hero-name {
  font-size: clamp(2.75rem, 9vw, 5.75rem);
  font-weight: 800;
  font-stretch: 125%;
  line-height: 0.95;
  letter-spacing: -0.025em;
  color: var(--heading);
}

.hero-desc {
  max-width: 44ch;
  font-size: clamp(1.0625rem, 1.6vw, 1.1875rem);
  line-height: 1.55;
  color: var(--text-muted);
}

.hero-status {
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--soft);
  color: var(--on-soft);
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.4;
}

.hero-ctas {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
  margin-top: 8px;
}

@media (max-width: 480px) {
  /* The wide font takes up a lot of room, so it gets a bit narrower on phones */
  .hero-name { font-stretch: 112%; }
  .hero-status { border-radius: 14px; }
}

/* ── Sections ── */
.section {
  padding-block: 0 clamp(64px, 9vw, 104px);
}

.section-head {
  display: grid;
  gap: 8px;
  padding-block: clamp(40px, 6vw, 56px) clamp(28px, 4vw, 40px);
  border-top: 1px solid var(--border); /* aligned with the content, not edge to edge */
}

.section-label {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-muted);
}

.section-title {
  font-size: clamp(1.75rem, 3.6vw, 2.4rem);
  font-weight: 750;
  font-stretch: 118%;
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--heading);
  text-wrap: balance;
}

.section-sub {
  max-width: 56ch;
  color: var(--text-muted);
}

/* ── About ──
   Three full-width blocks, stacked:
   description + facts card, background and skills. */
.about {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 56px);
  align-items: start;
}

.about-text {
  display: grid;
  gap: 16px;
}

.about-text p {
  max-width: 62ch;
  font-size: 1.0625rem;
  line-height: 1.7;
  color: var(--text-muted);
}

.about-text .about-lead {
  font-size: clamp(1.3rem, 2.4vw, 1.6rem);
  font-weight: 600;
  font-stretch: 112%;
  line-height: 1.3;
  color: var(--heading);
  text-wrap: balance;
}

/* Facts card */
.facts {
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
}

.facts > div {
  display: grid;
  grid-template-columns: 7.5em minmax(0, 1fr);
  gap: 12px;
  padding: 13px 20px;
}

.facts > div + div { border-top: 1px solid var(--border); }

.facts dt {
  padding-top: 2px;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-muted);
}

.facts dd {
  min-width: 0;
  font-size: 0.9375rem;
  font-weight: 500;
}

/* In the facts card the chip can wrap to two lines */
.facts .chip {
  align-items: flex-start;
  white-space: normal;
  border-radius: 12px;
}

.facts .chip .status-dot {
  flex: none;
  margin-top: 0.45em; /* aligned with the first line */
}

/* Small label (status, next step) */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--soft);
  color: var(--on-soft);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
  white-space: nowrap;
}

@media (max-width: 860px) {
  .about { grid-template-columns: 1fr; }
}

/* Subsections (background and skills) */
.subsection { margin-top: clamp(56px, 8vw, 88px); }

.subsection-head {
  display: grid;
  gap: 6px;
  margin-bottom: clamp(24px, 4vw, 36px);
}

.subsection-title {
  font-size: clamp(1.4rem, 2.8vw, 1.9rem);
  font-weight: 750;
  font-stretch: 118%;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--heading);
  text-wrap: balance;
}

/* ── Background: timelines ──
   Two vertical timelines side by side:
   education on the left and experience on the right.
   On phones they stack. */
.path-cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: 32px clamp(28px, 4vw, 48px);
}

/* Column title (Education / Experience) and project group title (Featured / Other) */
.path-col-title,
.group-title {
  margin-bottom: 18px;
  padding-bottom: 10px;
  border-bottom: 2px solid var(--heading);
  font-size: 1.15rem;
  font-weight: 750;
  font-stretch: 115%;
  color: var(--heading);
}

/* Continuous vertical line to the left of each column */
.path {
  position: relative;
  display: grid;
  gap: 12px;
}

.path::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 24px;
  bottom: 24px;
  border-left: 1.5px solid var(--border);
}

.path-item {
  position: relative;
  margin-left: 28px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
}

/* Dot for each stage: filled = finished, ring = in progress */
.path-item::before {
  content: "";
  position: absolute;
  left: -28px;
  top: 22px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--heading);
  box-shadow: 0 0 0 4px var(--bg);
}

.path-item--current::before {
  background: var(--bg);
  border: 2px solid var(--heading);
}

/* ── Background: collapsible cards ──
   Each card is a <details>: the header (<summary>) spans the full width,
   so tapping anywhere on it opens the card. */
.path-summary {
  display: grid;
  gap: 8px;
  padding: 20px;
  list-style: none;
  cursor: pointer;
}

.path-summary::-webkit-details-marker { display: none; }

/* Focus is shown on the whole card, not just the header */
@supports selector(:has(*)) {
  .path-summary:focus-visible { outline: none; }

  .path-item:has(.path-summary:focus-visible) {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
  }
}

/* "Show details ⌄" / "Hide details ⌃" */
.path-more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  justify-self: start;
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-muted);
  transition: color var(--ease);
}

.path-summary:hover .path-more { color: var(--heading); }

.path-more-icon {
  width: 12px;
  height: 12px;
  transition: transform 300ms var(--ease-swift);
}

.path-details[open] .path-more-icon { transform: rotate(180deg); }
.path-details:not([open]) .path-more-hide,
.path-details[open] .path-more-show { display: none; }

.path-body { padding: 0 20px 20px; }

/* Expands with an animation (in browsers that can animate to height: auto;
   elsewhere it opens instantly) */
@supports (interpolate-size: allow-keywords) {
  .path-details { interpolate-size: allow-keywords; }

  .path-details::details-content {
    block-size: 0;
    overflow-y: clip;
    transition:
      block-size 300ms var(--ease-swift),
      content-visibility 300ms allow-discrete;
  }

  .path-details[open]::details-content { block-size: auto; }

  @media (prefers-reduced-motion: reduce) {
    .path-details::details-content { transition: none; }
  }
}

.path-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}

.path-date {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-muted);
}

/* Status chip: main.js hides it once the end date has passed
   (needed because .chip's display: inline-flex overrides the browser's [hidden] style) */
.path-status[hidden] { display: none; }

/* Date + duration on the same line */
.path-when {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 8px;
}

/* Duration ("5 years 8 months"): calculated by main.js */
.path-duration {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text);
}

.path-duration:not(:empty)::before {
  content: "·";
  margin-right: 8px;
  color: var(--dash);
}

/* Phones: the duration drops below the date, so the
   "In progress" / "Current" chip has room in the top-right corner */
@media (max-width: 600px) {
  /* The date takes two lines, so the chip aligns to the top corner */
  .path-top { align-items: flex-start; }

  .path-when {
    flex-direction: column;
    align-items: flex-start;
  }

  .path-duration:not(:empty)::before { content: none; }
}

.path-title {
  font-size: 1.05rem;
  font-weight: 700;
  font-stretch: 110%;
  line-height: 1.25;
  color: var(--heading);
}

.path-role {
  font-size: 0.875rem;
  font-weight: 500;
}

.path-bullets li {
  position: relative;
  padding-left: 16px;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--text-muted);
}

.path-bullets li + li { margin-top: 4px; }

/* Relevant school coursework */
.path-areas {
  display: grid;
  gap: 12px;
}

.path-areas > div {
  display: grid;
  gap: 6px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.path-areas dt {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-muted);
}

.path-areas ul {
  display: grid;
  gap: 3px;
}

.path-areas li {
  font-size: 0.9375rem;
  line-height: 1.45;
}

.path-bullets li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.75em;
  width: 6px;
  height: 1.5px;
  background: var(--heading);
}

@media (max-width: 760px) {
  .path-cols { grid-template-columns: 1fr; }
}

/* ── Skills: one row per area ── */
.skills-list > div {
  display: grid;
  grid-template-columns: 160px minmax(0, 1fr);
  align-items: baseline;
  gap: 8px 28px;
  padding-block: 16px;
  border-top: 1px solid var(--border);
}

.skills-list > div:last-child { border-bottom: 1px solid var(--border); }

.skills-list dt {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--text-muted);
}

.skills-items {
  display: flex;
  flex-wrap: wrap;
  row-gap: 4px;
  font-size: 1.0625rem;
  font-weight: 500;
}

.skill { white-space: nowrap; }

/* The separator goes at the end of each item: if the row wraps, the "/" stays
   at the end of the line instead of starting the next one */
.skill:not(:last-child)::after {
  content: "/";
  margin-inline: 10px;
  color: var(--dash);
}

@media (max-width: 600px) {
  .skills-list > div { grid-template-columns: 1fr; }
}

/* ── Projects ──
   Two groups: featured (large card: wide cover on top and two columns
   below) and other (compact cards, no cover). */
.group-title--spaced { margin-top: clamp(48px, 7vw, 72px); }

.project-list {
  display: grid;
  gap: 24px;
}

.project {
  display: grid;
  gap: clamp(20px, 3vw, 28px);
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius-card) + 4px);
  background: var(--surface);
  transition: border-color 300ms var(--ease-swift), box-shadow 300ms var(--ease-swift);
}

.project:hover { border-color: var(--heading); }

.project-cover {
  position: relative;
  display: block;
  aspect-ratio: 21 / 9;
  overflow: hidden;
  border-radius: var(--radius-img);
  background: var(--soft);
}

.project-cover img {
  width: 100%;
  height: 100%; /* the <img> has height="900": this ties it to the cover's size */
  object-fit: cover;
  transition: transform 500ms var(--ease-swift);
}

.project:hover .project-cover img { transform: scale(1.04); }

/* Cover for projects without an image: the name on navy */
.project-cover--type {
  display: flex;
  align-items: flex-end;
  padding: clamp(20px, 3vw, 32px);
  background: var(--cover-bg);
  color: var(--cover-fg);
}

.project-cover--type span {
  max-width: 12ch;
  font-size: clamp(1.6rem, 3.2vw, 2.5rem);
  font-weight: 800;
  font-stretch: 125%;
  line-height: 0.98;
  letter-spacing: -0.025em;
  text-wrap: balance;
}

/* Below the cover: what the project is (left) and how it's built (right) */
.project-body {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(28px, 4vw, 48px);
  padding: 0 clamp(10px, 2vw, 22px) clamp(10px, 2vw, 18px);
}

.project-main {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
}

.project-main .project-links { margin-top: auto; padding-top: 6px; }

.project-inside {
  display: grid;
  align-content: start;
  gap: 14px;
  padding-left: clamp(28px, 4vw, 48px);
  border-left: 1px solid var(--border);
}

.project-inside-label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-muted);
}

.project-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
}

.project-date {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-muted);
}

.status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--status);
}

.project-title {
  font-size: clamp(1.75rem, 3.4vw, 2.5rem);
  font-weight: 750;
  font-stretch: 118%;
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--heading);
}

.project-desc {
  max-width: 56ch;
  font-size: 0.9375rem;
  line-height: 1.65;
  color: var(--text-muted);
}

/* Technical highlights of a featured project (same dash as .path-bullets) */
.project-highlights {
  display: grid;
  gap: 10px;
}

.project-highlights li {
  position: relative;
  padding-left: 16px;
  font-size: 0.9375rem;
  line-height: 1.55;
}

.project-highlights li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.75em;
  width: 6px;
  height: 1.5px;
  background: var(--heading);
}

.project-tech {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.project-tech li {
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  line-height: 1.5;
  white-space: nowrap;
}

.project-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 20px;
  margin-top: 4px;
}

/* Medium screens and phones: a narrower cover and the two columns stacked */
@media (max-width: 820px) {
  .project {
    gap: 18px;
    padding: 12px 12px 20px;
  }

  .project-cover { aspect-ratio: 16 / 10; }

  .project-body {
    grid-template-columns: 1fr;
    gap: 24px;
    padding: 0 8px;
  }

  .project-inside {
    padding: 22px 0 0;
    border-left: 0;
    border-top: 1px solid var(--border);
  }
}

/* Other projects: compact cards in a grid; the links sit at the very
   bottom, aligned across cards of different heights */
.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 290px), 1fr));
  gap: 20px;
}

.project-mini {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: clamp(20px, 3vw, 24px);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
  transition: border-color 300ms var(--ease-swift);
}

.project-mini:hover { border-color: var(--heading); }

.project-mini-title {
  font-size: 1.2rem;
  font-weight: 750;
  font-stretch: 115%;
  line-height: 1.2;
  color: var(--heading);
  text-wrap: balance;
}

.project-mini .project-links { margin-top: auto; padding-top: 4px; }

/* ── Contact ──
   Email takes center stage: a large title, the address at heading size
   with buttons to copy it or write, and GitHub / LinkedIn as secondary links. */
.section-contact .section-title {
  font-size: clamp(2.5rem, 7vw, 4.6rem);
  font-weight: 800;
  font-stretch: 125%;
  line-height: 0.98;
  letter-spacing: -0.025em;
}

.section-contact .section-head { gap: 14px; }

/* It can wrap to two lines on phones; without this it widens the page */
.contact-chip {
  justify-self: start;
  align-items: flex-start;
  max-width: 100%;
  white-space: normal;
  border-radius: 12px;
}

.contact-chip .status-dot {
  flex: none;
  margin-top: 0.45em;
}

.contact-mail {
  display: grid;
  gap: 16px;
  padding-block: 24px;
  border-block: 1px solid var(--border);
}

.contact-address {
  justify-self: start;
  font-size: clamp(1.3rem, 4vw, 2.4rem);
  font-weight: 600;
  font-stretch: 105%;
  letter-spacing: -0.01em;
  color: var(--heading);
  overflow-wrap: anywhere;
}

.contact-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}

/* "Copied" appears next to the buttons and fades out on its own (main.js) */
.contact-status {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--status);
  opacity: 0;
  transition: opacity 300ms var(--ease-swift);
}

.contact-status.is-visible { opacity: 1; }

.contact-others {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 32px;
  padding-top: 24px;
}

.contact-others li {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.contact-icon {
  width: 28px;
  height: 28px;
  border-radius: 7px;
  object-fit: cover;
}

/* ── Footer ── */
.footer-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 24px;
  padding-block: 28px 36px;
  border-top: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* ════════════════════════════════════════════════
   Interactions — hover and keyboard focus
   Every control reacts to :hover and :focus-visible
   the same way, so keyboard users see the same thing.
   ════════════════════════════════════════════════ */

/* Lines and fills: main.js sets classes instead of relying on :hover, so each animation
   finishes before the next one starts (see "Hover effects" in main.js).
   .fx-left: anchored to the left (while drawing). .fx-on: fully drawn. */

/* Buttons: the fill sweeps from left to right.
   On the secondary button it's navy, so the text and border switch to the --accent color. */
.btn.fx-left::before { transform-origin: left center; }
.btn.fx-on::before { transform: scaleX(1); }

.btn-secondary.fx-on {
  border-color: var(--accent);
  color: var(--on-accent);
}

/* Icon buttons: soft fill and a stronger border */
.icon-btn:is(:hover, :focus-visible) {
  border-color: var(--heading);
  background: var(--soft);
}

/* Mobile menu: the middle line gets shorter (only while the menu is closed) */
.nav-hamburger span:nth-child(2) { transform-origin: left center; }
.nav-hamburger:not(.open):is(:hover, :focus-visible) span:nth-child(2) { transform: scaleX(0.55); }

/* On press, they sink in slightly */
.btn:active,
.icon-btn:active { transform: scale(0.96); }

/* Links: the solid line draws in from the left and exits to the right on leave */
.text-link.fx-left { background-position: 0 100%, 0 100%; }
.text-link.fx-on { background-size: 100% 1.5px, 100% 1px; }

.nav-links a.fx-left { background-position: 0 100%; }
.nav-links a.fx-on { background-size: 100% 1.5px; }

.nav-links a:is(:hover, :focus-visible) { color: var(--heading); }

.nav-mobile-menu a:is(:hover, :focus-visible) { color: var(--text-muted); }

.lang-opt:not(.active):is(:hover, :focus-visible) { color: var(--heading); }

/* ↗ arrow: it exits through the top corner and the copy comes in from below */
.fx-on .icon-ext g { transform: translate(12px, -12px); }

/* "Show details": the chevron nudges toward where the card is about to move */
.path-summary:hover .path-more-icon { transform: translateY(2px); }
.path-details[open] .path-summary:hover .path-more-icon { transform: rotate(180deg) translateY(2px); }

/* On theme change, the new icon spins in (main.js adds the class) */
html.theme-switching .theme-icon { animation: icon-in 600ms var(--ease-spring); }

@keyframes icon-in {
  from { transform: rotate(-120deg) scale(0.4); opacity: 0; }
}

/* Theme change: the new theme expands in a circle from the button
   (View Transitions; main.js animates the clip-path). Without support, it switches instantly. */
::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}

/* ── Reduced motion ── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}
