/* AL Data Labs — aldatalabs.com
   Single stylesheet, no build step, no external requests.
   Bump the ?v= query string in every <link> when this file changes.

   ONE palette, defined once here. The comparison themes and gradient ramps that
   this file carried while the look was being chosen are gone — a palette nobody
   selects is a palette nobody maintains. */

:root {
  /* Page. The background sits deliberately deeper than the illustration's first
     gradient stop: the left-hand buildings are the pale-blue end of the ramp,
     and at anything close to their own lightness they simply disappear. */
  --bg:          #1189CE;
  --bg-soft:     #0F7BBA;
  --text:        #ffffff;
  --text-muted:  #dcf1fc;
  --border:      rgba(255, 255, 255, 0.28);
  --link:        #ffffff;
  --link-hi:     #ffe0f2;

  /* The illustration's five gradient stops, left to right across the scene.
     Snowflake's exact brand blue #29B5E8 is deliberately NOT among them — it was
     in the logo mark and had no business being in someone else's brand. */
  --g1: #1E9BE0;
  --g2: #3A6FDD;
  --g3: #7A3FD1;
  --g4: #C42BA6;
  --g5: #E4258F;

  /* Marks inside the buildings. Near-white because they sit on the blue page. */
  --detail:      #BDEEFF;

  --facet-light: rgba(255, 255, 255, 0.22);
  --facet-dark:  rgba(4, 26, 48, 0.16);
  --crowd:       #0C2B49;
  --crowd-back:  #1D4C77;

  /* the AI core and its badges */
  --badge-1:   #ffffff;
  --badge-2:   #CFE4FA;
  --badge-3:   #E0D3F7;
  --badge-ink: #101d31;
  --conn:      rgba(255, 255, 255, 0.55);

  --wrap: 1120px;
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

.g1 { stop-color: var(--g1); }
.g2 { stop-color: var(--g2); }
.g3 { stop-color: var(--g3); }
.g4 { stop-color: var(--g4); }
.g5 { stop-color: var(--g5); }

/* ---------- base ---------- */

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* The page is one screen of content over a full-width illustration.
     dvh, not vh: on a phone `100vh` is measured against the viewport with the
     browser's address bar *collapsed*, so the page is taller than what is
     actually on screen and the bottom of the picture gets cut off. The vh line
     stays as the fallback for anything without dvh. */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

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

a { color: var(--link); text-decoration: none; }
a:hover { color: var(--link-hi); text-decoration: underline; }

:focus-visible { outline: 2px solid var(--link); outline-offset: 3px; border-radius: 4px; }

/* Off-screen until tabbed to — without this rule the link is simply visible,
   sitting above the logo on every page that has one. */
.skip { position: absolute; left: -9999px; }
.skip:focus {
  left: 16px;
  top: 16px;
  z-index: 10;
  background: var(--text);
  color: var(--bg);
  padding: 10px 16px;
  border-radius: 8px;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 24px;
}

/* ---------- header ---------- */

.site-header { padding: 22px 0 0; }

.header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  font-weight: 650;
  letter-spacing: -0.01em;
  font-size: 1.05rem;
}
.brand:hover { text-decoration: none; color: var(--text); }

.brand-mark { width: 26px; height: 26px; flex: none; }

.header-mail {
  font-size: 0.92rem;
  color: var(--text-muted);
}
.header-mail:hover { color: var(--link-hi); }
.header-mail-icon { display: none; }   /* phones only — see the media query */

/* ---------- hero ---------- */

.hero {
  /* Deliberately tight: header + hero + skyline + footer has to come in under a
     900px-tall laptop viewport, or the crowd — the bottom of the picture — never
     gets seen. Every value here was traded against .skyline svg's max-height. */
  padding: clamp(24px, 4vw, 46px) 0 clamp(20px, 3vw, 34px);
  text-align: center;
  position: relative;   /* the AI core hangs off this box */
}

/* ---------- the AI core ---------- */

.ai {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  /* Hangs this far past the hero's bottom edge. The box is ~210px tall at full
     width, so most of that offset is the box itself clearing the headline. */
  bottom: -206px;
  width: min(940px, 94vw);
  pointer-events: none;       /* it is decoration; never trap a click */
}
.ai svg { display: block; width: 100%; height: auto; }

.ai-min { display: none; }   /* phones only — see the media query */

.conn path {
  fill: none;
  stroke: var(--conn);
  stroke-width: 2;
  stroke-dasharray: 5 8;
}
.b1 { fill: var(--badge-1); }
.b2 { fill: var(--badge-2); }
.b3 { fill: var(--badge-3); }
.glyph { fill: var(--badge-ink); color: var(--badge-ink); }
.ai-label {
  fill: var(--text);
  font-family: var(--font);
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.5px;
}

.eyebrow {
  margin: 0 0 18px;
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* Full white, not the muted token: at this size, spaced out, in a mono face,
     the muted colour was legible on a laptop and all but invisible on a large
     monitor. Size grows with the viewport below; the colour has to hold at all
     of them. */
  color: var(--text);
}

.hero h1 {
  margin: 0 auto 16px;
  max-width: 23ch;
  font-size: clamp(1.9rem, 4.4vw, 3.1rem);
  line-height: 1.1;
  letter-spacing: -0.03em;
  font-weight: 680;
  text-wrap: balance;
}


/* ---------- the skyline ---------- */

/* body is the flex column, so the element that has to grow is <main> — its
   direct child. Growing .skyline instead does nothing and leaves the page
   short of the viewport with blank space under the footer. */
main {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

/* On a tall monitor every spare pixel used to land in one gap: the headline sat
   at the top of a 1440px screen with 700px of void under it. Giving the hero an
   auto margin too splits that space above and below.

   Gated on height, and deliberately: at 900px there are only ~120 spare pixels,
   and handing half of them to the hero pushes the AI core onto the rooftops. The
   centring is only correct where there is room to centre. */
@media (min-height: 950px) {
  /* A measured lift, not `auto`. An even split put the headline in the middle of
     the screen with the city far below it; 8vh raises the block while leaving
     the sky band the AI core needs. 12vh was tried and drops the core onto the
     rooftops at 1920x1080. */
  .hero { margin-top: 8vh; }
}

.skyline {
  margin-top: auto;        /* holds the city against the bottom of the page */
  display: flex;
  align-items: flex-end;
  width: 100%;
  overflow: hidden;        /* the crowd is drawn past the viewBox edge */
}
.skyline svg {
  display: block;
  flex: none;              /* or the flex row shrinks it below its own width */
  width: 100%;
  height: auto;
  /* Never so tall that the crowd falls below the fold on a laptop, never so
     short that the buildings turn into a stripe. The px ceiling is what a large
     monitor gets: at 430px a 1440-tall screen left the city small and the page
     mostly empty. 46vh still governs short windows. */
  max-height: min(46vh, 600px);
  max-height: min(46dvh, 600px);
}

.facet-light { fill: var(--facet-light); }
.facet-dark  { fill: var(--facet-dark); }

.detail {
  fill: var(--detail);
  stroke: var(--detail);
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Shapes in that group that are strokes, not fills, say so themselves via
   fill="none" — everything else inherits the fill and ignores the stroke. */
.detail [fill="none"] { fill: none; }

.crowd-back  { fill: var(--crowd-back); }
.crowd-front { fill: var(--crowd); }

/* ---------- footer ---------- */

.site-footer {
  flex: none;
  padding: 20px 0 26px;
  background: var(--bg);
}
.footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  color: var(--text-muted);
  font-size: 0.88rem;
}
.footer-row p { margin: 0; }
.footer-nav { display: flex; gap: 22px; flex-wrap: wrap; }
.footer-nav a { color: var(--text-muted); }
.footer-nav a:hover { color: var(--link-hi); }
.footer-mail-short { display: none; }   /* phones only — see the media query */

/* ---------- legal pages (privacy) ---------- */

.legal {
  /* Top and bottom only. This class sits on the same element as .wrap, so the
     `padding` shorthand used to zero out .wrap's 24px side padding — invisible
     on a desktop, where the 78ch column is narrower than the viewport anyway,
     but on a phone it put the text flush against both edges. */
  padding-top: clamp(40px, 6vw, 72px);
  padding-bottom: clamp(48px, 7vw, 88px);
  max-width: 78ch;
}
.legal h1 {
  margin: 0 0 8px;
  font-size: clamp(1.8rem, 4vw, 2.4rem);
  letter-spacing: -0.02em;
  font-weight: 680;
}
.legal .updated {
  margin: 0 0 40px;
  color: var(--text-muted);
  font-family: var(--mono);
  font-size: 0.82rem;
}
.legal h2 { margin: 40px 0 12px; font-size: 1.18rem; font-weight: 640; letter-spacing: -0.01em; }
.legal h3 { margin: 26px 0 8px; font-size: 1rem; font-weight: 640; }
.legal p, .legal li { color: var(--text-muted); font-size: 0.98rem; }
.legal ul { padding-left: 22px; }
.legal li { margin-bottom: 8px; }
.legal strong { color: var(--text); font-weight: 600; }
.legal table { width: 100%; border-collapse: collapse; margin: 18px 0; font-size: 0.93rem; }
.legal th, .legal td {
  border: 1px solid var(--border);
  padding: 10px 12px;
  text-align: left;
  vertical-align: top;
  color: var(--text-muted);
}
.legal th { color: var(--text); font-weight: 600; background: var(--bg-soft); }
.table-scroll { overflow-x: auto; }

/* The privacy page is text, not a one-screen layout: let it grow. */
body:not(.home) .skyline { display: none; }

/* ---------- responsive ---------- */

/* The band of open sky between the headline and the rooftops is what this
   overlay lives in, and that band is set by viewport HEIGHT, not width: the
   skyline is 46vh, so a short window closes the gap and a fixed offset drops the
   constellation onto the buildings. Two steps down, then the phone treatment. */
@media (min-width: 721px) and (max-height: 860px) {
  .ai { width: min(520px, 86vw); bottom: -124px; }
}
/* Netbook heights: header + hero + city + footer runs a few pixels over 600px
   and the page starts to scroll, which on a one-screen layout means the crowd
   is cut off. The hero is the only part with padding to give back. */
@media (max-height: 650px) {
  .hero { padding-top: 14px; padding-bottom: 10px; }
  .eyebrow { margin-bottom: 10px; }
}

@media (min-width: 721px) and (max-height: 750px) {
  /* Under ~780px tall there is no band left worth a six-badge graphic. */
  .ai { display: none; }
  .ai-min {
    display: block;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: -58px;
    width: 76px;
    pointer-events: none;
  }
  .ai-min svg { display: block; width: 100%; height: auto; }
}

@media (max-width: 720px) {
  body { font-size: 16px; }
  /* The address is too wide for a phone, but hiding it outright left the
     wordmark alone on the left and the row lopsided. The envelope is 26px —
     the same as the brand mark — so both ends of the header weigh the same. */
  .header-mail { display: inline-flex; align-items: center; color: var(--text); opacity: 0.95; }
  .header-mail-text { display: none; }
  .header-mail-icon { display: block; width: 26px; height: 26px; }
  .hero { padding-top: 36px; }
  .hero h1 { max-width: 14ch; }
  .ai { display: none; }
  .ai-min {
    display: block;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: -120px;
    width: 108px;
  }
  .ai-min svg { display: block; width: 100%; height: auto; }
  .ai-min { pointer-events: none; }
  /* A 3.3:1 scene shrunk to fit a phone is a 117px stripe. Blow it up past the
     viewport and let .skyline's overflow crop the sides instead, so the middle
     of the city stays legible. The negative margin re-centres what is left. */
  .skyline svg {
    width: 260%;
    max-width: none;
    max-height: none;
    margin-left: -80%;
  }
  /* The footer was 105px — 12% of a phone screen — because the address pushed
     it onto a second line. One row instead: the full address becomes "Support",
     and the copyright drops the brand, which the header states anyway. Every
     pixel saved here goes to the sky between the AI core and the rooftops. */
  .site-footer { padding: 12px 0 16px; }
  .footer-row {
    justify-content: center;
    text-align: center;
    flex-wrap: nowrap;
    gap: 14px;
    font-size: 0.82rem;
  }
  .footer-nav { gap: 14px; }
  .footer-brand,
  .footer-mail-full { display: none; }
  .footer-mail-short { display: inline; }
  /* Reads "© 2026 · Privacy · Terms · Support": the address goes last without
     reordering the markup, which desktop still wants the other way round. */
  .footer-nav .footer-mail { order: 1; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* The hero padding shrinks below 650px tall (above), and the AI core hangs off
   the hero's bottom edge — so its offset has to give back exactly what the
   padding gave up, or the star climbs into the headline. Last in the file so it
   wins over the width-based blocks. */
@media (min-width: 721px) and (max-height: 650px) {
  .ai-min { bottom: -82px; }
}
@media (max-width: 720px) and (max-height: 650px) {
  .ai-min { bottom: -92px; width: 88px; }
}

/* Legacy 320x568 phones: after the header, headline and city there is no band
   left for the star, and it lands on the rooftops. Decoration is the thing that
   gives way. */
@media (max-width: 400px) and (max-height: 600px) {
  .ai-min { display: none; }
}

/* ---------- large monitors ----------
   Everything above is sized for a laptop. On a 27" screen the same values leave
   the headline small and the eyebrow illegible, so both scale up in two steps.
   The AI core grows with them: at a fixed 940px it starts to look like a detail
   dropped into the corner of a very large picture.

   Gated on height as well as width, because 1920x1080 is wide but short: the
   bigger type makes the hero taller, which pushes the AI core down onto the
   rooftops on exactly the screen the extra size was not meant for. */
@media (min-width: 1200px) {
  .eyebrow { font-size: 0.95rem; letter-spacing: 0.2em; margin-bottom: 22px; }
}
@media (min-width: 1900px) and (min-height: 1150px) {
  .eyebrow { font-size: 1.05rem; }
  .hero h1 { font-size: 3.9rem; max-width: 24ch; }
  .ai { width: min(1200px, 62vw); bottom: -250px; }
}
@media (min-width: 2400px) and (min-height: 1300px) {
  .eyebrow { font-size: 1.15rem; }
  .hero h1 { font-size: 4.6rem; }
  .ai { width: min(1440px, 58vw); bottom: -292px; }
}

/* The city gets a taller ceiling only where the screen is tall enough to spare
   it — below this, 46vh already governs and this rule never applies. It also
   removes the side gutters on a 1440px-tall monitor, where a 600px city was
   too short to span the width. */
@media (min-height: 1300px) {
  .skyline svg { max-height: min(46vh, 800px); }
}
