/*
 * project-pages.css: page-specific layer for ENTTEC project (solution) pages.
 *
 * Built ON TOP of the ENTTEC Design System (eds- components, the --enttec- and
 * --eds- tokens, and eds-reveal behaviour), which loads site-wide via the
 * enttec-design-system mu-plugin. This file adds only the project-page bits the
 * DS does not provide, all scoped under .proj. Enqueue on singular `solution`
 * only; bump ver= when editing (theme cache-versioning rule).
 *
 * DESIGN CONTRACT (do not drift):
 *  - Palette is STRICT SCM-SOP-144 brand only. No blue tints/opacities, ever.
 *      blue #0ea5df . black #000 . white #fff . dark grey #333 . mid grey #4c4c4c . light grey #d9d9d9
 *  - Type + proportions mirror the original snowglow solution template:
 *      h1 Montserrat 67/500 . h2 Montserrat 38/400 . body Source Sans 21/400 . body colour #4c4c4c
 *  - Sub-nav is a clone of the product-page sr-anchor-nav (dark bar, centred
 *    links, solid-blue underline on hover/active), NOT a pill nav.
 */

/* Brand palette, pinned locally so nothing reaches for an off-brand DS tint. */
.proj {
  --proj-blue:  #0ea5df;
  --proj-black: #000000;
  --proj-dark:  #333333;   /* brand "dark grey" - the dark bands */
  --proj-mid:   #4c4c4c;   /* brand "mid grey" - body text on white */
  --proj-light: #d9d9d9;   /* brand "light grey" - hairlines */
  --proj-subnav:#2a2a2a;   /* subtly darker than the #333 Overview band so the bar reads as its own */
  --eds-container: 1500px; /* content measure (widened per review; DS default is 1760) */
}

/* Bands run edge to edge. The theme can inset `main section`; neutralise that
   horizontal inset on project pages and let .proj fill its wrapper, rather than
   a 100vw breakout. (The old `width:100vw; left:50%; margin-left:-50vw` mixed vw,
   which counts the scrollbar, with 50%, which does not, so it shifted the whole
   page ~1 scrollbar-width left and left a white gap down the right edge.) The
   inner .eds-container still holds the readable measure. */
body.enttec-project-page main section,
body.enttec-project-page main > section {
  width: 100%; max-width: none; margin-left: 0; margin-right: 0;
  padding-left: 0; padding-right: 0;
}
.proj { width: 100%; margin-left: 0; margin-right: 0; }

/* ============================ TYPE SCALE ============================ */
.proj h1 { font-family: var(--enttec-font-display); font-weight: 500;
  font-size: clamp(40px, 6vw, 67px); line-height: 1.2; letter-spacing: normal; }
.proj h2 { font-family: var(--enttec-font-display); font-weight: 400;
  font-size: clamp(28px, 4vw, 38px); line-height: 1.2; letter-spacing: 0; margin: 0 0 30px; }
.proj h3 { font-family: var(--enttec-font-display); font-weight: 500;
  font-size: clamp(20px, 2vw, 24px); line-height: 1.25; }
.proj p  { font-size: clamp(17px, 1.4vw, 21px); font-weight: 400; line-height: 1.5; color: var(--proj-mid); }
.proj .eds-section--tone-dark p,
.proj .eds-section--tone-dark h2 { color: #fff; }

/* Body hyperlinks: ENTTEC blue. Underline ONLY inside body copy (paragraphs),
   never on cards / buttons / nav (those are links too and must stay clean).
   Hover thickens the underline (no blue tint); on dark bands the text goes white. */
.proj a { color: var(--proj-blue); text-decoration: none; transition: color .15s var(--eds-ease); }
.proj a:hover { color: var(--proj-blue); }                 /* keep blue on hover (override theme's grey) */
.proj p a { text-underline-offset: 3px; text-decoration-thickness: 1.5px; }
.proj p a:hover { text-decoration: underline; }            /* underline appears on hover only, light + dark */

/* Buttons keep their design-system label colour inside .proj (the broad `.proj a`
   colour rule above must not repaint button text: primary/ghost = white, outline =
   ink on light bands and white on dark). */
.proj a.eds-btn--primary { color: #fff; }
.proj a.eds-btn--ghost   { color: #fff; }
.proj a.eds-btn--outline { color: var(--enttec-ink); }
.proj .eds-section--tone-dark a.eds-btn--outline { color: #fff; }

/* Dark bands = flat brand dark grey. Grey band = light grey for the products row. */
.proj .eds-section--tone-dark { background: var(--proj-dark); }
.proj .eds-section--tone-grey { background: #f2f2f2; }

/* Eyebrows: solid ENTTEC blue everywhere (the DS tints them light-blue #5ec9ef on
   dark bands, an off-brand blue variant we are not allowed to use). The eyebrow is
   a <p>, so match the dark-band p-rule specificity to keep it blue. */
/* Restore the small eyebrow: it is a <p>, so the broad `.proj p` body rule
   (17-21px / weight 400) outranks the DS `.eds-eyebrow` and blows it up. */
.proj .eds-eyebrow { color: var(--proj-blue); font-size: 13px; font-weight: 600; line-height: 1.3; }
.proj .eds-section--tone-dark .eds-eyebrow { color: var(--proj-blue); }

/* ============================ HERO ============================ */
/* The page renders its own in-content eds-hero (prototype height min(86vh,760px)),
   so hide the theme's own title/banner band, it is 100vh (too tall) and would
   otherwise stack a second hero above ours. Scoped to project pages only. */
body.enttec-project-page #wrapper > header.header { display: none; }
/* With no theme banner, the theme flags body.noBannerApplied and flips the navbar
   to its dark-text/black-logo state. Our in-content hero is dark, so restore the
   over-hero WHITE navbar (text, icons, logo) for project pages. */
body.enttec-project-page.noBannerApplied { --navbar-header-color: #fff; --navbar-header-color-light: #fff; --header-icons: 0; }
body.enttec-project-page.noBannerApplied #navbar .white-logo { display: block !important; }
body.enttec-project-page.noBannerApplied #navbar .black-logo { display: none !important; }
/* The slow hero zoom waits for its own image, rather than starting at page load.
   Keyed off .is-hero-ready, which the JS adds on the image's load event (or
   immediately when it is already cached). Before this the 14s animation began
   whether or not there were pixels to show, so on a cold cache a heavy hero spent
   the first seconds animating nothing and the viewer only caught the tail, making
   the effect look inconsistent between pages purely because of file weight.
   Holding scale(1.08) until then also means no visible jump when it starts. */
.eds-hero > img { transform: scale(1.08); }
.eds-hero > img.is-hero-ready { animation: proj-hero-zoom 14s var(--eds-ease) both; }
@keyframes proj-hero-zoom { from { transform: scale(1.08); } to { transform: scale(1); } }

/* ============================ SUB-NAV ============================ */
/* Clone of the product-page sr-anchor-nav: dark bar, centred links, solid-blue
   underline on hover/active. Sticky via plain CSS (no scroll polling). */
/* Sticky handled by JS (theme overflow:hidden breaks position:sticky): the bar
   is relative in flow, and .is-pinned switches it to fixed on scroll. */
.proj-subnav { background: var(--proj-subnav); position: relative; z-index: 25; }
.proj-subnav.is-pinned { position: fixed; left: 0; right: 0; top: 0; z-index: 90; transition: top .25s var(--eds-ease); }
/* The JS spacer holds the bar's height while it is pinned (fixed). Give it the
   dark band colour so the reserved space blends into the Overview section below
   instead of flashing white between the (dark) hero and (dark) overview. */
.proj-subnav-spacer { background: var(--proj-dark); }
.proj-subnav ul { list-style: none; margin: 0; padding: 0; display: flex; justify-content: center;
  gap: 0; overflow-x: auto; scrollbar-width: none; }
.proj-subnav ul::-webkit-scrollbar { display: none; }
.proj-subnav li { display: flex; margin: 0; }  /* kill the theme's 6px li margin so the active underline sits on the bar's bottom edge */
.proj-subnav a { color: rgba(255,255,255,0.72); font-family: var(--enttec-font-body); font-size: 16px;
  font-weight: 400; white-space: nowrap; padding: 18px 22px; display: block; text-decoration: none;
  position: relative; transition: color .2s var(--eds-ease); }
/* Underline grows out from the centre on hover/active (scaleX) rather than just
   fading a colour in. Reuses the design-system "bar grows" motion. Absolutely
   positioned so it never affects the bar's height or triggers the ul overflow-x. */
.proj-subnav a::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--proj-blue); transform: scaleX(0); transform-origin: center;
  transition: transform .25s var(--eds-ease); }
.proj-subnav a:hover,
.proj-subnav a[aria-current="true"] { color: #fff; }
.proj-subnav a:hover::after,
.proj-subnav a[aria-current="true"]::after { transform: scaleX(1); }

/* ========================== OVERVIEW ========================== */
/* Snowglow layout: H2 left, (lead paragraph + specs table) right. */
.proj-overview { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: var(--eds-space-lg); align-items: start; }
.proj p.proj-overview__lead { font-size: clamp(18px, 1.6vw, 22px); line-height: 1.5; }
.proj .eds-section--tone-dark .proj-overview__lead { color: #fff; }
@media (max-width: 860px) { .proj-overview { grid-template-columns: 1fr; gap: var(--eds-space-md); } }

/* Specs table + Show more expander (rebuild of the Kadence show-more block). */
.proj-specs { width: 100%; border-collapse: collapse; margin-top: var(--eds-space-md); }
.proj-specs th, .proj-specs td { text-align: left; vertical-align: top; padding: 13px 0;
  border-top: 1px solid rgba(255,255,255,0.16); font-size: 16px; line-height: 1.5; }
.proj-specs tr:first-child th, .proj-specs tr:first-child td { border-top: 0; }
.proj-specs th { width: 34%; font-family: var(--enttec-font-body); font-weight: 600;
  color: rgba(255,255,255,0.72); text-transform: uppercase; letter-spacing: 0.06em; font-size: 13px; padding-right: 18px; }
.proj-specs td { color: #fff; }

/* Collapsed: clip the table and fade the bottom edge so it reads as "there's more"
   instead of a hard cut. Expanded removes the clip + fade. */
.proj-specs-wrap { position: relative; max-height: 640px; overflow: hidden;
  transition: max-height .45s var(--eds-ease); }
.proj-specs-wrap.is-collapsed { max-height: 212px; }
.proj-specs-wrap.is-collapsed::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 90px;
  background: linear-gradient(to bottom, rgba(51,51,51,0) 0%, var(--proj-dark) 92%);
  pointer-events: none;
}

/* min-height 44px: the accessible tap target. At 14px/9px padding this button
   computed to 40px, 4px short. Padding is unchanged so the label keeps its
   proportions; the height comes from the floor plus centring. */
.proj-showmore { margin-top: 18px; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; box-sizing: border-box;
  background: none; border: 1px solid rgba(255,255,255,0.3); border-radius: var(--enttec-radius-pill);
  color: #fff; font-family: var(--enttec-font-body); font-size: 14px; padding: 9px 20px; cursor: pointer;
  transition: border-color .2s var(--eds-ease), background .2s var(--eds-ease), transform .2s var(--eds-ease); }
.proj-showmore:hover { border-color: var(--proj-blue); transform: translateY(-2px); }
.proj-showmore:focus { outline: none; }                         /* no white browser outline */
.proj-showmore:focus-visible { outline: 2px solid var(--proj-blue); outline-offset: 3px; }
.proj-showmore svg { width: 13px; height: 13px; transition: transform .2s var(--eds-ease); }
.proj-showmore[aria-expanded="true"] svg { transform: rotate(180deg); }

/* ===================== FEATURE (venue / solution) ===================== */
.proj-feature { display: grid; grid-template-columns: 1.08fr 0.92fr; gap: var(--eds-space-lg); align-items: start; }
/* Even 50/50 variant for a row of two MEDIA items (no body copy to weight one
   side). Kadence called this colLayout "equal"; the default above is the
   text-plus-media proportion. Used by the snowglow highlight + video row.
   Tighter gutter than --eds-space-lg (72px at desktop, which left the pair
   reading as two small separate panels) so the two items read as one block. */
.proj-feature--even { grid-template-columns: 1fr 1fr; gap: clamp(14px, 1.7vw, 24px); }

/* Band holding a media-only row: no top padding, so the row sits directly under
   the story it illustrates instead of a full section gap away from it. It keeps
   the shared .eds-container measure on purpose. An earlier version widened this
   band past the page measure to make the media bigger; the 16px edge mismatch
   against every other section read as a mistake, so width comes from the tighter
   gutter alone. */
.proj-section--media { padding-top: 0; }
/* Explicit paragraph spacing so stacked body paragraphs read as separate blocks
   (the generic `.proj p` sets no margin, so they'd otherwise run together on the
   theme default). em-based so the gap scales with the body size. The figcaption
   keeps its own tighter margin via its higher-specificity rule. */
.proj-feature > div > p { margin: 0 0 1.2em; }
.proj-feature > div > p:first-child { margin-top: 0; }
.proj-feature > div > p:last-child { margin-bottom: 0; }
@media (max-width: 860px) { .proj-feature { grid-template-columns: 1fr; gap: var(--eds-space-md); } }

.proj-media { border-radius: var(--eds-radius); overflow: hidden; background: var(--proj-dark); }
.proj-media > img,
.proj-media > video { width: 100%; height: 100%; display: block; object-fit: cover; }
.proj-media--video { aspect-ratio: 16 / 9; position: relative; }
.proj-media--photo { aspect-ratio: 4 / 3; }
/* 16:9 photo. Same ratio as --video, so an image and a video sitting side by side
   in a .proj-feature--even row come out exactly the same height. */
.proj-media--wide  { aspect-ratio: 16 / 9; }
/* Caption under the video: small descriptive text, not body-copy size. Uses
   p.proj-figcaption so it outranks the generic .proj p 21px rule. */
.proj p.proj-figcaption { margin: 12px 2px 0; font-size: 13.5px; line-height: 1.45; color: var(--proj-mid); }
.proj .eds-section--tone-dark .proj-figcaption { color: rgba(255,255,255,0.62); }

/* ---- Custom video controls (branded bar; native controls are hidden) -------
   Reusable control bar for project videos: play/pause, a seekable scrubber,
   mute and fullscreen. Absolutely positioned over the bottom of the video,
   revealed on hover/focus (always shown on touch, and under reduced-motion
   where there is no autoplay to signal the video is playable). */
.proj-vctrl { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  display: flex; align-items: center; gap: 12px; padding: 14px 16px;
  background: linear-gradient(to top, rgba(0,0,0,0.6), transparent);
  opacity: 0; transform: translateY(8px); pointer-events: none;
  transition: opacity .25s var(--eds-ease), transform .25s var(--eds-ease); }
.proj-media--video:hover .proj-vctrl,
.proj-media--video:focus-within .proj-vctrl { opacity: 1; transform: none; pointer-events: auto; }
@media (hover: none) { .proj-vctrl { opacity: 1; transform: none; pointer-events: auto; } }
/* 44px, not 40: these sit over the video and are the smallest touch targets on
   the page, so they get the accessible minimum like every other control. */
.proj-vctrl__btn { flex: none; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: #fff; cursor: pointer; display: grid; place-items: center;
  transition: background .2s var(--eds-ease), color .2s var(--eds-ease); }
.proj-vctrl__btn:hover { background: rgba(255,255,255,0.16); color: var(--proj-blue); }
.proj-vctrl__btn:focus-visible { outline: 2px solid var(--proj-blue); outline-offset: 2px; }
.proj-vctrl__btn svg { width: 20px; height: 20px; fill: currentColor; display: block; }
.proj-vctrl .proj-vctrl__i-pause, .proj-vctrl .proj-vctrl__i-muted { display: none; }
.proj-vctrl.is-playing .proj-vctrl__i-play { display: none; }
.proj-vctrl.is-playing .proj-vctrl__i-pause { display: block; }
.proj-vctrl.is-muted .proj-vctrl__i-vol { display: none; }
.proj-vctrl.is-muted .proj-vctrl__i-muted { display: block; }
.proj-vctrl__scrub { flex: 1 1 auto; position: relative; height: 16px; cursor: pointer;
  display: flex; align-items: center; touch-action: none; }
.proj-vctrl__scrub::before { content: ""; position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%); height: 4px; border-radius: 999px; background: rgba(255,255,255,0.3); }
.proj-vctrl__scrub-fill { position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  height: 4px; width: 0; border-radius: 999px; background: var(--proj-blue); pointer-events: none; }
.proj-vctrl__scrub:focus-visible { outline: 2px solid var(--proj-blue); outline-offset: 3px; border-radius: 4px; }
.proj-vctrl__time { flex: none; min-width: 34px; text-align: center; font-family: var(--enttec-font-body);
  font-size: 12px; color: rgba(255,255,255,0.85); font-variant-numeric: tabular-nums; }

/* Controls / Lights: two-cell statement box on the dark Solution band. */
.proj-controls { display: grid; grid-template-columns: 1fr 1fr;
  border: 1px solid rgba(255,255,255,0.18); border-radius: var(--eds-radius-lg); overflow: hidden; }
.proj-controls__cell { padding: clamp(22px, 3vw, 38px); }
.proj-controls__cell + .proj-controls__cell { border-left: 1px solid rgba(255,255,255,0.18); }
.proj-controls__label { display: inline-block; font-size: 16px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--proj-blue); margin-bottom: 14px; font-weight: 600; }
/* NB: use `.proj p.proj-controls__stmt` (2 classes + element) so it outranks the
   generic `.proj p` 21px body rule, it's a <p>, so a single-class selector loses. */
.proj p.proj-controls__stmt { font-family: var(--enttec-font-display); font-weight: 400;
  font-size: clamp(24px, 2.8vw, 38px); line-height: 1.22; color: #fff; margin: 0; }
@media (max-width: 620px) {
  .proj-controls { grid-template-columns: 1fr; }
  .proj-controls__cell + .proj-controls__cell { border-left: 0; border-top: 1px solid rgba(255,255,255,0.18); }
}

/* System diagram: borderless, just the schematic (no grey frame). */
.proj-diagram { background: transparent; border: 0; box-shadow: none; padding: 0; max-width: 500px; margin-inline: auto; }
.proj-diagram__label { display: block; font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--proj-mid); margin-bottom: 14px; font-weight: 600; }
.proj-diagram img { width: 100%; height: auto; display: block; }

/* ========================== RESULT GALLERY ========================== */
/* Centre-focused, infinite, drag-scrollable strip: the centred slide is large,
   neighbours peek on both sides at reduced scale (JS sets .is-center). */
.proj-gallery { position: relative; margin-top: var(--eds-space-md); }
.proj-gallery__viewport { overflow: hidden; cursor: grab; }
.proj-gallery__viewport.is-dragging { cursor: grabbing; }
.proj-gallery__track { display: flex; align-items: flex-start; gap: 22px; list-style: none; margin: 0;
  padding: 0; will-change: transform; }
.proj-gallery__track.is-animating { transition: transform .55s var(--eds-ease); }
/* Suppresses BOTH track + slide transitions for the invisible loop-wrap teleport. */
.proj-gallery__track.no-anim,
.proj-gallery__track.no-anim .proj-gallery__slide { transition: none !important; }
/* EACH SLIDE KEEPS ITS OWN ASPECT RATIO: uniform image HEIGHT, natural width, no
   crop. Previously every slide was forced to 16/10 with object-fit:cover, which
   sliced the edges off anything that was not 16/10 (the artists' portrait lost
   its sides, the vertical shots lost their top and bottom).
   A common height is what keeps the strip orderly while widths vary; the carousel
   JS therefore MEASURES each slide instead of assuming one width, and remeasures
   as images load. See enttec-project-pages.js (metrics/nearestIndex). */
.proj-gallery__slide { flex: 0 0 auto; width: auto; margin: 0;
  transform: scale(.9); opacity: .4; transition: transform .55s var(--eds-ease), opacity .55s var(--eds-ease); }
.proj-gallery__slide.is-center { transform: scale(1); opacity: 1; }
.proj-gallery__slide figure { margin: 0; }
.proj-gallery__slide img { height: clamp(240px, 33vw, 480px); width: auto;
  max-width: min(86vw, 1040px); object-fit: contain; border-radius: var(--eds-radius);
  display: block; cursor: zoom-in; user-select: none; -webkit-user-drag: none; }
/* Captions sit under a variable-width image, so constrain them to the slide. */
.proj-gallery__slide figcaption { max-width: min(86vw, 1040px); }
.proj-gallery__viewport.is-dragging img { cursor: grabbing; }
.proj-gallery figcaption { margin-top: 14px; font-size: 14px; color: var(--proj-mid); text-align: center; }
.proj-gallery__arrow { position: absolute; top: 44%; transform: translateY(-50%);
  width: 52px; height: 52px; border-radius: 50%; border: 0; background: #fff; color: var(--proj-dark);
  cursor: pointer; display: grid; place-items: center; z-index: 3;
  box-shadow: 0 8px 22px -8px rgba(0,0,0,.45);
  transition: background .2s var(--eds-ease), color .2s var(--eds-ease), transform .2s var(--eds-ease); }
.proj-gallery__arrow svg { width: 22px; height: 22px; fill: none; stroke: currentColor;
  stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.proj-gallery__arrow:hover { background: var(--proj-dark); color: #fff; }
.proj-gallery__arrow:active { transform: translateY(-50%) scale(.94); }
.proj-gallery__arrow:focus-visible { outline: 3px solid var(--proj-blue); outline-offset: 3px; }
.proj-gallery__arrow--prev { left: 14px; }
.proj-gallery__arrow--next { right: 14px; }
/* Mobile: cap by width as well as height, so a wide panorama cannot run off the
   screen and a tall portrait cannot dominate the viewport. */
@media (max-width: 620px) {
  .proj-gallery__slide img { height: auto; max-height: 62vh; width: auto; max-width: 84vw; }
}

/* ===================== COMPANION STORY CARD =====================
   Link to the newsletter/story article behind the project, placed at the END of
   the Result section. Placement is evidence-led, not taste: NN/g's related-content
   guidelines say end the content with the related link and keep the scan path
   clear, and Lehmann et al. (2016), measuring in-body link clicks at scale, found
   links at the end of the text performed +35% against -28% near the start.

   Deliberately NOT a filled panel and NOT in a rail: "banner blindness" now covers
   anything that merely looks promotional, so this is a hairline rule plus the
   article's own image, which ties it to the piece just read. */
.proj-story {
  display: grid; grid-template-columns: minmax(0, 0.42fr) minmax(0, 0.58fr);
  gap: clamp(20px, 2.6vw, 38px); align-items: center;
  margin-top: clamp(36px, 4.5vw, 64px);
  padding-top: clamp(32px, 4vw, 48px);
  border-top: 1px solid var(--proj-light);
  text-decoration: none;
}
@media (max-width: 820px) { .proj-story { grid-template-columns: 1fr; gap: 20px; } }

.proj-story__media { position: relative; aspect-ratio: 16 / 10; border-radius: var(--eds-radius);
  overflow: hidden; box-shadow: 0 10px 30px -12px rgba(0,0,0,.35); }
.proj-story__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: transform 1s var(--eds-ease); }
.proj-story:hover .proj-story__media img { transform: scale(1.06); }

/* Element+class selectors so these beat the broad `.proj p` (17-21px) and
   `.proj h3` rules, same reason as .proj-product__name below. */
.proj p.proj-story__eyebrow { font-family: var(--enttec-font-display); font-size: 13px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--proj-blue); margin: 0 0 10px; }
.proj h3.proj-story__title { font-family: var(--enttec-font-display); font-weight: 600;
  font-size: clamp(22px, 2.3vw, 30px); line-height: 1.22; color: #111; margin: 0 0 12px;
  transition: color .2s var(--eds-ease); }
.proj-story:hover .proj-story__title { color: var(--proj-blue); }
.proj p.proj-story__teaser { font-size: clamp(16px, 1.25vw, 18px); line-height: 1.55;
  color: var(--proj-mid); margin: 0 0 16px; max-width: 56ch; }
.proj p.proj-story__meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-size: 13px; color: #767676; margin: 0 0 18px; }
.proj-story__meta .proj-story__dot { width: 4px; height: 4px; border-radius: 50%;
  background: var(--proj-light); flex: none; }
.proj-story__cta { font-family: var(--enttec-font-body); font-weight: 600; font-size: 15px;
  color: var(--proj-blue); display: inline-flex; align-items: center; gap: 8px; }
.proj-story__cta::after { content: " \2192"; transition: transform .25s var(--eds-ease); }
.proj-story:hover .proj-story__cta::after { transform: translateX(5px); }
.proj-story:focus-visible { outline: 3px solid var(--proj-blue); outline-offset: 6px; }

/* ========================== PRODUCTS ========================== */
/* "Products used" as editorial rows: large square product thumbnail (the images
   carry their own background, so no white tile), name + fuller description, and a
   "View product" link. "View all products" sits beside the heading. Generic
   .proj-product* classes so every project page reuses it. */
.proj .eds-section--tone-grey { padding-top: clamp(44px, 5.5vw, 76px); padding-bottom: clamp(44px, 5.5vw, 76px); }

/* Section head becomes a row: title left, "View all products" right. Override the
   DS section-head 760px cap so the button reaches the right edge of the rows. */
.proj-products-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; flex-wrap: wrap; max-width: none; }
.proj-products-head > div { min-width: 0; }
.proj-products-viewall { flex: none; }
/* This ghost button sits on the LIGHT grey band, so it must stay blue, not the
   white the general ghost rule gives. Extra specificity (a + 2 classes) to win. */
.proj a.proj-products-viewall.eds-btn--ghost { border-color: var(--proj-blue); color: var(--proj-blue); }
.proj a.proj-products-viewall.eds-btn--ghost:hover { background: var(--proj-blue); color: #fff; }

.proj-products { margin-top: clamp(20px, 2.5vw, 32px); border-top: 1px solid var(--proj-light); }

/* Long product lists collapse to the first three rows. Row-hiding, NOT the
   max-height fade the specs table uses: clipping a row mid-thumbnail looks like a
   rendering fault, and a whole-row cut needs no fragile pixel maths. The button
   says how many are hidden, so the count itself is the "there's more" cue. */
.proj-products-wrap.is-collapsed .proj-product:nth-child(n+4) { display: none; }

/* No rule under the LAST VISIBLE row: the list is bounded by the section below it,
   so a trailing hairline reads as an empty fourth row. Two cases, because which
   row is last depends on whether the list is collapsed:
     expanded  -> the real last child
     collapsed -> the third row, since 4+ are display:none and :last-child still
                  matches a hidden element. */
.proj-product:last-child { border-bottom: 0; }
.proj-products-wrap.is-collapsed .proj-product:nth-child(3) { border-bottom: 0; }
/* The show-more button is styled for the dark bands (white text and border), so
   on this light grey band it needs the ink treatment or it disappears. */
.proj .eds-section--tone-grey .proj-showmore { border-color: var(--proj-light); color: var(--proj-mid); }
.proj .eds-section--tone-grey .proj-showmore:hover { border-color: var(--proj-blue); color: var(--proj-blue); }
.proj-products-more { display: flex; justify-content: center; margin-top: 22px; }
/* Thumbnail box: SQUARE, matching the source crops. The shared homepage crops at
   website/pages/homepage/ are all 600x600 and framed for a square, so any other
   box shape means object-fit:cover throws away part of a deliberate crop. One
   variable drives both the grid column and the image so they cannot drift apart. */
.proj-products { --proj-thumb: clamp(160px, 13vw, 200px); }
.proj-product { display: grid; grid-template-columns: var(--proj-thumb) 1fr auto; gap: 32px; align-items: center;
  padding: 26px 8px; border-bottom: 1px solid var(--proj-light); text-decoration: none;
  transition: padding-left .25s var(--eds-ease); }
/* Win specificity over the global `.proj a { transition: color }` rule, which
   would otherwise clobber this transition and make the hover nudge instant. */
.proj a.proj-product { transition: padding-left .25s var(--eds-ease); }
.proj-product:hover { padding-left: 16px; }
.proj-product:hover .proj-product__name { color: var(--proj-blue); }
/* Row hover also gently zooms the thumbnail and slides the arrow, reusing the
   design-system card motion so it feels native. Both decorative: the padding
   nudge + name-to-blue already signal "this row is a link". */
.proj-product:hover .proj-product__thumb { transform: scale(1.04); }
.proj-product:hover .proj-product__cta::after { transform: translateX(4px); }
.proj-product:focus-visible { outline: 3px solid var(--proj-blue); outline-offset: 3px; }
.proj-product__thumb { width: var(--proj-thumb); height: var(--proj-thumb); border-radius: 12px;
  object-fit: cover; display: block; transition: transform .3s var(--eds-ease); }
/* Element+2-class selectors so the intended sizes actually win over the broad
   `.proj h3` / `.proj p` rules (which otherwise clobber them on specificity). */
.proj h3.proj-product__name { font-family: var(--enttec-font-display); font-weight: 600; font-size: 24px;
  line-height: 1.2; color: #111; margin: 0 0 6px; transition: color .2s var(--eds-ease); }
.proj p.proj-product__desc { font-size: 16px; line-height: 1.5; color: var(--proj-mid); margin: 0; max-width: 100ch; }
.proj-product__cta { justify-self: end; white-space: nowrap; font-weight: 600; font-size: 15px; color: var(--proj-blue); }
.proj-product__cta::after { content: " \2192"; display: inline-block; transition: transform .25s var(--eds-ease); }
@media (max-width: 640px) {
  /* Drops the "View product" column and shrinks the thumb; the variable keeps the
     grid column and the image box in step. */
  .proj-products { --proj-thumb: 118px; }
  .proj-product { grid-template-columns: var(--proj-thumb) 1fr; gap: 18px; }
  .proj-product__cta { grid-column: 2; justify-self: start; }
}

/* ========================== CLOSING CTA ========================== */
/* Mimics the live "Next Project" / "Talk to a lighting expert" cards: image card
   with name top-left + category pill top-right + heading and OUTLINE-PILL button
   bottom-left; and a bordered dark contact card with a blue outline-pill button. */
.proj .eds-cta__project { justify-content: space-between; min-height: clamp(380px, 30vw, 460px); }
/* Darken top + bottom of the image so the name/tag and heading/button stay legible. */
.proj .eds-cta__project::after {
  background: linear-gradient(180deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,.05) 32%, rgba(0,0,0,.1) 56%, rgba(0,0,0,.8) 100%);
}
.proj .eds-cta__top { display: flex; justify-content: space-between; align-items: flex-start; width: 100%; gap: 16px; }
.proj .eds-cta__meta { font-size: 14px; line-height: 1.35; color: #fff; margin: 0; }
.proj .eds-cta__meta strong { font-weight: 700; }
/* Category/sector label, NOT a button. Deliberately drops the blue border and
   pill shape (which read as an interactive affordance next to the real buttons)
   for a quiet, flat, uppercase metadata tag. */
.proj .eds-cta__tag { border: 0; background: rgba(255,255,255,0.16); color: #fff; border-radius: 6px;
  padding: 5px 11px; font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  white-space: nowrap; }
.proj .eds-cta__project h2 { font-size: clamp(26px, 3vw, 34px); margin: 0 0 4px; }
.proj .eds-cta__bottom { gap: 18px; }

.proj .eds-cta__contact { background: transparent; border: 1px solid rgba(255,255,255,0.18);
  border-radius: var(--eds-radius-lg); padding: clamp(28px, 4vw, 44px);
  justify-content: flex-end; align-items: flex-start; }
.proj .eds-cta__contact h2 { color: #fff; font-size: clamp(26px, 3vw, 34px); margin: 0 0 20px; }

/* Closing-CTA buttons use the design-system eds-btn component directly (ghost on
   the Next Project image card, primary on the contact card), so the page stays on
   one button system. No bespoke CTA button style here anymore. */

/* An eds-btn that is an ANCHOR loses the design system's transform/background
   transition to `.proj a { transition: color .15s }` up at line 57: `.proj a` is
   (0,1,1) and beats `.eds-btn`'s (0,1,0), so the declaration is replaced, not
   merged, and the DS -2px hover lift fires with no transition at all.
   That is why the two closing-CTA buttons felt different: "Get Inspired" is a
   <span> so `.proj a` never matches it and it keeps the smooth lift, while
   "Get In Touch" is an <a> and snapped. Restoring the DS transition on the anchor
   form fixes every link-button on the page (this one, "View all products"), not
   just the CTA. Same clobbering trap as `.proj a.proj-product` below. */
.proj a.eds-btn { transition: transform var(--eds-dur) var(--eds-ease),
                              background var(--eds-dur) var(--eds-ease),
                              border-color var(--eds-dur) var(--eds-ease),
                              color var(--eds-dur) var(--eds-ease); }

/* Arrow on the primary CTA only, reusing the .proj-product__cta idiom so the
   motion reads as native to the page. No box-shadow: a blue glow on the dark
   grey band read as muddy. */
.proj .eds-cta__contact a.eds-btn--primary::after {
  content: " \2192"; display: inline-block;
  transition: transform .25s var(--eds-ease); }
.proj .eds-cta__contact a.eds-btn--primary:hover::after { transform: translateX(4px); }

/* ========================== LIGHTBOX ========================== */
/* Full-screen image viewer, ported from the ELM 2026 product-page lightbox: a
   blurred dark backdrop above everything (the theme navbar is hidden while open,
   see below), the image scaled to fit, a rounded close button, an optional
   caption and a dismiss hint. Body scroll is locked while open (see the JS). */
.proj-lightbox { position: fixed; inset: 0; z-index: 2147483000; display: none;
  align-items: center; justify-content: center; padding: 4vh 4vw 84px;
  background: rgba(4,6,10,0.93); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  cursor: zoom-out; }
.proj-lightbox.is-open { display: flex; }
.proj-lightbox img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 12px; cursor: default; }
.proj-lightbox__close { position: fixed; top: 20px; right: 24px; width: 34px; height: 34px;
  border-radius: 9px; border: 0; background: rgba(255,255,255,0.08); color: #cfd6e0;
  font-size: 20px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: background .2s var(--eds-ease), color .2s var(--eds-ease); }
.proj-lightbox__close:hover { background: rgba(255,255,255,0.16); color: #fff; }
.proj-lightbox__cap { position: fixed; bottom: 50px; left: 50%; transform: translateX(-50%);
  text-align: center; color: var(--proj-light); font-size: 14px; max-width: 80vw; padding: 0 1rem; }
.proj-lightbox__hint { position: fixed; bottom: 26px; left: 50%; transform: translateX(-50%);
  font-family: var(--enttec-font-display); font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255,255,255,0.5); }
/* The zoomed image must sit above the theme's fixed navbar; hide the navbar while
   the lightbox is open so it never shows through or intercepts clicks. */
body.enttec-project-page:has(.proj-lightbox.is-open) #navbar {
  opacity: 0 !important; pointer-events: none !important; visibility: hidden !important;
}

@media (prefers-reduced-motion: reduce) {
  /* Blanket-kill animation/transition timing across the whole project layer
     (mirrors how the design system does it for `.eds *`), so every hover
     micro-animation degrades to an instant state change rather than motion. */
  .proj *, .proj *::before, .proj *::after { animation: none !important; transition: none !important; }
  .proj-lightbox, .proj-lightbox * { transition: none !important; }   /* lightbox lives outside .proj */
  /* No hero zoom, and critically NO leftover scale: the base rule holds the image
     at 1.08 waiting for the animation, so under reduced motion it must be reset to
     1 or the hero would sit permanently zoomed in. */
  .eds-hero > img,
  .eds-hero > img.is-hero-ready { animation: none !important; transform: none !important; }
  .proj-gallery__viewport { scroll-behavior: auto; }
  /* Remove the purely decorative hover transforms (thumb zoom, arrow slide,
     button lift) so nothing physically moves. Colour, the sub-nav underline
     and the focus outline still fire, so hover/focus stays legible. */
  .proj-product:hover .proj-product__thumb,
  .proj-product:hover .proj-product__cta::after,
  .proj-story:hover .proj-story__media img,
  .proj-story:hover .proj-story__cta::after,
  .proj .eds-cta__contact a.eds-btn--primary:hover::after,
  .proj-showmore:hover,
  .proj .eds-btn:hover { transform: none !important; }
  /* The arrow itself stays visible, it just doesn't slide. Background and colour
     still change on hover, so the affordance survives without motion. */
  /* No autoplay under reduced-motion, so keep the video controls always visible. */
  .proj-vctrl { opacity: 1 !important; transform: none !important; pointer-events: auto !important; }
}
