/* ==========================================================================
   Page layout

   The layout language introduced on /about and now shared by /work and the
   home page: a large mixed-case label paired with a block of copy, then flat
   multi-column lists — no cards, no per-item descriptions, bracket-style
   links. Modeled on
   untitledfilm.framer.website/about.

   Headings, copy and lists are Geist; Geist Mono is reserved for the labels
   above each block, the roles under each entry, and other short metadata. The
   rule across the whole site is the same one: sentences in sans, tags on
   sentences in mono.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Container

   Repeats .case-header's edge math (see nav.css), which in turn repeats
   .container's, breakpoint for breakpoint — pages using this layout have no
   .case-header, but still have to land on the same left edge as the rest of
   the site.

   The home page is the one page that sets its own measure — its work grid
   carries side room as padding inside a 1320px box — so the modifier mirrors
   that box exactly rather than approximating it, and the hero, grid and info
   columns share one left edge at every viewport width.
   -------------------------------------------------------------------------- */

.page-container {
  width: 100%;
  max-width: 1200px;
  margin: 0 20px;
}

@media screen and (max-width: 991px) {
  .page-container {
    margin-left: 10px;
    margin-right: 10px;
    padding-left: 32px;
    padding-right: 32px;
  }
}

@media screen and (max-width: 479px) {
  .page-container {
    margin-left: 0;
    margin-right: 0;
    padding-left: 16px;
    padding-right: 16px;
  }
}

/* Home — matches .work-grid-section, which carries its side room as padding
   rather than as margins. Same 1240px box as the nav, so the measure is the
   site's one measure. */
.page-container--home {
  max-width: 1240px;
  margin: 0;
  padding: 0 20px;
}

@media screen and (max-width: 991px) {
  .page-container--home {
    padding: 0 32px;
  }
}

@media screen and (max-width: 479px) {
  .page-container--home {
    padding: 0 16px;
  }
}

/* --------------------------------------------------------------------------
   Hero — label + opening statement, reusing .grid2column's 1fr/1fr split
   (already collapses to a single column at 767px).
   -------------------------------------------------------------------------- */

.page-hero {
  margin-top: 104px;
}

@media screen and (max-width: 767px) {
  .page-hero {
    margin-top: 80px;
  }
}

/* The hero on /about clears the nav by 104px plus the 120px .grid2column
   carries of its own. The home page's hero has no grid inside it — it is a
   bare block of copy — so it makes up that distance itself and the two pages
   open on the same line. */

.page-hero.page-container--home {
  margin-top: 224px;
}

@media screen and (max-width: 767px) {
  .page-hero.page-container--home {
    margin-top: 200px;
  }
}

.page-hero__label {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 34px;
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -.01em;
}

/* The opening paragraphs on /, /about and /contact. These used to be 13px
   uppercase mono, which is the one place the mono was doing real damage:
   several sentences of prose with no word shapes to read by. In sans at 16px
   the block occupies about the same space it did — uppercase mono is optically
   much larger than its point size — but it is now readable at length, and it
   matches .modernbody_16, the body size the case studies already use. */

.page-hero__copy {
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
}

.page-hero__photo {
  display: block;
  width: 120px;
  height: auto;
  margin: 0 0 24px;
  border-radius: 8px;
}

.page-hero__copy p,
.page-hero__copy h1 {
  margin: 0 0 20px;
  max-width: 620px;
  font: inherit;
}

/* The home page has no label above its copy, so the opening statement is the
   h1 there and nothing else on the page outranks it. font: inherit above
   flattens it to body copy, which left the site's largest claim set at its
   smallest size.

   At this size the optical settings are the point, not the size: tight
   tracking and leading are most of what separates display type from body copy
   that merely got bigger, and text-wrap: balance stops the last line dropping
   a single orphaned word.

   The colour split is the site's own device — .work-card__highlight in the
   grid directly below runs the same muted-remainder-with-one-clause-at-full-
   strength idiom, and .index-row-name does it on /work. Here the setup goes
   quiet so the payoff lands. */

.page-hero__copy h1 {
  max-width: 800px;
  font-size: clamp(28px, 4.4vw, 40px);
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: -.03em;
  text-wrap: balance;
  color: var(--text-muted);
}

.page-hero__accent {
  color: var(--text);
}

.page-hero__copy > :last-child {
  margin-bottom: 0;
  color: var(--text-muted);
}

/* Stacked, the copy needs the gap the grid column gave it. */
@media screen and (max-width: 767px) {
  .page-hero__copy {
    margin-top: 28px;
  }
}

/* --------------------------------------------------------------------------
   Column grid — a small label over a flat, undecorated list of lines.
   -------------------------------------------------------------------------- */

.page-columns {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: 32px;
  row-gap: 48px;
  margin-top: 160px;
}

/* The home page's fourth column holds the now-playing embed, which needs
   noticeably more room than a text column — an equal quarter squeezes it. */
.page-columns--home {
  grid-template-columns: 1fr 1fr 1fr 1.6fr;
}

/* Four columns is too tight below ~992px: the entries wrap to three lines and
   the now-playing embed, which has a minimum width of its own, spills past
   its column. */
@media screen and (max-width: 991px) {
  .page-columns {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media screen and (max-width: 767px) {
  .page-columns {
    grid-template-columns: 1fr;
    row-gap: 40px;
    margin-top: 100px;
  }
}

/* The label voice, and now the main thing mono is for. */

.page-col__label {
  margin: 0 0 20px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.page-col__list {
  display: flex;
  flex-direction: column;
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.9;
}

.page-col__list a {
  text-decoration: none;
  transition: color .2s ease;
}

.page-col__list a:hover {
  color: var(--text-muted);
}

.page-col__sublabel {
  margin: 20px 0 4px;
  color: var(--text-muted);
}

.page-col__status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.page-col__status-dot {
  position: relative;
  flex: none;
  width: 6px;
  height: 6px;
}

.page-col__status-dot::before,
.page-col__status-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #4ade80;
}

.page-col__status-dot::before {
  animation: nav-status-ping 3s cubic-bezier(.16, 1, .3, 1) infinite;
}

/* --------------------------------------------------------------------------
   Entries — a two-line variant of .page-col__list for Experience and
   Education: the name carries the line in medium weight, with the date beside
   it and the role under it in the same muted mono the labels use. Logos are
   optional and only used where the entry has a recognizable mark to show
   (Education).

   The logo sits on a small tilted card, so it reads as a physical thing
   resting on the page rather than an avatar. Consecutive badges lean opposite
   ways, which is what gives a run of them the loose, hand-stacked look.

   The card takes the theme's own ground -- white on light, near-black on dark
   -- so it never punches a bright hole in the page. That means the depth cue
   swaps too: on light, layered black shadows; on dark, where a cast shadow is
   invisible against the page, a hairline rim and a top highlight do the
   lifting, and hover brightens the rim rather than deepening a shadow.

   Only the transform animates on the card itself. The lift shadow lives on a
   pseudo-element that fades in, so the hover is an opacity and transform
   change the compositor can carry rather than a per-frame shadow repaint.
   -------------------------------------------------------------------------- */

.page-col__list--entries {
  gap: 20px;
  line-height: 1.5;
}

.page-col__entry {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.page-col__badge {
  /* Dark is the default theme: the card sits just above the page rather than
     on top of it, so the rim and the top highlight carry the edge and the
     cast shadow only pools right under the card. */
  --badge-surface: #161616;
  --badge-rest: 0 0 0 1px #ffffff1f, inset 0 1px 0 #ffffff14, 0 6px 14px -8px #000;
  --badge-lift: 0 0 0 1px #ffffff47, 0 14px 26px -12px #000;

  position: relative;
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  margin-top: 1px;
  border-radius: 11px;
  background: var(--badge-surface);
  box-shadow: var(--badge-rest);
  transform: rotate(-5deg);
  transform-origin: 50% 60%;
  transition: transform .55s cubic-bezier(.16, 1, .3, 1);
  will-change: transform;
}

html[data-theme="light"] .page-col__badge {
  --badge-surface: #fff;
  --badge-rest: 0 0 0 1px #0000000f, 0 1px 2px #00000014, 0 8px 16px -8px #00000038;
  --badge-lift: 0 0 0 1px #00000014, 0 3px 6px #0000001f, 0 18px 30px -12px #00000059;
}

/* The lean alternates down the column so a run of badges reads as a stack
   rather than a repeated stamp. */
.page-col__entry:nth-child(even) .page-col__badge {
  transform: rotate(4deg);
}

/* The deeper shadow rides on its own layer and cross-fades, which keeps the
   straightening rotation on the compositor instead of repainting a shadow on
   every frame. */
.page-col__badge::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: var(--badge-lift);
  opacity: 0;
  pointer-events: none;
  transition: opacity .55s cubic-bezier(.16, 1, .3, 1);
}

.page-col__badge:hover,
.page-col__badge:focus-visible,
.page-col__entry:nth-child(even) .page-col__badge:hover,
.page-col__entry:nth-child(even) .page-col__badge:focus-visible {
  transform: rotate(0) translateY(-3px);
}

.page-col__badge:hover::after,
.page-col__badge:focus-visible::after {
  opacity: 1;
}

.page-col__badge img {
  width: 24px;
  height: 24px;
  border-radius: 50%;
}

@media (prefers-reduced-motion: reduce) {
  .page-col__badge,
  .page-col__badge::after {
    transition-duration: .01ms;
  }

  /* The lean is the design, not the motion, so the card keeps it on hover.
     Only the straightening goes; the shadow still deepens. */
  .page-col__badge:hover,
  .page-col__badge:focus-visible {
    transform: rotate(-5deg);
  }

  .page-col__entry:nth-child(even) .page-col__badge:hover,
  .page-col__entry:nth-child(even) .page-col__badge:focus-visible {
    transform: rotate(4deg);
  }
}

.page-col__entry-name {
  font-weight: 500;
  letter-spacing: -.01em;
}

/* Date and role are the metadata on an entry, so they keep the mono the list
   itself has given up — which is also what separates them from the name now
   that the name is no longer a different family. */

.page-col__entry-date,
.page-col__entry-role {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.page-col__entry-date {
  white-space: nowrap;
}

.page-col__entry-role {
  margin-top: 2px;
  line-height: 1.5;
}

/* The now-playing widget is a third-party iframe, so it only gets a box to
   sit in that lines the column up with its neighbours. */

.page-col__embed {
  width: 100%;
  margin-top: -8px;
}
