/* ══════════════════════════════════════════════════════════════════════
   ncmbianchi.github.io — stylesheet
   Primary font: JetBrains Mono (Google Fonts)
   Style reference: bashbunni.dev — terminal-inspired, minimal
   Colour system: Afterglow dark, fixed site-wide (matches the index.html
   terminal — no light/dark toggle; every page is the same theme).
   ══════════════════════════════════════════════════════════════════════ */

/* ── 1. Design tokens — Afterglow dark (fixed, site-wide) ────────────── */
:root {
  /* Colours — Afterglow palette by YabataDesign, same as the landing terminal */
  --color-bg:              #2e2e2e;
  --color-bg-translucent:  rgba(46, 46, 46, 0.92);
  --color-surface:         #383838;
  --color-surface-alt:     #424242;
  --color-border:          #4d4d4d;
  --color-text:            #d6d6d6;
  --color-text-muted:      #9a9a95;
  --color-accent:          #9f4e85;   /* Afterglow magenta — TUI selected/hover */
  --color-accent-hover:    #b5679c;
  --color-accent-2:        #6c99bb;   /* Afterglow blue — pub/pres year */
  --color-accent-3:        #7e8e50;   /* Afterglow green — pub venue / pres event */
  --color-accent-4:        #e5b567;   /* Afterglow yellow — JS language tag */
  --color-accent-5:        #ac4142;   /* Afterglow red — Rust language tag */
  --color-accent-6:        #7dd6cf;   /* Afterglow cyan — repo latest-commit line */
  --color-accent-7:        #ff8800;   /* Afterglow orange — Shell language tag, same as .tc-host/.nav-host */
  --color-heading:         #f2f2ee;

  /* Typography — JetBrains Mono as primary (terminal aesthetic) */
  --font-base: 'JetBrains Mono', 'Geist Mono', ui-monospace, 'Cascadia Code',
               'Fira Code', monospace;
  --font-mono: 'JetBrains Mono', 'Geist Mono', ui-monospace, monospace;

  /* Type scale */
  --text-xs:   0.72rem;
  --text-sm:   0.85rem;
  --text-base: 1rem;
  --text-lg:   1.1rem;
  --text-xl:   1.25rem;
  --text-2xl:  1.45rem;
  --text-3xl:  1.75rem;
  --text-4xl:  2.1rem;

  /* Spacing */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-6:  1.5rem;
  --space-8:  2rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-24: 6rem;

  /* Layout */
  --container-max: 860px;
  --header-height: 52px;
  --radius-sm:   4px;
  --radius-md:   10px;
  --radius-lg:   16px;
  --radius-pill: 9999px;

  /* Transitions */
  --transition-fast: 150ms ease;
  --transition-base: 250ms ease;

  /* Shadows — deeper, for a dark surface */
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.30);
  --shadow-md: 0 6px 20px rgba(0, 0, 0, 0.40);
}

/* ── 3. Reset & base ───────────────────────────────────────────────── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-height);
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--font-base);
  font-size: var(--text-base);
  line-height: 1.75;
  color: var(--color-text);
  background-color: var(--color-bg);
}

a {
  color: var(--color-accent);
  text-decoration: none;
  transition: color var(--transition-fast);
}

a:hover {
  color: var(--color-accent-hover);
  text-decoration: underline;
}

img {
  max-width: 100%;
  display: block;
}

ul {
  list-style: none;
}

/* ── 4. Layout helpers ─────────────────────────────────────────────── */
.container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-6);
}

.section {
  padding-block: var(--space-24);
}

.section-title {
  font-size: var(--text-2xl);
  font-weight: 700;
  color: var(--color-heading);
  margin-bottom: var(--space-2);
  position: relative;
  padding-bottom: var(--space-3);
}

.section-title::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 32px;
  height: 2px;
  background: var(--color-accent);
  border-radius: var(--radius-pill);
}

.section-sub {
  color: var(--color-text-muted);
  margin-bottom: var(--space-8);
  font-size: var(--text-sm);
}

/* ── 5. Navigation ─────────────────────────────────────────────────── */
/* Lives inside .page-shell (§5b) as a fixed-height flex row — it never
   scrolls with the content, so it needs no sticky/backdrop-blur treatment. */
#site-header {
  flex-shrink: 0;
  height: var(--header-height);
}

.nav-inner {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
}

/* Terminal-prompt host, e.g. on the landing page's `.tc-host` — links back home. */
.nav-host {
  flex-shrink: 0;
  margin-right: var(--space-6);
  padding-bottom: 8px;  /* matches .nav-links — keeps both vertically centered together */
  color: #ff8800;
  font-weight: 700;
  font-size: var(--text-sm);
  white-space: nowrap;
  text-decoration: none;
}

.nav-host:hover {
  text-decoration: underline;
}

/* Wraps .nav-links + the custom scroll indicator below it. Native OS
   scrollbars (even with overflow-x:scroll) fade/auto-hide on most platforms
   regardless of CSS — there's no reliable cross-browser way to force them
   permanently visible — so the real indicator is this custom bar (JS-driven,
   below) instead of relying on browser scrollbar chrome at all. */
.nav-links-wrap {
  position: relative;
  margin-left: auto;
  min-width: 0;
  padding-bottom: 8px;  /* room for the indicator bar below the labels */
}

/* min-width:0 lets this shrink below its content size inside the flex row
   (flex items default to min-width:auto — without this the row would just
   overflow the header instead of scrolling). Native scrollbar hidden — the
   indicator bar below is the only visible affordance now. */
.nav-links {
  display: flex;
  gap: var(--space-6);
  align-items: center;
  min-width: 0;
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
}

.nav-links::-webkit-scrollbar { display: none; }

/* Custom scroll indicator: a full-width track at 50% opacity white, and a
   thumb at 100% opacity white sized/positioned by JS (updateNavScrollbar in
   main.js) to the actual scroll proportion. JS hides it entirely (display:
   none) when nothing overflows — no scroll affordance needed if every item
   already fits. */
.nav-scrollbar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: rgba(255, 255, 255, 0.5);
  border-radius: 1px;
  pointer-events: none;
}

.nav-scrollbar-thumb {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  background: rgba(255, 255, 255, 1);
  border-radius: 1px;
}

/* Every item keeps its natural width — the row overflows (scrolls) instead
   of squeezing/wrapping labels when it doesn't fit. */
.nav-links li { flex-shrink: 0; }

/* Mirrors the TUI cell states (.tc-cell / .tc-cell--idle:hover): plain grey
   idle, magenta + a leading ▸ on hover. padding-left reserves the triangle's
   space up front so it doesn't shift the link text when it appears. */
.nav-links a {
  position: relative;
  padding-left: 1.1em;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--color-text);
  text-decoration: none;
  transition: color var(--transition-fast);
}

.nav-links a::before {
  content: '';
  position: absolute;
  left: 0;
}

/* current page: purple + underline, no arrow (the arrow is hover-only) */
.nav-links a.active {
  color: var(--color-accent);
  font-weight: 700;
  text-decoration: underline;
}

/* hovering any link (including the active one): purple + arrow, no underline —
   matches the TUI's idle/hover cell states, where the ▸ only ever appears on
   the item the pointer is actually over */
.nav-links a:hover {
  color: var(--color-accent);
  font-weight: 700;
  text-decoration: none;
}

.nav-links a:hover::before {
  content: '▸';
}

/* Hamburger — visible on small screens */
.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 28px;
  height: 28px;
  background: none;
  border: none;
  cursor: pointer;
  margin-left: auto;
  padding: 0;
}

.nav-toggle span {
  display: block;
  width: 100%;
  height: 2px;
  background: var(--color-text);
  border-radius: 2px;
  transition: transform var(--transition-base), opacity var(--transition-base);
}

/* ── 5b. Page shell (regular pages) ──────────────────────────────────── */
/* Same frame as .term-page below: a fixed 100vh flex column with a padded
   inset, so header + footer are always visible and only the middle content
   scrolls. Header/footer span the full inset width (no extra centering) —
   .container (§4) still centers the actual reading content inside it. */
.page-shell {
  height:     100vh;
  overflow:   hidden;
  display:    flex;
  flex-direction: column;
  padding:    2rem 3rem;
  box-sizing: border-box;
}

/* flex column so a trailing .api-attr (§14) sits pinned to the bottom of
   this box (flush above the footer) when content is short, instead of
   floating right after the content with a big gap below it; on tall/
   overflowing content it just appears after everything once scrolled down,
   still immediately before the footer either way. */
.page-content {
  flex:       1;
  min-height: 0;          /* critical for flex overflow, same as .term-content */
  overflow-y: auto;
  display:    flex;
  flex-direction: column;
}

.page-content > .section {
  flex: 1 0 auto;
}

/* ── 6. Full-page landing terminal (index.html only) ──────────────── */
/*
 * Afterglow palette by YabataDesign — https://github.com/YabataDesign/afterglow-theme
 * bg/fg now the site-wide --color-bg/--color-text tokens (§1); page-landing
 * only adds the full-viewport, no-scroll layout the terminal animation needs.
 */

body.page-landing {
  margin:   0;
  height:   100vh;
  overflow: hidden;
  display:  flex;
}

.term-page {
  flex:            1;
  display:         flex;
  flex-direction:  column;
  height:          100vh;
  padding:         2rem 3rem;
  box-sizing:      border-box;
  color:           #d6d6d6;
  font-family:     var(--font-mono);
  font-size:       0.88rem;
  line-height:     1.65;
}

.term-content {
  flex:       1;
  min-height: 0;          /* critical for flex overflow */
  overflow-y: auto;
  overflow-x: hidden;
}
.term-content::-webkit-scrollbar        { width: 4px; }
.term-content::-webkit-scrollbar-track  { background: transparent; }
.term-content::-webkit-scrollbar-thumb  { background: #4d4d4d; border-radius: 2px; }

/* Afterglow ANSI colour mapping for terminal chrome (fish theme exact values) */
.tc-host   { color: #ff8800; }   /* orange  — ssh_color: (set_color ff8800)      */
.tc-fish   { color: #7dd6cf; }   /* cyan    — success_color: (set_color cyan)    */
.tc-path   { color: #e5b567; }   /* yellow  — directory_color: $fish_color_quote */
.tc-sep    { color: #d6d6d6; }   /* fg      — normal_color: (set_color normal)   */
.tc-branch { color: #7e8e50; }   /* green   — repository_color: $fish_color_cwd  */
.tc-status { color: #d6d6d6; }   /* fg      — normal_color: (set_color normal)   */
.tc-cursor { color: #7dd6cf; animation: blink 0.75s step-end infinite; }
.tc-cmd    { color: #d6d6d6; }
.tc-head   { color: #7dd6cf; }
.tc-rule   { color: #4d4d4d; }

/* ── TUI cell styles ── */
/* disable ligatures + fix inline element alignment inside <pre> */
.term-tui {
  margin:                   0;
  margin-top:               0.3em;
  font-family:              inherit;
  font-size:                inherit;
  line-height:              inherit;
  white-space:              pre;
  font-feature-settings:    "liga" 0;
  font-variant-ligatures:   none;
  letter-spacing:           0;
  word-spacing:             0;
}
.term-tui a,
.term-tui span {
  display:         inline;
  margin:          0;
  padding:         0;
  border:          0;
  text-decoration: none;
}
.term-tui.animating { pointer-events: none; }

/* cell state colours */
.tc-cell          { color: #d6d6d6; font-weight: normal; }
.tc-cell--sel     { color: #9f4e85; font-weight: 700; }  /* Afterglow magenta — animation cursor */
.tc-cell--done    { color: #505050; }                     /* Afterglow bright-black */
.tc-cell--idle:hover { color: #9b8bf4; font-weight: 700; } /* lilac — interactive hover */
.tc-cell--done:hover { color: #9b8bf4; font-weight: 700; } /* ✓ swaps to ▸ on hover */

/* Lock each cell's 4-char prefix to an exact 4ch advance. The ▸ (U+25B8) and
   ✓ (U+2713) glyphs render wider/narrower than 1ch when the browser falls back
   to a symbol font, which drifts the data rows off the grid the border lines
   sit on. A fixed-width inline-block forces the label to start at exactly 4ch
   regardless of glyph advance. Scoped under .term-tui to beat the generic
   `.term-tui span { display: inline }` rule above. No overflow:hidden — it would
   shift the inline-block baseline and misalign the prefix vertically. */
.term-tui .tc-pfx { display: inline-block; width: 4ch; }

/* Same fallback-glyph drift as .tc-pfx above, but for the box-drawing chars
   themselves (─ ╭ ╮ ╰ ╯ │) used in borders, header pipes and the cowsay
   bubble — never pinned before, so a row containing more of them could end
   up narrower than a row built mostly from plain ASCII, drifting the closing
   │ left of the corner above it. Width is set per-instance inline (run length
   varies). No overflow:hidden — same reason as .tc-pfx: it would switch the
   inline-block's baseline to its bottom margin edge instead of its line box,
   shifting the glyph vertically. */
.tc-glyph { display: inline-block; }

/* ── Shortkeys bar & output area ── */
.term-keys {
  color:       #505050;
  font-size:   0.75rem;
  margin-top:  0.4em;
  white-space: pre;
  user-select: none;
}

.term-outputs { margin-top: 0.3em; }

/* half-line gap before the prompt that reappears after the TUI (only that
   one — the very first .term-ln at the top of the page needs no extra gap) */
.term-ln--gap { margin-top: 0.85em; }

.term-out {
  margin:      0;
  margin-top:  0.25em;
  font-family: inherit;
  font-size:   inherit;
  line-height: inherit;
  white-space: pre-wrap;
}

/* ❯ Gum canonical input indicator — pinned to 1ch so the ❯ glyph can't shift
   the truncation grid renderOutputEl() measures against (same guard as .tc-pfx) */
.tc-gum { color: #9b8bf4; display: inline-block; width: 1ch; }   /* lilac — matches hover */

/* bold clickable section name in output lines */
.tc-section-link             { color: inherit; text-decoration: none; }
.tc-section-link strong      { font-weight: 700; color: #9b8bf4; }   /* always lilac */
.tc-section-link:hover strong { color: #b5a7f7; text-decoration: underline; }

/* cowsay — decorative, normal terminal colour */
.tc-cow { color: #d6d6d6; margin-top: 0.6em; }

/* ── Terminal footer — single line at bottom of full-page terminal ── */
.term-footer {
  display:     flex;
  align-items: center;
  gap:         1.5rem;
  padding:     0.5rem 0;
  border-top:  1px solid #4d4d4d;
  font-size:   0.65rem;
  color:       #505050;
  flex-shrink: 0;
}
.term-footer a { color: #505050; text-decoration: none; }
.term-footer a:hover { color: #d6d6d6; }
.footer-copy  { margin-right: auto; white-space: nowrap; }
.footer-theme { white-space: nowrap; }
.footer-badges {
  display:     flex;
  gap:         0.4rem;
  align-items: center;
  flex-shrink: 0;
}
.footer-badges img { display: block; opacity: 0.65; transition: opacity 150ms; }
.footer-badges a:hover img { opacity: 1; }

/* ── Skip button — fixed overlay ───────────────────────────────────── */
.term-skip {
  position:    fixed;
  bottom:      1.5rem;
  right:       2rem;
  background:  none;
  border:      1px solid #505050;
  color:       #505050;
  font-family: var(--font-mono);
  font-size:   0.65rem;
  cursor:      pointer;
  padding:     2px 10px;
  border-radius: 3px;
  z-index:     10;
  transition:  color 150ms, border-color 150ms;
}
.term-skip:hover { color: #d6d6d6; border-color: #d6d6d6; }

@keyframes blink {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0; }
}

/* Allow scrolling on narrow viewports */
@media (max-width: 640px) {
  body.page-landing { height: auto; overflow-y: auto; }
  .term-page        { height: auto; min-height: 100vh; padding: 1.5rem; }
  .page-shell       { height: auto; min-height: 100vh; overflow: visible; padding: 1.5rem; }
  .page-content     { overflow-y: visible; }
  /* drop the theme attribution rather than wrapping to a second line —
     copyright + badges stay on one row at any width */
  .footer-theme     { display: none; }
}

/* Phones: shrink the terminal so the header line still fits once the TUI grid
   collapses to fewer columns (JS reflows 3 → 2 → 1 by available width). */
@media (max-width: 500px) {
  .term-page { padding: 1rem; font-size: 0.78rem; }
  .term-keys { font-size: 0.68rem; }
}
@media (max-width: 380px) {
  .term-page { padding: 0.75rem; font-size: 0.72rem; }
}

/* ── 7. Pill / tag components ──────────────────────────────────────── */
.pill {
  display: inline-block;
  padding: var(--space-1) var(--space-4);
  border: 1.5px solid var(--color-accent);
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-accent);
  text-decoration: none;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.pill:hover {
  background: var(--color-accent);
  color: var(--color-bg);
  text-decoration: none;
}

.tag {
  display: inline-block;
  padding: 2px var(--space-3);
  background: var(--color-surface-alt);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--color-text-muted);
  text-decoration: none;
  transition: background var(--transition-fast), color var(--transition-fast);
}

a.tag:hover {
  background: var(--color-accent);
  color: var(--color-bg);
  text-decoration: none;
}

/* ── 8. Study cards (studies.html) ──────────────────────────────────── */
.study-card {
  border-radius: var(--radius-md);
  padding: var(--space-6);
  margin-bottom: var(--space-4);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base);
}

.study-card:hover {
  box-shadow: var(--shadow-md);
}

.study-meta {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  margin-bottom: var(--space-2);
}

/* half-opacity, same treatment as .proj-fork-badge on Repos */
.study-years {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  opacity: 0.6;
}

.study-grade {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.study-university {
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--color-accent);
  margin-bottom: var(--space-1);
}

.study-degree {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-accent-3);
  margin-bottom: var(--space-2);
}

.study-description {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-bottom: var(--space-3);
  line-height: 1.65;
}

/* ── 9. Publication cards ──────────────────────────────────────────── */
.pub-card {
  border-radius: var(--radius-md);
  padding: var(--space-6);
  margin-bottom: var(--space-4);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base);
}

.pub-card:hover {
  box-shadow: var(--shadow-md);
}

.pub-meta {
  display: flex;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

.pub-year {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-accent-2);
}

.pub-type {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.pub-title {
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.5;
  margin-bottom: var(--space-2);
}

.pub-authors {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-bottom: var(--space-1);
}

.pub-venue {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-accent-3);
  margin-bottom: var(--space-3);
}

.pub-links {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

/* per-paper citation count from Semantic Scholar, next to the DOI tag —
   plain text (no box, unlike .tag), yellow like the language tags on Repos */
.pub-citations {
  font-size: var(--text-xs);
  color: var(--color-accent-4);
}

/* ── 10. Presentation cards ────────────────────────────────────────── */
.pres-card {
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-6);
  margin-bottom: var(--space-4);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base);
}

.pres-card:hover {
  box-shadow: var(--shadow-md);
}

.pres-meta {
  display: flex;
  gap: var(--space-3);
  margin-bottom: var(--space-1);
}

.pres-year {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-accent-2);
}

.pres-type {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.pres-title {
  font-size: var(--text-base);
  font-weight: 600;
  margin-bottom: var(--space-1);
}

.pres-event {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-accent-3);
  margin-bottom: var(--space-3);
}

.pres-links {
  display: flex;
  gap: var(--space-2);
}

/* ── 11. Project grid ──────────────────────────────────────────────── */
.projects-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-6);
  margin-top: var(--space-8);
}

.proj-card {
  border-radius: var(--radius-md);
  padding: var(--space-6);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base), transform var(--transition-base);
}

.proj-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.proj-name {
  font-size: var(--text-sm);
  font-weight: 700;
  margin-bottom: var(--space-2);
}

/* fork badge sits inline next to the title, same muted/dimmed treatment as
   .proj-updated below — a label, not a .tag chip. */
.proj-fork-badge {
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--color-text-muted);
  opacity: 0.6;
  margin-left: var(--space-2);
}

/* star count — yellow, sits after the fork badge if both are present */
.proj-star-badge {
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--color-accent-4);
  margin-left: var(--space-2);
}

/* latest commit message — cyan, one more Afterglow accent */
.proj-commit {
  font-size: var(--text-xs);
  color: var(--color-accent-6);
  margin-bottom: var(--space-1);
}

.proj-updated {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  opacity: 0.7;
  margin-bottom: var(--space-2);
}

.proj-desc {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-bottom: var(--space-4);
  line-height: 1.65;
}

.proj-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

/* Per-language tags — text + tinted background, both from the language's own
   accent token. Everything else (topics) stays the plain default .tag. */
.tag--python { background: rgba(126, 142, 80, 0.15);  color: var(--color-accent-3); }
.tag--r      { background: rgba(108, 153, 187, 0.15); color: var(--color-accent-2); }
.tag--js     { background: rgba(229, 181, 103, 0.15); color: var(--color-accent-4); }
.tag--rust   { background: rgba(172, 65, 66, 0.15);   color: var(--color-accent-5); }
.tag--shell  { background: rgba(255, 136, 0, 0.15);   color: var(--color-accent-7); }
.tag--go     { background: rgba(125, 214, 207, 0.15); color: var(--color-accent-6); }

/* Skills icon grid — icons are simple-icons/grommet-icon/iconify images
   pre-coloured to --color-text-muted via each service's own colour param
   (baked into the URL, not a CSS recolour trick), so they read at the
   same grey/weight as surrounding text. Every tile (real icon or placeholder)
   is the same shape: a 32×32 visual on top, name label below — some icons
   alone aren't recognisable, so the label is always shown, not just on hover.
   Placeholders (no icon exists anywhere for these) swap the icon for a
   dashed box with just the initial; the full name is still in the label
   below and in the title tooltip. */
.skills-icon-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-8);
}

/* each tile is a link (official site or repo) — reset the default <a>
   styling and use opacity as the hover affordance rather than recolouring
   (the icons are pre-coloured bitmaps/SVGs baked to one hex each; a hover
   colour would need a second asset per icon). */
.skill-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 72px;
  gap: var(--space-1);
  text-decoration: none;
  color: inherit;
  opacity: 0.85;
  transition: opacity var(--transition-fast);
}

.skill-tile:hover {
  opacity: 1;
  text-decoration: none;
}

/* two stacked images (grey default, colour on hover), crossfaded via
   opacity — not a CSS grayscale() filter, which would convert each icon's
   own hue to a different luminance-based grey and break the uniform
   #9a9a95 look. The hover colour is a single flat hex per icon, picked as
   the closest match (white allowed, black excluded — invisible on the dark
   bg) from the site's own Afterglow palette tokens to that tool's real
   brand colour — not the brand's own hex — so every icon's hover state
   stays visually unified with the rest of the site. */
.skill-icon-stack {
  position: relative;
  width: 32px;
  height: 32px;
}

.skill-icon {
  width: 32px;
  height: 32px;
  object-fit: contain;
}

.skill-icon-stack .skill-icon {
  position: absolute;
  top: 0;
  left: 0;
  transition: opacity var(--transition-fast);
}

.skill-icon--color {
  opacity: 0;
}

.skill-tile:hover .skill-icon--grey {
  opacity: 0;
}

.skill-tile:hover .skill-icon--color {
  opacity: 1;
}

.skill-icon-placeholder {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--color-text-muted);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-text-muted);
}

.skill-label {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  text-align: center;
  line-height: 1.25;
}

/* Contribution graph (repos.html) — month×weekday grid, own styling instead
   of GitHub's, built from assets/contributions.json (see
   tools/contrib-graph + .github/workflows/contributions.yml). Horizontal
   scroll on narrow viewports rather than shrinking/wrapping the grid. */
.contrib-graph-wrap {
  margin-bottom: var(--space-8);
  overflow-x: auto;
}

.contrib-inner {
  display: inline-block;
}

/* width matched to .contrib-graph's rendered width by JS (contrib-graph.js) —
   left/centre/right labels via justify-content:space-between, same
   font-size/colour as .contrib-legend. */
.contrib-months {
  display: flex;
  justify-content: space-between;
  margin-bottom: var(--space-1);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.contrib-graph {
  display: inline-grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(7, 1fr);
  gap: 2px;
}

.contrib-cell {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  background: var(--color-surface-alt);
}

.contrib-cell[data-level="1"] { background: rgba(126, 142, 80, 0.35); }
.contrib-cell[data-level="2"] { background: rgba(126, 142, 80, 0.55); }
.contrib-cell[data-level="3"] { background: rgba(126, 142, 80, 0.75); }
.contrib-cell[data-level="4"] { background: var(--color-accent-3); }

.contrib-legend {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.contrib-legend .contrib-cell {
  display: inline-block;
}

.projects-more {
  text-align: center;
  margin-top: var(--space-8);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* ── 12. Contact section ───────────────────────────────────────────── */
.contact-list {
  margin-top: var(--space-8);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-2) var(--space-12);
  font-size: var(--text-sm);
}

/* ── 13. Footer ────────────────────────────────────────────────────── */
/* .footer-badges is shared with .term-footer (§6) — every page uses the
   homepage's actual footer markup now, so there's no separate footer system
   left here beyond this one shared class. */
.footer-badges {
  display:     flex;
  flex-wrap:   wrap;
  gap:         var(--space-2);
  align-items: center;
}

/* ── 14. Placeholder notes (remove with real content) ──────────────── */
.placeholder-note {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  font-style: italic;
  margin-top: var(--space-4);
}

/* Data-source attribution — same size/colour as .term-footer's text, sits
   right above the footer's border-top line on pages with a live API fetch
   (pinned there by .page-content's flex column, §5b). No inline padding:
   flush with .term-footer/.nav-inner, which also rely on .page-shell's own
   inset rather than adding their own. */
.api-attr {
  flex-shrink: 0;
  font-size: 0.65rem;
  color: #505050;
  padding-top: var(--space-4);
  padding-bottom: var(--space-2);  /* matches .term-footer's own 0.5rem line-to-text gap */
}

/* ── 15. Responsive ────────────────────────────────────────────────── */
@media (max-width: 640px) {
  :root {
    --text-4xl: 1.65rem;
    --text-3xl: 1.4rem;
  }

  .about-grid {
    grid-template-columns: 1fr;
    gap: var(--space-8);
  }

  .projects-grid {
    grid-template-columns: 1fr;
  }

  .contact-list {
    grid-template-columns: 1fr;
  }

  .nav-toggle {
    display: flex;
  }

  /* static: .nav-links.open below needs its position:absolute to anchor to
     the page, not to this wrapper (which .nav-scrollbar otherwise needs
     position:relative on) — and the indicator itself is irrelevant once the
     nav becomes a vertical dropdown, so hide it. */
  .nav-links-wrap {
    position: static;
    padding-bottom: 0;
  }

  .nav-scrollbar {
    display: none;
  }

  .nav-links {
    display: none;
    position: absolute;
    top: var(--header-height);
    left: 0;
    right: 0;
    background-color: var(--color-bg);
    border-bottom: 1px solid var(--color-border);
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding: var(--space-4) var(--space-6);
  }

  .nav-links.open {
    display: flex;
  }

  .nav-links li {
    width: 100%;
    padding-block: var(--space-2);
    border-bottom: 1px solid var(--color-border);
  }

  .nav-links li:last-child {
    border-bottom: none;
  }
}

/* ── 16. Link preview cards (interests.html) ─────────────────────────── */
/* Real cover images (goshootit.net, Behance), both already the same
   1200×800 (3:2) size, so both cards share one common ratio — no per-card
   override needed. One-line caption below each. */
.link-cards {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  margin-top: var(--space-8);
}

/* flex:1 1 0 (no max-width) — the two cards adaptively split the full row
   width between them rather than capping out at a fixed size.
   flex-direction:column stacks the image above the caption; display:flex
   is explicit (not left to default inline-for-<a>) because an inline box
   wrapping a block child leaves a small line-height gap below it, and that
   gap differed slightly between elements' own text metrics — the
   "different heights below the image" the two cards inconsistently showed
   back when the media block was the only child. */
/* border is transparent (not none) at 1.5px even at rest, so it doesn't
   change the box's geometry when hover turns it grey — avoids a layout
   shift/jump on hover. */
.link-card {
  display: flex;
  flex-direction: column;
  flex: 1 1 0;
  min-width: 0;
  border-radius: var(--radius-md);
  border: 1.5px solid transparent;
  background: var(--color-surface);
  overflow: hidden;
  text-decoration: none;
  color: var(--color-text);
  transition: box-shadow var(--transition-base), transform var(--transition-base), border-color var(--transition-base);
}

.link-card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--color-text-muted);
  transform: translateY(-2px);
  text-decoration: none;
}

.link-card-media {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: var(--color-surface-alt);
}

.link-card-caption {
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  text-align: center;
}
