/* ---------------------------------------------------------------------------
   Arpit Ramani — minimal.

   Two pages, one stylesheet. index.html is a centred paragraph; portfolio.html
   is the same paragraph's worth of restraint applied to a long list. Light
   only: near-black type on white, over a faint band of dots along the
   bottom of the page (field.js). No cards, no panels: hierarchy is size,
   weight and one accent.

   Everything is lowercase in the markup itself rather than via text-transform,
   so a screen reader and a copy-paste both get what the page shows.
   --------------------------------------------------------------------------- */

:root {
  --bg:      #ffffff;
  --head:    #111113;   /* name, section headings, emphasis */
  --text:    #55534f;   /* body copy */
  --faint:   #76736e;   /* dates, meta, punctuation between things */
  --rule:    #ebeae7;
  --line:    #d2d0cb;   /* resting underlines */
  --wash:    #f3f2ef;   /* hover fill behind icons, code */
  --dots:    #c4c1bb;   /* the background band (field.js) */
  --accent:  #111113;   /* the highlight: links and row titles */
  --accent-h:#000000;   /* and the only thing hover changes */

  --sans: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.65;
  font-weight: 400;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* The landscape canvas field.js puts behind everything. */
.field {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
}

a {
  color: var(--accent);
  text-decoration: none;
  transition: color 0.12s ease, text-decoration-color 0.12s ease;
}
a:hover { color: var(--accent-h); }

/* Links inside running text keep a hairline underline, because on a monochrome
   page nothing else distinguishes them from the emphasis around them. Row
   titles get theirs only on hover: a list of twenty underlined names is a mess,
   and there the pointer is already doing the asking. */
.blurb a, .facts a {
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}
.blurb a:hover, .facts a:hover { text-decoration-color: var(--head); }

a.name {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.24em;
}
a.name:hover { text-decoration-color: var(--head); }

::selection { background: var(--head); color: var(--bg); }

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


/* =============================== landing =================================== */
/* The whole point of the site: one block of text, vertically centred, with the
   links directly under it. min-height uses svh so mobile browser chrome sliding
   in and out does not shift the block. */

body.landing {
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100svh;
  padding: 3rem 1.5rem;
}

.card {
  max-width: 34rem;
  width: 100%;
}

.hi {
  margin: 0 0 1.4rem;
  font-size: 1.9rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.03em;
  color: var(--head);
}

.blurb {
  margin: 0;
  font-size: 1.06rem;
  line-height: 1.7;
}
.blurb strong {
  color: var(--head);
  font-weight: 600;
}
/* Y Combinator batch, kept quiet so it reads as an aside rather than a brag. */
.yc { color: var(--faint); }

/* The one destination on the page is a labelled link, not an icon: an icon can
   only ever hint, and "portfolio" has no glyph everyone reads the same way. It
   is the largest interactive thing here and sits on its own line above the
   secondary links, so there is no competition for what to click. */
.cta {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  margin-top: 2.1rem;
  font-size: 1.12rem;
  font-weight: 600;
  color: var(--head);
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
}
.cta:hover {
  color: var(--accent-h);
  text-decoration-color: var(--accent-h);
}
/* The arrow leans into the hover. Its own element so the underline under the
   label does not stretch as it moves. */
.cta .arrow {
  display: inline-block;
  transition: transform 0.15s ease;
}
.cta:hover .arrow { transform: translateX(3px); }

/* Everything else is a secondary link and gets an icon: recognisable marks that
   need no label, in a 2.4rem hit target with a ~21px glyph. The names live in
   aria-label and title, so the row still reads to a screen reader and on
   hover. */
.links {
  margin-top: 1.15rem;
  margin-left: -0.55rem;   /* optically align the first glyph with the text */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.15rem;
}
.links a {
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 10px;
  color: var(--faint);
}
/* "me" is the one word in the row: there is no glyph for "photos of my
   life" that reads at a glance. Same box height and colour as the icons, so
   it sits on their baseline as one more link. */
.links a.word {
  width: auto;
  padding: 0 0.6rem;
  font-size: 0.98rem;
  font-weight: 600;
}
.links a:hover {
  color: var(--head);
  background: var(--wash);
}

.links svg, .foot svg {
  width: 1.3125rem;
  height: 1.3125rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.links svg.solid, .foot svg.solid { fill: currentColor; stroke: none; }


/* ------------------------------- the photos -------------------------------- */
/* me.html: the photo dump. Same centred card as the landing page, with a
   small strip of photos under the heading drifting left to right on a loop,
   like a conveyor belt. belt.js clones the row once so the loop has no seam:
   the track slides from -50% to 0, which is exactly one copy's width, then
   starts over on an identical frame. The ends fade into the page so photos
   arrive and leave rather than being cut off. */

/* Wider than the landing card: the photos are the page here, so the column
   opens up to most of a laptop screen and the photos take about a third of
   its height. */
.card.dump { max-width: 64rem; }
.card > .back { margin-bottom: 2.2rem; }
.dumphead { margin-bottom: 1rem; font-size: 1.9rem; }
.mesec + .mesec { margin-top: 2.8rem; }

/* contain: inline-size stops the track's full width from counting toward the
   card's size; without it the landing grid widens the card to fit every
   photo and the page scrolls sideways on a phone. */
.belt {
  contain: inline-size;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.belt::-webkit-scrollbar { display: none; }
.track {
  display: flex;
  width: max-content;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Spacing is a margin on every photo, not flex gap: with gap the track is
   one gap short of two whole copies, and the loop would hitch by half a gap
   each time round. */
.track li { margin-right: 0.9rem; }
.track img {
  display: block;
  height: clamp(12rem, 38svh, 22rem);
  width: auto;
  border-radius: 6px;
}

/* The drift. Duration is set by belt.js from the track's width, so the speed
   is the same however many photos there are. */
@keyframes drift {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}
.js .belt { overflow: hidden; }
.js .track.moving {
  animation: drift var(--drift, 60s) linear infinite;
}
/* Resting a pointer on the belt stops it, so a photo can be looked at. */
.belt:hover .track { animation-play-state: paused; }

/* No drift for reduced motion: the strip just scrolls sideways by hand. */
@media (prefers-reduced-motion: reduce) {
  .js .belt { overflow-x: auto; }
  .js .track.moving { animation: none; }
}


/* -------------------------------- writing ----------------------------------- */
/* The writing list on me.html: one row per post, title on the left, month
   on the right, newest first. Same hover as everywhere: the
   title goes white and takes an underline. */

.posts {
  list-style: none;
  margin: 0;
  padding: 0;
}
.posts:empty { display: none; }
.posts a {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 1rem;
  padding: 0.45rem 0;
}
.posts .t {
  color: var(--head);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.24em;
  transition: text-decoration-color 0.12s ease;
}
.posts a:hover .t { text-decoration-color: var(--head); }
.posts .when { padding-left: 0; }
.empty { margin: 0; color: var(--faint); }


/* A post: one column held to a reading measure, a little larger and looser
   than the rest of the site because it is meant to be read at length. Body
   copy is --text grey and headings are --head, the same two voices as the
   landing paragraph. */

body.post {
  padding: clamp(3rem, 12vh, 7rem) 1.5rem 7rem;
}
.entry {
  max-width: 36rem;
  margin: 0 auto;
  font-size: 1.06rem;
  line-height: 1.78;
}
.entry .back { margin-bottom: 2.6rem; }
.entry h1 {
  margin: 0 0 0.35rem;
  font-size: 1.9rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.03em;
  color: var(--head);
}
.entry .date {
  margin: 0 0 2.4rem;
  font-size: 0.88rem;
  color: var(--faint);
}
.entry h2 {
  margin: 2.6rem 0 0.8rem;
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--head);
}
.entry h3 {
  margin: 2rem 0 0.6rem;
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--head);
}
.entry p, .entry ul, .entry ol, .entry blockquote, .entry pre, .entry figure {
  margin: 0 0 1.25rem;
}
.entry ul, .entry ol { padding-left: 1.3rem; }
.entry li { margin-bottom: 0.35rem; }
.entry li::marker { color: var(--faint); }
.entry strong { color: var(--head); font-weight: 600; }
.entry a {
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}
.entry a:hover { text-decoration-color: var(--head); }
.entry .back { text-decoration: none; }
.entry blockquote {
  padding-left: 1.1rem;
  border-left: 2px solid var(--rule);
  color: var(--faint);
}
.entry blockquote p:last-child { margin-bottom: 0; }
.entry code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.88em;
  padding: 0.1em 0.35em;
  border-radius: 4px;
  background: var(--wash);
  color: var(--head);
}
.entry pre {
  overflow-x: auto;
  padding: 1rem 1.1rem;
  border-radius: 8px;
  background: var(--wash);
  border: 1px solid var(--rule);
  line-height: 1.6;
}
.entry pre code { padding: 0; background: none; font-size: 0.86rem; color: var(--text); }
.entry img {
  display: block;
  max-width: 100%;
  max-height: 70svh;   /* a portrait photo should not outgrow the screen */
  width: auto;
  height: auto;
  margin: 0 auto;
  border-radius: 6px;
}
.entry figcaption {
  margin-top: 0.6rem;
  font-size: 0.86rem;
  color: var(--faint);
  text-align: center;
}
.entry hr {
  margin: 2.6rem 0;
  border: 0;
  border-top: 1px solid var(--rule);
}


/* =============================== portfolio ================================= */

body.work {
  padding: 5rem 1.5rem 7rem;
}

.wrap {
  max-width: 44rem;
  margin: 0 auto;
}

.back {
  display: inline-block;
  margin-bottom: 3.5rem;
  font-size: 0.9rem;
  color: var(--faint);
}
.back:hover { color: var(--accent); }

.pagehead {
  margin: 0 0 0.4rem;
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--head);
}
.pagesub {
  margin: 0 0 4rem;
  font-size: 0.98rem;
}

section { margin-bottom: 3.6rem; }

h2 {
  margin: 0 0 1.4rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--faint);
}

.rows {
  list-style: none;
  margin: 0;
  padding: 0;
}
.rows > li {
  padding: 0.85rem 0;
  border-top: 1px solid var(--rule);
}
.rows > li:last-child { border-bottom: 1px solid var(--rule); }

/* Title on the left, year pushed to the right; they collapse onto separate
   lines on a narrow screen because the row is allowed to wrap. */
.line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.55rem;
}
.name {
  color: var(--head);
  font-weight: 600;
  font-size: 1.02rem;
}
a.name { color: var(--accent); }
a.name:hover { color: var(--accent-h); }
.when {
  margin-left: auto;
  padding-left: 1rem;
  font-size: 0.85rem;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.role {
  display: block;
  font-size: 0.95rem;
  margin-top: 0.1rem;
}
.role .tag {
  color: var(--faint);
}
/* Same right-hand slot as .when, but for a tech list, which is long enough that
   it has to be allowed to wrap and does not want tabular figures. */
.tech {
  margin-left: auto;
  padding-left: 1rem;
  font-size: 0.85rem;
  color: var(--faint);
  text-align: right;
}

/* Detail disclosure. The marker is removed and replaced with a "+" that turns
   into "−", because the default triangle is the only thing on the page with a
   platform look. */
details { margin-top: 0.45rem; }
summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  width: max-content;
  font-size: 0.85rem;
  color: var(--faint);
  cursor: pointer;
  list-style: none;
}
summary::-webkit-details-marker { display: none; }
summary::before {
  content: "+";
  font-size: 0.95em;
  line-height: 1;
}
details[open] > summary::before { content: "\2212"; }
summary:hover { color: var(--accent); }

.facts {
  margin: 0.7rem 0 0.4rem;
  padding: 0 0 0 0.9rem;
  border-left: 1px solid var(--rule);
  font-size: 0.93rem;
}
.facts dt {
  color: var(--faint);
  font-weight: 500;
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  margin-top: 0.75rem;
}
.facts dt:first-child { margin-top: 0; }
.facts dd { margin: 0.1rem 0 0; }
.facts a { color: var(--accent); }

/* Stack of short "label — values" lines: tools, and the fun lists. */
.stack {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: 0.75rem 1rem;
  font-size: 0.95rem;
}
.stack dt {
  color: var(--faint);
  font-size: 0.85rem;
}
.stack dd { margin: 0; }

.prose {
  margin: 0;
  font-size: 0.95rem;
}
.prose .sep { color: var(--rule); padding: 0 0.15rem; }

.foot {
  margin-top: 4.5rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--rule);
  font-size: 0.9rem;
  color: var(--faint);
}
.foot {
  display: flex;
  align-items: center;
  gap: 0.15rem;
}
/* The negative margin sits on the first icon, not on .foot, so the rule above
   the row stays flush with every other section rule on the page. */
.foot a:first-child { margin-left: -0.55rem; }
.foot a {
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 10px;
  color: var(--faint);
}
.foot a:hover { color: var(--head); background: var(--wash); }

@media (max-width: 34rem) {
  body.work { padding-top: 3.5rem; }
  .hi { font-size: 1.65rem; }
  .when, .tech { margin-left: 0; padding-left: 0; text-align: left; }
  .stack { grid-template-columns: 1fr; gap: 0.2rem 0; }
  .stack dd { margin-bottom: 0.75rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}


/* ------------------------------ screen readers ----------------------------- */

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}


/* ------------------------------ inline marks ------------------------------- */

/* One real logo set in the sentence at type size: the Georgia Tech monogram,
   which replaces the word outright because it is legible enough alone that
   spelling it out too would be redundant.

   Finaldose's mark is NOT here, and should not be added back at this size. It
   is a halftone: a field of dots at roughly an 11.6px pitch in a 256px image.
   Rendered 17px tall that pitch is 0.77px — finer than one device pixel — so
   the dots alias into an orange smudge. No asset fixes it, because nothing is
   wrong with the asset; the mark simply has a minimum size, and body copy is
   under it. It reads correctly at the 32px slot on the portfolio page, and
   that is about the floor. If a Finaldose logo is wanted here, it has to be
   the wordmark lockup, not the dot.

   Sized in em so it tracks the paragraph, and aligned by eye rather than by
   baseline: the optical centre of a logo is never where the font's baseline
   puts it. */
.logomark {
  display: inline-block;
  width: auto;
  vertical-align: -0.16em;
  /* A word is read as part of the line; a logo is read as an object dropped
     into it, and needs more air on both sides than a word space gives. The
     left margin in particular keeps the "@" from looking attached to the
     mark. */
  margin: 0 0.22em 0 0.16em;
}
/* The GT file is two stacked paths, navy behind gold; on white both show,
   which is the mark as Georgia Tech prints it. */
/* No right margin on this one: the monogram's own artwork already carries
   whitespace on its right edge, so the extra margin read as a double space
   before "and". The word space in the markup is enough. */
.logomark.gt {
  height: 1.05em;
  margin-right: 0;
}
/* A logo does not need an underline to look clickable, and one drawn under a
   glyph like this looks like a mistake. Hover lifts it instead. */
.blurb a.marklink {
  text-decoration: none;
}
.logomark { transition: filter 0.12s ease; }
.marklink:hover .logomark { filter: brightness(0.85); }

/* The Finaldose lockup. The bare mark cannot be used at this size (see above),
   but the wordmark can: the halftone circle still smudges at 19px, and next to
   legible type it reads as part of a logo instead of as an unexplained dot. */
.logomark.fd {
  height: 1.25em;
  vertical-align: -0.28em;
}
