/* ==========================================================================
   ronald.is — design tokens + layout
   Ref: Figma Rasterisk / Desktop - 17 (3104:244)

   Follow-ups (planned):
   - Intersection Observer reveal transitions
   - Emil Kowalski / motion skill polish
   ========================================================================== */

/* --------------------------------------------------------------------------
   Fonts — Untitled Sans Light (Klim, licensed)
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Untitled Sans";
  src: url("fonts/untitled-sans-light.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

:root {
  /* —— Color primitives —— */
  --color-page-start: #212026;
  --color-page-end: #0e0d16;

  --color-gold-start: #ffdc7d;
  --color-gold-end: #ffc31d;

  --color-text-gold: #f7eac7;
  /* 60% of text-gold — swap to a solid token later if needed */
  --color-text-muted: color-mix(in srgb, var(--color-text-gold) 60%, transparent);

  --color-card-start: rgba(255, 255, 255, 0.05);
  --color-card-end: rgba(255, 255, 255, 0.02);

  --color-avatar-desat: #d9d9d9;

  /* —— Gradients (tokenised) —— */
  --gradient-page: linear-gradient(
    to bottom,
    var(--color-page-start),
    var(--color-page-end)
  );
  --gradient-gold: linear-gradient(
    to bottom,
    var(--color-gold-start),
    var(--color-gold-end)
  );
  --gradient-card: linear-gradient(
    to bottom,
    var(--color-card-start),
    var(--color-card-end)
  );

  /* —— Stroke / dash (1px dash · 3px gap) —— */
  --stroke-color: var(--color-gold-start);
  --stroke-width: 1px;
  --stroke-dash: 1px;
  --stroke-gap: 3px;
  --stroke-period: calc(var(--stroke-dash) + var(--stroke-gap));

  --stroke-color-22: color-mix(in srgb, var(--stroke-color) 22%, transparent);
  --stroke-color-28: color-mix(in srgb, var(--stroke-color) 38%, transparent);
  --stroke-color-35: color-mix(in srgb, var(--stroke-color) 35%, transparent);

  --line-h: repeating-linear-gradient(
    90deg,
    var(--stroke-color) 0 var(--stroke-dash),
    transparent var(--stroke-dash) var(--stroke-period)
  );
  --line-v: repeating-linear-gradient(
    180deg,
    var(--stroke-color) 0 var(--stroke-dash),
    transparent var(--stroke-dash) var(--stroke-period)
  );
  --line-h-22: repeating-linear-gradient(
    90deg,
    var(--stroke-color-22) 0 var(--stroke-dash),
    transparent var(--stroke-dash) var(--stroke-period)
  );
  --line-v-22: repeating-linear-gradient(
    180deg,
    var(--stroke-color-22) 0 var(--stroke-dash),
    transparent var(--stroke-dash) var(--stroke-period)
  );
  --line-v-28: repeating-linear-gradient(
    180deg,
    var(--stroke-color-28) 0 var(--stroke-dash),
    transparent var(--stroke-dash) var(--stroke-period)
  );
  --line-h-28: repeating-linear-gradient(
    90deg,
    var(--stroke-color-28) 0 var(--stroke-dash),
    transparent var(--stroke-dash) var(--stroke-period)
  );
  --line-h-35: repeating-linear-gradient(
    90deg,
    var(--stroke-color-35) 0 var(--stroke-dash),
    transparent var(--stroke-dash) var(--stroke-period)
  );

  /* Circle ring: N even slices of 360deg (no dash pile-up at the join).
     N ≈ circumference / (dash+gap) so 1px · 3px holds as the logo scales. */
  --ring-dashes: round(
    nearest,
    calc(pi * var(--logo-size) / var(--stroke-period)),
    1
  );
  --ring-period: calc(360deg / var(--ring-dashes));
  --ring-dash: calc(var(--ring-period) * 0.25);

  /* —— Type scale (Figma @1440 → fluid)
     Heading 41 · body 25 · small 17
     Kept on-scale; clamps for ~380–1440 viewports —— */
  --font-sans: "Untitled Sans", ui-sans-serif, system-ui, sans-serif;
  --font-weight-light: 300;

  --text-heading: clamp(1.75rem, 1.45rem + 1vw, 2.25rem); /* 28–36 */
  --text-body: clamp(1.125rem, 0.95rem + 0.7vw, 1.5625rem); /* 18–25 */
  --text-small: clamp(0.9375rem, 0.88rem + 0.25vw, 1.0625rem); /* 15–17 */
  --leading-tight: 1;
  --leading-body: 1.25;

  /* —— Space scale (Figma 36 / 48 / 54 / 72 / 84 / 96) —— */
  --space-2xs: 0.5rem;
  --space-xs: 0.75rem;
  --space-sm: clamp(1.25rem, 1rem + 1vw, 2.25rem); /* ~20–36 */
  --space-md: clamp(1.5rem, 1.1rem + 1.2vw, 3rem); /* ~24–48 indent */
  --space-lg: clamp(2rem, 1.5rem + 1.5vw, 3.375rem); /* ~32–54 */
  --space-xl: clamp(2.5rem, 1.75rem + 2vw, 4.5rem); /* ~40–72 */
  --space-2xl: clamp(2.75rem, 2rem + 2.2vw, 5.25rem); /* ~44–84 card pad */
  --space-3xl: clamp(3rem, 2.25rem + 2.5vw, 6rem); /* ~48–96 */

  /* —— Layout —— */
  --card-max: 38rem;
  --radius-card: 0;
  --avatar-size: clamp(4rem, 3.5rem + 1.5vw, 5.875rem); /* 64–94 */
  --logo-size: clamp(4rem, 3.5rem + 1.5vw, 6rem);
  /* Shared x for page rails, chapter spines, and chapter padding-inline.
     Logo + avatars centre on this inset. */
  --rail-inset: var(--space-2xl);
  /* How far the logo overhangs to the left of the card edge.
     Figma: card at 366.75, logo centre at 451.5 → overhang ≈ card-pad-left. */
  --logo-overhang: var(--rail-inset);
  /* Logo left offset so its centre sits on the left rail */
  --spine-inset: calc(var(--logo-overhang) - var(--logo-size) / 2);
  /* U-frame closes in the page’s bottom padding; site links sit just above */
  --frame-end: calc(2.5rem + var(--space-md));

  /* —— Motion hooks (IO / Kowalski later) —— */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-reveal: 700ms;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
  /* Solid on html so the body gradient is not propagated to the canvas
     (which would size it to the viewport). Overscroll matches page-end. */
  background-color: var(--color-page-end);
}

body {
  margin: 0;
  min-height: 100dvh;
  font-family: var(--font-sans);
  font-weight: var(--font-weight-light);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--color-text-gold);
  background: var(--gradient-page);
  -webkit-font-smoothing: antialiased;
}

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

a {
  color: inherit;
  text-decoration: none;
  transition: color 220ms var(--ease-out-expo);
}

@media (hover: hover) {
  a:hover {
    color: #fff;
  }

  a:hover .text-gold {
    background: none;
    color: #fff;
    -webkit-background-clip: unset;
    background-clip: unset;
  }
}

a:focus-visible {
  outline: 2px solid var(--color-gold-start);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Dashed underline — content links only (not brand mark, not nav) */
a:not(.brand) {
  position: relative;
  isolation: isolate;
  display: inline-block;
}

a:not(.brand)::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset-inline: 0;
  bottom: -4px;
  height: var(--stroke-width);
  pointer-events: none;
  background: var(--line-h);
  background-size: var(--stroke-period) var(--stroke-width);
  opacity: 0.35;
  transition: opacity 220ms var(--ease-out-expo);
}

@media (hover: hover) {
  a:not(.brand):hover::after {
    opacity: 1;
  }
}

a:not(.brand):focus-visible::after {
  opacity: 1;
}

nav a::after {
  content: none;
}

/* Gold gradient text utility */
.text-gold {
  background: var(--gradient-gold);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.text-muted {
  color: var(--color-text-muted);
}

/* --------------------------------------------------------------------------
   Page shell + vertical spine
   -------------------------------------------------------------------------- */

.page {
  position: relative;
  width: min(100% - 2rem, var(--card-max));
  margin-inline: auto;
  /* Extra bottom room so the raised U-frame isn’t flush with the page edge */
  padding-block: clamp(3rem, 4vw, 5.5rem)
    calc(var(--frame-end) + 1.25rem);
  /* Allow logo to hang left without clipping */
  overflow: visible;
}

.page::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: var(--frame-end);
  /* Spine x = card's padding-inline-start = where text starts = logo centre */
  left: var(--rail-inset);
  width: var(--stroke-width);
  background: var(--line-v-28);
  background-size: var(--stroke-width) var(--stroke-period);
  pointer-events: none;
  /* Behind cards (z-index: 1) so it reads through their translucent fill */
  z-index: 0;
}

/* Right rail + bottom connector — U-frame with the left spine.
   Starts at the first chapter (below logo); ends where the left spine ends. */
.page__rail--end {
  position: absolute;
  /* Match first chapter top: page pad-top + logo + brand margin */
  top: calc(
    clamp(3rem, 4vw, 5.5rem) + var(--logo-size) + var(--space-xl)
  );
  bottom: var(--frame-end);
  right: var(--rail-inset);
  width: var(--stroke-width);
  background: var(--line-v-28);
  background-size: var(--stroke-width) var(--stroke-period);
  pointer-events: none;
  z-index: 0;
}

.page__rail--bottom {
  position: absolute;
  left: var(--rail-inset);
  right: var(--rail-inset);
  bottom: var(--frame-end);
  height: var(--stroke-width);
  background: var(--line-h-28);
  background-size: var(--stroke-period) var(--stroke-width);
  pointer-events: none;
  z-index: 0;
}

/* --------------------------------------------------------------------------
   Brand mark
   -------------------------------------------------------------------------- */

.brand {
  position: relative;
  z-index: 1;
  display: block;
  width: var(--logo-size);
  height: var(--logo-size);
  /* Centre logo on the left rail */
  margin-left: var(--spine-inset);
  margin-bottom: var(--space-xl);
  border-radius: 50%;
  overflow: hidden;
  isolation: isolate;
  background: var(--gradient-card);
  backdrop-filter: blur(8px);
}

.brand::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  z-index: 1;
  background: repeating-conic-gradient(
    from 0deg,
    var(--stroke-color) 0 var(--ring-dash),
    transparent var(--ring-dash) var(--ring-period)
  );
  mask: radial-gradient(
    farthest-side,
    transparent calc(100% - var(--stroke-width)),
    #fff calc(100% - var(--stroke-width))
  );
  -webkit-mask: radial-gradient(
    farthest-side,
    transparent calc(100% - var(--stroke-width)),
    #fff calc(100% - var(--stroke-width))
  );
}

.brand__logo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* --------------------------------------------------------------------------
   Chapter cards (ronald is / was)
   -------------------------------------------------------------------------- */

.chapter {
  position: relative;
  z-index: 1;
  margin-bottom: var(--space-xl);
  padding-block: var(--space-2xl);
  padding-inline-start: var(--rail-inset);
  /* Extra --space-sm so copy doesn’t kiss the right spine */
  padding-inline-end: calc(var(--rail-inset) + var(--space-sm));
  border-radius: var(--radius-card);
  border: none;
  background: var(--gradient-card);
  backdrop-filter: blur(8px);
}

/* Spine segments inside each card — live above the backdrop-filter layer
   so they're visible through the translucent fill */
.chapter__spine {
  position: absolute;
  top: 0;
  bottom: 0;
  /* Same x as the page spine: card padding-inline-start = where text begins */
  left: var(--rail-inset);
  width: var(--stroke-width);
  background: var(--line-v-28);
  background-size: var(--stroke-width) var(--stroke-period);
  pointer-events: none;
  z-index: 1;
}

.chapter__spine--end {
  left: auto;
  right: var(--rail-inset);
}

.chapter__stroke {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.chapter__stroke rect {
  fill: none;
  x: 0.5px;
  y: 0.5px;
  width: calc(100% - 1px);
  height: calc(100% - 1px);
  rx: 0;
  ry: 0;
  /* Same mix as the rails/spines — full --stroke-color reads ~3× heavier */
  stroke: var(--stroke-color-28);
  stroke-width: var(--stroke-width);
  stroke-dasharray: var(--stroke-dash) var(--stroke-gap);
  vector-effect: non-scaling-stroke;
}

.chapter__title {
  margin: 0 0 var(--space-md);
  font-size: var(--text-heading);
  font-weight: var(--font-weight-light);
  line-height: var(--leading-tight);
  letter-spacing: 0;
  color: var(--color-text-muted);
}

.chapter__title .text-gold {
  /* restore gradient clip on the emphasized word */
  display: inline;
}

.roles {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  margin: 0;
  padding: 0;
  list-style: none;
}

.role {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.role__title {
  margin: 0;
  font-size: var(--text-body);
  font-weight: var(--font-weight-light);
  line-height: var(--leading-body);
}

.role__title a .text-gold {
  position: relative;
  z-index: 1;
  /* Keep descenders in the fill box so they cover the dash */
  text-box: trim-both cap text;
}

.role__lines {
  margin: 0;
  padding: 0 0 0 var(--space-md);
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.role__lines li {
  color: var(--color-text-muted);
  max-width: 30rem;
}

/* --------------------------------------------------------------------------
   Testimonials
   -------------------------------------------------------------------------- */

.quotes {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-3xl);
  margin: var(--space-3xl) 0;
  padding: 0;
  list-style: none;
}

.quote {
  position: relative;
  display: grid;
  grid-template-columns: var(--avatar-size) minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: var(--space-md);
  row-gap: var(--space-2xs);
  align-items: start;
  /* Centre the avatar on the left rail; end the block at the right rail */
  margin-left: calc(var(--rail-inset) - var(--avatar-size) / 2);
  margin-right: var(--rail-inset);
}

/* East-emerging divider — ends at the right rail (quote box ends at --rail-inset).
   Meta/body use padding-inline-end so type sits inside the rail. */
.quote::after {
  content: "";
  position: absolute;
  top: calc((var(--avatar-size) - var(--stroke-width)) / 2);
  left: var(--avatar-size);
  right: 0;
  height: var(--stroke-width);
  background: var(--line-h-35);
  background-size: var(--stroke-period) var(--stroke-width);
  pointer-events: none;
}

.quote__avatar {
  grid-row: 1 / -1;
  position: relative;
  z-index: 1;
  width: var(--avatar-size);
  height: var(--avatar-size);
  border-radius: 50%;
  border: none;
  overflow: hidden;
  background: transparent;
}

.quote__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

.quote__meta {
  display: flex;
  align-items: flex-end;
  min-height: calc(var(--avatar-size) / 2);
  margin: 0;
  padding-bottom: var(--space-2xs);
  padding-inline-end: var(--space-sm);
  font-size: var(--text-small);
  color: var(--color-text-muted);
}

.quote__text {
  margin: 0;
  padding-inline-end: var(--space-sm);
  font-size: clamp(1.05rem, 0.95rem + 0.5vw, 1.5rem); /* ~17–24 */
  font-weight: var(--font-weight-light);
  line-height: var(--leading-body);
}

/* --------------------------------------------------------------------------
   Site links — centred on the bottom U-frame rail.
   Opaque plate covers the array so the rail dash is hidden under the type.
   -------------------------------------------------------------------------- */

.site-links {
  position: absolute;
  z-index: 1;
  left: 50%;
  bottom: var(--frame-end);
  translate: -50% 41%;
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  gap: 0.35em 0.15em;
  margin: 0;
  padding: 0.35em 0.65em;
  list-style: none;
  font-size: var(--text-small);
  text-align: center;
  /* Continuous plate from first link through last — masks the bottom rail */
  background-color: var(--color-page-end);
  pointer-events: auto;
}

.site-links li:not(:last-child)::after {
  content: "·";
  margin-inline: 0.55em;
  opacity: 0.85;
}

.site-links a {
  color: var(--color-gold-start);
  display: inline;
}

/* --------------------------------------------------------------------------
   Reveal hooks for Intersection Observer (inactive until JS lands)
   -------------------------------------------------------------------------- */

[data-reveal] {
  /* reserved — opacity/transform set by motion layer later */
}

/* --------------------------------------------------------------------------
   text-box-trim
   Does not inherit — applied to type-bearing elements.
   Headings: cap-height top, descender bottom.
   Body: cap-height top, alphabetic baseline.
   Quotes: left untrimmed (gradient clip + last-line descenders).
   -------------------------------------------------------------------------- */

:is(h1, h2, h3, h4) {
  text-box: trim-both cap text;
}

:is(p, li, a, span) {
  text-box: trim-both cap alphabetic;
}

/* Quotes keep the full font box — trim + background-clip:text clips last-line descenders */
.quote__text {
  text-box-trim: none;
}


/* --------------------------------------------------------------------------
   Narrow viewports
   -------------------------------------------------------------------------- */

@media (max-width: 520px) {
  :root {
    --rail-inset: var(--space-lg);
  }

  .page {
    width: min(100% - 1.25rem, var(--card-max));
  }

  .chapter {
    padding-block: var(--space-xl);
  }
}
