/* ---------------------------------------------------------------
   Portfolio — one stylesheet, no frameworks, no JS.
   Tweak the variables below to restyle the whole site.
   --------------------------------------------------------------- */

:root {
  /* One line changes the whole site. */
  --font: "Avenir Next", Avenir, "Segoe UI", system-ui, sans-serif;

  /* The two palettes. Colours are written here and nowhere else; the blocks
     below only pick which set is live.
     Light is gruvbox's warm ink on white rather than its cream paper — the
     cream read as dingy next to the dark theme. Put #f2e5bc back in --light-bg
     (and #d5c4a1 in --light-rule) for true gruvbox light. */
  --light-bg:     #ffffff;
  --light-text:   #3c3836;
  --light-muted:  #7c6f64;
  --light-rule:   #e7e3db;
  --light-accent: #076678;
  --light-hover:  #af3a03;
  --light-select: #d79921;

  /* gruvbox dark — bg0_hard / fg1 / fg4 / bg2 / bright blue / bright orange */
  --dark-bg:     #1d2021;
  --dark-text:   #ebdbb2;
  --dark-muted:  #a89984;
  --dark-rule:   #504945;
  --dark-accent: #83a598;
  --dark-hover:  #fe8019;
  --dark-select: #fabd2f;

  --width:   40rem;   /* content column */
  --gap:     3.5rem;  /* space between sections */

  /* Light unless something below says otherwise. */
  --bg:     var(--light-bg);
  --text:   var(--light-text);
  --muted:  var(--light-muted);
  --rule:   var(--light-rule);
  --accent: var(--light-accent);
  --hover:  var(--light-hover);
  --select: var(--light-select);
  color-scheme: light;
}

/* Follow the OS — but not once the visitor has picked light themselves. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:     var(--dark-bg);
    --text:   var(--dark-text);
    --muted:  var(--dark-muted);
    --rule:   var(--dark-rule);
    --accent: var(--dark-accent);
    --hover:  var(--dark-hover);
    --select: var(--dark-select);
    color-scheme: dark;
  }
}

/* An explicit choice from the toggle (see theme.js), restored before paint. */
:root[data-theme="dark"] {
  --bg:     var(--dark-bg);
  --text:   var(--dark-text);
  --muted:  var(--dark-muted);
  --rule:   var(--dark-rule);
  --accent: var(--dark-accent);
  --hover:  var(--dark-hover);
  --select: var(--dark-select);
  color-scheme: dark;
}

::selection { background: var(--select); color: #282828; }

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 3.5rem 1.5rem 7rem;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.65;
}

main { max-width: var(--width); margin: 0 auto; }

/* --- type ------------------------------------------------------ */

h1, h2, h3 { font-weight: 600; line-height: 1.3; margin: 0; }

h1 { font-size: 1.375rem; letter-spacing: -0.01em; }
h3 { font-size: 1rem; }

h2 {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 1.75rem;
}
p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }

a { color: var(--accent); text-decoration: underline; text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { color: var(--hover); }

code { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.9em; }

.muted { color: var(--muted); }
.small { font-size: 0.875rem; }

/* --- nav -------------------------------------------------------- */

.nav {
  max-width: var(--width);
  margin: 0 auto var(--gap);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  font-size: 1.0625rem;
}
.nav-name { color: var(--text); font-weight: 600; text-decoration: none; }
.nav-name:hover { color: var(--hover); }
.nav-links { display: flex; align-items: center; gap: 1.25rem; }
.nav-links a { color: var(--muted); text-decoration: none; }
.nav-links a:hover { color: var(--hover); }
.nav-links a[aria-current="page"] { color: var(--text); }

/* Theme toggle — ships hidden, revealed by theme.js. Without JS the site
   simply follows the OS, so there is no dead button. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  margin: -0.5rem 0;   /* keeps the nav the same height */
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
}
.theme-toggle:hover { color: var(--hover); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Show the theme you would switch *to*. */
.theme-toggle .icon-sun { display: none; }
:root[data-resolved="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-resolved="dark"] .theme-toggle .icon-moon { display: none; }

/* --- page header ------------------------------------------------ */

.intro { margin-bottom: var(--gap); }

.links a { margin-right: 0.85rem; }

section { margin-bottom: var(--gap); }
section:last-child { margin-bottom: 0; }

/* --- detail / listing page header ------------------------------- */

.page-head { margin-bottom: 2.25rem; }
.page-head .date,
.page-head .where { font-size: 0.875rem; color: var(--muted); margin: 0.4rem 0 0; }
.page-head .links { margin-top: 0.75rem; font-size: 0.875rem; }

/* Dates left, location right-anchored on the same line. */
.head-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 0.4rem;
}
.head-row .date,
.head-row .where { margin: 0; }

/* Tags left, links right — and still right when they wrap to their own line. */
.head-meta { margin-top: 0.9rem; }
.head-meta .tags { margin: 0; }
.page-head .head-meta .links { margin: 0 0 0 auto; }
.head-meta .links a:last-child { margin-right: 0; } /* sit flush with the edge */

/* --- two-column job pages --------------------------------------- */

/* One column by default: text first, then media (with its heading). */
.split { display: grid; gap: var(--gap); }
.split > div > section:last-child { margin-bottom: 0; }

@media (min-width: 58rem) {
  /* Every page shares one frame width, so the nav, the footer rule and the
     left edge of the content line up from page to page. What varies inside it
     is the content: two columns on detail pages, a capped list on the
     listing pages. */
  :root { --width: 58rem; }

  .split { grid-template-columns: 19rem 1fr; gap: 3rem; }
  .split .col-media { grid-column: 1; grid-row: 1; }
  .split .col-body  { grid-column: 2; grid-row: 1; }

  /* The column speaks for itself, and pairs stack in a narrow column. */
  .split .col-media h2 { display: none; }
  .split .col-media section { margin-bottom: 0; }
  .split .col-media .media.two-up { grid-template-columns: 1fr; }
}

/* --- list rows -------------------------------------------------- */

.entry-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
}

.entry-head .date {
  font-size: 0.875rem;
  color: var(--muted);
  white-space: nowrap;
}

.card-body p { margin: 0.25rem 0 0; color: var(--muted); }

/* --- list with thumbnails (experience.html, projects.html) ------- */

.cards { list-style: none; margin: 0; padding: 0; }
.card {
  display: grid;
  grid-template-columns: 10.5rem 1fr;
  gap: 1.25rem;
  align-items: start;
}
.card + .card { margin-top: 2.25rem; }

.card-thumb { display: block; }
.card-thumb img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 2px;
}

/* Square company logos instead of 16:9 stills. */
.cards.logos .card { grid-template-columns: 4rem 1fr; }
.cards.logos .card-thumb img { aspect-ratio: 1 / 1; }

@media (max-width: 34rem) {
  .card { grid-template-columns: 1fr; gap: 0.75rem; }
  /* Logos stay beside the text — full width would be enormous. */
  .cards.logos .card { grid-template-columns: 3.5rem 1fr; gap: 1rem; }
}

/* --- bullets ---------------------------------------------------- */

ul.bullets { margin: 0; padding-left: 1.1rem; }
ul.bullets li { margin-bottom: 0.5rem; }
ul.bullets li::marker { color: var(--muted); }

/* --- tags ------------------------------------------------------- */

.tags { list-style: none; display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.75rem 0 0; padding: 0; }
.tags li {
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--muted);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.05rem 0.45rem;
}

/* --- media ------------------------------------------------------ */

.media { margin: 0; display: grid; gap: 1.5rem; }
.media + .media { margin-top: 1.5rem; }

/* Side-by-side pair on wide screens; stacks below. */
@media (min-width: 40rem) {
  .media.two-up { grid-template-columns: 1fr 1fr; }
}

.media figure { margin: 0; }
.media img,
.media video {
  display: block;
  width: 100%;
  height: auto;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 2px;
}
.media figcaption { font-size: 0.8125rem; color: var(--muted); margin-top: 0.5rem; }

/* --- spatial photo (see viewer.js) ------------------------------ */

.photo {
  position: relative;
  max-width: 19rem;          /* keeps it sane when the page is one column */
  margin-inline: auto;       /* …and centred there; a no-op in its own column */
  aspect-ratio: 3 / 4;       /* must match the GLB's source aspect */
  overflow: hidden;
  background: #000;
  border: 1px solid var(--rule);
  border-radius: 2px;
}
.photo canvas { display: block; width: 100%; height: 100%; }

/* Shown until the model loads, and left up if WebGL is unavailable.
   --photo-zoom comes from content.js and must match the viewer's zoom, or the
   poster and the first rendered frame will not line up. */
.photo-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(var(--photo-zoom, 1));
  transition: opacity 0.3s linear;
}
.photo[data-loaded="true"] .photo-poster { opacity: 0; }

/* "hover to interact" — revealed by viewer.js once the pointer does something,
   cleared after the first hover. Never eats pointer events itself. */
.photo-badge {
  position: absolute;
  left: 50%;
  bottom: 0.75rem;
  transform: translateX(-50%);
  padding: 0.15rem 0.6rem;
  border-radius: 2px;
  background: rgba(29, 32, 33, 0.72);
  color: #fbf1c7;
  font-size: 0.75rem;
  line-height: 1.6;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s linear;
}
.photo[data-badge="show"] .photo-badge { opacity: 1; }

/* --- video player (see player.js) ------------------------------- */

.player { position: relative; line-height: 0; }

/* Covers the whole video: click anywhere to play or pause. */
.player-toggle {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.play-icon {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  padding-left: 0.15rem;   /* optically centre the triangle */
  border-radius: 50%;
  background: rgba(29, 32, 33, 0.72);
  color: #fbf1c7;
}
.player[data-playing="true"] .play-icon { display: none; }

.player-fullscreen {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  display: none;
  place-items: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: rgba(29, 32, 33, 0.72);
  color: #fbf1c7;
  cursor: pointer;
}
.player[data-playing="true"] .player-fullscreen { display: grid; }

/* In fullscreen it is the way back out, so show it paused or playing.
   Separate rules — one unknown selector would invalidate the whole list. */
.player:fullscreen .player-fullscreen { display: grid; }
.player:-webkit-full-screen .player-fullscreen { display: grid; }

.player-toggle:focus-visible,
.player-fullscreen:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Fullscreen: let the video fill the screen, drop the page styling.
   The two selectors cannot be combined — one unknown selector would
   invalidate the whole rule. */
.player:fullscreen { display: grid; place-items: center; background: #000; }
.player:fullscreen video { width: auto; height: 100%; max-width: 100vw; border: 0; border-radius: 0; }
.player:-webkit-full-screen { display: grid; place-items: center; background: #000; }
.player:-webkit-full-screen video { width: auto; height: 100%; max-width: 100vw; border: 0; border-radius: 0; }

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

footer {
  max-width: var(--width);
  margin: var(--gap) auto 0;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  font-size: 0.875rem;
  color: var(--muted);
}
