/* ==========================================================================
   Andrea Konechny: site styles
   One stylesheet for every page. Change a colour or size here once
   and it updates everywhere.
   ========================================================================== */

/* ---------- Fonts ---------- */
@font-face {
  font-family: "Authentic Sans";
  src: url("../assets/fonts/authentic-sans-60.woff") format("woff");
  font-weight: 300 400;
  font-display: swap;
}
@font-face {
  font-family: "Louise";
  src: url("../assets/fonts/louise.woff") format("woff");
  font-display: swap;
}

/* ---------- Design tokens (edit these!) ---------- */
:root {
  --lavender: #c2bffd;      /* nav, footer, buttons */
  --lilac: #f6e5ff;         /* button gradient centre */
  --violet: #6e53ff;        /* links + hover colour */
  --ink: #333;              /* body text */
  --black: #000;            /* grid lines */
  --bg: #fff;

  --line: 1px solid var(--black);
  --radius: 20px;
  --pad: 24px;              /* space inside each grid cell */
  --width: 100%;            /* width of the bordered column (100% = edge to edge) */

  --sans: "Authentic Sans", "Helvetica Neue", Arial, sans-serif;
  --script: "Louise", cursive;
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html, body { overflow-x: clip; }   /* hides that 1px without adding a sideways scrollbar */
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 12px;
  line-height: 1.5;
}
img { display: block; max-width: 100%; }
a { color: var(--violet); text-decoration: none; }
p { margin: 0 0 1em; }
h1, h2, h3 { margin: 0; font-weight: 400; }
/* No widows: browsers balance the last lines so one word is never left alone */
p, h1, h2, h3, li { text-wrap: pretty; }

/* ---------- Header / nav ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--lavender);
  transition: background-color 1s ease;   /* colour drift: see js/header.js */
}
.site-header__inner {
  display: flex;
  align-items: baseline;     /* menu sits on the same baseline as the name */
  justify-content: space-between;
  gap: 16px;
  padding: 27px 20px 13px;   /* a bit more on top: the script sits high, so this centres it by eye */
}
.logo {
  white-space: nowrap;
  word-spacing: -0.12em;    /* tighter gap between first + last name */
  font-family: var(--script);
  font-size: 32px;
  line-height: 1;
  color: var(--black);
}
.logo { transition: color .25s ease; }
.logo:hover { color: var(--violet); }   /* name turns purple on hover */

.nav { display: flex; gap: 14px; }
.nav a {
  color: var(--black);
  font-size: 14px;
  letter-spacing: 0.15px;
}
.nav a[aria-current="page"] { color: var(--violet); }


/* ---------- The bordered grid ----------
   Every page is a 12-column grid inside a column with a black line on
   each side. Each .cell draws its own right + bottom line, so cells
   tile together like a table without doubled-up borders.            */
.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  width: calc(var(--width) + 1px);   /* the extra 1px pushes the right-edge line just off screen */
  margin: 0 auto;
}
.cell {
  grid-column: span 12;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: var(--pad);
  border-right: var(--line);
  border-bottom: var(--line);
  min-width: 0;
  container-type: inline-size;   /* lets titles size themselves to the box */
}
/* The same space at the bottom of every box */
.cell { padding-bottom: 20px; }
/* Captions sit at the bottom of their box, so titles in the same row always line up */
.cell > .media + .caption, .cell > .media-pair + .caption { margin-top: auto; }
/* A little breathing room between an image and its title (a touch more on wide screens, where titles are bigger) */
.cell > .media + .caption, .cell > .media-pair + .caption { padding-top: clamp(4px, 0.6vw, 10px); }

/* Width helpers: out of 12 columns */
.w-3  { grid-column: span 3; }
.w-4  { grid-column: span 4; }
.w-5  { grid-column: span 5; }
.w-6  { grid-column: span 6; }
.w-7  { grid-column: span 7; }
.w-8  { grid-column: span 8; }
.w-9  { grid-column: span 9; }
.w-12 { grid-column: span 12; }
.tall { grid-row: span 2; }   /* cell that sits beside two stacked cells */
.centered { justify-content: center; align-items: center; text-align: center; }

/* ---------- Media (images inside cells) ---------- */
.media {
  position: relative;
  flex: 1 0 auto;               /* grows to match a taller neighbour */
  aspect-ratio: var(--ratio, 4 / 5);
  max-height: 88vh;             /* never taller than the screen on big monitors */
  border-radius: var(--radius);
  overflow: hidden;
  background: #f2f0ff;
}
.media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.media img.hover-swap { display: none; }
.media-pair .media { display: block; }
a.media-pair { color: inherit; }

/* MOTIF: starts on the tote photo, hovering slowly fades to the bags photo */
/* Homepage hover (subtle): a clickable image eases in a little closer,
   and its title turns purple, so you can tell the box is a link */
a.media img { transition: transform 1.4s cubic-bezier(.2, .7, .2, 1), opacity .9s ease; }
a.media:hover img { transform: scale(1.025); }
.title a { transition: color .4s ease; }
.cell:has(a.media:hover) .title a, .title a:hover { color: var(--violet); }

.media--swap img.swap { opacity: 0; transition: opacity .9s ease, transform 1.4s cubic-bezier(.2, .7, .2, 1); }
.media--swap:hover img.swap { opacity: 1; }

/* Shown at full natural height, never capped */
.media--full { max-height: none; }

/* A few key images may use a bit more of the screen height */
.media--tall { max-height: calc(100vh - 110px); }

/* Show the whole image (no cropping): good for logos & wordmarks */
.media--contain { background: transparent; }
.media--contain img { object-fit: contain; }
/* KLEE poster: always shows the whole poster, with its own dark navy filling any extra space */
.media--klee { background: #000514; }

.media-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

/* ---------- Project caption (title + small details) ---------- */
.caption {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;        /* title and small details always line up along the top */
  gap: 16px;
}
.title {
  font-size: clamp(24px, 2.7vw, 40px);    /* one size for every title, so neighbours always match */
  line-height: 1.1;
  font-weight: 400;
  color: var(--ink);
}
.title--sm { font-size: clamp(18px, 2vw, 22px); }
/* Bigger titles under the biggest images (full-width and two-thirds-width boxes) */
.w-8 > .caption .title, .w-9 > .caption .title, .w-12 > .caption .title { font-size: clamp(26px, 3vw, 44px); }
/* Three-across boxes are narrow, so their titles stay a little smaller */
.w-4 > .caption .title:not(.title--sm) { font-size: clamp(22px, 2.2vw, 32px); }
.title .artist { color: #9a9a9a; }   /* artist name after a song title */
.title a { color: inherit; }
.details {
  flex-shrink: 0;
  margin: 0;                      /* no extra paragraph gap under the small text */
  text-align: right;
  font-size: 12px;
  line-height: 1.5;
}
.details span { display: block; }
/* Captions side by side are evened out by js/rows.js, so titles line up */

/* ---------- Big friendly text ---------- */
.lede {
  font-size: clamp(24px, 3.2vw, 36px);
  font-weight: 300;
  line-height: 1.3;
  letter-spacing: 0.02em;
  margin: 0;
}
.lede + .lede { margin-top: 0.4em; }
.lede--sm { font-size: clamp(18px, 2.2vw, 24px); }
.emojis { font-size: 50px; line-height: 1; margin: 0 0 12px; }
/* Homepage intro: keep the text in a narrow column like the original */
/* Homepage intro: keep the text in a narrow column like the original */
.hello-blurb .lede { max-width: 8.5em; font-size: clamp(26px, 3.5vw, 40px); }   /* a touch bigger than other big text */
.hello-blurb .lede + .lede { margin-top: 0.15em; }   /* "Hi! I’m Andrea." sits closer to the sentence below */
/* ---------- Intro entrance (homepage) ----------
   A quiet, slow fade: the emojis first, then the two sentences.
   Skipped for people who turn off motion in their computer settings. */
@media (prefers-reduced-motion: no-preference) {
  .hello-blurb .emojis,
  .hello-blurb .lede {
    opacity: 0;
    animation: soft-fade 1.2s ease forwards;
  }
  .hello-blurb .emojis   { animation-delay: .1s; }
  .hello-blurb h1.lede   { animation-delay: .35s; }
  .hello-blurb p.lede    { animation-delay: .6s; }
}
@keyframes soft-fade {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}

/* Narrow, centred paragraphs (homepage education blurb) */
.narrow-text .lede { max-width: 13em; margin-inline: auto; text-wrap: balance; font-size: clamp(22px, 2.5vw, 34px); }

/* ---------- Pill buttons ---------- */
.button {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 41px;
  padding: 10px 20px;
  border-radius: 999px;
  background: radial-gradient(circle, var(--lilac), var(--lavender));
  color: var(--black);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
/* A box sharing a row with a "View project" box keeps the same space, so titles line up */
.match-button::after { content: ""; display: block; height: 41px; flex: none; }
.button-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }

/* ---------- Small labels (footer, about page) ---------- */
.label {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  -webkit-text-stroke: 0.35px currentColor;   /* a tiny outline so the small caps read a touch bolder */
  padding-bottom: 4px;
  margin-bottom: 16px;       /* space under the line: more than the gap between items */
  border-bottom: var(--line);
}
.list { list-style: none; margin: 0 0 24px; padding: 0; }
.list li { margin-bottom: 2px; }

/* ---------- Project pages ---------- */
/* Project credits: comfortable size, even spacing */
.credits p { margin: 0 0 6px; font-size: 14px; line-height: 1.5; }

/* Project story text: shorter lines, even gaps between paragraphs */
.prose { gap: 0; font-size: 18px; line-height: 1.5; font-weight: 300; }
.prose p { max-width: 32em; margin: 0 0 0.9em; text-wrap: pretty; }
.prose .note { margin-top: 0.6em; font-size: 13px; font-weight: 400; max-width: 44em; }

/* ---------- Video links: a "Watch" label follows the cursor (see js/cursor.js) ---------- */
.cursor-dot::after {
  content: attr(data-label);
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  padding-top: 2px;         /* nudges the word down: this font sits a touch high */
  color: var(--black);
  opacity: 0; transition: opacity .2s ease;
}
.cursor-dot.has-label, .cursor-dot.is-over-link.has-label { width: 72px; height: 72px; }
.cursor-dot.has-label::after { opacity: 1; }
/* On touch screens (no cursor), video boxes show a small "Watch" tag instead */
@media (hover: none) {
  a.media[data-cursor]::after {
    content: "▶ " attr(data-cursor);
    position: absolute; left: 12px; bottom: 12px; z-index: 2;
    padding: 4px 10px; border-radius: 999px;
    background: var(--lavender); color: var(--black);
    font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  }
}

/* ---------- Titles + their small text fade up as they scroll into view (see js/reveal.js) ---------- */
@media (prefers-reduced-motion: no-preference) {
  .js-reveal .cell > .caption .title,
  .js-reveal .cell > .caption .details { opacity: 0; transform: translateY(4px); }
  .js-reveal .cell > .caption.is-in .title,
  .js-reveal .cell > .caption.is-in .details {
    opacity: 1; transform: none;
    transition: opacity 1.2s ease, transform 1.2s ease;
    transition-delay: var(--reveal-delay, 0s);
  }
  /* the small text follows a beat after its title */
  .js-reveal .cell > .caption.is-in .details { transition-delay: calc(var(--reveal-delay, 0s) + .2s); }
}

/* ---------- Click-to-enlarge images (see js/lightbox.js) ---------- */
[data-zoom] { cursor: zoom-in; }
.lightbox {
  position: fixed; inset: 0; z-index: 50;
  display: grid; place-items: center;
  padding: 24px;
  background: color-mix(in srgb, var(--drift, var(--lavender)) 85%, transparent);
  opacity: 0; pointer-events: none;
  transition: opacity .3s ease;
}
.lightbox.is-open { opacity: 1; pointer-events: auto; cursor: zoom-out; }
.lightbox img {
  max-width: 100%; max-height: calc(100vh - 48px);
  border-radius: 12px;
  box-shadow: 0 10px 40px rgba(0,0,0,.2);
}
.lightbox__close {
  position: absolute; top: 16px; right: 20px;
  border: 0; background: none; font: inherit; font-size: 28px; line-height: 1; color: var(--black);
}

/* ---------- Experiments page ---------- */
.intro {
  position: sticky;
  top: 92px;                /* sits just under the header when it sticks */
  padding: 0 8px;
  margin-top: 0;            /* first line sits level with the "2026" heading */
}
.intro .lede { max-width: 13em; text-wrap: balance; }   /* narrow, left-aligned, even line breaks */
.year { margin-bottom: 40px; }
.year h2 {
  font-size: 18px;
  padding-bottom: 6px;
  margin-bottom: 16px;
  border-bottom: var(--line);
}
.covers {
  display: grid;
  grid-template-columns: repeat(3, 1fr);   /* 3 across, like the original */
  gap: 16px;
}
/* Each year fills its rows completely, depending on how many covers it has:
   - a multiple of 3 (6, 9…)  → first cover double size, rows of 3
   - 1 extra (4, 7…)          → first cover full width, rows of 3 below
   - 2 extra (5, 8…)          → 2 across, all big                        */
.covers > :first-child { grid-column: span 2; grid-row: span 2; }

/* 2026 layout: the first two covers big side by side, then rows of three */
.covers-mixed {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 16px;
}
.covers-mixed > * { grid-column: span 2; }
.covers-mixed > :nth-child(-n+2) { grid-column: span 3; }
.covers:has(> :nth-child(3n+1):last-child) > :first-child { grid-column: 1 / -1; grid-row: auto; }
.covers:has(> :nth-child(3n+2):last-child) { grid-template-columns: repeat(2, 1fr); }
.covers:has(> :nth-child(3n+2):last-child) > :first-child { grid-column: auto; grid-row: auto; }
/*   ...and if that count is odd (5, 11…), the first cover goes full width so the rest pair up evenly */
.covers:has(> :nth-child(6n+5):last-child) > :first-child { grid-column: 1 / -1; }
/* Each cover links to its playlist on Spotify */
.cover { display: block; position: relative; border-radius: 6px; overflow: hidden; }
.cover img {
  width: 100%;
  height: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  transition: transform .4s ease;
}
a.cover:hover img { transform: scale(1.03); }

/* ---------- About page (laid out like the original) ---------- */
.about-photo .media { flex: 1 0 auto; }        /* photo fills the full height of its box */
@media (min-width: 768px) {
  /* the portrait stretches to the full height of the row, so there is no gap under it */
  .about-photo .media { max-height: none; aspect-ratio: auto; min-height: 60vh; }
}
.about-info { padding: clamp(48px, 5vw, 72px) clamp(24px, 3vw, 48px) 32px; }   /* more room above Hello! */
.about-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));     /* three columns spread across the width */
  gap: 24px clamp(32px, 4vw, 72px);
  height: 100%;
}
.about-col { display: flex; flex-direction: column; min-width: 0; }
.about-bottom { margin-top: auto; padding-top: 32px; }  /* the bio sits at the bottom, like the original */
.hello {
  font-family: var(--script);
  font-size: 60px;
  line-height: 1.15;
  color: var(--black);
  margin-bottom: 22px;      /* gap between Hello! and the line below */
}
.aka { font-size: 16px; line-height: 1.4; color: #555; max-width: 18em; text-wrap: balance; }
.job { margin-bottom: 10px; }
.job em { display: block; }
/* Shorter lines in the About columns, with even breaks */
.about-col .job, .about-col .list li { max-width: 20em; text-wrap: balance; }
/* Bio bullets: the ✧ hangs on the left so wrapped lines line up with the words */
.bio li {
  position: relative;
  margin-bottom: 6px;
  padding-left: 1.4em;
  text-wrap: balance;        /* wrapped lines come out evenly sized */
}
.bio li::before { content: "✧"; position: absolute; left: 0; }
.cell.about-contact {   /* the text has built-in space above its letters, so the top padding is trimmed to match: looks centred by eye */
  padding-top: calc(clamp(56px, 5.5vw, 90px) - 8px);
  padding-bottom: calc(clamp(56px, 5.5vw, 90px) + 4px);
  gap: 24px;
}
.about-contact .lede { text-align: center; }
.about-contact .button { width: min(500px, 100%); }

/* ---------- Footer ---------- */
.site-footer {
  position: relative;
  margin-top: -1px;          /* sits over the last grid line, so there is no stroke above the footer */
  background: var(--lavender);
  transition: background-color 1s ease;   /* colour drift: see js/header.js */
  padding: 20px;
}
.site-footer__inner {
  display: grid;
  grid-template-columns: repeat(3, minmax(100px, 160px)) 1fr;
  gap: 20px;
}
.site-footer a { color: var(--black); }
.copyright { text-align: right; }

/* ---------- Tablet & phone ---------- */
@media (max-width: 767px) {
  :root { --pad: 16px; }
  .grid { width: calc(100% + 1px); margin: 0; }
  .cell { grid-column: span 12 !important; grid-row: auto !important; border-right: 0; }
  .media { flex: none; aspect-ratio: var(--ratio-mobile, 4 / 5); }
  .intro { position: static; }
  /* phones: the two homepage text blurbs get the same generous space above and below
     (".cell." makes this win over the general cell padding further down) */
  .cell.hello-blurb, .cell.narrow-text { padding-block: 52px 56px; }
  /* phones: the Experiments intro is centred */
  .intro { text-align: center; padding-block: 28px 26px; }
  .intro .lede { margin-inline: auto; }
  .match-button::after { display: none; }     /* the spacer that lines up side-by-side boxes isn't needed when they stack */
  .cell > .caption .details { min-height: 0; }   /* no empty lines reserved under the small text */
  .about-grid { grid-template-columns: 1fr; height: auto; }
  .about-bottom { margin-top: 24px; padding-top: 0; }
  .site-footer__inner { grid-template-columns: 1fr 1fr; }
  .copyright { grid-column: span 2; text-align: left; }
  .button-row { grid-template-columns: 1fr; }
  /* phones: two covers per row, so the page isn't endless (written strongly enough to beat the desktop rules above).
     If a year has an odd number of covers, its first cover goes full width so the rest pair up evenly. */
  .covers, .covers:has(> :nth-child(n):last-child), .covers-mixed { grid-template-columns: 1fr 1fr; gap: 8px; }
  .covers:has(> :nth-child(n):last-child) > :first-child, .covers-mixed > *, .covers-mixed > :nth-child(-n+2) { grid-column: auto; grid-row: auto; }
  .covers:has(> :nth-child(2n+1):last-child) > :first-child,
  .covers-mixed:has(> :nth-child(2n+1):last-child) > :first-child { grid-column: 1 / -1; }
}
@media (max-width: 420px) {
  .site-header__inner { padding: 20px 16px 10px; gap: 12px; flex-wrap: wrap; row-gap: 6px; }
  .logo { font-size: 20px; }
  .nav { gap: 10px; }
  .nav a { font-size: 12.5px; }
  .caption { flex-direction: column; gap: 6px; }
  .details { text-align: left; }
  .details span { display: inline; }
  .details span + span::before { content: " · "; }
}


/* Homepage top image: always fits on screen with its title on first load */
@media (min-width: 768px) {
  .hero-media { max-height: calc(100vh - 170px); min-height: 420px; }
}

/* ---------- Looping YouTube clip (see js/clip.js) ---------- */
.media--clip .clip,
.media--clip iframe {
  position: absolute;
  top: 50%; left: 50%;
  width: 100%; height: 160%;          /* extra-tall player: the video sits in the middle at full width,
                                         and YouTube's title + bottom bar fall outside the box */
  transform: translate(-50%, -50%);
  border: 0;
  pointer-events: none;               /* clicks go to the link, not the player */
  opacity: 0;
  transition: opacity .6s ease;
}
.media--clip.is-playing iframe { opacity: 1; }
.media--clip { background: #000; }
/* Boy Most Wanted: the video sits a little smaller, with black space above and below */
.media--clip-inset .clip, .media--clip-inset iframe { width: 92%; height: 160%; }

/* ---------- Circle cursor (see js/cursor.js) ---------- */
.has-cursor-dot, .has-cursor-dot * { cursor: none !important; }
.cursor-dot {
  position: fixed;
  top: 0; left: 0;
  z-index: 100;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--drift, var(--lavender));   /* same colour as the header drift */
  border: 1px solid var(--black);
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%);
  transition: opacity .2s ease, width .25s ease, height .25s ease;
}
.cursor-dot.is-visible { opacity: 0.7; }   /* slightly see-through */
.cursor-dot.is-over-link { width: 46px; height: 46px; }   /* grows over anything clickable */

/* Tighter gap between project details and the button (details always reserve 3 lines) */
.cell > .caption + .button,
.match-button::after { margin-top: -8px; }
.cell { padding-bottom: var(--pad); }
