/* kitten.me — a list of things currently holding my attention. Each project is
   a plate: supporting text on the left, its visual on the right. For the cats
   that visual is a live window onto the meadow, and the paper the whole page is
   printed on takes its colour from that world's palette. */

:root {
  /* day phase, as a first paint before the world reports in */
  --paper: #f6f1e6;
  --ink: #2c2822;
  --ink-soft: #7e7566;
  --accent: #c17648;
  --rule: #d6cdbc;

  --mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --serif: Fraunces, Georgia, 'Times New Roman', serif;

  /* the plate: reading column + gutter + visual, plus the page margin.
     box-sizing is border-box, so the wrapper's max-width has to carry the
     padding too or the visual gets squeezed below the 640px the meadow's
     camera is tuned for. */
  --col-read: 16rem;
  --col-visual: 40rem;
  --gutter: clamp(28px, 4vw, 56px);
  --pad: clamp(24px, 4vw, 64px);
  --plate: calc(var(--col-read) + var(--gutter) + var(--col-visual) + 2 * var(--pad));
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 16px;
  /* the palette is sampled a few times a second; this smooths the steps
     between samples so the page never visibly stair-steps through a phase */
  transition: background-color .3s linear, color .3s linear;
}

/* ── the page ────────────────────────────────────────────────────── */

.page {
  flex: 1;
  width: 100%;
  max-width: var(--plate);
  margin-inline: auto;
  padding: clamp(40px, 7vh, 88px) var(--pad) clamp(24px, 4vh, 48px);
}

.lede {
  margin: 0 0 clamp(36px, 5vh, 64px);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  transition: color .3s linear;
}

/* ── projects ────────────────────────────────────────────────────── */

.projects {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* the rule and the space only exist between siblings, so a single project
   sits on the page exactly as it did before there was a list */
.project + .project {
  margin-top: clamp(48px, 8vh, 72px);
  padding-top: clamp(48px, 8vh, 72px);
  border-top: 1px solid var(--rule);
  transition: border-color .3s linear;
}

.project-title {
  margin: 0 0 22px;
  font-family: var(--serif);
  font-variation-settings: 'SOFT' 90, 'WONK' 1, 'opsz' 96;
  font-weight: 400;
  font-size: clamp(22px, 2.4vw, 28px);
  line-height: 1.2;
  letter-spacing: -.01em;
  color: var(--ink);
  text-wrap: pretty;
  transition: color .3s linear;
}

/* "at" recedes so the two proper nouns carry the line */
.project-prep { color: var(--ink-soft); transition: color .3s linear; }

.project-title a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  transition: color .3s linear, border-color .3s linear;
}

.project-title a:hover,
.project-title a:focus-visible { border-bottom-color: currentColor; }

/* supporting text left, visual right — top-aligned so each block reads
   downward from its own title */
.project-body {
  display: grid;
  grid-template-columns: minmax(190px, var(--col-read)) minmax(0, var(--col-visual));
  align-items: start;
  gap: 0 var(--gutter);
}

.reading { grid-column: 1; }
.project-visual { grid-column: 2; }

/* ── the window ──────────────────────────────────────────────────── */

.window {
  position: relative;
  width: 100%;
  aspect-ratio: 640 / 466;
  border-radius: 3px;
  overflow: hidden;
  box-shadow:
    0 18px 40px -22px rgba(40, 32, 18, .6),
    0 0 0 1px rgba(40, 32, 18, .14);
}

/* The mat — an inset shadow on the container would paint behind the canvas,
   so the ring is its own layer above it. It is the paper showing through, not
   white: at night the page inverts, and a white mat would ring the dark window
   in a bright frame instead of quietly bordering it. */
.window::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 6px color-mix(in srgb, var(--paper) 55%, transparent);
}

@supports not (color: color-mix(in srgb, red 50%, transparent)) {
  .window::after { box-shadow: inset 0 0 0 6px rgba(255, 255, 255, .35); }
}

#meadow {
  display: block;
  width: 100%;
  height: 100%;
  cursor: default;
}

/* ── the reading ─────────────────────────────────────────────────── */

.tick {
  font-family: var(--serif);
  font-variation-settings: 'SOFT' 90, 'WONK' 1, 'opsz' 144;
  font-weight: 400;
  font-size: clamp(38px, 5.4vw, 62px);
  line-height: .92;
  letter-spacing: -.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  transition: color .3s linear;
}

.meta {
  margin: 10px 0 0;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  transition: color .3s linear;
}

.phase { color: var(--accent); transition: color .3s linear; }

.roster {
  margin: 28px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.roster li {
  font-size: 12px;
  line-height: 1.35;
  color: var(--ink-soft);
  transition: color .3s linear, opacity .2s ease;
  cursor: default;
}

.roster .name { color: var(--ink); transition: color .3s linear; }

/* hovering a row is the inverse of hovering a cat: it names the cat in
   the window instead of the window naming it here */
@media (hover: hover) {
  .roster:hover li { opacity: .45; }
  .roster li:hover { opacity: 1; }
}

/* ── live / local indicator ──────────────────────────────────────── */

.source i {
  display: block;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  opacity: .3;
}

.source[data-state="live"] { color: var(--accent); }
.source[data-state="live"] i { animation: blip 2.4s ease-in-out infinite; }

@keyframes blip { 0%, 100% { opacity: .35 } 50% { opacity: 1 } }

/* ── colophon ────────────────────────────────────────────────────── */

/* no underline and no hover — it is a wordmark, not a link, and dressing it
   as one would promise something to click */
.colophon {
  padding: clamp(32px, 5vh, 56px) var(--pad) clamp(24px, 4vh, 40px);
  width: 100%;
  max-width: var(--plate);
  margin-inline: auto;
  font-size: 12px;
  letter-spacing: .04em;
  color: var(--ink-soft);
  transition: color .3s linear;
}

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

/* ── 1e: the phone ───────────────────────────────────────────────── */

@media (max-width: 820px) {
  .project-body {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
  }

  /* the visual leads on the phone, the text follows it */
  .project-visual { grid-column: 1; grid-row: 1; }
  .reading { grid-column: 1; grid-row: 2; }

  /* the window goes portrait and crops the world tighter — same meadow,
     less of it, which is fine because it is a viewport and never claimed
     to be the whole thing */
  .window { aspect-ratio: 342 / 460; }

  .tick { font-size: clamp(38px, 12vw, 46px); line-height: .95; }
  .meta { margin-top: 7px; font-size: 10.5px; }
  .roster { margin-top: 16px; gap: 5px; }
  .roster li { font-size: 11.5px; }
}

@media (max-width: 820px) and (max-height: 700px) {
  .window { aspect-ratio: 4 / 3; }
}

/* ── reduced motion ──────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: .01ms !important; }
  .source[data-state="live"] i { animation: none; opacity: 1; }
}
