/* ============================================================
   THEME / POLISH LAYER  (loaded AFTER each page's own stylesheet)
   Refines the existing dark-minimal identity: depth, smoother
   motion, refined cards, scroll reveal, page transitions.
   Safe to remove by deleting the <link> + <script> tags.
   ============================================================ */

/* one consistent web font across every page / device.
   Self-hosted Inter (variable, latin), served from this origin only.
   No third party, no external request, and it satisfies the CSP. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/inter.woff2") format("woff2");
}

/* applies site-wide (loaded after each page's own font-family) */
html, body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
}

/* Cross-page View Transitions are intentionally OFF (the root size-morph made
   the short home page look shrunk). Instead we fade page content in/out via JS,
   over a constant dark background, so there is no blank frame and no scaling. */
body { opacity: 1 !important; }

/* arriving content page: a quick, snappy fade-up so navigation feels continuous
   (navigation itself is instant; home has its own signature entrance) */
main.page {
  animation: pageEnter 0.32s cubic-bezier(.16, 1, .3, 1) both;
}
@keyframes pageEnter {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: translateY(0); }
}

:root {
  --bg:          #07080a;
  --surface-top: #161719;
  --surface-bot: #0f1011;
  --line:        rgba(255,255,255,0.08);
  --line-strong: rgba(255,255,255,0.22);
  --muted:       rgba(255,255,255,0.62);
  --radius:      18px;
  --accent:      120,150,230;          /* cool premium accent (rgb) */
  --ease:        cubic-bezier(.22,.61,.36,1);
  --ease-out:    cubic-bezier(.16,1,.3,1);
}

/* ===== smoother base ===== */
html {
  background: var(--bg);
  scroll-behavior: smooth;
}
body {
  background: transparent;
}

/* refined scrollbar */
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,0.18) transparent;
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,0.14);
  border-radius: 20px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.26); background-clip: padding-box; }

/* nicer text selection */
::selection { background: rgba(255,255,255,0.16); color: #fff; }

/* accessible focus: a clearly visible keyboard ring on every interactive
   element. :focus-visible keeps it off pointer clicks; !important guarantees
   it overrides any page-level "outline: none" reset on form fields. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:not([tabindex="-1"]):focus-visible {
  outline: 2px solid rgba(255,255,255,0.9) !important;
  outline-offset: 3px;
  border-radius: 4px;
}

/* ===== ambient aurora (behind everything) ===== */
.aurora {
  position: fixed;
  inset: 0;                 /* stay within the viewport (no horizontal overflow) */
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  filter: blur(90px);
}
.aurora span {
  position: absolute;
  display: block;
  border-radius: 50%;
  opacity: 0.72;
  will-change: transform;
}
.aurora span:nth-child(1) {
  width: 46vw; height: 46vw;
  top: -6%; left: 8%;
  background: radial-gradient(circle at 50% 50%, rgba(255,255,255,0.06), transparent 65%);
  animation: auroraA 30s var(--ease) infinite alternate;
}
.aurora span:nth-child(2) {
  width: 40vw; height: 40vw;
  top: 30%; right: 4%;
  background: radial-gradient(circle at 50% 50%, rgba(190,194,202,0.05), transparent 65%);
  animation: auroraB 38s var(--ease) infinite alternate;
}
.aurora span:nth-child(3) {
  width: 38vw; height: 38vw;
  bottom: -10%; left: 30%;
  background: radial-gradient(circle at 50% 50%, rgba(255,255,255,0.045), transparent 65%);
  animation: auroraC 44s var(--ease) infinite alternate;
}
@keyframes auroraA { from { transform: translate3d(-4%, -3%, 0) scale(1); } to { transform: translate3d(6%, 5%, 0) scale(1.15); } }
@keyframes auroraB { from { transform: translate3d(3%, 2%, 0) scale(1.05); } to { transform: translate3d(-5%, -4%, 0) scale(0.95); } }
@keyframes auroraC { from { transform: translate3d(0, 4%, 0) scale(1); } to { transform: translate3d(4%, -4%, 0) scale(1.12); } }

/* ===== INTRO EDGE TRACE (shared; injected by effects.js on every page) =====
   A light streak traces the viewport border on load: the top & bottom halves draw
   from the edge centres out to the corners, then the sides continue to the
   left/right edge centres, then the frame fades. Timing comes from custom props so
   inner pages run quick and the home page (.edge-trace--home, set by effects.js)
   runs a touch slower + more deliberate. Plays for everyone (no reduce-motion
   override, by request). Triggered by body.loaded, which effects.js always sets. */
/* Inner pages (the default) are the quick/thin/faint version; the home hero
   (.edge-trace--home) keeps the slower, thicker, fuller-glow original. Width, glow
   and timing are all per-tier so tweaking one never touches the other. */
.edge-trace {
  --et-w: 3px;                            /* bar thickness (inner: a bit thicker) */
  --et-h-dur: .8s; --et-h-delay: .12s;    /* top/bottom bars: slow enough to read the middle->edge draw */
  --et-v-dur: .8s;  --et-v-delay: .5s;    /* side bars follow */
  --et-fade: 1.9s;                        /* holds the drawn streak, then fades (56% hold ~ draw end) */
  position: fixed;
  inset: 0;
  z-index: 9990;              /* above the topbar (60), below the page-fade (9999) */
  pointer-events: none;
  /* soft halo for the whole layer: each bar's own box-shadow is clipped by its
     clip-path wipe, so this filter carries the glow that bleeds inward. */
  filter: drop-shadow(0 0 4px rgba(185, 220, 255, 0.35))
          drop-shadow(0 0 13px rgba(150, 200, 255, 0.22));
}
.edge-trace--home {
  --et-w: 3px;                            /* home: thicker */
  --et-h-dur: .55s; --et-h-delay: .25s;   /* home: slower, more of a moment */
  --et-v-dur: .6s;  --et-v-delay: .75s;
  --et-fade: 2.5s;
  /* home: fuller glow (the original) */
  filter: drop-shadow(0 0 6px rgba(185, 220, 255, 0.6))
          drop-shadow(0 0 18px rgba(150, 200, 255, 0.4));
}
.et {
  position: absolute;
  background: rgb(226, 243, 255);
  box-shadow: 0 0 4px rgba(200, 230, 255, 0.55), 0 0 9px rgba(160, 205, 255, 0.28);
}
.edge-trace--home .et {   /* home: fuller bar glow (the original) */
  box-shadow: 0 0 6px rgba(200, 230, 255, 0.9), 0 0 14px rgba(160, 205, 255, 0.55);
}
/* top & bottom bars: --et-w tall, each spans centre -> its corner */
.et-tr, .et-tl { top: 0; }
.et-br, .et-bl { bottom: 0; }
.et-tr, .et-tl, .et-br, .et-bl { height: var(--et-w); }
.et-tr, .et-br { left: 50%; right: 0; clip-path: inset(0 100% 0 0); }   /* wipe rightward from centre */
.et-tl, .et-bl { left: 0; right: 50%; clip-path: inset(0 0 0 100%); }   /* wipe leftward from centre */
/* left & right bars: --et-w wide, each spans a corner -> the side centre */
.et-rt, .et-rb { right: 0; }
.et-lt, .et-lb { left: 0; }
.et-rt, .et-lt, .et-rb, .et-lb { width: var(--et-w); }
.et-rt, .et-lt { top: 0; bottom: 50%; clip-path: inset(0 0 100% 0); }   /* wipe downward from top corner */
.et-rb, .et-lb { top: 50%; bottom: 0; clip-path: inset(100% 0 0 0); }   /* wipe upward from bottom corner */

/* Inner pages show ONLY the top edge (a top progress-bar-style streak); the home
   hero keeps the full border. */
.edge-trace:not(.edge-trace--home) .et-br,
.edge-trace:not(.edge-trace--home) .et-bl,
.edge-trace:not(.edge-trace--home) .et-rt,
.edge-trace:not(.edge-trace--home) .et-lt,
.edge-trace:not(.edge-trace--home) .et-rb,
.edge-trace:not(.edge-trace--home) .et-lb { display: none; }

/* horizontals draw first, then the verticals continue the trace to the sides */
body.loaded .et-tr, body.loaded .et-tl,
body.loaded .et-br, body.loaded .et-bl { animation: etWipe var(--et-h-dur) cubic-bezier(.4,0,.3,1) var(--et-h-delay) both; }
body.loaded .et-rt, body.loaded .et-lt,
body.loaded .et-rb, body.loaded .et-lb { animation: etWipe var(--et-v-dur) cubic-bezier(.3,0,.2,1) var(--et-v-delay) both; }
@keyframes etWipe { to { clip-path: inset(0 0 0 0); } }   /* reveal from each bar's start edge */

/* once drawn, the whole frame fades out */
body.loaded .edge-trace { animation: etFade var(--et-fade) ease forwards; }
@keyframes etFade { 0%, 56% { opacity: 1; } 100% { opacity: 0; } }

/* ===== cursor glow (desktop, subtle) ===== */
.cursor-glow {
  position: fixed;
  top: 0; left: 0;
  width: 400px; height: 400px;
  margin: -200px 0 0 -200px;
  border-radius: 50%;
  /* dim core (as before), gentle multi-stop falloff = soft edge, larger area */
  background: radial-gradient(circle, rgba(216,218,224,0.07) 0%, rgba(216,218,224,0.035) 42%, transparent 72%);
  pointer-events: none;
  z-index: 60;
  /* NOT mix-blend-mode:screen, screen is invisible over light pixels, which
     made the glow vanish over the metallic name and the footer text. A plain
     additive overlay reads the same brightness everywhere on the page. */
  opacity: 0;
  transition: opacity .65s ease;
  will-change: transform;
}
.cursor-glow.on { opacity: 1; }

/* Touch variant: phones/tablets. Brighter and a little tighter so it stays
   visible around a fingertip (which sits on the dim centre of the desktop
   glow). JS lifts it above the contact point and toggles this class. */
.cursor-glow.touch {
  width: 300px; height: 300px;
  margin: -150px 0 0 -150px;
  background: radial-gradient(circle, rgba(216,218,224,0.10) 0%, rgba(216,218,224,0.05) 44%, transparent 72%);
}

/* ===== topbar: SOLID ===== */
.topbar {
  /* Height is set here (overriding the per-page CSS, which theme.css loads
     after) so the bar is a touch taller and carries the top edge-trace streak
     with room to spare. Change here and the matching .page padding-top below. */
  height: 88px;
  /* Spot-lit black glass-metal: a soft light source behind the wordmark and a
     top-to-bottom sheen so the bar reads as lit from above rather than flat.
     Still pure black + silver; just more depth to sit beside the bright band. */
  background:
    radial-gradient(120% 180% at 12% -40%, rgba(255,255,255,0.05) 0%, transparent 55%),
    linear-gradient(180deg, #131417 0%, #0a0b0c 100%);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom: 1px solid transparent;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07);   /* top catch-light */
  transition: box-shadow .35s var(--ease);
}
/* tapered silver hairline at the base: faint at rest, resolves on scroll */
.topbar::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.22) 20%, rgba(255,255,255,0.22) 80%, transparent);
  opacity: .6;
  transition: opacity .35s var(--ease);
}
/* Persistent white streak along the very top edge of inner pages: the top
   edge-trace intro draws over this and fades, leaving this line behind so it
   stays. Only on .topbar, so the homepage hero is untouched. */
.topbar::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 3px;                         /* match the edge-trace streak (--et-w) so the line doesn't thin out when the streak settles into it */
  background: rgba(255,255,255,0.9);   /* uniform white line, full width */
  box-shadow: 0 0 8px rgba(255,255,255,0.28);
  pointer-events: none;
  z-index: 2;
  /* Not there until the edge-trace intro has run: stay hidden, then fade in as
     the streak finishes drawing, so the streak "settles" into this line. */
  opacity: 0;
  animation: topline-reveal .5s var(--ease, ease) 1.4s forwards;
}
@keyframes topline-reveal { to { opacity: 1; } }
.topbar.scrolled {
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07), 0 16px 44px -28px rgba(0,0,0,0.95);
}
.topbar.scrolled::after { opacity: 1; }
/* ===== signature wordmark: flowing metallic gradient + glow (uniform sitewide) =====
   Same effect on the home hero (.name) and every sub-page topbar logo (.brand). */
.brand,
.name {
  /* Periodic grey<->white sheen (~50:50 per cycle), repeated so the wordmark
     always shows both tones at once, it can never go fully white. */
  background-image: repeating-linear-gradient(100deg,
    #8f949d 0%, #f2f3f5 12.5%, #8f949d 25%);
  background-size: 200% auto;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  animation: wordmarkFlow 14s linear infinite;
}
/* Travels exactly one tile (200%) so the wrap is seamless; starts on the wordmark. */
@keyframes wordmarkFlow {
  0%   { background-position: 50% center; }
  100% { background-position: -150% center; }
}

/* Pause every continuous ambient animation while the tab is hidden (effects.js
   sets html.anim-paused on visibilitychange). Stops the aurora + wordmark from
   repainting in a background tab, saving CPU/GPU/battery; resumes on return. */
html.anim-paused .aurora span,
html.anim-paused .brand,
html.anim-paused .name,
html.anim-paused .name-motion { animation-play-state: paused !important; }

/* one authoritative wordmark size/tracking for every sub-page topbar (list +
   entry), so "AMAYA KAVYA" never changes size between pages. Loaded after each
   page's own CSS; the mobile size is unified in the breakpoint below. */
.brand {
  font-size: 1.05rem;
  letter-spacing: 0.22em;
  white-space: nowrap;       /* the wordmark must never wrap to two lines */
  transition: letter-spacing .35s var(--ease);
}
.brand:hover { letter-spacing: 0.26em; }

/* ===== minimal nav: About / Research / Posts + search + Menu sheet =====
   The primary row is always visible; every other section lives in a
   full-screen sheet toggled by the Menu button. The existing per-page JS
   toggles .open on #mainNav; effects.js handles Escape, outside taps,
   scroll lock and aria-expanded. The id selectors deliberately outrank the
   legacy absolute-dropdown rules still present in each page's own CSS
   (.nav under @media 768px), at every width. */
#mainNav {
  position: relative;
  z-index: 60;               /* the sheet must stack above fixed page furniture */
  flex-direction: row;
  align-items: center;
  top: auto; left: auto; right: auto;
  border: 0;
  background: none;
  padding: 0;
  transform: none;
  pointer-events: auto;
}
.topbar #mainNav {
  display: flex;
  gap: 1.9rem;
  margin-left: auto;
  opacity: 1;                /* the legacy panel rules hide .nav on phones; the row stays */
}

/* burger: the classic three bars, always visible, morphing to an X while
   the sheet is open (the open button doubles as the close control) */
#mainNav .menu-toggle {
  display: inline-block;
  position: relative;
  z-index: 2;                /* stays clickable above the open sheet */
  background: none;
  border: 0;
  padding: 4px 2px;
  cursor: pointer;
}
#mainNav .menu-toggle span {
  display: block;
  width: 20px;
  height: 2px;
  margin: 4px 0;
  background: #aeaeb2;
  transition: transform .28s var(--ease), opacity .2s var(--ease), background .25s var(--ease);
}
#mainNav .menu-toggle:hover span { background: #fff; }
#mainNav.open .menu-toggle span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
#mainNav.open .menu-toggle span:nth-child(2) { opacity: 0; }
#mainNav.open .menu-toggle span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* inline search: a bare typing line with a magnifier, same hairline language
   as the nav underline. Submits to /search?q= (the search page reads ?q=). */
#mainNav .nav-find {
  position: relative;        /* anchors the live-results panel */
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 2px 1px 5px;
  border-bottom: 1px solid var(--line);
  transition: border-color .25s var(--ease);
}
#mainNav .nav-find:focus-within { border-color: rgba(255, 255, 255, 0.55); }
#mainNav .nav-find svg { color: #7e838c; flex: none; transition: color .25s var(--ease); }
#mainNav .nav-find:focus-within svg { color: #e6e8ec; }
#mainNav .nav-find input {
  appearance: none;
  -webkit-appearance: none;      /* Safari styles type=search as a rounded field */
  background: none;
  border: 0;
  outline: 0;
  border-radius: 0;
  padding: 0 0 2px;              /* keep descenders off the hairline */
  width: 106px;
  color: #e6e8ec;
  caret-color: #e6e8ec;
  font-family: inherit;
  font-size: 0.9rem;
  letter-spacing: 0.01em;        /* typed text at near-normal tracking */
  transition: width .3s var(--ease);
}
/* room to actually type: the line stretches while the field is in use */
#mainNav .nav-find:focus-within input { width: 200px; }
#mainNav .nav-find input::placeholder { color: #6f747d; letter-spacing: 0.06em; }
/* kill the native webkit clear/decoration so the line stays clean */
#mainNav .nav-find input::-webkit-search-decoration,
#mainNav .nav-find input::-webkit-search-cancel-button { -webkit-appearance: none; display: none; }
/* the global focus-visible ring (a white rounded box) reads as ugly clutter on
   this bare typing line; the field already signals focus by lighting its
   hairline + magnifier, so suppress just the outline here (mirrors the home
   hero's .home-find treatment). Needs !important to beat the a11y rule. */
#mainNav .nav-find input:focus-visible,
#mainNav .nav-find input:focus { outline: none !important; }

/* live results under the box: solid panel, hairline border, quiet rows */
#mainNav .find-panel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  width: 330px;
  z-index: 5;
  padding: 5px;
  background: #0c0d0f;
  border: 1px solid var(--line);
  box-shadow: 0 24px 50px -26px rgba(0, 0, 0, 0.95);
}
#mainNav .find-panel .find-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 9px 10px;
  font-size: 0.88rem;
  letter-spacing: 0.02em;
  color: #aeaeb2;
  transition: background .2s var(--ease), color .2s var(--ease);
}
#mainNav .find-panel .find-row + .find-row { border-top: 1px solid rgba(255, 255, 255, 0.04); }
#mainNav .find-panel .find-row:hover,
#mainNav .find-panel .find-row.sel { background: rgba(255, 255, 255, 0.045); color: #fff; }
.find-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.find-cat { flex: none; font-size: 0.72rem; letter-spacing: 0.06em; color: #6f747d; }
#mainNav .find-panel .find-all {
  display: block;
  width: 100%;
  margin-top: 5px;
  padding: 9px 4px 5px;
  background: none;
  border: 0;
  border-top: 1px solid var(--line);
  color: #7e838c;
  font-family: inherit;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-align: center;
  cursor: pointer;
  transition: color .2s var(--ease);
}
#mainNav .find-panel .find-all:hover { color: #fff; }
.find-none { padding: 10px; font-size: 0.8rem; letter-spacing: 0.03em; color: #6f747d; }
/* full-screen sheet: solid, quiet, a single fade - same restraint as the
   solid topbar (no glass blur, no staggered entrances) */
#mainNav .nav-sheet {
  position: fixed;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: safe center;   /* centers when it fits; falls back to the top
                                     (scrollable) when the list is taller than the
                                     screen, instead of clipping the first items */
  gap: 2rem;
  padding: 9vh 6vw;
  overflow-y: auto;
  background: #0c0d0f;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .25s var(--ease), visibility 0s linear .25s;
}
#mainNav.open .nav-sheet {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity .25s var(--ease);
}
.sheet-links {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, auto));
  gap: 1.6rem 5rem;
  text-align: center;
}
#mainNav .nav-sheet a {
  position: relative;
  font-size: clamp(1.2rem, 3vw, 1.6rem);
  letter-spacing: 0.06em;
  color: #aeaeb2;
  transition: color .25s var(--ease);
}
#mainNav .nav-sheet a:hover,
#mainNav .nav-sheet a.active { color: #fff; }
/* utility + legal links (moved here from the footer): a small, quiet, wrapping
   row set off from the sections by a hairline divider */
.sheet-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.8rem 1.5rem;
  max-width: 620px;
  padding-top: 2rem;
  border-top: 1px solid rgba(255,255,255,0.08);
}
#mainNav .nav-sheet .sheet-meta a {
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #6f747d;
}
#mainNav .nav-sheet .sheet-meta a:hover { color: #fff; }

/* tablets: not enough room for the full row beside the wordmark, keep only
   the CURRENT section link (so the way back stays one glance away), plus the
   search box and the burger. The rest lives in the sheet. */
@media (max-width: 880px) {
  .topbar #mainNav > a:not(.active) { display: none; }
  .topbar #mainNav { gap: 1.4rem; }
}

/* phones: the topbar keeps brand + Menu; the row links live in the sheet */
@media (max-width: 560px) {
  .topbar #mainNav > a { display: none; }
  .topbar #mainNav .nav-find { display: none; }
  /* keep the sections in a 2-column grid on phones (6 rows), with airy gaps */
  .sheet-links {
    grid-template-columns: repeat(2, minmax(0, auto));
    gap: 3rem 2.8rem;
  }
  #mainNav .nav-sheet { gap: 3.6rem; padding: 11vh 5vw; }
  #mainNav .nav-sheet a { font-size: 1.2rem; }
  /* legal links below form a 3x2 grid, with wide gaps so no two links sit close
     enough to be read as one */
  .sheet-meta {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, auto));
    justify-content: center;
    gap: 2.4rem 2rem;
    text-align: center;
    padding-top: 3.6rem;
  }
  #mainNav .nav-sheet .sheet-meta a { font-size: 0.66rem; letter-spacing: 0.1em; }
}

/* comfortable tap target for the burger on touch devices (~44px) */
@media (hover: none) and (pointer: coarse) {
  #mainNav .menu-toggle { padding: 12px 8px; }
}

/* ===== arcade (play/) shared chrome ===== */
/* stage sound toggle, injected by play/sfx.js into the stage bar (.bar-right)
   beside Pause/Exit. Inherits .icon-btn chrome per game; sized as a compact
   icon button so the bar stays on one line on narrow phones. */
.sfx-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 7px 9px;
}
.sfx-btn svg { display: block; }
.sfx-btn.muted { opacity: 0.55; }

/* personal best chip on the arcade index cards (play/play.js) */
.card-best {
  color: #e6e8ec;
  white-space: nowrap;
}

/* freeze the page behind the open mobile menu (no background scroll) */
html.nav-open,
html.nav-open body {
  overflow: hidden;
  touch-action: none;
}

/* ===== one consistent nav underline everywhere (home, lists, entries) ===== */
.nav a { transition: color .25s var(--ease); }
/* uniform topbar nav-link size across every sub-page (list + entry). Some pages
   shrank these to 0.78rem on mobile and others didn't, so the menu items
   changed size between pages. Scoped to .topbar so the home hero menu (.nav
   without a topbar) keeps its own sizing. Higher specificity than the per-page
   .nav a rules, so it wins at every breakpoint. */
.topbar .nav a { font-size: 0.9rem; }
.nav a::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.85), transparent);
  transition: width .3s var(--ease), left .3s var(--ease);
}
.nav a:hover::after,
.nav a.active::after {
  width: 100%;
  left: 0;
}

/* ===== page header: subtle gradient title ===== */
.page-header h1 {
  /* one uniform title size across every page (list + entry). Loaded after each
     page's own CSS, so this overrides their per-page h1 sizes. Desktop stays
     larger; the mobile size is unified to 1.8rem in the breakpoint below. */
  font-size: 2.4rem;
  line-height: 1.3;
  background-image: linear-gradient(120deg, #cfd2d6 0%, #ffffff 50%, #cfd2d6 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* entry header is a centered flex container; let its child shrink so long
   article titles wrap within the viewport instead of overflowing the edge */
.entry-header-inner {
  min-width: 0;
  max-width: 100%;
}

/* ===== full-width frosted-glass header band (iOS-style) ===== */
.page { padding-top: 88px; }            /* sit flush under the solid topbar (matches .topbar height) */

.page-header {
  position: relative;
  margin-bottom: 0;                     /* band sits directly above content */
  padding: 56px 6vw 60px;
  /* Inverted, iOS-style light frosted glass: a bright translucent pane that
     stands clearly apart from the dark topbar above and the dark content below.
     The light tint sits over the body aurora, so it frosts rather than going
     flat white. */
  background:
    linear-gradient(180deg, rgba(250,250,252,0.82) 0%, rgba(232,234,240,0.68) 100%);
  -webkit-backdrop-filter: blur(30px) saturate(180%);
  backdrop-filter: blur(30px) saturate(180%);
  border-top: 1px solid rgba(255,255,255,0.55);      /* specular top edge */
  border-bottom: 1px solid rgba(0,0,0,0.14);         /* crisp seam into content */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.9),             /* top glass highlight */
    inset 0 -1px 0 rgba(255,255,255,0.25),
    0 22px 44px -32px rgba(0,0,0,0.75);              /* soft lift over content */
}

/* invert the wordmark-style title to a dark metallic sheen so it reads on the
   light glass while keeping the same brushed-gradient feel */
.page-header h1 {
  background-image: linear-gradient(120deg, #3a3d43 0%, #0a0b0d 50%, #3a3d43 100%);
}

/* entry meta row (category / date / status) is white by default, so darken it so
   it stays legible on the light band */
.page-header .meta {
  color: rgba(22,24,28,0.60);
}

/* ===== content surface: its own dark panel below the band ===== */
.content-surface {
  background: linear-gradient(180deg, var(--surface-top) 0%, var(--surface-bot) 100%);
  position: relative;
}

@media (max-width: 768px) {
  .topbar { height: 72px; }              /* taller mobile bar (overrides per-page 64px) */
  .nav { top: 72px; }                    /* keep the mobile menu flush under the taller bar */
  .page { padding-top: 72px; }
  .page-header { padding: 34px 6vw 38px; }
  /* uniform mobile title size across every page (list + entry) */
  .page-header h1 { font-size: 1.8rem; }
  /* uniform mobile wordmark across every page; sized to match desktop (1.05rem)
     so "AMAYA KAVYA" is the same on phones and PC. Slightly tighter tracking on
     phones to keep it comfortably within the bar. */
  .brand { font-size: 1.05rem; letter-spacing: 0.18em; }
}

/* ===== unified card polish (research / publications / initiatives / posts) ===== */
.research-card,
.publication-card,
.initiative-card,
.post-card {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 0;
  background: linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0.012));
  overflow: hidden;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05);   /* subtle top edge */
  transition: transform .45s var(--ease-out),
              border-color .35s var(--ease),
              background .35s var(--ease),
              box-shadow .45s var(--ease-out);
  will-change: transform;
}
/* left accent that grows on hover */
.research-card::before,
.publication-card::before,
.initiative-card::before,
.post-card::before {
  content: "";
  position: absolute;
  top: 0; left: 0; bottom: 0;
  width: 2px;
  background: linear-gradient(180deg, rgba(255,255,255,0.85), rgba(255,255,255,0.15));
  transform: scaleY(0);
  transform-origin: top;
  transition: transform .45s var(--ease-out);
}
.research-card:hover,
.publication-card:hover,
.initiative-card:hover,
.post-card:hover {
  transform: translateY(-5px);
  border-color: var(--line-strong);
  background: linear-gradient(180deg, rgba(255,255,255,0.065), rgba(255,255,255,0.02));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.08),
    0 32px 60px -32px rgba(0,0,0,0.9);
}
.research-card:hover::before,
.publication-card:hover::before,
.initiative-card:hover::before,
.post-card:hover::before {
  transform: scaleY(1);
}
.research-card h2,
.publication-card h2,
.initiative-card h2,
.post-card h2 {
  transition: color .25s var(--ease);
}

/* ===== "Elsewhere" + entry links: smoother ===== */
.elsewhere-links a,
.entry-links a {
  transition: color .2s var(--ease), border-color .2s var(--ease);
}

/* ===== page fade overlay (works on every page) ===== */
.page-fade {
  position: fixed;
  inset: 0;
  background: var(--bg);
  opacity: 0;
  pointer-events: none;
  transition: opacity .42s var(--ease);
  z-index: 9999;
}
.page-fade.active { opacity: 1; }

/* (No scroll-reveal animation: content is simply present as you scroll.) */

/* ===== footer (consistent across all pages, with legal links) ===== */
.footer {
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 8px;
  height: auto;
  padding: 30px 6vw calc(30px + env(safe-area-inset-bottom));
}
.footer .copyright {
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  color: rgba(255,255,255,0.30);
}
.footer-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 14px;
  pointer-events: auto;
}
.footer-meta a {
  pointer-events: auto;
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  color: rgba(255,255,255,0.6);
  text-decoration: none;
  transition: color .25s var(--ease);
}
.footer-meta a:hover { color: rgba(255,255,255,0.92); }

/* On phones the six links wrap and leave one stranded on its own row.
   Lay them out as an even grid instead (3 columns, so 6 links = 2 tidy rows;
   2 columns on very narrow screens) so nothing is ever left dangling. */
@media (max-width: 600px) {
  .footer-meta {
    display: grid;
    grid-template-columns: repeat(3, auto);
    justify-content: center;
    column-gap: 18px;
    row-gap: 10px;
  }
  .footer-meta a { text-align: center; }
}
@media (max-width: 360px) {
  .footer-meta { grid-template-columns: repeat(2, auto); }
}

/* ===== mobile safety: prevent horizontal overflow, wrap long content ===== */
html, body { overflow-x: hidden; }

.page-header h1,
.research-card h2,
.publication-card h2,
.initiative-card h2,
.post-card h2,
.content p,
.intro,
.exp-org {
  overflow-wrap: break-word;
  word-break: break-word;
}

/* entry meta row: wrap instead of forcing the page wide */
.meta {
  flex-wrap: wrap;
}
@media (max-width: 768px) {
  .meta { gap: 6px 16px; }
}

/* Note: animations intentionally play regardless of the OS "Reduce Motion"
   setting, by request. (No prefers-reduced-motion overrides.) */

/* ===== STICKY FOOTER =====
   Pin the footer to the bottom of the viewport on short pages, on every
   device. The topbar, grain (body::before), aurora, and cursor glow are all
   position:fixed, so they stay out of the flex flow; only main.page and the
   footer are in-flow flex items. The home hero centers via .stage, which is
   untouched. 100dvh keeps it correct under mobile browser UI. */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

.footer {
  margin-top: auto;
}

/* ===== PRINT =====
   Site-wide (theme.css loads on every page). Strips the dark theme and
   site chrome so any page prints as clean black-on-white. */
@media print {

  /* ink-friendly: black text, no dark fills, no shadows/gradients */
  @page {
    margin: 16mm;
  }

  body,
  body * {
    color: #000 !important;
    background: transparent !important;
    box-shadow: none !important;
    text-shadow: none !important;
    -webkit-text-fill-color: #000 !important;
  }

  /* Un-clip the document so the WHOLE page prints, not just the viewport.
     The page CSS sets html/body height:100% (+ overflow:hidden on home),
     which otherwise limits print to one screen. Reset overflow, heights,
     and transforms on EVERYTHING (a transformed ancestor clips printed
     output to its own box). */
  *,
  *::before,
  *::after {
    overflow: visible !important;
    max-height: none !important;
    transform: none !important;
    -webkit-transform: none !important;
    animation: none !important;
  }

  html,
  body,
  main.page,
  .page,
  .content-surface,
  .content {
    height: auto !important;
    min-height: 0 !important;
    position: static !important;
  }

  html,
  body {
    background: #fff !important;
  }

  /* drop decorative layers and site chrome */
  body::before,
  .aurora,
  .edge-trace,
  .cursor-glow,
  .topbar,
  .footer,
  .menu-toggle,
  .nav,
  .back-link {
    display: none !important;
  }

  /* reclaim the space the fixed topbar reserved */
  main.page,
  .page {
    padding-top: 0 !important;
  }

  /* full-width content on paper */
  .content {
    max-width: 100% !important;
    margin: 0 !important;
    padding: 0 !important;
  }

  /* surfaces and cards: plain; flow continuously (no forced page breaks) */
  .content-surface,
  .research-card,
  .publication-card,
  .initiative-card,
  .post-card,
  .link-btn {
    background: #fff !important;
  }

  .research-card,
  .publication-card,
  .initiative-card,
  .post-card {
    border: 1px solid #ccc !important;
  }

  a {
    text-decoration: underline;
  }

  h1, h2, h3 {
    break-after: avoid;
  }

  img {
    max-width: 100% !important;
  }
}

/* ===== SKIP LINK removed ===== */


/* =========================================================================
   REDUCE ANIMATIONS  (Settings toggle -> html[data-motion="reduce"])
   effects.js already skips injecting the aurora / edge-trace / cursor-glow on
   load; this also flattens CSS animation + transitions and hides those layers
   if the preference is flipped live.
   ========================================================================= */
html[data-motion="reduce"] *,
html[data-motion="reduce"] *::before,
html[data-motion="reduce"] *::after {
  animation-duration: .001ms !important;
  animation-delay: 0s !important;
  animation-iteration-count: 1 !important;
  transition-duration: .001ms !important;
  transition-delay: 0s !important;
}
html[data-motion="reduce"] { scroll-behavior: auto; }
html[data-motion="reduce"] .aurora,
html[data-motion="reduce"] .edge-trace,
html[data-motion="reduce"] .cursor-glow { display: none !important; }


/* =========================================================================
   PERFORMANCE MODE  (Settings toggle -> html[data-perf="lite"])
   For weak phones/laptops and for the games in Play/Labs: drop the GPU-heavy
   compositing (backdrop blur, ambient glow/grain, blur filters) and flatten
   animation so the main thread + GPU are free for the game. effects.js also
   skips injecting the aurora / streak / cursor-glow when this is on.
   ========================================================================= */
html[data-perf="lite"] *,
html[data-perf="lite"] *::before,
html[data-perf="lite"] *::after {
  animation-duration: .001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: .001ms !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
html[data-perf="lite"] .aurora,
html[data-perf="lite"] .edge-trace,
html[data-perf="lite"] .cursor-glow,
html[data-perf="lite"] .name-motion { display: none !important; }


/* =========================================================================
   LARGER TEXT  (Settings toggle -> html[data-text="large"])
   Scales the root so all rem-based type grows site-wide.
   ========================================================================= */
html[data-text="large"] { font-size: 112.5%; }


/* =========================================================================
   HIGH CONTRAST  (Settings toggle -> html[data-contrast="high"])
   Pushes the readable text + hairlines to full strength. In light mode the root
   inversion flips these to near-black automatically.
   ========================================================================= */
html[data-contrast="high"] { --muted: #ffffff; --line: rgba(255,255,255,0.55); --line-strong: #ffffff; }
html[data-contrast="high"] body { background: #000 !important; color: #fff; }
html[data-contrast="high"] .content-surface { background: #000 !important; }
/* every piece of readable text to pure white (drop the dim greys entirely) */
html[data-contrast="high"] .content h2,
html[data-contrast="high"] .content h3,
html[data-contrast="high"] .content h4,
html[data-contrast="high"] .content p,
html[data-contrast="high"] .content li,
html[data-contrast="high"] .content strong,
html[data-contrast="high"] .content a,
html[data-contrast="high"] .meta,
html[data-contrast="high"] .nav a,
html[data-contrast="high"] #mainNav .nav-sheet a,
html[data-contrast="high"] #mainNav .nav-sheet .sheet-meta a,
html[data-contrast="high"] .home-chips a,
html[data-contrast="high"] .home-find input,
html[data-contrast="high"] .home-find .find-row,
html[data-contrast="high"] .t-title,
html[data-contrast="high"] .t-artist,
html[data-contrast="high"] .setting-btn,
html[data-contrast="high"] .switch-label,
html[data-contrast="high"] .footer .copyright { color: #fff !important; }
/* underline links so they're distinguishable without relying on colour */
html[data-contrast="high"] .content a { text-decoration: underline !important; text-decoration-color: #fff !important; }
/* strong, clearly-visible hairlines and control borders */
html[data-contrast="high"] .tracklist li,
html[data-contrast="high"] .playlist-head,
html[data-contrast="high"] .sheet-meta,
html[data-contrast="high"] #mainNav .nav-find,
html[data-contrast="high"] .switch-track,
html[data-contrast="high"] .setting-btn { border-color: #ffffff !important; }
/* page title: solid dark on the silver band (the silver gradient is unreadable
   against the bright band in a high-contrast pass) */
html[data-contrast="high"] .page-header h1 {
  background-image: none !important;
  -webkit-text-fill-color: #0a0b0d !important;
  color: #0a0b0d !important;
}



/* =========================================================================
   LIGHT MODE  (Settings toggle -> html[data-theme="light"])
   The site is monochrome, so light mode is a straight inversion: black<->white,
   greys flip, and every layer (edge-streak, aurora, scripture, gradients, the
   silver wordmark) flips uniformly with no per-element theming. hue-rotate keeps
   the faint cool accent roughly true. Real images / canvas / video are inverted
   back so photos and the arcade render normally.
   ========================================================================= */
html[data-theme="light"] {
  filter: invert(1) hue-rotate(180deg);
}
html[data-theme="light"] img,
html[data-theme="light"] picture,
html[data-theme="light"] video,
html[data-theme="light"] canvas,
html[data-theme="light"] .dg-dot,
html[data-theme="light"] .no-invert {
  filter: invert(1) hue-rotate(180deg);
}
