/* ==================================================================
   MIKE TISCARENO — PORTFOLIO v2
   Sidebar bio + colour thumbnail gallery. Selecting a project turns
   the gallery into a persistent greyscale toggle in the sidebar.
   ================================================================== */

/* Type: DM Sans (display) + DM Mono (labels) + Literata (body serif).
   (Fieldstone was dropped — its bundled license is Fort Foundry
   Desktop only and forbids web embedding.) */

:root {
  --bg:      #ffffff;
  --ink:     #17264a;   /* navy — primary text */
  --muted:   #667085;   /* muted blue-grey — labels */
  --navy:    #17264a;   /* the left tab */
  --card-border: #bac7d8;   /* grid thumbnail border */
  --gold:    #e3ab3c;   /* active toggle */
  --hair:    rgba(23, 38, 74, 0.22);

  --font-display: "DM Sans", "Helvetica Neue", Arial, system-ui, sans-serif;
  --font-serif:   "Literata", Georgia, "Times New Roman", serif;
  --font-mono:    "DM Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  --side-w:   244px;                    /* text column */
  --col-gap:  clamp(36px, 5vw, 64px);   /* gap between column and gallery */
  --bar-h:    56px;                     /* project / résumé fixed top bar */
  --bar-pad-l: clamp(38px, 5vw, 66px);  /* left inset of the top bar's wordmark */
  --app-max:  1052px;                   /* 244 + 64 + 744 — group stops growing here */
  --edge:     clamp(24px, 9vw, 120px);  /* left / right window margin */
  --stage-max: 880px;
  --pad-x:    clamp(24px, 2.4vw, 38px);
}

*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  min-height: 100dvh;
  padding-inline: var(--edge);   /* window margin; the fixed navy tab ignores this */
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-serif);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; display: block; }
a { color: inherit; }
::selection { background: var(--navy); color: #fff; }

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

.skip {
  position: fixed; left: 12px; top: -48px; z-index: 100;
  background: var(--navy); color: #fff; padding: 8px 14px;
  font-family: var(--font-mono); font-size: 12px; text-decoration: none;
  transition: top .18s;
}
.skip:focus { top: 12px; }

/* ----------------------------------------------------------------
   The [ text column | gallery ] pair is one group, centred in the
   window. As the window grows past --app-max the extra space becomes
   left / right margin; as it shrinks the gallery scales down.
   ---------------------------------------------------------------- */
#app {
  display: flex;
  align-items: flex-start;
  gap: var(--col-gap);
  max-width: var(--app-max);
  margin: 0 auto;
  min-height: 100dvh;
}

.side {
  position: sticky;
  top: 0;
  align-self: flex-start;
  flex: 0 0 var(--side-w);
  min-height: 100vh;
  max-height: 100vh;
  padding: clamp(64px, 9vh, 120px) 0 40px;   /* ~40px bottom margin for the links */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* home: float the links to the bottom of the panel */
body[data-view="home"] .side-nav { margin-top: auto; }
.side > * { width: 100%; }

/* navy tab — pinned to the WINDOW's left edge, independent of the
   centred group. project / résumé: a short bar near the top. */
body::before {
  content: "";
  position: fixed;
  left: 0; top: 0;
  width: 9px; height: clamp(120px, 16vh, 188px);
  background: var(--navy);
  z-index: 10;
}
/* home: drop the tab down to sit beside the identity block */
body[data-view="home"]::before {
  top: clamp(64px, 9vh, 120px);
  height: clamp(150px, 20vh, 230px);
}

.ident { position: relative; }
.ident::before { display: none; }   /* desktop: the tab is body::before */

.stage {
  flex: 1 1 auto;
  min-width: 0;
  padding: clamp(64px, 9vh, 120px) 0 128px;
}

/* ----------------------------------------------------------------
   Project / résumé: a full-width bar locked to the top of the window
   (name left, close right); everything else scrolls behind it.
   Same model at every screen size.
   ---------------------------------------------------------------- */
body[data-view="project"]::before { top: 0; height: var(--bar-h); z-index: 41; }

body[data-view="project"] .side,
body[data-view="resume"] .side {
  position: static;
  min-height: 0;
  max-height: none;
  overflow: visible;
  padding-top: calc(var(--bar-h) + 28px);
}
body[data-view="project"] .stage,
body[data-view="resume"] .stage { padding-top: calc(var(--bar-h) + 28px); }

/* project: a little more air above the scrolling content */
body[data-view="project"] .side,
body[data-view="project"] .stage { padding-top: calc(var(--bar-h) + 43px); }

/* résumé: no navy tab, no side rail — a left-aligned document whose
   left edge lines up with the wordmark in the top bar */
body[data-view="resume"]::before { display: none; }
body[data-view="resume"] { padding-inline: 0; }
body[data-view="resume"] #app { gap: 0; max-width: none; }
body[data-view="resume"] .side {
  flex: 0 0 0;
  width: 0;
  padding: 0;
  overflow: visible;
}
body[data-view="resume"] .stage {
  padding-left: var(--bar-pad-l);
  padding-right: clamp(24px, 4vw, 64px);
}
body[data-view="resume"] .cv { margin: 0; }

/* the top-bar name is hidden until the content title scrolls under the bar */
body[data-view="resume"] .p-topbar .wordmark {
  opacity: 0;
  transform: translateY(7px);
  transition: opacity .3s ease, transform .3s cubic-bezier(.2, .7, .2, 1);
  pointer-events: none;
}
body[data-view="resume"] .p-topbar.show-title .wordmark {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
@media (prefers-reduced-motion: reduce) {
  body[data-view="resume"] .p-topbar .wordmark { transform: none; transition: opacity .12s ease; }
}

/* --- identity --------------------------------------------------- */
.wordmark {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 18px;
  letter-spacing: .005em;
  text-transform: lowercase;
  text-decoration: none;
  color: var(--ink);
}
.wordmark:hover { color: var(--navy); }

.title-lg {
  margin: 1px 0 14px;
  font-family: var(--font-display);
  font-weight: 400;
  font-style: italic;
  font-size: clamp(2rem, 2.6vw, 2.6rem);
  line-height: 1.0;
  letter-spacing: -.01em;
  color: var(--navy);
}

.based {
  margin: 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #5e6e81;
}

.bio {
  margin: clamp(44px, 8vh, 92px) 0 0;   /* intentional thick gap above the bio */
  font-size: 15px;
  line-height: 1.62;
  max-width: 33ch;
}

.side-nav {
  display: flex;
  flex-direction: column;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: 13px;
}
.side-nav a { text-decoration: none; width: max-content; }
.side-nav a:hover { text-decoration: underline; text-underline-offset: 3px; }

.rule { width: 46px; height: 1px; background: var(--navy); opacity: .55; margin-top: 2px; }

/* --- home grid — fixed 4-row pattern, centred in the stage -------
   row 1  554×303  +  166×303
   row 2  360×198  ×2
   row 3  166×303  +  554×303   (mirror of row 1)
   row 4  360×198  ×2
   …then the 1–4 pattern repeats.                                   */
.grid {
  --g: 24px;
  max-width: 744px;              /* 554 + 24 + 166 */
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--g);
}
.grow { display: flex; gap: var(--g); }
.grow > * { min-width: 0; height: 100%; }

/* each row carries the aspect ratio; the tiles just fill it, so the
   554 : 166 / 360 : 360 splits stay exact at any width */
.grow--1, .grow--3 { aspect-ratio: 744 / 303; }
.grow--2, .grow--4 { aspect-ratio: 744 / 198; }

.grow--1 > :first-child,
.grow--3 > :last-child   { flex: 554 1 0; }
.grow--1 > :last-child,
.grow--3 > :first-child  { flex: 166 1 0; }
.grow--2 > *,
.grow--4 > *             { flex: 360 1 0; }
.grow > :only-child      { flex: 1 1 100%; }

.card {
  position: relative;
  display: block;
  overflow: hidden;
  background: #fff;
  text-decoration: none;
  transition: transform .16s cubic-bezier(.33, 1, .68, 1);
}
.card:active { transform: scale(.975); }   /* press feedback before the morph */
@media (prefers-reduced-motion: reduce) { .card:active { transform: none; } }
.card img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .55s cubic-bezier(.2, .7, .2, 1);
}
/* the 4px frame — a top layer, so it never affects the flex sizing */
.card::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid var(--card-border);
  pointer-events: none;
  z-index: 2;
}
.card:hover img, .card:focus-visible img { transform: scale(1.035); }
.card__cap {
  position: absolute;
  z-index: 1;
  left: 0; right: 0; bottom: 0;
  padding: 20px 12px 9px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #fff;
  background: linear-gradient(to top, rgba(23, 38, 74, .82), rgba(23, 38, 74, 0));
  opacity: 0;
  transition: opacity .25s ease;
}
.card:hover .card__cap, .card:focus-visible .card__cap { opacity: 1; }

/* --- project / résumé: top bar + sidebar toggle -------------- */
.p-topbar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 40;
  height: var(--bar-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 clamp(18px, 3vw, 40px) 0 var(--bar-pad-l);
  background: var(--bg);
  border-bottom: 1px solid var(--card-border);
}

.toggle {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 7px;
  width: 100%;
}
.thumb {
  padding: 0;
  border: 1px solid var(--card-border);
  background: #fff;
  cursor: pointer;
  aspect-ratio: 93 / 50;
  overflow: hidden;
  opacity: .62;
  transition: opacity .2s ease, box-shadow .2s ease;
}
.thumb img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.12) brightness(.94);
}
.thumb:hover { opacity: .9; }
.thumb.is-active {
  opacity: 1;
  border-color: var(--gold);
  box-shadow: 0 0 0 2px var(--gold);
}

.p-title {
  margin: 8px 0 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.5rem, 2vw, 1.95rem);
  line-height: 1.08;
  letter-spacing: -.03em;
}
.p-kicker {
  margin: 8px 0 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.p-year {
  margin: 3px 0 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}

.more-btn {
  display: none;
  margin: 14px 0 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink);
}
.more-btn:hover { text-decoration: underline; text-underline-offset: 3px; }

.p-body { margin-top: 14px; font-size: 14.5px; line-height: 1.62; }
.p-body p { margin: 0 0 12px; }
.p-body p:last-child { margin-bottom: 0; }

.p-links { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.p-links a {
  font-family: var(--font-mono);
  font-size: 12px;
  text-decoration: none;
  width: max-content;
}
.p-links a:hover { text-decoration: underline; text-underline-offset: 3px; }

.p-credit {
  margin: 10px 0 0;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 12.5px;
  color: var(--muted);
}

/* --- project: stage (image scroll) -------------------------- */
.close {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
  transition: opacity .2s ease;
}
.close svg {
  width: 27px; height: 27px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
}
.close:hover { opacity: .5; }

.shots {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 2vw, 28px);
  max-width: var(--stage-max);
}
.shots img { width: 100%; border: 1px solid var(--card-border); background: #fff; }
.shot-video {
  aspect-ratio: 16 / 9;
  border: 1px solid var(--card-border);
  background: #000;
}
.shot-video iframe { width: 100%; height: 100%; border: 0; display: block; }
.shot-video--narrow { aspect-ratio: 9 / 16; max-width: 340px; margin-inline: auto; }
.shot-note {
  margin: 2px 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink);
}

/* --- résumé page ------------------------------------------------ */
.cv { max-width: 660px; }
.cv .p-title {
  font-size: clamp(1.7rem, 2.4vw, 2.2rem);
  font-weight: 500;
  text-transform: lowercase;   /* the name, lowercase DM Sans */
}
.cv-summary { margin: 14px 0 0; font-size: 15.5px; line-height: 1.62; }
.cv-links { margin: 12px 0 0; font-family: var(--font-mono); font-size: 12px; display: flex; gap: 16px; flex-wrap: wrap; }
.cv-links a { text-decoration: none; }
.cv-links a:hover { text-decoration: underline; text-underline-offset: 3px; }
.cv-h {
  margin: 34px 0 14px;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  border-top: 1px solid var(--hair);
  padding-top: 14px;
}
.cv-job { margin-bottom: 20px; }
.cv-job h3 { margin: 0; font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; }
.cv-org {
  margin: 2px 0 8px;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.cv-note { margin: 0; font-size: 15px; line-height: 1.58; }
.cv-list { margin: 0; padding-left: 18px; font-size: 14px; line-height: 1.6; }
.cv-list li { margin-bottom: 6px; }
.cv-list strong { font-family: var(--font-display); font-weight: 600; }

/* --- route transition: content fades + slides up into place ---
   (the fixed top bar and the toggle you clicked stay put) */
.side > *, .stage {
  transition: opacity .24s ease, transform .28s cubic-bezier(.33, 1, .68, 1);
}
body.is-swapping .side > *:not(.p-topbar):not(.toggle),
body.is-swapping .stage { opacity: 0; transform: translateY(10px); }

/* --- shared-element "hero" morph (View Transitions API) ------
   Supported browsers morph the clicked thumbnail into the project's
   first image, then cascade the rest of the content in. Others fall
   back to the fade/slide above.                                     */
::view-transition-group(hero-img) {
  animation-duration: .44s;
  animation-timing-function: cubic-bezier(.33, 1, .68, 1);
}
::view-transition-old(hero-img),
::view-transition-new(hero-img) {
  animation-duration: .44s;
  animation-timing-function: cubic-bezier(.33, 1, .68, 1);
  height: 100%;
  object-fit: cover;
}
/* while the hero morphs, don't crossfade the whole page — the cascade does it */
html.vt-hero::view-transition-old(root) { animation-duration: .26s; }
html.vt-hero::view-transition-new(root) { animation: none; }

html.vt-hero .vt-cascade {
  animation: vt-stagger .38s cubic-bezier(.33, 1, .68, 1) both;
  animation-delay: calc(.26s + var(--si, 0) * 40ms);
}
@keyframes vt-stagger {
  from { opacity: 0; transform: translateY(10px); }
}
@media (prefers-reduced-motion: reduce) {
  html.vt-hero .vt-cascade { animation: none; }
}

/* --- résumé "root push" (View Transitions API) --------------
   Entering the résumé, the portfolio recedes (fade + slight scale)
   while the document rises up from below through the fixed bar.
   Leaving, the document sinks back down and the portfolio fades in.
   The top bar is lifted into its own layer so it stays anchored. */
html.vt-resume::view-transition-old(root) {
  animation: vt-recede .30s cubic-bezier(.33, 1, .68, 1) both;
}
html.vt-resume::view-transition-new(root) {
  animation: vt-rise .34s cubic-bezier(.33, 1, .68, 1) both;
}
html.vt-resume.vt-back::view-transition-old(root) {
  animation: vt-sink .26s cubic-bezier(.55, 0, .68, .3) both;
}
html.vt-resume.vt-back::view-transition-new(root) {
  animation: vt-fadein .28s ease both;
}
html.vt-resume::view-transition-group(vt-bar) { animation-duration: .28s; }
html.vt-resume::view-transition-old(vt-bar),
html.vt-resume::view-transition-new(vt-bar) { animation-duration: .2s; }

@keyframes vt-recede { to   { opacity: 0; transform: scale(.985); } }
@keyframes vt-rise   { from { opacity: 0; transform: translateY(26px); } }
@keyframes vt-sink   { to   { opacity: 0; transform: translateY(26px); } }
@keyframes vt-fadein { from { opacity: 0; } }

/* ==================================================================
   MOBILE
   ================================================================== */
@media (max-width: 820px) {
  :root { --bar-h: 46px; }
  body { padding-inline: 0; }
  #app { display: block; max-width: none; }

  .side {
    --pad-x: 30px;
    position: static;
    flex: none;
    min-height: 0;
    max-height: none;
    overflow: visible;
    padding: 30px var(--pad-x) 22px;
    gap: 16px;
    border-bottom: 1px solid var(--hair);
  }
  body[data-view="home"] .side-nav { margin-top: 20px; }

  /* mobile home: the tab hugs the identity block instead of the window edge */
  body[data-view="home"]::before { display: none; }
  .ident::before {
    content: "";
    display: block;
    position: absolute;
    left: calc(-1 * var(--pad-x));
    top: -4px; bottom: -4px;
    width: 9px;
    background: var(--navy);
  }

  body[data-view="home"] .side { padding-top: clamp(28px, 6vh, 52px); }
  body[data-view="home"] .bio { margin-top: clamp(16px, 3vh, 28px); }

  /* roomier tap targets for the sidebar links — read as stacked cells */
  .side-nav { gap: 0; }
  .side-nav a {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 50px;
    border-top: 1px solid var(--card-border);
  }
  .side-nav a:last-child { border-bottom: 1px solid var(--card-border); }
  .title-lg { font-size: clamp(2.5rem, 9vw, 3.3rem); }
  .wordmark { font-size: 17px; }

  .stage { padding: 22px 30px 96px; }

  .bio { max-width: none; font-size: 17px; }

  /* +1pt on mobile — Literata body copy */
  .p-body { font-size: 15.5px; }
  .cv-note { font-size: 16px; }
  .cv-summary { font-size: 16.5px; }
  .cv-list { font-size: 15px; }
  /* +1pt on mobile — DM Mono caps labels (all one size) */
  .p-kicker, .p-year, .cv-org, .cv-h, .shot-note, .based, .card__cap, .more-btn { font-size: 13px; }

  .card__cap { opacity: 1; }

  /* ---- project / résumé: top bar (base) + a 2nd fixed thumbnail strip ---- */
  .p-topbar { padding: 0 12px 0 26px; }

  .toggle {                       /* only rendered on project / résumé */
    position: fixed;
    inset: var(--bar-h) 0 auto 0;
    z-index: 39;
    display: flex;
    grid-template-columns: none;
    gap: 8px;
    padding: 15px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    background: var(--bg);
    border-bottom: 1px solid var(--card-border);
  }
  .thumb { flex: 0 0 93px; }

  body[data-view="resume"] .side { padding-top: 140px; border-bottom: 0; }
  body[data-view="project"] .side { padding-top: 155px; border-bottom: 0; }

  body[data-view="project"] .close,
  body[data-view="resume"] .close { width: 40px; height: 40px; }

  body[data-view="project"] .stage,
  body[data-view="resume"] .stage { padding-top: 10px; }

  /* project: collapsible description */
  .more-btn { display: inline-block; }
  .p-body {
    max-height: 0;
    margin-top: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-height .35s ease, opacity .3s ease, margin-top .3s ease;
  }
  .p-body.is-open { max-height: 2400px; opacity: 1; margin-top: 14px; }
}

/* near mobile: drop the 4-row pattern — one column of landscape cards */
@media (max-width: 600px) {
  .grid { max-width: none; }
  .grow--1, .grow--2, .grow--3, .grow--4 {
    flex-direction: column;
    aspect-ratio: auto;
  }
  .grow--1 > :first-child, .grow--1 > :last-child,
  .grow--3 > :first-child, .grow--3 > :last-child,
  .grow--2 > *, .grow--4 > * {
    flex: 0 0 auto;
    height: auto;
    aspect-ratio: 16 / 10;
  }
}

/* ==================================================================
   REDUCED MOTION
   ================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: .001ms !important;
    animation-duration: .001ms !important;
  }
}
