/* Vivenso Labs — shared design system.
   One stylesheet. No remote fonts, no external requests, no frameworks, no script.

   The identity is the Vivenso Labs brand board, v1.0 (adopted 2026-09-21): a light
   ground, navy for trust and for text, azure for technology, teal and leaf green for
   health and growth, Montserrat for headings and the name. The board's four accent
   colours are too light to be read as text on its own ground (azure 2.46:1, teal 2.15,
   leaf green 2.14 against the background), so each has a deeper "ink" twin for text,
   and the bright originals draw rules, icons, gradients and the mark. Every text colour
   below is checked against the ground by tools/verify.mjs. */

/* ---------- fonts ---------- */

/* The board's two faces, both under the SIL Open Font License 1.1 and served from
   this origin: Montserrat 7.200 for headings and the name, Inter 4.1 for text. Each
   is subset to Latin, and the copyright and the licence are carried inside each
   file. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/inter-400.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/inter-600.woff2") format("woff2");
}
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/montserrat-400.woff2") format("woff2");
}
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/fonts/montserrat-700.woff2") format("woff2");
}

/* ---------- tokens ---------- */

:root {
  /* Light-first and light-only: nothing here repaints because a reader's system is
     set one way or the other. The site declares its own ground. */
  color-scheme: light;

  /* The board's colour palette. */
  --navy:     #0b2d5b;  /* trust, stability, foundation */
  --azure:    #00a9ff;  /* innovation, clarity, intelligence */
  --teal:     #00c2a8;  /* balance, technology, progress */
  --leaf:     #56c271;  /* health, vitality, growth */
  --mint:     #e6f7f2;  /* calm, clean, openness */
  --charcoal: #1f2937;  /* readability, contrast */

  /* The board's interface neutrals. */
  --bg:      #f5faff;   /* background */
  --surface: #f0fdf7;   /* surface */
  --neutral: #fafafb;   /* neutral */
  --text:    #0b2d5b;   /* text primary */
  --text-3:  #64748b;   /* text secondary */

  /* Derived here. Running text sits between charcoal and the secondary grey; the
     inks are the accents deepened until they pass 4.5:1 as text on the ground. */
  --text-2:      #334155;
  --paper:       #ffffff;
  --rule:        #dfe7f1;
  --rule-strong: #c6d4e5;
  --azure-ink:   #0069c2;
  --teal-ink:    #007566;
  --leaf-ink:    #237a3b;
  --warn-ink:    #7a4a00;
  --warn-wash:   #fff8eb;
  --warn-rule:   #efcd86;

  /* The board's two gradients. */
  --grad-tech:   linear-gradient(90deg, #0b2d5b, #00a9ff);
  --grad-nature: linear-gradient(90deg, #00c2a8, #56c271);

  --accent:      var(--azure);
  --accent-text: var(--azure-ink);
  --accent-wash: #eaf5ff;

  --state-live: var(--leaf-ink);
  --state-test: var(--azure-ink);
  --state-idea: var(--text-3);

  --shadow: 0 1px 2px rgba(11, 45, 91, 0.05), 0 8px 24px -12px rgba(11, 45, 91, 0.16);
  --radius: 12px;

  /* The board's type: Montserrat for headings and the name, Inter for text. Both are
     served from here; the system faces behind them are only what shows while a face
     is still loading. */
  --display: "Montserrat", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "Segoe UI Mono", Menlo, Consolas, monospace;

  --measure: 66ch;
  --rail: 10.5rem;
  --step: 2.5rem;
}

/* Per-area accent. The system is shared; the signal colour is not. Each is the
   product's own hue taken down until it is legible on the light ground — the hue
   belongs to the product, the lightness belongs to this site. */
.t-proofkin  { --accent: #d35432; --accent-text: #b03e1e; --accent-wash: #fcefea; }
.t-bodylytix { --accent: #1fa881; --accent-text: #0f7a5f; --accent-wash: #e7f6f0; }
.t-blx       { --accent: #2f6fe0; --accent-text: #1f5bc7; --accent-wash: #edf3ff; }
.t-pdf       { --accent: #10201c; --accent-text: #10201c; --accent-wash: #eef5f1; }
.t-tnt       { --accent: #8e5bc0; --accent-text: #7443a8; --accent-wash: #f4eefa; }
.t-wos       { --accent: #1a9bb8; --accent-text: #0e7490; --accent-wash: #e6f6f9; }

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

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

html { -webkit-text-size-adjust: 100%; background: var(--bg); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  overflow-wrap: break-word;
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 0;
  color: var(--text);
  text-wrap: balance;
}

p { margin: 0 0 1.1em; max-width: var(--measure); color: var(--text-2); }
p:last-child { margin-bottom: 0; }
p b, li b { color: var(--text); font-weight: 600; }

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 0.22em; }
p a, li a, dd a { color: var(--accent-text); text-decoration-color: rgba(0, 105, 194, 0.35); }
a:hover { text-decoration-color: var(--teal); }

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

::selection { background: #c4ecf6; color: var(--navy); }

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

ul, ol { max-width: var(--measure); color: var(--text-2); }

code { font-family: var(--mono); font-size: 0.88em; color: var(--azure-ink); }

/* ---------- layout ---------- */

.wrap { width: min(100% - 2.5rem, 70rem); margin-inline: auto; }

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--navy);
  color: #ffffff;
  padding: 0.75rem 1.1rem;
  z-index: 20;
  font-size: 0.85rem;
  font-weight: 600;
  border-radius: 8px;
}
.skip:focus { left: 0.75rem; top: 0.75rem; }

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

/* One masthead, on every public route, and it is the same object everywhere: the
   mark and the name going home, then three customer destinations. There is no
   second row, no internal entry, and nothing that asks a visitor to understand
   how this company works on the inside. */
.masthead {
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.masthead-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.9rem 1.6rem;
  padding-block: 0.85rem;
}

/* The name as the board sets it: "Vivenso" heavy in navy, "Labs" light in teal,
   close enough to read as one word and still two words to a screen reader. The
   link is a flex box, which drops the space between the two words from the layout
   (not from the text), so the gap is drawn as a margin instead. */
.wordmark {
  display: inline-flex;
  align-items: center;
  font-family: var(--display);
  font-size: 1.32rem;
  line-height: 1;
  letter-spacing: -0.01em;
  text-decoration: none;
  color: var(--navy);
  flex: none;
}
.wordmark img { width: 36px; height: 32px; display: block; margin-right: 0.6rem; }
.wordmark b { font-weight: 700; }
.wordmark span { color: var(--teal); font-weight: 400; margin-left: 0.16em; }
.wordmark:hover span { color: var(--teal-ink); }

.nav ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.15rem 1.6rem;
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
}
.nav a {
  position: relative;
  display: inline-block;
  padding: 0.42rem 0;
  font-size: 0.95rem;
  color: var(--text-2);
  text-decoration: none;
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  border-radius: 3px;
  background: var(--grad-nature);
  opacity: 0;
}
.nav a:hover { color: var(--navy); }
.nav a:hover::after { opacity: 0.45; }
/* aria-current="page" is the page the reader is on. aria-current="true" is the
   section it sits in — a product page is inside Products — and the two are drawn
   the same way on purpose, because to a reader they mean the same thing. */
.nav a[aria-current] { color: var(--navy); font-weight: 600; }
.nav a[aria-current]::after { opacity: 1; }

/* Phones. Nothing folds behind a control: the name takes its own line and the
   four destinations take the full width beneath it. */
@media (max-width: 46rem) {
  .masthead-inner { flex-direction: column; align-items: stretch; gap: 0.45rem; }
  .nav ul { gap: 0 1.4rem; }
}

/* ---------- editorial primitives ---------- */

/* The board's section label: small, spaced capitals with a short line of the
   nature gradient in front. */
.kicker {
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-3);
  margin: 0 0 1.1rem;
  max-width: none;
  display: flex;
  align-items: center;
  gap: 0.7rem;
}
.kicker::before {
  content: "";
  width: 1.8rem;
  height: 3px;
  border-radius: 3px;
  background: var(--grad-nature);
  flex: none;
}

.lede {
  font-size: clamp(1.1rem, 1.02rem + 0.38vw, 1.3rem);
  line-height: 1.55;
  color: var(--text-2);
  max-width: 56ch;
}

.small { font-size: 0.9rem; color: var(--text-3); }

/* A rail + body grid: the label lives in the margin, like a printed note. */
.rail {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  gap: 0 2.5rem;
  align-items: start;
}
.rail > .rail-label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-3);
  margin: 0.42rem 0 0;
  padding-top: 0.6rem;
  max-width: none;
  background: var(--grad-nature) top left / 100% 3px no-repeat;
}

.section {
  padding-block: clamp(2.4rem, 1.5rem + 3.4vw, 4.4rem);
  border-top: 1px solid var(--rule);
}
.section h2 {
  font-size: clamp(1.5rem, 1.25rem + 1.05vw, 2.1rem);
  margin-bottom: 1rem;
}
.section h3 { font-size: 1.06rem; margin: 0 0 0.55rem; }

/* A heading that starts a block inside a section rather than starting a new one.
   ".section h3" out-specifies a bare class, so this needs the element too. */
.section h3.op-title {
  font-size: 1.12rem;
  margin: var(--step) 0 0.2rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--rule);
}

@media (max-width: 46rem) {
  .rail { grid-template-columns: minmax(0, 1fr); gap: 0.8rem 0; }
  .rail > .rail-label { margin-top: 0; justify-self: start; min-width: 7rem; }
}

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

.hero { padding-block: clamp(2.6rem, 1.4rem + 5vw, 5rem) clamp(2.2rem, 1.2rem + 4vw, 4rem); }
.hero h1 {
  font-size: clamp(2rem, 1.4rem + 2.6vw, 3.35rem);
  letter-spacing: -0.022em;
  max-width: 20ch;
}
.hero .lede { margin-top: 1.4rem; }

/* The one place on the site with atmosphere: the board's light ground, with an
   azure light from one corner and a mint one from the other. No image, nothing
   fetched. */
.ground {
  background-color: var(--bg);
  background-image:
    radial-gradient(52rem 26rem at 88% -8%, rgba(0, 194, 168, 0.13), transparent 62%),
    radial-gradient(44rem 24rem at 4% 0%, rgba(0, 169, 255, 0.1), transparent 60%),
    linear-gradient(180deg, #ffffff, rgba(255, 255, 255, 0) 70%);
  border-bottom: 1px solid var(--rule);
}

.hero-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.6rem;
  margin-top: 1.8rem;
  font-size: 0.82rem;
  letter-spacing: 0.02em;
  color: var(--text-3);
  max-width: none;
}
.hero-meta > span { display: inline-flex; align-items: center; }

/* ---------- the home hero: the board's first row ---------- */

/* The lockup on one side — the mark, the name and the line under it — and the
   essence on the other, divided by a hairline, as the board lays them out. */
.hero-home {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: 2rem clamp(2rem, 1rem + 4vw, 4.5rem);
  align-items: center;
}
.hero-home .essence { border-left: 1px solid var(--rule); padding-left: clamp(2rem, 1rem + 4vw, 4.5rem); }
.hero-home h1 { max-width: 16ch; }
.hero-home h1::after {
  content: "";
  display: block;
  width: 3rem;
  height: 3px;
  margin-top: 1.2rem;
  border-radius: 3px;
  background: var(--grad-nature);
}
.hero-home .lede { margin-top: 1.3rem; }
.hero-note { margin-top: 1rem; font-size: 1rem; }

.lockup { margin: 0; display: grid; justify-items: center; text-align: center; }
.lockup-mark { width: clamp(150px, 10vw + 90px, 230px); height: auto; display: block; }
.lockup-name {
  margin: 0.9rem 0 0;
  max-width: none;
  font-family: var(--display);
  font-size: clamp(2rem, 1.5rem + 1.9vw, 3.1rem);
  line-height: 1;
  letter-spacing: -0.02em;
  word-spacing: -0.14em;
  color: var(--navy);
}
.lockup-name b { font-weight: 700; }
.lockup-name span { color: var(--teal); font-weight: 400; }

/* The line under the name. Written in sentence case and set in spaced capitals,
   so a screen reader says it as a sentence rather than spelling out a shout. */
.tagline {
  margin: 0.8rem 0 0;
  max-width: none;
  font-size: clamp(0.6rem, 0.55rem + 0.25vw, 0.74rem);
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--navy);
}

/* The board's four values, each an outline icon over two words. */
.values {
  list-style: none;
  margin: 2rem 0 0;
  padding: 1.3rem 0 0;
  border-top: 1px solid var(--rule);
  max-width: none;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.values li {
  display: grid;
  justify-items: center;
  align-content: start;
  gap: 0.6rem;
  padding: 0.2rem 0.6rem;
  text-align: center;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.45;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--teal-ink);
}
.values li + li { border-left: 1px solid var(--rule); }
.values svg {
  width: 40px;
  height: 40px;
  fill: none;
  stroke: var(--teal);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.values .ink { stroke: var(--navy); }

@media (max-width: 60rem) {
  .hero-home { grid-template-columns: minmax(0, 1fr); }
  .hero-home .essence { border-left: 0; padding-left: 0; }
  .lockup { justify-items: start; text-align: left; }
}
@media (max-width: 30rem) {
  .values { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 1.1rem; }
  .values li:nth-child(3) { border-left: 0; }
}

/* ---------- outbound links ---------- */

/* A link that leaves this site. It is set apart from the site's own navigation on
   purpose: it names the destination it goes to, carries the arrow that says it is
   leaving, and tells a screen reader that a new tab is about to open. Nothing is
   fetched from the other origin — this is a destination a reader chooses, not a
   request the page makes. */
.ext {
  display: inline-flex;
  align-items: center;
  gap: 0.34rem;
  min-height: 24px;
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--accent-text);
  text-decoration-color: var(--rule-strong);
  text-underline-offset: 0.3em;
}
.ext::after {
  content: "\2197";
  color: var(--accent-text);
  font-size: 1.05em;
  line-height: 1;
}
.ext:hover { text-decoration-color: var(--teal); }
.ext-lg { font-size: 0.95rem; }

/* The product page states its address under the hero meta, before the mark. */
.hero-out {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem 0.9rem;
  margin-top: 1.5rem;
  max-width: none;
}
.hero-out .small { color: var(--text-3); }

/* An index entry for a product that runs its own public site. The second link sits
   outside the entry link rather than inside it — an anchor cannot hold another
   anchor — and lines up with the entry body so the two destinations read as one
   block rather than as a stray line under the list. */
.index > li.has-site .entry { padding-bottom: 0.7rem; }
.entry-out { margin: 0; padding: 0 0 1.5rem 5.9rem; max-width: none; }
@media (max-width: 46rem) {
  .entry-out { padding-left: 4.9rem; }
}

/* ---------- portfolio index ---------- */

.index { list-style: none; margin: 0; padding: 0; max-width: none; }
.index > li { border-top: 1px solid var(--rule); }
.index > li:last-child { border-bottom: 1px solid var(--rule); }

.entry {
  display: grid;
  grid-template-columns: 4.4rem minmax(0, 1fr) auto;
  gap: 0.3rem 1.5rem;
  padding: 1.5rem 0;
  text-decoration: none;
  color: inherit;
  align-items: start;
}
.entry:hover { background: linear-gradient(90deg, var(--accent-wash), rgba(255, 255, 255, 0) 72%); }
.entry:hover .entry-title { color: var(--accent-text); }
.entry:hover .entry-title::after { transform: translateX(0.28rem); }

/* The number and the mark sit on one line, so an entry with a mark is the same
   height as one without and the six read as one list rather than six boxes. */
.entry-id { display: flex; align-items: center; gap: 0.6rem; padding-top: 0.12rem; }
.entry-num {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.86rem;
  letter-spacing: 0.04em;
  color: var(--azure-ink);
}
.entry-mark { width: 26px; height: 26px; border-radius: 6px; display: block; }

.entry-title {
  grid-column: 2;
  font-size: 1.3rem;
  margin: 0;
  color: var(--text);
}
.entry-title::after {
  content: "\2192";
  display: inline-block;
  margin-left: 0.5rem;
  color: var(--accent);
  transition: transform 140ms ease;
}
.entry-title .small { color: var(--text-3); font-family: var(--sans); font-weight: 400; letter-spacing: 0; }
.entry-body { grid-column: 2; margin: 0.45rem 0 0; color: var(--text-2); }
.entry-body p { margin: 0; }
.entry-state { grid-column: 3; grid-row: 1; justify-self: end; }

@media (max-width: 46rem) {
  .entry { grid-template-columns: 3.4rem minmax(0, 1fr); }
  .entry-mark { width: 22px; height: 22px; }
  .entry-state { grid-column: 2; grid-row: auto; justify-self: start; margin-top: 0.6rem; }
}

/* ---------- state chips ---------- */

.state {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--state-idea);
}
.state::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  flex: none;
}
.state-live { color: var(--state-live); }
.state-live::before { background: currentColor; }
.state-test { color: var(--state-test); }
.state-test::before { background: linear-gradient(135deg, currentColor 0 50%, transparent 50% 100%); }
.state-idea { color: var(--state-idea); }

/* ---------- key ---------- */

.key {
  list-style: none;
  margin: 1.4rem 0 0;
  padding: 1rem 0 0;
  border-top: 1px solid var(--rule);
  display: grid;
  gap: 0.55rem;
  max-width: none;
}
.key li { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.key .small { max-width: 42ch; }

/* ---------- ledger (fact + state list) ---------- */

.ledger { list-style: none; margin: 1.1rem 0 0; padding: 0; max-width: none; }
.ledger > li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.2rem 1.5rem;
  padding: 1.05rem 0;
  border-top: 1px solid var(--rule);
  align-items: start;
}
.ledger > li:last-child { border-bottom: 1px solid var(--rule); }
.ledger .ledger-what { margin: 0; font-weight: 600; max-width: 52ch; color: var(--text); }
.ledger .small { grid-column: 1; margin: 0.15rem 0 0; max-width: 64ch; }
.ledger .state { grid-column: 2; grid-row: 1; justify-self: end; }
@media (max-width: 40rem) {
  .ledger > li { grid-template-columns: minmax(0, 1fr); }
  .ledger .state { grid-column: 1; grid-row: auto; justify-self: start; margin-top: 0.5rem; }
}

/* ---------- columns ---------- */

.cols {
  display: grid;
  gap: 1.6rem 2.5rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  margin-top: 1.6rem;
}
.cols p, .cols .small { max-width: 42ch; }
.cols-3 { grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); }
.cols-2 { grid-template-columns: repeat(auto-fit, minmax(21rem, 1fr)); }
.cols + p { margin-top: var(--step); }

/* A line of the nature gradient over each column, so four habits read as four
   columns of a printed table rather than as four loose paragraphs. */
.cols.ruled > div {
  padding-top: 1rem;
  background: linear-gradient(90deg, var(--teal), var(--leaf) 45%, var(--rule) 45%) top left / 100% 2px no-repeat;
}
.cols.ruled h3 { font-size: 1.02rem; }

/* ---------- pull / notice ---------- */

.pull {
  font-family: var(--display);
  font-size: clamp(1.1rem, 1rem + 0.45vw, 1.32rem);
  line-height: 1.45;
  color: var(--navy);
  border-left: 3px solid var(--teal);
  padding-left: 1.1rem;
  margin-top: 1.6rem;
  max-width: 46ch;
}

.notice {
  border: 1px solid var(--rule);
  background: var(--paper);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.25rem 1.4rem;
  margin-block: var(--step);
  max-width: none;
}
.notice h2, .notice h3 { font-size: 1.05rem; margin-bottom: 0.5rem; }
.notice p { font-size: 0.94rem; color: var(--text-2); }
.notice-warn { border-color: var(--warn-rule); background: var(--warn-wash); box-shadow: none; }
.notice-warn h2, .notice-warn h3 { color: var(--warn-ink); }

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

.points { list-style: none; margin: 1rem 0 0; padding: 0; }
.points > li {
  position: relative;
  padding-left: 1.35rem;
  margin-bottom: 0.7rem;
  color: var(--text-2);
}
.points > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.68em;
  width: 0.6rem;
  height: 2px;
  border-radius: 2px;
  background: var(--teal);
}
.points > li:last-child { margin-bottom: 0; }
.points + p { margin-top: 1.15em; }

/* ---------- evidence figure ---------- */

.shot { margin: 1.6rem 0 0; }
.shot-frame {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: var(--shadow);
  padding: 0.6rem;
  overflow: hidden;
}
.shot-frame img { display: block; width: 100%; height: auto; border-radius: 4px; }
.shot figcaption { margin-top: 0.7rem; font-size: 0.87rem; color: var(--text-3); max-width: 62ch; }

/* ---------- product marks ---------- */

.markbox {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 0 1.2rem;
  align-items: center;
  margin: 2rem 0 0;
  max-width: 46rem;
}
.markbox img { width: 64px; height: 64px; border-radius: 12px; display: block; }
.markbox figcaption { font-size: 0.87rem; color: var(--text-3); }

.marks-note {
  margin-top: 1.4rem;
  font-size: 0.87rem;
  color: var(--text-3);
  max-width: 70ch;
  border-top: 1px solid var(--rule);
  padding-top: 0.9rem;
}

/* ---------- fact list ---------- */

.facts {
  margin: 1.4rem 0 0;
  display: grid;
  grid-template-columns: minmax(9rem, 14rem) minmax(0, 1fr);
  max-width: 56rem;
  border-top: 1px solid var(--rule);
}
.facts dt {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
  padding: 0.85rem 1.4rem 0.78rem 0;
  border-bottom: 1px solid var(--rule);
}
.facts dd {
  margin: 0;
  padding: 0.78rem 0;
  color: var(--text);
  border-bottom: 1px solid var(--rule);
  font-size: 0.95rem;
}
.facts dd .small { display: block; color: var(--text-3); margin-top: 0.15rem; }
@media (max-width: 40rem) {
  .facts { grid-template-columns: minmax(0, 1fr); }
  .facts dt { padding-bottom: 0; border-bottom: 0; }
  .facts dd { padding-top: 0.2rem; }
}

/* ---------- screen-reader text ---------- */

.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- contact ---------- */

.contact {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 1.2rem;
  margin-top: 1.6rem;
  max-width: none;
}
.contact > div {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: var(--shadow);
  padding: 1.2rem 1.3rem;
}
.contact h3 {
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-3);
  margin: 0 0 0.6rem;
}
.contact p { font-size: 0.94rem; max-width: none; }
.contact .value { font-family: var(--display); font-weight: 700; font-size: 1.12rem; color: var(--text); margin: 0 0 0.35rem; }
.contact .pending {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
  border: 1px dashed var(--rule-strong);
  border-radius: 999px;
  padding: 0.4rem 0.8rem;
  margin-bottom: 0.6rem;
}

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

/* The board's navy banner: the tile mark, the name in white and teal, and the line
   under it, over the site's own index. */
.footer {
  --text-3: #9fb7d6;
  background-color: var(--navy);
  background-image:
    radial-gradient(40rem 18rem at 100% 0%, rgba(0, 169, 255, 0.16), transparent 65%),
    radial-gradient(30rem 16rem at 0% 100%, rgba(0, 194, 168, 0.12), transparent 65%);
  color: #c9d8ee;
  margin-top: clamp(2.5rem, 1.5rem + 4vw, 5rem);
  padding-block: 2.8rem 2.6rem;
  border-top: 3px solid var(--teal);
}
.footer :focus-visible { outline-color: #5cc8ff; }

.footer-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: 2rem 3rem;
  padding-bottom: 2rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.footer-lockup { display: grid; justify-items: start; align-content: start; gap: 0.6rem; }
.footer-lockup img {
  width: 48px;
  height: 48px;
  display: block;
  border-radius: 11px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16), 0 8px 24px -8px rgba(0, 169, 255, 0.45);
}
.footer-name {
  margin: 0.2rem 0 0;
  max-width: none;
  font-family: var(--display);
  font-size: 1.5rem;
  line-height: 1;
  letter-spacing: -0.015em;
  word-spacing: -0.14em;
  color: #ffffff;
}
.footer-name b { font-weight: 700; color: #ffffff; }
.footer-name span { color: var(--teal); font-weight: 400; }
.footer .tagline { margin: 0; font-size: 0.62rem; letter-spacing: 0.26em; color: var(--text-3); }

.footer-nav {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1.4rem 2.5rem;
}
.footer-nav > div > p {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-3);
  margin: 0 0 0.6rem;
  padding-bottom: 0.45rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  max-width: none;
}
.footer-nav ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.3rem; max-width: none; }
.footer-nav a {
  font-size: 0.92rem;
  color: #c9d8ee;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  display: inline-block;
  padding: 0.16rem 0;
}
.footer-nav a:hover { color: #ffffff; border-bottom-color: rgba(0, 194, 168, 0.6); }
.footer-nav a[aria-current] { color: #ffffff; border-bottom-color: var(--teal); }

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.6rem 2rem;
  padding-top: 1.5rem;
}
.footer-inner p { margin: 0; max-width: 54ch; font-size: 0.88rem; color: var(--text-3); }
.footer-inner p b { color: #ffffff; }
.footer-brand { display: inline-flex; align-items: center; gap: 0.55rem; }

@media (max-width: 46rem) {
  .footer-top { grid-template-columns: minmax(0, 1fr); }
}

.by {
  margin-top: var(--step);
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  font-size: 0.85rem;
  color: var(--text-3);
  max-width: none;
}
.by a { color: var(--text-2); text-decoration-color: var(--rule-strong); }

/* ---------- 404 ---------- */

.lost { padding-block: clamp(3.5rem, 2rem + 7vw, 7rem); }
.lost h1 { font-size: clamp(1.9rem, 1.4rem + 2.2vw, 2.9rem); max-width: 22ch; }
.lost .lede { margin-top: 1.4rem; }
.lost .code {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--azure-ink);
  margin: 0 0 0.9rem;
}

/* ---------- research (.tabs, .grid) ---------- */

/* The research section's own tabs: links between its pages, drawn as a row of tabs
   under the page heading. Plain links, so they work with no script. */
.tabs { margin-top: 2rem; max-width: none; }
.tabs ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: none;
}
.tabs a {
  display: inline-block;
  padding: 0.55rem 1.05rem;
  border: 1px solid var(--rule-strong);
  border-radius: 999px;
  background: var(--paper);
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--text-2);
  text-decoration: none;
}
.tabs a:hover { border-color: var(--azure-ink); color: var(--navy); }
.tabs a[aria-current] { background: var(--navy); border-color: var(--navy); color: var(--paper); }

/* A comparison table. It scrolls sideways inside its own frame on a narrow screen,
   so the page itself never does. */
.table-wrap {
  margin-top: 1.4rem;
  max-width: none;
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper);
}
.table-wrap + p, .table-wrap + .shot { margin-top: 1.4rem; }
.grid { width: 100%; min-width: 38rem; border-collapse: collapse; font-size: 0.9rem; }
.grid th, .grid td {
  padding: 0.65rem 0.9rem;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--rule);
}
.grid thead th {
  font-family: var(--display);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--text-2);
  background: var(--accent-wash);
  white-space: nowrap;
}
.grid tbody th { font-weight: 600; color: var(--text); }
.grid td { color: var(--text-2); }
.grid tbody tr:last-child th, .grid tbody tr:last-child td { border-bottom: 0; }
.after-shot { margin-top: 1.2rem; }

/* A set of clips, one per model. Each plays only when its own control is pressed:
   nothing loads but the poster until then, and nothing plays by itself. */
.clips {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.2rem;
  margin: 1.6rem 0 0;
  max-width: none;
}
.clip { margin: 0; }
.clip video, .clip img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--navy);
}
/* One film shown by itself, in its own shape: the Studio pages. */
.clips-film { grid-template-columns: minmax(0, 46rem); }
.clips-film .clip video { aspect-ratio: 1 / 1; }
.clip figcaption { margin-top: 0.55rem; font-size: 0.87rem; color: var(--text-3); }
.clip figcaption b { color: var(--text); font-weight: 600; }
.clip-none {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 9;
  padding: 1rem;
  border: 1px dashed var(--rule-strong);
  border-radius: var(--radius);
  font-size: 0.9rem;
  color: var(--text-3);
  text-align: center;
}
.clips + .table-wrap, .clips + p { margin-top: 1.4rem; }
@media (max-width: 46rem) {
  .clips { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- motion ---------- */

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

/* ---------- utilities ---------- */

.nowrap { white-space: nowrap; }

/* ---------- Filekin (.t-pdf, .fk-) ---------- */

/* Filekin's own identity, 03 · The Seam: a forest-black tile, mint, and an amber join.
   It sits inside the site's light system rather than replacing it, so the masthead,
   the footer and the running text are the same objects as on every other page.

   Forest is Filekin's brand and interactive colour: the promise, the links and the
   keyboard focus ring. Mint is a surface and a rule. Amber is only ever the join, a
   short stroke or a hairline, and never text or a control. As text on the light ground
   amber reads at 2.4:1 and mint at 1.3:1, so neither may carry words, and
   tools/verify.mjs holds that. Everything below is namespaced .fk- or scoped to the
   Filekin page (.t-pdf main), so no other page moves. */
:root {
  --fk-forest: #10201c;  /* the tile; 16.1:1 as text on the ground */
  --fk-mint:   #cfe2d8;  /* surfaces and rules only */
  --fk-amber:  #d39a3a;  /* the join, and nothing else */
  --fk-seam: linear-gradient(90deg, var(--fk-forest) 0 62%, var(--fk-amber) 62% 74%, var(--fk-mint) 74%);
}

/* The section labels and the kicker carry the seam instead of the nature gradient. */
.t-pdf .kicker::before,
.t-pdf .rail > .rail-label { background-image: var(--fk-seam); }

/* Links and the keyboard focus ring in forest, inside the page only: the masthead and
   the navy footer keep the site's own, which are drawn for their grounds. */
.t-pdf main p a,
.t-pdf main li a,
.t-pdf main dd a { text-decoration-color: rgba(16, 32, 28, 0.4); }
.t-pdf main a:hover { text-decoration-color: var(--fk-forest); }
.t-pdf main :focus-visible { outline-color: var(--fk-forest); }

/* The hero: the Seam mark beside the name and the promise. The mark is the canonical
   vector, copied unchanged; nothing here redraws, recolours or crops it. */
.fk-lockup {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
}
.fk-mark {
  display: block;
  flex: none;
  width: clamp(72px, 3.2vw + 58px, 104px);
  height: auto;
}
.fk-promise {
  margin: 0.55rem 0 0;
  max-width: none;
  font-family: var(--display);
  font-size: clamp(1.2rem, 1rem + 0.9vw, 1.7rem);
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--fk-forest);
}
.fk-promise::after {
  content: "";
  display: block;
  width: 3.5rem;
  height: 3px;
  margin-top: 0.9rem;
  border-radius: 3px;
  background: var(--fk-seam);
}
.fk-hero .lede { margin-top: 1.5rem; }
.fk-naming { margin: 1.1rem 0 0; }

/* The screenshot is the product itself, and its label says so in the brand colour. */
.fk-shot .shot-frame { border-color: var(--fk-mint); }
.fk-shot figcaption b { color: var(--fk-forest); font-weight: 600; }

/* Five jobs, each under a forest rule with the amber join at its end. */
.fk-jobs {
  list-style: none;
  margin: 1.6rem 0 0;
  padding: 0;
  max-width: none;
  display: grid;
  gap: 1.4rem 2.2rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}
.fk-jobs > li {
  padding-top: 0.9rem;
  background:
    linear-gradient(90deg, var(--fk-forest) 0 2.2rem, var(--fk-amber) 2.2rem 2.7rem, var(--rule) 2.7rem)
    top left / 100% 2px no-repeat;
}
.fk-jobs h3 { font-size: 1.02rem; margin: 0 0 0.45rem; }
.fk-jobs p { margin: 0; font-size: 0.94rem; max-width: 42ch; }
.fk-notbuilt { border-left: 3px solid var(--fk-forest); }

/* The Plus preview, on the board's mint surface, where every text colour the site
   uses still reads at 4.5:1. */
.fk-plus {
  margin-top: 1.4rem;
  padding: 1.2rem 1.35rem;
  border: 1px solid var(--fk-mint);
  border-radius: var(--radius);
  background: var(--surface);
  max-width: 46rem;
}
.fk-plus h3 { margin-bottom: 0.4rem; }
.fk-plus .points { margin-top: 0.6rem; }
.t-pdf .points > li::before { background: var(--fk-forest); }
.fk-boundary {
  margin: 1rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--fk-mint);
}

/* A SHA-256 digest is 64 characters with nowhere to break, so it may break anywhere
   rather than push a phone's page sideways. */
.fk-hash {
  font-family: var(--mono);
  font-size: 0.8rem;
  overflow-wrap: anywhere;
  word-break: break-all;
}

/* The private preview: the trust notice beside the one download, and the file's facts
   under both. Side by side on a desktop, so the notice is read in the same glance as the
   action; stacked on a phone, notice first. The notice comes before the link in the
   markup either way, which is the order a screen reader and a keyboard meet them. */
.fk-get-body {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: 1.4rem 2.2rem;
  align-items: start;
  margin-top: 1.8rem;
}
.fk-get-body .notice { margin: 0; }
.fk-trust .points { margin-top: 0.5rem; }
.fk-trust .points > li { font-size: 0.94rem; }
@media (max-width: 52rem) {
  .fk-get-body { grid-template-columns: minmax(0, 1fr); }
}

/* The one download: a plain link, drawn as the page's only button. Forest with white
   text, which reads at 16.9:1 (12.3:1 on the hover ground), and a second line that
   names the file, its size and the host it comes from, so nobody meets the destination
   only after clicking. */
.fk-download {
  display: grid;
  gap: 0.2rem;
  min-height: 44px;
  padding: 0.95rem 1.3rem 1rem;
  border-radius: 10px;
  background: var(--fk-forest);
  color: #ffffff;
  text-decoration: none;
  box-shadow: var(--shadow);
}
.fk-download:hover { background: #1f3a33; }
.fk-download-label {
  font-family: var(--display);
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1.25;
}
.fk-download-file { font-size: 0.84rem; line-height: 1.4; overflow-wrap: anywhere; }

.fk-get-facts {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.3rem;
  font-size: 0.92rem;
  color: var(--text-2);
}
.fk-get-facts > li { position: relative; padding-left: 1.1rem; }
.fk-get-facts > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.68em;
  width: 0.5rem;
  height: 2px;
  border-radius: 2px;
  background: var(--fk-forest);
}

/* The digest, whole and in one piece: one click selects all 64 characters, and a phone
   wraps it rather than scrolling the page sideways. Nothing is inserted to wrap it, so
   what is copied is exactly what Get-FileHash prints. No script is involved. */
.fk-file { margin-top: 1.8rem; }
.t-pdf main code { color: var(--fk-forest); overflow-wrap: anywhere; }
.fk-sha,
.fk-cmd {
  display: block;
  margin: 0.35rem 0 0;
  padding: 0.45rem 0.65rem;
  border: 1px solid var(--fk-mint);
  border-radius: 6px;
  background: var(--surface);
  -webkit-user-select: all;
  user-select: all;
}
.fk-sha {
  margin-top: 0;
  font-size: 0.92rem;
  letter-spacing: 0.02em;
  word-break: break-all;
}

/* VL PDF portfolio entry, October 2026. Product assets from Brand Kit edition 3. */
.t-vl-pdf { --accent: #006d5e; --accent-text: #006d5e; --accent-wash: #e6f7f2; }
.vl-pdf-hero { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:3rem; align-items:center; }
.vl-pdf-hero h1 { font-size:clamp(2rem,3.5vw,3.3rem); }
.vl-pdf-lockup { display:block; width:190px; height:auto; margin:1rem 0 1.5rem; }
.vl-pdf-actions { display:flex; flex-wrap:wrap; align-items:center; gap:1rem 1.5rem; margin:1.6rem 0; }
a.vl-pdf-button { display:inline-flex; align-items:center; justify-content:center; min-height:48px; padding:.8rem 1.2rem; border-radius:6px; background:#006d5e; color:white; font-weight:600; text-decoration:none; }
a.vl-pdf-button:hover { background:#005548; color:white; }
.vl-pdf-gallery { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:1.5rem; }
.t-vl-pdf .shot-frame { display:block; }
.t-vl-pdf .shot { min-width:0; }
.contact a { overflow-wrap:anywhere; }
@media(max-width:52rem) { .vl-pdf-hero { grid-template-columns:1fr; gap:1rem; } .vl-pdf-gallery { grid-template-columns:1fr; } }
