/*
  FILE: project.css
  PURPOSE: Shared styles for every project page under
  /projects/*. Same idea as work.css/about.css, but
  reused across many pages instead of just one: each project page links
  this file and pastes in its own copy of the section markup (this site
  has no build step/includes, see /src/components/README.md), so a
  class defined once here styles every project page that uses it.
  Colours/fonts/sizes come from tokens.css, nav styling comes from
  float-nav.css, footer styling comes from footer.css (none of those
  duplicated here).

  The "project-layout--v2"/"project-header--v2" modifier classes every
  project page's markup carries are a leftover from when this file also
  served a sidebar-nav ("v1") version of the site (nav.css/nav.html/
  nav.js) alongside this floating-nav one -- v1 has since been split
  off into its own repo (LuCamiMa/websitev1), so every page using this
  file is "v2" now, but the modifier classes were left in place rather
  than stripped out, harmless either way.
*/

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--color-bg-content); /* per Lucrecia's request, matches the max-width box's own colour, was --color-bg-default */
  color: var(--color-text-dark);
}

/* ---- Outer page wrapper: max-width 1200px, 1px outline all round ---- */

.project-page {
  max-width: 1200px;
  margin: 0 auto;
  box-sizing: border-box; /* keeps the outline below flush with the 1200px edge, not 2px wider */
  background: var(--color-bg-content); /* per Lucrecia's request, matches the Work page's own bordered box, every breakpoint */
  border: 1px solid var(--color-text-dark);
  /* No bottom border: the footer sits directly below with its own
     border-top (footer.css), so a bottom border here would double up
     with it, 2px within this box's own 1200px width where the two
     overlap, next to the footer's single 1px everywhere wider. */
  border-bottom: none;
}

/* Nav sits beside the project header only, not the whole page (see
   .project-main below), align-items: stretch makes the nav's box match
   the header's height exactly, whichever project's header content
   makes it, rather than a hardcoded number that would need adjusting
   per project. */
.project-layout {
  display: flex;
  align-items: stretch;
}

/* Below the nav's own mobile breakpoint, stack instead of sitting side
   by side. This rule (like .project-layout itself just above) is
   functionally dead now that every project page carries the
   project-layout--v2 modifier, see that modifier's own comment further
   down for why it's still here. */
@media (max-width: 768px) {
  .project-layout {
    flex-direction: column;
  }

  .project-header {
    border-left: none; /* nav is a stacked block here, not a side column, so no vertical divider */
    border-top: 1px solid var(--color-text-dark);
  }
}

/* ---- Everything after the header: full 1200px width, no nav column ---- */

.project-main {
  /* No layout rules needed yet, block-level and full width by default.
     Kept as its own class (rather than styling the bare <main>) for
     consistency with how every other structural piece on this site is
     classed. */
}

/* ---- Divider between sections: 1px dark line at the join between
   each section (see the individual sections below for where it's
   used). Same technique as work.css's .divider--solid. ---- */

.divider--solid {
  border: none;
  margin: 0;
  height: 1px;
  background: var(--color-text-dark);
}

/* ---- Section 1, Project header: hero image + title/company/role/description ---- */

.project-header {
  flex: 1;
  min-width: 0; /* allows the column to shrink below its content's natural width, e.g. the fixed-height image */
  box-sizing: border-box;
  border-left: 1px solid var(--color-text-dark); /* divider between the nav column and the header */
}

/* ---- "project-layout--v2"/"project-header--v2": every project page
   carries these alongside the base classes above. Originally added so
   a since-retired sidebar-nav ("v1") version of these same pages could
   keep its real sidebar and nav-column divider untouched while this
   floating-nav version dropped both -- v1 is gone now (split off into
   LuCamiMa/websitev1), so these modifiers are the only behavior left
   in practice, the base rules above are functionally dead but kept
   as-is rather than merged in, see project.css's own header comment.
   Declared AFTER the base rules above so these win the cascade, same
   equal-specificity-so-source-order-decides issue documented elsewhere
   in this file. .project-header's own border-left (and mobile
   border-top) existed only as the divider against the nav column that
   no longer exists here, so this modifier drops both. No extra top
   clearance needed unlike About page's own header: the floating nav
   overlaps the top portion of .project-header__image (550px tall) the
   same way Landing V3's own floating nav already overlaps its full-
   height hero photo -- a nav floating over a photo is the established
   pattern on this site, it's only floating over READABLE TEXT (like
   About's title) that needed padding to stay clear. .project-layout
   itself needs no override: .project-header's own flex:1 already fills
   the row's full width with no nav sibling competing for space, this
   modifier exists only so a future reader isn't left wondering why a
   flex "layout" row exists around a single child. */
.project-layout--v2 {
  display: block;
}

.project-header--v2 {
  border-left: none;
}

@media (max-width: 768px) {
  .project-header--v2 {
    border-top: none;
  }
}

/* Once a project's header image is uploaded, use this on a real <img>
   (see sky/index.html). object-fit: cover crops it to fill the fixed
   488px height regardless of the image's own aspect ratio. */
.project-header__image {
  display: block;
  width: 100%;
  height: 550px;
  object-fit: cover;
  box-shadow: var(--shadow-image); /* same soft drop shadow as Work page images */
  /* Deliberately no border-radius: unlike other thumbnails on this site,
     the brief calls for square corners on this image specifically. */
}

/* Grey placeholder for projects whose header image isn't uploaded yet,
   same box dimensions/shadow/corners as .project-header__image above so
   swapping one for the other doesn't shift any layout. */
.project-header__image-placeholder {
  width: 100%;
  height: 550px;
  box-sizing: border-box;
  background: var(--color-placeholder);
  box-shadow: var(--shadow-image);
}

.project-header__copy {
  /* Top/bottom padding standardized to 50px (was 40px), per Lucrecia's
     request, applied here in the shared file so it's identical on
     every project page -- left/right stay at 40px, only asked to
     change top/bottom. */
  padding: 50px 40px;
  box-sizing: border-box;
}

.project-header__title {
  margin: 0 0 30px;
  font-family: var(--font-heading);
  font-size: var(--font-size-h1);
  font-weight: var(--weight-medium);
  color: var(--color-text-dark);
  text-transform: uppercase; /* per Lucrecia's request, the copy itself stays normal-case in the HTML */
}

.project-header__meta {
  display: flex;
  align-items: flex-start;
  gap: 30px; /* between the facts column and the description, back to 30px now that the facts column is a constant width (was 40px, before that 30px) */
}

/* Fixed width (not shrink-to-fit) so this column renders the exact
   same size on every project page regardless of how long the Role
   text is -- flex: 0 0 auto + max-width used to let the box shrink
   down to as little as ~90px for a short role ("UX Designer") or grow
   up to the full 150px for a longer one that wraps ("Lead Interaction
   Designer"), which shifted where the description column started (and
   how much room it had to wrap into) differently on every page. Bug
   fix, per Lucrecia's report. */
.project-header__facts {
  flex: 0 0 150px;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 30px; /* per the brief: gap between the Company block and the Role block */
}

.project-header__fact {
  margin: 0; /* resets the default <dl> child spacing, this wrapper's own gap comes from .project-header__facts above */
}

.project-header__fact-label {
  margin: 0 0 5px;
  font-family: var(--font-body);
  font-size: var(--font-size-small);
  font-weight: var(--weight-semibold);
  color: var(--color-text-dark);
  text-transform: uppercase; /* "Company" / "Role" labels, per Lucrecia's request, copy stays normal-case in the HTML */
}

.project-header__fact-value {
  margin: 0; /* resets the default <dd> left margin/indent too */
  font-family: var(--font-body);
  font-size: var(--font-size-project-body); /* project pages only, see .project-copy__body p below, tokens.css's --font-size-body (14px) is untouched so other pages aren't affected */
  line-height: var(--line-height-project-body);
  font-weight: var(--weight-regular);
  color: var(--color-text-dark);
}

/* Sizing only, sits in the flex row alongside .project-header__facts.
   The actual paragraph styling/spacing comes from .project-copy__body
   below (add that class alongside this one in the HTML). */
.project-header__description {
  flex: 1;
  min-width: 0;
}

/* Desktop only, per Lucrecia's request: bumps just the header's own
   description paragraphs to 18px, larger than the 16px
   --font-size-project-body every other project-copy__body block on
   the page still uses (Role, Collaborators, etc. are untouched). Below
   769px this rule simply doesn't apply, so mobile falls back to the
   shared 16px from .project-copy__body p above. Selector combines both
   classes (instead of just ".project-header__description p") so its
   specificity beats .project-copy__body p even though that rule is
   declared later in this file -- equal specificity would otherwise let
   source order decide and silently lose this override. */
@media (min-width: 769px) {
  .project-header__description.project-copy__body p {
    font-size: 18px;
  }
}

/* ---- Shared "title + body copy" text pattern ---- */
/* Per the brief: every section's text follows Title (H2) + body copy,
   reused wherever that pattern appears (Role below, and whichever
   later sections follow the same structure), not just role-specific. */

.project-copy {
  flex: 1;
  min-width: 0;
}

.project-copy__title {
  margin: 0 0 15px;
  font-family: var(--font-heading);
  font-size: var(--font-size-h2);
  font-weight: var(--weight-medium);
  color: var(--color-text-dark);
}

/* Wraps one or more <p> tags. Gap between paragraphs is a general
   site-wide rule (10px), not just for this section, use this class on
   any stacked block of body copy. */
.project-copy__body {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.project-copy__body p {
  margin: 0;
  font-family: var(--font-body);
  /* Project-page body copy uses its own token (16px / 156% line height)
     instead of the site-wide --font-size-body token (14px), scoped to
     project.css only so nothing else on the site changes. Collaborators
     is the one exception (see .project-collaborators__person below),
     left at the regular 14px token per the brief. */
  font-size: var(--font-size-project-body);
  line-height: var(--line-height-project-body);
  font-weight: var(--weight-regular);
  color: var(--color-text-dark);
}

/* ---- Section 2, Role: image + Title/body copy, side by side ---- */

.project-role {
  display: flex;
  align-items: flex-start;
  gap: 30px;
  padding: 50px 40px;
  box-sizing: border-box;
}

/* Both the image and the text column below used to be fixed pixel
   sizes (650px tall image, 534px wide text), which matched perfectly
   at the page's full 1200px width but didn't shrink together as the
   viewport narrowed below that, so the two could add up to more than
   the section actually had room for. Both are now sized as a
   percentage of the section's own available width instead (available
   width = the page's own width, capped at 1200px, minus this
   section's 80px of padding, its 30px gap, and the page's 2px
   border), so they always add up to exactly the space there is, at
   any width, and only stop shrinking once the mobile layout takes
   over below 768px (see the mobile query further down, which stacks
   image and text instead). The two percentages (51.01% / 48.99%) are
   the same 555.86px/534px split the fixed pixel values used to
   produce at 1200px width, so nothing changes at that width or wider,
   this only smooths out the range in between. */
.project-role__image {
  display: block;
  width: calc((min(100vw, 1200px) - 112px) * 0.5101);
  height: auto; /* follows the image's own real aspect ratio, so it can't ever look stretched/squashed */
  flex-shrink: 0;
}

/* Grey placeholder for projects whose Role image isn't uploaded yet,
   same idea as .project-header__image-placeholder above. aspect-ratio
   gives it a sensible portrait shape (no real photo to size it from
   yet), same width formula as the real image above. */
.project-role__image-placeholder {
  width: calc((min(100vw, 1200px) - 112px) * 0.5101);
  aspect-ratio: 4 / 5;
  flex-shrink: 0;
  box-sizing: border-box;
  background: var(--color-placeholder);
  box-shadow: var(--shadow-image);
}

/* Per the brief: the Role text starts 50px below the top of the image.
   .project-copy's height used to be pinned to a fixed formula (a
   ceiling meant to mirror a ~650px-tall image), which worked fine as
   long as a project's Role photo happened to share that same rough
   portrait proportion, but produced a mismatch (a tall gap of empty
   space below a flatter/landscape photo) whenever it didn't, since the
   .project-role row itself sizes to whichever child is tallest.
   .project-copy now just sizes to its own natural content height
   instead, so the section always wraps around whichever of image or
   text is taller, matching the image exactly for every project's own
   photo regardless of its proportions. The spacer below is a fixed
   50px (not a shrink target any more, there's no longer a hard
   ceiling for it to compete against), so text always starts exactly
   50px below the top of the image. */
.project-role .project-copy {
  display: flex;
  flex-direction: column;
  /* Fixed instead of flex: 1, so the text column is exactly the same
     width in every .project-role section regardless of what's on the
     image side. 48.99% of the available width is the same 534px this
     used to be fixed at, at the page's full 1200px width, used as the
     shared reference so "A note on development" (2 stacked images
     instead of 1, see .project-role__image-stack below) lines its
     text up exactly the same. */
  flex: 0 0 auto;
  width: calc((min(100vw, 1200px) - 112px) * 0.4899);
}

.project-role__copy-spacer {
  flex: 0 0 50px;
}

.project-role .project-copy__title,
.project-role .project-copy__body {
  flex-shrink: 0;
}

/* Mirrors the whole section: image on the right, text on the left,
   used by "A note on development" on spyscape-digital (identical
   layout to Role otherwise, same spacer/offset behaviour). Flipping
   via flex-direction keeps the HTML in the same [image, copy] order
   as Role, no markup difference beyond this one modifier class.
   justify-content: flex-end matters whenever the image and text
   column don't add up to exactly the full available width (e.g. a
   project-specific override that caps the image at a fixed height
   instead of the shared width formula): row-reverse also reverses
   which edge "flex-start" packs against, so without this, any leftover
   space collects on the LEFT instead of the right, pushing the text
   column away from the section's own left padding. Harmless when
   image + text do add up to the full width (the normal case), since
   there's no leftover space for justify-content to redistribute
   either way. */
.project-role--reverse {
  flex-direction: row-reverse;
  justify-content: flex-end;
}

/* For a .project-role--reverse section that needs 2 images instead of
   Role's 1 (see "A note on development"): sits where .project-role__image
   normally would, but as a column of 2 stacked images instead. flex: 1
   fills whatever width is left over after the text column's own fixed
   534px (see .project-role .project-copy above) and the 30px gap,
   instead of being sized by either image's own intrinsic width, that's
   what keeps the text column lined up the same as Role's. */
.project-role__image-stack {
  display: flex;
  flex-direction: column;
  gap: 20px;
  flex: 1;
  min-width: 0;
}

.project-role__image-stack-item {
  display: block;
  width: 100%;
  height: auto;
}

/* ---- Section 3, Full size image: edge to edge, no padding ---- */

/* "Full size" read as showing the whole image at the section's full
   1200px width, so width: 100% + height: auto (not a fixed height with
   object-fit: cover, that would crop it) - flag if a cropped/fixed-
   height treatment was actually wanted instead. */
.project-full-image {
  display: block;
  width: 100%;
  height: auto;
}

/* Masks an image's own drop shadow (var(--shadow-image)) flush at its
   bottom edge -- e.g. an image meant to sit flush with the end of its
   section, where the shadow would otherwise visibly cross into the
   divider below it. clip-path extends the clip region beyond the
   image's own edges on top/left/right (enough to clear the shadow's
   own blur there, so it still renders in full on those sides) while
   clipping exactly at the bottom edge, cutting the shadow off cleanly
   there instead of letting it bleed past the section. Applied directly
   to the image, no wrapper element needed -- unlike an overflow:hidden
   wrapper, clip-path is purely a paint-time mask, it doesn't insert a
   new containing block that would throw off the image's own
   percentage-based width elsewhere. */
.project-shadow-mask-bottom {
  clip-path: inset(-10px -15px 0 -15px);
}

/* Same idea, for an image with no side inset to spare (edge to edge,
   e.g. a full-bleed full-size image) -- expanding the clip region
   sideways there would let the shadow poke past the page's own edge,
   so only the top gets the extra allowance and the shadow is masked
   at the sides too. Imperceptible in practice: it's a subtle shadow
   sitting flush against the page's own border already. */
.project-shadow-mask-bottom--edge-to-edge {
  clip-path: inset(-10px 0 0 0);
}

/* Grey placeholder for a full size image section that isn't uploaded
   yet, same idea as the header/Role placeholders above. No real photo
   to size it from yet, so this falls back to the site's default 16:10
   crop (see CLAUDE.md's asset ratio convention) rather than guessing
   at a specific image's own shape. */
.project-full-image-placeholder {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  box-sizing: border-box;
  background: var(--color-placeholder);
}

/* For a full size image section that should read as taller than the
   others on the same page (see CSA Mobile's 2nd full-size image), a
   narrower placeholder ratio stands in for that until the real photo
   is uploaded, no real image to size this from yet so this is a guess
   at "taller", flag if a specific height/ratio was actually meant. */
.project-full-image-placeholder--tall {
  aspect-ratio: 3 / 4;
}

/* ---- Section, Final designs (stacked): Title + a plain vertical
   stack of images ---- */
/* Simpler than project-showcase's per-zone grid system (see
   spyscape-museum), for projects whose "final designs" is just one
   series of images one after another, not multiple named sub-sections. */

.project-stack {
  padding: 50px 40px;
  box-sizing: border-box;
}

.project-stack__images {
  margin-top: 30px;
  display: flex;
  flex-direction: column;
  gap: 50px; /* desktop only, mobile keeps the original 30px, see the mobile media query below */
}

.project-stack__image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-image);
}

.project-stack__image-placeholder {
  width: 100%;
  aspect-ratio: 16 / 10;
  box-sizing: border-box;
  background: var(--color-placeholder);
  border-radius: var(--radius-image);
}

/* ---- Section, Full size video: edge to edge, no padding ---- */
/* Same "full width, no padding" spirit as .project-full-image above,
   for projects whose full-scale section is a YouTube embed instead of
   a still image (see spyscape-museum). aspect-ratio: 16/9 is YouTube's
   standard embed ratio, so the iframe scales with the page width
   without needing a fixed pixel height. */
.project-full-video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
}

/* ---- Section, Project detail: icon legend + a diagram/plan image + Title/body copy ---- */
/* For projects that need to explain a spatial layout (see the
   spyscape-museum floor plan): a row of small icon + label pairs
   (matching the icons used again as markers in the Final designs
   section below), then the full-width diagram, then the usual
   Title/body copy pattern underneath. */

.project-detail {
  padding: 50px 40px;
  box-sizing: border-box;
}

.project-detail__legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between; /* spreads the items out to fill the section's full width instead of clumping with a fixed gap */
  gap: 10px; /* minimum spacing, only kicks in if the items ever wrap onto multiple lines */
  margin: 0 0 30px;
}

.project-detail__legend-item {
  display: flex;
  align-items: center;
  gap: 10px;
}

.project-detail__legend-icon {
  display: block;
  width: 24px;
  height: 24px;
}

.project-detail__legend-label {
  margin: 0;
  font-family: var(--font-body);
  font-size: 18px;
  font-weight: var(--weight-semibold);
  color: var(--color-text-dark);
}

.project-detail__plan {
  display: block;
  width: 100%;
  height: auto;
  margin: 0 0 30px;
}

/* ---- Section, Final designs: repeated Title/description/icon/image-grid
   "showcase" subsections, each marked off by a full-width dashed divider ---- */
/* Per the brief: every subsection has the same header pattern (Title +
   description capped at 560px, the zone's icon sitting to its right at
   100px tall, vertically centred with the text and flush with the
   section's right edge) and the same 50px/40px section padding, but
   each subsection's image grid composition is different, see the
   per-zone grid rules and utility placement classes further down. */

.project-showcase__section {
  padding: 50px 40px;
  box-sizing: border-box;
}

.project-showcase__heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 30px;
}

.project-showcase__text {
  max-width: 560px;
}

.project-showcase__icon {
  display: block;
  height: 100px;
  width: auto;
  flex-shrink: 0;
}

/* Full width but still inset by the section's own 40px side padding,
   unlike .divider--solid above which runs truly edge to edge between
   the page's main sections. */
.project-showcase__divider-dashed {
  border: none;
  margin: 0 40px;
  height: 0;
  border-top: 1px dashed var(--color-text-dark);
}

/* Every zone's grid is really just a stack of rows, and every row is
   either a plain side-by-side strip of images, or a row containing a
   nested column of 2 stacked images, since each zone's composition is
   different (see the brief). Plain nested flexbox handles both of
   those shapes without needing CSS Grid's row/column tracks. */

.project-showcase__grid {
  margin-top: 30px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.project-showcase__row {
  display: flex;
  gap: 20px;
}

/* A column of 2 (or more) stacked images, used as one "slot" inside a
   .project-showcase__row alongside a plain image, e.g. a tall image
   next to a pair of smaller stacked ones. */
.project-showcase__col {
  display: flex;
  flex-direction: column;
  gap: 20px;
  flex: 1;
  min-width: 0;
}

/* Default tile: a plain square, cropped to fit via object-fit so a row
   of mixed portrait/landscape source photos still lines up evenly.
   Every image below is a flex item (of the grid, a row, or a col), so
   flex: 1 makes it share space equally with its siblings unless a
   specific row overrides that (see the per-zone widths below). */
.project-showcase__grid img {
  display: block;
  width: 100%;
  min-width: 0;
  flex: 1;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--radius-image);
}

/* Note: these need to match "img" in the selector (not just the class
   alone), otherwise they lose the cascade to the plain-tile rule above,
   a class selector alone is lower specificity than a class + element
   selector, regardless of which one is written later in the file. */

/* A lone image sitting directly in the grid (not inside a row), full
   width, wide rather than square since it reads as a hero shot. */
img.project-showcase__grid-item--full {
  aspect-ratio: 16 / 9;
}

/* Sits in a .project-showcase__row beside a .project-showcase__col:
   no fixed shape of its own, instead stretches (the row's default
   cross-axis behaviour) and crops via object-fit to exactly match
   whatever height the stacked column next to it ends up being. */
img.project-showcase__grid-item--tall {
  aspect-ratio: auto;
}

/* Shows the photo/gif at its own real proportions instead of the
   default square crop, for compositions where the images need to line
   up using their actual shape rather than being cropped to match. */
img.project-showcase__grid-item--natural {
  aspect-ratio: auto;
}

/* Desktop-only: a taller mask than the default square tile (see
   Deception's last row), 400px instead of the 360px the 3 equal tiles
   would otherwise compute to at the section's 1120px content width
   (1120 - 40px of gaps) / 3. Resets back to the default square on
   mobile, see the mobile media query below. */
.project-showcase__row--tall-mask img {
  aspect-ratio: auto;
  height: 400px;
}

/* ---- Section, Collaborators: heading + a "Name / Role" column list ---- */
/* Padding not specified in the brief for this section, matches the
   50px/40px padding already used for Role.

   2 equal-width columns by default, 3 once there are more than 16
   people (the brief's "max 8 per column" rule), the :has() selector
   below lets that branch in plain CSS without needing JS to count the
   list. Browsers balance multi-column content by height, not a strict
   item count, so "8 per column" is an approximate guideline this
   follows rather than a hard runtime guarantee, close enough unless
   entries vary wildly in how many lines their role wraps to. */

.project-collaborators {
  padding: 50px 40px;
  box-sizing: border-box;
}

.project-collaborators__list {
  margin: 30px 0 0;
  padding: 0;
  list-style: none;
  columns: 2;
  column-gap: 30px;
}

.project-collaborators__list:has(> li:nth-child(17)) {
  columns: 3;
}

.project-collaborators__list > li {
  margin: 0 0 10px; /* per the brief: 10px between each name */
  break-inside: avoid; /* keeps one person's name/role together instead of splitting across a column break */
}

.project-collaborators__person {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--font-size-body); /* stays at the regular 14px token, the one exception to the 16px body copy test above */
  font-weight: var(--weight-regular);
  color: var(--color-text-dark);
}

.project-collaborators__name {
  font-weight: var(--weight-medium);
}

/* Sits below the name/role list, not inside it, a general note rather
   than a person entry. */
.project-collaborators__note {
  margin: 30px 0 0;
  font-family: var(--font-body);
  font-size: var(--font-size-small);
  font-weight: var(--weight-regular);
  color: var(--color-text-dark);
}

/* ---- Section, Similar projects: heading + 2 linked thumbnails ---- */
/* Same 16:10 crop + corner-radius/shadow treatment as the landing
   page's thumbnails (a plain aspect-ratio: 16/10, not the landing
   page's own responsive clamp() crop, that's specific to its coverflow
   carousel, not a general-purpose thumbnail shape). */

.project-similar {
  padding: 50px 40px;
  box-sizing: border-box;
}

.project-similar__grid {
  margin-top: 30px;
  display: flex;
  gap: 30px;
}

.project-similar__item {
  flex: 1;
  min-width: 0;
}

.project-similar__thumbnail-link {
  display: block;
}

.project-similar__thumbnail-link:focus-visible {
  outline: 2px solid var(--color-text-dark);
  outline-offset: 2px;
}

.project-similar__thumbnail {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--radius-image);
  box-shadow: var(--shadow-image);
  transition: transform 200ms ease-out, box-shadow 200ms ease-out; /* same hover treatment as the Work page's thumbnails, see work.css */
}

.project-similar__thumbnail-link:hover .project-similar__thumbnail,
.project-similar__thumbnail-link:focus-visible .project-similar__thumbnail {
  transform: scale(1.03);
  box-shadow: var(--shadow-image-hover);
}

.project-similar__title {
  margin: 15px 0 0;
  font-family: var(--font-heading);
  font-size: var(--font-size-h3);
  font-weight: var(--weight-bold);
}

.project-similar__title-link {
  color: var(--color-text-dark);
  text-decoration: none;
}

.project-similar__title-link:hover,
.project-similar__title-link:focus-visible {
  text-decoration: underline;
}

@media (max-width: 768px) {
  .project-collaborators__list,
  .project-collaborators__list:has(> li:nth-child(17)) {
    columns: 1; /* per the brief: single full-width column on mobile */
  }

  .project-similar__grid {
    flex-direction: column;
  }

  /* Every row (and any nested column already stacked) becomes a plain
     single column of images, same idea as every other grid on this
     site collapsing to 1 column on mobile. */
  .project-showcase__row {
    flex-direction: column;
  }

  /* No more row to stretch against once everything is a single
     column, back to the same plain square tile as every other image.
     Matches "img" in the selector to equal the specificity of the
     desktop rule above, otherwise this override loses the cascade. */
  img.project-showcase__grid-item--tall {
    aspect-ratio: 1 / 1;
  }

  /* Per the brief: title and icon share the same line (icon on the
     right), the description drops to its own full-width line below.
     .project-showcase__text stops being a visual grouping box on
     mobile (display: contents "unwraps" it) so its children (title,
     body) become direct flex/wrap items alongside the icon, instead of
     moving as one block, the order values below put them back in the
     right visual sequence since unwrapping puts the icon after the
     body in source order. */
  .project-showcase__heading {
    flex-wrap: wrap;
    align-items: flex-end; /* bottom of the icon lines up with the bottom of the title text */
    row-gap: 15px; /* title/icon row to the body paragraph below, 30px halved */
    column-gap: 15px; /* title to icon, same row */
  }

  .project-showcase__text {
    display: contents;
  }

  .project-showcase__heading .project-copy__title {
    flex: 1;
    min-width: 0;
    order: 1;
    /* The shared .project-copy__title rule has its own 15px bottom
       margin, which would both throw off the flex-end bottom
       alignment with the icon (margin counts as part of the item's
       box) and stack on top of the heading's own 30px row-gap below.
       Zeroed out here so the row-gap is the only source of that
       spacing and the title/icon bottoms line up exactly. */
    margin-bottom: 0;
  }

  .project-showcase__icon {
    height: 36px; /* 60px, 40% smaller */
    order: 2;
  }

  .project-showcase__heading .project-copy__body {
    flex-basis: 100%; /* forces this onto its own new line below title+icon */
    order: 3;
  }

  /* Natural height instead of the fixed 550px (desktop)/300px (this
     rule, previously) crop, per Lucrecia's request -- shows the real
     dedicated mobile header photo at its own real proportions, same
     treatment .project-showcase__grid-item--natural already gives
     other images on these pages, rather than cropping it again on top
     of the crop it was already given. object-fit:cover (inherited
     from the base rule) has no effect once height is auto -- there's
     no longer a mismatched box size for it to crop into. */
  .project-header__image {
    height: auto;
  }

  .project-header__image-placeholder {
    height: 300px; /* unused by any page's real markup any more (every project now has a real header photo), kept only so this class still has a sane fallback if it's ever reused */
  }

  /* Per the brief: mobile section padding is 50px top/bottom, 20px
     sides, and 30px vertical spacing between elements within a
     section. Applied below to every section that had its own padding
     (header copy, Role, Collaborators, Similar projects). */

  .project-header__copy {
    /* Top reduced to 40px per Lucrecia's request (was 50px), bottom/
       sides unchanged. */
    padding: 40px 20px 50px;
  }

  .project-header__meta {
    flex-direction: column;
    gap: 30px; /* matches the desktop gap above */
  }

  .project-header__facts {
    /* Reset back to auto-sized: .project-header__meta is a column on
       mobile, so the desktop rule's flex-basis: 150px would now fix
       this element's HEIGHT (the column's main axis) instead of its
       width, clipping or stretching it depending on content. */
    flex: 0 0 auto;
    max-width: none;
    flex-direction: row;
    gap: 30px; /* still per the brief, just laid out horizontally now there's a full line to itself */
  }

  .project-detail,
  .project-showcase__section,
  .project-collaborators,
  .project-similar {
    padding: 50px 20px;
  }

  /* Per the brief: the legend wraps into 2 items per row at this
     width (space-between already pushes item 2 to the row's right
     edge), the item in that right-hand slot gets its own content
     (icon + label) right-aligned too, mirroring the left column's
     content hugging the left edge instead of both trailing off toward
     the middle. */
  .project-detail__legend-item:nth-child(even) {
    flex-direction: row-reverse;
  }

  /* Rotates the floor plan 90 degrees into a portrait box that's the
     full width of the padded content area (matching every other
     mobile image on this page). A CSS transform only rotates the
     image visually, it doesn't resize the space reserved for it, so
     the wrapper below is sized to the ROTATED footprint (width: the
     available content width, height: that width scaled by the
     original image's own ratio, 2307x1314), overflow: hidden clips
     anything outside that box, and the image inside is absolutely
     positioned, centred, and given the un-rotated dimensions that
     produce exactly that footprint once rotated (its pre-rotation
     height becomes the rotated width, width: auto keeps its real
     aspect ratio so the pre-rotation width becomes the rotated
     height). .project-page is edge to edge at this width, so 100vw
     stands in for "full available page width" here. */
  .project-detail__plan-wrapper {
    position: relative;
    width: calc(100vw - 40px);
    height: calc((100vw - 40px) * 2307 / 1314);
    overflow: hidden;
    margin: 0 auto;
  }

  .project-detail__plan {
    position: absolute;
    top: 50%;
    left: 50%;
    height: calc(100vw - 40px);
    width: auto;
    max-width: none;
    margin: 0;
    transform: translate(-50%, -50%) rotate(90deg);
  }

  /* Per the brief: hides specific images within each interactive's
     gallery on mobile only, to keep the page shorter. Add/remove this
     class on any image below to change which ones show on mobile.
     Matches "img" in the selector, otherwise this loses the cascade to
     the plain-tile rule's display: block (same specificity issue as
     the other grid-item utilities above). Also usable directly on a
     .project-showcase__row wrapper itself, for a row whose every image
     is hidden, so the empty row doesn't still eat a gap on either side
     (see Deception's row 2). */
  img.project-showcase__grid-item--hide-mobile,
  .project-showcase__row.project-showcase__grid-item--hide-mobile {
    display: none;
  }

  /* Smaller 10px gap between images than the 20px desktop default,
     confirmed after trying it out on Encryption only first. */
  .project-showcase__grid,
  .project-showcase__row,
  .project-showcase__col {
    gap: 10px;
  }

  /* Resets Deception's desktop-only taller mask (see the non-mobile
     rule above) back to the default square tile, the mobile-specific
     treatment for this row is handled separately by the hide-mobile
     and mobile-natural classes on its individual images instead. */
  .project-showcase__row--tall-mask img {
    aspect-ratio: 1 / 1;
    height: auto;
  }

  /* Full (uncropped) height for one specific image on mobile only, see
     Deception's last image, distinct from the shared --natural class
     above so it doesn't also affect that image's desktop styling. The
     extra .project-showcase__row--tall-mask in the selector raises
     this above the row reset just above, which would otherwise win at
     equal specificity by coming later in the file. */
  .project-showcase__row--tall-mask img.project-showcase__grid-item--mobile-natural {
    aspect-ratio: auto;
  }

  .project-showcase__divider-dashed {
    margin: 0 20px; /* matches the 20px mobile side inset above, was 40px on desktop */
  }

  .project-role {
    flex-direction: column;
    padding: 50px 20px;
  }

  .project-role__image,
  .project-role__image-placeholder,
  .project-role__image-stack {
    height: auto;
    width: 100%;
  }

  .project-role .project-copy {
    height: auto; /* the 650px height only matters beside the fixed-height desktop image, stacked mobile layout goes back to natural sizing */
    flex: 1 1 auto; /* the fixed 534px desktop width only matters side by side, stacked mobile layout goes back to full width */
    width: auto;
  }

  /* Per the brief: the Role section's 50px top offset on the right
     column is a desktop-only detail (it starts the text below the top
     edge of the picture beside it), on mobile the image and text stack
     instead so that offset doesn't apply, the 30px section spacing
     above already separates the image from the text. */
  .project-role__copy-spacer {
    display: none;
  }

  /* Per the brief: body copy on mobile stays at the regular 14px size
     (not the 16px project-page token above). line-height nudged up a
     little from plain "normal" (~1.15-1.2 for this font at this size),
     per Lucrecia's request for a bit more breathing room, matching the
     spirit of the desktop bump above without going all the way to the
     desktop's own larger value. */
  .project-header__fact-value,
  .project-copy__body p {
    font-size: var(--font-size-body);
    line-height: 1.35;
  }

  /* Per the brief: mask the full-size image to a 4:3-ish crop on
     mobile instead of showing it uncropped, fixed 296px height + full
     width + object-fit: cover, same masking technique as
     .project-header__image above. object-position: top keeps the crop
     anchored to the top of the image (object-fit's default centres
     the crop, which can cut off the top) so whatever's at the top of
     the photo stays visible whenever this mask is applied, this is the
     one masking breakpoint today but the same object-position should
     carry over to any future one too. */
  .project-full-image {
    height: 296px;
    object-fit: cover;
    object-position: top;
  }

  .project-stack__images {
    gap: 30px; /* the 50px desktop spacing is a desktop-only choice, mobile keeps the original 30px */
  }
}
