/* =================================================================
   Constantin - Ring of Services
   Act 0 (static rest state) styling. Acts 1-3 not yet animated.
   Aesthetic: calm clinical-editorial. Warm paper ground, ink text,
   muted sage accent. Display serif (Fraunces) + humanist body (Spline Sans).
   Positioning is transform-only, driven by --x / --y / --d CSS vars.
   ================================================================= */

:root {
  --paper:      #f4f1ea;   /* warm bone ground */
  --paper-deep: #ece7dc;
  --ink:        #1f2421;   /* near-black green-ink */
  --ink-soft:   #4b524d;
  --sage:       #6f7d68;   /* muted accent */
  --sage-deep:  #4f5b49;
  --clay:       #b08968;   /* warm secondary accent */
  --line:       rgba(31, 36, 33, 0.14);

  /* Constellation circle size - larger spheres. */
  --card-size:  clamp(78px, 8vw, 152px);

  /* Act 0 ring geometry - the single source of truth for the rest state.
     positionCards() reads these as its defaults. Dialable here.
     Tightened from 42vw/30vh so the formation reads as a smaller, elegant
     constellation with lots of surrounding negative space. */
  --rx-rest: 27vw;
  --ry-rest: 24vh;

  --ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  --font-display: "Fraunces", Georgia, serif;
  --font-body: "Spline Sans", system-ui, sans-serif;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }

/* ---------------- Top bar ---------------- */
.topbar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 22px clamp(20px, 4vw, 56px);
  mix-blend-mode: multiply;
}
.brand {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(19px, 2vw, 24px);
  letter-spacing: -0.01em;
}
.topnav {
  display: flex;
  gap: clamp(18px, 2.4vw, 38px);
  font-size: 14px;
  letter-spacing: 0.02em;
}
.topnav a {
  position: relative;
  color: var(--ink-soft);
  transition: color 0.3s var(--ease-out);
}
.topnav a:hover,
.topnav a:focus-visible { color: var(--ink); }

/* ---------------- Ring zone (pinned section) ----------------
   Act-0-only: zone is exactly one viewport tall. app.js bumps
   this taller once Acts 1-3 are wired (act count * 100svh). */
/* Acts 0-2: three viewports tall. First viewport = rest state in view,
   second = Act 1 scrub (spin/contract/fade), third = Act 2 scrub (zoom).
   Act 3 carousel will add more height when built. */
#ring-zone {
  position: relative;
  height: 300vh;        /* fallback */
  height: 300svh;       /* iOS-safe */
  background:
    radial-gradient(120% 80% at 50% 42%, var(--paper) 0%, var(--paper-deep) 100%);
}
#ring-pin {
  position: sticky;
  top: 0;
  height: 100vh;        /* fallback */
  height: 100svh;       /* iOS-safe */
  width: 100%;
  overflow: hidden;
}

/* The formation. This whole layer is what Acts 1-2 will rotate/scale. */
.ring-wrap {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  /* NOT promoted: the cards are the cached layers (each <= heroPx, crisp).
     Promoting the whole wrap would cache the giant ring as one oversized,
     down-rastered texture -> blur. The wrap only re-composites the cards. */
}

/* ---------------- Center logo slot ---------------- */
.ring-logo {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: clamp(80px, 9vw, 132px);
  height: clamp(80px, 9vw, 132px);
  display: grid;
  place-items: center;
  z-index: 1;   /* sits BEHIND the circles */
}
.ring-logo img,
.ring-logo svg {
  max-width: 100%;
  max-height: 100%;
  display: block;
}
/* transparent PNG logo - sits clean on the paper ground */
.ring-logo__img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* Placeholder mark - removed visually once a real asset is dropped in */
.ring-logo__placeholder {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(44px, 6vw, 76px);
  color: var(--ink);
  line-height: 1;
  opacity: 0.92;
}

/* ---------------- Spinning corner mark ----------------
   Fixed bottom-right; rotation driven by scroll position in app.js. */
.corner-logo {
  position: fixed;
  right: clamp(16px, 2.4vw, 34px);
  bottom: clamp(16px, 2.4vw, 34px);
  width: clamp(54px, 6.5vw, 92px);
  height: clamp(54px, 6.5vw, 92px);
  z-index: 60;
  display: block;
  will-change: transform;
}
.corner-logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.corner-logo:focus-visible {
  outline: 2px solid var(--sage-deep);
  outline-offset: 4px;
  border-radius: 50%;
}

/* Labels layer - outside the scaling wrap, covers the viewport */
.ring-labels {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 4;
}

/* ---------------- Cards ---------------- */
.ring-cards {
  list-style: none;
  margin: 0;
  padding: 0;
}
.ring-item {
  position: absolute;
  left: 50%;
  top: 50%;
  /* --x / --y written by positionCards() in px; transform only */
  transform: translate(-50%, -50%) translate(var(--x, 0px), var(--y, 0px));
  will-change: transform;
  z-index: 3;   /* circles sit ABOVE the labels and the centre logo */
}

.ring-card {
  position: relative;
  display: block;
  width: var(--card-size);
  height: var(--card-size);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--paper);
  overflow: hidden;
  cursor: pointer;
  touch-action: manipulation;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.6) inset,
              0 14px 34px -22px rgba(31, 36, 33, 0.55);
  transition: transform 0.5s var(--ease-out),
              box-shadow 0.5s var(--ease-out),
              border-color 0.5s var(--ease-out);
}
.ring-card:hover,
.ring-card:focus-visible {
  transform: scale(1.06);
  border-color: var(--sage);
  box-shadow: 0 18px 42px -20px rgba(31, 36, 33, 0.6);
}
.ring-card:focus-visible {
  outline: 2px solid var(--sage-deep);
  outline-offset: 3px;
}
.ring-card__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Tinted fill shown until real imagery lands */
.ring-card__fill {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background:
    radial-gradient(85% 85% at 30% 25%, var(--paper) 0%, var(--paper-deep) 70%, #e1dccf 100%);
}
.ring-card__num {
  font-family: var(--font-display);
  font-size: clamp(15px, 1.6vw, 20px);
  font-style: italic;
  color: var(--sage-deep);
  opacity: 0.7;
}

/* ---------------- Labels ----------------
   Anchored to each card, sitting just outside the circle.
   --d is the label's offset direction (left/right of card)
   so labels on the left half flow leftward, right half rightward. */
.ring-label {
  position: absolute;
  left: 50%;
  top: 50%;
  /* caption sits just below the circle, centered, and always on top */
  transform: translate(-50%, -50%) translate(var(--x, 0px), var(--y, 0px)) translate(0, var(--ly, 0px));
  width: max-content;
  max-width: 168px;
  pointer-events: none;
  font-size: 12.5px;
  line-height: 1.25;
  letter-spacing: 0.01em;
  color: var(--ink-soft);
  text-align: center;
  opacity: 1;          /* Act 1 scrubs this to 0 as the clean circle forms */
  transition: opacity 0.4s var(--ease-out);
  will-change: opacity;
  z-index: 4;          /* above the circles so the caption is never clipped */
}
/* Visually-hidden helper - labels keep text in DOM for SR even when faded */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------------- Act 2/3 feature titles ----------------
   A stacked layer of large display titles, bottom-left over the expanded
   circle (offmenu feel). One per service, all pinned to the same spot so
   they crossfade as each card reaches the center hero. Hidden at rest;
   Act 2 fades the first in, Act 3 crossfades through the rest. */
.feature-titles {
  position: absolute;
  left: clamp(20px, 5vw, 72px);
  bottom: clamp(28px, 8vh, 80px);
  z-index: 7;
  pointer-events: none;
  width: min(80vw, 16ch);
  height: clamp(48px, 12vh, 130px);
}
.feature-title {
  position: absolute;
  left: 0;
  bottom: 0;
  margin: 0;
  max-width: 13ch;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(40px, 8.2vw, 118px);
  line-height: 0.96;
  letter-spacing: -0.022em;
  color: var(--ink);
  opacity: 0;                 /* timeline scrubs the active one to 1 */
  text-wrap: balance;
  will-change: opacity, transform;
}

/* ---------------- Scroll cue ---------------- */
.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-soft);
  z-index: 6;
}
.scroll-cue__line {
  width: 1px;
  height: 40px;
  background: linear-gradient(var(--ink-soft), transparent);
  animation: cue-pulse 2.4s var(--ease-out) infinite;
}
@keyframes cue-pulse {
  0%, 100% { transform: scaleY(0.4); transform-origin: top; opacity: 0.4; }
  50%      { transform: scaleY(1);   transform-origin: top; opacity: 1; }
}

/* ---------------- Service detail page (overlay) ----------------
   offmenu-style: full-bleed hero with the title overlaid, then a two-column
   case layout (Introduction + Details) and a Scope list. The overlay scrolls
   internally; background scroll is locked while open (html.detail-open). */
.detail {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--paper);
}
.detail[hidden] { display: none; }
.detail__scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
}
.detail__close {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 3;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 10px 18px;
  font-family: var(--font-body);
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.3s var(--ease-out), background 0.3s var(--ease-out);
}
.detail__close:hover { border-color: var(--sage); background: #fff; }
.detail__close:focus-visible { outline: 2px solid var(--sage-deep); outline-offset: 2px; }

/* Hero - full-bleed, fills the whole viewport (image expands to all borders) */
.detail__hero {
  position: relative;
  height: 100vh;
  height: 100svh;
  width: 100%;
  overflow: hidden;
  background: var(--paper-deep);
}
.detail__picture {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}
.detail__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.detail__fill {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(90px, 20vw, 280px);
  color: var(--sage-deep);
  opacity: 0.4;
  background:
    radial-gradient(90% 90% at 32% 26%, var(--paper) 0%, var(--paper-deep) 62%, #e0dbce 100%);
}
.detail__hero-title {
  position: absolute;
  left: clamp(20px, 5vw, 72px);
  bottom: clamp(28px, 6vh, 64px);
  z-index: 1;
  margin: 0;
  max-width: 16ch;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(40px, 7vw, 104px);
  line-height: 0.98;
  letter-spacing: -0.022em;
  color: var(--ink);
  text-wrap: balance;
}
/* real image behind the hero: title goes white + a soft bottom scrim */
.detail.has-img .detail__hero-title { color: #fff; }
.detail.has-img .detail__hero::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to top, rgba(18, 22, 19, 0.62) 0%, rgba(18, 22, 19, 0) 44%);
}

/* Case layout */
.detail__case {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(32px, 6vw, 96px);
  max-width: 1320px;
  margin: 0 auto;
  padding: clamp(48px, 9vh, 120px) clamp(20px, 5vw, 72px) clamp(24px, 5vh, 56px);
}
.detail__eyebrow {
  display: block;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: clamp(18px, 3vh, 30px);
}
.detail__narrative {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(22px, 2.5vw, 38px);
  line-height: 1.28;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.meta-list { margin: 0; }
.meta-row {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 15px 0;
  border-top: 1px solid var(--line);
  font-size: clamp(14px, 1.1vw, 16px);
}
.meta-row:last-child { border-bottom: 1px solid var(--line); }
.meta-row__label { color: var(--ink-soft); }
.meta-row__value { color: var(--ink); text-align: right; }
.meta-row__value a { color: var(--sage-deep); text-decoration: none; border-bottom: 1px solid var(--line); }
.meta-row__value a:hover { border-color: var(--sage); }

/* Scope */
.detail__scopewrap {
  max-width: 1320px;
  margin: 0 auto;
  padding: clamp(24px, 5vh, 56px) clamp(20px, 5vw, 72px) clamp(64px, 12vh, 140px);
}
.scope-list { list-style: none; margin: 0; padding: 0; }
.scope-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 20px;
  padding: clamp(16px, 2.4vh, 26px) 0;
  border-top: 1px solid var(--line);
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(20px, 2.4vw, 34px);
  letter-spacing: -0.01em;
  color: var(--ink);
}
.scope-row:last-child { border-bottom: 1px solid var(--line); }
.scope-row__num {
  font-family: var(--font-body);
  font-size: clamp(12px, 1vw, 14px);
  color: var(--ink-soft);
}

/* lock background scroll while the overlay is open */
html.detail-open, body.detail-open { overflow: hidden; }

@media (max-width: 760px) {
  .detail__hero { height: 70vh; height: 70svh; }
  .detail__case { grid-template-columns: 1fr; gap: 36px; }
}

/* ---------------- Downstream placeholder sections ---------------- */
.section-pad {
  padding: clamp(72px, 12vh, 160px) clamp(20px, 6vw, 120px);
  border-top: 1px solid var(--line);
}
.section-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, 4.4vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin: 0 0 0.5em;
  max-width: 16ch;
}
.section-lede {
  max-width: 52ch;
  color: var(--ink-soft);
  font-size: clamp(16px, 1.6vw, 19px);
}

/* ---------------- Contact section ---------------- */
.contact {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(32px, 6vw, 96px);
}
.contact__intro { max-width: 56ch; }
.contact__cta {
  display: inline-block;
  margin-top: 1.5em;
  font-family: var(--font-display);
  font-size: clamp(20px, 2.4vw, 30px);
  color: var(--ink);
  border-bottom: 1px solid var(--line);
  padding-bottom: 4px;
  transition: border-color 0.3s var(--ease-out), color 0.3s var(--ease-out);
}
.contact__cta:hover,
.contact__cta:focus-visible {
  color: var(--sage-deep);
  border-color: var(--sage);
}
.contact__mark {
  width: clamp(96px, 12vw, 168px);
  height: auto;
  flex-shrink: 0;
  opacity: 0.95;
}

/* ---------------- Site footer ---------------- */
.site-footer {
  background: #2a3038;
  color: #d8dcdb;
  padding: clamp(56px, 9vh, 104px) clamp(20px, 6vw, 120px) clamp(28px, 4vh, 44px);
}
.site-footer__inner {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: clamp(32px, 5vw, 80px);
  max-width: 1200px;
}
.footer-brand__name {
  font-family: var(--font-display);
  font-size: clamp(24px, 2.6vw, 34px);
  color: #fff;
  letter-spacing: -0.01em;
}
.footer-brand__line {
  margin: 0.8em 0 0;
  max-width: 34ch;
  color: #9aa1a0;
  font-size: 15px;
  line-height: 1.6;
}
.footer-eyebrow {
  display: block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #8b9290;
  margin-bottom: 1.2em;
}
.footer-address {
  font-style: normal;
  line-height: 1.7;
}
.footer-address p { margin: 0 0 1em; }
.footer-address a,
.footer-nav a {
  color: #d8dcdb;
  transition: color 0.25s var(--ease-out);
}
.footer-address a:hover,
.footer-address a:focus-visible,
.footer-nav a:hover,
.footer-nav a:focus-visible { color: var(--clay); }
.footer-nav {
  list-style: none;
  margin: 0;
  padding: 0;
  line-height: 2.2;
}
.site-footer__base {
  margin-top: clamp(40px, 6vh, 72px);
  padding-top: 24px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 13px;
  color: #8b9290;
}

/* =================================================================
   MOBILE
   Radii are handled in JS via vmin() so the ring adapts to portrait widths.
   Here we tune circle size, label size, logo and nav for small screens.
   ================================================================= */
@media (max-width: 768px) {
  :root {
    --card-size: clamp(60px, 16vw, 104px);
  }
  .topnav { gap: 16px; font-size: 13px; }
  .ring-label { font-size: 11px; max-width: 110px; }
  .ring-logo { width: clamp(64px, 18vw, 100px); height: clamp(64px, 18vw, 100px); }
  .corner-logo { width: clamp(48px, 12vw, 68px); height: clamp(48px, 12vw, 68px); }

  .contact { flex-direction: column; align-items: flex-start; }
  .contact__mark { align-self: center; }
  .site-footer__inner { grid-template-columns: 1fr; gap: 40px; }
}

@media (max-width: 480px) {
  :root { --card-size: clamp(56px, 17vw, 92px); }
  .topbar { padding: 16px 18px; }
  .topnav a:nth-child(2) { display: none; } /* trim crowding on the smallest screens */
  .ring-label { font-size: 11px; max-width: 96px; }
}

/* =================================================================
   REDUCED MOTION - app.js skips the Act 1 pin/scrub entirely and
   renders the static rest constellation. Here we also kill the cue
   pulse and card transitions. Section height collapses to one
   viewport so there's no empty scroll gap with no pinned motion.
   ================================================================= */
@media (prefers-reduced-motion: reduce) {
  #ring-zone { height: 100vh; height: 100svh; }
  .scroll-cue__line { animation: none; }
  .ring-card { transition: none; }
  .ring-label { transition: none; }
  * { scroll-behavior: auto !important; }
}
