/*
 * Solheim design tokens — the editorial language, shared by every live page.
 *
 * Taken from design/Solheim landing page design/Solheim Landing - Editorial.dc.html:
 * paper stock rather than a console, a heavy uppercase display grotesk, rust as
 * the only accent, and content set on rules — 2px for a section, a hairline for
 * a row. No rounded corners and no shadows anywhere: depth is done with rules
 * and weight.
 *
 * Every page imports this file *first* (`@import` at the top of landing.css and
 * app.css, rather than a second <link>), because the bundler emits a page's own
 * stylesheet before a linked shared one — which would put the base rules after
 * the page rules that are supposed to override them.
 *
 * Two deliberate departures from the source design:
 *
 *   1. Fonts are self-hosted (scripts/fetch-fonts.sh), never fetched from
 *      Google's CDN — an EU-sovereignty product that leaks every visitor's IP
 *      to a US CDN on first paint has undermined its pitch before the hero text
 *      renders. They are the latin and latin-ext subsets, which is why no copy
 *      uses a glyph outside them: an arrow "→" (U+2192) would silently fall
 *      back to whatever the visitor's system has.
 *   2. The dimmest greys are lifted to a 0.50 lightness floor (5.44:1 on paper,
 *      5.05:1 on the panel tint). Verify with: bun run scripts/check-contrast.ts
 */

@font-face {
  font-family: "Archivo";
  src: url("./fonts/Archivo-var-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
  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: "Archivo";
  src: url("./fonts/Archivo-var-latin-ext.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("./fonts/IBMPlexMono-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
  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";
  src: url("./fonts/IBMPlexMono-400-latin-ext.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("./fonts/IBMPlexMono-500-latin.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
  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";
  src: url("./fonts/IBMPlexMono-500-latin-ext.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* surfaces */
  --bg: oklch(0.965 0.012 92);
  --surface: oklch(0.94 0.014 92);

  /* rules: 2px ink for a section, a hairline between rows */
  --rule-heavy: oklch(0.18 0.012 60);
  --rule: oklch(0.82 0.012 80);
  /* Anything a pointer lands on gets a full-strength edge, never a hairline. */
  --rule-interactive: oklch(0.18 0.012 60);

  /* text — floor is --fg-faint at 5.44:1 on --bg, 5.05:1 on --surface */
  --fg: oklch(0.18 0.012 60);
  --fg-body: oklch(0.32 0.012 62);
  --fg-muted: oklch(0.42 0.012 62);
  --fg-dim: oklch(0.46 0.012 63);
  --fg-faint: oklch(0.5 0.012 65);

  /* accent */
  --accent: oklch(0.5 0.14 35);
  --accent-text: oklch(0.5 0.14 35);
  --accent-deep: oklch(0.3 0.08 35);
  --accent-ink: oklch(0.98 0.01 92);
  --accent-wash: oklch(0.5 0.14 35 / 0.12);
  --accent-edge: oklch(0.5 0.14 35);

  --warn: oklch(0.45 0.17 25);

  --font-sans: "Archivo", ui-sans-serif, system-ui, -apple-system, Helvetica, Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --measure: 1240px;
  --gutter: 32px;
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/*
 * A button is a piece of typography like everything else here. Without this the
 * UA font leaks into any button that does not name a face of its own — which is
 * every button built out of the shared components rather than out of .btn.
 */
button {
  font-family: inherit;
}

a {
  color: var(--accent-text);
  text-decoration: none;
}
a:hover {
  color: var(--accent-deep);
}

/* Visible keyboard focus everywhere. The source design had none. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

::selection {
  background: var(--accent-wash);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- page frame ------------------------------------------------------------- */

/*
 * The column every page is set in, and the link that lets a keyboard user out
 * of the masthead. Both live here rather than in a page stylesheet because
 * pages are now written two ways — bundled index.html files and server-rendered
 * strings from src/web/layout.ts — and the frame has to be the same thing in
 * both. src/web/app.css narrows it to .narrow for the signup column.
 */
.shell {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: 10px 16px;
  background: var(--rule-heavy);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: 13px;
  z-index: 10;
}
.skip-link:focus {
  left: 0;
}

/* --- primitives shared by the landing page and the app ---------------------- */

/*
 * The small-caps label. Every section number, column head, field label and
 * panel title on every page is this one thing.
 */
.eyebrow,
.field__label,
.panel__title,
.panel__bar,
.tile__label {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin: 0;
}

.eyebrow {
  color: var(--accent-text);
}

.mono {
  font-family: var(--font-mono);
}
.accent {
  color: var(--accent-text);
}

/* --- the masthead ----------------------------------------------------------- */

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 20px 0;
  border-bottom: 2px solid var(--rule-heavy);
  flex-wrap: wrap;
}

.wordmark {
  display: flex;
  align-items: baseline;
  gap: 12px;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--fg);
}
.wordmark:hover {
  color: var(--accent-text);
}
.wordmark__region {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 400;
  letter-spacing: 0.08em;
  color: var(--fg-faint);
}
/*
 * Which part of the site you are in, set beside the wordmark — "Notes" on the
 * blog. Same slot as the region label, louder, because it is a place rather
 * than a footnote.
 */
.wordmark__section {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.12em;
  color: var(--accent-text);
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 28px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  flex-wrap: wrap;
}
.site-nav a {
  color: var(--fg);
}
.site-nav a:hover {
  color: var(--accent-text);
}

/*
 * The masthead's trailing group: nav, then the language switcher.
 *
 * The header is `space-between`, so without this wrapper a third child would
 * push the nav into the middle of the bar. Present on every page whether or not
 * a switcher is, so the two cases lay out identically.
 */
.site-header__end {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}

/*
 * The language switcher.
 *
 * Sits after the nav rather than inside it, and quieter than a nav item on
 * purpose: for the overwhelming majority of visitors the page is already in the
 * right language, so this is a way out for the few who need one rather than a
 * fifth destination competing with the four that sell something.
 *
 * The separating rule is on the left edge so the control reads as belonging to
 * the masthead's trailing group. It disappears with the element, because the
 * switcher is absent entirely on any page with no translation — see
 * `alternates` in src/web/layout.ts.
 */
.site-lang {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-left: 20px;
  border-left: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.site-lang a {
  color: var(--fg-faint);
}
.site-lang a:hover {
  color: var(--accent-text);
}

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

.site-footer {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 26px 0 48px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-faint);
  flex-wrap: wrap;
}
.site-footer nav {
  display: flex;
  gap: 22px;
  /*
   * The footer wraps, but its row of links must as well: German labels are
   * wider than their English ones, and the row runs past a 390px viewport.
   */
  flex-wrap: wrap;
}
.site-footer a {
  color: var(--fg-faint);
}
.site-footer a:hover {
  color: var(--fg);
}

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

.btn {
  display: inline-block;
  text-align: center;
  padding: 13px 20px;
  border: 1px solid var(--rule-heavy);
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}
.btn--solid {
  background: var(--rule-heavy);
  color: var(--bg);
}
.btn--solid:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
/*
 * The rust slab. Reserved for the one button on a page that spends money or
 * makes a thing — today that is "create project" at the foot of the
 * configurator, and it is the only accent-filled surface in the app. It inverts
 * to ink on hover rather than lightening, so the pair reads as one gesture with
 * .btn--solid, which goes the other way.
 */
.btn--accent {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.btn--accent:hover {
  background: var(--rule-heavy);
  border-color: var(--rule-heavy);
  color: var(--bg);
}

.btn--outline {
  background: transparent;
  color: var(--fg);
}
.btn--outline:hover {
  border-color: var(--accent);
  color: var(--accent-text);
}
.btn--block {
  display: block;
  width: 100%;
}
.btn:disabled {
  background: var(--rule);
  border-color: var(--rule);
  color: var(--fg-muted);
  cursor: default;
}

/* A quieter button for in-panel actions: copy, new key, revoke. */
.copy {
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 5px 10px;
  cursor: pointer;
  background: transparent;
  color: var(--fg-muted);
  border: 1px solid var(--rule-heavy);
  transition: border-color 120ms ease, color 120ms ease;
}
/*
 * The same move as .btn--outline: the edge and the label take the accent, and
 * the button stays a button.
 *
 * It used to invert — ink fill, paper label — which on a page made of hairlines
 * and paper stock reads as a black slab dropped on the layout rather than as a
 * response to a pointer. Inverting is a *state* in this language (see .chip--on),
 * so spending it on hover also left nothing to say "this one is selected" with.
 */
.copy:hover {
  border-color: var(--accent);
  color: var(--accent-text);
}
.copy:disabled {
  border-color: var(--rule);
  color: var(--fg-faint);
  background: transparent;
  cursor: default;
}
