/*
 * styles.css
 * Dominic Caulfield-Duverger
 * Oct 9, 2026
 *
 * Order: variables, base stuff, layout, components, animation, mobile.
 * Colors/fonts/spacing are all variables at the top, so start there
 * if you want to change the look.
 */


/* ------------------------------------------------------------------
   Variables
   Change these and it updates everywhere.
   ------------------------------------------------------------------ */

:root {
  /* colors (light) */
  --bg:          #fafaf9;
  --surface:     #ffffff;
  --text:        #18181b;
  --muted:       #6b6b73;
  --line:        #e7e5e4;
  --accent:      #2563eb;   /* main accent */
  --accent-soft: #eff4ff;

  /* fonts (loaded in index.html) */
  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, Menlo, monospace;

  /* spacing - clamp() scales with screen width */
  --radius:      10px;
  --max-width:   880px;
  --gutter:      clamp(16px, 4vw, 32px);     /* page side padding */
  --section-gap: clamp(72px, 10vw, 120px);
}


/* Dark mode. Same colors twice: once for the OS setting (unless the
   toggle forced light), once for when the toggle forces dark. */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:          #0e0e10;
    --surface:     #161618;
    --text:        #ededef;
    --muted:       #9a9aa3;
    --line:        #26262b;
    --accent:      #6ea8ff;
    --accent-soft: #15203a;
  }
}

:root[data-theme="dark"] {
  --bg:          #0e0e10;
  --surface:     #161618;
  --text:        #ededef;
  --muted:       #9a9aa3;
  --line:        #26262b;
  --accent:      #6ea8ff;
  --accent-soft: #15203a;
}


/* ------------------------------------------------------------------
   Base
   Resets + a few shared classes.
   ------------------------------------------------------------------ */

/* padding/border count toward width */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: 72px;  /* so headings don't end up under the nav */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.65 var(--font-sans);
  -webkit-font-smoothing: antialiased;
  transition: background 0.25s, color 0.25s;
}

/* kill default margins and bullets, spacing is set per component */
h1, h2, h3, p, ul, ol, dl, dd {
  margin: 0;
}

ul,
ol {
  padding: 0;
  list-style: none;
}

button {
  font: inherit;
  color: inherit;
  cursor: pointer;
}

a {
  color: inherit;
}

/* make sure [hidden] wins over any display: flex etc */
[hidden] {
  display: none !important;
}

/* outline for keyboard users only */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}


/* ---- shared classes ---- */

.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.muted {
  color: var(--muted);
}

/* small uppercase headings like LANGUAGES in Skills */
.label {
  margin-bottom: 14px;
  font: 500 12px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.lead {
  max-width: 64ch;
  font-size: 18px;
}


/* ------------------------------------------------------------------
   Layout
   ------------------------------------------------------------------ */

/* ---- nav (sticky, frosted glass) ---- */

.nav {
  position: sticky;
  top: 0;
  z-index: 10;

  display: flex;
  align-items: center;
  gap: 24px;
  padding: 14px var(--gutter);

  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

/* the DC initials */
.nav__mark {
  font: 600 15px var(--font-mono);
  letter-spacing: 0.02em;
  text-decoration: none;
}

/* scrolls sideways if it doesn't fit on small screens */
.nav__links {
  display: flex;
  gap: 20px;
  margin-left: auto;
  overflow-x: auto;
  scrollbar-width: none;
}

.nav__links a {
  font-size: 14px;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s;
}

/* is-current comes from the scroll-spy in main.js */
.nav__links a:hover,
.nav__links a.is-current {
  color: var(--text);
}

/* light/dark button */
.theme-toggle {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  background: none;
  border: 1px solid var(--line);
  border-radius: 50%;
}


/* ---- hero (name at the top) ---- */

.hero {
  padding: clamp(80px, 14vw, 160px) 0 clamp(56px, 8vw, 96px);
}

.hero__eyebrow {
  margin-bottom: 18px;
  font: 500 13px var(--font-mono);
  color: var(--accent);
}

.hero__name {
  font-size: clamp(38px, 7vw, 64px);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.035em;
}

.hero__tagline {
  max-width: 52ch;
  margin-top: 22px;
  font-size: clamp(17px, 2.2vw, 20px);
  color: var(--muted);
}


/* ---- sections ---- */

.section {
  padding-top: var(--section-gap);
}

.section__head {
  margin-bottom: 32px;
  border-bottom: 1px solid var(--line);
}

/* the whole heading is the open/close button */
.section__toggle {
  display: flex;
  align-items: baseline;
  gap: 14px;
  width: 100%;
  padding: 0 0 14px;
  background: none;
  border: 0;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

/* + on the far right, turns into x when open */
.section__icon {
  margin-left: auto;
  font: 400 20px var(--font-mono);
  color: var(--muted);
  transition: transform 0.2s;
}

.section__toggle[aria-expanded="true"] .section__icon {
  transform: rotate(45deg);
}

.section__toggle:hover .section__title {
  color: var(--accent);
}

/* the 01, 02... numbers */
.section__num {
  font: 500 13px var(--font-mono);
  color: var(--accent);
}

.section__title {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
}


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

.footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px;
  margin-top: var(--section-gap);
  padding-top: 28px;
  padding-bottom: 40px;
  border-top: 1px solid var(--line);
  font-size: 13px;
}


/* ------------------------------------------------------------------
   Components
   ------------------------------------------------------------------ */

/* ---- About stat boxes ----
   1px gap over a grey background = thin divider lines between boxes */

.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  margin-top: 40px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.stat {
  padding: 22px 20px;
  background: var(--surface);
}

.stat__value {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.stat__label {
  margin-top: 2px;
  font-size: 13px;
  color: var(--muted);
}


/* ---- project filter buttons ---- */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 24px;
}

.chip {
  padding: 6px 14px;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 13px;
  color: var(--muted);
  transition: all 0.15s;
}

.chip:hover {
  color: var(--text);
}

.chip.is-active {
  background: var(--text);
  border-color: var(--text);
  color: var(--bg);
}


/* ---- project cards ---- */

/* align-items: start so opening one card doesn't stretch the one next to it */
.cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  align-items: start;
}

.card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 24px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 0.2s, transform 0.2s;
}

.card:hover {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
  transform: translateY(-2px);
}

/* category + status row */
.card__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font: 500 12px var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

.badge {
  padding: 3px 9px;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 999px;
  text-transform: none;
  letter-spacing: 0;
}

.card__title {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.card__desc {
  font-size: 15px;
  color: var(--muted);
}

.card__more {
  padding-top: 4px;
}

/* for when repos go public */
.card__links {
  display: flex;
  gap: 14px;
  margin-top: 12px;
  font-size: 14px;
}

.card__links a {
  color: var(--accent);
  text-decoration: none;
}

/* Details button, margin-top auto keeps it at the bottom */
.toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  margin-top: auto;
  padding: 0;
  background: none;
  border: 0;
  font: 500 13px var(--font-mono);
  color: var(--accent);
}

/* the GitHub link on repo cards is an <a>, not a button */
a.toggle {
  text-decoration: none;
}

a.toggle:hover span:first-child {
  text-decoration: underline;
}

/* Public repos subsection under the project cards.
   Smaller version of a section heading, closed by default */
.subsection {
  margin-top: 40px;
}

.subsection__head {
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}

.subsection__toggle {
  width: 100%;
  justify-content: space-between;
  font: 600 16px var(--font-sans);
  color: var(--text);
  cursor: pointer;
}

.subsection__toggle:hover {
  color: var(--accent);
}

.subsection .cards {
  margin-top: 20px;
}

/* repo card inside a project's Details: a bit smaller, no lift */
.card--nested {
  margin-top: 14px;
  padding: 16px;
  background: var(--bg);
}

.card--nested:hover {
  transform: none;
}

/* shown in place of a repo card while the repo is private */
.repo-private {
  margin-top: 14px;
  font: 400 13px var(--font-mono);
  color: var(--muted);
}

/* + turns into x when open */
.toggle__icon {
  transition: transform 0.2s;
}

.toggle[aria-expanded="true"] .toggle__icon {
  transform: rotate(45deg);
}


/* ---- tags (tech stack + skills) ---- */

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

.tags li {
  padding: 3px 9px;
  border: 1px solid var(--line);
  border-radius: 6px;
  font: 400 12px var(--font-mono);
  color: var(--muted);
}

/* bigger version for Skills */
.tags--lg li {
  padding: 5px 11px;
  background: var(--surface);
  font-size: 13px;
  color: var(--text);
}


/* ---- bullet lists, dash instead of a dot ---- */

.bullets li {
  position: relative;
  padding-left: 18px;
  font-size: 15px;
}

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

.bullets li::before {
  content: "–";
  position: absolute;
  left: 0;
  color: var(--muted);
}


/* ---- experience timeline (dates left, details right) ---- */

.timeline {
  display: grid;
  gap: 44px;
}

.job {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 24px;
}

.job__when {
  font: 400 13px/1.9 var(--font-mono);
  color: var(--muted);
}

.job__role {
  font-size: 18px;
  font-weight: 600;
}

.job__where {
  margin: 2px 0 14px;
  color: var(--muted);
}

/* other experience list */
.other {
  margin-top: 44px;
  padding-top: 24px;
  border-top: 1px dashed var(--line);
}

.other li {
  font-size: 15px;
  color: var(--muted);
}

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


/* ---- skills ---- */

.skills {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 36px 32px;
}


/* ---- education / certs ---- */

.edu {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 40px;
}

.edu__title {
  font-weight: 600;
}

.edu__item + .edu__item {
  margin-top: 16px;
}

.certs li {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  font-size: 15px;
}

.certs li:first-child {
  padding-top: 0;
}


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

.contact {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin-top: 28px;
}

.contact__email {
  font: 500 clamp(18px, 3vw, 24px) var(--font-mono);
  word-break: break-all;   /* so it can wrap on phones */
}

/* GitHub / LinkedIn links (hero + contact) */
.socials {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-top: 24px;
  padding: 0;
  list-style: none;
  font-size: 15px;
}

.socials a {
  color: var(--accent);
  text-decoration: none;
}

.socials a:hover {
  text-decoration: underline;
}

.btn {
  padding: 8px 16px;
  background: var(--text);
  border: 1px solid var(--text);
  border-radius: 8px;
  font-size: 14px;
  color: var(--bg);
}

.btn:hover {
  opacity: 0.85;
}


/* ------------------------------------------------------------------
   Motion
   main.js adds .is-visible when a section scrolls into view.
   ------------------------------------------------------------------ */

.reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* turn animations off if the OS has reduce motion on */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .card:hover {
    transform: none;
  }
}


/* ------------------------------------------------------------------
   Responsive
   Phones / small tablets: fewer columns, dates stacked above jobs.
   ------------------------------------------------------------------ */

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

  .cards,
  .skills,
  .edu {
    grid-template-columns: 1fr;
  }

  .job {
    grid-template-columns: 1fr;
    gap: 6px;
  }

  .nav {
    gap: 14px;
  }

  .nav__links {
    gap: 16px;
  }
}
