/* Orin site styles.
 *
 * THE LAW: this file defines no custom properties and holds no literal values.
 * Every value is read straight from the semantic token layer in
 * vendor/tokens.css as var(--orin-…), which is what a client consuming the
 * token set writes too — so what an inspector shows here is the deliverable,
 * not a local dialect of it. A value the design needs but doesn't have is a
 * TOKEN PROPOSAL: edit the JSON, rebuild, sync. Never a literal added here,
 * and never a convenience alias — the shorter name is worth less than the
 * property of having one source of truth visible in the inspector.
 *
 * Enforced by check 9 in tokens/scripts/report.mjs.
 */

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--orin-colour-background-default);
  color: var(--orin-colour-text-default);
  font-family: var(--orin-font-family-base);
  font-size: var(--orin-font-size-400);
  line-height: var(--orin-font-line-height-body-large);
  letter-spacing: var(--orin-font-letter-spacing-body-large);
  font-weight: var(--orin-font-weight-regular);
}

/* section band (full-bleed background) + wrap (68ch measure, inline padding only) */
.section { padding-block: var(--orin-space-16); }
.section--hero { padding-block: var(--orin-space-24); }
.section--inverse { background: var(--orin-colour-background-inverse); color: var(--orin-colour-text-inverse); }
.wrap { max-width: var(--orin-measure-prose); margin-inline: auto; padding-inline: var(--orin-space-6); }

/* --- 12-col grid scaffolding (Step 0.5). .container is the wide (75rem)
   outer measure; .section-grid is the 12-col layer inside it. Prose still
   clamps to --measure (68ch) via the existing p{} rule — wide scaffolding,
   narrow text. --- */
.container { max-width: var(--orin-container-max); margin-inline: auto; padding-inline: var(--orin-space-6); }
.section-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--orin-space-6); }
.section-grid--center { align-items: center; }
.section-grid h2 { margin-top: 0; }

.rail { grid-column: 1 / 2; margin: 0; color: var(--orin-colour-text-link); }
.col-main { grid-column: 2 / -1; }
.col-heading { grid-column: 2 / 7; }
.col-body { grid-column: 7 / -1; }
/* On an inverse band both the rail and the eyebrow have to flip. --ink-muted
   is a mid neutral chosen against paper; on the inverse ground it lands at
   2:1, well under AA. The rail was flipped in Step 0 and the eyebrow was not,
   which is the same defect twice — so they are one rule now. */
.section--inverse .rail,
.section--inverse .eyebrow { color: var(--orin-colour-text-inverse); }

h1, h2, h3 {
  font-family: var(--orin-font-family-display);
  font-weight: var(--orin-font-weight-semibold);
  margin: 0 0 var(--orin-space-6);
}
h1 {
  font-size: var(--orin-font-size-1000);
  line-height: var(--orin-font-line-height-display-medium);
  letter-spacing: var(--orin-font-letter-spacing-display-medium);
}
h2 {
  font-size: var(--orin-font-size-800);
  margin-top: var(--orin-space-12);
  line-height: var(--orin-font-line-height-headline-large);
  letter-spacing: var(--orin-font-letter-spacing-headline-large);
}
h3 {
  font-size: var(--orin-font-size-600);
  line-height: var(--orin-font-line-height-headline-medium);
  letter-spacing: var(--orin-font-letter-spacing-headline-medium);
}

p { margin: 0 0 var(--orin-space-4); max-width: var(--orin-measure-prose); }

a { color: var(--orin-colour-text-link); text-underline-offset: 0.15em; transition: color var(--orin-motion-duration-fast) var(--orin-motion-easing-standard); }
a:hover { color: var(--orin-colour-text-link-hover); }
a:focus-visible { outline: 2px solid var(--orin-colour-text-link); outline-offset: 3px; }

/* Off-screen but announced. For a heading a section needs structurally but
   the approved copy doesn't print — the /work card grid runs h1 → h3 without
   it. Not a component; an accessibility utility, same technique as .skip-link
   below. */
.visually-hidden {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--orin-colour-background-raised);
  color: var(--orin-colour-text-default);
  padding: var(--orin-space-2) var(--orin-space-4);
  border-radius: var(--orin-radius-md);
}
.skip-link:focus {
  left: var(--orin-space-4);
  top: var(--orin-space-4);
}

.button {
  display: inline-block;
  font-family: var(--orin-font-family-ui);
  font-size: var(--orin-font-size-300);
  font-weight: var(--orin-font-weight-medium);
  text-decoration: none;
  background: var(--orin-colour-background-accent);
  color: var(--orin-colour-text-on-accent);
  border: none;
  border-radius: var(--orin-radius-md);
  padding: var(--orin-space-3) var(--orin-space-6);
  cursor: pointer;
  transition: background-color var(--orin-motion-duration-fast) var(--orin-motion-easing-standard);
}
.button:hover { background: var(--orin-colour-background-accent-hover); color: var(--orin-colour-text-on-accent); }
.button:focus-visible { outline: 2px solid var(--orin-colour-text-link); outline-offset: 3px; }

.card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--orin-colour-border-strong);
  background: var(--orin-colour-background-raised);
  border-radius: var(--orin-radius-md);
  padding: var(--orin-space-6);
}
.card h3 { margin-top: 0; }
.card :last-child { margin-bottom: 0; }

.eyebrow, .rail, .card__index {
  font-family: var(--orin-font-family-ui);
  font-size: var(--orin-font-size-200);
  font-weight: var(--orin-font-weight-medium);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.eyebrow { color: var(--orin-colour-text-muted); }
.card__index { color: var(--orin-colour-text-link); margin: 0 0 var(--orin-space-2); }

/* --- hero: fluid type + decorative 12-col overlay (Step 0.5) --- */
.hero-heading {
  font-size: clamp(var(--orin-font-size-1000), 4vw + 1.5rem, var(--orin-font-size-1100));
}
.section--hero { position: relative; }
.section--hero .container { position: relative; z-index: 1; }
.grid-overlay {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--orin-space-6);
  max-width: var(--orin-container-max);
  margin-inline: auto;
  padding-inline: var(--orin-space-6);
  pointer-events: none;
}
.grid-overlay span {
  border-left: 1px solid var(--orin-colour-border-divider);
  padding-top: var(--orin-space-2);
  padding-left: var(--orin-space-2);
  font-family: var(--orin-font-family-ui);
  font-size: var(--orin-font-size-100);
  color: var(--orin-colour-text-muted);
  opacity: 0.6;
}

/* --- pricing cards row (Step 0.5; 2×2 since The Foundation made four) --- */
/* Was repeat(auto-fit, minmax(16rem, 1fr)), which fitted three engagements
   neatly and orphaned the fourth on its own row. Auto-fit can't express "two
   per row" robustly here — the track minimum that excludes a third column at
   desktop also excludes a second at tablet, and the widths that thread that
   gap leave ~2px of headroom. So the count is stated rather than derived. */
.cards { display: grid; grid-template-columns: 1fr; gap: var(--orin-space-6); }

/* At and above breakpoint.md (48rem — tokens/src/layout.json,
   --orin-breakpoint-md). Same documented exception as the query below: a
   literal, because @media cannot read custom properties. */
@media (min-width: 48rem) {
  .cards { grid-template-columns: repeat(2, 1fr); }
}
/* margin-top: auto pushes the rule + link to the card bottom, so slack from
   shorter cards sits above the rule and links align across the row */
.card-rule { border: none; border-top: 1px solid var(--orin-colour-border-divider); margin: auto 0 var(--orin-space-4); }

/* section-level "more →" link sitting below a section's content (e.g. below the cards) */
.section-more { margin-top: var(--orin-space-6); }

/* --- shared chrome --- */
.site-nav, .site-footer { font-family: var(--orin-font-family-ui); font-size: var(--orin-font-size-300); }
.site-nav { display: flex; flex-wrap: wrap; gap: var(--orin-space-6); padding: var(--orin-space-6); border-bottom: 1px solid var(--orin-colour-border-divider); }
.site-nav a { text-decoration: none; color: var(--orin-colour-text-default); }
.site-nav a:hover { color: var(--orin-colour-text-link); }
.site-footer { padding: var(--orin-space-8) var(--orin-space-6); border-top: 1px solid var(--orin-colour-border-divider); color: var(--orin-colour-text-muted); }

/* --- specimen: pipeline proof, lives at /tokens. Do not delete — it's the
   proof artefact for technical buyers ("this site runs on its own pipeline").
   Only /tokens/index.html references these classes. --- */
/* --- /tokens proof artefact only. Not part of the component budget: these
   describe the token layer rather than composing a page, and no other page
   uses them. The per-item colour/width/radius is set inline on the element,
   because each row differs by exactly one token and thirteen near-identical
   modifier classes would be worse. Those inline styles still resolve through
   var(--orin-…), so the law holds. --- */
.swatch { width: var(--orin-space-16); height: var(--orin-space-16); border-radius: var(--orin-radius-md); border: 1px solid var(--orin-colour-border-strong); flex: none; }

/* Colour and radius: a grid of labelled samples. */
.token-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--orin-space-4);
  margin: var(--orin-space-6) 0;
  padding: 0;
  list-style: none;
}
.token-item { display: flex; align-items: center; gap: var(--orin-space-3); }
.token-meta { display: flex; flex-direction: column; gap: var(--orin-space-1); min-width: 0; }
.token-name {
  font-family: var(--orin-font-family-ui);
  font-size: var(--orin-font-size-200);
  color: var(--orin-colour-text-default);
  overflow-wrap: anywhere;
}
.token-value {
  font-family: var(--orin-font-family-ui);
  font-size: var(--orin-font-size-200);
  color: var(--orin-colour-text-muted);
  /* Reserved so the runtime value swap doesn't shift the row. */
  min-width: 11ch;
}
.radius-sample {
  width: var(--orin-space-16);
  height: var(--orin-space-16);
  flex: none;
  background: var(--orin-colour-background-raised);
  border: 1px solid var(--orin-colour-border-strong);
}

/* Spacing: name, a bar drawn at the token's own width, then the value. */
.scale-list { margin: var(--orin-space-6) 0; padding: 0; list-style: none; }
.scale-row {
  display: flex;
  align-items: center;
  gap: var(--orin-space-4);
  padding: var(--orin-space-2) 0;
  border-bottom: 1px solid var(--orin-colour-border-divider);
}
.scale-row .token-name { min-width: 7ch; flex: none; }
.scale-row .bar { height: var(--orin-space-3); background: var(--orin-colour-background-accent); flex: none; }
.scale-row .token-value { margin-left: auto; text-align: right; }
.specimen-row { display: flex; align-items: baseline; gap: var(--orin-space-4); padding: var(--orin-space-2) 0; border-bottom: 1px solid var(--orin-colour-border-divider); }
.specimen-row .label { font-family: var(--orin-font-family-ui); font-size: var(--orin-font-size-200); color: var(--orin-colour-text-muted); min-width: 9rem; }

@media (prefers-reduced-motion: reduce) {
  a, .button { transition: none; }
}

/* Below breakpoint.md (48rem — tokens/src/layout.json, --orin-breakpoint-md).
   Same documented literal exception as the queries below: @media cannot read
   custom properties. The specimen stacks its label above the sample, because a
   single word at the 1000 and 1100 steps is wider than the column left beside a
   9rem label — it overflowed 360px by 7px before this. Stacking fixes the whole
   scale rather than the one row that happened to show it. */
@media (max-width: 47.9375rem) {
  .specimen-row { flex-direction: column; align-items: flex-start; gap: var(--orin-space-1); }
  .specimen-row .label { min-width: 0; }
}

/* Below breakpoint.lg (64rem — tokens/src/layout.json, --orin-breakpoint-lg).
   CSS @media conditions cannot read custom properties, so this is the one
   documented exception to "every value resolves through the token layer":
   the breakpoint value is duplicated here as a literal. See decisions.md.
   Collapses the 12-col grid to one column; rail/content stack in DOM order
   (rail markup precedes heading/body, so it lands above on small screens). */
@media (max-width: 63.9375rem) {
  .section-grid { grid-template-columns: 1fr; row-gap: var(--orin-space-4); }
  .rail, .col-main, .col-heading, .col-body { grid-column: 1 / -1; }
  .grid-overlay { display: none; }
}
