/* ==========================================================================
   Layout — Home (+ dashboard) and Project pages.
   Breakpoints: ≥1101 desktop · 768–1100 tablet (desktop layout, tighter)
                ≤767 mobile (Figma mobile frames)
   ========================================================================== */

/* ==========================================================================
   HOME
   ========================================================================== */
.home {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  background: var(--color-home-fallback);   /* shows until the first image has loaded */
}
.home__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;   /* zoomed framings stay inside the frame */
}
/* one image per project, stacked; the active one fades in as the carousel changes */
.home__bg > * {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  /* per-project framing from content.js (bg / bgMobile) */
  object-position: var(--bg-pos, 50% 50%);
  transform: scale(var(--bg-zoom, 1));
  transform-origin: var(--bg-origin, 50% 50%);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-out);
}
.home__bg > .is-active { opacity: 1; }
@media (max-width: 767px) {
  .home__bg > * {
    object-position: var(--bg-pos-m, 50% 50%);
    transform: scale(var(--bg-zoom-m, 1));
    transform-origin: var(--bg-origin-m, 50% 50%);
  }
}

/* ---- Dashboard (closed ⇄ open) ------------------------------------------ */
.dashboard {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: flex-end;
  align-items: flex-end;
  padding: var(--space-edge);
  padding-top: var(--footer-height);   /* clears the floating footer text */
  pointer-events: none;             /* only the actual cards catch clicks */
  z-index: 5;                       /* above the blur overlay (4) and the footer text (3) */
}
.dashboard__scrim {
  position: absolute;
  inset: 0;
  z-index: 4;                       /* over the footer text (3), under the dashboard (5) */
  background: var(--color-surface-scrim);
  -webkit-backdrop-filter: blur(var(--blur-scrim));
  backdrop-filter: blur(var(--blur-scrim));
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-base) var(--ease-out), visibility 0s linear var(--dur-base);
}
.dashboard__inner {
  position: relative;
  display: flex;
  flex-direction: column-reverse;   /* DOM: bar → info (tab order); visual: info above bar */
  gap: var(--dash-gap);
  width: var(--dashboard-width);
  max-height: 100%;
  pointer-events: none;   /* closed: only the carousel bar takes clicks (see below) */
}
.dashboard__bar { flex: none; display: flex; gap: var(--dash-gap); align-items: center; justify-content: flex-end; pointer-events: auto; }

/* The reveal box is a clipping window sitting on top of the carousel bar;
   the info panel slides up out of it, so it never passes over the bar. */
.dashboard__reveal {
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  visibility: hidden;
  transition: visibility 0s linear var(--dur-reveal);
}
.dashboard__info {
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--dash-gap);
  padding-top: var(--space-edge);   /* keeps the scroll edge off the viewport top */
  opacity: 0;
  transform: translateY(1.6rem);
  transition:
    opacity var(--dur-fast) var(--ease-out),
    transform var(--dur-reveal) var(--ease-in-out);
}
.dashboard__row { display: flex; gap: var(--dash-gap); }

/* open */
.dashboard.is-open,
.dashboard.is-open .dashboard__inner { pointer-events: auto; }
.dashboard.is-open + .dashboard__scrim { opacity: 1; visibility: visible; transition: opacity var(--dur-base) var(--ease-out); }
.dashboard.is-open .dashboard__reveal { visibility: visible; transition: none; }
.dashboard.is-open .dashboard__info {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-reveal) var(--ease-out),
    transform var(--dur-reveal) var(--ease-out);
}

/* dashboard cards and the carousel use exactly the button text, at every size */
.dashboard__info,
.carousel {
  font-size: var(--type-button-size);
  line-height: var(--type-button-lh);
  letter-spacing: var(--type-button-ls);
}

/* ---- Dashboard cards (desktop) ------------------------------------------- */
.card--clients { flex: none; width: var(--clients-width); }
/* Disciplines + Awards to the right of Clients: Disciplines is as wide as its
   longest line, Awards takes the rest so each award stays on one line */
.dashboard__pair { flex: 1 1 0; min-width: 0; display: flex; gap: var(--dash-gap); }
.card--disciplines { flex: none; }
@media (min-width: 768px) {
  .card--awards { padding-right: 2.5rem; }   /* room for "Health & Wellness, Integrated" on one line */
}
.card--awards,
.card--contact,
.card--projects { flex: 1 1 0; }
.card--projects { gap: 1.3rem; }

/* Clients: a slow, endless "credits" roll inside a fixed-height card.
   The list is rendered twice and the track moves by exactly one copy (-50%),
   so the loop is seamless. The card height comes from Disciplines
   (size containment stops the list from stretching the row). */
.clients-marquee {
  flex: 1 1 0;
  min-height: 0;
  contain: size;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, rgb(0 0 0 / 0.35), #000 9%, #000 91%, rgb(0 0 0 / 0.35));
  mask-image: linear-gradient(to bottom, rgb(0 0 0 / 0.35), #000 9%, #000 91%, rgb(0 0 0 / 0.35));
}
.clients-track {
  display: flex;
  flex-direction: column;
  animation: credits-y var(--marquee-duration, 28s) linear infinite;
}
.clients-track > ul { padding-bottom: var(--list-gap); }
@keyframes credits-y { to { transform: translateY(-50%); } }
@keyframes credits-x { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .clients-marquee { overflow: auto; -webkit-mask-image: none; mask-image: none; }
  .clients-track { animation: none; }
  .clients-track > [aria-hidden="true"] { display: none; }
}

.contact { display: flex; flex-direction: column; gap: 2rem; padding-top: 0.6rem; flex: 1 1 auto; }
.contact__links { margin-top: auto; }   /* buttons sit on the card bottom padding, level with Selected projects */
.contact__time { display: flex; align-items: center; gap: 1.7rem; }

/* ---- Dashboard (mobile) --------------------------------------------------- */
@media (max-width: 767px) {
  /* same spacing as the project pages: 7px edges (--space-project).
     Top padding keeps the panel clear of the toggle (7px below the video top, 26px tall). */
  .dashboard { padding: var(--space-project); padding-top: calc(var(--space-project) + 26px + var(--space-project)); z-index: 5; }   /* above the blur overlay (4) and the floating footer text (3) */
  .dashboard__inner { width: 100%; gap: 0.25rem; }   /* tighter: last card to carousel */
  .dashboard__bar { gap: 0.25rem; align-items: stretch; }   /* carousel ↔ ⋮ button: same as the dashboard gaps */
  /* when the cards do not fit, they scroll inside a frame with rounded corners */
  .dashboard__reveal { border-radius: var(--radius-card); }
  .dashboard__info { gap: 0.25rem; padding-top: 0; border-radius: var(--radius-card); }   /* tighter gaps between dashboard sections */
  .dashboard__row { display: contents; }
  .dashboard__pair { flex: none; gap: 0.25rem; }   /* phones: still side by side, Awards on the right */
  .card--disciplines { flex: 1 1 0; }              /* phones: an equal pair */
  .card--clients { width: auto; }
  .card--projects { gap: 0.7rem; }
.clients-marquee {
  flex: none;
  contain: none;
  -webkit-mask-image: linear-gradient(to right, rgb(0 0 0 / 0.35), #000 5%, #000 95%, rgb(0 0 0 / 0.35));
  mask-image: linear-gradient(to right, rgb(0 0 0 / 0.35), #000 5%, #000 95%, rgb(0 0 0 / 0.35));
}
.clients-track { flex-direction: row; width: max-content; animation-name: credits-x; }
.clients-track > ul { flex-direction: row; gap: 1.2rem; padding: 0 1.2rem 0 0; white-space: nowrap; }
  .card--contact { gap: 0.4rem; }
  /* buttons share the card bottom padding. The gap before the clock is up to
     40px but shrinks on narrow phones; on the narrowest, the clock wraps onto
     its own line instead of being cut off. */
  .contact {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: flex-start;
    column-gap: clamp(1.2rem, 100vw - 37.4rem, 4rem);
    row-gap: 1.2rem;
    padding-top: 0;
  }
  .contact__links { margin-top: 0; }
  .contact__links { order: -1; flex-direction: row; }
  .contact__time { gap: 1.2rem; }
  .card--projects .btn-group { flex-direction: row; flex-wrap: wrap; gap: var(--dash-gap); }
}

/* ==========================================================================
   PROJECT
   ========================================================================== */
.project {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: calc(var(--sidebar-width) - var(--space-page)) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto;
  grid-template-areas:
    "info media"
    "nav  media";
  gap: var(--space-project);          /* one spacing value between every element on the page */
  padding: var(--space-project);
  position: relative;
}

/* ---- Sidebar: intro + details scroll together on desktop ----------------- */
.project-info { grid-area: info; min-height: 0; padding: 2rem 3.5rem 0.7rem 0.7rem; }   /* top: Figma spacing · right: room before the images */
@media (min-width: 768px) {
  /* desktop: the info column only scrolls when its text is actually cut off
     (app.js adds .is-overflowing); otherwise it's locked, so no nudge or bounce */
  .project-info.scroll-y { overflow-y: hidden; }
  .project-info.scroll-y.is-overflowing { overflow-y: auto; }
  .project-details.scroll-y { overflow: visible; }   /* scrolls as one with the intro */
  /* the project list works the same way */
  .project-list__panel.scroll-y { overflow-y: hidden; }
  .project-list__panel.scroll-y.is-overflowing { overflow-y: auto; }
}
.project-intro { display: flex; flex-direction: column; gap: 0.4rem; }
@media (min-width: 768px) {
  .project-intro h1 { margin-bottom: 1.2rem; }   /* desktop: more room under the project headline */
}
.project-intro__more { display: none; }

.project-details {
  display: flex;
  flex-direction: column;
  gap: var(--space-section);
  margin-top: 3.2rem;   /* body copy → Role: a touch more than the gaps between the info sections */
}
.project-details > div { display: flex; flex-direction: column; gap: 0.4rem; }
.project-details dt { color: var(--color-text-primary); }

.project-nav { grid-area: nav; }
.project-nav .btn-group { gap: var(--space-project); }
@media (min-width: 768px) { .project-nav .btn { padding-top: 0.75rem; padding-bottom: 0.75rem; } }   /* desktop: a bit taller than standard buttons */
@media (min-width: 1920px) { .project-nav .btn { padding-top: 0.55rem; padding-bottom: 0.55rem; } }   /* large, wide displays: shorter */

/* ---- Image panel ---------------------------------------------------------- */
.project-media {
  grid-area: media;
  min-height: 0;
  border-radius: var(--radius-media);
  /* hard-clip the panel (Safari can let composited images spill past a rounded
     scroll container), so the images end exactly level with the buttons */
  clip-path: inset(0 round var(--radius-media));
  isolation: isolate;
}

/* ---- Project list overlay ------------------------------------------------- */
.project-list {
  grid-area: info;
  z-index: 3;
  margin: calc(-1 * var(--space-project)) 0 0 calc(-1 * var(--space-project));
  overflow: hidden;                 /* clipping window: the panel rises from its bottom edge */
  visibility: hidden;
  transition: visibility 0s linear var(--dur-reveal);
}
.project-list__panel {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;   /* tiles sit at the bottom via margin-top:auto on the list, so a tall list overflows downward and stays scrollable */
  padding: var(--space-project) 0 0 var(--space-project);
  background: var(--color-surface);
  opacity: 0;
  transition: opacity var(--dur-list-bg) var(--ease-out) 80ms;   /* closing: tiles leave first */
}
.project-list ul {
  display: flex;
  margin-top: auto;
  flex-direction: column;
  gap: var(--space-project);
  opacity: 0;
  transform: translateY(1.6rem);
  transition:
    opacity var(--dur-fast) var(--ease-out),
    transform var(--dur-reveal) var(--ease-in-out);
}
.project-list.is-open { visibility: visible; transition: none; }
.project-list.is-open .project-list__panel { opacity: 1; transition: opacity var(--dur-list-bg) var(--ease-out); }
.project-list.is-open ul {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-reveal) var(--ease-out) 60ms,
    transform var(--dur-reveal) var(--ease-out) 60ms;
}

/* ---- Project (mobile) ----------------------------------------------------- */
@media (max-width: 767px) {
  .project {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "intro"
      "media"
      "nav";
    row-gap: var(--space-project);
    padding-bottom: 0.2rem;   /* buttons sit close to the bottom of the screen */
  }
  .project-info { display: contents; }
  .project-intro { grid-area: intro; gap: 0; padding: 1.2rem 2.4rem 0.7rem 0; }   /* top: a little room below the page edge · right: breathing room for the copy */
  .project-intro__desc { margin-top: 0.9rem; }   /* mobile: headline → body */
  .project-intro__more { display: inline-flex; align-self: flex-start; margin-top: 1.5rem; }   /* body → button */
  /* "Less info" stays the default button color (no selected state) */
  .project-intro__more[aria-expanded="true"] { background: var(--color-button); }
  @media (hover: hover) { .project-intro__more[aria-expanded="true"]:hover { background: var(--color-button-hover); } }

  /* "More info" overlays the image panel */
  .project-details {
    grid-area: media;
    z-index: 2;
    gap: 1.9rem;
    margin: 0 calc(-1 * var(--space-page));
    padding: 0.4rem calc(var(--space-page) + 2.4rem) var(--space-page) var(--space-page);   /* text starts right under the button */
    background: var(--color-surface);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--dur-fast) var(--ease-out), visibility 0s linear var(--dur-fast);
  }
  .project-details.is-open {
    opacity: 1;
    visibility: visible;
    transition: opacity var(--dur-fast) var(--ease-out);
  }

  .project-nav .btn-group { gap: var(--space-project); }

  .project-list {
    grid-area: 1 / 1 / 3 / 2;   /* covers intro + images, stops above the nav */
    z-index: 60;                /* sits in front of the dark-mode toggle (z-index 50) when tall */
    margin: calc(-1 * var(--space-page)) calc(-1 * var(--space-page)) 0;
  }
  .project-list__panel { padding: var(--space-project) var(--space-project) 0; }
  .project-list ul { gap: var(--space-project); }

  /* smooth, quick background fade: a plain white layer fades on its own (cheap
     for phones to animate) instead of fading the whole scrolling panel */
  .project-list { position: relative; }
  .project-list::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--color-surface);
    opacity: 0;
    will-change: opacity;
    transition: opacity 220ms ease-out 40ms;   /* closing: tiles start leaving first */
  }
  .project-list.is-open::before { opacity: 1; transition: opacity 220ms ease-out; }
  .project-list__panel,
  .project-list.is-open .project-list__panel {
    position: relative;             /* above the white layer */
    background: transparent;
    opacity: 1;
    transition: none;
  }
}

/* ==========================================================================
   ERROR PAGES (404 / 403 / 500)
   ========================================================================== */
.error {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.8rem;
  padding: var(--space-edge);
  text-align: center;
}
.error__code {
  font-size: var(--type-headline-size);
  line-height: var(--type-headline-lh);
  letter-spacing: var(--type-headline-ls);
  color: var(--color-text-primary);
}
.error__title { color: var(--color-text-primary); }
.error__text { max-width: 36rem; }
.error__home { margin-top: 1.6rem; }


/* Chrome on phones only: extra room under the project-page buttons
   (html.is-chrome is set by app.js; Safari keeps the 2px default). */
@media (max-width: 767px) {
  .is-chrome .project { padding-bottom: 0.8rem; }
}

/* ---- Home on phones: edge-to-edge video (same technique as bd85bd85.com) ------
   Only <body> blocks scrolling (html stays "visible"), so Safari locks the page
   but still draws what runs past the screen, including behind its address bar and
   toolbar. The video is made taller than the screen to reach both edges; the
   carousel, dashboard and footer keep their normal positions. */
@media (max-width: 767px) {
  html:has(body[data-page="home"]) { overflow: visible; overscroll-behavior: auto; overscroll-behavior-x: contain; }
  body[data-page="home"] { overflow: hidden; overscroll-behavior: auto; }   /* same as the reference: Safari then lets the page run under its bars */
  .page--home,
  .page--home .home { overflow: visible; }
  /* no fade-in on the first frame: Safari decides on the first paint whether the page runs under its bars */
  .page--home { animation: none; }
  /* The page now runs up under Safari's bars (see .home__bg below), so anything placed
     from the top of the page would sit under them. Pinned (fixed) elements are measured
     from the visible area instead — below the address bar, above the toolbar — which is
     how the reference site keeps its menu in view. So the footer text and the whole
     dashboard (carousel, ⋮, info cards) are pinned; only the background runs edge to edge. */
  .page--home .site-footer { position: fixed; top: env(safe-area-inset-top, 0px); }
  .page--home .dashboard { position: fixed; inset: 0; }
  /* the open-dashboard blur is page content sized exactly like the background, so it
     also runs under Safari's bars and covers the whole image */
  .page--home .dashboard__scrim {
    position: absolute;
    inset: auto;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    height: 100lvh;
  }
  @supports (hanging-punctuation: first) and (font: -apple-system-body) and (-webkit-appearance: none) {
    .page--home .dashboard__scrim { height: calc(100svh + 220px); }
  }
/* subtle dark fades at both ends of the video. One layer exactly the size of the
   video, so the bottom fade ends where the video ends (the very bottom of the
   screen, behind the browser toolbar) and the top fade starts at its top edge. */
.page--home .home::after {
  content: "";
  position: absolute;   /* on top of the background, same size, from the top of the page */
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  height: 100lvh;
  pointer-events: none;
  z-index: 1;
  background: linear-gradient(to bottom,
    rgb(0 0 0 / 0.22) 0%, rgb(0 0 0 / 0) 16%,
    rgb(0 0 0 / 0) 84%, rgb(0 0 0 / 0.22) 100%);
}
@supports (hanging-punctuation: first) and (font: -apple-system-body) and (-webkit-appearance: none) {
  .page--home .home::after { height: calc(100svh + 220px); }
}
  /* The background is ordinary page content at the very top of the page (NOT fixed or
     absolute), made taller than the screen — exactly how bd85bd85.com builds its slider.
     Because the page itself is then taller than the screen, iOS Safari runs the page up
     under its top bar (and its bottom toolbar) instead of starting it below the bar. */
  .page--home .home__bg {
    position: relative;
    inset: auto;
    display: block;
    width: 100vw;
    height: 100vh;
    height: 100lvh;
  }
  /* Safari only (same feature check as the reference site) */
  @supports (hanging-punctuation: first) and (font: -apple-system-body) and (-webkit-appearance: none) {
    .page--home .home__bg { height: calc(100svh + 220px); }
  }
}

/* large, wide displays: Disciplines a little wider than its content; Awards takes the rest */
@media (min-width: 1920px) {
  .card--disciplines { flex: none; width: 21rem; }
}
