/*
  Homepage stylesheet. Loaded only on / via the pageStylesheets field in
  src/index.njk.

  The homepage is NOT a case page: it does not load case-shared.css and
  none of its rhythm values (spacing, type scale) come from the case
  pages. Every value below is read from reference/homepage-bron.html
  (an in-project copy of the finished Claude Design export's rendered
  markup) and reference/css-en-js/homepage-logic.js, not estimated off
  the screenshot. Where a value already has a token in tokens.css
  (colors, fonts, the canvas), this file uses that token; values that
  only exist on this page (the muted hero grey, the card border grey,
  the conic-gradient stops) stay literal here, each commented with
  where it came from.

  Section order below matches src/index.njk top to bottom: sticky
  contact bar, hero, cases label + card list, currently/Rabobank
  teaser, worked-with marquee. The five locked interactions this file
  and home.js implement together:
    1. Scroll reveal (fade + rise, one-shot, IntersectionObserver)
    2. Worked-with marquee (seamless rAF loop)
    3. Sticky contact bar (fades in once case 1 reaches the header)
    4. Case card hover (lift + spinning conic-gradient glow ring)
    5. Scroll cue click (scrolls down to the case list)
*/

/* ==========================================================================
   Homepage-only sticky header
   The reference's sticky contact bar hangs directly off a sticky
   header (bar top = header height). The site header is not sticky
   sitewide yet, that lands in the later integration session (see
   docs/Handoff_Code_Fase.md, build order step 7), so this rule makes
   it sticky ONLY on this page. Because home.css is only ever loaded
   here, case pages and About keep the current non-sticky header
   untouched. When step 7 makes the header sticky everywhere, this
   rule moves into base.css and can be deleted from here.
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  /* The header already has a white background from base.css; sticky
     positioning alone would let page content show through at the
     seam while scrolling if that were ever removed, so it is
     repeated here defensively. */
  background: var(--color-bg);
}

/* ==========================================================================
   Canvas override
   <main class="site-canvas"> (base.njk) already applies 120px side
   padding sitewide. On the homepage, the section dividers themselves
   need to run the full 1440px canvas width (matching
   reference/screenshots/homepage.png), with each section applying its
   own 120px inset instead. This override is scoped to this page only
   via home.css's own load scope, so case pages (which rely on the
   inherited 120px main padding) are unaffected.
   ========================================================================== */
main.site-canvas {
  padding-inline: 0;
  max-width: none;
}

/* Re-apply the canvas's own max-width as an inner cap, so content
   still cannot exceed 1440px on very wide screens, matching the
   sitewide structural rule in CLAUDE.md: content sits in a
   fixed-width canvas, centered, extra space shows the background
   color only. */
.home-canvas {
  max-width: var(--canvas-width);
  margin-inline: auto;
}

/* ==========================================================================
   1. STICKY CONTACT BAR
   Sits in a zero-height sticky slot directly under the sticky header
   (home.js sets the slot's top to the header's measured height). Off
   by default; home.js fades it in once the first case card's top
   edge reaches the header's bottom edge, and back out when scrolling
   up past that point. See home.js for the trigger and the reveal
   timing (opacity/translateY over 1250ms, matching the scroll-reveal
   effect below, same split easing).
   ========================================================================== */
.home-bar-slot {
  position: sticky;
  top: 0;
  height: 0;
  z-index: 20;
  overflow: visible;
}

.home-bar {
  display: flex;
  justify-content: center;
  padding: 14px 120px 0;
  /* Start hidden; home.js flips these two custom properties on and
     off, so the transition only ever needs writing once, here. */
  opacity: 0;
  transform: translateY(-18px);
  transition: opacity 1250ms ease, transform 1250ms cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}

.home-bar--on {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.home-bar__pill {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 10px 12px 10px 10px;
  background: var(--color-bg);
  /* #D8DAE0: card/pill border grey, only used on this page, no token. */
  border: 1px solid #d8dae0;
  border-radius: 999px;
  box-shadow: 0 18px 38px -22px rgba(17, 17, 17, 0.35);
  width: max-content;
  max-width: 100%;
}

.home-bar__avatar {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  flex: 0 0 56px;
}

.home-bar__identity {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-right: 4px;
}

.home-bar__name {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--color-title);
  white-space: nowrap;
}

.home-bar__role {
  font-size: 13px;
  color: var(--color-muted);
  white-space: nowrap;
}

.home-bar__divider {
  width: 1px;
  height: 34px;
  /* #E1E4EA: hairline divider inside the pill, only used here. */
  background: #e1e4ea;
  flex: 0 0 1px;
}

.home-bar__status {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 14px;
  /* #4A505C: status-line grey, only used here. */
  color: #4a505c;
  white-space: nowrap;
}

.home-bar__status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  /* #1FA971: the "open to a conversation" green, only used here. */
  background: #1fa971;
  flex: 0 0 8px;
}

.home-bar__cta {
  display: inline-flex;
  align-items: center;
  padding: 12px 24px;
  border-radius: 999px;
  background: var(--color-accent);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  white-space: nowrap;
  transition: background 240ms ease;
}

.home-bar__cta:hover {
  /* #0B33A9: the reference's confirmed accent hover-darken, only used
     here (no other page has a filled accent button to hover). */
  background: #0b33a9;
}

/* ==========================================================================
   2. HERO
   Not marked data-reveal: the reveal script in home.js explicitly
   skips anything already above 90% of the viewport height on load,
   which the hero always is, so it is simply left off the reveal list
   rather than relying on that runtime skip.
   ========================================================================== */
.home-hero {
  position: relative;
  overflow: hidden;
  background: var(--color-bg);
  padding: 104px 120px 44px;
}

.home-hero__grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 440px;
  gap: 76px;
  align-items: center;
}

.home-hero__text {
  text-align: right;
  justify-self: end;
}

.home-hero__title {
  margin: 0;
  max-width: 820px;
  margin-left: auto;
  font-size: 60px;
  line-height: 1.04;
  letter-spacing: -0.032em;
  font-weight: 600;
  color: var(--color-title);
  text-wrap: balance;
}

.home-hero__subline {
  margin: 26px 0 0;
  max-width: 640px;
  margin-left: auto;
  font-size: 21px;
  line-height: 1.45;
  font-weight: 400;
  /* #8A8F98: muted hero subline grey, lighter than --color-muted,
     only used here, kept distinct from the sitewide muted tier on
     purpose (matches the reference exactly). */
  color: #8a8f98;
  text-wrap: pretty;
}

.home-hero__media {
  position: relative;
  width: 440px;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  /* #F4EFE7: warm portrait backdrop tint, matches the photo's own
     background so the edges disappear, only used here. */
  background: #f4efe7;
  /* Square corners: the reference has no radius on the hero image.
     The sitewide 12px hero radius (docs/iteration-protocol.md) is
     part of the case-page Format A/B hero system; this page was
     never part of that system and follows its own reference instead. */
}

.home-hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* 12% down from the top keeps the face centred in the 4:5 box
     rather than the geometric middle, matching the source photo's
     framing. */
  object-position: 50% 12%;
  display: block;
}

/* ----- Scroll cue -----
   A calm, looping vertical glow, top to bottom, restarting, not a
   spinner. Structure: a static faint rail (the full travel path) plus
   two moving layers, a blurred halo and a sharper core, both running
   the same pfCueGlow keyframe (see tokens.css companion below) offset
   by nothing, i.e. moving together as one glowing point. */
.home-cue-row {
  display: flex;
  justify-content: center;
  padding-top: 36px;
}

.home-cue {
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: 14px 24px;
  display: block;
}

.home-cue__rail {
  position: relative;
  display: block;
  width: 14px;
  height: 56px;
  overflow: hidden;
}

.home-cue__track {
  position: absolute;
  left: 6px;
  top: 0;
  width: 2px;
  height: 56px;
  background: linear-gradient(
    180deg,
    rgba(180, 190, 205, 0),
    rgba(180, 190, 205, 0.55),
    rgba(180, 190, 205, 0)
  );
}

.home-cue__halo {
  position: absolute;
  left: 5px;
  top: 0;
  width: 4px;
  height: 34px;
  border-radius: 3px;
  background: radial-gradient(
    44% 40% at 50% 50%,
    rgba(160, 192, 255, 0.85),
    rgba(78, 134, 238, 0.28) 62%,
    rgba(78, 134, 238, 0) 100%
  );
  filter: blur(1.1px);
  animation: pfCueGlow 3900ms cubic-bezier(0.45, 0, 0.55, 1) infinite;
}

.home-cue__core {
  position: absolute;
  left: 6px;
  top: 0;
  width: 2px;
  height: 28px;
  border-radius: 2px;
  background: rgba(78, 134, 238, 0.9);
  filter: blur(0.4px);
  animation: pfCueGlow 3900ms cubic-bezier(0.45, 0, 0.55, 1) infinite;
}

@keyframes pfCueGlow {
  0% {
    transform: translateY(-18px) scaleY(0.7);
    opacity: 0;
  }
  25% {
    opacity: 1;
  }
  75% {
    opacity: 1;
  }
  100% {
    transform: translateY(34px) scaleY(0.7);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .home-cue__halo,
  .home-cue__core {
    animation: none;
    opacity: 1;
  }
}

/* ==========================================================================
   3. CASES
   Label row carries data-work-anchor (the scroll cue's target) and
   the top divider. Card list below it: three real cards plus one
   commented-out template card in index.njk, see that file's own
   comment for exactly what to fill in to activate a fourth case.
   ========================================================================== */
.home-cases-label-row {
  border-top: 1px solid var(--color-line);
  padding: 30px 120px 26px;
}

.home-cases-list {
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding: 0 120px 88px;
}

/* ----- Case card -----
   Two-layer hover effect built on @property --pf-a: a spinning
   conic-gradient ring behind the card (sharp) plus a second, blurred
   copy of the same ring (halo), both faded in via opacity so no
   layout shift happens on hover. The card itself lifts on hover with
   a blue drop shadow. All values (lift distance, shadow, ring inset/
   blur/opacity, spin duration) are the reference's confirmed final
   numbers, not adjustable without breaking the Designer-check grep in
   docs/iteration-protocol.md. */
@property --pf-a {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes pfSpin {
  to {
    --pf-a: 360deg;
  }
}

.home-card {
  position: relative;
  /* Lift and shadow both animate on :hover/:focus-within so keyboard
     focus gets the same feedback as a mouse hover, see the
     Interaction-check note in docs/iteration-protocol.md. */
  transition: transform 620ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 620ms ease;
}

.home-card:hover,
.home-card:focus-within {
  transform: translateY(-10px);
  box-shadow: 0 26px 46px -26px rgba(14, 66, 216, 0.4);
}

.home-card__ring,
.home-card__glow {
  position: absolute;
  background: conic-gradient(
    from var(--pf-a),
    /* long light-blue arc, one travelling peak; the dim point stays
       a pale grey, never near black, per the reference's own comment */ #eaedf2
      0deg,
    #dce6fa 60deg,
    #b9cdf7 120deg,
    #93b4f5 190deg,
    #6e9cf2 240deg,
    #4e86ee 270deg,
    #6e9cf2 300deg,
    #93b4f5 330deg,
    #c8d7f8 350deg,
    #eaedf2 360deg
  );
  animation: pfSpin 5.2s linear infinite;
  opacity: 0;
  transition: opacity 620ms ease;
  pointer-events: none;
  z-index: 0;
}

.home-card__ring {
  inset: -2px;
  border-radius: 3px;
}

.home-card__glow {
  inset: -5px;
  border-radius: 5px;
  filter: blur(7px);
  opacity: 0;
}

.home-card:hover .home-card__ring,
.home-card:focus-within .home-card__ring {
  opacity: 1;
}

.home-card:hover .home-card__glow,
.home-card:focus-within .home-card__glow {
  opacity: 0.7;
}

/* @property fallback, per CLAUDE.md and docs/Handoff_Code_Fase.md:
   browsers without @property support (e.g. older Firefox) ignore the
   whole @property block above and never animate --pf-a, so the conic
   gradient renders as a static image frozen at its 0deg starting
   angle. That alone is a perfectly reasonable static ring, no further
   fallback rule is needed: the gradient's own stop list already reads
   fine held still, it just does not spin. */

.home-card__link {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 580px 1fr;
  align-items: stretch;
  background: var(--color-bg);
  border: 1px solid #d8dae0;
}

/* Image-right modifier: flips the grid so the image cell renders
   second. Used on the Frits card (the middle of the three), matching
   the reference's left/right/left alternation. */
.home-card__link--image-right {
  grid-template-columns: 1fr 580px;
}

.home-card__link--image-right .home-card__media {
  order: 2;
}

.home-card__media {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 10;
  /* #F1F4FA: pale card-image backdrop, matches the collage images'
     own background so their edges disappear against it. */
  background: #f1f4fa;
  /* Square corners, see .home-hero__media's comment above for why. */
}

.home-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  display: block;
}

.home-card__body {
  padding: 48px 48px 48px 56px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.home-card__link--image-right .home-card__body {
  padding: 48px 56px 48px 48px;
}

.home-card__eyebrow {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent);
}

.home-card__title {
  margin: 18px 0 0;
  font-size: 30px;
  line-height: 1.26;
  letter-spacing: -0.025em;
  font-weight: 500;
  color: var(--color-title);
  text-wrap: pretty;
}

.home-card__cta {
  display: inline-block;
  margin-top: 26px;
  font-size: 15px;
  font-weight: 500;
  color: var(--color-accent);
}

/* ==========================================================================
   4. CURRENTLY / RABOBANK TEASER
   Deliberately does NOT reuse .home-card's border/hover treatment:
   per docs/Designbriefing_Portfolio.md this block must read as
   unmistakably non-clickable (no card border, no hover state, no
   arrow), so it does not get mistaken for a fourth case.
   ========================================================================== */
.home-currently {
  background: var(--color-bg);
  padding: 88px 120px;
  border-top: 1px solid var(--color-line);
}

.home-currently__grid {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 64px;
  align-items: start;
}

.home-currently__label {
  padding-top: 6px;
  color: var(--color-accent);
}

.home-currently__block {
  border-left: 3px solid var(--color-accent);
  padding-left: 32px;
  max-width: 840px;
}

.home-currently__logo {
  display: block;
  height: 34px;
  width: auto;
  margin-bottom: 18px;
}

.home-currently__role {
  margin: 0;
  font-size: 23px;
  line-height: 1.35;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--color-title);
}

.home-currently__meta {
  margin: 8px 0 0;
  font-size: 18px;
  line-height: 1.4;
  color: var(--color-muted);
}

.home-currently__body {
  margin: 26px 0 0;
  font-size: 19px;
  line-height: 1.6;
  color: var(--color-body);
  text-wrap: pretty;
}

/* ==========================================================================
   5. WORKED WITH MARQUEE
   Track holds the 11 logos TWICE (see index.njk), which is what makes
   the half-scroll-width wrap in home.js seamless: at pos = half the
   track has scrolled exactly one full set, and the second copy is
   sitting exactly where the first one started. This is the confirmed
   fix for the earlier "doesn't loop seamlessly" bug (see
   docs/Ideas.md), so the double-list markup and the half-width wrap
   in home.js must always change together.
   ========================================================================== */
.home-worked-with {
  background: var(--color-bg);
  padding: 80px 120px 96px;
  border-top: 1px solid var(--color-line);
}

.home-worked-with__label {
  display: block;
}

.home-marquee {
  position: relative;
  margin-top: 36px;
  padding: 0 58px;
}

.home-marquee__viewport {
  overflow: hidden;
  padding: 0 24px;
  /* Fades the two outer edges of the row to transparent so logos
     don't appear to clip abruptly as they scroll past the mask. */
  mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 96px,
    #000 calc(100% - 96px),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 96px,
    #000 calc(100% - 96px),
    transparent 100%
  );
}

.home-marquee__track {
  display: flex;
  align-items: center;
  gap: 72px;
  width: max-content;
  will-change: transform;
}

.home-marquee__track img {
  height: auto;
  display: block;
  flex: 0 0 auto;
}

.home-marquee__nudge {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  appearance: none;
  background: var(--color-bg);
  /* #DDE0E6: nudge-button border grey, only used here. */
  border: 1px solid #dde0e6;
  border-radius: 4px;
  width: 38px;
  height: 38px;
  cursor: pointer;
  color: var(--color-muted);
  font-size: 13px;
  letter-spacing: -0.06em;
  font-family: var(--font-base);
}

.home-marquee__nudge:hover,
.home-marquee__nudge:focus-visible {
  color: var(--color-accent);
  border-color: var(--color-accent);
}

.home-marquee__nudge--back {
  left: 0;
}

.home-marquee__nudge--fwd {
  right: 0;
}

/* ==========================================================================
   Scroll reveal
   Elements marked data-reveal in index.njk (or tagged onto .site-footer
   at runtime by home.js, see that file) start hidden via this class,
   which home.js's IntersectionObserver removes once each element
   scrolls into view. Kept as a CSS class rather than fully inline
   styles (unlike the reference's React version) so the starting state
   is visible directly in the stylesheet, not buried in JS.
   ========================================================================== */
/* Split into two classes on purpose. home.js adds BOTH together when
   arming an element, then only ever removes .home-reveal-hidden to
   trigger the reveal. If the transition lived on .home-reveal-hidden
   itself (as a single class), removing that class would drop the
   transition declaration in the exact same reflow as the opacity/
   transform change, so the element would jump straight to its
   revealed state instead of animating: confirmed by sampling opacity
   every 100ms across a reveal and finding it was already 1 on the
   very first sample, never mid-transition. Keeping the transition on
   a class that's never removed is what makes it actually animate. */
.home-reveal {
  transition: opacity 1250ms ease, transform 1250ms cubic-bezier(0.22, 1, 0.36, 1);
}

.home-reveal-hidden {
  opacity: 0;
  transform: translateY(34px);
}

@media (prefers-reduced-motion: reduce) {
  .home-reveal-hidden {
    opacity: 1;
    transform: none;
  }

  .home-reveal {
    transition: none;
  }
}

/* ==========================================================================
   Mobile, below 768px

   No mobile reference screenshot exists for the homepage, unlike the
   three case pages (see reference/*-mobile.css). Everything in this
   block is a reasoned build decision from the desktop reference, not
   a confirmed match, and is reported as such in QA-check.
   ========================================================================== */
@media (max-width: 767px) {
  .home-bar {
    padding: 14px 24px 0;
  }

  /* The pill has no room for the status sentence at mobile widths
     without wrapping awkwardly across two lines inside a rounded
     pill; drop it and keep name, role and the mail button. */
  .home-bar__status {
    display: none;
  }

  .home-bar__divider {
    display: none;
  }

  .home-hero {
    padding: 48px 24px 32px;
  }

  .home-hero__grid {
    grid-template-columns: 1fr;
    gap: 32px;
  }

  /* Portrait first, then text, both left-aligned: the right-aligned
     desktop treatment only works with the image beside the text. */
  .home-hero__text {
    order: 2;
    text-align: left;
    justify-self: stretch;
  }

  .home-hero__title {
    margin-left: 0;
    font-size: 38px;
    letter-spacing: -0.02em;
  }

  .home-hero__subline {
    margin-left: 0;
    max-width: none;
    font-size: 18px;
  }

  .home-hero__media {
    order: 1;
    width: 100%;
    max-width: 320px;
    margin-inline: auto;
  }

  .home-cases-label-row {
    padding: 24px 24px 20px;
  }

  .home-cases-list {
    padding: 0 24px 56px;
    gap: 20px;
  }

  /* Every card stacks image-above-text; the left/right alternation
     is a desktop-only rhythm device and collapses here. */
  .home-card__link,
  .home-card__link--image-right {
    grid-template-columns: 1fr;
  }

  .home-card__link--image-right .home-card__media {
    order: 0;
  }

  .home-card__body,
  .home-card__link--image-right .home-card__body {
    padding: 28px 24px;
  }

  .home-currently {
    padding: 56px 24px;
  }

  .home-currently__grid {
    grid-template-columns: 1fr;
    gap: 24px;
  }

  .home-worked-with {
    padding: 56px 24px 64px;
  }

  .home-marquee {
    /* No room for the nudge-button gutter at mobile widths; the
       motion keeps running, only the manual controls are hidden. */
    padding: 0;
  }

  .home-marquee__nudge {
    display: none;
  }

  .home-marquee__viewport {
    padding: 0 12px;
  }
}
