/* ── Tokens ──────────────────────────────────────────────────────────── */
:root {
  --ink: #1a1a1a;
  --mute: #8a8a8a;
  --paper: #ffffff;
  --accent: #6ba3c7;

  /* Surfaces & hairlines (used by tweaks panel, chips, dashed rules) */
  --surface: #ffffff;
  --border: #e0e0e0;
  --border-soft: #ececec;

  --font-sans: "Inter", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", Menlo, monospace;
  --font-hand: "Gloria Hallelujah", cursive;
  --font-prose: "Crimson Pro", "EB Garamond", Georgia, serif;

  /* SVG squiggle, regenerated by JS when --accent changes */
  --squiggle-bg: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 6' preserveAspectRatio='none'><path d='M0 3 Q 2.5 0, 5 3 T 10 3 T 15 3 T 20 3' fill='none' stroke='%236ba3c7' stroke-width='1.2'/></svg>");
}

/* ── Dark theme ──────────────────────────────────────────────────────── */
/* Cool near-black / warm cream — ice-blue accent glows against it. */
[data-theme="dark"] {
  --ink: #ece7d8;       /* warm cream — text reads softer than pure white */
  --mute: #8a857a;      /* warm muted gray — keeps meta readable */
  --paper: #0e1013;     /* deep cool near-black — bg */
  --accent: #6ba3c7;    /* mid-blue — contrasts on white, still pops on dark */
  --surface: #1a1d22;   /* cool lifted panel */
  --border: #2a2e34;    /* cool hairline */
  --border-soft: #20242a;
}

/* Smooth palette swap after first paint (gated so it doesn't fire on load). */
html.theme-ready,
html.theme-ready body {
  transition: background-color 0.35s ease, color 0.35s ease;
}

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

html, body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
}

::selection { background: var(--ink); color: var(--paper); }

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

/* ── Paragraph view ─────────────────────────────────────────────────── */
/* Mostly white paper with two soft accent washes — strong in the
   top-left, quieter in the bottom-right, fading to paper through the
   middle reading column. color-mix keeps the tint consistent if the
   user swaps the accent from the tweaks panel. */
.view-paragraph {
  min-height: 100vh;
  color: var(--ink);
  padding: 80px 32px 60px;
  background:
    radial-gradient(ellipse 900px 520px at 15% -8%,
      color-mix(in oklab, var(--accent) 40%, transparent) 0%,
      color-mix(in oklab, var(--accent) 13%, transparent) 35%,
      var(--paper) 70%),
    radial-gradient(ellipse 700px 500px at 100% 100%,
      color-mix(in oklab, var(--accent) 25%, transparent) 0%,
      transparent 60%),
    var(--paper);
}

.paragraph-inner {
  max-width: 620px;
  margin: 0 auto;
}

.name {
  font-family: var(--font-hand);
  font-size: 64px;
  font-weight: 400;
  line-height: 0.95;
  margin: 0 0 4px;
  letter-spacing: 0;
}

.subtitle {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--mute);
  letter-spacing: 0.3px;
  margin: 0 0 36px;
}

.prose {
  font-family: var(--font-prose);
  font-size: 19px;
  line-height: 1.55;
  margin: 0 0 16px;
  color: var(--ink);
}

.prose:first-of-type { margin-top: 0; }

.prose em { font-style: italic; }

/* 0 → 1 inline chip */
.arrow {
  font-family: var(--font-mono);
  font-size: 16px;
}

/* Solid underline (companies) — matches .email-pill hover language:
   currentColor underline + accent on hover, so the two inline link
   patterns feel like one system. */
.u-solid {
  border-bottom: 1.5px solid currentColor;
  cursor: pointer;
  transition: color 0.15s;
  /* Works on both <span> and <a class="u-solid"> — the border-bottom is
     the only underline, so kill the anchor default and inherit prose color. */
  color: inherit;
  text-decoration: none;
}

.u-solid:hover,
.u-solid:focus-visible {
  color: var(--accent);
}

/* Dotted underline (AI paragraph highlights) */
.u-dotted {
  border-bottom: 1.5px dotted var(--accent);
}

/* Wavy squiggle that spans the full wrapping phrase */
.squiggle {
  background-image: var(--squiggle-bg);
  background-repeat: repeat-x;
  background-position: left 100%;
  background-size: 10px 6px;
  padding-bottom: 6px;
}

/* ── Stack (tech pill chips) ────────────────────────────────────────── */
/* Slots into the prose flow between career + AI-tools paragraphs. Tokens
   only — recolors with the tweaks panel. A subtle border-to-accent hover
   mirrors the .u-solid / .email-pill interaction language. */
.stack {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 16px;
}

.stack-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 6px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1;
  color: var(--ink);
  background: transparent;
  transition: border-color 0.15s, color 0.15s;
}

.stack-pill:hover {
  border-color: var(--ink);
  color: var(--accent);
}

.stack-pill img {
  width: 15px;
  height: 15px;
  display: block;
}

/* Near-black brand marks (Next.js, GitHub, Vercel…) disappear on the
   near-black dark paper. Flip them so they read as cream. */
[data-theme="dark"] .stack-pill[data-invert-dark] img {
  filter: invert(1);
}

/* ── Email link (inline mailto:) ─────────────────────────────────────── */
.email-pill {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  position: relative;
  transition: color 0.15s;
}

.email-pill .email-text {
  border-bottom: 1.5px solid currentColor;
  transition: border-color 0.15s;
  overflow-wrap: break-word;
}

.email-pill:hover,
.email-pill:focus-visible { color: var(--accent); }

/* Resting: plain envelope. On hover, it gets startled —
   quick jump with a nervous head-shake, then settles back. */
.email-icon {
  display: inline-block;
  width: 18px;
  height: 18px;
  vertical-align: -0.3em;
  margin-right: 4px;
  overflow: visible;
  transform-origin: 50% 60%;
}

.email-icon path {
  fill: currentColor;
}

@keyframes email-startle {
  0%   { transform: translateY(0) rotate(0deg); }
  12%  { transform: translateY(-5px) rotate(-14deg); }
  26%  { transform: translateY(-6px) rotate(12deg); }
  42%  { transform: translateY(-3px) rotate(-8deg); }
  58%  { transform: translateY(-1px) rotate(5deg); }
  76%  { transform: translateY(0) rotate(-2deg); }
  100% { transform: translateY(0) rotate(0deg); }
}

.email-pill:hover .email-icon,
.email-pill:focus-visible .email-icon {
  animation: email-startle 620ms cubic-bezier(0.3, 0.7, 0.3, 1) both;
}

/* ── Chips (handwritten marker links) ───────────────────────────────── */
/* Big hand-script row — echoes the name up top. Each chip sways gently
   at rest at its own phase; on hover it lifts and tilts at its own
   angle with a springy overshoot. */
.chips {
  margin: 1.5rem 0 2rem;
  display: flex;
  gap: 1.4em;
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--ink);
  cursor: default;
  -webkit-user-select: none;
  user-select: none;
}

.chips a {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  display: inline-block;
  transform-origin: 50% 80%;
  transition:
    transform 180ms cubic-bezier(0.34, 1.56, 0.64, 1),
    color 120ms ease;
  animation: chip-sway 6s ease-in-out infinite;
  -webkit-user-select: none;
  user-select: none;
}

.chips a:nth-child(1) { animation-delay: 0s; }
.chips a:nth-child(2) { animation-delay: -1.5s; }
.chips a:nth-child(3) { animation-delay: -3s; }
.chips a:nth-child(4) { animation-delay: -4.5s; }

@keyframes chip-sway {
  0%, 100% { transform: rotate(-0.4deg); }
  50%      { transform: rotate(0.4deg); }
}

.chips a:hover {
  color: var(--accent);
  animation: none;
}

.chips a:nth-child(1):hover { transform: translateY(-2px) rotate(-2deg); }
.chips a:nth-child(2):hover { transform: translateY(-2px) rotate(1.5deg); }
.chips a:nth-child(3):hover { transform: translateY(-2px) rotate(-1deg); }
.chips a:nth-child(4):hover { transform: translateY(-2px) rotate(2deg); }

.chips a:active {
  transform: translateY(0) rotate(0);
  transition-duration: 80ms;
}

.chips a:focus-visible {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
  outline: none;
}

@media (max-width: 640px) {
  .chips {
    font-size: 1.25rem;
    flex-wrap: wrap;
    row-gap: 0.4em;
    gap: 1em;
  }
}

/* ── Footer (ladder loop + theme toggle) ────────────────────────────── */
.paragraph-footer {
  margin-top: 60px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--mute);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.ladder {
  display: inline-block;
  line-height: 1.2;
  vertical-align: middle;
  white-space: nowrap;
  min-width: 0;
}

.ladder-caret {
  display: inline-block;
  width: 0.55em;
  height: 1em;
  margin-left: 2px;
  background: var(--accent);
  vertical-align: -0.12em;
  animation: ladder-caret-blink 1.05s linear infinite;
}

/* Just the leading "©" glyph — JetBrains Mono renders it high (up
   near the ascender), so we pull it down to seat on the baseline
   with the rest of the line. Scoped to this one span so no other
   text in the footer is affected. */
.copyright-glyph {
  display: inline-block;
  vertical-align: -0.2em;
}

/* While typing or erasing, keep the caret steadily on — the motion
   itself already signals activity; a second blink reads as noise. */
.ladder.is-busy .ladder-caret {
  animation: none;
  opacity: 1;
}

@keyframes ladder-caret-blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* ── Theme toggle ────────────────────────────────────────────────────── */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--mute);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  flex-shrink: 0;
  transition: color 0.2s ease, transform 0.25s cubic-bezier(0.6, 0, 0.2, 1);
}

.theme-toggle:hover,
.theme-toggle:focus-visible {
  color: var(--accent);
  transform: rotate(15deg);
}

.theme-toggle svg {
  display: block;
  width: 14px;
  height: 14px;
}

/* Light mode: show moon (click to go dark). Dark mode: show sun. */
.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: block; }

[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* ── Tweaks panel ───────────────────────────────────────────────────── */
.tweaks-panel {
  position: fixed;
  bottom: 20px;
  right: 20px;
  width: 280px;
  background: var(--surface);
  border: 1.5px solid var(--ink);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.13);
  font-family: var(--font-sans);
  z-index: 1000;
  padding: 16px;
}

.tweaks-panel[hidden] { display: none; }

.tweaks-header {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 2px;
  color: var(--mute);
  margin-bottom: 12px;
}

.tweaks-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
  font-size: 12px;
}

.tweaks-label {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--mute);
  width: 58px;
  text-transform: uppercase;
  letter-spacing: 1px;
  flex-shrink: 0;
}

.tweaks-group {
  display: flex;
  gap: 4px;
}

.tweaks-group-wrap { flex-wrap: wrap; }

.tweaks-group[data-group="accent"] { gap: 5px; }
.tweaks-group[data-group="paper"] { gap: 5px; }

.chip {
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 4px 8px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.chip.is-active {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--paper);
}

.swatch,
.paper-swatch {
  width: 22px;
  height: 22px;
  border: 1px solid var(--border);
  background: var(--ink);
  cursor: pointer;
  padding: 0;
  -webkit-appearance: none;
  appearance: none;
}

.swatch { border-radius: 0; }

.swatch.is-active,
.paper-swatch.is-active {
  border: 2px solid var(--ink);
}

.tweaks-footer {
  font-family: var(--font-mono);
  font-size: 9px;
  color: var(--mute);
  margin-top: 8px;
}

.tweaks-footer kbd {
  font-family: var(--font-mono);
  font-size: 9px;
  padding: 1px 4px;
  border: 1px solid var(--mute);
  border-radius: 2px;
}

/* ── Intro animation ────────────────────────────────────────────────── */
/* First-paint sequence, orchestrated from portfolio.js:
     1. `.name` handwrites in (clip-path reveal, ~1.3s)
     2. `.subtitle` types out char-by-char with a blinking caret
     3. `.prose`, `.chips`, `.paragraph-footer` fade + rise, staggered
   Initial hidden states are gated behind `html.js-ready` so no-JS
   visitors still see everything. The inline script in <head> sets
   `.js-ready` before first paint, so there's no unstyled flash. */

html.js-ready .name {
  clip-path: inset(0 100% 0 0);
  will-change: clip-path;
}

html.js-ready .name.is-written {
  animation: name-handwrite 1300ms cubic-bezier(0.55, 0.05, 0.25, 1) both;
}

@keyframes name-handwrite {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

/* Preserve one-line height while JS clears textContent to retype. */
html.js-ready .subtitle {
  min-height: 1.2em;
  opacity: 0;
}

html.js-ready .subtitle.is-typing,
html.js-ready .subtitle.is-typed {
  opacity: 1;
}

/* Blinking block caret that rides along with the typed text.
   `::after` is attached to the <p>, so it sits at the end of whatever
   textContent currently is — which grows one char per tick.
   Shape + cadence are shared with `.ladder-caret` so both carets on the
   page read as one thing. */
html.js-ready .subtitle.is-typing::after {
  content: "";
  display: inline-block;
  width: 0.55em;
  height: 1em;
  margin-left: 2px;
  background: var(--accent);
  vertical-align: -0.12em;
  animation: ladder-caret-blink 1.05s linear infinite;
}

/* Prose paragraphs, chips row, and footer all share one fade-rise.
   The stagger is applied via JS by toggling `.is-in` at the right
   moment — simpler than per-index delays and survives reordering. */
html.js-ready .prose,
html.js-ready .stack,
html.js-ready .chips,
html.js-ready .paragraph-footer {
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 720ms ease-out,
    transform 720ms cubic-bezier(0.2, 0.7, 0.25, 1);
  will-change: opacity, transform;
}

html.js-ready .prose.is-in,
html.js-ready .stack.is-in,
html.js-ready .chips.is-in,
html.js-ready .paragraph-footer.is-in {
  opacity: 1;
  transform: translateY(0);
}

/* ── Responsive ─────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  .view-paragraph { padding: 56px 22px 56px; }
  .name { font-size: 52px; }
  .prose { font-size: 17px; }
  .footnotes { gap: 16px; }
}

@media (max-width: 520px) {
  .email-text { word-break: break-word; }
}

/* ── Motion preferences ─────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .ladder-caret { animation: none !important; opacity: 1; }
  .email-icon { animation: none !important; }
  .theme-toggle { transition: color 0.2s ease !important; }
  .theme-toggle:hover,
  .theme-toggle:focus-visible { transform: none !important; }
  /* Kill the idle sway and the per-chip rotation, keep the lift. */
  .chips a { animation: none !important; transform: none !important; }
  .chips a:nth-child(1):hover,
  .chips a:nth-child(2):hover,
  .chips a:nth-child(3):hover,
  .chips a:nth-child(4):hover {
    transform: translateY(-2px) !important;
  }
  html.theme-ready,
  html.theme-ready body { transition: none !important; }

  /* Intro animation: snap to final state, skip the reveal. */
  html.js-ready .name {
    clip-path: none !important;
    animation: none !important;
  }
  html.js-ready .subtitle {
    opacity: 1 !important;
  }
  html.js-ready .subtitle.is-typing::after { display: none !important; }
  html.js-ready .prose,
  html.js-ready .stack,
  html.js-ready .chips,
  html.js-ready .paragraph-footer {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ── Print ──────────────────────────────────────────────────────────── */
@media print {
  @page { margin: 0; }

  html, body {
    background: var(--paper);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .tweaks-panel { display: none !important; }

  * { animation: none !important; transition: none !important; }
}
