@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300;0,9..144,400;1,9..144,300;1,9..144,400&family=Hanken+Grotesk:wght@400;500&display=swap');

:root{
  --porcelain:#F5EFE7;   /* page */
  --surface:#E8E6E1;     /* surfaces / cards — cool pale neutral */
  --rose:#C98A8F;        /* accent — dusty rose, use sparingly */
  --mist:#6B6E77;        /* secondary text — cool grey */
  --ink:#23252B;         /* primary text — soft charcoal */
  --body:#454852;        /* body copy — mid charcoal */
  --pearl:linear-gradient(118deg,#EAF1E6 0%,#D6E8DC 20%,#F1CFC4 40%,#E1EDE0 58%,#F3D4CA 78%,#E9F1E7 100%);
  --serif:"Fraunces",Georgia,serif;
  --sans:"Hanken Grotesk","Pretendard",system-ui,sans-serif;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{background:var(--porcelain);color:var(--ink);font-family:var(--sans);-webkit-font-smoothing:antialiased}

.hero,.main{position:relative;min-height:100svh;overflow:hidden;display:flex;flex-direction:column}

/* mother-of-pearl signature — large, slow pastel drift, softened for the colored-pencil blur */
.pearl{position:absolute;inset:-30px;z-index:0;pointer-events:none;
  background:var(--pearl);background-size:240% 240%;
  filter:blur(2px);
  animation:pearlDrift 15s ease-in-out infinite}
@keyframes pearlDrift{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}

/* caustic light-web — soft rippling light warped into a water surface, tuned pale for the minty water */
.caustics{position:absolute;inset:-60px;z-index:1;pointer-events:none;mix-blend-mode:screen;opacity:.55;
  filter:url(#rippleStrong) blur(4px);
  background:
    repeating-linear-gradient(38deg, rgba(255,247,232,0) 0, rgba(255,247,232,.55) 70px, rgba(255,247,232,0) 148px),
    repeating-linear-gradient(-54deg, rgba(255,250,242,0) 0, rgba(255,250,242,.4) 98px, rgba(255,250,242,0) 206px);
  background-size:200% 200%,220% 220%;
  animation:causticFlow 24s ease-in-out infinite}
@keyframes causticFlow{
  0%{background-position:0% 0%,100% 100%}
  50%{background-position:60% 40%,40% 60%}
  100%{background-position:0% 0%,100% 100%}
}

/* film grain — grainier paper-tooth texture, warped by the ripple filter into a watery shimmer */
.grain{position:absolute;inset:0;z-index:2;pointer-events:none;opacity:.14;mix-blend-mode:multiply;
  filter:url(#ripple);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.72' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}

/* cursor light — a soft light hotspot that trails the pointer */
.cursor-glow{position:absolute;top:0;left:0;width:46vmax;height:46vmax;margin:-23vmax 0 0 -23vmax;
  z-index:1;pointer-events:none;mix-blend-mode:screen;opacity:0;
  background:radial-gradient(circle, rgba(255,244,224,.55), rgba(255,244,224,0) 62%);
  transform:translate3d(-100vw,-100vw,0);transition:opacity .8s ease}

nav{position:relative;z-index:3;display:flex;flex-wrap:wrap;row-gap:.7rem;justify-content:space-between;align-items:center;
  padding:clamp(1.5rem,3.5vw,2.4rem) clamp(1.5rem,5vw,3.6rem)}
.mark{font-family:var(--serif);font-weight:400;font-size:1.02rem;letter-spacing:.01em;color:var(--ink);text-decoration:none}
.links{display:flex;flex-wrap:wrap;row-gap:.5rem;gap:clamp(1.1rem,2.4vw,2rem)}
.links a{color:var(--ink);text-decoration:none;font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;
  opacity:.72;transition:opacity .5s ease,color .35s ease}
/* header text changes color on hover */
.links a:hover,.links a:focus-visible{opacity:1;color:var(--rose);outline:none}
.links a:focus-visible{text-decoration:underline;text-underline-offset:5px}
/* the current page's link stays highlighted */
.links a[aria-current="page"]{opacity:1;color:var(--rose)}
/* "In Progress..." behaves like the other links (normal color, rose on hover) */

.stage{position:relative;z-index:3;flex:1;display:flex;align-items:flex-end;
  padding:0 clamp(1.5rem,5vw,3.6rem) clamp(3rem,8vw,5.5rem)}
.eyebrow{font-size:.72rem;letter-spacing:.24em;text-transform:uppercase;color:var(--mist);font-weight:500;margin-bottom:1.1rem}
h1{font-family:var(--serif);font-weight:300;font-optical-sizing:auto;letter-spacing:-.02em;
  font-size:clamp(2.9rem,10vw,7rem);line-height:.92;max-width:16ch}
.desc{margin-top:1.5rem;max-width:44ch;font-size:clamp(1rem,1.5vw,1.15rem);line-height:1.55;color:var(--body)}
.desc em{font-family:var(--serif);font-style:italic;font-weight:400;color:var(--rose)}

/* inner-page content — quiet and typographic */
.stage h2{font-family:var(--serif);font-weight:400;font-size:1.4rem;margin:2rem 0 .6rem;letter-spacing:-.01em}
.stage ul{list-style:none;max-width:54ch;margin-top:2rem}
/* project rows: hairline-ruled. rising-tide fill — pearl rises from the base like water
   filling the row, instead of the whole surface switching at once */
.stage li{position:relative;overflow:hidden;isolation:isolate;
  padding:1rem 1.1rem;border-top:1px solid rgba(35,37,43,.12);color:var(--body);line-height:1.5;
  border-radius:3px;transition:color .55s ease}
.stage li::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:var(--pearl);transform:translateY(101%);
  transition:transform .55s cubic-bezier(.4,0,.2,1)}
.stage li:hover{color:var(--ink)}
.stage li:hover::before{transform:translateY(0)}
/* section headings within the list */
.stage .group{margin-top:3rem}
.stage .group:first-of-type{margin-top:1.4rem}

/* scrollable content pages (index + detail): block flow so content fills the width */
.stage--doc{display:block;align-items:flex-start;padding-top:clamp(1rem,4vw,2.5rem)}
/* centered reading column — text, media, and code all share one width instead of
   hugging the left edge with a dead gutter on wide screens */
.stage--doc>div{width:100%;max-width:60ch;margin-inline:auto}
/* the card grid (projects index) wants the full stage width for its column layout */
.stage--doc:has(.cards)>div{max-width:none;margin-inline:0}
/* the about page's text+portrait row needs more than 60ch or the intro paragraph
   gets squeezed into a sliver beside the image */
.stage--doc:has(.about-hero)>div{max-width:78ch}
.stage--doc h1{font-size:clamp(2rem,5.5vw,3.4rem);line-height:1;max-width:22ch}

/* project cards — readable buttons that lead to a detail page */
/* fixed column counts (max 3) so the soft column-themes hold: movement | product | hardware */
.cards{display:grid;grid-template-columns:1fr;
  gap:clamp(.9rem,1.5vw,1.25rem);margin-top:1.5rem;list-style:none}
@media(min-width:560px){.cards{grid-template-columns:1fr 1fr}}
@media(min-width:880px){.cards{grid-template-columns:repeat(3,1fr)}}
/* subgrid: each card shares the row's track heights, so titles, meta, teasers, chips and
   the CTA all line up across a row regardless of how long any one of them runs */
.card{position:relative;overflow:hidden;isolation:isolate;
  display:grid;grid-template-rows:subgrid;grid-row:span 6;row-gap:.5rem;
  padding:clamp(1.3rem,1.9vw,1.75rem);border-radius:6px;
  background:rgba(248,243,236,.5);-webkit-backdrop-filter:blur(12px) saturate(1.15);
  backdrop-filter:blur(12px) saturate(1.15);
  color:var(--body);text-decoration:none;
  transition:transform .5s ease,box-shadow .6s ease,color .6s ease}
/* caustic reveal — a slow water-light shimmer surfaces inside the glass on hover
   (reuses the same rippleStrong filter + flow as the page's .caustics) */
.card::before{content:"";position:absolute;inset:-40%;z-index:-1;pointer-events:none;
  mix-blend-mode:screen;opacity:0;
  background:
    repeating-linear-gradient(38deg, rgba(255,247,232,0) 0, rgba(255,247,232,.85) 54px, rgba(255,247,232,0) 120px),
    repeating-linear-gradient(-54deg, rgba(210,235,222,0) 0, rgba(210,235,222,.7) 74px, rgba(210,235,222,0) 170px),
    repeating-linear-gradient(84deg, rgba(243,212,202,0) 0, rgba(243,212,202,.4) 110px, rgba(243,212,202,0) 230px);
  background-size:170% 170%,200% 200%,240% 240%;
  filter:url(#rippleStrong) blur(2.5px);
  transition:opacity .6s ease;
  animation:causticFlow 20s ease-in-out infinite}
/* glare — a small cursor-tracked light sheen, positioned by --mx/--my (set in effects.js).
   Reads as light catching the glass, so it stands in for the elevation a shadow used to give. */
.card::after{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  mix-blend-mode:screen;opacity:0;
  background:radial-gradient(220px circle at var(--mx,50%) var(--my,50%),rgba(255,255,255,.55),transparent 70%);
  transition:opacity .4s ease}
.card:hover,.card:focus-visible{color:var(--ink);
  transform:translateY(-2px);box-shadow:0 16px 40px -22px rgba(201,138,143,.55);outline:none}
.card:hover::before,.card:focus-visible::before{opacity:.92}
.card:hover::after,.card:focus-visible::after{opacity:1}
.card:focus-visible{box-shadow:0 0 0 2px var(--rose)}
.card .pname{font-family:var(--serif);font-weight:400;font-size:1.28rem;letter-spacing:-.01em;
  color:var(--ink);line-height:1.15}
.card .meta{font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;color:var(--mist);font-weight:500}
.card .teaser{font-size:.98rem;line-height:1.55;color:inherit}
/* area tags — small descriptive pills, not filters. Quiet at rest, readable on hover.
   Pinned to the bottom of the card (margin-top:auto) so the chip row lines up across
   cards of a row regardless of how long each teaser runs. */
/* area tags — small descriptive pills, not filters. Reused on cards and detail pages. */
.tags{display:flex;flex-wrap:wrap;gap:.4rem}
.tag{font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;font-weight:500;
  color:var(--mist);border:1px solid rgba(35,37,43,.14);border-radius:100px;padding:.24rem .56rem;
  transition:border-color .5s ease,color .5s ease}
/* on cards: outdent so the chip TEXT sits flush with the title/teaser, and warm on hover */
.card .tags{margin-left:-.56rem}
.card:hover .tag,.card:focus-visible .tag{border-color:rgba(35,37,43,.24);color:var(--body)}
/* on detail pages: a chip row sitting just under the metarow */
.tags--doc{margin-top:.9rem}

/* skill chips — a second, more granular row under the area tags. Color-coded by
   kind (language / tool·platform / method·concept) so the category reads at a
   glance without a label. Filled, unlike the outline-only area tags, so the two
   rows stay visually distinct even when both are quiet at rest. */
.skills{display:flex;flex-wrap:wrap;gap:.4rem}
.skill{font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;font-weight:500;
  border-radius:100px;padding:.24rem .56rem;border:1px solid transparent;
  transition:border-color .5s ease,background .5s ease}
.skill--lang{color:#4F6C57;background:rgba(126,168,143,.16);border-color:rgba(126,168,143,.3)}
.skill--tool{color:#8A5F2E;background:rgba(184,146,90,.18);border-color:rgba(184,146,90,.34)}
.skill--method{color:#4C5E78;background:rgba(123,143,168,.18);border-color:rgba(123,143,168,.34)}
.card .skills{margin-left:-.56rem}
.card:hover .skill,.card:focus-visible .skill{border-color:currentColor}
.skills--doc{margin-top:.6rem}
.card .go{margin-top:1.2rem;font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--rose);display:inline-flex;align-items:center;gap:.4rem;transition:gap .4s ease}
.card:hover .go,.card:focus-visible .go{gap:.75rem}
.card--soon{opacity:.72}
.card--soon .go{color:var(--mist)}

/* detail pages — back link, meta row, long-form prose */
.backlink{display:inline-flex;align-items:center;gap:.45rem;font-size:.72rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mist);text-decoration:none;font-weight:500;
  transition:color .4s ease,gap .4s ease;margin-bottom:1.5rem}
.backlink:hover,.backlink:focus-visible{color:var(--rose);gap:.7rem;outline:none}
.metarow{margin-top:1rem;font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--mist);font-weight:500;line-height:1.7}
.prose{margin-top:1.9rem;max-width:60ch}
.prose p{margin-top:1.15rem;color:var(--body);line-height:1.7;font-size:clamp(1rem,1.4vw,1.08rem)}
.prose p:first-child{margin-top:0}
.prose .note{margin-top:1.8rem;font-size:.88rem;color:var(--mist);font-style:italic;line-height:1.6}
.prose a{color:var(--rose);text-decoration:none;border-bottom:1px solid rgba(201,138,143,.5);transition:color .4s ease}
.prose a:hover,.prose a:focus-visible{color:var(--ink)}
/* GitHub / external link button */
.repo{display:inline-flex;align-items:center;gap:.45rem;margin-top:1.3rem;
  font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;font-weight:500;
  color:var(--rose);text-decoration:none;border:1px solid rgba(201,138,143,.45);border-radius:6px;
  padding:.55rem .9rem;transition:background .4s ease,color .4s ease,border-color .4s ease}
.repo:hover,.repo:focus-visible{background:var(--rose);color:var(--porcelain);border-color:transparent;outline:none}
/* project media — frosted frame + grain pass so photos and diagrams sit inside the
   same glass language as the cards, not pasted on top of it. One class, reused
   everywhere media appears on a detail page. */
.media-frame{position:relative;overflow:hidden;isolation:isolate;margin-top:1.9rem;
  border-radius:8px;border:1px solid rgba(255,255,255,.5);
  background:rgba(248,243,236,.5);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  box-shadow:0 4px 16px -10px rgba(35,37,43,.25),inset 0 1px 0 rgba(255,255,255,.35)}
.media-frame img{display:block;width:100%;height:auto}
.media-frame figcaption{padding:.75rem 1rem;font-size:.8rem;color:var(--mist);line-height:1.5}
.media-grid{display:grid;grid-template-columns:1fr;gap:1.1rem;margin-top:1.9rem}
.media-grid .media-frame{margin-top:0}
@media(min-width:640px){.media-grid{grid-template-columns:1fr 1fr}}

/* about page: portrait sits beside the opening two paragraphs, then prose
   goes back to full width below */
.about-hero{display:flex;flex-direction:column-reverse;gap:1.9rem;margin-top:1.9rem}
.about-hero .about-intro{margin-top:0}
.about-portrait{margin-top:0;flex-shrink:0;align-self:center;width:100%;max-width:20rem;aspect-ratio:3/4}
.about-portrait img{width:100%;height:100%;object-fit:cover}
@media(min-width:760px){.about-hero{flex-direction:row;align-items:flex-start}
  .about-hero .about-intro{flex:1 1 auto}
  .about-portrait{align-self:flex-start}}

/* video embeds — same frosted frame language as .media-frame, held to 16:9 */
.video-frame{position:relative;overflow:hidden;isolation:isolate;margin-top:1.9rem;
  aspect-ratio:16/9;border-radius:8px;border:1px solid rgba(255,255,255,.5);
  background:rgba(248,243,236,.5);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  box-shadow:0 4px 16px -10px rgba(35,37,43,.25),inset 0 1px 0 rgba(255,255,255,.35)}
.video-frame iframe{display:block;width:100%;height:100%;border:0}

/* code appendix — monospace, dimmer than prose, scrolls its own overflow rather
   than the page */
.codeblock{margin-top:1.9rem;max-width:60ch;border-radius:8px;
  border:1px solid rgba(35,37,43,.14);background:rgba(35,37,43,.04);overflow-x:auto}
.codeblock pre{padding:1.1rem 1.3rem;font-family:ui-monospace,"SF Mono",Menlo,monospace;
  font-size:.82rem;line-height:1.6;color:var(--body);white-space:pre}
details.codewrap summary{margin-top:1.9rem;cursor:pointer;font-size:.72rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--rose);font-weight:500;list-style:none}
details.codewrap summary::-webkit-details-marker{display:none}
details.codewrap summary::before{content:"View code ";}
details.codewrap[open] summary::before{content:"Hide code ";}
details.codewrap .codeblock{margin-top:1rem}

/* project subsections on a combined page */
.workblock{margin-top:2.6rem;padding-top:2.4rem;border-top:1px solid rgba(35,37,43,.12)}
.workblock h2{font-family:var(--serif);font-weight:400;font-size:1.5rem;letter-spacing:-.01em;margin:0}
.foot{display:block;margin-top:2.6rem}
.stage a.textlink{color:var(--rose);text-decoration:none;border-bottom:1px solid rgba(201,138,143,.55)}
.stage a.textlink:hover{color:var(--ink)}

/* ── blob variant (#7 reimagined): borderless frosted-glass blobs floating on the water.
   Organic asymmetric radii, each breathing on its own slow, desynced cycle. Soft shadows
   follow the shape so they read as glass resting on the surface. Scoped to .cards--blobs. */
/* Extreme organic droplets. Content is minimal (title only, centered) because an irregular
   outline has no straight edge to seat body text — teaser/chips live on the detail page. */
.cards.cards--blobs{grid-template-columns:repeat(auto-fit,minmax(23rem,1fr));
  gap:clamp(2.5rem,5vw,5rem);align-items:start}
.cards--blobs .card{grid-template-rows:none;grid-row:auto;border:none;
  display:flex;flex-direction:column;justify-content:center;align-items:center;gap:.6rem;text-align:center;
  min-height:17rem;padding:clamp(2.6rem,4vw,4rem);
  /* translucent glass over the water */
  background:rgba(255,255,255,.16);
  -webkit-backdrop-filter:blur(7px) saturate(1.5) brightness(1.05);
  backdrop-filter:blur(7px) saturate(1.5) brightness(1.05);
  /* subtle glass form (masked to the cloud): light off the top, shade at the base */
  box-shadow:inset 0 12px 22px -14px rgba(255,255,255,.6),inset 0 -16px 28px -18px rgba(35,37,43,.22);
  /* cloud silhouette: a union of soft circles (border-radius can't make lobes) */
  -webkit-mask:var(--cloud);mask:var(--cloud);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  transform:translate(var(--dx,0px),var(--dy,0px))}
.cards--blobs .card:hover,.cards--blobs .card:focus-visible{
  transform:translate(var(--dx,0px),calc(var(--dy,0px) - 8px))}
/* three cloud silhouettes + varied heights, cycled */
.cards--blobs .card:nth-child(3n+1){min-height:18rem;
  --cloud:radial-gradient(circle at 30% 57%,#000 21%,transparent 24%),radial-gradient(circle at 44% 43%,#000 24%,transparent 27%),radial-gradient(circle at 59% 45%,#000 23%,transparent 26%),radial-gradient(circle at 70% 56%,#000 20%,transparent 23%),radial-gradient(circle at 50% 62%,#000 23%,transparent 26%)}
.cards--blobs .card:nth-child(3n+2){min-height:16rem;
  --cloud:radial-gradient(circle at 32% 48%,#000 21%,transparent 24%),radial-gradient(circle at 47% 59%,#000 23%,transparent 26%),radial-gradient(circle at 63% 46%,#000 22%,transparent 25%),radial-gradient(circle at 69% 57%,#000 19%,transparent 22%),radial-gradient(circle at 43% 41%,#000 19%,transparent 22%)}
.cards--blobs .card:nth-child(3n){min-height:17rem;
  --cloud:radial-gradient(circle at 30% 54%,#000 20%,transparent 23%),radial-gradient(circle at 43% 44%,#000 24%,transparent 27%),radial-gradient(circle at 57% 57%,#000 23%,transparent 26%),radial-gradient(circle at 69% 48%,#000 21%,transparent 24%),radial-gradient(circle at 54% 63%,#000 21%,transparent 24%)}
/* scattered placement — visual only (transform), so layout and gaps are untouched */
.cards--blobs .card:nth-child(1){--dx:-.6rem;--dy:.4rem}
.cards--blobs .card:nth-child(2){--dx:.9rem;--dy:4rem}
.cards--blobs .card:nth-child(3){--dx:-.4rem;--dy:1.4rem}
.cards--blobs .card:nth-child(4){--dx:1rem;--dy:3rem}
.cards--blobs .card:nth-child(5){--dx:-1.1rem;--dy:.6rem}
.cards--blobs .card:nth-child(6){--dx:.5rem;--dy:4.4rem}
.cards--blobs .card:nth-child(7){--dx:-.7rem;--dy:2rem}
.cards--blobs .card:nth-child(8){--dx:.7rem;--dy:.3rem}
.cards--blobs .card:nth-child(9){--dx:-.5rem;--dy:3.4rem}
/* liquid inner sheen — inside the masked card, so it takes the cloud shape */
.cards--blobs .card::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;mix-blend-mode:screen;
  background:
    radial-gradient(58% 42% at 36% 26%, rgba(255,255,255,.66), rgba(255,255,255,.16) 46%, transparent 64%),
    radial-gradient(70% 55% at 66% 86%, rgba(255,255,255,.22), transparent 60%);
  transition:opacity .6s ease}
.cards--blobs .card:hover::after,.cards--blobs .card:focus-visible::after{opacity:.85}
.cards--blobs .card .teaser,.cards--blobs .card .tags,.cards--blobs .card .skills,.cards--blobs .card .go{display:none}
.cards--blobs .card .pname{font-size:clamp(1.05rem,1.5vw,1.32rem);max-width:11ch;line-height:1.15}
.cards--blobs .card .meta{display:none}

/* ── index / list format (alternative to the card grid) ──────────────────────
   A typographic table of contents: big serif names, hairline rules, and the pearl
   rising from the baseline on hover. Lets the full-page water breathe behind it. */
.index{list-style:none;margin-top:1.6rem;border-top:1px solid rgba(35,37,43,.12)}
.index .row{position:relative;overflow:hidden;isolation:isolate;
  display:grid;grid-template-columns:1fr auto;column-gap:2rem;row-gap:.55rem;align-items:baseline;
  padding:1.5rem 1.1rem;border-bottom:1px solid rgba(35,37,43,.12);
  text-decoration:none;color:var(--body)}
.index .row::before{content:"";position:absolute;inset:0;z-index:-1;background:var(--pearl);
  transform:translateY(101%);transition:transform .55s cubic-bezier(.4,0,.2,1)}
.index .row:hover::before,.index .row:focus-visible::before{transform:translateY(0)}
.index .row:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--rose)}
/* name top-left, year anchored top-right; meta + teaser stack beneath in the left column */
.index .rname{grid-column:1;grid-row:1;font-family:var(--serif);font-weight:400;letter-spacing:-.01em;
  line-height:1.05;font-size:clamp(1.35rem,3vw,2rem);color:var(--ink)}
.index .ryear{grid-column:2;grid-row:1;justify-self:end;font-size:.76rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--mist);font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap}
.index .rmeta{grid-column:1;grid-row:2;font-size:.7rem;letter-spacing:.16em;text-transform:uppercase;color:var(--mist);font-weight:500}
.index .rteaser{grid-column:1;grid-row:3;font-size:1rem;line-height:1.55;color:var(--body);max-width:60ch}
.index .row:hover .rteaser,.index .row:focus-visible .rteaser{color:var(--ink)}

@media (prefers-reduced-motion:reduce){
  .pearl,.caustics,.card::before,.cards--blobs .card{animation:none}  /* freeze drift, caustics, blob morph */
  .stage li::before,.index .row::before{transition:none}  /* rising tide appears without the sweep */
}
