/*
  Homepage — Rob Newport.
  Same design system as the three case-study pages (tokens, nav, footer and
  motion classes are carried over verbatim from
  ../times-checkout-editorial-hero-v2/styles.css). Only the page-specific
  sections below (.intro, .work/.herocard, .about) are new.

  Page rhythm inverts the case studies deliberately: they open dark, so this
  one opens white and saves its single dark moment for the About teaser at
  the foot of the page.
*/

:root {
  /* Colour — near-monochrome; blue accent appears only in small doses */
  --bg: #ffffff;
  --ink: #14181a;
  --muted: #5c666b;
  --faint: #949da1;
  --rule: #e3e1dc;
  --accent: #181bf3;
  --dark-bg: #14181a;
  --dark-text: #ffffffdb;
  --dark-faint: #ffffff8c;
  --wash: #f4f1ec;
  --card: #d3e1e7;
  /* Cool light grey tinted toward the accent blue — the hero band's
     background, not a neutral pick. */
  --intro-bg: #eef0f7;

  /* Motion */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);

  --font: "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Layout */
  --gutter: 37.6667px;
  --measure: 560px;
  --page-max: 1180px;

  /* Vertical rhythm */
  --gap-s: 24px;
  --gap-m: 48px;
  --gap-l: 96px;
  --gap-xl: 180px;
}

* { box-sizing: border-box; }

/* Cross-document view transitions (Chrome 126+, Safari 18.2+, Firefox
   144+): opts this page in to native transitions on same-origin
   navigation. The matching @view-transition rule must ALSO be present on
   whichever case-study page this navigates to — if only one side opts in,
   the browser silently falls back to a plain navigation, which is exactly
   the degradation we want everywhere else (this file has no JS fallback
   for older browsers, the CSS opt-in IS the whole feature). Named elements
   that make the actual card→hero morph happen live further down (see
   .herocard--checkout .herocard__art etc.) and in each destination page's
   own styles.css. */
@view-transition {
  navigation: auto;
}

/* Default browser timing reads as an abrupt cut on a morph this large
   (card thumbnail → full hero) — same easing token as the rest of the
   site's motion, applied to every named pair. */
@media not (prefers-reduced-motion: reduce) {
  ::view-transition-group(*) {
    animation-duration: 500ms;
    animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
  }
}

/* The @view-transition opt-in above is unconditional (per spec there's no
   CSS-level way to gate it on prefers-reduced-motion), so a reduced-motion
   visitor would otherwise still get the browser's own default morph/fade —
   kill it explicitly rather than just skipping our custom timing. Result is
   an instant cross-doc swap, same as a browser that doesn't support this at
   all. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

/* Hero-echo card choreography, overriding the flat 500ms default above for
   these name sets specifically (a literal ::view-transition-group(name)
   selector outranks the ::view-transition-group(*) one). The card/background
   leads on its own — it should read as the dark ground taking over the page
   — and the four content pieces are held back with a delay so they arrive
   afterward, each still using the browser's default morph (position/size
   interpolated from old rect to new rect), just started later and eased so
   it reads as "falling into place" rather than four things resizing in
   lockstep with the background over one identical span.
   Same timing, per project, is mirrored in each case-study page's own
   styles.css — both sides of a cross-document transition need to agree;
   see the @view-transition comment above for why. Originally tuned on
   Checkout alone; ported unchanged to Entitlements/Quick Checker's own
   vt-*-entitlements/vt-*-quickchecker names (2026-08-23) when their cards
   were ported to .herocard too. */
@media not (prefers-reduced-motion: reduce) {
  ::view-transition-group(vt-card-checkout),
  ::view-transition-group(vt-card-entitlements),
  ::view-transition-group(vt-card-quickchecker) {
    animation-duration: 650ms;
    animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
  }

  ::view-transition-group(vt-media-checkout),
  ::view-transition-group(vt-media-entitlements),
  ::view-transition-group(vt-media-quickchecker) {
    animation-duration: 550ms;
    animation-delay: 300ms;
    animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
  }

  ::view-transition-group(vt-eyebrow-checkout),
  ::view-transition-group(vt-eyebrow-entitlements),
  ::view-transition-group(vt-eyebrow-quickchecker) {
    animation-duration: 500ms;
    animation-delay: 350ms;
    animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
  }

  ::view-transition-group(vt-title-checkout),
  ::view-transition-group(vt-title-entitlements),
  ::view-transition-group(vt-title-quickchecker) {
    animation-duration: 500ms;
    animation-delay: 420ms;
    animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
  }

  ::view-transition-group(vt-meta-checkout),
  ::view-transition-group(vt-meta-entitlements),
  ::view-transition-group(vt-meta-quickchecker) {
    animation-duration: 450ms;
    animation-delay: 500ms;
    animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
  }
}

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

/* ── Top nav ─────────────────────────────────────────────────── */

/* .nav is a direct child of <body> (not nested inside the max-width
   constrained .page), so width:100% is all it needs — and the full-bleed
   breakout trick (100vw + left:50% + translateX(-50%)) is unreliable
   combined with position:sticky, so don't reach for it here. */
.nav {
  width: 100%;
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--bg);
  transition: transform 0.3s var(--ease-out);
}

.nav.is-hidden {
  transform: translateY(-100%);
}

.nav__inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 24px var(--gutter);
}

.nav__logo {
  font: 500 15px/20px var(--font);
  letter-spacing: -0.01em;
  color: var(--ink);
}

.nav__links {
  display: flex;
  gap: 32px;
}

.nav__links a {
  font: 400 13px/18px var(--font);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  transition: color 150ms ease;
}

.nav__links a:hover { color: var(--ink); }

.nav__links a[aria-current="page"] { color: var(--ink); }

/* ── Page column ─────────────────────────────────────────────── */

.page {
  margin: 0 auto;
  max-width: var(--page-max);
  padding: 0 var(--gutter);
}

/* Small uppercase section marker — the page's only routine use of accent */
.label {
  font: 500 13px/18px var(--font);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0;
}

/* ── Intro ───────────────────────────────────────────────────── */

/* Full-bleed hero band — same breakout as .about (100vw + left:50% +
   translateX(-50%)), safe here since .intro, like .about, is never
   position:sticky. .intro__inner puts the content back inside the page's
   own max-width/gutter, same split as .about/.about__inner below. */
.intro {
  width: 100vw;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
  background: var(--intro-bg);
}

/* Title and lead sit side by side as one row, the lead vertically centred
   against the title block rather than stacked beneath it. */
.intro__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 120px var(--gutter) var(--gap-xl);
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: 64px;
  align-items: center;
}

.intro__title {
  font: 700 clamp(44px, 6vw, 80px) / 1.04 var(--font);
  letter-spacing: -0.03em;
  color: var(--ink);
  max-width: 15ch;
  margin: 24px 0 0;
}

.intro__lead {
  font: 400 19px/32px var(--font);
  color: var(--muted);
  max-width: var(--measure);
  /* No top margin here — vertical placement now comes from the grid row's
     own align-items: center, not from stacking under the title. */
  margin: 0;
}

/* ── Selected work ───────────────────────────────────────────── */

/* .intro's own bottom padding sits inside the grey band (it's what gives
   the band its height), so it reads as part of the hero, not as space
   after it — this is the actual gap between the band and "Selected work". */
.work {
  padding-top: var(--gap-xl);
}

.work__label {
  padding-bottom: 28px;
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--gap-l);
}

/* ── Hero-echo cards ────────────────────────────────────────────
   A contained, rounded, dark card per project holding a slimmed-down copy
   of that project's own destination hero — eyebrow, title, description,
   image, Role/Team/Duration hidden until hover. Replaced an earlier light
   editorial-card design (.project — grid row, alternating image side,
   hover-glimpse image cycling) that all three cards used at first; that
   system is gone from this page entirely as of 2026-08-23, once Checkout's
   redesign (built first, as a trial) was approved and ported to the other
   two. Composition deliberately mirrors .hero__art / .hero__top on the
   case-study pages (art on the right, bottom-anchored text on the left) so
   the click-through view transition below has as little distance to travel
   as possible between card and hero. */

.herocard {
  position: relative;
  display: block;
  aspect-ratio: 2 / 1;
  overflow: hidden;
  border-radius: 8px;
  background: var(--dark-bg);
  text-decoration: none;
}

.herocard + .herocard {
  margin-top: var(--gap-xl);
}

/* Cross-document view transition targets (see the @view-transition rule
   near the top of this file), one set per project — each name here has
   exactly one matching element of the same name in that project's own
   case-study page (.hero → vt-card-*, .hero__art → vt-media-*,
   .hero__eyebrow → vt-eyebrow-*, .hero__title → vt-title-*, .hero__meta →
   vt-meta-*). Scoped to each --modifier rather than baked into the bare
   .herocard__* classes above/below, since a view-transition-name must be
   unique per document — three cards sharing one literal name would collide.
   The outer .herocard itself carries the vt-card-* name so it morphs into
   the hero SECTION on click (rounded → square corners, contained →
   full-bleed); independent of the four inner names, nested named elements
   each get their own transition group and compose correctly. */
.herocard--checkout { view-transition-name: vt-card-checkout; }
.herocard--entitlements { view-transition-name: vt-card-entitlements; }
.herocard--quickchecker { view-transition-name: vt-card-quickchecker; }

.herocard--checkout .herocard__art { view-transition-name: vt-media-checkout; }
.herocard--entitlements .herocard__art { view-transition-name: vt-media-entitlements; }
.herocard--quickchecker .herocard__art { view-transition-name: vt-media-quickchecker; }

.herocard--checkout .herocard__eyebrow { view-transition-name: vt-eyebrow-checkout; }
.herocard--entitlements .herocard__eyebrow { view-transition-name: vt-eyebrow-entitlements; }
.herocard--quickchecker .herocard__eyebrow { view-transition-name: vt-eyebrow-quickchecker; }

.herocard--checkout .herocard__title { view-transition-name: vt-title-checkout; }
.herocard--entitlements .herocard__title { view-transition-name: vt-title-entitlements; }
.herocard--quickchecker .herocard__title { view-transition-name: vt-title-quickchecker; }

.herocard--checkout .herocard__meta { view-transition-name: vt-meta-checkout; }
.herocard--entitlements .herocard__meta { view-transition-name: vt-meta-entitlements; }
.herocard--quickchecker .herocard__meta { view-transition-name: vt-meta-quickchecker; }

.herocard__art {
  position: absolute;
  top: 50%;
  /* Pulled in from 4% (2026-08-23, Rob: "too far apart") — moved toward the
     card's centre together with .herocard__inner's own tighter indent
     below, closing the dead gap that opened up between the text and the
     image instead of leaving both pinned out near the card's edges. */
  right: 10%;
  transform: translateY(-50%);
  width: 34%;
  min-width: 150px;
}

.herocard__art img {
  width: 100%;
  height: auto;
  display: block;
}

/* Quick Checker has no real asset yet — the placeholder inside .herocard__art
   is given the same 1009:1024 aspect ratio the other two cards' composite
   images happen to share, so it behaves identically in the layout (same
   width-driven sizing, same centring, same stacked-breakpoint treatment)
   without .herocard__art itself needing an img-vs-placeholder branch. Swap
   for a real <img class="herocard__art img">-equivalent once art lands. */
.herocard__art .ph {
  width: 100%;
  aspect-ratio: 1009 / 1024;
  border-radius: 8px;
}

/* Centered to match .herocard__art's own top:50%/translateY(-50%) centering
   — previously bottom-anchored (justify-content: flex-end), which put the
   text a full text-block-height below the image's vertical middle and read
   as two unrelated things sharing a box rather than one composition. */
.herocard__inner {
  position: relative;
  height: 100%;
  /* Narrowed 58%→48% and indent widened 40px→64px (2026-08-23, paired with
     .herocard__art's own move above) — brings the text column in from the
     left edge to close the gap toward the image, rather than leaving it
     stretched out to nearly meet the art on its own. */
  max-width: 48%;
  padding: 28px 0 28px 64px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.herocard__eyebrow {
  display: block;
  font: 500 12px/16px var(--font);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #fff;
  margin-bottom: 14px;
}

/* Sized up from clamp(20px, 2.6vw, 30px) — at the card's own width the old
   scale read as a caption next to the large image, not a headline; the
   larger size also fills more of .herocard__inner's wrap width, closing the
   whitespace gap to the art without moving either element. */
.herocard__title {
  font: 700 clamp(26px, 3.6vw, 42px) / 1.1 var(--font);
  letter-spacing: -0.02em;
  color: #fff;
  margin: 0;
}

/* Added 2026-08-23 — the Checkout hero's own description now lives above
   the fold as part of its primary composition (see that page's 2026-08-23
   "description moved above the fold" note), so the card omitting it was
   stale reasoning there, not a deliberate difference. Carried the same
   description over to the Entitlements/Quick Checker cards for consistency
   across all three, even though their own destination heroes haven't had
   that same restructure yet (their description is still a separate
   below-the-fold block there) — the card is its own slimmed composition,
   not a strict 1:1 crop of the current hero layout. No view-transition-name
   on any of the three: none of the destination .hero__description elements
   carry one, so there's nothing to pair it with. */
.herocard__description {
  font: 400 14px/22px var(--font);
  color: #fff;
  margin: 12px 0 0;
}

/* Occupies its slot at rest (no layout shift on hover) — just invisible
   until hovered. Named so it morphs into .hero__meta on click; since a
   click requires the pointer to already be over the card (or, on touch,
   it's always visible per the media query below), it's always in its
   revealed state at the moment a transition actually starts. */
.herocard__meta {
  /* 14px→28px (2026-08-23) — the description sits directly above with no
     bottom margin of its own, so this top margin was the whole gap; too
     tight once the description was added. */
  margin: 28px 0 0;
  display: flex;
  gap: 20px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 400ms var(--ease-out), transform 400ms var(--ease-out);
}

.herocard:is(:hover, :focus-visible) .herocard__meta {
  opacity: 1;
  transform: translateY(0);
}

@media (hover: none) {
  .herocard__meta { opacity: 1; transform: none; }
}

.herocard__meta-item { display: flex; flex-direction: column; gap: 3px; }

.herocard__meta dt {
  font: 500 10px/14px var(--font);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--dark-faint);
}

.herocard__meta dd {
  margin: 0;
  font: 400 12px/16px var(--font);
  color: #fff;
}

.herocard:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

/* Reveal-on-scroll: the whole card fades/rises as one unit — no separate
   image/text stagger, since this is meant to read as a single hero-like
   composition, not two independently-animating halves. */
.herocard {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 700ms var(--ease-out), transform 700ms var(--ease-out);
}

.herocard.is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .herocard,
  .herocard__meta {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ── Image placeholder (carried over from the Quick Checker page) ─ */

.ph {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 24px;
  text-align: center;
  background: var(--wash);
  border: 1px dashed #cdc4b6;
  border-radius: 8px;
}

.ph__tag {
  font: 500 11px/16px var(--font);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--accent);
}

.ph__label {
  font: 400 15px/23px var(--font);
  color: #8b8375;
  max-width: 340px;
}

.ph--dark {
  background: #1f262a;
  border-color: rgba(255, 255, 255, 0.22);
}

.ph--dark .ph__tag { color: #fff; }
.ph--dark .ph__label { color: var(--dark-faint); }

/* ── About teaser — the page's one dark moment ───────────────── */

.about {
  width: 100vw;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
  background: var(--dark-bg);
  margin-top: var(--gap-xl);
  padding: 120px 0;
}

.about__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 0 var(--gutter);
  display: grid;
  grid-template-columns: 400px 1fr;
  gap: 80px;
  align-items: center;
}

.about__portrait {
  aspect-ratio: 4 / 5;
}

.about__label { color: #fff; }

.about__text {
  font: 400 22px/36px var(--font);
  letter-spacing: -0.01em;
  color: #fff;
  max-width: var(--measure);
  margin: 28px 0 0;
}

.about__link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font: 500 15px/20px var(--font);
  color: #fff;
  text-decoration: none;
  margin-top: 40px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.28);
  transition: border-color 300ms var(--ease-out);
}

.about__link svg { transition: transform 500ms var(--ease-out); }

.about__link:is(:hover, :focus-visible) { border-color: #fff; }
.about__link:is(:hover, :focus-visible) svg { transform: translateX(6px); }

/* ── Footer ──────────────────────────────────────────────────── */

.foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 40px 0 64px;
  border-top: 1px solid var(--rule);
}

/* The dark About band already provides the edge — a second hairline
   immediately under it reads as a double rule. */
.about + .foot {
  border-top: none;
  padding-top: 64px;
}

.foot__name {
  font: 400 14px/20px var(--font);
  color: var(--faint);
}

.foot__links { display: flex; gap: 28px; }

.foot__links a {
  font: 400 14px/20px var(--font);
  color: var(--muted);
  text-decoration: none;
  transition: color 150ms ease;
}

.foot__links a:hover { color: var(--ink); }

/* ── Motion ──────────────────────────────────────────────────── */

.js-fade-up,
.js-reveal {
  opacity: 0;
  transform: translateY(16px);
  transition-property: opacity, transform;
  transition-timing-function: var(--ease-out);
  transition-duration: 600ms;
}

.js-fade-up.is-visible,
.js-reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js-fade-up,
  .js-reveal { opacity: 1; transform: none; transition: none; }
  .about__link svg { transition: none; }
}

/* ── Tablet ──────────────────────────────────────────────────── */

@media (max-width: 1080px) {
  :root { --gutter: 48px; --gap-xl: 128px; --gap-l: 72px; }

  .about__inner { grid-template-columns: 320px 1fr; gap: 56px; }
  .about { padding: 96px 0; }
  .about__text { font-size: 20px; line-height: 33px; }
}

/* ── Stacked (narrow tablet / large phone) ───────────────────── */

@media (max-width: 900px) {
  /* The title/lead row runs out of room for two columns once the title
     wraps to 3-4 lines at this width — back to stacked, lead under title. */
  .intro__inner {
    grid-template-columns: 1fr;
  }

  .intro__lead { margin-top: 32px; }

  .about__inner { grid-template-columns: 1fr; gap: 40px; }
  .about__portrait { max-width: 320px; }

  /* The side-by-side art+text composition needs real horizontal room —
     below 900px the absolutely-positioned art starts colliding with the
     text column (confirmed by testing at 390px: the meta row overflowed
     the card and wrapped illegibly). Switch to a stacked flex column:
     image on top at its own natural aspect ratio, text below in normal
     flow. */
  .herocard {
    aspect-ratio: auto;
    display: flex;
    flex-direction: column;
  }

  .herocard__art {
    position: static;
    transform: none;
    width: 60%;
    max-width: 280px;
    margin: 28px auto 0;
  }

  .herocard__inner {
    max-width: none;
    height: auto;
    padding: 20px 24px 28px;
  }

  .herocard__meta { flex-wrap: wrap; row-gap: 10px; }
}

/* ── Mobile ──────────────────────────────────────────────────── */

@media (max-width: 720px) {
  :root { --gutter: 24px; --gap-xl: 88px; --gap-l: 56px; }

  .intro__inner { padding: 72px var(--gutter) var(--gap-xl); }
  .intro__lead { font-size: 17px; line-height: 29px; margin-top: 28px; }

  .work__label { margin-bottom: var(--gap-m); }

  .herocard__art { width: 68%; max-width: 220px; }
  .herocard__inner { padding: 20px 20px 24px; }
  .herocard__description { font-size: 13px; line-height: 20px; }
  .herocard__meta { column-gap: 16px; }

  .about { padding: 72px 0; margin-top: var(--gap-xl); }
  .about__text { font-size: 18px; line-height: 30px; }

  .foot { flex-direction: column; align-items: flex-start; gap: 20px; padding: 32px 0 48px; }
}
