@import url("../fonts/fonts.css");

/* ============================================================================
   DEVTAC DESIGNS — design system
   Dark, technical, high-contrast. One accent, used sparingly.
   ========================================================================== */

:root {
  /* surfaces */
  --bg:         #08090a;
  --bg-2:       #0d0f11;
  --surface:    #121417;
  --surface-2:  #181b1f;
  --surface-3:  #1f2429;

  /* lines */
  --line:       rgba(255, 255, 255, 0.08);
  --line-2:     rgba(255, 255, 255, 0.14);
  --line-3:     rgba(255, 255, 255, 0.22);

  /* text */
  --text:       #eceded;
  --text-2:     #9ba3ab;
  --text-3:     #6b737b;

  /* accent */
  --accent:     #e8b44a;
  --accent-2:   #f5c86a;
  --accent-dim: rgba(232, 180, 74, 0.14);
  --accent-line:rgba(232, 180, 74, 0.35);
  --danger:     #e5484d;
  --ok:         #46c07a;

  /* type */
  /* Inter has neither Arabic nor Thai glyphs, so the stack names the faces
     every platform already ships — Segoe UI and Leelawadee on Windows, Geeza
     Pro and Thonburi on Apple, the Noto families on Android and most Linux.
     Self-hosting either script would be another 300 kB for one language, and
     the privacy policy says our fonts come from our own server rather than a
     font network: the honest way to keep both is to use what the reader
     already has. */
  --font: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial,
          "Segoe UI Arabic", "Geeza Pro", "Noto Naskh Arabic", "Arabic Typesetting",
          "Leelawadee UI", "Thonburi", "Noto Sans Thai", "Sarabun",
          sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Consolas,
          "Segoe UI Mono", monospace;

  /* metrics */
  --nav-h: 68px;
  --pad: clamp(20px, 5vw, 64px);
  --maxw: 1320px;
  --radius: 3px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 24px);
  /* Must live here, not on body: overflow-x on body makes body a scroll
     container (overflow-y computes to auto), which stops IntersectionObserver
     firing for anything below the fold. */
  overflow-x: hidden;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, svg, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }

::selection { background: var(--accent); color: #000; }

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

/* ------------------------------------------------------------- typography */
h1, h2, h3, h4 {
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
h1 { font-size: clamp(2.6rem, 7vw, 5.6rem); font-weight: 700; letter-spacing: -0.04em; }
h2 { font-size: clamp(1.9rem, 4vw, 3.2rem); }
h3 { font-size: clamp(1.25rem, 2vw, 1.6rem); letter-spacing: -0.02em; }
h4 { font-size: 1.0625rem; letter-spacing: -0.01em; }

p { text-wrap: pretty; }

.lede {
  font-size: clamp(1.0625rem, 1.6vw, 1.3rem);
  line-height: 1.62;
  color: var(--text-2);
  max-width: 62ch;
  font-weight: 300;
}
/* Every page until now used one lede at a time, so no rule ever separated two.
   An argument made in three paragraphs needs them to look like three. */
.lede + .lede { margin-top: 0.9em; }

.muted { color: var(--text-2); }
.dim   { color: var(--text-3); }

/* micro-label — the technical voice of the brand */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
}
.eyebrow::before {
  content: "";
  width: 20px;
  height: 1px;
  background: var(--accent);
  opacity: 0.6;
}
.eyebrow--plain { color: var(--text-3); }
.eyebrow--plain::before { background: var(--text-3); }

.mono {
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
}

/* --------------------------------------------------------------- layout */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.section { padding-block: clamp(72px, 11vw, 152px); }
.section--tight { padding-block: clamp(52px, 7vw, 88px); }
.section--alt { background: var(--bg-2); border-block: 1px solid var(--line); }

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

.section-head {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(20px, 4vw, 64px);
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: clamp(36px, 5vw, 64px);
}
.section-head > div:first-child { max-width: 68ch; }
.section-head h2 { margin-top: 18px; }
.section-head p { margin-top: 18px; }

.grid { display: grid; gap: clamp(16px, 2.2vw, 28px); }
/* A grid item's automatic minimum size is its content's min-content width, so a
   wide table inside one widens the whole track — and, with overflow-x hidden on
   html, the mobile layout viewport with it. Let tracks shrink; the tables carry
   their own overflow-x wrapper. */
.grid > *, .product > * { min-width: 0; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 960px) {
  .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------- buttons */
.btn {
  --btn-bg: transparent;
  --btn-fg: var(--text);
  --btn-bd: var(--line-2);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px 26px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-bd);
  border-radius: var(--radius);
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.25s var(--ease), border-color 0.25s var(--ease),
              color 0.25s var(--ease), transform 0.25s var(--ease);
}
.btn:hover { border-color: var(--line-3); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn--primary {
  --btn-bg: var(--accent);
  --btn-fg: #0a0a0a;
  --btn-bd: var(--accent);
  font-weight: 500;
}
.btn--primary:hover { --btn-bg: var(--accent-2); --btn-bd: var(--accent-2); }

.btn--ghost:hover { background: rgba(255, 255, 255, 0.04); }

.btn--sm { padding: 10px 18px; font-size: 0.6875rem; }
.btn--block { width: 100%; }

.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }

/* arrow link */
.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-2);
  transition: color 0.2s var(--ease), gap 0.2s var(--ease);
}
.arrow-link:hover { color: var(--accent); gap: 16px; }
.arrow-link::after { content: "→"; }

/* ------------------------------------------------------------------- nav */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  border-bottom: 1px solid transparent;
  transition: background 0.35s var(--ease), border-color 0.35s var(--ease),
              backdrop-filter 0.35s var(--ease);
}
.nav.is-stuck {
  background: rgba(8, 9, 10, 0.82);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom-color: var(--line);
}
.nav .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  /* Never squeezed. In a flex row every item shrinks by default, and the first
     thing a crowded bar crushes is the logo - the one item on it with a fixed
     shape. */
  flex: none;
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.brand img {
  display: block;
  height: 22px;
  width: auto;
}
.brand span {
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.22em;
  color: var(--accent);
  font-weight: 500;
}

.nav-links {
  display: flex;
  align-items: center;
  /* Tighter than it was, twice over: translated labels are longer than the
     English ones — "Configurador", "Konfigurator" — and the campaign link made
     ten items out of nine. The gaps are the cheapest place to find width, and
     measuring says French and Spanish need every pixel of it. */
  /* The upper bound matters more than it looks: the bar lives inside a
     container capped at --maxw, so above ~1450px the space stops growing while
     a vw-based gap keeps growing into it. Capping the gap is what stops the
     widest screens from being the ones that overflow. */
  gap: clamp(10px, 1.3vw, 18px);
  list-style: none;
}
.nav-links a {
  position: relative;
  /* Without this a label breaks at its own space rather than the bar running
     out of room — "À propos" and "NIJ 3" each fold onto two lines and the bar
     silently grows a second row instead of overflowing. A wrapped nav item
     also hides the overflow from any measurement taken in scrollWidth. */
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 0.6875rem;
  /* 0.13em elsewhere in the brand voice, 0.10em here: ten items in
     Ukrainian is the case that decides it, and tracking is the last
     width available before an item has to go. */
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--text-2);
  padding-block: 6px;
  transition: color 0.2s var(--ease);
}
.nav-links a:hover { color: var(--text); }
.nav-links a[aria-current="page"] { color: var(--text); }
.nav-links a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--accent);
}

/* Signed in: the link wears the visitor's name, lit by a small dot. Normal
   case rather than the nav's uppercase, because it is a name, not a label. */
.nav-links a.is-signed-in {
  color: var(--text);
  text-transform: none;
  letter-spacing: 0.04em;
}
.nav-links a.is-signed-in::before {
  content: "";
  display: inline-block;
  width: 5px; height: 5px;
  margin-inline-end: 7px;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: middle;
}

.nav-cta { display: flex; align-items: center; gap: 12px; flex: none; }

/* The founding date is a flourish. It is the first thing to go when a longer
   language needs the room, and nobody misses it. */
/* "EST. 2011" was already sacrificed below 1340 to make room for translated
   labels. The campaign link takes the rest of it: the flourish costs 55px
   that Ukrainian and French need to show ten items at all, and the wordmark
   carries the brand without it. */
@media (min-width: 0px) {
  .brand span { display: none; }
  .nav-cta .btn { padding-inline: 16px; }
}

.nav-toggle {
  display: none;
  width: 40px; height: 40px;
  margin-inline-end: -8px;
  position: relative;
}
.nav-toggle span {
  position: absolute;
  left: 9px;
  width: 22px; height: 1.5px;
  background: var(--text);
  transition: transform 0.3s var(--ease), opacity 0.2s var(--ease);
}
.nav-toggle span:nth-child(1) { top: 15px; }
.nav-toggle span:nth-child(2) { top: 21px; }
.nav-toggle span:nth-child(3) { top: 27px; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* The bar carries nine links, a language control and the order button; below
   this width it stops fitting honestly, so it collapses to the menu. */
/* Was 1150. A tenth item overflows the bar in Ukrainian below about 1280, and an overlapping nav is worse than a menu
   button — so the bar now folds while it still fits. tools/_navfit.mjs
   measured the number; it is not a guess. */
@media (max-width: 1280px) {
  .nav-toggle { display: block; }
  .nav-cta .btn { display: none; }
  .nav-links {
    position: fixed;
    inset: var(--nav-h) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 12px var(--pad) 28px;
    background: rgba(8, 9, 10, 0.97);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border-bottom: 1px solid var(--line);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.28s var(--ease), transform 0.28s var(--ease), visibility 0.28s;
  }
  .nav-links.is-open { opacity: 1; visibility: visible; transform: none; }
  .nav-links a {
    padding: 16px 0;
    font-size: 0.8125rem;
    border-bottom: 1px solid var(--line);
  }
  .nav-links a[aria-current="page"]::after { display: none; }
  .nav-links a[aria-current="page"] { color: var(--accent); }
}

/* ------------------------------------------------------------------ hero */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-top: var(--nav-h);
  overflow: hidden;
}
.hero__canvas {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero__canvas canvas { width: 100%; height: 100%; }

/* Photographic hero. A still costs ~100 KB against ~730 KB of three.js plus a
   2 MB model, so the landing page uses a photo and the 3D lives one click away
   in the configurator. */
.hero__photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
}
.hero__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 72% 42%;
}
@media (max-width: 900px) {
  .hero__photo img { object-position: 64% 38%; }
}

/* vignette + floor fade so type always stays readable over the 3D */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 74% 42%, transparent 24%, rgba(8,9,10,0.5) 68%, var(--bg) 100%),
    linear-gradient(90deg, var(--bg) 0%, rgba(8,9,10,0.92) 30%, rgba(8,9,10,0.45) 56%, rgba(8,9,10,0.15) 78%),
    linear-gradient(0deg, var(--bg) 1%, rgba(8,9,10,0.35) 22%, transparent 46%);
}
.hero .wrap { position: relative; z-index: 2; width: 100%; }
.hero__inner { max-width: 40rem; padding-block: 96px 120px; }
.hero h1 { margin-top: 26px; }
.hero h1 em {
  display: block;
  font-style: normal;
  color: var(--text-3);
  font-weight: 300;
  font-size: 0.42em;
  letter-spacing: -0.01em;
  margin-top: 20px;
  line-height: 1.3;
}
.hero .lede { margin-top: 26px; }
.hero .btn-row { margin-top: 40px; }

.hero__hint {
  position: absolute;
  inset-inline-end: var(--pad);
  bottom: 32px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-3);
}
.hero__hint b { color: var(--accent); font-weight: 500; }
.hero__hint { transition: color 0.2s var(--ease); }
a.hero__hint:hover { color: var(--text-2); }

/* placeholder shimmer while a lazy 3D tile boots */
[data-helmet].is-loading::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,0.045) 50%, transparent 70%);
  background-size: 220% 100%;
  animation: shimmer 1.6s linear infinite;
  pointer-events: none;
}
@keyframes shimmer { to { background-position: -220% 0; } }
@media (max-width: 900px) { .hero__hint { display: none; } }

/* live status dot */
.dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0 var(--accent-line);
  animation: pulse 2.4s var(--ease-io) infinite;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(232,180,74,0.5); }
  70%  { box-shadow: 0 0 0 7px rgba(232,180,74,0); }
  100% { box-shadow: 0 0 0 0 rgba(232,180,74,0); }
}

/* ----------------------------------------------------------------- cards */
.card {
  position: relative;
  padding: clamp(22px, 2.6vw, 34px);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 0.3s var(--ease), background 0.3s var(--ease),
              transform 0.3s var(--ease);
}
.card--link:hover {
  border-color: var(--line-3);
  background: var(--surface-2);
  transform: translateY(-3px);
}
.card h3 { margin-top: 14px; }
.card p { margin-top: 12px; color: var(--text-2); font-size: 0.9375rem; }

.card__num {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  color: var(--accent);
}

/* ten reasons

   A numbered list rather than cards: these are ten of one thing, read in order,
   and a grid of ten boxes reads as a menu. The counter comes from the <ol> so
   the numbering is the document's, not a set of hand-typed labels that can fall
   out of step with it. */
.reasons {
  list-style: none;
  counter-reset: reason;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 clamp(24px, 4vw, 64px);
}
.reasons > li {
  counter-increment: reason;
  padding: clamp(18px, 2.2vw, 26px) 0;
  border-bottom: 1px solid var(--line);
  display: grid;
  grid-template-columns: 2.6em 1fr;
  gap: 0 4px;
  /* Rows pack to the top. The two columns of the outer grid share a row height,
     so a short entry beside a long one would otherwise stretch and float its
     answer away from its question. */
  align-content: start;
}
.reasons > li::before {
  /* Down the left of both rows, so the question and the answer share the text
     column. Without this the answer lands in the number's column and wraps a
     word at a time. */
  grid-row: 1 / span 2;
  content: counter(reason, decimal-leading-zero);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  color: var(--accent);
  padding-top: 0.35em;
}
.reasons h3 {
  grid-column: 2;
  margin: 0 0 8px;
  font-size: clamp(0.9375rem, 1.4vw, 1.0625rem);
  line-height: 1.35;
}
.reasons p {
  grid-column: 2;
  margin: 0;
  max-width: 46ch;
  font-size: 0.875rem;
  line-height: 1.65;
  color: var(--text-2);
}

@media (max-width: 860px) {
  .reasons { grid-template-columns: 1fr; }
}

/* stat */
.stat__value {
  font-family: var(--mono);
  font-size: clamp(2rem, 4.4vw, 3.4rem);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--text);
}
.stat__value sup {
  font-size: 0.34em;
  color: var(--accent);
  letter-spacing: 0.1em;
  vertical-align: super;
}
.stat__label {
  margin-top: 14px;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text-3);
}

/* --------------------------------------------------------------- product */
.product {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(24px, 4vw, 72px);
  align-items: center;
}
.product--rev > *:first-child { order: 2; }
@media (max-width: 900px) {
  .product { grid-template-columns: 1fr; }
  .product--rev > *:first-child { order: 0; }
}

.product__visual {
  position: relative;
  aspect-ratio: 4 / 3;
  background:
    radial-gradient(70% 70% at 50% 45%, rgba(255,255,255,0.05), transparent 70%),
    var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.product__visual canvas { width: 100%; height: 100%; }

.badge {
  position: absolute;
  top: 16px; left: 16px;
  z-index: 3;
  padding: 6px 11px;
  background: rgba(8,9,10,0.72);
  backdrop-filter: blur(8px);
  border: 1px solid var(--line-2);
  border-radius: 2px;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text-2);
}

/* ------------------------------------------------------------ spec table */
.spec {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}
.spec th, .spec td {
  padding: 15px 4px;
  text-align: start;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.spec th {
  width: 42%;
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 400;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-3);
}
.spec td { font-family: var(--mono); font-size: 0.8125rem; color: var(--text); }
.spec tr:last-child th, .spec tr:last-child td { border-bottom: 0; }

/* Parts tables carry a sentence of description, which is unreadable set in the
   mono face the compact spec tables use. Prices stay mono — they are data. */
.spec--parts td {
  font-family: var(--font);
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--text-2);
}
.spec--parts td b { color: var(--text); font-weight: 600; }
.spec--parts td.mono {
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--accent);
  white-space: nowrap;
  text-align: end;
}
.spec--parts th { width: auto; }

/* ---------------------------------------------------------------- footer */
.footer {
  border-top: 1px solid var(--line);
  background: var(--bg-2);
  padding-block: clamp(48px, 6vw, 80px) 32px;
}
.footer__grid {
  display: grid;
  grid-template-columns: 1.6fr repeat(3, 1fr);
  gap: clamp(28px, 4vw, 56px);
}
@media (max-width: 860px) { .footer__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .footer__grid { grid-template-columns: 1fr; } }

.footer h4 {
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 18px;
}
.footer ul { list-style: none; display: grid; gap: 11px; }
.footer a {
  font-size: 0.875rem;
  color: var(--text-2);
  transition: color 0.2s var(--ease);
}
.footer a:hover { color: var(--accent); }

.footer__bottom {
  margin-top: clamp(40px, 5vw, 64px);
  padding-top: 26px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: space-between;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  color: var(--text-3);
}

/* ----------------------------------------------------------------- forms */
.field { display: grid; gap: 9px; }
.field label {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-3);
}
.field label .req { color: var(--accent); }

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 13px 15px;
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  font-size: 0.9375rem;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.field textarea { min-height: 132px; resize: vertical; line-height: 1.6; }
.field input::placeholder, .field textarea::placeholder { color: var(--text-3); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface-2);
}
.field select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-2) 50%),
                    linear-gradient(135deg, var(--text-2) 50%, transparent 50%);
  background-position: calc(100% - 19px) 20px, calc(100% - 14px) 20px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.field select option { background: var(--surface); }

.field-note { font-size: 0.8125rem; color: var(--text-3); }
.field.has-error input,
.field.has-error textarea,
.field.has-error select { border-color: var(--danger); }
.field__err {
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--danger);
  display: none;
}
.field.has-error .field__err { display: block; }

.form-status {
  padding: 15px 18px;
  border: 1px solid var(--line-2);
  border-inline-start: 2px solid var(--accent);
  background: var(--surface);
  border-radius: var(--radius);
  font-size: 0.875rem;
  color: var(--text-2);
}
.form-status.is-ok { border-inline-start-color: var(--ok); }
/* the same colour on the line that reports a confirmed payment */
.field-note.is-ok { color: var(--ok); }
.form-status.is-err { border-inline-start-color: var(--danger); }

/* ------------------------------------------------------- scroll reveal */
/* Hidden only when JS is present to un-hide it — without this a script
   failure would leave most of the page permanently invisible. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
  transition-delay: var(--d, 0ms);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------- utilities */
.page-head { padding-top: calc(var(--nav-h) + clamp(56px, 8vw, 112px)); }
.page-head h1 { font-size: clamp(2.2rem, 5.4vw, 4.2rem); margin-top: 22px; }
.page-head .lede { margin-top: 24px; }

.stack   { display: grid; gap: 20px; }
.stack-s { display: grid; gap: 12px; }
.mt-l    { margin-top: clamp(32px, 4vw, 56px); }
.center  { text-align: center; margin-inline: auto; }
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; top: -60px; left: var(--pad); z-index: 200;
  padding: 12px 18px; background: var(--accent); color: #000;
  font-family: var(--mono); font-size: 0.75rem; border-radius: var(--radius);
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: 12px; }

/* --------------------------------------------------------------- gallery */
.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(12px, 1.6vw, 20px);
}
.gallery__item {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 0.3s var(--ease);
}
.gallery__item--wide { grid-column: span 2; }
.gallery__item:hover { border-color: var(--line-3); }

.gallery__item img {
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 0.65s var(--ease);
}
.gallery__item:hover img { transform: scale(1.035); }

.gallery__item figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 34px 16px 14px;
  background: linear-gradient(transparent, rgba(8, 9, 10, 0.92));
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-2);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.32s var(--ease), transform 0.32s var(--ease);
}
.gallery__item:hover figcaption,
.gallery__item:focus-within figcaption { opacity: 1; transform: none; }

@media (max-width: 900px) {
  .gallery { grid-template-columns: repeat(2, 1fr); }
  .gallery__item figcaption { opacity: 1; transform: none; }
}
@media (max-width: 560px) {
  .gallery { grid-template-columns: 1fr; }
  .gallery__item--wide { grid-column: span 1; }
}

code {
  font-family: var(--mono);
  font-size: 0.875em;
  padding: 2px 6px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 2px;
  color: var(--text-2);
}

/* ---------------------------------------------------------------- figures */
.figure {
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}
.figure img { width: 100%; height: auto; display: block; }
/* Photo rows that have to line up: crop each frame to a common shape rather
   than letting mixed source aspects stagger the captions across the row. */
.figure--tile img { aspect-ratio: 3 / 4; object-fit: cover; }

.figure figcaption {
  padding: 14px 18px;
  border-top: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  color: var(--text-3);
}

/* ----------------------------------------------------------------- video */
.videos {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(12px, 1.6vw, 22px);
}
@media (max-width: 900px) { .videos { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .videos { grid-template-columns: 1fr; } }

.video {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  aspect-ratio: 16 / 9;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  cursor: pointer;
  text-align: start;
  transition: border-color 0.3s var(--ease), transform 0.3s var(--ease);
}
.video:hover { border-color: var(--line-3); transform: translateY(-3px); }

.video img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.78;
  transition: opacity 0.35s var(--ease), transform 0.6s var(--ease);
}
.video:hover img { opacity: 1; transform: scale(1.04); }

.video__play {
  position: absolute;
  top: 50%; left: 50%;
  width: 56px; height: 56px;
  transform: translate(-50%, -50%);
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 50%;
  background: rgba(8, 9, 10, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: background 0.25s var(--ease), border-color 0.25s var(--ease),
              transform 0.25s var(--ease);
}
/* The play triangle keeps pointing right in every language. Media transport
   controls are not mirrored for right-to-left reading — a play button that
   points left reads as rewind to everyone. */
.video__play::after {
  content: "";
  position: absolute;
  top: 50%; left: 54%;
  transform: translate(-50%, -50%);
  border-left: 13px solid var(--text);
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
}
.video:hover .video__play {
  background: var(--accent);
  border-color: var(--accent);
  transform: translate(-50%, -50%) scale(1.06);
}
.video:hover .video__play::after { border-left-color: #0a0a0a; }

.video__title {
  position: absolute;
  inset: auto 0 0 0;
  padding: 40px 14px 13px;
  background: linear-gradient(transparent, rgba(8, 9, 10, 0.94));
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.videos iframe {
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  display: block;
}


/* ------------------------------------------------------------------ order */
.order { display: grid; gap: clamp(28px, 4vw, 48px); }
.order__block {
  border-top: 1px solid var(--line);
  padding-top: clamp(22px, 3vw, 34px);
}
.order__block > h2 { font-size: clamp(1.1rem, 2vw, 1.4rem); margin-bottom: 18px; }
.order__block .field, .order__block .grid { margin-bottom: 14px; }

.order-views {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  margin-bottom: 22px;
}
@media (max-width: 760px) { .order-views { grid-template-columns: repeat(2, 1fr); } }
.order-views figure {
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
}
.order-views img { width: 100%; height: auto; display: block; }
.order-views figcaption {
  padding: 7px 9px;
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
  border-top: 1px solid var(--line);
}

.order-total {
  display: grid;
  gap: 5px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.order-total > span { display: flex; justify-content: space-between; gap: 16px; align-items: baseline; }
.order-total i { font-style: normal; font-size: 0.8125rem; color: var(--text-3); }
.order-total b { font-family: var(--mono); font-size: 0.8125rem; color: var(--text-2); }

/* One price on the page, and it is this one. */
.order-total .sum-price__total {
  margin-top: 8px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.order-total .sum-price__total i {
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-2);
}
.order-total .sum-price__total b { font-size: 1.375rem; color: var(--accent); }

.pay-methods { display: grid; gap: 10px; margin-bottom: 20px; }
.pay {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
}
.pay:has(input:checked) { border-color: var(--accent-line); background: var(--accent-dim); }
.pay input { margin-top: 3px; accent-color: var(--accent); }
.pay__body { display: grid; gap: 4px; }
.pay__body b { font-size: 0.9375rem; }
.pay__body span { font-size: 0.8125rem; line-height: 1.55; color: var(--text-3); }

.chk-line {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--text-2);
  cursor: pointer;
}
.chk-line input { margin-top: 4px; accent-color: var(--accent); }
.chk-line.is-bad { color: var(--danger); }

.order-empty, .order-done { max-width: 62ch; }
.order-done__head { margin-bottom: 30px; }


/* ----------------------------------------------------------------- spares */
.spares { display: grid; gap: 26px; }
.spares__group h3 {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-3);
  padding-bottom: 9px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 4px;
}
.spare {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 14px;
  align-items: center;
  padding: 11px 12px;
  border: 1px solid transparent;
  border-radius: var(--radius);
}
.spare.is-on { border-color: var(--accent-line); background: var(--accent-dim); }
.spare__body { display: grid; gap: 2px; min-width: 0; }
.spare__body b { font-size: 0.875rem; font-weight: 500; }
.spare__body span { font-size: 0.75rem; color: var(--text-3); }
.spare__price {
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--accent);
  white-space: nowrap;
}
.spare__qty { display: flex; align-items: center; gap: 2px; }
.spare__qty button {
  width: 30px; height: 30px;
  font: inherit; font-size: 1rem; line-height: 1;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
}
.spare__qty button:hover { color: var(--text); border-color: var(--line-2); }
.spare__qty input {
  width: 46px; height: 30px;
  text-align: center;
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--text);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  -moz-appearance: textfield;
}
.spare__qty input::-webkit-outer-spin-button,
.spare__qty input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

@media (max-width: 560px) {
  .spare { grid-template-columns: 1fr auto; row-gap: 8px; }
  .spare__qty { grid-column: 2; }
  .spare__price { grid-column: 2; grid-row: 1; text-align: end; }
}

.spares__foot {
  position: sticky;
  bottom: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
  margin-top: 26px;
  padding: 16px 0 calc(16px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line-2);
  background: linear-gradient(to top, var(--bg) 72%, transparent);
}
.spares__total i { font-style: normal; font-size: 0.8125rem; color: var(--text-3); margin-inline-end: 12px; }
.spares__total b { font-family: var(--mono); font-size: 1.0625rem; color: var(--accent); }
.btn.is-disabled { opacity: 0.4; pointer-events: none; }


/* ---------------------------------------------------------------- account */
.auth-card {
  max-width: 27rem;
  padding: clamp(24px, 4vw, 36px);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.auth-card h2 { font-size: clamp(1.15rem, 2.2vw, 1.45rem); }
.auth-card__intro {
  margin-top: 12px;
  font-size: 0.8125rem;
  line-height: 1.65;
  color: var(--text-3);
}
.auth-card__form { display: grid; gap: 15px; margin-top: 22px; }
.auth-card__swap {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  align-items: baseline;
  margin-top: 22px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  font-size: 0.8125rem;
  color: var(--text-3);
}
.auth-card__swap button {
  font: inherit;
  font-weight: 500;
  color: var(--accent);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.auth-card__swap button:hover { color: var(--accent-2); }
/* "Forgotten your password?" sits under the button, quieter than the swap —
   it is the rarer road out of this card, not the alternative to it. */
.auth-card__aside {
  display: block;
  margin-top: 14px;
  padding: 0;
  font: inherit;
  font-size: 0.75rem;
  color: var(--text-3);
  background: none;
  border: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.auth-card__aside:hover { color: var(--text-2); }

.auth-card__warn {
  margin-top: 16px;
  font-size: 0.6875rem;
  line-height: 1.6;
  color: var(--text-3);
}
.account__head {
  display: flex; flex-wrap: wrap; gap: 14px;
  align-items: center; justify-content: space-between;
  padding-bottom: 18px; margin-bottom: 24px;
  border-bottom: 1px solid var(--line);
}
.pill-status {
  font-family: var(--mono); font-size: 0.625rem;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--accent); border: 1px solid var(--accent-line);
  background: var(--accent-dim); border-radius: 2px; padding: 3px 8px;
}

/* ------------------------------------------------------------- order desk

   A dense list, because the point of it is to see everything at once, with the
   detail opening in place rather than on another page — comparing two orders
   should not cost two navigations. */

.admin-denied { max-width: 46ch; }
.admin-denied h2 { font-size: 1.25rem; margin-bottom: 10px; }

.admin-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px;
  margin: 26px 0;
}
.admin-stat {
  display: grid;
  gap: 3px;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.admin-stat__k {
  font-family: var(--mono); font-size: 0.625rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-3);
}
.admin-stat__v { font-size: 1.5rem; font-weight: 600; color: var(--text); }
.admin-stat__n { font-size: 0.6875rem; color: var(--text-3); }

/* The hidden attribute means hidden.

   Its own rule is display:none at the lowest specificity, so any class that
   sets a display beats it: .admin-filters is display:flex, and switching the
   desk to the People view left the order filters on screen. This is the fix
   the HTML standard itself recommends. */
[hidden] { display: none !important; }

/* desk tabs — the same shape as the viewer's, which lives in a stylesheet this
   page does not load. */
.vtabs {
  display: flex;
  gap: 2px;
  margin: 26px 0 18px;
  border-bottom: 1px solid var(--line);
}
.vtab {
  padding: 10px 16px;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.vtab:hover { color: var(--text-2); }
.vtab.is-on { color: var(--accent); border-bottom-color: var(--accent); }

/* the people list

   A table, because this is tabular: six facts about each of a hundred rows,
   compared down the columns. It scrolls inside its own box rather than pushing
   the page sideways on a narrow screen. */
.admin-table-wrap { overflow-x: auto; }
.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8125rem;
}
.admin-table th,
.admin-table td {
  padding: 10px 14px 10px 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  white-space: nowrap;
}
.admin-table thead th {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
  font-weight: 400;
}
.admin-table td { color: var(--text-2); }
.admin-table .num { text-align: right; padding-right: 22px; }
.admin-table .mono { font-family: var(--mono); font-size: 0.75rem; }

.tag {
  display: inline-block;
  margin-inline-start: 6px;
  padding: 1px 6px;
  border: 1px solid var(--line-2);
  border-radius: 2px;
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
  vertical-align: middle;
}
.tag--warn { color: var(--accent); border-color: var(--accent-line); }

.admin-filters {
  display: flex; flex-wrap: wrap; gap: 14px;
  align-items: center; justify-content: space-between;
  margin-bottom: 18px;
}
.admin-search input {
  min-width: 260px; padding: 9px 12px;
  font: inherit; font-size: 0.8125rem;
  color: var(--text); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius);
}
.admin-search input:focus-visible { outline: 1px solid var(--accent); outline-offset: 1px; }

/* One order. The head is a button so the whole row opens it. */
.ord { border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 8px; }
.ord.is-open { border-color: var(--accent-line); }
.ord__head {
  display: grid;
  grid-template-columns: minmax(150px, 1fr) minmax(190px, 1.4fr) minmax(180px, 1.6fr) 100px 110px 120px;
  gap: 14px; align-items: center;
  width: 100%; padding: 14px 16px;
  font: inherit; text-align: start; color: var(--text-2);
  background: none; border: 0; cursor: pointer;
}
.ord__head:hover { background: var(--surface); }
.ord__ref { display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; }
.ord__ref b { font-family: var(--mono); font-size: 0.8125rem; color: var(--text); }
.ord__flag {
  font-family: var(--mono); font-size: 0.5625rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--danger);
  border: 1px solid var(--danger); border-radius: 2px; padding: 1px 5px;
}
.ord__who { font-size: 0.8125rem; color: var(--text); }
.ord__who i { display: block; font-style: normal; font-size: 0.75rem; color: var(--text-3); }
.ord__what { font-size: 0.75rem; color: var(--text-3); }
.ord__when { font-size: 0.75rem; color: var(--text-3); }
.ord__amount { font-family: var(--mono); font-size: 0.8125rem; color: var(--accent); text-align: end; }
.ord__head .pill-status { justify-self: end; white-space: nowrap; }

/* Where an order has got to, at a glance: waiting on us, moving, or done. */
.pill-status--placed { color: var(--danger); border-color: var(--danger); background: none; }
.pill-status--delivered,
.pill-status--shipped { color: var(--ok); border-color: var(--ok); background: none; }
.pill-status--cancelled { color: var(--text-3); border-color: var(--line); background: none; }

.ord__body { padding: 4px 16px 22px; border-top: 1px solid var(--line); }
.ord__grid { display: grid; grid-template-columns: 1.15fr 1fr; gap: 30px; }
.ord__col h3 {
  font-family: var(--mono); font-size: 0.625rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-3);
  margin: 22px 0 8px;
}
.ord__views {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 8px; margin-bottom: 6px;
}
.ord__views img {
  width: 100%; aspect-ratio: 1; object-fit: cover;
  border: 1px solid var(--line); border-radius: var(--radius); background: #000;
}
.ord__notes, .ord__addr { font-size: 0.8125rem; line-height: 1.7; color: var(--text-2); }
.ord__warn { font-size: 0.75rem; line-height: 1.6; color: var(--danger); margin-top: 10px; }
.ord__note {
  width: 100%; padding: 10px 12px;
  font: inherit; font-size: 0.8125rem; color: var(--text);
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  resize: vertical;
}
.ord__note:focus-visible { outline: 1px solid var(--accent); outline-offset: 1px; }

@media (max-width: 1100px) {
  .ord__head { grid-template-columns: 1fr 1fr; gap: 8px; }
  .ord__amount { text-align: start; }
  .ord__head .pill-status { justify-self: start; }
  .ord__grid { grid-template-columns: 1fr; gap: 12px; }
}

/* The chip is the configurator's control, and viewer.css is loaded only there.
   The desk uses the same shape for its filters and its status buttons, so it
   carries its own copy rather than pulling in a stylesheet for a 3D viewer. */
.admin-filters .chips,
.ord .chips { display: flex; flex-wrap: wrap; gap: 6px; }
.admin-filters .chip,
.ord .chip {
  padding: 8px 13px;
  font-family: var(--mono); font-size: 0.625rem;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--line-2); border-radius: 2px;
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease),
              background 0.2s var(--ease);
}
.admin-filters .chip:hover,
.ord .chip:hover { color: var(--text); border-color: var(--line-3); }
.admin-filters .chip.is-on {
  color: var(--accent); border-color: var(--accent-line);
  background: rgba(232, 180, 74, 0.08);
}
.admin-filters .chip b { font-weight: 500; color: var(--accent); margin-inline-start: 6px; }
.admin-filters .chip.is-on b { color: inherit; }
.ord .chip:disabled { opacity: 0.5; cursor: default; }

/* ---------------------------------------------------- paying in two parts */

.pay-split { margin-top: 22px; }
.pay-split h3 {
  font-family: var(--mono); font-size: 0.625rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-3);
  margin-bottom: 10px;
}
.pay-split .pay__body b i { font-style: normal; color: var(--accent); }

/* The amount only matters once the deposit option is chosen, so it stays out
   of the way until then rather than sitting there inviting a number. */
.pay-split__amount {
  display: grid; gap: 6px;
  margin-top: 10px; padding-top: 12px;
  border-top: 1px solid var(--line);
  opacity: 0.45; pointer-events: none;
  transition: opacity 0.2s var(--ease);
}
.pay-split.is-split .pay-split__amount { opacity: 1; pointer-events: auto; }
.pay-split__amount label {
  font-family: var(--mono); font-size: 0.625rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-3);
}
.pay-split__amount input {
  width: 160px; padding: 9px 12px;
  font: inherit; font-family: var(--mono); font-size: 0.875rem;
  color: var(--text); background: var(--bg);
  border: 1px solid var(--line-2); border-radius: var(--radius);
}
.pay-split__amount input:focus-visible { outline: 1px solid var(--accent); outline-offset: 1px; }
/* Below the floor, or above the total: say what will be recorded instead. */
.pay-split__amount .field-note.is-corrected { color: var(--accent); }

/* The customer's own order list, where a split order needs a second line. */
.ord-split { display: block; font-size: 0.6875rem; color: var(--text-3); margin-top: 3px; }
.ord__amount i {
  display: block; font-style: normal;
  font-size: 0.6875rem; color: var(--danger); margin-top: 2px;
}
.pill-status--deposit-paid { color: var(--text-2); border-color: var(--line-3); background: none; }
.pill-status--balance-due { color: var(--danger); border-color: var(--danger); background: none; }

/* ------------------------------------------------------------ legal pages

   The footer's legal links sit between the copyright and "Made in Japan", so
   they read as part of the same line rather than as another menu. */
.footer__legal { display: flex; flex-wrap: wrap; gap: 18px; }
.footer__legal a { color: var(--text-3); }
.footer__legal a:hover { color: var(--text-2); }

/* Long-form text. One column at a readable measure — a privacy policy is only
   any use if someone can actually get through it. */
.legal { max-width: 68ch; }
.legal h2 {
  font-size: 1.125rem;
  margin-top: 46px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
  color: var(--text);
}
.legal h2:first-of-type { margin-top: 0; padding-top: 0; border-top: 0; }
.legal h3 {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-top: 30px;
}
.legal p, .legal li {
  font-size: 0.9375rem;
  line-height: 1.8;
  color: var(--text-2);
  margin-top: 14px;
}
.legal ul { margin-top: 8px; padding-inline-start: 20px; list-style: disc; }
.legal li { margin-top: 8px; }
.legal li::marker { color: var(--text-3); }
.legal b { color: var(--text); font-weight: 500; }
.legal a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.legal a:hover { color: var(--accent-2); }
.legal code {
  font-family: var(--mono);
  font-size: 0.8125em;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 1px 5px;
}
.legal table { margin-top: 18px; }
.legal__stamp {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 34px;
}

/* Something the reader needs to act on, not just be told. */
.legal__warn {
  margin-top: 18px;
  padding: 16px 18px;
  border: 1px solid var(--danger);
  border-radius: var(--radius);
  background: rgba(229, 72, 77, 0.06);
  font-size: 0.9375rem;
  line-height: 1.8;
  color: var(--text-2);
}
.legal__warn b { color: var(--text); }

/* ---------------------------------------------------------------- language

   Held invisible only while a translation is pending, and only when the reader
   asked for something other than English — an English visitor, which is most of
   them, never waits on this. */
.i18n-pending body { visibility: hidden; }

/* Two characters wide, because the bar has no room for "Portugues" and the
   reader already knows which language they are looking at. The full names live
   in the menu, which is where somebody switching actually looks. */
.lang { position: relative; flex: none; }
.lang__btn {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 7px 9px;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  color: var(--text-2);
  background: none;
  border: 1px solid var(--line-2);
  border-radius: 2px;
  cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.lang__btn:hover { color: var(--text); border-color: var(--line-3); }
.lang__btn::after {
  content: "";
  width: 0; height: 0;
  /* A downward caret: symmetric, so it needs no flipping. */
  border-left: 3px solid transparent;
  border-right: 3px solid transparent;
  border-top: 4px solid currentColor;
  opacity: 0.7;
}
.lang__menu {
  position: absolute;
  top: calc(100% + 8px);
  inset-inline-end: 0;
  z-index: 60;
  min-width: 158px;
  padding: 5px;
  list-style: none;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
}
.lang__menu button {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 9px 11px;
  font: inherit;
  font-size: 0.8125rem;
  color: var(--text-2);
  text-align: start;
  background: none;
  border: 0;
  border-radius: 2px;
  cursor: pointer;
}
.lang__menu button:hover { background: var(--surface); color: var(--text); }
.lang__menu button[aria-current="true"] { color: var(--accent); }
/* A tick beside the language you are on. Written as the character itself,
   not a CSS escape: an escape is one mangled backslash away from putting
   something meaningless in the menu, which is exactly what happened. */
/* A tick beside the language you are on. Written as the character itself,
   not a CSS escape: an escape is one mangled backslash away from putting
   something meaningless in the menu, which is exactly what happened. */
.lang__menu button[aria-current="true"]::after { content: "✓"; }


/* ------------------------------------------------------------ right to left

   The layout is written in logical properties, so it mirrors on its own when
   the document direction changes. These are the places where mirroring is not
   what you want, or not enough. */

/* A price, a part number, a phone number and an email address are read left to
   right in every language. Left to itself, a right-to-left paragraph moves the
   currency symbol to the far side of the number and reorders "$2,060 USD" into
   something that is not a price. */
[dir="rtl"] .mono,
[dir="rtl"] .sum-price b,
[dir="rtl"] .order-total b,
[dir="rtl"] .ord__amount,
[dir="rtl"] .spare__price,
[dir="rtl"] .admin-stat__v,
[dir="rtl"] .mod__price {
  direction: ltr;
  unicode-bidi: isolate;
}

/* The wordmark is an image and the founding date beside it is set in the
   monospace face; the pair reads as one lockup and stays as drawn. */
[dir="rtl"] .brand { direction: ltr; }

/* Arabic has no capitals, so letter-spaced uppercase — which carries a lot of
   this design — does nothing but push the glyphs apart and break the joins
   between them. */
[dir="rtl"] .eyebrow,
[dir="rtl"] .nav-links a,
[dir="rtl"] .btn,
[dir="rtl"] .chip,
[dir="rtl"] .pill,
[dir="rtl"] .vtab,
[dir="rtl"] .admin-stat__k,
[dir="rtl"] .legal__stamp,
[dir="rtl"] .footer h4 {
  text-transform: none;
  letter-spacing: 0;
}

/* The language button keeps its code in Latin either way. */
[dir="rtl"] .lang__btn { direction: ltr; }

/* ---------------------------------------------------- the preorder campaign

   Twenty places, and a bar that says how many are gone. The fill is set from
   the server's count in preorder.js; nothing here invents a number, and if the
   count cannot be fetched the whole block is hidden rather than shown empty. */

.raise {
  display: grid;
  gap: 14px;
  padding: 22px 24px;
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
}

.raise__nums {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.raise__count {
  font-family: var(--mono);
  font-size: 1.75rem;
  line-height: 1;
  color: var(--accent);
  /* A tally is a number even when the sentence around it runs the other way. */
  direction: ltr;
  unicode-bidi: isolate;
}
.raise__of {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
}

.raise__track {
  position: relative;
  height: 8px;
  background: var(--surface-3);
  border-radius: 999px;
  overflow: hidden;
}
.raise__fill {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 0;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  border-radius: 999px;
  transition: width 900ms cubic-bezier(0.16, 1, 0.3, 1);
}
.raise.is-funded .raise__fill {
  background: linear-gradient(90deg, var(--ok), #6fd79a);
}

.raise__status {
  font-size: 0.875rem;
  color: var(--text-2);
}
.raise.is-funded .raise__status { color: var(--ok); }

/* The bar fills from the start of the line, which is the right in Arabic. */
[dir="rtl"] .raise__fill {
  background: linear-gradient(270deg, var(--accent), var(--accent-2));
}

/* -------------------------------------------------- the live campaign link

   NIJ 3 is a campaign, not a section, and it is only interesting while it is
   running. The dot says "something is happening here" without a second word of
   label — which matters, because the bar is already tight and a tenth item is
   what brought back the overlap the two-letter language picker was built to
   fix. Remove the class when the campaign closes and the item goes quiet. */

.nav-links a.nav-live {
  color: var(--accent);
  padding-inline-start: 12px;
}
.nav-links a.nav-live:hover { color: var(--accent-2); }

.nav-links a.nav-live::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 50%;
  width: 5px;
  height: 5px;
  margin-top: -2px;
  border-radius: 50%;
  background: var(--accent);
  animation: nav-live-pulse 2.4s var(--ease) infinite;
}

@keyframes nav-live-pulse {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.8); }
}

/* A blinking dot is decoration to a reader and a distraction to anybody who
   asked the system to stop moving things. */
@media (prefers-reduced-motion: reduce) {
  .nav-links a.nav-live::before { animation: none; }
}
