/* ============================================================================
   Editorial pages — technology.html and applications.html
   (.media-placeholder is also used by workflow.html for its comic-panel slots)

   These two pages were built with their own forest-green/parchment palette
   (--eco-forest #173f2a, --eco-paper #fbfdfb, --eco-gold …), a second type
   scale and their own copies of card, disclosure and section styles. That is
   why they read as a different website.

   Everything that had a component equivalent now uses it (.ep-section,
   .ep-card, .ep-disclosure, .ep-figure, .ep-page-header). What is left here is
   genuinely specific to these two pages: the mindmap diagram and the labelled
   media placeholders. (Back to top moved to ecopi-components.css when it went
   from this page to every page.) All colour comes from tokens.
   ========================================================================= */

/* ---- Modal images --------------------------------------------------------
   Project detail modals on the applications page show the project photo
   at the top of the body, full-width with rounded corners. */
.ep-modal-img {
  width: 100%;
  height: auto;
  border-radius: var(--ep-radius-md);
  margin-bottom: var(--ep-space-4);
}

/* ---- Project modals ------------------------------------------------------ */
.ep-project-modals .modal-dialog {
  margin: auto;
}

.ep-project-modals .modal-content {
  border-radius: var(--ep-radius-lg);
  border: none;
  box-shadow: var(--ep-shadow-lg);
}

.ep-project-modals .modal-header {
  background-color: #e8eff3;
  border-bottom: 1px solid var(--ep-border);
  padding: var(--ep-space-4) var(--ep-space-5);
}

.ep-project-modals .modal-title {
  font-family: var(--ep-font-body);
  font-size: var(--ep-h4);
  font-weight: 600;
  line-height: var(--ep-leading-snug);
  color: var(--ep-text);
}

.ep-project-modals .modal-body {
  padding: var(--ep-space-5);
}

/* Bottom fade over the scrollable body, signalling there's more text below
   to scroll to — same idea as .ep-comic__fade on workflow.html (journey.css),
   mirrored onto the vertical axis these modals scroll on. Bootstrap already
   gives .modal-dialog-scrollable .modal-content position:relative and
   overflow:hidden, so this only needs the overlay itself. Taller than a
   plain edge fade, with an opaque "shelf" at the very bottom rather than a
   fade all the way through — a thin even fade blends into whatever text or
   whitespace happens to sit behind it and reads as nothing at all.

   Gated on .ep-scroll-hint, which modal-scroll-hint.js toggles: unlike the
   comic (always overflowing on small screens), these modals hold a varying
   amount of text and are often read to the end, so a fade/arrow that never
   goes away would end up pointing at nothing. */
.ep-project-modals .modal-content.ep-scroll-hint::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 4.5rem;
  border-radius: 0 0 var(--ep-radius-lg) var(--ep-radius-lg);
  background: linear-gradient(to top, var(--bs-modal-bg, #fff) 40%, transparent);
  pointer-events: none;
}

/* Explicit "scroll for more" chevron riding on top of the fade, so the
   affordance doesn't depend on the fade alone being noticed — same pairing
   as .ep-comic__hint next to .ep-comic__fade, adapted to a centred badge
   since this hint points down rather than sideways. Painted after (and so
   on top of) the ::before fade in default stacking order, no z-index
   needed. */
.ep-project-modals .modal-content.ep-scroll-hint::after {
  content: "\2193";
  position: absolute;
  left: 50%;
  bottom: 0.75rem;
  transform: translateX(-50%);
  width: 1.75rem;
  height: 1.75rem;
  line-height: 1.75rem;
  text-align: center;
  border-radius: 999px;
  background: rgba(14, 42, 50, 0.72);
  color: #fff;
  font-size: 0.95rem;
  pointer-events: none;
}

/* ---- Main section images with rounded corners ---------------------------- */
.ep-category-row__media img {
  border-radius: var(--ep-radius-lg);
  width: 100%;
  height: auto;
}

/* ---- Media placeholder ---------------------------------------------------
   Stands in for photography that does not exist yet. Deliberately reads as a
   placeholder rather than pretending to be an image. */

.media-placeholder,
.ep-card__media--label {
  display: grid;
  place-items: center;
  padding: var(--ep-space-5);
  font-family: var(--ep-font-body);
  font-size: var(--ep-text-xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-align: center;
  text-transform: uppercase;
}

/* The card variant keeps the filled dark panel: on the applications page it
   sits in a row of real cards and has to carry the weight an image would. */
.ep-card__media--label {
  background: var(--ep-bg-inverse);
  color: rgba(255, 255, 255, 0.82);          /* 8.4:1 on --ep-bg-inverse */
}

/* The standalone one does not. Six filled dark slabs down the ecoPi page read
   as a design decision — heavy, and the same colour as the "Produktplattform"
   band that was removed for being exactly that. An outlined frame says "a
   photograph belongs here" instead, and stops absent content from dominating
   the page it is missing from. */
.media-placeholder {
  min-height: 24rem;
  border: 1px dashed var(--ep-border-strong);
  border-radius: var(--ep-radius-lg);
  background: var(--ep-bg-card);
  color: var(--ep-text-muted);               /* 5.28:1 on card */
}

@media (max-width: 991.98px) {
  .media-placeholder { min-height: 18rem; }
}

@media (max-width: 575.98px) {
  .media-placeholder { min-height: 15rem; }
}

/* ---- Bilingual figures ---------------------------------------------------
   Images that exist in separate German and English files. Only the one
   matching the active language is shown; the other is kept in the DOM but
   hidden so the figure keeps its layout. Mirrors the .ep-comic pattern in
   journey.css. */
.ep-figure img[data-lang-text] {
  display: none;
}

html[data-lang="de"] .ep-figure img[data-lang-text="de"],
html[data-lang="en"] .ep-figure img[data-lang-text="en"] {
  display: block;
}

/* ---- ecoPi page: feature lists ------------------------------------------ */

.ep-lead {
  margin-bottom: 20px;
}

.feature-list {
  border-bottom: 1px solid var(--ep-border);
}

/* Low-key follow-on link after a section's feature list, e.g. dashboard.html
   pointing to technology.html — not a competing CTA, so it stays secondary
   and sits close to the text column rather than the page's closing CTA. */
.ep-feature-followup {
  margin-top: 5rem;
}

.ep-feature-followup--right {
  text-align: right;
}

/* On mobile the button column is full-width (col-12); center it there,
   but keep the right alignment on desktop. */
@media (max-width: 991.98px) {
  .ep-feature-followup--right {
    text-align: center;
  }
}

/* ---- Applications page: category bullet points -------------------------- */

.category-points {
  margin: 0;
  padding-left: 1.25rem;
  color: var(--ep-text-secondary);
}

.category-points li + li {
  margin-top: var(--ep-space-3);
}

/* Two-column layout: bullet points on the left, inline carousel on the right.
   The carousel height is standardised across all three sections so they line
   up visually regardless of how much text each section has. */
.ep-category-row {
  display: grid;
  grid-template-columns: 1fr 28rem;
  gap: var(--ep-space-7);
  align-items: start;
  margin-bottom: var(--ep-space-7);
}

.ep-category-row__text > h2 {
  margin-bottom: var(--ep-space-4);
}

.ep-category-row__media {
  position: sticky;
  top: var(--ep-space-5);
}

@media (max-width: 991.98px) {
  .ep-category-row {
    grid-template-columns: 1fr;
    gap: var(--ep-space-5);
  }

  .ep-category-row__media {
    position: static;
  }
}

/* ---- Applications page: inline gallery carousel ------------------------- */

.ep-gallery-inline {
  position: relative;
  border-radius: var(--ep-radius-md);
  overflow: hidden;
  cursor: pointer;
  box-shadow: var(--ep-shadow-sm, 0 1px 3px rgba(0, 0, 0, 0.12));
  transition: box-shadow var(--ep-duration-fast) var(--ep-ease);
}

.ep-gallery-inline:hover,
.ep-gallery-inline:focus-visible {
  box-shadow: var(--ep-shadow-md, 0 4px 12px rgba(0, 0, 0, 0.15));
  outline: none;
}

.ep-gallery-inline__carousel .carousel-inner {
  border-radius: var(--ep-radius-md);
}

/* The image and placeholder share a fixed height so all three sections'
   carousels line up regardless of the underlying photo's dimensions. */
.ep-gallery-inline__img,
.ep-gallery-inline__frame {
  display: block;
  width: 100%;
  height: 16rem;
  object-fit: cover;
}

.ep-gallery-inline__frame {
  display: grid;
  place-content: center;
  gap: var(--ep-space-2);
  padding: var(--ep-space-4);
  background: var(--ep-bg-inverse);
  text-align: center;
}

.ep-gallery-inline__frame-label {
  color: rgba(255, 255, 255, 0.82);
  font-size: var(--ep-text-xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.ep-gallery-inline__frame-note {
  color: rgba(255, 255, 255, 0.6);
  font-size: var(--ep-text-xs);
  font-style: italic;
}

/* Dark disc controls, same treatment as the modal gallery. */
.ep-gallery-inline .carousel-control-prev,
.ep-gallery-inline .carousel-control-next {
  width: 2.5rem;
  opacity: 0;
  transition: opacity var(--ep-duration-fast) var(--ep-ease);
}

.ep-gallery-inline:hover .carousel-control-prev,
.ep-gallery-inline:hover .carousel-control-next,
.ep-gallery-inline:focus-within .carousel-control-prev,
.ep-gallery-inline:focus-within .carousel-control-next {
  opacity: 1;
}

.ep-gallery-inline .carousel-control-prev-icon,
.ep-gallery-inline .carousel-control-next-icon {
  width: 2rem;
  height: 2rem;
  padding: 0.5rem;
  border-radius: 50%;
  background-color: rgba(6, 26, 32, 0.72);
  background-size: 0.9rem 0.9rem;
  transition: background-color var(--ep-duration-fast) var(--ep-ease);
}

.ep-gallery-inline .carousel-control-prev:hover .carousel-control-prev-icon,
.ep-gallery-inline .carousel-control-next:hover .carousel-control-next-icon {
  background-color: var(--ep-bg-inverse);
}

.ep-gallery-inline__footer {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ep-space-2);
  padding: var(--ep-space-3) var(--ep-space-4);
  background: var(--ep-bg-card);
  border-top: 1px solid var(--ep-border);
}

.ep-gallery-inline__caption {
  font-size: var(--ep-text-sm);
  color: var(--ep-text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ep-gallery-inline__hint {
  flex: none;
  font-size: var(--ep-text-xs);
  color: var(--ep-text-muted);
  white-space: nowrap;
}

@media (max-width: 575.98px) {
  .ep-gallery-inline__img,
  .ep-gallery-inline__frame {
    height: 12rem;
  }

  .ep-gallery-inline .carousel-control-prev,
  .ep-gallery-inline .carousel-control-next {
    display: none;
  }
}

/* ---- Applications page: project card extras ----------------------------- */

.project-stub,
.project-partner {
  /* Was #7c8880 — 3.69:1 on white, a real AA failure flagged in the audit. */
  color: var(--ep-text-muted);              /* 5.28:1 on card */
  font-size: var(--ep-text-sm);
}

.project-stub {
  margin: 0;
  font-style: italic;
}

.project-partner {
  display: block;
  margin-top: var(--ep-space-2);
}

.project-link-label {
  display: inline-block;
  margin-top: var(--ep-space-2);
  color: var(--ep-primary);
  font-weight: 700;
  text-decoration: none;
}

/* Bold colour alone still read as a caption rather than a link — a
   permanent, thin, offset underline is the one signal browsers use for
   links themselves, so it reads as clickable without adding visual weight.
   Thicker on hover as the interactive confirmation. */
a.project-link-label {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

a.project-link-label:hover {
  text-decoration-thickness: 2px;
}

/* Small diagonal arrow marking these as external links — the label alone
   (bold, coloured) read too much like a caption rather than something
   clickable. Only on the <a> variant: modal-proj-6 reuses this class on a
   plain <span> for a project with no external page. */
a.project-link-label::after {
  content: "\2197";
  display: inline-block;
  margin-left: 0.3em;
}

/* ---- Applications page: mindmap ----------------------------------------- */

.mindmap-nav {
  padding-block: var(--ep-section-y);
  border-bottom: 1px solid var(--ep-border);
}

.mindmap-diagram {
  position: relative;
  width: 100%;
  max-width: 640px;
  margin-inline: auto;
  aspect-ratio: 100 / 70;
}

/* 42% of a 640px diagram is ~269px, against a 490px source, so there is still
   resolution in hand. Do not push much past this: the bubbles are positioned
   from percentages in the markup and the device starts crowding the lines. */
.mindmap-device {
  position: absolute;
  left: 50%;
  top: 53%;
  width: 42%;
  height: auto;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 10px 18px rgba(14, 42, 50, 0.14));
}

.mindmap-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.mindmap-lines line {
  stroke: var(--ep-primary);
  stroke-width: 0.5;
  opacity: 0.55;
}

.mindmap-lines line.dashed {
  stroke: var(--ep-border-strong);
  stroke-dasharray: 2 1.6;
  opacity: 1;
}

.mindmap-bubble {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  max-width: 10.5rem;
  min-height: 44px;                          /* WCAG 2.2 target size */
  padding: var(--ep-space-3) var(--ep-space-4);
  border: 1px solid var(--ep-border);
  border-radius: var(--ep-radius-lg);
  background: var(--ep-bg-card);
  color: var(--ep-primary);
  font-family: var(--ep-font-body);
  font-size: var(--ep-text-sm);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  transform: translate(-50%, -50%);
  box-shadow: var(--ep-shadow-sm);
  transition: transform var(--ep-duration-fast) var(--ep-ease),
              box-shadow var(--ep-duration-fast) var(--ep-ease),
              border-color var(--ep-duration-fast) var(--ep-ease);
}

.mindmap-bubble:hover {
  border-color: var(--ep-primary);
  background: var(--ep-primary-faint);
  color: var(--ep-primary-hover);
  transform: translate(-50%, -50%) translateY(-2px);
  box-shadow: var(--ep-shadow-md);
}

/* The centre bubble is the contact call to action, not a category. */
.mindmap-bubble.cta {
  width: 8.5rem;
  height: 8.5rem;
  max-width: none;
  border-color: var(--ep-accent);
  border-radius: 50%;
  background: var(--ep-accent-faint);
  color: var(--ep-accent);                   /* 6.00:1 on card */
  font-family: var(--ep-font-heading);
  font-size: var(--ep-text-base);
  font-style: italic;
  font-weight: 600;
}

.mindmap-bubble.cta:hover {
  background: var(--ep-accent);
  color: #fff;
}

/* Below the small breakpoint the diagram stops being a diagram.
   The bubbles are absolutely positioned from inline percentages and pulled
   back by translate(-50%, -50%), so the leftmost one hung 9px off the left
   edge at 320px — and no amount of shrinking fixes that, because the
   percentages are in the markup. Becoming a plain stack of links is also
   simply easier to use on a phone than a spatial diagram. */
@media (max-width: 575.98px) {
  .mindmap-diagram {
    display: flex;
    flex-direction: column;
    gap: var(--ep-space-3);
    aspect-ratio: auto;
    max-width: none;
  }

  .mindmap-lines,
  .mindmap-device {
    display: none;
  }

  .mindmap-bubble,
  .mindmap-bubble.cta {
    position: static;
    width: auto;
    height: auto;
    max-width: none;
    border-radius: var(--ep-radius-md);
    transform: none;
    text-align: left;
    justify-content: flex-start;
  }

  .mindmap-bubble:hover,
  .mindmap-bubble.cta:hover {
    transform: none;
  }
}

/* ---- Applications page: gallery ------------------------------------------
   Trigger button plus the modal carousel it opens. Behaviour comes from the
   Bootstrap bundle the base layout already loads; everything here is styling.
   See src/_includes/partials/gallery.njk. */

.ep-gallery-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--ep-space-2);
}

/* Count of photographs, so the button says how much is behind it. */
.ep-gallery-trigger__count {
  padding: 0 0.45em;
  border-radius: var(--ep-radius-sm);
  background: var(--ep-bg-faint);
  color: var(--ep-text-secondary);
  font-size: var(--ep-text-xs);
  font-weight: 700;
  line-height: 1.6;
}

.ep-gallery .modal-body {
  padding: var(--ep-space-5);
}

.ep-gallery__figure {
  margin: 0;
}

/* The image and the placeholder share this box, so swapping a placeholder for
   a real photograph cannot change the carousel's height.  A viewport-relative
   height keeps the modal — header, caption, indicators, footer — on screen
   without the modal itself scrolling. */
.ep-gallery__img,
.ep-gallery__frame {
  display: block;
  width: 100%;
  height: 55vh;
  border-radius: var(--ep-radius-md);
  object-fit: cover;
}

.ep-gallery__frame {
  display: grid;
  place-content: center;
  gap: var(--ep-space-2);
  padding: var(--ep-space-6);
  background: var(--ep-bg-inverse);
  text-align: center;
}

.ep-gallery__frame-label {
  color: rgba(255, 255, 255, 0.82);          /* 8.4:1 on --ep-bg-inverse */
  font-size: var(--ep-text-xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.ep-gallery__frame-note {
  color: rgba(255, 255, 255, 0.6);
  font-size: var(--ep-text-xs);
  font-style: italic;
}

.ep-gallery__caption {
  display: flex;
  align-items: baseline;
  gap: var(--ep-space-3);
  padding-top: var(--ep-space-4);
  color: var(--ep-text-secondary);
  font-size: var(--ep-text-sm);
}

.ep-gallery__counter {
  flex: none;
  color: var(--ep-text-muted);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

/* Bootstrap's controls are white-on-image by default, which vanishes against a
   light photograph. Give them their own dark discs instead. */
.ep-gallery .carousel-control-prev,
.ep-gallery .carousel-control-next {
  align-items: flex-start;
  width: 4rem;
  padding-top: 25%;
  opacity: 1;
}

.ep-gallery .carousel-control-prev-icon,
.ep-gallery .carousel-control-next-icon {
  width: 2.75rem;
  height: 2.75rem;
  padding: 0.75rem;
  border-radius: 50%;
  background-color: rgba(6, 26, 32, 0.72);
  background-size: 1.25rem 1.25rem;
  transition: background-color var(--ep-duration-fast) var(--ep-ease);
}

.ep-gallery .carousel-control-prev:hover .carousel-control-prev-icon,
.ep-gallery .carousel-control-next:hover .carousel-control-next-icon,
.ep-gallery .carousel-control-prev:focus-visible .carousel-control-prev-icon,
.ep-gallery .carousel-control-next:focus-visible .carousel-control-next-icon {
  background-color: var(--ep-bg-inverse);
}

/* Indicators sit under the figure rather than over the image, where they would
   collide with the caption. */
.ep-gallery .carousel-indicators {
  position: static;
  margin: var(--ep-space-4) 0 0;
}

.ep-gallery .carousel-indicators [data-bs-target] {
  width: 0.5rem;
  height: 0.5rem;
  margin-inline: 0.25rem;
  border: none;
  border-radius: 50%;
  background-color: var(--ep-border);
  opacity: 1;
}

.ep-gallery .carousel-indicators .active {
  background-color: var(--ep-primary);
}

@media (max-width: 575.98px) {
  /* No room for side controls next to the image at this width; the indicators
     and swipe remain. */
  .ep-gallery .carousel-control-prev,
  .ep-gallery .carousel-control-next {
    display: none;
  }

  .ep-gallery__img,
  .ep-gallery__frame {
    height: 45vh;
  }
}
