/* ===========================================================================
   Motion & imagery layer.
   Icons, generated cover art, hover transformations, scroll behaviour.
   Loaded after main.css, which owns the design tokens.
   ======================================================================== */

/* ---------------------------------------------------------------------- */
/* Icons                                                                   */
/* ---------------------------------------------------------------------- */

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.icon {
  width: 1em;
  height: 1em;
  flex: none;
  vertical-align: -0.125em;
  stroke-linecap: square;
  stroke-linejoin: miter;
  transition: transform .22s var(--ease);
}

/* Small mono labels want a slightly larger glyph to stay legible. */
.label .icon,
.meta .icon,
.article-meta .icon,
.post-aside .icon,
.entry-link .icon,
.card-links .icon,
.footer-links .icon { width: 1.15em; height: 1.15em; }

.section-title .icon { color: var(--accent); width: .82em; height: .82em; }

/* ---------------------------------------------------------------------- */
/* Page scroll progress                                                    */
/* ---------------------------------------------------------------------- */

.scroll-progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 2px;
  z-index: 60;
  background: transparent;
  pointer-events: none;
}
.scroll-progress span {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

/* ---------------------------------------------------------------------- */
/* Masthead detail                                                         */
/* ---------------------------------------------------------------------- */

.wordmark { display: inline-flex; align-items: center; gap: 10px; }

/* A small square that rotates into a diamond on hover. */
.wordmark-mark {
  width: 12px;
  height: 12px;
  background: var(--accent);
  transition: transform .4s var(--ease), border-radius .4s var(--ease);
}
.wordmark:hover .wordmark-mark { transform: rotate(45deg) scale(1.12); }

/* Nav underline sweeps in from the left. */
.nav a span {
  display: inline-block;
  position: relative;
  padding-bottom: 3px;
}
.nav a span::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform .28s var(--ease);
}
.nav a:hover span::after { transform: scaleX(1); }

/* Theme toggle: the two glyphs stack and cross-fade. */
.theme-icons {
  position: relative;
  display: block;
  width: 15px;
  height: 15px;
}
.theme-icons .icon {
  position: absolute;
  inset: 0;
  width: 15px;
  height: 15px;
  transition: opacity .3s var(--ease), transform .45s var(--ease);
}
.theme-icons .is-sun  { opacity: 0; transform: rotate(-90deg) scale(.5); }
.theme-icons .is-moon { opacity: 1; transform: none; }
[data-theme="dark"] .theme-icons .is-sun  { opacity: 1; transform: none; }
[data-theme="dark"] .theme-icons .is-moon { opacity: 0; transform: rotate(90deg) scale(.5); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-icons .is-sun  { opacity: 1; transform: none; }
  :root:not([data-theme="light"]) .theme-icons .is-moon { opacity: 0; transform: rotate(90deg) scale(.5); }
}

.ghost-btn:hover .icon { transform: scale(1.12); }

/* ---------------------------------------------------------------------- */
/* Cover artwork                                                           */
/* ---------------------------------------------------------------------- */

.cover {
  position: relative;
  overflow: hidden;
  background: var(--field);
  border: var(--hair) solid var(--rule);
}
.cover-card { aspect-ratio: 400 / 260; }
.cover-wide { aspect-ratio: 21 / 8; }
.cover-square { aspect-ratio: 1; }

.cover > svg,
.cover > img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .7s var(--ease), filter .5s var(--ease);
}

/* A hairline grid laid over the art, so it reads as an editorial plate. */
.cover-veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--paper) 32%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--paper) 32%, transparent) 1px, transparent 1px);
  background-size: 34px 34px;
  opacity: .5;
  transition: opacity .5s var(--ease);
}

/* ---------------------------------------------------------------------- */
/* Card hover transformations                                              */
/* ---------------------------------------------------------------------- */

.rail-item,
.project-card {
  position: relative;
  transition: transform .4s var(--ease);
}

/* An accent rule wipes across the top edge on hover. */
.rail-item::before,
.project-card::before {
  content: "";
  position: absolute;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform .38s var(--ease);
}
.rail-item:hover::before,
.project-card:hover::before { transform: scaleX(1); }

.rail-item:hover { transform: translateY(-6px); }

/* Grid cells carry their own rules, so shifting them would drag the
   hairlines with them -- inset the content instead of lifting the card. */
.project-card { transition: padding-left .34s var(--ease); }
.project-card:hover { padding-left: 14px; }

.rail-item:hover .cover > svg,
.rail-item:hover .cover > img,
.project-card:hover .cover > svg,
.project-card:hover .cover > img { transform: scale(1.07); }

.rail-item:hover .cover-veil,
.project-card:hover .cover-veil { opacity: .12; }

.rail-item:hover .card-title,
.project-card:hover .card-title { color: var(--accent); }

.has-cover .cover,
.project-card .cover { margin-bottom: 18px; }

.project-card { padding-top: 26px; }

.card-org { display: inline-flex; align-items: center; gap: 7px; margin-bottom: 14px; }

/* Stack chips shift up in sequence when the card is hovered. */
.stack li { transition: background .25s var(--ease), color .25s var(--ease); }
.rail-item:hover .stack li,
.project-card:hover .stack li { background: var(--accent-soft); }

/* Link icons slide out of the card edge. */
.card-links a:hover .icon { transform: translate(2px, -2px); }

/* ---------------------------------------------------------------------- */
/* Index rows                                                              */
/* ---------------------------------------------------------------------- */

.row-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  color: var(--accent);
  opacity: 0;
  transform: translateX(-8px);
  transition: opacity .28s var(--ease), transform .28s var(--ease);
}
.post-row > a:hover .row-arrow { opacity: 1; transform: none; }

.post-row > a { position: relative; }

/* Background wipe from the left, instead of a flat colour swap. */
.post-row > a::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--field);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform .4s var(--ease);
}
/* Content rides above the wipe. */
.post-row > a > * { position: relative; z-index: 1; }
.post-row > a:hover::before { transform: scaleX(1); }

.post-row > a:hover { background: none; }

.post-week { transition: transform .28s var(--ease); display: inline-block; }
.post-row > a:hover .post-week { transform: translateX(4px); }

@media (max-width: 680px) {
  .post-row > a { grid-template-columns: 60px minmax(0, 1fr); }
  .row-arrow { display: none; }
}

/* Floating preview that tracks the cursor over an index row. */
.hover-peek {
  position: fixed;
  top: 0; left: 0;
  width: 260px;
  z-index: 70;
  pointer-events: none;
  opacity: 0;
  transform: translate3d(0, 0, 0) scale(.9) rotate(-3deg);
  transition: opacity .28s var(--ease), transform .28s var(--ease);
  will-change: transform;
}
.hover-peek.is-on { opacity: 1; }
.hover-peek .cover { border: 2px solid var(--ink); }
.hover-peek .cover-veil { opacity: .18; }

@media (hover: none), (max-width: 900px) { .hover-peek { display: none; } }

/* ---------------------------------------------------------------------- */
/* Hero                                                                    */
/* ---------------------------------------------------------------------- */

.hero-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(180px, 24vw, 290px);
  gap: clamp(20px, 4vw, 56px);
  align-items: center;
  margin-bottom: 34px;
}

.hero-art {
  position: relative;
  margin: 0;
  border: 2px solid var(--ink);
  will-change: transform;
}
.hero-art > svg,
.hero-art > img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
}
.hero-art figcaption {
  position: absolute;
  left: -2px; bottom: -2px;
  background: var(--ink);
  color: var(--paper);
  padding: 6px 11px;
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.hero-statement { margin-bottom: 0; }

@media (max-width: 820px) {
  .hero-top { grid-template-columns: 1fr; }
  .hero-art { max-width: 220px; }
}

/* Headline words rise into place, one after another. */
[data-split] .word {
  display: inline-block;
  opacity: 0;
  transform: translateY(.5em);
  animation: word-in .7s var(--ease) forwards;
}
@keyframes word-in {
  to { opacity: 1; transform: none; }
}

.hero-stat dt { display: inline-flex; align-items: center; gap: 6px; }
.hero-stat dd { transition: color .3s var(--ease); }
.hero-stats:hover dd { color: var(--accent); }

.hero-links a { position: relative; overflow: hidden; }
.hero-links a .icon { transition: transform .3s var(--ease); }
.hero-links a:hover .icon { transform: translateY(-2px) scale(1.1); }

/* ---------------------------------------------------------------------- */
/* Article cover                                                           */
/* ---------------------------------------------------------------------- */

.article-cover {
  margin: clamp(26px, 4vw, 44px) 0 0;
  will-change: transform;
}
.article-cover .cover { border: 2px solid var(--ink); }

.back-link .icon { transition: transform .25s var(--ease); }
.back-link:hover .icon { transform: translateX(-4px); }
.back-link:hover { color: var(--accent); }

.article-meta a {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border-bottom: var(--hair) solid var(--rule);
  padding-bottom: 1px;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.article-meta a:hover { color: var(--accent); border-color: var(--accent); }
.article-meta > span { display: inline-flex; align-items: center; gap: 6px; }

.post-nav .label .icon { transition: transform .25s var(--ease); }
.post-nav a:hover .label .icon { transform: translateX(-4px); }
.post-nav a + a:hover .label .icon { transform: translateX(4px); }

/* ---------------------------------------------------------------------- */
/* Buttons & filters                                                       */
/* ---------------------------------------------------------------------- */

.btn { position: relative; overflow: hidden; }
.btn > * { position: relative; z-index: 1; }

/* Accent fill rises from the bottom edge. */
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform .34s var(--ease);
}
.btn:hover::before { transform: scaleY(1); }
.btn:hover { background: var(--ink); color: #fff; border-color: var(--accent); }
.btn-ghost:hover { color: #fff; }
.btn:hover .icon { transform: translateY(-2px); }

.filter-icon { color: var(--accent); display: inline-flex; margin-right: 2px; }

.filter-btn { position: relative; overflow: hidden; }
.filter-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform .3s var(--ease);
}
.filter-btn > * { position: relative; z-index: 1; }
.filter-btn:hover::before { transform: scaleY(1); }
.filter-btn:hover { color: var(--paper); border-color: var(--ink); }

.entry-badge { color: var(--accent); opacity: 0; transition: opacity .3s var(--ease); }
.entry:hover .entry-badge { opacity: 1; }

.entry { transition: padding-left .3s var(--ease); }
.entry:hover { padding-left: 10px; }
.entry:hover .entry-title { color: var(--accent); }
.entry-title { transition: color .25s var(--ease); }

.tl-item { transition: padding-left .3s var(--ease); }
.tl-item:hover { padding-left: 10px; }
.tl-item:hover .tl-role { color: var(--accent); }
.tl-role { transition: color .25s var(--ease); }

.skill-items li { transition: transform .25s var(--ease), background .25s var(--ease); }
.skill-items li:hover { transform: translateY(-3px); background: var(--accent-soft); }

/* ---------------------------------------------------------------------- */
/* Back to top                                                             */
/* ---------------------------------------------------------------------- */

.to-top {
  position: fixed;
  right: clamp(16px, 3vw, 34px);
  bottom: clamp(16px, 3vw, 34px);
  z-index: 50;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
  color: var(--ink);
  border: 2px solid var(--ink);
  cursor: pointer;
  opacity: 0;
  transform: translateY(14px);
  pointer-events: none;
  transition: opacity .3s var(--ease), transform .3s var(--ease),
              background .2s var(--ease), color .2s var(--ease);
}
.to-top.is-on { opacity: 1; transform: none; pointer-events: auto; }
.to-top:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.to-top .icon { width: 18px; height: 18px; }

/* ---------------------------------------------------------------------- */
/* Palette detail                                                          */
/* ---------------------------------------------------------------------- */

.palette-field {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-left: 20px;
  border-bottom: var(--hair) solid var(--rule);
  color: var(--muted);
}
.palette-field .icon { width: 17px; height: 17px; }
.palette-input { border-bottom: 0; padding-left: 0; }

.palette-panel { animation: palette-in .28s var(--ease); }
@keyframes palette-in {
  from { opacity: 0; transform: translateY(-12px); }
  to { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------------- */
/* Staggered reveals                                                       */
/* ---------------------------------------------------------------------- */

.reveal { transition-delay: var(--delay, 0ms); }

/* Reveals that arrive from the side read better on index rows. */
.post-list .reveal,
.entry-list .reveal,
.timeline .reveal { transform: translateY(10px); }

@media (prefers-reduced-motion: reduce) {
  [data-split] .word { opacity: 1; transform: none; animation: none; }
  .hover-peek { display: none; }
  .scroll-progress span { transform: scaleX(0) !important; }
  .rail-item:hover, .project-card:hover, .entry:hover, .tl-item:hover { transform: none; }
}

@media print {
  .to-top, .scroll-progress, .hover-peek, .cover, .hero-art { display: none !important; }
}
