/* =============================================================
   Resources — writing index composed on NC tokens
   Loaded after styles.css; reuses :root design tokens.
   Namespace: .res-
   (.res-section, .res-wrap and .res-eyebrow already resolve to the
   shared container and eyebrow rules in styles.css.)
   ============================================================= */

/* overflow-x: clip contains the atmosphere glows, which bleed past the
   viewport edge on purpose. clip, not hidden, so the y axis is untouched. */
.res { position: relative; overflow-x: clip; }

/* =============================================================
   ATMOSPHERE — paper canvas + soft glows, per
   docs/ui-guidelines.md → background atmosphere, not content.
   Same oklch palette as the home hero and the portfolio index.
   ============================================================= */
.res-atmos {
  position: absolute; inset: 0 0 auto; z-index: 0;
  height: clamp(520px, 72vh, 880px);
  pointer-events: none;
}
.res-atmos span { position: absolute; display: block; border-radius: 50%; }

/* Three-colour wash for this page: green, yellow and blue (assigned accents),
   each blob crossfading between two of the three so the wash reads as one
   palette morphing into itself rather than three unrelated spots. Uses the
   --g-h1/--g-h2/--g-w/--g-h/--g-x/--g-y custom properties registered once in
   css/styles.css. */

/* Blue, dominant, upper right — stays inside the blue family (210-238deg) so
   it always reads as blue, never blends toward the page's green or yellow.
   Box and offset share the same vw value (half the box, negative, on both
   axes) so the gradient's own centre lands exactly on the atmosphere's
   top-right corner. */
.res-atmos__mint {
  top: -36vw; right: -36vw;
  width: 72vw; height: 72vw;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.68 0.18 var(--g-h1, 224deg) / 0.31),
    oklch(0.76 0.16 var(--g-h1, 224deg) / 0.14) 44%,
    transparent 70%);
  animation:
    res-glow-morph-mint 7s ease-in-out infinite,
    res-glow-float-mint 10s ease-in-out infinite;
}
@keyframes res-glow-morph-mint {
  0%, 100% { --g-h1: 210deg; --g-w: 46%; --g-h: 54%; --g-x: 48%; --g-y: 52%; }
  50%      { --g-h1: 238deg; --g-w: 58%; --g-h: 40%; --g-x: 60%; --g-y: 38%; }
}
@keyframes res-glow-float-mint {
  0%, 100% { transform: scale(1)    translate3d(0, 0, 0);     filter: saturate(1); }
  50%      { transform: scale(1.2)  translate3d(-9%, 7%, 0);  filter: saturate(1.1); }
}

/* Green, lower left — lands under the first card row. Stays inside the
   green family (142-165deg). Box and offset share the same vw value so the
   gradient's own centre lands exactly on the atmosphere's bottom-left
   corner. */
.res-atmos__lime {
  bottom: -26.4vw; left: -26.4vw;
  width: 52.8vw; height: 52.8vw;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.8 0.19 var(--g-h1, 155deg) / 0.275),
    transparent 64%);
  animation:
    res-glow-morph-lime 6s ease-in-out -3s infinite,
    res-glow-float-lime 9s ease-in-out -5s infinite;
}
@keyframes res-glow-morph-lime {
  0%, 100% { --g-h1: 145deg; --g-w: 44%; --g-h: 44%; --g-x: 54%; --g-y: 46%; }
  50%      { --g-h1: 168deg; --g-w: 54%; --g-h: 34%; --g-x: 42%; --g-y: 58%; }
}
@keyframes res-glow-float-lime {
  0%, 100% { transform: scale(1.05) translate3d(0, 0, 0);      filter: saturate(1); }
  50%      { transform: scale(0.86) translate3d(12%, -9%, 0);  filter: saturate(1.12); }
}

/* Yellow, upper-centre — the page's third colour, kept in its own family
   (66-86deg) so all three accents stay distinguishable at a glance. */
.res-atmos__blend {
  top: -12%; left: 42%;
  width: 40vw; height: 40vw;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.85 0.19 var(--g-h1, 75deg) / 0.24),
    transparent 66%);
  animation:
    res-glow-morph-blend 7s ease-in-out -6s infinite,
    res-glow-float-blend 11s ease-in-out -8s infinite;
}
@keyframes res-glow-morph-blend {
  0%, 100% { --g-h1: 66deg; --g-w: 46%; --g-h: 46%; --g-x: 50%; --g-y: 50%; }
  50%      { --g-h1: 86deg; --g-w: 56%; --g-h: 36%; --g-x: 40%; --g-y: 60%; }
}
@keyframes res-glow-float-blend {
  0%, 100% { transform: scale(1)    translate3d(0, 0, 0);     filter: saturate(1);   opacity: 1; }
  50%      { transform: scale(1.24) translate3d(-8%, 6%, 0);  filter: saturate(1.08); opacity: 0.7; }
}

/* Mandatory corner-seam accent: centred exactly where .res-atmos's own
   bottom edge meets the page below it, bottom-left. Box and offset share the
   same vw value (half the box size, negative) so the gradient's centre —
   not its edge — sits on that seam point. */
.res-atmos__corner {
  bottom: -37vw; right: -37vw;
  width: 74vw; height: 74vw;
  background: radial-gradient(
    var(--g-w, 50%) var(--g-h, 50%) at var(--g-x, 50%) var(--g-y, 50%),
    oklch(0.85 0.19 var(--g-h1, 75deg) / 0.14),
    transparent 60%);
  animation:
    resx-glow-morph-corner 8s ease-in-out -4s infinite,
    resx-glow-float-corner 12s ease-in-out -7s infinite;
}
@keyframes resx-glow-morph-corner {
  0%, 100% { --g-h1: 66deg; --g-w: 46%; --g-h: 46%; --g-x: 50%; --g-y: 50%; }
  50%      { --g-h1: 86deg; --g-w: 55%; --g-h: 37%; --g-x: 40%; --g-y: 60%; }
}
@keyframes resx-glow-float-corner {
  0%, 100% { transform: scale(1)    translate3d(0, 0, 0);    filter: saturate(1); }
  50%      { transform: scale(1.16) translate3d(9%, -6%, 0); filter: saturate(1.05); }
}

/* content rides above the wash */
.res > .page-hero,
.res > .res-section,
.res > .section { position: relative; z-index: 1; }

.res-section { padding: var(--space-7) var(--gutter) 0; }

/* ---------- Section head ----------
   Left aligned on purpose: the hero above is centred, so the page does
   not read as two stacked centred blocks. */
.res-head { max-width: 760px; }
.res-head .section__title { margin: var(--space-3) 0 0; }
.res-head__lead {
  font-size: var(--fs-lead); line-height: 1.55;
  color: var(--color-ink-60);
  margin: var(--space-3) 0 0;
}

/* =============================================================
   ARTICLE CARDS — dark surfaces on paper.
   The card sits black against the paper behind it, so the grid
   reads as raised without a heavy border or a coloured shadow.
   Nothing is published yet, so a card is not a link. It carries a
   status chip instead of an arrow, so it never reads as clickable.
   ============================================================= */
.res-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-6);
}

.res-card {
  position: relative; overflow: clip;
  display: flex; flex-direction: column;
  padding: clamp(1.5rem, 2.4vw, 2.25rem);
  background: var(--color-ink);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-lg);
  color: var(--color-on-dark);
  box-shadow: 0 24px 50px -42px rgba(10, 10, 8, 0.4);
}

/* accent wash keyed to the card topic, sitting inside the card */
.res-card__glow {
  position: absolute; z-index: 0; pointer-events: none;
  top: -34%; right: -16%;
  width: 62%; aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%,
    color-mix(in srgb, var(--res-accent, var(--color-secondary-green)) 30%, transparent),
    transparent 70%);
  filter: blur(30px);
}
.res-card > *:not(.res-card__glow) { position: relative; z-index: 1; }

/* the accent carries the topic, lightened toward on-dark so 11px
   uppercase still clears contrast on a black card */
.res-card__tag {
  font-family: var(--font-title);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: color-mix(in srgb,
    var(--res-accent, var(--color-secondary-green)) 65%, var(--color-on-dark));
}
.res-card__title {
  font-family: var(--font-title); font-weight: 700;
  font-size: clamp(1.3rem, 1.7vw, 1.5rem);
  line-height: 1.15; letter-spacing: -0.02em;
  color: var(--color-on-dark);
  margin: var(--space-3) 0 0;
}
.res-card__body {
  font-size: var(--fs-md); line-height: 1.6;
  color: var(--color-on-dark-muted);
  max-width: 52ch;
  /* bottom margin is the floor gap: the chip below uses margin-top:auto
     to sit on the card floor, and auto cannot also hold a minimum. */
  margin: var(--space-3) 0 var(--space-5);
}
/* the status chip sits on the card floor, so a row of cards lines up */
.res-card__status {
  align-self: flex-start;
  margin-top: auto;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-on-dark-muted);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-pill);
  padding: 0.28rem 0.75rem;
}

/* ---------- Featured card ---------- */
.res-card--feature {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: clamp(1.5rem, 4vw, 4rem);
  padding: clamp(1.75rem, 3vw, 3rem);
}
/* both columns stretch, so the status chip lands on the card floor
   next to the last row of the covers list */
.res-card--feature .res-card__main {
  display: flex; flex-direction: column;
}
.res-card--feature .res-card__title {
  font-size: clamp(1.75rem, 2.6vw, 2.25rem);
  letter-spacing: -0.03em;
}
.res-card--feature .res-card__glow {
  top: -46%; right: 24%;
  width: 34%;
}

/* what the featured piece covers — content, not decoration.
   Rows are separated by a full hairline, never a left-edge bar. */
.res-covers { margin: 0; padding: 0; list-style: none; }
.res-covers__label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-on-dark-muted);
  margin: 0 0 var(--space-2);
}
.res-covers li {
  font-size: var(--fs-base); line-height: 1.5;
  color: var(--color-on-dark-muted);
  padding: var(--space-3) 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.res-covers li:first-child { padding-top: var(--space-2); }
.res-covers li:last-child { border-bottom: 0; padding-bottom: 0; }

/* ---------- Responsive ---------- */
@media (max-width: 1024px) {
  .res-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Stacked, the two columns become one flow. display: contents lifts the
     copy column's children into the card grid so the status chip can be
     ordered last, after the covers list, instead of landing mid-card. */
  .res-card--feature { grid-template-columns: 1fr; gap: 0; }
  .res-card--feature .res-card__main { display: contents; }
  .res-card--feature .res-card__body { margin-bottom: var(--space-4); }
  /* justify-self, because the chip is a grid item once main is contents */
  .res-card--feature .res-card__status {
    order: 1; justify-self: start; margin-top: var(--space-5);
  }
}

@media (max-width: 700px) {
  .res-grid { grid-template-columns: 1fr; }
  .res-section { padding-top: var(--space-6); }
}

@media (prefers-reduced-motion: reduce) {
  .res-atmos span { animation: none; }
}
