/* =========================================================================
   BrandedReputation — core.css
   Hand-written. No framework. See CLAUDE.md before changing anything here.
   ========================================================================= */

/* ---------- 1. Reset ---------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body, h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol {
  margin: 0;
  padding: 0;
}

ul[role="list"], ol[role="list"] { list-style: none; }

img, svg, canvas { display: block; max-width: 100%; }

/* Any `display` rule on an element beats the hidden attribute, which silently
   revealed a success panel underneath a live form. Make hidden mean hidden. */
[hidden] { display: none !important; }

input, button, textarea, select { font: inherit; color: inherit; }

button { background: none; border: 0; cursor: pointer; }

a { color: inherit; text-decoration: none; }

:where(:focus-visible) {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---------- 2. Tokens --------------------------------------------------- */

:root {
  /* Ground. Warm, not clinical: #FFF reads as a browser default, paper does not.
     Warmed further in the premium pass: against a blue bloom the old value went
     grey and the whole page read like a screenshot of paper. */
  --void:      #FAF8F4;
  --field:     #FFFFFF;
  --panel:     #FFFFFF;

  /* Data. Ultramarine carries every measured value. */
  --core:      #1B3BFF;
  --beam:      #3D63FF;
  --halo:      #7A97FF;
  --wash:      #EAEEFF;

  /* RATIONED. Vermillion marks the client's own position and nothing else.
     Surveyors mark in red, it is the complement of ultramarine, and cyan has
     no strength on paper. */
  --signal:    #E33A12;
  --indigo:    #4B3BE8;

  /* Ink */
  /* Ink carries a trace of blue rather than being neutral black. Printed ink
     never sits at #000, and the difference is most of why a page reads as
     printed rather than rendered. */
  --ink:       #0A0C14;
  --muted:     #4A5162;
  --dim:       #8A8F9C;

  /* Lines & surfaces */
  --hairline:      rgba(11, 13, 18, 0.11);
  --hairline-firm: rgba(11, 13, 18, 0.22);
  --glass:         rgba(255, 255, 255, 0.74);

  /* Type */
  --sans: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --mono: "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* Space — deliberate, non-default steps */
  --s1: 0.5rem;
  --s2: 1rem;
  --s3: 1.5rem;
  --s4: 2.5rem;
  --s5: 4rem;
  --s6: 6rem;
  --s7: 9rem;
  --s8: 12.5rem;

  --gutter: clamp(1.25rem, 5vw, 4rem);
  --measure: 62ch;
  --shell: 1240px;

  /* Applied top AND bottom, so consecutive sections stacked ~350px of dead air.
     Negative space belongs around the focal object, not between blocks. */
  --section-y: clamp(3.75rem, 7.5vh, 6.5rem);

  /* Motion */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --slow: 900ms;
  --med:  420ms;
  --fast: 200ms;

  /* Grain — mandatory over every gradient. Never ship a bare gradient. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- 3. Base ----------------------------------------------------- */

body {
  background: var(--void);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

::selection { background: var(--core); color: var(--ink); }

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Skip link — back-of-the-cabinet craft. */
.skip {
  position: absolute;
  top: 0; left: 50%;
  transform: translate(-50%, -120%);
  z-index: 200;
  padding: 0.75rem 1.5rem;
  background: var(--ink);
  color: var(--void);
  font: 500 0.8125rem/1 var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 0 0 8px 8px;
  transition: transform var(--fast) var(--ease);
}
.skip:focus { transform: translate(-50%, 0); }

/* ---------- 4. Typography ----------------------------------------------- */

.eyebrow {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--dim);
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.eyebrow::before {
  content: "";
  width: 1.75rem;
  height: 1px;
  background: var(--hairline-firm);
  flex: none;
}

/* Optical sizing by hand. A single tracking value cannot serve 40px and 92px:
   what looks tight at the small end goes slack at the large one. The clamp
   scales tracking with size, which is what a type designer would do. */
.display {
  font-weight: 400;
  font-size: clamp(2.5rem, 6.4vw, 5.75rem);
  line-height: 0.95;
  letter-spacing: clamp(-0.045em, -0.028em - 0.22vw, -0.03em);
  text-wrap: balance;
}

/* Must stay clearly below the h1. Section heads were rendering larger than the
   page title, which inverts the hierarchy no matter how good the type is. */
.display-s {
  font-weight: 400;
  font-size: clamp(1.625rem, 2.7vw, 2.4375rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

/* Two-tone headline (ref 07): muted lead, white payload. Never gradient text. */
.display .lead,
.display-s .lead { color: var(--dim); display: block; }

.lede {
  font-size: clamp(1rem, 1.35vw, 1.1875rem);
  line-height: 1.62;
  color: var(--muted);
  max-width: var(--measure);
  text-wrap: pretty;
}

.fine {
  font-family: var(--mono);
  font-size: 0.75rem;
  line-height: 1.55;
  letter-spacing: 0.01em;
  color: var(--dim);
}

.fine a { border-bottom: 1px solid var(--hairline-firm); }
.fine a:hover { color: var(--muted); border-bottom-color: var(--muted); }

/* The data voice. Every actionable number is mono. */
.datum {
  font-family: var(--mono);
  font-weight: 300;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1;
}

.datum-xl { font-size: clamp(2.25rem, 5.2vw, 4rem); }
.datum-l  { font-size: clamp(1.75rem, 3vw, 2.5rem); }

/* Superscript decimals (ref 06) */
.datum sup {
  font-size: 0.42em;
  vertical-align: super;
  letter-spacing: 0;
  margin-left: 0.08em;
  color: var(--muted);
}

.unit {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dim);
}

/* ---------- 5. Grain & light -------------------------------------------- */

/* Grain has to be SEEN. In ref 02 it is the dominant texture, not a checkbox.
   Overlay blend puts most of the noise into the mid-tones of the light source
   and leaves the true blacks alone, which is how film actually behaves. */
.grain::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--grain);
  background-size: 160px 160px;
  opacity: 0.09;
  mix-blend-mode: multiply;
  pointer-events: none;
  z-index: 3;
}

@media (min-resolution: 2dppx) {
  .grain::after { background-size: 128px 128px; }
}

/* A single luminous source per view.

   REGRESSION NOTE: this rule was deleted when the grain block was rewritten,
   which dropped `position: absolute` and left every `.source` div as a static
   1024x1024 box in normal flow. That, not padding, was the cause of the huge
   empty runs between sections. Sections carry `.grain`, so these gradients are
   still grained and never ship bare. */
.source {
  position: absolute;
  z-index: 0;
  border-radius: 50%;
  pointer-events: none;
}

/* -------------------------------------------------------------------------
   The plate.
   Ref 02 is not a card. It is a large empty field with four tiny crosshairs
   at the extreme corners, one annotation floating at top centre, and one
   numbered rule at bottom centre. The marks belong to the FIELD, not to a
   box inside it. Nothing here draws a border, a radius, or a background.
   ------------------------------------------------------------------------- */

.plate { position: relative; }

.plate > .mark {
  position: absolute;
  z-index: 6;
  width: 11px;
  height: 11px;
  pointer-events: none;
  opacity: 0.42;
}
.plate > .mark::before,
.plate > .mark::after {
  content: "";
  position: absolute;
  background: rgba(11, 13, 18, 0.42);
}.plate > .mark::before { left: 50%; top: 0; width: 1px; height: 100%; transform: translateX(-50%); }
.plate > .mark::after  { top: 50%; left: 0; height: 1px; width: 100%; transform: translateY(-50%); }

.plate > .mark.tl { top: 22px; left: 22px; }
.plate > .mark.tr { top: 22px; right: 22px; }
.plate > .mark.bl { bottom: 22px; left: 22px; }
.plate > .mark.br { bottom: 22px; right: 22px; }

/* Annotation floating in the void, centred, tiny. Never in a header bar. */

.plate-note {
  position: absolute;
  z-index: 6;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 300;
  letter-spacing: 0.22em;
  color: rgba(11, 13, 18, 0.5);
  white-space: nowrap;
  pointer-events: none;
}
.plate-note.top { top: 24px; }
.plate-note.bottom { bottom: 24px; }

/* A rule that actually measures something, with numbers under the long ticks. */
.rule-scale {
  position: absolute;
  z-index: 6;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  display: grid;
  justify-items: center;
  gap: 5px;
  pointer-events: none;
}
.rule-scale .bars {
  display: flex;
  align-items: flex-end;
  gap: 7px;
  height: 10px;
}
.rule-scale .bars i {
  display: block;
  width: 1px;
  height: 3px;
  background: rgba(11, 13, 18, 0.3);
}
.rule-scale .bars i.major { height: 9px; background: rgba(11, 13, 18, 0.5); }

.rule-scale .nums {
  display: flex;
  justify-content: space-between;
  width: 100%;
  font-family: var(--mono);
  font-size: 0.5625rem;
  font-weight: 300;
  letter-spacing: 0.08em;
  color: rgba(11, 13, 18, 0.5);
}

/* ---------- 6. Pill button — the only button shape ---------------------- */

.pill {
  --pill-bg: var(--ink);
  --pill-fg: var(--void);
  display: inline-flex;
  align-items: center;
  gap: 0.875rem;
  padding: 0.6875rem 0.6875rem 0.6875rem 1.5rem;
  border-radius: 999px;
  background: var(--pill-bg);
  color: var(--pill-fg);
  font-size: 0.9375rem;
  font-weight: 450;
  letter-spacing: -0.01em;
  white-space: nowrap;
  transition: transform var(--fast) var(--ease), background var(--fast) var(--ease);
}

.pill:hover  { transform: translateY(-1px); }
.pill:active { transform: translateY(0); }

.pill .cap {
  display: grid;
  place-items: center;
  width: 1.875rem;
  height: 1.875rem;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.1);
  flex: none;
  transition: transform var(--med) var(--ease);
}

.pill:hover .cap { transform: translateX(2px); }
.pill .cap svg { width: 0.75rem; height: 0.75rem; }

.pill[disabled] { opacity: 0.4; pointer-events: none; }

.pill-ghost {
  --pill-bg: transparent;
  --pill-fg: var(--ink);
  box-shadow: inset 0 0 0 1px var(--hairline-firm);
  padding: 0.6875rem 1.5rem;
}
.pill-ghost:hover { --pill-bg: rgba(255, 255, 255, 0.05); }

.pill-mono {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.5rem 1.125rem;
  border-radius: 999px;
  background: rgba(75, 59, 232, 0.22);
  color: var(--halo);
  box-shadow: inset 0 0 0 1px rgba(143, 176, 255, 0.24);
  display: inline-block;
  transition: background var(--fast) var(--ease);
}
.pill-mono:hover { background: rgba(75, 59, 232, 0.34); }

/* ---------- 7. Glass panel ---------------------------------------------- */

.panel {
  position: relative;
  border-radius: 26px;
  background: var(--glass);
  backdrop-filter: blur(22px) saturate(120%);
  -webkit-backdrop-filter: blur(22px) saturate(120%);
  overflow: hidden;
  isolation: isolate;
}

/* 1px top border that catches light and fades downward. */
.panel::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(
    to bottom,
    rgba(11, 13, 18, 0.16) 0%,
    rgba(11, 13, 18, 0.07) 34%,
    rgba(11, 13, 18, 0.04) 100%
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
  z-index: 4;
}

/* ---------- 8. Instrumentation chrome ----------------------------------- */
/* Crosshairs and tick rulers. These annotate REAL values only. */

.instrument { position: relative; }

.instrument .xhair {
  position: absolute;
  width: 9px;
  height: 9px;
  pointer-events: none;
  opacity: 0.5;
  z-index: 5;
}
.instrument .xhair::before,
.instrument .xhair::after {
  content: "";
  position: absolute;
  background: var(--hairline-firm);
}
.instrument .xhair::before { left: 50%; top: 0; width: 1px; height: 100%; transform: translateX(-50%); }
.instrument .xhair::after  { top: 50%; left: 0; height: 1px; width: 100%; transform: translateY(-50%); }

.instrument .xhair.tl { top: 14px; left: 14px; }
.instrument .xhair.tr { top: 14px; right: 14px; }
.instrument .xhair.bl { bottom: 14px; left: 14px; }
.instrument .xhair.br { bottom: 14px; right: 14px; }

.ticks {
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 12px;
}
.ticks i {
  display: block;
  width: 1px;
  height: 4px;
  background: var(--hairline-firm);
}
.ticks i:nth-child(5n + 1) { height: 9px; }

.readout {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--dim);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.readout .dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--signal);
  flex: none;
}

/* Honest instrument: says so when it is not showing live data. */
.readout.is-demo { color: #C8A54A; }
.readout.is-demo .dot { background: #C8A54A; }

/* ---------- 9. Hairline list rows — replaces icon-card grids ------------ */

.rows { border-top: 1px solid var(--hairline); }

.row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--s3);
  align-items: start;
  padding: var(--s4) 0;
  border-bottom: 1px solid var(--hairline);
}

/* Three children in a two column grid. Auto placement dropped the paragraph
   into column one on the next row, so column one sized itself to the paragraph
   and the heading was left reading down a 52px ribbon on a phone. Both the
   heading and the paragraph belong in column two, under each other. */
.row .marker { grid-column: 1; }
.row .head,
.row > p { grid-column: 2; }

/* Dot marker, ref 07. The index alone read as a numbered list; the dot is what
   makes it a row in an instrument. */
.row .marker {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  color: var(--dim);
  padding-top: 0.45rem;
  min-width: 2.25rem;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}
.row .marker::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--beam);
  flex: none;
  transform: translateY(-2px);
}

.row .head { display: grid; gap: 0.4375rem; align-content: start; }

.row h3 {
  font-size: clamp(1.125rem, 1.7vw, 1.375rem);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.28;
}

/* Two-tier data row, ref 06: label above, the actual figures beneath it in
   mono. Only rows that HAVE a value carry one. */
.row .tag {
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 300;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dim);
}

.row p {
  color: var(--muted);
  max-width: 54ch;
  font-size: 0.9375rem;
  text-wrap: pretty;
}

@media (min-width: 860px) {
  /* 22rem forced two-line headings while the paragraph column sat half empty.
     The heading is the thing being read first, so it gets the room. */
  .row { grid-template-columns: 3.5rem minmax(0, 27rem) minmax(0, 1fr); }
  .row .head { grid-column: 2; }
  .row > p { grid-column: 3; }
  .row p { padding-top: 0.3rem; }
  .row h3 { margin-bottom: 0; }
}

/* ---------- 10. Section furniture --------------------------------------- */

section { position: relative; }

.band { padding-block: var(--section-y); }

.band-head {
  display: grid;
  gap: var(--s3);
  margin-bottom: var(--s5);
  max-width: 46rem;
}

.rule {
  height: 1px;
  background: var(--hairline);
  border: 0;
}

/* ---------- 11. Reduced motion ------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
