/* COR Projects — Figma "Project Single" (653:5578). 1980 comp; margins 40 (bleed) / 100 (text).
   Colours from Elementor Global Colors: primary #1A4348 · secondary #259596 · accent #B8DCFC */
.cor-prj-hero, .cor-prj-meta, .cor-prj-lede, .cor-prj-body, .cor-prj-gallery, .cor-prj-scope, .cor-prj-mosaic, .cor-prj-related, .cor-prj-grid{
  --p-green: var(--e-global-color-primary, #1A4348); --p-agave: var(--e-global-color-secondary, #259596); --p-blue: var(--e-global-color-accent, #B8DCFC);
  --p-ink: #2D2926; --p-serif: "utile-display", "Utile Display", Georgia, serif; --p-sans: "CircularXX", "Circular", "Helvetica Neue", Arial, sans-serif;
  --p-ease: cubic-bezier(.22, 1, .36, 1); --p-gutter: 2.02vw; /* 40/1980 */ --p-inset: 5.05vw; /* 100/1980 */
  box-sizing: border-box;
}
.cor-prj-hero *, .cor-prj-gallery *, .cor-prj-scope *, .cor-prj-mosaic *, .cor-prj-related *, .cor-prj-grid *{ box-sizing: border-box; }
.cor-prj-hero figure, .cor-prj-gallery figure, .cor-prj-mosaic figure{ margin: 0; }

/* ---------- hero: full-bleed image with 40px inset + r40, title bottom-left, meta bar bottom-right ---------- */
.cor-prj-hero{ position: relative; margin: 0 var(--p-gutter); height: clamp(420px, 38.2vw, 757px); }
.cor-prj-hero__media{ position: absolute; inset: 0; border-radius: 40px 40px 0 0; overflow: hidden; background: #e9ebea; }   /* square bottom corners */
.cor-prj-hero__media img{ width: 100%; height: 100%; object-fit: cover; display: block; }
.cor-prj-hero__title{
  position: absolute; left: calc(var(--p-inset) - var(--p-gutter)); bottom: 63px; margin: 0; max-width: 62%;   /* 63px off the image's bottom edge */
  font: 500 clamp(44px, 5.66vw, 112px)/0.9 var(--p-serif); color: #fff; letter-spacing: 0; text-shadow: 4px 4px 50px rgba(0,0,0,.15); }
.cor-prj-hero .cor-prj-meta{ position: absolute; right: calc(var(--p-gutter) * -1); bottom: -3.1vw; }   /* overlaps the hero's bottom edge, flush right */

/* meta bar: Midnight, 117px tall, rounded bottom-left 58, right-aligned text, items 40px apart */
.cor-prj-meta{ display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 0 40px;
  min-height: clamp(64px, 5.9vw, 117px); padding: 18px 5.05vw 18px 60px; background: var(--p-green); color: #fff; border-radius: 0 0 0 58px;
  font: 400 18px/26.35px var(--p-sans); }
/* CS-180 (17 Sep): Jim — "Location, Industry, Solutions need to be Circular
   Medium." This said 500, which is what Medium means in CSS everywhere else —
   but on this site the kit registers CircularXXWeb-Medium.woff2 at
   `font-weight: 600`, and there is no 500 face at all. CSS font matching for a
   desired 500 with faces at 400/600/700 checks 500, finds nothing, then
   descends — so 500 was silently rendering Regular. 600 is the declaration that
   actually loads the Medium file. Measured: the same string sets 512px wide at
   400/450/500 and 538px at 600. */
.cor-prj-meta strong{ font-weight: 600; }

/* ---------- lede + body: Utile Display Medium 43/1.25 +1px · 24/1.25 +1px, max 1040 ---------- */
/* both are full-bleed like the gallery and apply the comp's 100px inset themselves — set the section's side padding to 0.
   text column = 1040px (comp) */
.cor-prj-lede, .cor-prj-body{ box-sizing: border-box; width: 100vw; margin-left: calc(50% - 50vw); padding-left: var(--p-inset); padding-right: var(--p-gutter);
  max-width: min(100vw, calc(var(--p-inset) + 1040px)); }
.cor-prj-lede{ margin-top: 0; margin-bottom: 22px; font: 500 clamp(28px, 2.17vw, 43px)/1.25 var(--p-serif); letter-spacing: 0; color: var(--p-green); }
.cor-prj-body{ font: 500 clamp(18px, 1.21vw, 24px)/1.25 var(--p-serif); letter-spacing: 0; color: var(--p-ink); }   /* CS-53/70: no tracking on body copy */
/* when the lede sits right above the body in separate widgets, keep the comp's 22px between them */
.elementor-widget:has(.cor-prj-lede) + .elementor-widget:has(.cor-prj-body) .cor-prj-body{ margin-top: 0; }
.cor-prj-body p{ margin: 0 0 1em; font: inherit; color: inherit; }
.cor-prj-body p:last-child{ margin-bottom: 0; }

/* ---------- gallery: 780×776 slides r40, 20px gap, bleeds off the right; arrows + dots below ---------- */
/* full-bleed: the track spans the whole viewport (escapes any boxed container) so slides run off the screen edges;
   the first slide still starts at the 40px inset via scroll padding */
.cor-prj-gallery{ position: relative; width: 100vw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); }
/* the scope panel's Midnight block rises up behind the bottom third of the slides (comp: 264px of the 776px slide) and
   runs down through the arrows row, so it meets [cor_project_details] seamlessly below */
.cor-prj-gallery::before{ content: ""; position: absolute; left: 0; bottom: 0; z-index: 0; width: min(1000px, 50.5vw);
  height: calc(clamp(320px, 39.2vw, 776px) / 3 + 100px); background: var(--p-green); }
.cor-prj-track, .cor-prj-gallery__nav{ position: relative; z-index: 1; }
.cor-prj-track{ display: flex; gap: 20px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; -ms-overflow-style: none;
  padding-left: var(--p-gutter); padding-right: var(--p-gutter); scroll-padding-left: var(--p-gutter); cursor: grab; scroll-behavior: smooth; }
/* the active slide always parks at the 40px inset; the previous slide keeps peeking in from the left edge (inset − 20px gap) */
.cor-prj-track::-webkit-scrollbar{ display: none; }
.cor-prj-track.is-dragging{ cursor: grabbing; scroll-behavior: auto; scroll-snap-type: none; }
/* slides: LOCKED height (comp 776 at 1980 → 39.2vw), width follows each image's own ratio — nothing is cropped */
.cor-prj-slide{ --ratio: 1.5; flex: 0 0 auto; height: clamp(320px, 39.2vw, 776px); width: calc(clamp(320px, 39.2vw, 776px) * var(--ratio)); max-width: 88vw;
  scroll-snap-align: start; border-radius: 10px; overflow: hidden; background: #e9ebea; }
.cor-prj-slide a{ display: block; width: 100%; height: 100%; cursor: zoom-in; }
.cor-prj-slide img{ width: 100%; height: 100%; object-fit: cover; display: block; user-select: none; }   /* container already has the image's ratio, so no visible crop */
/* 34px, not the comp's 76px. 34 is a box number that buys a 40px INK inset —
   the button carries 6px of padding around the glyph — so these arrows line up
   with the Elementor rails and the Related rail below. See the .cor-prj-btn
   width override further down for the arithmetic. */
.cor-prj-gallery__nav{ display: flex; align-items: center; justify-content: space-between; margin: 24px 34px 0 var(--p-gutter); padding-left: 50.5vw; }
.cor-prj-dots{ display: flex; gap: 12px; }
/* CS-118: the dot the eye sees is the ::after, not the button.
   The states used to be transform: scale() on an 8px button — scale(1.25) for
   active, scale(.625) for the window edge. Scaling a circle that small means the
   engine rasterises a 5-8px box and then stretches it, and the active dot came
   out flat-sided rather than round. Real widths and heights avoid that.

   That first fix left the button at 8px and let the 10px active ::after spill
   over it, held in place by the negative auto margins that inset:0 + margin:auto
   produces when the child is bigger than its containing block. It looked right
   in Chrome and wrong on iOS: the active dot — the only one larger than its own
   containing block — rendered as a rounded rectangle with flat top, bottom and
   sides. Safari resolves `border-radius: 50%` there against the 8px containing
   block, not the element's own 10px box, so a 10px square got a 4px radius.

   Two changes, either of which would have been enough, kept together because
   they cost nothing:

   1. The button is sized to the LARGEST state (10px), so no ::after ever
      exceeds its containing block and no auto margin is ever negative. The
      smaller states centre inside it with ordinary positive margins. The row
      still never reflows on a state change — every button is 10px whatever its
      dot is doing.
   2. `border-radius: 999px` instead of 50%. A px radius is clamped to half the
      box by the spec, so it is a circle for any square element and cannot be
      resolved against the wrong box. */
.cor-prj-dot{ width: 10px !important; height: 10px !important; padding: 0 !important; border-radius: 999px !important;
  background: transparent !important; cursor: pointer; position: relative; }
.cor-prj-dot::after{ content: ""; position: absolute; inset: 0; margin: auto; width: 8px; height: 8px;
  border-radius: 999px; background: #D9D9D6; transition: width .2s, height .2s, background .2s; }
.cor-prj-dot.is-active::after{ background: var(--p-green); width: 10px; height: 10px; }
.cor-prj-dot:hover::after{ background: var(--p-agave); }
/* The capped dot window — see windowDots() in cor-projects.js. Never more than one
   row; the small dot at an end means there are more images that way. */
.cor-prj-dot.is-hidden{ display: none !important; }
.cor-prj-dot.is-edge::after{ width: 5px; height: 5px; }
.cor-prj-arrows{ display: flex; gap: 0; }
/* hard resets — the theme styles every <button> (border, min-width, maroon) */
.cor-prj-btn, .cor-prj-btn:hover, .cor-prj-btn:focus, .cor-prj-dot, .cor-prj-dot:hover, .cor-prj-dot:focus{
  background-image: none !important; border: 0 !important; box-shadow: none !important; text-shadow: none !important; outline: none;
  min-width: 0 !important; min-height: 0 !important; margin: 0 !important; line-height: 1 !important; -webkit-appearance: none; appearance: none; }
.cor-prj-btn{ width: 76px !important; height: 76px !important; border-radius: 50% !important; background: transparent !important; cursor: pointer; padding: 0 !important;
  font: 500 40px/1 var(--p-serif) !important; color: var(--p-agave) !important; transition: color .2s, transform .35s var(--p-ease); }
.cor-prj-btn:hover{ color: var(--p-green) !important; background: transparent !important; }
.cor-prj-btn:focus-visible{ outline: 2px solid var(--p-agave); outline-offset: 2px; }
.cor-prj-btn.cor-prj-next:hover{ transform: translateX(6px); } .cor-prj-btn.cor-prj-prev:hover{ transform: translateX(-6px); }
/* Matching the Elementor rails, measured by INK rather than by box.
   Those arrows are a 36px SVG that fills its button, so 40px from the edge and
   12px apart means the glyphs are 40 and 12. These are a 32px glyph centred in
   a 76px round hit area — 22px of padding on every side — so the same box
   numbers put the glyphs 62px from the edge with 45px between them, which is
   what Jim was looking at when he asked for them tighter.
   The hit area narrows to 44px and the containers move in by that 22 − 6 = 16px
   (right: 34, margin-right: 34), which lands both glyphs at 40/12. Height stays
   76px, so the gallery's nav row does not change height and nothing below it
   moves. Desktop only: the ≤1024 rails sit in their own row and keep the wider
   target. */
@media (min-width: 1025px){
    .cor-prj-btn{ width: 44px !important; border-radius: 999px !important; }
}


/* ---------- scope panel + mosaic (comp, 1980 wide, measured from the gallery's bottom edge G):
   panel 0→1000 wide from G+5 · tall image right-flush 820×1229 from G+171 · wide image at x=40, 1088×680, from G+543 · next section at G+1555 ---------- */
.cor-prj-scope{ position: relative; z-index: 2; box-sizing: border-box; width: min(1000px, 50.5vw); padding: 62px var(--p-inset) 60px; background: var(--p-green); color: #fff;
  border-radius: 0 0 100px 0; font-family: var(--p-sans); }
.cor-prj-eyebrow{ display: block; margin: 0 0 32px; font: 700 18px/1 var(--p-sans); letter-spacing: 2px; text-transform: uppercase; color: var(--p-blue); }
/* CS-127: the tracks used to be `240px 240px 1fr` inside a panel that is only
   50.5vw wide. Two fixed 240s plus the gaps need 520px of the panel's content
   box, and the panel only clears that above roughly 1520px of viewport — below
   it the third column is squeezed to its min-content and the whole grid
   overflows the padding and then the panel's rounded edge. At 1280 "Completed"
   was hanging 28px outside the green.
   Fluid tracks with a 240px ceiling keep the wide layout and let the columns
   give way instead of the panel. --cor-scope-cols is set by the shortcode to
   however many columns actually have content. */
.cor-prj-scope__cols{ display: grid; grid-template-columns: repeat(var(--cor-scope-cols, 3), minmax(0, 240px)); gap: 0 20px; }
.cor-prj-field{ margin-bottom: 30px; }
.cor-prj-field:last-child{ margin-bottom: 0; }
.cor-prj-field__label{ display: block; font: 500 18px/26.35px var(--p-sans); margin-bottom: 4px; }
.cor-prj-field__value{ display: block; font: 400 16px/24px var(--p-sans); max-width: 330px; }

/* [cor_project_details] — one full-bleed canvas, everything placed in vw so it scales like the frame */
/* pulled up by the gallery's nav row (76px arrows + 24px) so PROJECT SCOPE starts 62px under the slides, like the comp;
   the canvas itself ignores clicks so the dots/arrows underneath stay usable */
.cor-prj-details{ position: relative; width: 100vw; margin-left: calc(50% - 50vw); height: 70.7vw; margin-top: -100px; pointer-events: none; }
.cor-prj-details > *{ pointer-events: auto; }
.cor-prj-details .cor-prj-scope{ position: absolute; left: 0; top: 0; }
.cor-prj-details .cor-prj-mosaic{ position: static; margin: 0; min-height: 0; width: auto; }
.cor-prj-details .cor-prj-mosaic__tall{ position: absolute; right: 0; top: 8.6vw; width: 41.4vw; max-width: none; height: 62vw; aspect-ratio: auto; border-radius: 40px 0 0 40px; }
.cor-prj-details .cor-prj-mosaic__wide{ position: absolute; left: var(--p-gutter); top: 27.4vw; width: 55vw; max-width: none; height: 34.3vw; margin: 0; aspect-ratio: auto; border-radius: 40px; }
.cor-prj-details--no-mosaic{ height: auto; } .cor-prj-details--no-mosaic .cor-prj-scope{ position: relative; }

/* standalone [cor_project_mosaic] (if used without the combined shortcode) */
.cor-prj-mosaic{ position: relative; width: 100vw; margin: 0 0 0 calc(50% - 50vw); min-height: 62vw; }
.cor-prj-mosaic__tall{ position: absolute; right: 0; top: 0; width: 41.4vw; max-width: 820px; aspect-ratio: 820 / 1229; border-radius: 40px 0 0 40px; overflow: hidden; background: #e9ebea; }
.cor-prj-mosaic__wide{ position: absolute; left: var(--p-gutter); top: 18.8vw; width: 55vw; max-width: 1088px; aspect-ratio: 1088 / 680; border-radius: 40px; overflow: hidden; background: #e9ebea; }
.cor-prj-mosaic figure{ overflow: hidden; background: #e9ebea; }
.cor-prj-mosaic img{ width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- related projects: full-bleed track, active card at the 100px inset, next card cropped by the screen edge.
   Non-active cards: title fades out to the right (gradient text), location hidden; both fade in when the card becomes active. ---------- */
.cor-prj-related{ position: relative; width: 100vw; margin-left: calc(50% - 50vw); }
.cor-prj-related__head{ display: flex; align-items: flex-end; justify-content: space-between; margin: 0 0 30px; padding: 0 var(--p-inset) 0 5.15vw; }
.cor-prj-h2{ margin: 0; font: 500 clamp(40px, 3.43vw, 68px)/1.03 var(--p-serif); letter-spacing: -.2px; color: var(--p-green); }
/* CS-125, second pass. The arrows began at `bottom: 12px`, which centred their
   76px box on the TITLE row — and a title long enough to wrap ran straight
   under them. Moving them to their own row after the track cleared that, but
   dropped them 88px below the card text, which Jim read as too far down:
   "have it sit in the space where the location would be just under the project
   header."
   So they are back over the card text, one line lower than they started —
   centred on the LOCATION line instead of the title row. That single line of
   difference is what makes it safe: a title's second line ends where the
   location line begins, so the two no longer share a band.
   The 24px of bottom padding is what lets a 76px-tall box centre on that line
   without hanging below the section. `right: 34px` puts the GLYPH 40px from the
   edge — the global sweep Jim asked for on 15 Sep; this rail is PHP rather than
   Elementor, so it was missed at the time. */
/* `bottom: 0` is only the fallback. The section's height is set by the TALLEST
   card's text, so when some other card in the rail carries a two-line title the
   section floor drops 35px and the arrows go with it, while the active card's
   location line stays where it is. The script measures that line and writes
   --cor-arrow-top; this is the no-JS position, near enough and never wrong.
   A white scrim was tried here and removed: a 273px box of gradient sat across
   the incoming card's title and punched a hole through the middle of a word,
   which is worse than the overlap it was guarding against. The real cause was a
   title wrapping where it should not — see the one-line clamp below — so the
   arrows need nothing behind them. */
.cor-prj-related{ padding-bottom: 24px; }
.cor-prj-related .cor-prj-arrows{
    position: absolute; right: 34px; bottom: 0; z-index: 2; justify-content: flex-end;
}
.cor-prj-related.has-arrow-anchor .cor-prj-arrows{ top: var(--cor-arrow-top); bottom: auto; }
.cor-prj-track--cards{ gap: 25px; padding-left: 5.15vw; padding-right: 0; scroll-padding-left: 5.15vw; }
/* end spacer so the last card can travel all the way to the left inset (otherwise it stops early, still cropped) */
.cor-prj-track--cards::after{ content: ''; flex: 0 0 calc(100vw - 5.15vw - min(60.3vw, 1194px) - 25px); }
/* CS-126: once the rail loops, the spacer's job is done — cloned cards fill the
   tail instead, and leaving it in would put ~420px of white back at the end. The
   class is only ever set by the script, after the clones are in, so a rail with
   no JS keeps the spacer and its old behaviour. */
.cor-prj-track--cards.is-looping::after{ content: none; }
.cor-prj-track--cards .cor-prj-card{ flex: 0 0 60.3vw; max-width: 1194px; }
.cor-prj-card{ display: block; text-decoration: none !important; color: inherit; scroll-snap-align: start; }
.cor-prj-card__media{ display: block; aspect-ratio: 1194 / 650; border-radius: 10px; overflow: hidden; background: #e9ebea; }
.cor-prj-card__media img{ width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .6s var(--p-ease); }
.cor-prj-card:hover .cor-prj-card__media img{ transform: scale(1.03); }
/* The 5px of bottom padding is what stops descenders being sliced off — see the
   non-active rule below for why the box height matters at all here. */
.cor-prj-card__title{ display: inline-block; margin-top: 16px; padding-bottom: 5px; font: 500 32px/1.1 var(--p-serif); color: var(--p-green); transition: color .4s, opacity .4s; }
.cor-prj-arrow{ display: inline-block; font: 400 21px/1 var(--p-serif); color: var(--p-agave); margin-left: 2px; white-space: nowrap; transition: transform .35s var(--p-ease), opacity .4s; vertical-align: 2px; }
.cor-prj-card:hover .cor-prj-arrow{ transform: translateX(8px); }
.cor-prj-card:hover .cor-prj-card__title{ color: var(--p-agave); }
/* -1px, not 4px: the title above now carries 5px of bottom padding, so this
   gives back the same 5px and the location line sits exactly where it did. */
.cor-prj-card__loc{ display: block; margin-top: -1px; font: 400 18px/27.6px var(--p-sans); color: var(--p-ink); transition: opacity .4s; }
/* cropped / non-active cards */
/* Why the title needs bottom padding: this fade is `background-clip: text`, so
   the letters are painted by clipping the element's BACKGROUND to their shape —
   and a background only covers the element's own box. utile-display at 32px has
   a 43px font box inside a 35.2px line box (line-height 1.1), which leaves ink
   hanging 3.4px below the box with no background to paint it. The result was a
   bitten-off descender on every faded title: the g in "Engineering". Active
   titles have a real `color` and were never affected, which is what made it look
   like a font bug rather than a box one. */
/* One line, and only one. The fade is a HORIZONTAL device — it says "this card
   runs off the side of the screen". A wrapped title breaks that completely: the
   second line starts back at the left of the card, where the gradient is still
   fully opaque, so a cropped card ended up with a ghosted first line and a
   second line reading at full strength with a live-looking arrow beside it.
   `nowrap` keeps the teaser to a single trailing-off line; `max-width: 100%`
   stops the inline-box growing past the card and into its neighbour; and
   `overflow: hidden` clips at the PADDING box, which the 5px above puts below
   the descenders, so the hard cut takes nothing with it. The visible cut is the
   gradient's, at 75%, not this one.
   Only non-active cards. The card you are actually reading wraps as it likes. */
.cor-prj-track--cards .cor-prj-card:not(.is-active) .cor-prj-card__title{
  background: linear-gradient(90deg, var(--p-green) 0%, rgba(26,67,72,.55) 45%, rgba(26,67,72,0) 75%); -webkit-background-clip: text; background-clip: text; color: transparent;
  max-width: 100%; white-space: nowrap; overflow: hidden; }
.cor-prj-track--cards .cor-prj-card:not(.is-active) .cor-prj-arrow{ opacity: 0; }
.cor-prj-track--cards .cor-prj-card:not(.is-active) .cor-prj-card__loc{ opacity: 0; }
.cor-prj-track--cards .cor-prj-card:not(.is-active):hover .cor-prj-card__media img{ transform: none; }

/* ---------- portfolio grid ---------- */
.cor-prj-grid{ display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 60px 25px; }
.cor-prj-grid .cor-prj-card__media{ aspect-ratio: 920 / 650; }

@media (max-width: 1024px){
  .cor-prj-hero{ height: 52vw; } .cor-prj-hero__title{ max-width: 80%; bottom: 40px; }
  .cor-prj-hero .cor-prj-meta{ position: static; margin: 0 calc(var(--p-gutter) * -1) 0 auto; border-radius: 0 0 0 40px; font-size: 15px; gap: 0 20px; padding: 14px 24px; }
  .cor-prj-hero{ height: auto; } .cor-prj-hero__media{ position: relative; aspect-ratio: 16/10; } .cor-prj-hero__title{ position: absolute; }
  .cor-prj-slide{ height: 60vw; width: calc(60vw * var(--ratio)); border-radius: 10px; } .cor-prj-gallery__nav{ padding-left: 0; }
  .cor-prj-scope{ width: 100%; border-radius: 0 0 60px 0; padding: 48px 32px; } .cor-prj-scope__cols{ grid-template-columns: 1fr 1fr; }
  .cor-prj-details{ height: auto; width: 100%; margin-left: 0; margin-top: 24px; } .cor-prj-details .cor-prj-scope{ position: relative; }
  .cor-prj-details .cor-prj-mosaic__tall, .cor-prj-mosaic__tall{ position: relative; top: auto; width: 100%; height: auto; aspect-ratio: 4/3; border-radius: 24px; margin-top: 24px; }
  .cor-prj-details .cor-prj-mosaic__wide, .cor-prj-mosaic__wide{ position: relative; top: auto; left: 0; width: 100%; height: auto; aspect-ratio: 16/10; border-radius: 24px; margin-top: 20px; }
  .cor-prj-mosaic{ min-height: 0; width: 100%; margin: 0; }
  .cor-prj-track--cards .cor-prj-card{ flex-basis: 80vw; max-width: none; }
  /* On small screens the cards are 80vw and the text wraps freely, so the arrows
     keep their own row under the track rather than sitting over it. */
  .cor-prj-related{ padding-bottom: 0; }
  .cor-prj-related .cor-prj-arrows{ position: static; padding: 12px 24px 0 0; background: none; }   /* own row, so no scrim to fade */
  .cor-prj-grid{ grid-template-columns: 1fr; gap: 40px; }
  .cor-prj-btn{ width: 56px; height: 56px; font-size: 30px; }
  /* CS-54/57: no Midnight tab behind the dots on small screens; dots and arrows sit in a clean row under the slides */
  .cor-prj-gallery::before{ display: none; }
  /* CS-181 (21 Sep): Keilian — "Add additional padding mobile", boxing the strip
     between the dots and the Midnight Project Scope band. The bottom margin here
     was 0, and nothing below supplies the space: the gallery has no padding of
     its own and the scope band starts at its own top padding, so the dots and
     arrows ended up sitting on the colour boundary. 32px gives the controls the
     same air under them that the 16px above plus the slide gap gives them on
     top. Desktop is untouched — there the Midnight tab behind the dots
     (.cor-prj-gallery::before) already separates the two. */
  .cor-prj-gallery__nav{ margin: 16px var(--p-gutter) 32px; padding-left: 0; }
  /* CS-164. The dots sat hard against the gutter and the arrows did not, so the
     row looked pushed left even though both ends used the same margin. The
     arrow is a 52px button around a 26px glyph, so the glyph floats (52-26)/2 =
     13px inside its own box and reads as 21px off the right edge, against the
     dots' 7.94px. Measured at 393px, the width the ticket was filed at.
     Bumping the dots right by that same 13px puts both ends of the row on the
     same optical inset — 21px and 21px.
     The button's size is set in the kit CSS, not here (the 16 Sep 40px arrow
     sweep), so re-measure (button width - glyph width) / 2 if the arrows are
     ever resized rather than assuming 13px still holds. */
  .cor-prj-dots{ gap: 10px; flex-wrap: nowrap; padding-left: 13px; }   /* the window is capped, so a row can never need to wrap */
  /* CS-55: labels read bold on desktop; keep that weight when the columns stack */
  .cor-prj-field__label{ font-weight: 700; }
}
@media (max-width: 640px){
  .cor-prj-lede, .cor-prj-body{ padding-left: 20px; padding-right: 20px; }
  .cor-prj-hero{ margin: 0 16px; } .cor-prj-hero__media{ border-radius: 20px 20px 0 0; } .cor-prj-hero__title{ font-size: 40px; left: 20px; }
  .cor-prj-scope__cols{ grid-template-columns: 1fr; } .cor-prj-card__title{ font-size: 26px; }
  /* CS-55: when the three columns stack, every field keeps its 30px gap (the per-column last-child reset no longer applies) */
  .cor-prj-field, .cor-prj-field:last-child{ margin-bottom: 30px; }
  .cor-prj-scope__cols > :last-child .cor-prj-field:last-child{ margin-bottom: 0; }
}
@media (prefers-reduced-motion: reduce){ .cor-prj-track{ scroll-behavior: auto; } .cor-prj-btn, .cor-prj-arrow, .cor-prj-card__media img, .cor-prj-dot::after{ transition: none !important; } }

/* ---------- hero intro (frame reveal like the home page) ---------- */
html.cor-prj-intro-on{ overflow: hidden; }
.cor-prj-intro{ position: fixed; left: 0; right: 0; bottom: 0; z-index: 99990; pointer-events: none; }
.cor-prj-intro__img{ position: absolute; inset: 0; background-size: cover; background-position: center; }
.cor-prj-intro__frame{ position: absolute; box-shadow: 0 0 0 200vmax #fff; will-change: top, left, width, height; }   /* white outside the frame; picture underneath never moves */
/* header sits above the image layer during the intro: transparent, white text/logo; colours transition back as the frame lands */
.cor-prj-intro-header{ position: relative; z-index: 99995; }
.cor-prj-intro-header, .cor-prj-intro-header .e-con, .cor-prj-intro-header .e-con-inner{ background: transparent !important; box-shadow: none !important; }
.cor-prj-intro-header :where(h1,h2,h3,h4,h5,h6,a,span,button,p,div,input,label){ color: #fff !important; -webkit-text-fill-color: #fff !important; transition: color .7s ease, -webkit-text-fill-color .7s ease; }
.cor-prj-intro-header img{ filter: brightness(0) invert(1); transition: filter .7s ease; }
.cor-prj-intro-header--landing :where(h1,h2,h3,h4,h5,h6,a,span,button,p,div,input,label){ color: var(--e-global-color-primary, #1A4348) !important; -webkit-text-fill-color: var(--e-global-color-primary, #1A4348) !important; }
.cor-prj-intro-header--landing img{ filter: none; }
/* title slides in from the left as the frame lands; meta bar fades up after */
.cor-prj-hero--intro .cor-prj-hero__title{ opacity: 0; transform: translateX(-60px); }
.cor-prj-hero__title{ transition: opacity .7s ease, transform .9s cubic-bezier(.22, 1, .36, 1); }
.cor-prj-hero--intro.cor-prj-hero--title-in .cor-prj-hero__title{ opacity: 1; transform: none; }
.cor-prj-hero--intro .cor-prj-meta{ opacity: 0; transform: translateY(18px); }
.cor-prj-hero .cor-prj-meta{ transition: opacity .6s ease, transform .7s cubic-bezier(.22, 1, .36, 1); }
.cor-prj-hero--intro.cor-prj-hero--meta-in .cor-prj-meta{ opacity: 1; transform: none; }
/* lede + body: same slide-right/fade as the title, half a second later */
html.cor-prj-intro-run .cor-prj-lede, html.cor-prj-intro-run .cor-prj-body{ opacity: 0; transform: translateX(-60px); transition: opacity .7s ease, transform .9s cubic-bezier(.22, 1, .36, 1); }
html.cor-prj-intro-run.cor-prj-copy-in .cor-prj-lede, html.cor-prj-intro-run.cor-prj-copy-in .cor-prj-body{ opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce){ .cor-prj-hero__title, .cor-prj-hero .cor-prj-meta{ transition: none !important; } }

/* ============================================================
   Portfolio browser — sort bar, search, chips
   Figma 1229:2614 (pills) and 1229:2499 (search field).
   Dropdowns are native <details>, so there is no JS here.
   ============================================================ */

.cor-prj-sortbar{
    display:flex; flex-wrap:wrap; justify-content:flex-end; align-items:center;
    /* row then column. The shorthand was 20 for both; a wrapped second row of
       pills wants more air than the space between two pills on one line. */
    gap:14px 20px; position:relative; z-index:5;
}

/* --- the pill --- */
.cor-prj-pill{ position:relative; }
.cor-prj-pill > summary{
    display:flex; align-items:center; gap:8px;
    /* border-box or the 1px border and 9px padding push a 42px pill to 62. */
    box-sizing:border-box; height:42px; padding:9px 15px 9px 20px;
    border:1px solid var(--pb-agave,#259596); border-radius:40px;
    font:700 16px/21.6px "Circular",sans-serif;
    letter-spacing:1.6px; text-transform:uppercase; color:#259596;
    background:transparent; cursor:pointer; white-space:nowrap;
    list-style:none;                       /* Firefox */
    transition:background .25s ease, color .25s ease;
}
.cor-prj-pill > summary::-webkit-details-marker{ display:none; }   /* Safari/Chrome */
.cor-prj-pill > summary:hover,
.cor-prj-pill[open] > summary,
.cor-prj-pill.is-on > summary{ background:#259596; color:#fff; }
.cor-prj-caret{
    font:500 18px/24.3px utile-display,sans-serif; letter-spacing:1.8px;
    transition:transform .25s ease;
}
.cor-prj-pill[open] .cor-prj-caret{ transform:rotate(180deg); }

/* --- the menu --- */
.cor-prj-menu{
    position:absolute; top:calc(100% + 8px); right:0; z-index:20;
    min-width:260px; max-height:340px; overflow:auto;
    padding:8px 0; background:#fff; border:1px solid #E4E4E2; border-radius:20px;
    box-shadow:0 18px 40px -24px rgba(26,67,72,.55);
}
.cor-prj-opt{
    display:flex; justify-content:space-between; align-items:center; gap:16px;
    padding:9px 22px; text-decoration:none;
    font:400 16px/24px "Circular",sans-serif; color:#1A4348;
    transition:background .2s ease, color .2s ease;
}
.cor-prj-opt:hover{ background:#F5F5F4; color:#259596; }
.cor-prj-opt.is-on{ color:#259596; font-weight:500; }
.cor-prj-opt-n{ font-size:14px; color:#888B8D; }
.cor-prj-opt--clear{ border-bottom:1px solid #E4E4E2; margin-bottom:4px; padding-bottom:12px; }
/* narrowing. An option with nothing behind it under the current filter leaves
   its menu — a 30-row brand list is only useful once the dead rows are out of
   it. A pill with no live options left STAYS, dimmed and unclickable, so the
   bar keeps its width and its order instead of reflowing every time a filter
   is set. */
/* CS-95: the MillerKnoll brands lead the Brands menu, with a rule under the last
   of them so the pinned block reads as a block rather than as an alphabetical
   list that happens to start oddly. The marker moves to the last one still
   standing when a filter empties some of them — see paintOptions(). */
.cor-prj-opt--pinned-last{ border-bottom:1px solid #E4E4E2; margin-bottom:4px; padding-bottom:12px; }
.cor-prj-opt--gone{ display:none !important; }
.cor-prj-pill--gone{ opacity:.35; pointer-events:none; }
.cor-prj-pill--gone > summary{ cursor:default; }
.cor-prj-pill--gone .cor-prj-caret{ visibility:hidden; }   /* nothing to open */

/* --- search field: 1780 x 80, 1px agave, radius 40 --- */
.cor-prj-search{
    display:flex; align-items:center; gap:25px;
    box-sizing:border-box; width:100%; height:80px; padding:0 21px;
    background:#fff; border:1px solid #259596; border-radius:40px;
}
.cor-prj-search-glyph{ font:700 40px/1 "Circular",sans-serif; color:#259596; }
.cor-prj-search input[type="search"]{
    flex:1; min-width:0; border:0; outline:0; background:transparent;
    font:400 21px/1.2 "Circular",sans-serif; color:#2D2926;
}
.cor-prj-search input[type="search"]::placeholder{ color:#2D2926; opacity:1; }

/* --- active filter chips --- */
.cor-prj-chips{ display:flex; flex-wrap:wrap; gap:14px 20px; align-items:center; }
/* The wrapper always renders so the filter script has something to swap; with
   no filters set it holds nothing and must take no space. */
.cor-prj-chips:empty{ display:none; }
/* Inside the bar the chips are the first child, held left by an auto margin
   while the pills keep the right edge the comp draws them on. An auto margin
   rather than `space-between` because the bar wraps: with nothing chosen the
   chips are display:none and the pills have to stay right on their own. */
.cor-prj-sortbar > .cor-prj-chips{ margin-right:auto; }
/* The bar section was built with a second shortcode widget for the chips. That
   shortcode now returns nothing, but the widget it sits in is still a flex child
   of the section and still claims the container's row gap under the bar. The
   widget can simply be deleted in Elementor; until it is, this collapses it. */
.cor-prj-page__bar .elementor-widget-shortcode:has(> .elementor-widget-container > .elementor-shortcode:empty){ display:none; }
/* Filtering in place: dim the results while the next page is on its way, and
   keep the pointer honest. Only the grid fades — the sort bar has to stay
   usable so a second pill can be chosen straight away. */
.cor-prj-loading .elementor-widget-loop-grid{ opacity:.45; transition:opacity .15s ease; pointer-events:none; }
/* The featured rail when nothing featured survives the filter. A class, not the
   `hidden` attribute, because an Elementor container carries display:flex and
   would win over [hidden]. */
.cor-prj-gone{ display:none !important; }

/* ---------- filtering changes what the page is (CS-96, CS-98) ----------
   Two things go once anything is chosen or typed:

   · the hero eyebrow (CS-96). It labels the page "PROJECTS"; the H1 under it
     then says "Brand: Herman Miller", and the pair says the word twice. The
     first selector is the structural one and works with no JavaScript at all —
     the heading whose next sibling holds the scope title; the second is the
     class the script stamps on that same widget, for anything without :has().

   · the Featured rail (CS-98). It is a hand-picked editorial selection of the
     whole portfolio, so above three filtered results it is not "featured", it is
     a second unrelated grid the visitor has to scroll past to reach what they
     asked for. */
body.cor-prj-filtered .cor-prj-page__hero > .elementor-widget-heading:has(+ .elementor-widget-heading .cor-prj-title),
body.cor-prj-filtered .cor-prj-eyebrow-slot,
body.cor-prj-filtered .cor-prj-page__featured{ display:none !important; }
/* One featured project left: it is a card, not a carousel. Drop the arrows and
   let the single slide take the full width — Swiper is deliberately not
   initialised in this case, so nothing else is sizing it. */
.cor-feat--single .elementor-swiper-button,
.cor-feat--single .swiper-pagination{ display:none !important; }
.cor-feat--single .swiper-wrapper{ display:block; transform:none !important; }
.cor-feat--single .swiper-slide{ width:100% !important; margin:0 !important; }
/* With one match there is no Swiper, so no slide is ever marked active — the
   panel and the rounded corner have to come back on their own or the single
   card renders as a bare picture. */
.cor-feat--single .cor-feat__panel{ opacity:1 !important; pointer-events:auto !important; }
.cor-feat--single .cor-feat__media{ border-top-left-radius:40px; border-bottom-left-radius:40px; }
/* Drawn to the pill's own measurements — 42px tall, 16px Circular at 1.6
   tracking — so a chosen filter and an offered one read as the same control.
   Nowrap because a chip that breaks across two lines stops looking like a pill. */
.cor-prj-chip{
    display:inline-flex; align-items:center; gap:8px;
    box-sizing:border-box; height:42px; padding:9px 20px;
    border:1px solid #259596; border-radius:40px;
    font:700 16px/21.6px "Circular",sans-serif; letter-spacing:1.6px;
    text-transform:uppercase; color:#259596; text-decoration:none;
    white-space:nowrap;
    transition:background .25s ease, color .25s ease;
}
.cor-prj-chip:hover{ background:#259596; color:#fff; }
.cor-prj-chip--clear{ background:#1A4348; border-color:#1A4348; color:#fff; padding:9px 32px; }   /* CS-52: same solid pill as the Products browser */
.cor-prj-chip--clear:hover{ background:#259596; border-color:#259596; color:#fff; }

/* ---------- Load More (CS-94) ----------
   Drawn as the solid Midnight pill the site already uses for its one primary
   action per block — the same shape and type as "Clear all" — so the grid ends
   in a control that reads as part of the set, not a browser default button.
   Centred under the grid with the rhythm's own spacing above it. */
.cor-prj-more-wrap{ display:flex; justify-content:center; margin:56px 0 0; }
.cor-prj-more-wrap[hidden]{ display:none; }
.cor-prj-more{
    box-sizing:border-box; min-height:56px; padding:16px 48px;
    border:1px solid #1A4348; border-radius:40px;
    background:#1A4348; color:#fff;
    font:700 16px/21.6px "Circular",sans-serif; letter-spacing:1.6px;
    text-transform:uppercase; cursor:pointer; white-space:nowrap;
    transition:background .25s ease, border-color .25s ease;
}
/* CS-129: the Elementor kit carries `.elementor-kit-7 button:hover{ color:
   Secondary; background-color: Secondary }` — Agave text on an Agave background,
   which is a button with no readable label. It only reaches bare <button>
   elements, and on the front end every one of those is ours; the carousel arrows
   and dots already fend it off with the !important resets near the top of this
   file, and this was the one left exposed.
   Specificity, not source order: the kit selector scores (0,2,1) and outranks a
   plain `.cor-prj-more:hover` at (0,2,0), so the class is repeated to reach
   (0,3,0) and win wherever WordPress decides to print the two stylesheets. */
.cor-prj-more.cor-prj-more:hover,
.cor-prj-more.cor-prj-more:focus-visible{ background:#259596; border-color:#259596; color:#fff; }
/* The grid's cards take focus programmatically after a load so the reader lands
   on the new work; they are not tab stops, so they must not draw a ring. */
.elementor-widget-loop-grid .e-loop-item[tabindex="-1"]:focus{ outline:none; }

@media (max-width:1024px){
    .cor-prj-more-wrap{ margin-top:40px; }
    .cor-prj-sortbar{ justify-content:flex-start; gap:12px; }
    .cor-prj-menu{ left:0; right:auto; }
    .cor-prj-search{ height:64px; gap:14px; }
    .cor-prj-search input[type="search"]{ font-size:17px; }
}
@media (prefers-reduced-motion: reduce){
    .cor-prj-pill > summary, .cor-prj-caret, .cor-prj-opt, .cor-prj-chip, .cor-prj-more{ transition:none; }
}

/* ---------- the search box's suggestions (projects only) ---------- */
.cor-prj-search{ position:relative; }
.cor-prj-suggest{
    position:absolute; left:0; right:0; top:calc(100% + 8px); z-index:20;
    margin:0; padding:8px 0; list-style:none;
    max-height:340px; overflow-y:auto;
    background:#fff; border:1px solid var(--p-rule, #D9D9D6); border-radius:10px;
    box-shadow:0 12px 32px rgba(26,67,72,.12);
}
.cor-prj-suggest li{
    padding:10px 24px; cursor:pointer;
    font:400 17px/1.35 "CircularXX","Circular","Helvetica Neue",Arial,sans-serif;
    color:var(--e-global-color-primary,#1A4348);
}
.cor-prj-suggest li:hover,
.cor-prj-suggest li.is-on{ background:var(--e-global-color-secondary,#259596); color:#fff; }

/* ============================================================
   CS-161 — phones: one Filter dropdown, sectioned by facet.
   Keilian asked for the six pills (three rows on a 393 phone) to become one
   row; the team chose a single dropdown and asked that it still separate the
   filters by type. The pills are the same <details> as on desktop, wrapped in
   .cor-prj-pills — `display: contents` above 767 so the bar is unchanged.
   ============================================================ */
.cor-prj-filterbtn,
.cor-prj-pill-cat{ display:none; }
.cor-prj-pills{ display:contents; }

@media (max-width:767px){
    .cor-prj-sortbar{ position:relative; }
    /* Specificity is deliberate: the Elementor kit styles every <button>
       (Midnight fill) at (0,1,1) and its :hover/:focus at (0,2,1), so a plain
       class loses — the first render drew a solid Midnight pill. */
    .cor-prj-sortbar button.cor-prj-filterbtn{
        display:flex; align-items:center; gap:10px; width:100%; order:-1;
        box-sizing:border-box; height:48px; min-height:0; padding:0 18px 0 22px; margin:0;
        border:1px solid #259596; border-radius:40px; background:transparent; box-shadow:none;
        font:700 16px/21.6px "Circular",sans-serif; letter-spacing:1.6px;
        text-transform:uppercase; color:#259596; cursor:pointer;
        transition:background .25s ease, color .25s ease;
    }
    .cor-prj-filterbtn .cor-prj-caret{ margin-left:auto; }
    .cor-prj-filterbtn[aria-expanded="true"] .cor-prj-caret{ transform:rotate(180deg); }
    .cor-prj-sortbar button.cor-prj-filterbtn:focus,
    .cor-prj-sortbar button.cor-prj-filterbtn[aria-expanded="true"],
    .cor-prj-sortbar button.cor-prj-filterbtn.is-on{ background:#259596; border-color:#259596; color:#fff; }
    .cor-prj-sortbar button.cor-prj-filterbtn:focus:not(:focus-visible):not(.is-on):not([aria-expanded="true"]){ background:transparent; color:#259596; }
    /* hover only where there is a pointer — on a phone it sticks after a tap */
    @media (hover:hover){ .cor-prj-sortbar button.cor-prj-filterbtn:hover{ background:#259596; border-color:#259596; color:#fff; } }
    .cor-prj-filterbtn-n{
        display:inline-flex; align-items:center; justify-content:center;
        min-width:22px; height:22px; padding:0 6px; box-sizing:border-box;
        border-radius:11px; background:#fff; color:#259596;
        font:700 13px/1 "Circular",sans-serif; letter-spacing:0;
    }
    .cor-prj-filterbtn-n:empty{ display:none; }

    /* the panel — only once the script is there to open it */
    body.cor-prj-js .cor-prj-pills{
        /* the button is ordered first in the bar, so the panel hangs off it
           rather than off the bar — the chips wrap underneath and get covered */
        display:none; position:absolute; top:56px; left:0; right:0; z-index:20;
        max-height:70vh; overflow:auto; overscroll-behavior:contain;
        padding:6px 0; background:#fff; border:1px solid #E4E4E2; border-radius:20px;
        box-shadow:0 18px 40px -24px rgba(26,67,72,.55);
    }
    body.cor-prj-js .cor-prj-sortbar.is-all-open .cor-prj-pills{ display:block; }
    /* no script: the sections simply stack in the bar */
    body:not(.cor-prj-js) .cor-prj-filterbtn{ display:none; }
    body:not(.cor-prj-js) .cor-prj-pills{ display:block; width:100%; border:1px solid #E4E4E2; border-radius:20px; }

    /* each facet is a section row: LABEL ......... chosen value ↓ */
    .cor-prj-pills .cor-prj-pill{ width:100%; }
    .cor-prj-pills .cor-prj-pill + .cor-prj-pill{ border-top:1px solid #E4E4E2; }
    .cor-prj-pills .cor-prj-pill > summary,
    .cor-prj-pills .cor-prj-pill > summary:hover,
    .cor-prj-pills .cor-prj-pill[open] > summary,
    .cor-prj-pills .cor-prj-pill.is-on > summary{
        height:auto; min-height:52px; padding:14px 18px 14px 22px; gap:0;
        border:0; border-radius:0; background:transparent;
        /* the text node is the chosen value (or the label, which the section
           heading already shows) — sized to zero unless something is chosen */
        font:400 0/1.3 "Circular",sans-serif; letter-spacing:0; text-transform:none;
        color:#259596; white-space:normal; text-align:right;
    }
    .cor-prj-pills .cor-prj-pill.is-on > summary{ font-size:15px; }
    .cor-prj-pill-cat{
        display:block; order:-1; flex:1 1 auto; margin-right:12px; text-align:left;
        font:700 14px/21.6px "Circular",sans-serif; letter-spacing:1.4px;
        text-transform:uppercase; color:#1A4348;
    }
    .cor-prj-pills .cor-prj-pill > summary .cor-prj-caret{
        margin-left:12px; font-size:18px; color:#259596;
    }
    .cor-prj-pills .cor-prj-menu{
        position:static; min-width:0; max-height:none; overflow:visible;
        padding:0 0 10px; border:0; border-radius:0; box-shadow:none; background:transparent;
    }
    .cor-prj-pills .cor-prj-opt{ padding:10px 22px 10px 34px; }
}

/* ============================================================
   CS-248 — tablet and phone: the two mosaic photos under the scope panel.
   Two rules in the ≤1024 block never applied. The 24px / 20px margin-tops lose
   to `.cor-prj-mosaic figure{ margin:0 }` (0,1,1 beats 0,1,0), so the photos
   touched. And `height:100%` on the <img> cannot resolve against a figure
   whose height comes from aspect-ratio, so the tall photo rendered at its own
   2:3 height and the figure cut it off at the top — a crop of the ceiling.
   The image is now pinned to the figure's box, so object-fit crops it centred.
   ============================================================ */
@media (max-width: 1024px){
    /* !important: Elementor's `.elementor .elementor-widget:not(…):not(…) figure{ margin:0 }` is (0,4,1) */
    .cor-prj-mosaic figure.cor-prj-mosaic__tall{ margin-top: 24px !important; }
    .cor-prj-mosaic figure.cor-prj-mosaic__wide{ margin-top: 20px !important; }
    .cor-prj-mosaic figure{ position: relative; }
    .cor-prj-mosaic figure img{ position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
}
