/* scizar.co - the corporate landing page.

   THE PALETTE IS COPIED FROM THE APP, NOT SHARED. src/scizar/web/static/styles.css
   is 76KB of catalogue chrome served by a Python app on another host; this is one
   static page on Cloudflare Pages. There is no import that would work across the
   two, so the tokens below are a copy and they will drift. That is the deliberate
   trade, and the same one Rule 1 makes about vendored code: if the brand blue
   moves, it moves in both places by hand.

   THE ONLY BLOCK THAT MATTERS IS :root. Everything under it is layout for this
   page. If the app's palette changes, change these eight lines and nothing else.

   And note the opposite rule applies next door: canary-site/ must share NOTHING
   with the brand (docs/CANARY.md 6). Do not read that rule as covering this
   directory - this page is supposed to look like SciZar. */

:root {
  --bg:        #0a0b0e;
  --surface:   #121319;
  --surface-2: #191b23;
  --border:    #262932;
  --border-2:  #333744;
  --text:      #e8eaf0;
  --muted:     #a6acbd;
  --muted-2:   #7d8296;
  --accent:    #31a8f1;   /* SciZar logo blue */
  --accent-dim:#1c7fc4;
  --commercial:#7c93ff;   /* the indigo in the gradient */
  --academic:  #c69cff;   /* the violet at the end of it */
  --radius:    14px;
  --maxw:      1180px;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

html, body { margin: 0; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

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

main { max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }

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

.site-header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  max-width: var(--maxw); margin: 0 auto; padding: 20px 24px;
}
.brand { display: flex; align-items: center; gap: 9px; }
.brand-logo {
  width: 34px; height: 34px; object-fit: contain;
  filter: drop-shadow(0 0 12px rgba(49, 168, 241, 0.35));
}
.brand-name { font-weight: 700; letter-spacing: -0.02em; font-size: 23px; }
.brand-accent { color: var(--accent); }
/* The header wordmark alone, a size up from the footer's. See the catalogue's
   styles.css for why this is not a change to .brand-name itself. */
.brand .brand-name { font-size: 26px; }
/* The trademark mark. Same values and same reasoning as the catalogue's
   styles.css, where the note lives: TM and never (R) while the application is
   pending, and a relative nudge rather than `vertical-align: super`, because
   the glyph is already drawn raised and superscripting it raises it twice. */
.tm {
  font-size: 0.52em; font-weight: 400; letter-spacing: 0;
  position: relative; top: -0.55em; margin-left: 0.10em;
}

.site-nav { display: flex; align-items: center; gap: 18px; }
.site-nav a { color: var(--text); font-weight: 600; font-size: 15px; white-space: nowrap; }
.site-nav a:hover { color: var(--accent); }
/* The launch button is an <a> in the nav, so it must not inherit the hover
   above - a primary button going pale blue on dark blue reads as broken. */
.site-nav a.btn-primary:hover { color: #052236; }
/* Under 480px the brand, the anchor and the button add up to about 391px inside
   a 390px viewport, so the nav wraps to a row of its own and sits under the
   logo looking like a mistake. The anchor is the one to drop: it scrolls to a
   section the reader reaches in two thumb-flicks anyway, and the hero carries
   the same link as a button. The launch button stays at every width - it is the
   only thing on this page that has a job. */
@media (max-width: 480px) {
  .site-nav a:not(.btn) { display: none; }
}

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

.hero {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 32px; row-gap: 14px; align-items: center;
  padding: 40px 0 44px;
}
/* Soft glow behind the hero. The RIGHT edge is flush and the left one bleeds:
   `main` is centred with a max-width, so a negative right inset sits harmlessly
   in the margin on a wide screen and becomes sideways scroll on a phone. This
   exact bug cost a day on the app (docs/UI-ARCHITECTURE.md); do not "tidy" it
   into symmetry. */
.hero::before {
  content: ""; position: absolute; z-index: -1; inset: -40px 0 auto -80px; height: 360px;
  background:
    radial-gradient(420px 200px at 12% 30%, rgba(49, 168, 241, 0.12), transparent 70%),
    radial-gradient(360px 200px at 60% 10%, rgba(124, 147, 255, 0.10), transparent 70%);
  pointer-events: none;
}

.hero-copy { max-width: 780px; }
.hero-kicker {
  margin: 0 0 12px; font-size: 15px; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--accent);
}
.hero h1 {
  font-size: clamp(34px, 5vw, 58px); line-height: 1.02; margin: 0 0 16px;
  letter-spacing: -0.03em; font-weight: 800;
}
.hero-sub { color: var(--muted); font-size: 17px; margin: 0 0 28px; max-width: 700px; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 12px; margin: 0; }

.hero-art { align-self: center; }
.nodes-canvas { width: 340px; height: 320px; display: block; }

@media (max-width: 820px) {
  .hero { grid-template-columns: 1fr; padding: 28px 0 32px; }
  .hero-art { display: none; }
}

/* blue -> indigo -> violet gradient text */
.grad {
  background: linear-gradient(100deg, var(--accent), var(--commercial) 55%, var(--academic));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
/* The same ramp, slid slowly across. The gradient is MIRRORED and twice as wide
   as the box, so sliding by exactly one box width returns to the start and the
   loop has no seam. A one-way ramp snaps back to blue every cycle. */
.grad-drift {
  background-image: linear-gradient(100deg,
    var(--accent), var(--commercial) 25%, var(--academic) 50%,
    var(--commercial) 75%, var(--accent) 100%);
  background-size: 200% 100%;
  animation: grad-drift 9s linear infinite;
}
@keyframes grad-drift {
  from { background-position: 0% 0; }
  to   { background-position: 200% 0; }
}
@media (prefers-reduced-motion: reduce) { .grad-drift { animation: none; } }

/* ---- buttons ---- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--surface); border: 1px solid var(--border-2); color: var(--text);
  border-radius: 11px; padding: 11px 18px; font-size: 14px; font-weight: 600;
  font-family: inherit; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.btn:hover { border-color: var(--accent); }
.btn-primary { background: var(--accent); color: #052236; border-color: var(--accent); }
.btn-primary:hover { background: #5cbcf5; border-color: #5cbcf5; }
.btn-sm { padding: 7px 13px; font-size: 13px; border-radius: 9px; gap: 6px; }
.btn-lg { padding: 14px 24px; font-size: 16px; border-radius: 12px; }

/* ---- the divider ---- */

.rule { height: 1px; background: var(--border); margin: 8px 0; }

/* ---- sections ---- */

/* One rule for every section heading rather than a selector per section, so a
   new section is a <section> and nothing else. */
section { padding: 44px 0 8px; }
section > h2 {
  font-size: clamp(24px, 3vw, 32px); letter-spacing: -0.02em;
  margin: 0 0 24px; font-weight: 800;
}
/* The hero sets its own padding and has no h2. */
.hero { padding: 40px 0 44px; }

/* ---- prose ---- */

/* Narrower than the grid on purpose. Body text set to the full 1180px runs to
   about 150 characters a line on a desktop, which is roughly twice a readable
   measure - the cards get away with it because each one is its own column. */
.prose { max-width: 760px; }
.prose p { color: var(--muted); font-size: 16.5px; margin: 0 0 18px; }
.prose p:last-child { margin-bottom: 0; }
.prose em { color: var(--text); font-style: italic; }

/* TWO COLUMNS, stated rather than derived. `auto-fit` with a 300px floor gives
   three at this max-width, and there are four cards, so the second row was one
   card and a hole. A count that falls out of an arithmetic accident is a layout
   that breaks the day somebody writes a fifth card; 2x2 is what four cards want,
   and a fifth would want its own look at this line either way.

   Single column below 760px. Note there is no bare `minmax(300px, 1fr)`
   anywhere here: that has a hard floor, and below it the track keeps its width
   and the row leaves the screen sideways. It cost the app a day at 320px, in
   all three of its grids. */
.cards { display: grid; gap: 16px; grid-template-columns: 1fr; }
@media (min-width: 760px) {
  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Three across only once there is room for three readable columns. Between 760
   and 1000 it stays at two, which leaves one card on its own row - better than
   three columns of four words a line. */
@media (min-width: 1000px) {
  .cards-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 22px;
  transition: border-color .15s;
}
.card:hover { border-color: var(--border-2); }
.card h3 { margin: 0 0 10px; font-size: 17px; font-weight: 700; letter-spacing: -0.01em; }
.card p { margin: 0; color: var(--muted); font-size: 15px; }

/* ---- the product panel ---- */

/* The one place on this page that points hard at the app. Boxed and tinted so
   it reads as the call to action rather than as another section of company
   copy. */
.panel {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px 32px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 30px 32px; margin: 44px 0 8px;
}
.panel h2 { margin: 0 0 10px; font-size: clamp(21px, 2.4vw, 27px); font-weight: 800; letter-spacing: -0.02em; }
.panel-copy { max-width: 620px; }
.panel-copy p { margin: 0; color: var(--muted); font-size: 16px; }
.panel-cta { margin: 0; }

/* ---- enquiries ---- */

.enquiries { padding-bottom: 48px; }
.enquiries-lead { color: var(--muted); font-size: 16px; margin: -8px 0 22px; max-width: 700px; }
.enq-list { list-style: none; margin: 0; padding: 0; max-width: 760px; }
.enq-list li {
  display: flex; align-items: baseline; gap: 6px 16px; flex-wrap: wrap;
  padding: 13px 0; border-top: 1px solid var(--border);
}
.enq-list li:last-child { border-bottom: 1px solid var(--border); }
/* The link takes a fixed column on a wide screen so the descriptions line up,
   and gives it back below - a fixed basis with no wrap turns into a squeezed
   two-word column on a phone. */
.enq-list a { color: var(--accent); font-weight: 600; font-size: 15.5px; flex: 0 0 auto; min-width: 220px; }
.enq-list a:hover { color: var(--text); }
.enq-list span { color: var(--muted); font-size: 15px; flex: 1 1 260px; }

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

.site-footer {
  border-top: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px 24px; flex-wrap: wrap;
  max-width: var(--maxw); margin: 0 auto; padding: 26px 24px 40px;
  color: var(--muted); font-size: 14px;
}
.foot-brand .brand-name { font-size: 16px; }
.foot-parent { margin: 6px 0 0; color: var(--muted-2); font-size: 13px; }
.site-footer { align-items: flex-start; }
.foot-links { display: flex; flex-wrap: wrap; gap: 18px; }
.foot-links a { color: var(--muted); }
.foot-links a:hover { color: var(--accent); }
