@import url("fonts.css");

/* ==========================================================================
   DataBeacon — design system (light)
   Brand: navy #011b26, teal #168485, Barlow (self-hosted, no CDN).
   One stylesheet, no build step, no JS dependency for layout.

   RULE: no literal colour may appear outside :root (and the two documented
   dark-context blocks below). Verify with:
       grep -n '#[0-9a-f]\{3,6\}' assets/css/site.css
   Everything else must go through a token, which is what lets a dark chapter
   re-skin every component by redefining tokens instead of overriding rules.

   Contrast (WCAG 2.1, computed — do not "improve" these by eye):
     --ink      on --paper   17.6:1     --teal-ink on --paper    7.4:1
     --ink-2    on --paper    6.8:1     --teal     on --paper    4.5:1  ⚠ large/fill only
     --on-dark  on --navy    17.7:1     --teal-bright on --navy  8.3:1
   ========================================================================== */

:root {
  /* ---- surfaces ---- */
  --paper:       #ffffff;   /* default chapter */
  --surface:     #f5f6f7;   /* tinted chapter, footer */
  --surface-2:   #eceff1;   /* media wells, bezels, quiet buttons */
  --line:        #e3e6e8;
  --line-2:      #d8dcde;

  /* ---- ink ---- */
  --ink:         #0b1b22;   /* headings + body */
  --ink-2:       #4f5d63;   /* secondary text, ledes, captions */

  /* ---- brand ---- */
  --navy:        #011b26;   /* dark chapter background */
  --navy-2:      #04222e;   /* inner surfaces inside a dark chapter */
  --navy-3:      #062b39;
  --teal:        #168485;   /* FILLS and large text only — never small text on white */
  --teal-ink:    #0d5f60;   /* links, eyebrows, small text */
  --teal-bright: #2ec4c5;   /* accents on navy ONLY */
  --teal-wash:   #e8f2f2;

  /* ---- dark-context ink ---- */
  --on-dark:     #ffffff;
  --on-dark-2:   #c3d2d5;
  --line-dark:   rgba(255, 255, 255, .14);
  --shadow:      rgba(1, 27, 38, .22);
  --shadow-soft: rgba(1, 27, 38, .06);
  --hairline:    rgba(1, 27, 38, .10);

  /* ---- status ---- */
  --ok:   #1f8a4c;          /* darkened from #3dc372 — unusable on white */
  --warn: #b3660f;          /* darkened from #ff9e45 — unusable on white */

  /* ---- weights ----
     Barlow ships 300/400/500/600/900 here. Never write a bare number: an
     unavailable weight silently resolves upward (600 used to render as 900,
     which is why the old site read so heavy). */
  --wt-body:    400;
  --wt-medium:  500;
  --wt-bold:    600;
  --wt-display: 600;

  /* ---- measure ---- */
  --measure:     38rem;
  --wrap:        78rem;
  --wrap-narrow: 46rem;
  --wrap-wide:   96rem;
  --header-h:    72px;
  --gutter:      clamp(1.25rem, 4vw, 2.5rem);
  --radius:      clamp(12px, 1.4vw, 22px);

  /* ---- type scale ---- */
  --step--1: clamp(.8125rem, .79rem + .1vw, .875rem);
  --step-0:  clamp(1.0625rem, 1.03rem + .16vw, 1.125rem);
  --step-1:  clamp(1.25rem, 1.15rem + .5vw, 1.5rem);
  --step-2:  clamp(1.625rem, 1.35rem + 1.2vw, 2.25rem);
  --step-3:  clamp(2.125rem, 1.6rem + 2.4vw, 3.5rem);
  --step-4:  clamp(2.75rem, 1.85rem + 4.2vw, 5rem);
  --step-5:  clamp(3rem, 1.9rem + 5.4vw, 6.5rem);
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: clip; }

body {
  margin: 0;
  font-family: Barlow, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: var(--step-0);
  font-weight: var(--wt-body);
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  margin: 0 0 .4em;
  font-weight: var(--wt-bold);
  line-height: 1.08;
  letter-spacing: -.021em;
  text-wrap: balance;
  color: var(--ink);
}
h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); line-height: 1.15; letter-spacing: -.012em; }
h4 { font-size: var(--step-1); }

/* Display type: sub-1 leading and heavier negative tracking only work above
   ~48px. Barlow needs more negative tracking than a system UI face; past
   -.045em the "fl"/"ti" pairs start to collide. */
.display, .hero h1 {
  font-size: var(--step-5);
  font-weight: var(--wt-display);
  line-height: .98;
  letter-spacing: -.035em;
  max-width: 16ch;
}

p { margin: 0 0 1.15em; max-width: var(--measure); }
a { color: var(--teal-ink); text-decoration-thickness: 1px; text-underline-offset: .18em; }
a:hover { color: var(--teal); }
img, video { max-width: 100%; height: auto; display: block; }
strong { font-weight: var(--wt-bold); }
code {
  font-size: .9em; background: var(--surface-2); color: var(--ink);
  padding: .1em .4em; border-radius: 4px;
}

:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--teal-ink); outline-offset: 3px; border-radius: 4px;
}

/* ---------- layout ---------- */
.wrap   { width: min(100% - (var(--gutter) * 2), var(--wrap)); margin-inline: auto; }
.wrap-n { width: min(100% - (var(--gutter) * 2), var(--wrap-narrow)); margin-inline: auto; }
.wrap-w { width: min(100% - (var(--gutter) * 2), var(--wrap-wide)); margin-inline: auto; }

/* `.section` is the legacy name, `.chapter` the new one. Both are live so
   pages can migrate one at a time; drop the `.section*` selectors once every
   page uses `.chapter`. */
.section, .chapter {
  position: relative;
  padding-block: clamp(5rem, 12vh, 10rem);
  background: var(--paper);
  color: var(--ink);
}

.section--alt, .chapter--tint { background: var(--surface); }

/* Opt-in full height. min() so tall content is never trapped, svh so iOS
   Safari's collapsing URL bar doesn't make it jump. */
.chapter--full {
  min-height: min(100svh, 60rem);
  display: grid;
  align-content: center;
}

.center, .chapter--centred { text-align: center; }
.center :is(p, .lede), .chapter--centred :is(p, .lede) { margin-inline: auto; }
.center .btn-row, .chapter--centred .btn-row { justify-content: center; }

/* ---------- the dark chapter ----------
   This is the load-bearing idea of the stylesheet. A dark context redefines
   the TOKENS rather than overriding each component, so every component —
   including ones written later — works on navy for free. The eight
   `.section--dark h2 {}`-style overrides this replaces are all gone. */
.section--dark, .chapter--dark, .hero {
  background: var(--navy);
  color: var(--on-dark-2);
  --ink: var(--on-dark);
  --ink-2: var(--on-dark-2);
  --paper: var(--navy-2);
  --surface: var(--navy-2);
  --surface-2: var(--navy-3);
  --line: var(--line-dark);
  --line-2: var(--line-dark);
  --teal-ink: var(--teal-bright);
  --hairline: var(--line-dark);
  color-scheme: dark;
}

.eyebrow {
  font-size: var(--step--1);
  font-weight: var(--wt-bold);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--teal-ink);
  margin: 0 0 1.25rem;
  max-width: none;
}

.lede {
  font-size: var(--step-1);
  font-weight: var(--wt-body);
  line-height: 1.4;
  letter-spacing: -.01em;
  color: var(--ink-2);
  max-width: 44ch;
}

/* ---------- header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--paper) 72%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid var(--line);
}
@supports not (backdrop-filter: blur(1px)) {
  .site-header { background: var(--paper); }
}
.site-header .wrap { display: flex; align-items: center; gap: 1.5rem; min-height: var(--header-h); }

.brand { display: flex; align-items: center; gap: .6rem; text-decoration: none; }
.brand img { height: 30px; width: auto; }
.brand__word {
  color: var(--ink); font-weight: var(--wt-medium);
  letter-spacing: -.02em; line-height: 1; font-size: 1.25rem;
}

.nav { display: flex; gap: 1.5rem; margin-left: auto; align-items: center; }
.nav a {
  color: var(--ink-2); text-decoration: none;
  font-size: .9375rem; font-weight: var(--wt-body); white-space: nowrap;
}
.nav a:hover, .nav a[aria-current="page"] { color: var(--ink); }
.nav .btn { color: var(--paper); }

/* Mobile menu — a <details> disclosure, so aria-expanded, Enter/Space and
   Escape are free and no JavaScript is involved. `display: contents` at
   desktop makes the panel a direct flex child of the header, so ONE set of
   link markup serves both breakpoints. */
.menu { margin-left: auto; }
.menu__btn { list-style: none; cursor: pointer; padding: .5rem; display: inline-flex; }
.menu__btn::-webkit-details-marker { display: none; }
.menu__btn span, .menu__btn span::before, .menu__btn span::after {
  display: block; width: 22px; height: 1.5px; background: var(--ink); content: "";
}
.menu__btn span { position: relative; }
.menu__btn span::before { position: absolute; top: -7px; }
.menu__btn span::after  { position: absolute; top: 7px; }
.menu__panel {
  position: fixed; inset: var(--header-h) 0 auto 0;
  background: color-mix(in srgb, var(--paper) 94%, transparent);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--line);
  padding: 1.5rem var(--gutter) 2rem;
  display: grid; gap: 1.25rem; font-size: var(--step-1);
}
@media (min-width: 56rem) {
  .menu { display: contents; }
  .menu__btn { display: none; }
  .menu__panel {
    position: static; background: none; backdrop-filter: none; border: 0;
    padding: 0; grid-auto-flow: column; gap: 1.5rem; font-size: .9375rem;
    align-items: center; margin-left: auto;
  }
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .82em 1.5em; border-radius: 999px;
  font-weight: var(--wt-bold); font-size: var(--step-0); letter-spacing: 0;
  text-transform: none; text-decoration: none; cursor: pointer;
  border: 1px solid transparent;
  transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}
/* Primary is an INK pill, not teal: white-on-#168485 is 4.49:1 and fails AA.
   Inside a dark chapter the tokens flip, so this becomes a white pill with a
   navy label automatically. */
.btn--primary { background: var(--ink); color: var(--paper); }
.btn--primary:hover { background: var(--teal-ink); color: var(--paper); }

.btn--quiet { background: var(--surface-2); color: var(--ink); }
.btn--quiet:hover { background: var(--teal-wash); color: var(--teal-ink); }

/* Apple's real secondary action: a plain link with a chevron, no chrome.
   `.btn--ghost` is the legacy name kept until the HTML pass retires it — it
   was white-on-transparent and has no light equivalent. */
.btn--text, .btn--ghost {
  padding: .82em 0; color: var(--teal-ink); background: none; border: 0;
}
.btn--text::after, .btn--ghost::after {
  content: " \203A"; font-weight: var(--wt-body); padding-left: .3em;
}
.btn--text:hover, .btn--ghost:hover {
  color: var(--teal-ink); text-decoration: underline; text-underline-offset: .25em;
}

.btn-row { display: flex; gap: 1.25rem; flex-wrap: wrap; align-items: center; margin-top: 2rem; }

/* ---------- hero ----------
   Still the legacy text-over-video treatment, and still dark: the markup
   carries a full-bleed <video> behind white text. Phase 3 replaces it with
   type-on-white above a framed stage; until the markup changes, turning this
   light would put white text on a white background. */
.hero { overflow: clip; }   /* clip, NOT hidden: hidden would create a scroll
                               container and silently break every sticky
                               descendant on the page. */
.hero__media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .38; }
.hero__inner { position: relative; padding: clamp(4rem, 11vw, 9rem) 0 clamp(3.5rem, 8vw, 6rem); }
.hero h1 { max-width: 18ch; }

.hero__platform { position: absolute; top: 0; right: 0; z-index: 2; display: block; line-height: 0; }
.hero__platform img { width: clamp(9rem, 15vw, 14rem); height: auto; }
@media (max-width: 46rem) {
  .hero__platform { position: static; margin-bottom: 2rem; }
  .hero__platform img { width: 9rem; }
}

/* Picks LIVE and REPLAY out of the hero headline. The old version added a
   breathing neon glow; there is no version of that which reads as intentional
   on white, so it is colour only now. */
.hl { color: var(--teal-ink); font-weight: var(--wt-bold); white-space: nowrap; }

/* ---------- steps ---------- */
.steps {
  display: grid; gap: clamp(2rem, 4vw, 3.5rem);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  margin-top: 3rem;
}
.step__n {
  font-size: var(--step--1); font-weight: var(--wt-bold);
  letter-spacing: .12em; color: var(--teal-ink); text-transform: uppercase;
}
.step h3 { margin-top: .5rem; }
.step p { color: var(--ink-2); margin-bottom: 0; }

/* ---------- metrics ----------
   Giant numerals over a hairline, not bordered boxes. This is also what
   retires the six inline white-on-dark styles in technology/index.html —
   there is no box left to un-box. */
.metrics {
  display: grid; gap: clamp(1.5rem, 3vw, 3rem);
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  margin-top: clamp(2.5rem, 5vw, 4rem);
}
.metric { border-top: 1px solid var(--line); padding-top: 1.25rem; }
.metric__v {
  font-size: var(--step-4); font-weight: var(--wt-display); line-height: 1;
  color: var(--ink); letter-spacing: -.035em;
  font-variant-numeric: tabular-nums;   /* Barlow's `1` is narrow; without this
                                           a row of metrics visibly jitters. */
}
.metric__k { font-size: var(--step-0); color: var(--ink-2); margin-top: .75rem; max-width: 22ch; }
.note { font-size: var(--step--1); color: var(--ink-2); margin-top: 2rem; max-width: var(--measure); }

/* ---------- product cards ---------- */
.products {
  display: grid; gap: clamp(1.5rem, 2.5vw, 2rem);
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  margin-top: 3rem;
}
.card {
  display: flex; flex-direction: column;
  border-radius: 18px; overflow: hidden; background: var(--surface);
  transition: transform .25s ease, box-shadow .25s ease;
}
.card:hover { transform: translateY(-4px); box-shadow: 0 18px 40px -20px var(--shadow); }
/* The product shots are transparent device cut-outs with dark screens. On a
   light well the screen becomes the focal point — the same treatment Apple
   uses. (This well used to be navy, which camouflaged them.) */
.card__media {
  aspect-ratio: 4 / 3; object-fit: contain; width: 100%;
  background: var(--surface-2); padding: clamp(1.25rem, 3vw, 2rem);
}
/* For the two card images that are NOT cut-outs (an opaque screenshot and a
   full-bleed photo) — fill the frame instead of floating in the well. */
.card__media--photo { object-fit: cover; background: none; padding: 0; }
.card__body { padding: 1.75rem; display: flex; flex-direction: column; flex: 1; }
.card__body h3 { margin-bottom: .35rem; }
.card__body p { color: var(--ink-2); flex: 1; max-width: none; }
.card__kicker {
  font-size: .8125rem; color: var(--teal-ink); font-weight: var(--wt-bold);
  letter-spacing: .04em; text-transform: uppercase;
}

/* ---------- feature rows ---------- */
.feature { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center; grid-template-columns: 1fr; }
@media (min-width: 56rem) {
  .feature { grid-template-columns: 1fr 1fr; gap: clamp(3rem, 7vw, 7rem); }
  .feature--flip .feature__media { order: -1; }
  .feature--wide { grid-template-columns: .85fr 1.15fr; }
}
.feature + .feature { margin-top: clamp(4rem, 10vw, 8rem); }
.feature__media img, .feature__media video { border-radius: var(--radius); width: 100%; }

/* ---------- bezel ----------
   For screenshots that are themselves dark (the ATC interfaces are drawn on
   #202020 and cannot be recoloured — they are operational displays). The
   light well plus an inner hairline stops them reading as a hole punched in
   the page. */
.bezel {
  margin: 0;
  background: var(--surface-2);
  border-radius: var(--radius);
  padding: clamp(.75rem, 1.4vw, 1.25rem);
  box-shadow: 0 1px 2px var(--shadow-soft), 0 20px 48px -28px var(--shadow);
}
.bezel img, .bezel video {
  width: 100%; border-radius: calc(var(--radius) - .5rem);
  border: 1px solid var(--hairline);
}
.bezel figcaption { font-size: var(--step--1); color: var(--ink-2); margin-top: .9rem; max-width: 60ch; }
.chapter--dark .bezel, .section--dark .bezel { box-shadow: none; }

/* ---------- sticky media ("the media stays, the text scrolls") ---------- */
.scrolly__grid { display: grid; gap: clamp(2rem, 5vw, 5rem); grid-template-columns: 1fr; }
@media (min-width: 60rem) {
  .scrolly__grid { grid-template-columns: 1.15fr .85fr; align-items: start; }
  .scrolly__media {
    position: sticky;
    top: calc(var(--header-h) + clamp(1.5rem, 6vh, 4rem));
    align-self: start;   /* REQUIRED. A grid item defaults to `stretch`, which
                            fills the row and leaves sticky nothing to do —
                            this is the usual reason the effect "doesn't work". */
  }
  .scrolly--flip .scrolly__media { order: -1; }
  .beat { min-height: 78svh; display: grid; align-content: center; }
  .beat:first-child, .beat:last-child { min-height: 60svh; }
}
@media (max-width: 59.99rem) {
  .scrolly__media { position: static; margin-bottom: 2rem; }
  .beat + .beat { margin-top: 2.5rem; }
}

/* ---------- scroll reveal ----------
   Decoration only. Firefox stable still has scroll-driven animations behind a
   flag, so the fallback is the finished state: visible, no transform. Never
   used for anything the layout depends on, and never in the hero (it must not
   delay the largest contentful paint). */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: reveal-in linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 34%;
    }
    @keyframes reveal-in {
      from { opacity: 0; transform: translateY(24px); }
      to   { opacity: 1; transform: none; }
    }
  }
}

/* ---------- list ---------- */
.ticks { list-style: none; padding: 0; margin: 1.5rem 0 0; max-width: var(--measure); }
.ticks li { padding-left: 1.6rem; position: relative; margin-bottom: .7rem; }
.ticks li::before {
  content: ""; position: absolute; left: 0; top: .58em;
  width: .5rem; height: .5rem; border-radius: 50%; background: var(--teal-ink);
}

/* ---------- pull quote ---------- */
.principle {
  font-size: var(--step-3); font-weight: var(--wt-display);
  line-height: 1.1; letter-spacing: -.028em; max-width: 18ch;
}

/* ---------- spec table ---------- */
.spec { width: 100%; border-collapse: collapse; margin-top: clamp(2rem, 4vw, 3rem); font-size: var(--step-0); }
.spec th, .spec td { text-align: left; padding: 1.1rem 1rem; border-bottom: 1px solid var(--line); vertical-align: top; }
/* Flush the table with the left edge of the body text above it. */
.spec th:first-child, .spec td:first-child { padding-left: 0; }
.spec th:last-child,  .spec td:last-child  { padding-right: 0; }
.spec tr:first-child :is(th, td) { border-top: 1px solid var(--line); }
.spec th { width: 28%; font-weight: var(--wt-bold); color: var(--ink); }
.spec td { color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* Never place a spec table inside a sticky column: this scroll container
   would break the stickiness. */
.table-scroll { overflow-x: auto; }

/* ---------- footer ---------- */
.site-footer {
  background: var(--surface); color: var(--ink-2);
  border-top: 1px solid var(--line);
  padding: clamp(2.5rem, 5vw, 3.5rem) 0 2rem;
  font-size: .8125rem; line-height: 1.5;
}
.site-footer h4 {
  color: var(--ink); font-size: .8125rem; font-weight: var(--wt-bold);
  letter-spacing: 0; text-transform: none; margin-bottom: .75rem;
}
.site-footer a { color: var(--ink-2); text-decoration: none; }
.site-footer a:hover { color: var(--ink); text-decoration: underline; }
.footer-grid { display: grid; gap: 2.5rem; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
.footer-grid ul { list-style: none; padding: 0; margin: 0; }
.footer-grid li { margin-bottom: .55rem; }
.footer-bottom {
  margin-top: 2.5rem; padding-top: 1.25rem; border-top: 1px solid var(--line-2);
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
}

/* ---------- utilities ---------- */
.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--paper);
  padding: .75rem 1rem; border-radius: 999px; z-index: 100;
}
.skip:focus { left: 1rem; top: 1rem; }

/* ---------- reduced motion ----------
   `animation: none` can strand a JS animation mid-way because animationend
   never fires; near-zero duration is the safe idiom. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .hero__media { display: none; }
  .beat { min-height: 0; }
  .scrolly__media { position: static; }
  .reveal { opacity: 1; transform: none; }
}
