/* BitRanch LLC company site — "Sky Editorial", dark.

   ChessRoller's Sky design language (DM Sans, the 12·16·20·32·40·80 scale, the
   1280px column, 7px ink buttons, the dark footer band) carried onto this
   site's own editorial layout: left-aligned, hairlines instead of cards, and a
   280px term column set against a 640px measure.

   ChessRoller itself is light-only. The dark palette below is not invented —
   it is derived from the one dark surface that design already has, its footer
   band: #141413 ground, #ffffff ink, #b0aea4 muted. Cards lift off that ground
   and the footer sinks below it.

   Zero external requests: DM Sans and DM Mono are self-hosted, no JS, no
   webfont CDN. */

/* DM Sans ships one variable file covering every weight the site uses. DM Mono
   is here for the three micro-labels only, which all sit at 500 — the 400 cut
   is deliberately not shipped because nothing uses it. */
@font-face {
  font-family: 'DM Sans Variable';
  font-style: normal;
  font-weight: 100 1000;
  font-display: swap;
  src: url('/assets/fonts/dm-sans-latin-wght-normal.9fea608a.woff2') format('woff2-variations');
}
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/dm-mono-latin-500-normal.9964608a.woff2') format('woff2');
}

:root {
  /* committed to dark, the way ChessRoller is committed to light */
  color-scheme: dark;

  --bg: #141413;
  --card: #1e1e1c;
  --ink: #ffffff;
  --ink-muted: #b0aea4;
  --line: rgba(255, 255, 255, 0.25);
  --line-soft: rgba(255, 255, 255, 0.2);
  --on-ink: #141413;
  --ink-wash: rgba(255, 255, 255, 0.09);
  --ink-wash-hover: rgba(255, 255, 255, 0.14);
  --footer-bg: #0e0e0d;
  --footer-ink: #ffffff;
  --footer-muted: #b0aea4;

  /* The one hue. ChessRoller's --match (#016d4d) was darkened to clear AA on
     paper; on this ground the same hue has to be lifted instead. #35d39b sits
     at 8.1:1 over the resolved wash, against CR's 4.7:1 on paper. */
  --match: #35d39b;
  --match-wash: rgba(53, 211, 155, 0.1);

  --sans:
    'DM Sans Variable', 'DM Sans', -apple-system, BlinkMacSystemFont,
    'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
  --mono: 'DM Mono', ui-monospace, 'SF Mono', Consolas, 'Liberation Mono', monospace;

  /* ChessRoller's fitted gutter, kept verbatim */
  --gutter: clamp(1.5rem, 1rem + 4.05vw, 5.5rem);
  --col-wide: 80rem;
  --col-mid: 55rem;
  --col-text: 40rem;

  /* the editorial grid: a fixed term column against the text measure, with the
     tag rail on the right. 280 + 40 + 680 + 40 + 240 = 1280. */
  --term-col: 280px;
  --tag-col: 240px;
  --col-gap: 40px;

  --header-h: 64px;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}
html:has(.nav-menu[open]) {
  overflow: hidden;
}
/* the nav jumps to sections and the header is sticky, so a target has to stop
   short or its heading lands underneath. A section's 40px heading margin
   collapses out through its zero top padding — the section box top *is* the
   heading top — so that 40px has to be added here rather than assumed. */
[id] {
  scroll-margin-top: calc(var(--header-h) + 2.5rem);
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

.col {
  width: min(var(--col-wide), 100% - 2 * var(--gutter));
  margin-inline: auto;
}

/* ── Type scale ──────────────────────────────────────────────────────
   Ten styles carry the site, each defined once with every selector that
   uses it listed on the rule. Scale: 10 · 12 · 16 · 20 · 32 · 40 · 80. */

/* display — the hero headline; the only tier that scales with the viewport.
   5.56vw so the 80px cap is actually reached at 1440. The 62.5rem cap is
   ChessRoller's own, and is what keeps "We build desktop software." on one
   line at full width. */
.display {
  font-weight: 700;
  font-size: clamp(2rem, 5.56vw, 5rem);
  line-height: 1.06;
  letter-spacing: -0.01em;
  max-width: 62.5rem;
}

/* h1 — page titles. Deliberately not qualified with .page-head: a display
   headline lives inside one on the product and 404 pages, and a descendant
   selector here would outrank .display and shrink it. */
h1 {
  font-weight: 700;
  font-size: 2.5rem;
  line-height: 1.15;
}

/* h2 — section headings. Left-aligned here, where ChessRoller centres them. */
h2,
.section-head h2 {
  font-weight: 700;
  font-size: 2rem;
  line-height: 1.2;
}

/* h3 — every subhead: row terms, product name, prose h2 */
h3,
.prose h2:not(.eyebrow),
.product-name {
  font-weight: 700;
  font-size: 1.25rem;
  line-height: 1.3;
}

/* body-strong — separated from body by weight alone */
strong {
  font-weight: 700;
}

/* ui — controls: buttons, nav, standalone links */
.site-nav a,
.link-standalone {
  font-weight: 500;
  font-size: 1rem;
  line-height: 1.2;
}

/* menu — the full-screen panel's links. Mobile only: the panel does not exist
   above 640px. */
.menu-panel a {
  font-weight: 500;
  font-size: 1.5rem;
  line-height: 1.2;
}

/* micro — small print sitting under or beside everything else */
.micro,
.link-groups li,
.footer-bottom p,
.footer-bottom address,
.copyright,
.page-head .meta,
figcaption {
  font-size: 0.75rem;
  line-height: 1.4;
}

/* label — the mono kicker above a headline */
.eyebrow {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 0.75rem;
  line-height: 1.3;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* label-sm — mono column and group headers */
.group-label {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 0.75rem;
  line-height: 1.3;
  letter-spacing: 0.125em;
  text-transform: uppercase;
}

/* label-xs — the tag, and the only 10px on the site */
.tag {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 0.625rem;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* ── Links ───────────────────────────────────────────────────────────
   No accent hue in the palette, so nothing moves on colour except to
   lighten. Links in running text carry an underline at rest (WCAG 1.4.1);
   standalone links are marked by position and a trailing arrow. */

a {
  color: var(--ink);
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}
p a,
.prose li a,
.facts dd a,
address a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}
p a:hover,
.prose li a:hover,
.facts dd a:hover,
address a:hover {
  color: var(--ink-muted);
}

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.skip-link {
  position: absolute;
  left: -9999px;
}
.skip-link:focus {
  left: var(--gutter);
  top: 0.5rem;
  z-index: 20;
  background: var(--bg);
  border: 1px solid var(--line);
  padding: 0.5rem 0.85rem;
  border-radius: 4px;
}

/* ── Header ──────────────────────────────────────────────────────────
   The bar rides the content column's edges rather than the page gutter, so
   the brand lines up with the grid below. */

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 2rem;
  min-height: var(--header-h);
  padding-block: 1rem;
  padding-inline: max(var(--gutter), (100% - var(--col-wide)) / 2);
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

.brand {
  font-weight: 700;
  font-size: 1.25rem;
  line-height: 1.3;
  color: var(--ink);
  margin-right: auto;
}
.brand:hover {
  text-decoration: none;
}
.brand-logo {
  display: block;
  height: 18px;
  width: auto;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 2rem;
  flex-wrap: wrap;
}
.site-nav a[aria-current='page'] {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* hamburger dropdown — hidden on desktop, replaces .site-nav on mobile.
   A <details> element, so it opens and closes without JavaScript. */
.nav-menu {
  display: none;
}
.nav-menu summary {
  list-style: none;
  display: flex;
  align-items: center;
  cursor: pointer;
  padding: 0.25rem;
  color: var(--ink);
}
.nav-menu summary::-webkit-details-marker {
  display: none;
}
/* two bars that cross into an X when the panel opens. Both move to the same
   centre line and counter-rotate, so open and closed are the same two elements
   rather than a swapped icon — which is what lets it read as one movement. */
.burger {
  position: relative;
  display: block;
  width: 26px;
  height: 26px;
}
.burger span {
  position: absolute;
  left: 2px;
  right: 2px;
  height: 1.5px;
  border-radius: 1px;
  background: var(--ink);
  transition:
    top 0.2s ease,
    transform 0.2s ease;
}
.burger span:first-child {
  top: 9.5px;
}
.burger span:last-child {
  top: 15.5px;
}
.nav-menu[open] .burger span {
  top: 12.5px;
}
.nav-menu[open] .burger span:first-child {
  transform: rotate(45deg);
}
.nav-menu[open] .burger span:last-child {
  transform: rotate(-45deg);
}
/* deliberately no hover colour: this control only exists below 640px, where a
   tap leaves an emulated hover behind and the icon would stay tinted */

/* full-screen below the header, so the menu is the page rather than a panel
   hanging off it. Fixed rather than absolute: the sheet stays put if the page
   behind it scrolls. */
.menu-panel {
  position: fixed;
  top: var(--header-h);
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  overflow-y: auto;
  /* clears the home indicator on notched phones */
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.menu-panel a {
  padding: 0.9rem var(--gutter);
  color: var(--ink);
  /* fainter than --line: these separate list items, not sections */
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.menu-panel a:first-child {
  border-top: none;
}
.menu-panel a:hover {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ── Controls ────────────────────────────────────────────────────────── */

/* standalone link — the underline rides the label span so it stops before the
   trailing arrow, which would otherwise be underlined too */
.link-standalone {
  color: var(--ink);
  text-decoration: none;
}
.link-standalone:hover {
  text-decoration: none;
}
.link-standalone:hover span {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ── Sections ────────────────────────────────────────────────────────── */

/* Sections carry their space below them only. The block above — a hero, a page
   head, or the preceding section — already supplies the gap, so a top padding
   here would double it. */
section {
  padding-block: 0 6rem;
}
/* the opening block is the only one with space above it — everything below
   hangs off the previous section's tail */
.about {
  padding-block: 5rem;
}
.page-head {
  padding-block: 6rem 4rem;
}
.page-body {
  padding-block: 0 6rem;
}
/* 40px above and below, so a section heading sits in its own band */
.section-head h2,
.company .group-label {
  margin-block: 2.5rem;
}
.company .group-label {
  color: var(--ink-muted);
}
/* a 40px headline wants a little more air beneath it than the 1rem the prose
   rhythm gives */
.about h1 {
  margin-bottom: 1.5rem;
}

.lede {
  max-width: var(--col-text);
  color: var(--ink-muted);
  margin-top: 1.5rem;
}
.page-head .meta {
  color: var(--ink-muted);
  margin-top: 1rem;
}
.eyebrow {
  color: var(--ink-muted);
  margin-bottom: 1.5rem;
}

/* ── The editorial grid ──────────────────────────────────────────────
   A 280px term column against the 640px measure. Everything on the page
   that pairs a label with a body hangs off these two verticals: the
   definition rows, the company facts, and the product module. */

.facts {
  border-top: 1px solid var(--line);
}
.facts > div {
  display: grid;
  grid-template-columns: var(--term-col) minmax(0, 1fr);
  gap: 0 var(--col-gap);
  padding-block: 1.25rem;
  border-bottom: 1px solid var(--line);
}
.facts dt,
.facts dd {
  color: var(--ink-muted);
  max-width: var(--col-text);
}
.facts {
  max-width: var(--col-text);
}

/* ── Product module ──────────────────────────────────────────────────
   Set between hairlines rather than boxed in a card, on the same grid as
   the rows above it, with a tag rail in the third column. */

/* 240 + 40 + 360 = 640: the module sits at the text measure rather than the
   full column, and the tag rail moves under the name instead of taking a
   third column of its own */
.product {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: 0 var(--col-gap);
  align-items: start;
  max-width: var(--col-text);
  padding-block: 2rem;
  border-block: 1px solid var(--line);
}

.product-id {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
}
/* 1rem from the stack gap plus this makes the 40px the design puts between
   the name and the tag rail */
.product-id .tags {
  margin-top: 1.5rem;
}
/* the PNG ships with square corners, so clip them to the 15/72 radius */
.product-icon {
  display: block;
  width: 72px;
  height: 72px;
  border-radius: 15px;
}
/* the product page leads with the mark stacked over an 80px display title,
   which needs more air under it than the 16px gap the module uses beside a
   20px name */
.page-head .product-icon {
  margin-bottom: 2rem;
}
.product-name {
  margin: 0;
}
.product-tagline {
  color: var(--ink-muted);
}

.product-body > p {
  color: var(--ink-muted);
  max-width: var(--col-text);
}
.product-body .link-standalone {
  display: inline-block;
  margin-top: 2rem;
}
/* a mono kicker above the summary, so the margin sits below it rather than
   above — it opens the block and has nothing to clear */
/* tag rail — ChessRoller's "matches your device" chip. Square corners are
   deliberate: that rule carries no border-radius. */
.tags {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.tag {
  display: inline-flex;
  padding: 0.25rem 0.5rem;
  background: var(--match-wash);
  color: var(--match);
}

/* ── Screenshot ──────────────────────────────────────────────────────── */

/* the shot carries its own window chrome and shadow on a transparent margin,
   so no border or radius here — they would box the transparent margin rather
   than the window inside it */
/* ── Prose ───────────────────────────────────────────────────────────
   Running copy at the 640px measure, left-aligned on the column's own
   edge. Headings carry a rule above them — the device this site had
   before, and the thing that makes a long page read as a document. */

.prose {
  max-width: var(--col-text);
}
.prose > * + * {
  margin-top: 1rem;
}
.prose h2:not(.eyebrow),
.prose h3.ruled {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
}
/* an unclassed heading that opens the block sits below something that already
   drew a rule — the page head — so it needs neither. .ruled is opt-in and
   always draws, including when it comes first. */
.prose > h2:not(.eyebrow):first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
.prose ul,
.prose ol {
  padding-left: 1.5rem;
}
.prose li + li {
  margin-top: 1rem;
}
.prose address {
  font-style: normal;
  line-height: 1.7;
}

/* ── Footer ──────────────────────────────────────────────────────────
   The band sinks below the page ground rather than lifting off it. */

.site-footer {
  background: var(--footer-bg);
  color: var(--footer-muted);
  padding-block: 5rem;
  padding-inline: max(var(--gutter), (100% - var(--col-wide)) / 2);
}
.footer-top {
  display: flex;
  align-items: flex-start;
  gap: 10rem;
  flex-wrap: wrap;
  margin-bottom: 8rem;
}
.footer-top .brand {
  color: var(--footer-ink);
  margin-right: 0;
}
.footer-mark img {
  display: block;
  width: 56px;
  height: 74px;
}
.link-groups {
  display: flex;
  gap: 4.5rem;
  flex-wrap: wrap;
}
.link-groups .group-label {
  color: var(--footer-ink);
  margin-bottom: 1rem;
}
.link-groups ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.link-groups a {
  color: var(--footer-muted);
}
.link-groups a:hover {
  color: var(--footer-ink);
  text-decoration: none;
}
.footer-bottom {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.5rem;
}
.site-footer address {
  font-style: normal;
  color: var(--footer-muted);
  line-height: 1.7;
}
.site-footer address a,
.footer-bottom a {
  color: var(--footer-muted);
  text-decoration: none;
}
.site-footer address a:hover,
.footer-bottom a:hover {
  color: var(--footer-ink);
  text-decoration: none;
}
.copyright {
  color: var(--footer-muted);
}

/* ── 404 ─────────────────────────────────────────────────────────────── */

.notfound {
  padding-block: 10rem;
}

/* ── Narrow viewports ────────────────────────────────────────────────
   The three-column product grid collapses before the two-column rows do:
   the tag rail is the first thing that stops earning its width. */

@media (max-width: 68rem) {
  .footer-top {
    gap: 4rem;
    margin-bottom: 5rem;
  }
}

@media (max-width: 48rem) {
  .facts > div,
  .product {
    grid-template-columns: minmax(0, 1fr);
  }
  .facts dd {
    margin-top: 0.5rem;
  }
  .product-body {
    margin-top: 1.5rem;
  }
  .link-groups {
    gap: 2.5rem;
  }
  .site-header {
    flex-wrap: wrap;
    gap: 1rem;
  }
  .site-nav {
    gap: 1.5rem;
  }
}

/* the inline nav gives way to the panel — the header bar keeps only the
   wordmark and the toggle */
@media (max-width: 40rem) {
  .site-nav {
    display: none;
  }
  .nav-menu {
    display: block;
  }
  .site-header {
    flex-wrap: nowrap;
  }
}

@media print {
  .site-header,
  .site-footer {
    display: none;
  }
}
