/* ==========================================================================
   Lift The Value
   Static rebuild. Values resolved from the rendered DOM / computed styles.
   ========================================================================== */

/* ---------- Self-hosted fonts ------------------------------------------- */
/* Copied verbatim from the Google Fonts css2 response for
   Space Grotesk 700 / IBM Plex Sans 400,500,600 / IBM Plex Mono 400, with only
   the src URL swapped for the local file. unicode-range is preserved exactly,
   so per-glyph fallback (the ▼ ▲ arrows are not in these subsets) is unchanged.
   Only the `latin` subset is shipped — it is the only one the page's glyphs
   pull in. Space Grotesk and IBM Plex Sans are variable fonts, so the three
   IBM Plex Sans weights share one file. */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(../assets/fonts/ibm-plex-sans-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(../assets/fonts/ibm-plex-sans-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(../assets/fonts/ibm-plex-sans-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(../assets/fonts/space-grotesk-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../assets/fonts/ibm-plex-mono-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ---------- Tokens ------------------------------------------------------ */
:root {
  /* Core palette */
  --bg:            #F4EFE6;   /* page background */
  --header-bg:     rgba(244, 239, 230, 0.9);
  --surface:       #EDE7DC;   /* media wells, progress track */
  --pill-hover:    #F0EBE1;
  --white:         #FFFFFF;
  --ink:           #152430;
  --primary:       #12557F;
  --primary-dark:  #0E4468;
  --teal:          #1E8C7E;
  --teal-link:     #35C6AE;
  --amber:         #C08A2E;
  --muted:         #4A5C69;   /* body muted */
  --card-body:     #5A6B77;
  --feed-name:     #3C4E5B;
  /* Deliberate deviation from the design source: the captured token was
     #8B9AA5, which is 2.52:1 on the cream page and 2.89:1 on white at 12px —
     a WCAG AA failure. Darkened until both pairs clear 4.5:1. See README. */
  --mono-label:    #5F6E78;
  --panel-label:   #7C97A5;
  --panel-text:    #9CB4BF;
  --panel-base:    #CFDDE4;

  /* Service-card icon swatches */
  --swatch-1: #DCEAF3;
  --swatch-2: #D8EDE7;
  --swatch-3: #F3E3CB;
  --swatch-4: #E3E0F0;
  --swatch-5: #DCE6E3;

  /* Shadows */
  --sh-pill:  0 2px 10px rgba(21, 36, 48, 0.06);
  --sh-card:  0 12px 30px rgba(21, 36, 48, 0.06);
  --sh-panel: 0 12px 30px rgba(21, 36, 48, 0.07);
  --sh-hover: 0 18px 34px rgba(21, 36, 48, 0.10);
  --sh-hero:  0 30px 60px rgba(21, 36, 48, 0.14);

  /* Type */
  --font-body:    'IBM Plex Sans', system-ui, sans-serif;
  --font-display: 'Space Grotesk', sans-serif;
  --font-mono:    'IBM Plex Mono', monospace;

  /* Radii */
  --r-pill:  999px;
  --r-hero:  clamp(18px, 3vw, 36px);
  --r-card:  clamp(18px, 2.5vw, 28px);
  --r-panel: clamp(18px, 2.5vw, 32px);
  --r-big:   clamp(20px, 3vw, 40px);

  /* Layout */
  --wrap:   1220px;
  --header-offset: 90px;
}

/* ---------- Base -------------------------------------------------------- */
* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

body {
  -webkit-font-smoothing: antialiased;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  min-height: 100vh;
}

a { color: inherit; text-decoration: none; }
a:hover { color: var(--teal-link); }

/* ---------- Focus ------------------------------------------------------- */
/* Keyboard-only ring, drawn in the primary petrol so it reads as part of the
   palette. `outline` follows each element's own border-radius, so the pills,
   buttons and the feed toggle all get a ring in their own shape. Never
   `outline: none` without one of these replacing it. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}

/* The email button sits ON the blue card, where a petrol ring would vanish, so
   that one inverts to cream. */
.btn-email:focus-visible { outline-color: var(--bg); }

img, video { max-width: 100%; }

.wrap { max-width: var(--wrap); margin: 0 auto; }

/* Anchor targets clear the sticky header even without JS. */
#c-services, #c-live, #c-about, #c-contact { scroll-margin-top: var(--header-offset); }

/* ---------- Keyframes --------------------------------------------------- */
@keyframes ltv-marquee { from { transform: translateX(0); }              to { transform: translateX(-50%); } }
@keyframes ltv-rise    { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
@keyframes ltv-grow    { from { transform: scaleY(0.02); }               to { transform: scaleY(1); } }
@keyframes ltv-pulse   { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
@keyframes ltv-float   { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }

/* Reveal state applied by js/main.js */
.is-revealing { animation: ltv-rise 750ms cubic-bezier(0.2, 0.8, 0.2, 1) both; }

/* ---------- Status dots ------------------------------------------------- */
.dot { border-radius: 50%; display: inline-block; flex: none; }
.dot-teal  { width: 7px; height: 7px; background: var(--teal); }
.dot-2200  { animation: ltv-pulse 2.2s ease-in-out infinite; }
.dot-1600  { animation: ltv-pulse 1.6s ease-in-out infinite; }

/* ==========================================================================
   1. Header
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  /* `center`, not `space-between`: justify-content acts per flex LINE, and when
     the pills wrap below their own row (<=415px) they are the only item on that
     line — space-between shoved that lone item to flex-start (left). `center`
     centres the wrapped row; the side-by-side layout at wider widths is
     reproduced exactly by the auto margins on .logo and .site-header::after
     below, so no width band changes except the intended centring. */
  justify-content: center;
  gap: 24px;
  padding: 14px clamp(16px, 3vw, 40px);
  flex-wrap: wrap;
  background: var(--header-bg);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

/* margin-right auto: with justify-content now `center`, this auto margin soaks
   up the line's free space and keeps the logo flush left / pills flush right on
   the one-row layouts (416-599px), exactly as space-between did. On the wrapped
   layout the logo is alone on its line, so it stays flush left there too. */
.logo { height: 38px; width: auto; display: block; margin-right: auto; }

.nav-pills {
  display: flex;
  gap: 8px;
  padding: 6px;
  background: var(--white);
  border-radius: var(--r-pill);
  box-shadow: var(--sh-pill);
}

.pill {
  padding: 9px 18px;
  border-radius: var(--r-pill);
  color: var(--muted);
  font-size: 14px;
}
.pill:hover { background: var(--pill-hover); color: var(--primary); }

.pill-active { background: var(--primary); color: var(--white); }
/* In the original, the active pill carried its own class, so the Services /
   Contact hover rule never touched it and hovering "Home" was a visual no-op.
   Here .pill-active also matches .pill, so the background has to be restated
   to keep that no-op behaviour. */
.pill-active:hover { background: var(--primary); color: var(--white); }

/* The header once held three items (logo, pills, CTA button) and `space-between`
   put the pills on the page centre for free. With the CTA gone there are only
   two, so `space-between` would fling the pills against the right edge. This
   spacer restores the third slot: it mirrors the logo's rendered width, which
   puts the pills back on the true centre.

   84px is derived, not magic — the logo is intrinsically 168x76 and `.logo`
   renders it at `height: 38px`, so 168 * (38 / 76) = 84. If the logo file or
   its rendered height ever changes, recompute this to match.

   The spacer is gated to >=600px because it must not be the thing that forces a
   new row. Letting it shrink instead of gating it does NOT work: flex-wrap is
   applied before flex-shrink, so a shrinkable spacer wraps to its own row rather
   than giving up width (measured: it added a third row at 390px). One row needs
   84 + 24 + 275.5 + 24 + 84 = 491.5px of content box, which 600px clears with
   ~72px to spare — enough that a webfont failing to load, and the pills growing
   in the fallback face, still cannot push it over.

   That gate costs one narrow band, 543-599px, where the pills sit flush right
   instead of centred — 57px of viewport width, left alone deliberately rather
   than spent on a third layout rule. Everywhere below it the header is strictly
   better than it was with the button: it used to need 543px to fit on one row
   and now needs 416px, so 416-542px went from two rows to one, and below 415px
   from three rows to two. */
@media (min-width: 600px) {
  .site-header::after {
    content: "";
    width: 84px;
    height: 0;
    /* Pairs with .logo's margin-right auto: the two auto margins split the
       line's free space evenly, which lands the pills on the same page-centre
       position space-between produced with three items. */
    margin-left: auto;
  }
}

/* ==========================================================================
   2. Hero copy
   ========================================================================== */
.s-hero {
  padding: clamp(36px, 6vw, 56px) clamp(16px, 4vw, 40px) 36px;
  text-align: center;
}

.hero-inner { max-width: 960px; margin: 0 auto; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 26px;
  padding: 8px 16px;
  border-radius: var(--r-pill);
  background: var(--white);
  box-shadow: var(--sh-pill);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--teal);
}

.h-hero {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(44px, 6vw, 96px);
  line-height: 0.96;
  letter-spacing: -0.04em;
  color: var(--ink);
  text-wrap: balance;
}

.hero-sub {
  margin: 26px auto 0;
  max-width: 620px;
  font-size: 18px;
  line-height: 1.6;
  color: var(--muted);
  text-wrap: pretty;
}

.hero-cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 32px;
}

.btn-ghost {
  display: inline-flex;
  align-items: center;
  padding: 16px 28px;
  border-radius: var(--r-pill);
  background: var(--white);
  color: var(--ink);
  font-size: 16px;
  box-shadow: var(--sh-pill);
}
.btn-ghost:hover { background: var(--surface); color: var(--ink); }

/* ==========================================================================
   3. Hero media
   ========================================================================== */
.s-heromedia { padding: 0 clamp(12px, 3vw, 24px) clamp(40px, 6vw, 64px); }

.hero-well {
  position: relative;
  border-radius: var(--r-hero);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--sh-hero);
}

/* height:auto lets the width/height attributes act as an aspect-ratio hint
   (no layout shift) instead of a hard pixel height. */
.hero-video { width: 100%; height: auto; max-height: 620px; display: block; object-fit: cover; }
/* The stand-in poster keeps the well's 620px cap and crop, so the mobile /
   reduced-motion / no-JS layout matches the design at every width. */
.hero-poster { width: 100%; height: auto; max-height: 620px; display: block; object-fit: cover; }

/* ==========================================================================
   4. Services
   ========================================================================== */
/* Verbatim from source: fixed 40px sides, not a clamp. */
.s-services { padding: 0 40px 80px; }

.h-services {
  margin: 0 0 32px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(30px, 3.4vw, 48px);
  letter-spacing: -0.03em;
  color: var(--ink);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
}

.card {
  background: var(--white);
  border-radius: var(--r-card);
  padding: clamp(20px, 3vw, 30px) clamp(18px, 2.5vw, 26px);
  transition: transform 220ms, box-shadow 220ms;
}
.card:hover { transform: translateY(-6px); box-shadow: var(--sh-hover); }

.swatch { width: 46px; height: 46px; border-radius: 16px; margin-bottom: 24px; }
.swatch-1 { background: var(--swatch-1); }
.swatch-2 { background: var(--swatch-2); }
.swatch-3 { background: var(--swatch-3); }
.swatch-4 { background: var(--swatch-4); }
.swatch-5 { background: var(--swatch-5); }

.h-card {
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 21px;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.p-card { margin: 0; font-size: 15px; line-height: 1.6; color: var(--card-body); }

/* ==========================================================================
   5. Live
   ========================================================================== */
.s-live { padding: 0 clamp(16px, 4vw, 40px) clamp(48px, 6vw, 72px); }

.live-head { margin: 0 auto 26px; }

.h-live {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(26px, 3vw, 40px);
  letter-spacing: -0.03em;
  color: var(--ink);
}

.section-sub {
  margin: 12px 0 0;
  max-width: 620px;
  font-size: 16px;
  line-height: 1.6;
  color: var(--muted);
}

.live-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 24px;
}

.panel-light {
  background: var(--white);
  border-radius: var(--r-panel);
  padding: clamp(20px, 3vw, 30px);
  box-shadow: var(--sh-panel);
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 22px;
}

.mono-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mono-label);
}

.live-label {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--teal);
}

/* Groups the Live label with its pause control so `justify-content:
   space-between` still puts one item at each end of the panel head. */
.live-group { display: flex; align-items: center; gap: 12px; }

/* WCAG 2.2.2: the feed animates on a timer, so it needs a user control.
   Sized 24px for the minimum target, then pulled back 5px top and bottom so
   the panel head stays at its designed 14px row height — the overhang falls
   in the panel's own padding, and the layout is pixel-identical to the source.
   Only shown when JS is running; without JS the feed is static anyway. */
.feed-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 24px;
  min-width: 24px;
  margin: -5px 0;
  padding: 0 12px;
  /* Boundary drawn in the label's own colour: 5.27:1 on the white panel, so
     the control is identifiable without a second accent colour (WCAG 1.4.11). */
  border: 1px solid var(--mono-label);
  border-radius: var(--r-pill);
  background: var(--white);
  color: var(--mono-label);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  line-height: 1;
  text-transform: uppercase;
  cursor: pointer;
}
.feed-toggle:hover { background: var(--pill-hover); color: var(--primary); }
/* aria-pressed="false" == feed paused: mark the non-default state. The state is
   also carried by the visible word (Pause / Play), never by colour alone. */
.feed-toggle[aria-pressed="false"] { color: var(--primary); }
.feed-toggle[hidden] { display: none; }

.feed-row {
  display: grid;
  grid-template-columns: minmax(100px, 140px) minmax(90px, 1fr) 62px 56px;
  gap: 12px;
  align-items: center;
  padding: 11px 0;
}

.feed-name { font-family: var(--font-mono); font-size: 13px; color: var(--feed-name); }

.bar-track {
  display: block;
  height: 10px;
  border-radius: var(--r-pill);
  background: var(--surface);
}

.bar-fill {
  display: block;
  height: 10px;
  border-radius: var(--r-pill);
  background: var(--primary);
  transition: width 900ms;
}

.feed-cpa { font-family: var(--font-mono); font-size: 14px; color: var(--ink); text-align: right; }

.feed-delta { font-family: var(--font-mono); font-size: 12px; text-align: right; }
.delta-down { color: var(--teal); }
.delta-up   { color: var(--amber); }

.panel-dark {
  background: var(--ink);
  border-radius: var(--r-panel);
  padding: clamp(20px, 3vw, 30px);
  color: var(--panel-base);
}

.panel-dark-label { color: var(--panel-label); margin-bottom: 20px; }

.log-lines { display: flex; flex-direction: column; gap: 11px; }

/* The seed strings keep their literal column padding, but — exactly as in the
   original render — HTML whitespace collapsing makes them display single-spaced.
   Do not add white-space: pre-wrap here; it would not match the design. */
.log-line {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  color: var(--panel-text);
}
.log-line-new { animation: ltv-rise 400ms ease-out both; }

/* ==========================================================================
   6. About
   ========================================================================== */
.s-about { padding: 0 clamp(16px, 4vw, 40px) clamp(48px, 6vw, 80px); }

.about-card {
  max-width: var(--wrap);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: clamp(24px, 3vw, 56px);
  align-items: center;
  background: var(--white);
  border-radius: var(--r-big);
  padding: clamp(20px, 3vw, 44px);
  box-shadow: var(--sh-card);
}

.about-well { border-radius: 28px; overflow: hidden; background: var(--surface); }

.about-video { width: 100%; height: auto; display: block; object-fit: cover; }
.about-poster { width: 100%; height: auto; display: block; }

.h-about {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(28px, 3.2vw, 44px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--ink);
}

.p-about { margin: 22px 0 0; font-size: 17px; line-height: 1.65; color: var(--muted); max-width: 480px; }

/* ==========================================================================
   7. Contact + footer
   ========================================================================== */
/* The footer used to live inside this section and inherited its padding. It is
   now a real <footer> outside <main> (so it is a contentinfo landmark), and
   .page-footer carries the padding the section used to supply — the 20px that
   was .site-footer's margin-top plus the page's bottom padding. Net geometry
   is unchanged. */
.s-contact { padding: 0 clamp(16px, 4vw, 40px); }

.page-footer { padding: 20px clamp(16px, 4vw, 40px) clamp(48px, 6vw, 72px); }

.contact-card {
  max-width: var(--wrap);
  margin: 0 auto;
  background: var(--primary);
  border-radius: var(--r-big);
  padding: clamp(32px, 5vw, 64px) clamp(20px, 4vw, 56px);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
}

.h-contact {
  margin: 0;
  max-width: 600px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(28px, 3.2vw, 46px);
  line-height: 1.06;
  letter-spacing: -0.03em;
  color: var(--white);
}

.btn-email {
  padding: 18px 30px;
  border-radius: var(--r-pill);
  background: var(--bg);
  color: var(--primary);
  font-size: 17px;
  font-weight: 600;
}
.btn-email:hover { background: var(--white); color: var(--primary-dark); }

.site-footer {
  max-width: var(--wrap);
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 20px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mono-label);
}

/* ==========================================================================
   404 page (404.html) — same tokens, no new colours
   ========================================================================== */
.s-404 {
  min-height: calc(100vh - 84px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(36px, 6vw, 56px) clamp(16px, 4vw, 40px) clamp(48px, 6vw, 72px);
  text-align: center;
}

.code-404 {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mono-label);
  margin-bottom: 18px;
}

/* ==========================================================================
   Media swap — deliberately NOT a media query.
   There is no `display: none` on a <video> anywhere in this file, and that is
   the point: a hidden <video> with `autoplay` still downloads its source, which
   cost mobile ~1.26 MB before. js/main.js builds exactly one element per media
   well — a <video> only at >=768px with motion allowed, the poster <img>
   otherwise — so bytes are never fetched for something that is not shown.
   Breakpoint and behaviour match the original (window.innerWidth < 768).
   The <noscript> block in each well ships the same poster for JS-off.
   ========================================================================== */

/* ==========================================================================
   Reduced motion — no reveal animation, no pulse, no autoplaying video.
   (The video/poster choice itself is made in JS, see above.)
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
