/* ==========================================================================
   Bob Ferry — portfolio (v2 layout)
   Single source of truth for styling. Design tokens live in :root.
   ========================================================================== */

/* Smooth cross-page navigation where supported (progressive enhancement). */
@view-transition { navigation: auto; }
/* Custom root transition: the outgoing page fades out, the incoming one fades in
   with a soft 10px rise — gentler than the default hard cross-fade. */
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in  { from { opacity: 0; transform: translateY(10px); } }
::view-transition-old(root) { animation: vt-out 200ms ease both; }
::view-transition-new(root) { animation: vt-in 280ms cubic-bezier(0.22, 1, 0.36, 1) both; }

:root {
  /* Fonts */
  --font-header: "Plus Jakarta Sans", sans-serif;
  --font-body: "Manrope", sans-serif;

  /* Colour palette (from Bob's Figma) */
  --bg: #F1EBF5;            /* lavender (page + button faces) */
  --text: #101137;         /* deep navy ink (logo circle) */
  --indigo: #4C4D90;       /* mid indigo — nav borders, walls, title */
  --subtitle: #A493AF;     /* mauve — header subtitle */
  --muted: #6b6b8a;        /* slate-purple secondary text */
  --border: var(--indigo); /* hairline borders (cards / section bar) — same strong purple as the nav */
  --accent: #F2B816;       /* yellow (gold from logo) */
  --tile: #fdfcfa;         /* near-white tile fill */

  /* Recess interaction (brutalist "push the page in") — tunable knobs.
     wall   = how far the face shifts + indigo inner-wall thickness
     shadow = how much FURTHER the orange shadow reaches beyond the wall */
  --wall: 8px;             /* hover */
  --wall-press: 12px;      /* press */
  --shadow: 16px;          /* hover */
  --shadow-press: 20px;    /* press */
  --recess-wall: var(--indigo); /* recess inner-wall colour — decoupled from the border */
  --recess-face: var(--bg);     /* recessed button face — equals page bg in light, lightens in dark */
  --recess-blend: rgba(225, 198, 186, 0.35); /* #E1C6BA @ 35% — the live recess shadow on cards + nav tiles + socials, multiplied into the face (multiply in both themes) */

  /* Footer (decoupled so dark mode can keep it dark) */
  --footer-bg: #101137;
  --footer-text: #F1EBF5;

  /* Spacing */
  --maxw: 940px;
  --pad: 24px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 18px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* Sticky footer: body is a full-height flex column so the footer pins to the
     bottom of the viewport on short pages (e.g. 404) instead of floating up and
     leaving a band of page bg below it. On long pages the content overflows
     normally and the footer just follows. (.container flex-grows; see below.) */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;   /* dvh = the real visible height on mobile incl. browser UI */
}

.container {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--pad);
  flex: 1 0 auto;       /* grow to absorb the slack, pushing the footer down */
  width: 100%;          /* fill the flex line so max-width + auto margins still centre */
}

/* ---- Header --------------------------------------------------------------- */
.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 64px 0 48px;
  flex-wrap: wrap;
  /* Pinned across page navigations: the header sits at the same top position on every
     page, so naming it lifts it out of the root fade — it stays anchored while only
     <main> (the root) fades + rises. Content is identical page-to-page, so the group's
     cross-fade is imperceptible. (See @view-transition at the top of this file.) */
  view-transition-name: site-header;
}

.brand { display: flex; align-items: center; gap: 20px; }

.logo { height: 88px; width: auto; flex-shrink: 0; }

.site-title {
  font-family: var(--font-header);
  font-weight: 800;
  font-size: 28px;
  letter-spacing: -0.05em;
  line-height: 1.05;
  color: var(--indigo);
}

.site-subtitle {
  font-family: var(--font-header);
  font-weight: 800;
  font-size: 28px;
  letter-spacing: -0.05em;
  line-height: 1.05;
  color: var(--subtitle);
}
.site-subtitle a { color: inherit; text-decoration: none; }
.site-subtitle a:hover { color: var(--indigo); }

/* Social tiles (top-right) */
.socials { display: flex; gap: 12px; }

/* Icon tiles = the same recess button with NO border: free-floating icons at
   rest, the recess box only appears on hover/press (see shared rules above). */
.social-tile {
  width: 80px;
  height: 80px;
  background: transparent;
  position: relative;        /* anchor the recess layers */
  isolation: isolate;        /* confine the ::before multiply to the tile */
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  overflow: hidden;
  transition: background-color 200ms ease-out;
}

.social-tile img { width: 36px; height: 36px; transition: transform 200ms ease-out; }

/* Theme toggle — reuses the borderless recess tile; swaps sun/moon by theme. */
.theme-toggle { border: 0; padding: 0; cursor: pointer; font: inherit; }
.social-tile svg { width: 28px; height: 28px; color: var(--indigo); transition: transform 200ms ease-out; }
.theme-toggle .icon-sun { display: none; color: var(--accent); }  /* gold sun, matches the selected-tile underline */
[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
[data-theme="dark"] .theme-toggle .icon-sun { display: inline-block; }

/* ---- Primary navigation (2x2 grid) --------------------------------------- */
/* 2x2 grid; the 1px indigo gaps + outer border frame each tile as a sharp box. */
.main-nav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--indigo);
  border: 1px solid var(--indigo);
  /* Pinned too (same fixed position on every page). Only its content differs — the
     active tile / gold underline — so navigating cross-fades the underline from the
     old tile to the new one in place, rather than the whole nav fading out and in. */
  view-transition-name: main-nav;
}

.nav-tile {
  padding: 36px 24px;
  text-align: center;
  text-decoration: none;
  font-family: var(--font-header);
  font-weight: 400;
  font-size: 24px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--indigo);
  background: var(--bg);
  position: relative;        /* anchor the recess layers */
  isolation: isolate;        /* confine the ::before multiply to the tile */
  overflow: hidden;
  /* Smart-Animate-style tween pulled from the Figma: 200ms ease-out */
  transition: background-color 200ms ease-out;
}

.nav-label {
  display: inline-block;       /* shrink-wrap the text so the underline matches its width */
  position: relative;
  transition: transform 200ms ease-out;
}

/* "You are here" cue + hover affordance: an underline beneath the label that grows
   out from the centre. Persistent on the current page; animates in on hover/focus.
   Replaces the old permanent-recess cue, which relied on shade contrast and got lost
   once the current tile kept its dark rest background. */
.nav-label::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -8px;
  height: 2px;
  background: var(--accent);   /* TEST: gold underline (both themes — likely too light for light mode) */
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 200ms ease-out;
}
.nav-tile.active .nav-label::after,
.nav-tile:hover .nav-label::after,
.nav-tile:focus-visible .nav-label::after {
  transform: scaleX(1);
}

/* Recess — the SAME material as the post-cards (see the .post-card block), as two
   layers behind the sliding label/icon (z-index:-1):
   - ::after = the indigo WALL, crisp, painted on top of the shadow.
   - ::before = the warm SHADOW, mix-blend-mode multiply (both themes; dark uses a
     near-black navy), colour --recess-blend (#E1C6BA @ 35%).
   The label/icon slides down-right into the recess; press = deeper. (Unlike the
   cards, the wall grows in with the slide rather than being revealed by an opaque
   face — the button content is transparent — but it's the identical material.) */
.nav-tile::before, .nav-tile::after,
.social-tile::before, .social-tile::after,
.footer-link::before, .footer-link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  transition: box-shadow 200ms ease-out;
}
.nav-tile::before, .social-tile::before, .footer-link::before { mix-blend-mode: multiply; }

/* Hover / focus */
.nav-tile:hover::after, .nav-tile:focus-visible::after,
.social-tile:hover::after, .social-tile:focus-visible::after,
.footer-link:hover::after, .footer-link:focus-visible::after {
  box-shadow: inset var(--wall) var(--wall) 0 0 var(--recess-wall);
}
.nav-tile:hover::before, .nav-tile:focus-visible::before,
.social-tile:hover::before, .social-tile:focus-visible::before,
.footer-link:hover::before, .footer-link:focus-visible::before {
  box-shadow: inset calc(var(--wall) + var(--shadow)) calc(var(--wall) + var(--shadow)) 0 0 var(--recess-blend);
}
.nav-tile:hover .nav-label, .nav-tile:focus-visible .nav-label,
.social-tile:hover img, .social-tile:focus-visible img,
.social-tile:hover svg, .social-tile:focus-visible svg,
.footer-link:hover .footer-link-label, .footer-link:focus-visible .footer-link-label {
  transform: translate(var(--wall), var(--wall));
}

/* Press: same material, deeper. */
.nav-tile:active::after, .social-tile:active::after, .footer-link:active::after {
  box-shadow: inset var(--wall-press) var(--wall-press) 0 0 var(--recess-wall);
}
.nav-tile:active::before, .social-tile:active::before, .footer-link:active::before {
  box-shadow: inset calc(var(--wall-press) + var(--shadow-press)) calc(var(--wall-press) + var(--shadow-press)) 0 0 var(--recess-blend);
}
.nav-tile:active .nav-label,
.social-tile:active img,
.social-tile:active svg,
.footer-link:active .footer-link-label {
  transform: translate(var(--wall-press), var(--wall-press));
}

/* Recessed FACE colour. In light mode --recess-face == --bg (no visible change);
   in dark mode it lightens, so the recess reads as light pooling into the dip. */
/* NB: .nav-tile.active is deliberately NOT here. The current-page tile keeps the
   default (dark) --bg at rest — its shallow permanent recess alone signals "you are
   here" — and only lightens to --recess-face on hover/focus/press, like any tile. */
.nav-tile:hover, .nav-tile:focus-visible, .nav-tile:active,
.social-tile:hover, .social-tile:focus-visible, .social-tile:active,
.footer-link:hover, .footer-link:focus-visible, .footer-link:active,
.post-card:hover {
  background: var(--recess-face);
}

/* ---- Intro ---------------------------------------------------------------- */
main { padding-top: 40px; }

.intro { margin-bottom: 8px; }

/* Same type spec as .page-title on the other pages, so the top heading is consistent
   site-wide (only the margin differs — this one leads into intro text). */
.intro-title {
  font-family: var(--font-header);
  font-weight: 800;
  font-size: 28px;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--text);
  margin-bottom: 16px;
}

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

/* ---- Section bar + post list --------------------------------------------- */
.section-bar {
  margin-top: 40px;
  padding: 16px 24px;
  font-family: var(--font-header);
  font-weight: 800;
  font-size: 24px;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  color: var(--text);
}

.posts {
  display: flex;
  flex-direction: column;
}

/* Borderless variant (homepage): flush-left so "Latest Writing" lines up with the
   post images now that the box border is gone. The .standalone bar (cases/visuals)
   keeps its own bottom border + horizontal padding. */
.section-bar:not(.standalone) { padding-left: 0; padding-right: 0; }

.post-card {
  position: relative;        /* containing block for the recess layers */
  isolation: isolate;        /* confine the ::before multiply to the card (not the page) */
  display: flex;
  align-items: stretch;
  height: 200px;             /* uniform row height; with the 200px-wide cell the image is square */
  overflow: hidden;
  transition: background-color 200ms ease-out;
}
.post-card > * { transition: transform 200ms ease-out; }

.post-image-cell {
  width: 200px;              /* = card height → square */
  flex-shrink: 0;
  background: rgba(255, 255, 255, 0.35);
  display: flex;
  overflow: hidden;
}
.post-image-cell img { width: 100%; height: 100%; object-fit: cover; }

/* The recess, as two layers (the single-inset version failed on a multi-part card —
   see CLAUDE.md). On hover the WHOLE row slides down-right (`> *` translate):
   - ::after = the indigo WALL. ALWAYS on, painted BEHIND the content (z-index:-1).
     The opaque content (image cell + text box) covers it at rest; the sliding row
     EXPOSES it in the gap it vacates, and RE-COVERS it on the way back — so it never
     animates in/out (no appear/disappear flicker).
   - ::before = the warm SHADOW on the sunken face. ON TOP (z-index:2) so it survives
     over the opaque image (which becomes its own stacking context when transformed),
     inset by the wall width so it never tints the wall, multiplied into the content
     (multiply in both themes; dark uses a near-black navy so the dip still darkens). */
.post-card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  box-shadow: inset var(--wall) var(--wall) 0 0 var(--recess-wall);
}
.post-card::before {
  content: "";
  position: absolute;
  top: var(--wall); left: var(--wall); right: 0; bottom: 0;
  z-index: 2;
  pointer-events: none;
  mix-blend-mode: multiply;
  transition: box-shadow 200ms ease-out;
}
.post-card:hover::before {
  box-shadow: inset var(--shadow) var(--shadow) 0 0 var(--recess-blend);
}
.post-card:hover > * { transform: translate(var(--wall), var(--wall)); }

/* Scroll-reveal (the .reveal class is added by JS, so no-JS keeps posts visible).
   NB: keep background-color in the transition list — the recess itself lives on the
   pseudo-elements + `> *`, so it's unaffected, but this avoids the bg snap. */
.post-card.reveal { opacity: 0; transform: translateY(12px); }
.post-card.reveal.in { opacity: 1; transform: none; transition: opacity .5s ease, transform .5s ease, background-color 200ms ease-out; }

/* Opaque so it fully covers the always-on wall at rest (matches the page bg, so it's
   invisible). The image cell is already opaque. */
.post-content { flex: 1; padding: 24px; background: var(--bg); }

.post-title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 20px;
  line-height: 1.25;
  letter-spacing: -0.02em;
  margin-bottom: 6px;
  /* clamp so a long title can't blow out the fixed-height card */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.post-title a { text-decoration: none; color: var(--text); }
.post-title a:hover { color: var(--accent); }

.post-meta { font-size: 14px; color: var(--muted); margin-bottom: 12px; }
.post-excerpt {
  color: var(--muted);
  /* clamp to keep every card the same height (image stays square) */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}

/* ---- Page title ----------------------------------------------------------- */
.page-title {
  font-family: var(--font-header);
  font-weight: 800;
  font-size: 28px;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  margin-bottom: 24px;
}

/* ---- Prose (about page, page leads) -------------------------------------- */
.prose { max-width: 680px; }
.prose + .prose { margin-top: 16px; }
.prose p { color: var(--muted); margin-bottom: 16px; }
.prose p:last-child { margin-bottom: 0; }
.prose strong { color: var(--text); font-weight: 600; }
.prose a { color: var(--indigo); text-decoration: underline; }
.prose a:hover { color: var(--accent); }
.prose ul { margin: 0; padding-left: 20px; }
.prose li { color: var(--muted); margin-bottom: 10px; }
.prose li:last-child { margin-bottom: 0; }

/* A section bar used on its own (not capping a bordered .posts block) needs its
   bottom edge back, otherwise it reads as an open-ended box. */
.section-bar.standalone { border-bottom: 1px solid var(--border); margin-bottom: 24px; }

/* ---- Visual gallery grid ------------------------------------------------- */
.visual-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.visual-tile {
  border: 1px solid var(--indigo);
  background: var(--tile);
  overflow: hidden;
}
.visual-thumb { aspect-ratio: 4 / 3; background: var(--swatch, var(--indigo)); }
.visual-caption {
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
}

/* ---- Gradient placeholder thumbnails (stand in for real imagery) --------- */
/* Brand-palette gradients with a soft light highlight, echoing the logo badge.
   Used on post/case image cells and the visuals gallery until real art lands. */
.ph-thumb {
  background-color: var(--c2, #101137);
  background-image:
    radial-gradient(circle at 72% 26%, rgba(255, 255, 255, 0.22), transparent 46%),
    linear-gradient(135deg, var(--c1, #4C4D90), var(--c2, #101137));
}
.ph-thumb--g1 { --c1: #4C4D90; --c2: #101137; }
.ph-thumb--g2 { --c1: #F2B816; --c2: #A493AF; }
.ph-thumb--g3 { --c1: #A493AF; --c2: #4C4D90; }
.ph-thumb--g4 { --c1: #101137; --c2: #4C4D90; }
.ph-thumb--g5 { --c1: #EAD9D6; --c2: #A493AF; }
.ph-thumb--g6 { --c1: #4C4D90; --c2: #F2B816; }

/* ---- About: portrait + intro --------------------------------------------- */
.about-head { display: flex; gap: 28px; align-items: flex-start; }

/* About portrait — a real photo, no frame. */
.about-photo {
  width: 300px;
  max-width: 100%;
  flex-shrink: 0;
}
.about-photo img { display: block; width: 100%; height: auto; }

/* ---- Article / case reading page ----------------------------------------- */
/* A read-in-full page (a post or a case write-up) drops the space-eating 2x2 nav
   for a single back link, and reads in a narrower column. Same header/footer chrome
   as the rest of the site. Template lives in article.html. */
.article { max-width: 720px; margin: 0 auto; }

.article-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  transition: color 200ms ease-out;
}
.article-back:hover { color: var(--indigo); }

/* Wide colourful banner — stands in for the role the nav grid played at the top of
   the other pages (uses the same brand gradients as the placeholder thumbs). */
.article-hero {
  aspect-ratio: 21 / 9;
  margin: 28px 0 32px;
  border: 1px solid var(--indigo);
}

/* Reading title: larger + sentence-case (the uppercase .page-title spec is for the
   short section landing pages; a long post headline reads better mixed-case). */
.article-title {
  font-size: 34px;
  text-transform: none;
  letter-spacing: -0.02em;
  margin-bottom: 12px;
}

.article-meta {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 28px;
}

.pull-quote {
  border-left: 3px solid var(--accent);
  padding-left: 22px;
  margin: 32px 0;
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 22px;
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--text);
  text-wrap: balance;
}

.article-figure { margin: 32px 0; }
.article-figure .ph-thumb,
.article-figure img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--indigo);
}
.article-figure figcaption { margin-top: 10px; font-size: 14px; color: var(--muted); }

.article-foot {
  max-width: 720px;
  margin: 48px auto 0;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}

/* ---- Footer (full-width, dark) ------------------------------------------- */
.site-footer {
  background: var(--footer-bg);
  color: var(--footer-text);
  padding: 48px 0;
  margin-top: 96px;
  flex-shrink: 0;        /* never compress the footer to fit the flex column */
}
.footer-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--pad);
  display: flex;
  /* top-align so the tagline's position doesn't shift when the right-hand button
     stack grows taller (it sits next to the top "AI usage statement" button) */
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
}
.footer-text { color: var(--footer-text); }

/* Group for the footer recess buttons (AI usage statement on top, On AI ethics below):
   a right-aligned vertical stack at the end of the footer row. */
.footer-links { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; }

/* AI-usage link = a SMALL recess button, the same two-layer material as the nav tiles
   (the ::before/::after + slide rules live up in the shared recess block, where
   .footer-link is added to each selector). Scoped here to the footer's always-dark
   surface: it forces the dark-recess palette + tighter knobs in BOTH themes, since the
   footer is navy even in light mode. */
.footer-link {
  position: relative;        /* anchor the recess layers */
  isolation: isolate;        /* confine the ::before multiply to the button */
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  border: 1px solid rgba(236, 231, 242, 0.30);
  padding: 10px 18px;
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--footer-text);
  background: transparent;
  /* dark-surface recess palette + smaller knobs, forced regardless of theme */
  --wall: 5px; --wall-press: 7px; --shadow: 10px; --shadow-press: 12px;
  --recess-wall: #05041E;
  --recess-blend: rgba(12, 12, 38, 0.35);
  --recess-face: #191A44;
  transition: background-color 200ms ease-out, color 200ms ease-out;
}
.footer-link-label { display: inline-block; position: relative; transition: transform 200ms ease-out; }
.footer-link:hover, .footer-link:focus-visible { color: var(--accent); }
/* Left column = tagline stacked above the colophon, so the two stay tight together
   regardless of how tall the right-hand button stack grows. */
.footer-textcol { display: flex; flex-direction: column; gap: 12px; }
.footer-colophon {
  font-size: 13px;
  opacity: 0.6;
  color: var(--footer-text);
}

/* ---- Responsive ----------------------------------------------------------- */
@media (max-width: 768px) {
  .site-header { padding: 32px 0 24px; }
  .site-title { font-size: 22px; }
  .site-subtitle { font-size: 22px; }
  .logo { height: 64px; width: auto; }
  .social-tile { width: 60px; height: 60px; }
  .social-tile img { width: 28px; height: 28px; }

  .nav-tile { padding: 24px 12px; font-size: 18px; letter-spacing: 0.08em; }

  /* stacked image-over-text; release the desktop fixed square height (revisit for
     a proper mobile treatment later) */
  .post-card { flex-direction: column; height: auto; }
  .post-image-cell { width: 100%; min-height: 160px; }

  .footer-inner { flex-direction: column; align-items: flex-start; }

  .visual-grid { grid-template-columns: 1fr 1fr; }
  .about-head { flex-direction: column; gap: 20px; }

  .article-title { font-size: 26px; }
  .pull-quote { font-size: 19px; }
}

/* ---- Keyboard focus — hard single-colour ring matching the borders -------- */
:focus-visible { outline: 2px solid var(--indigo); outline-offset: 2px; }

/* ---- Typography & finishing polish (v=25) --------------------------------- */
/* Balance short headings so the last line isn't lopsided / a lone word; prettify
   body copy so paragraphs don't end on an orphan. Both are progressive enhancement
   (older browsers just ignore them). */
.site-title, .site-subtitle, .intro-title, .page-title, .section-bar,
.post-title { text-wrap: balance; }
.intro-text, .post-excerpt, .prose p { text-wrap: pretty; }

/* Brand-tinted selection + scrollbar + form-control accents — small cues that the
   palette is deliberate. --indigo/--bg both flip in dark mode, so this stays legible. */
::selection { background: var(--indigo); color: var(--bg); }
html { accent-color: var(--indigo); scrollbar-color: var(--indigo) transparent; }

/* ---- Dark mode (toggled via [data-theme]; a tiny head script sets it from
   localStorage, falling back to the OS preference) -------------------------- */
:root[data-theme="dark"] {
  --bg: #101137;          /* deep navy page + button faces (rest) */
  --text: #ECE7F2;        /* light ink */
  --indigo: #A6A4E0;      /* lifted indigo for borders, title, nav */
  --subtitle: #8E86AE;
  --muted: #ABA5C6;
  --border: var(--indigo);  /* match the nav's strong purple in dark too */
  --recess-wall: #05041E;   /* recess wall (dark) */
  --recess-blend: rgba(12, 12, 38, 0.35); /* #0C0C26 @ 35% — dark recess shadow (multiplied; a true dark dip, not light-pooling) */
  --recess-face: #191A44;   /* recessed face still lightens (the face catches light; the shadow darkens it) */
  --tile: #1E1E38;
  --footer-bg: #05051A;
  --footer-text: #ECE7F2;
}
/* lift the (baked-indigo) CV icon so it stays visible on the dark page */
[data-theme="dark"] .social-tile.cv img { filter: brightness(1.7); }

/* Recess shadow stays multiply in both themes — light uses a warm tint, dark uses a
   near-black navy (--recess-blend), so the dip genuinely darkens on the dark page. */

/* ---- Reduced motion: keep the recess feedback, drop the sliding motion ----- */
@media (prefers-reduced-motion: reduce) {
  .nav-tile, .nav-label, .nav-label::after, .social-tile, .social-tile img,
  .nav-tile::before, .nav-tile::after, .social-tile::before, .social-tile::after,
  .footer-link, .footer-link-label, .footer-link::before, .footer-link::after,
  .post-card, .post-card > *, .post-card::before,
  .post-card.reveal, .post-card.reveal.in { transition: none !important; }
  .nav-tile:hover .nav-label, .nav-tile:active .nav-label, .nav-tile.active .nav-label,
  .social-tile:hover img, .social-tile:active img,
  .social-tile:hover svg, .social-tile:active svg,
  .footer-link:hover .footer-link-label, .footer-link:active .footer-link-label,
  .post-card:hover > * { transform: none !important; }
  .post-card.reveal { opacity: 1 !important; transform: none !important; }
  /* keep page swaps a plain instant fade — no rise */
  ::view-transition-new(root) { animation: vt-out 120ms ease reverse both; }
  /* don't cross-fade the pinned header/nav groups either */
  ::view-transition-group(*) { animation-duration: 0.01ms !important; }
}
