/* =====================================================================
   INTERFACE LAYER — loaded after style.css
   =====================================================================

   Turns the site into a set of flat colour fields (see "Page fields" in
   tokens.css) with a spec-sheet layout on top:

     - Crop marks: every page hero is framed by four corner marks, with
       the headline set huge, tight and centred inside them.
     - Ruled blocks: a section that opens with a label (.eyebrow) gets a
       thin vertical rule down its left edge, label small and mono at the
       top, content below — like annotated columns on a data sheet.
     - Hero columns: on wide screens the hero's intro paragraphs sit side
       by side as ruled columns under the headline.
     - Blocks, not pills: buttons and footer links are solid rectangles.
     - Path breadcrumb, bracketed current nav item, pointer-lit dot grid
       on the homepage hero, and a mono status bar in the footer.

   Everything here is layout; colour comes only from the tokens, so the
   same rules work on every field, paper and ink included.
   ===================================================================== */

body {
  font-size: 1.0625rem;
  line-height: 1.5;
  letter-spacing: -0.005em;
  overflow-x: clip;
}

::selection {
  background: var(--color-text);
  color: var(--color-bg);
}

/* ---------------------------------------------------------------------
   Type — one grotesk, big and tight
   --------------------------------------------------------------------- */

h1, .h1,
h2, .h2,
h3, .h3 {
  font-weight: 500;
  text-wrap: balance;
}

/* H1: Archivo, sentence case (UK style), tight — see TYPE in tokens.css */
h1, .h1 {
  font-family: var(--font-headline);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 0.86;
}

h2, .h2 {
  letter-spacing: -0.035em;
  line-height: 1;
}

h3, .h3 {
  letter-spacing: -0.025em;
}

.lead {
  font-size: clamp(1.1875rem, 1.05rem + 0.5vw, 1.4375rem);
  font-weight: 500;
  line-height: 1.32;
  letter-spacing: -0.015em;
  color: var(--color-text);
}

.case-title,
.service-title,
.impact-title {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.02em;
}

.case-title {
  font-size: 1.375rem;
  line-height: 1.15;
}

/* Label — small mono, sentence case, no marker */
.eyebrow {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-transform: none;
  color: var(--color-text);
  margin-bottom: var(--space-8);
}

.eyebrow::before {
  display: none;
}

a {
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a[href] {
  cursor: pointer;
}

/* Plain text links invert on hover, like a selected cell in text mode.
   On the colour fields --color-link equals --color-text, so a colour
   change alone would be invisible. :where() keeps this at low
   specificity so buttons, registers and nav keep their own states. */
:where(main a[href]:not([class])):hover {
  background: var(--color-text);
  color: var(--color-bg);
  box-shadow: 0 0 0 2px var(--color-text);
  text-decoration-color: transparent;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* ---------------------------------------------------------------------
   Crop marks — a corner-marked frame, drawn with background gradients
   so it needs no extra elements and follows the current text colour
   --------------------------------------------------------------------- */

.hero,
.crop-marks {
  --mark: 14px;
  --mark-color: var(--color-text);
  background:
    linear-gradient(var(--mark-color), var(--mark-color)) top left / var(--mark) 1px no-repeat,
    linear-gradient(var(--mark-color), var(--mark-color)) top left / 1px var(--mark) no-repeat,
    linear-gradient(var(--mark-color), var(--mark-color)) top right / var(--mark) 1px no-repeat,
    linear-gradient(var(--mark-color), var(--mark-color)) top right / 1px var(--mark) no-repeat,
    linear-gradient(var(--mark-color), var(--mark-color)) bottom left / var(--mark) 1px no-repeat,
    linear-gradient(var(--mark-color), var(--mark-color)) bottom left / 1px var(--mark) no-repeat,
    linear-gradient(var(--mark-color), var(--mark-color)) bottom right / var(--mark) 1px no-repeat,
    linear-gradient(var(--mark-color), var(--mark-color)) bottom right / 1px var(--mark) no-repeat;
}

.hero {
  padding-top: calc(var(--space-24) + var(--space-8));
  padding-bottom: var(--space-12);
  margin-bottom: var(--space-12);
}

/* The frame is drawn on the container's padding box; inset it so the
   marks sit just outside the content edge rather than at the viewport
   gutter. */
.hero.container {
  width: calc(100% - 2 * var(--space-4));
  max-width: calc(var(--container-width) - 2 * var(--space-4));
  padding-inline: calc(var(--container-pad) - var(--space-4));
}

/* Headline: huge, centred */
.hero h1 {
  font-size: clamp(3rem, 1rem + 7.25vw, 8.25rem);
  text-align: center;
  max-width: 16ch;
  margin-inline: auto;
  margin-bottom: var(--space-16);
}

.hero > .eyebrow {
  display: flex;
  justify-content: center;
  margin-bottom: var(--space-4);
}

/* Intro paragraphs become ruled columns */
.hero > p:not(.hero-status):not(.caption),
.hero > div > .lead {
  max-width: 34rem;
  margin: 0 0 var(--space-6);
  padding-left: var(--space-4);
  border-left: 1px solid var(--color-text);
}

@media (min-width: 56rem) {
  .hero:not(.hero-full-screen) {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--space-12);
    align-items: start;
  }

  .hero:not(.hero-full-screen) > * {
    grid-column: 1 / -1;
  }

  .hero:not(.hero-full-screen) > p:not(.caption) {
    grid-column: auto;
    max-width: none;
  }
}

.hero .hero-actions {
  margin-top: var(--space-8);
}

/* Inline widgets in the hero keep their natural width inside the grid */
.hero > .hm-toggle,
.hero > .stat-callout,
.hero > .back-link {
  justify-self: start;
}

.hm-toggle,
.hm-toggle-btn {
  border-radius: 0;
}

/* ---------------------------------------------------------------------
   Homepage hero — full screen, same frame, pointer-lit dot grid
   --------------------------------------------------------------------- */

/* Headline anchored to the top: style.css makes this hero fill the
   viewport, which let the content float down the page as the window
   changed shape. */
.hero-full-screen {
  position: relative;
  isolation: isolate;
  min-height: 0;
  justify-content: flex-start;
}

.hero-full-screen h1 {
  font-size: clamp(3rem, 0.5rem + 8.25vw, 9.5rem);
  max-width: 15ch;
  margin-bottom: var(--space-12);
  /* The reveal animation clips to the headline's box; at this line
     height descenders ("g", "y") would hang outside it and get cut. */
  padding-bottom: 0.14em;
}

.hero-full-screen .lead {
  font-size: clamp(1.1875rem, 1.05rem + 0.5vw, 1.4375rem);
}

/* Blinking block cursor after the homepage headline. Hidden while the
   headline streams in (main.js), then blinks once it has "finished". */
.hero-cursor {
  display: inline-block;
  width: 0.42em;
  height: 0.7em;
  margin-left: 0.06em;
  /* Takes no inline space, so it never changes where the headline
     breaks; it simply hangs past the final full stop. */
  margin-right: -0.48em;
  background: currentColor;
  vertical-align: baseline;
  animation: hero-status-blink 1060ms step-end infinite;
}

/* The headline's reveal crops to its own box, which would cut off the
   hanging cursor. Once revealed, let the crop extend 1em to the right
   (and a little below, for descenders) — whether the reveal ran as the
   word-by-word sequence or as the plain scanline sweep without JS. */
.hero-full-screen h1.scan-reveal {
  overflow: visible;
}

html[data-hero-sequence="typing"] .hero-full-screen [data-hero-headline],
html[data-hero-sequence="done"] .hero-full-screen [data-hero-headline] {
  clip-path: inset(0 -1em -0.2em 0);
}

@media (prefers-reduced-motion: no-preference) {
  .hero-full-screen .scan-reveal {
    animation-name: hero-headline-reveal;
  }
}

@keyframes hero-headline-reveal {
  to {
    clip-path: inset(0 -1em -0.2em 0);
  }
}

html[data-hero-sequence="pending"] .hero-cursor,
html[data-hero-sequence="active"] .hero-cursor,
html[data-hero-sequence="typing"] .hero-cursor {
  visibility: hidden;
}

.hero-full-screen .hero-status {
  text-align: center;
}

@media (min-width: 56rem) {
  .hero-full-screen .lead {
    max-width: 30rem;
  }

  .hero-full-screen {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--space-12);
    align-content: start;
  }

  .hero-full-screen > * {
    grid-column: 1 / -1;
  }

  .hero-full-screen > .lead {
    grid-column: auto;
  }
}

/* ---------------------------------------------------------------------
   Context diamond — a wireframe octahedron turning in 3D above the
   homepage headline, with a smaller one counter-rotating inside it.
   Lines are drawn by main.js. Every part is pure black: a deliberate
   exception to the field-tinted ink used elsewhere. Decorative.
   --------------------------------------------------------------------- */

.context-diamond {
  --diamond-ink: #000;
  position: relative;
  width: 100%;
  max-width: 52rem;
  margin: 0 auto var(--space-8);
}

/* The diamond takes most of the hero's top padding; keep just enough
   to clear the header. */
.hero-full-screen:has(> .context-diamond) {
  padding-top: var(--space-16);
}

.context-diamond svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.context-diamond .context-diamond-axis {
  stroke: var(--diamond-ink);
  stroke-width: 1;
  stroke-dasharray: 2 6;
  opacity: 0.35;
}

.context-diamond-outer {
  stroke: var(--diamond-ink);
  stroke-width: 1.25;
}

.context-diamond-inner {
  stroke: var(--diamond-ink);
  stroke-width: 1;
  stroke-dasharray: 4 3;
}

.context-diamond-ring {
  fill: var(--diamond-ink);
}

.context-diamond-vertex {
  fill: var(--diamond-ink);
  stroke: var(--diamond-ink);
  stroke-width: 1;
}

.context-diamond-readout {
  position: absolute;
  font-family: var(--font-dos);
  font-size: 16px;
  line-height: 1;
  color: var(--diamond-ink);
}

.context-diamond-readout {
  right: 0;
  bottom: 0;
  font-variant-numeric: tabular-nums;
}

.hero-full-screen::before,
.hero-full-screen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: radial-gradient(circle, currentColor 1px, transparent 1.5px);
  background-size: 24px 24px;
  background-position: 11px 11px;
}

.hero-full-screen::before {
  color: var(--color-text);
  opacity: 0.14;
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, #000 10%, transparent 75%);
  mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, #000 10%, transparent 75%);
}

.hero-full-screen::after {
  color: var(--color-text);
  opacity: 0;
  -webkit-mask-image: radial-gradient(circle 180px at var(--mx, 50%) var(--my, 50%), #000, transparent);
  mask-image: radial-gradient(circle 180px at var(--mx, 50%) var(--my, 50%), #000, transparent);
  transition: opacity 400ms var(--ease-standard);
}

.hero-full-screen.is-lit::after {
  opacity: 0.8;
}

/* ---------------------------------------------------------------------
   Ruled blocks — a labelled section gets a rule down its left edge
   --------------------------------------------------------------------- */

.section:not(.hero):has(> .eyebrow) {
  position: relative;
  padding-left: calc(var(--container-pad) + var(--space-4));
}

.section:not(.hero):has(> .eyebrow)::before {
  content: "";
  position: absolute;
  left: var(--container-pad);
  top: var(--space-16);
  bottom: var(--space-16);
  border-left: 1px solid var(--color-text);
  pointer-events: none;
}

.prose:not(.section):not(.hero):has(> .eyebrow) {
  padding-left: var(--space-4);
  border-left: 1px solid var(--color-text);
}

@media (max-width: 40rem) {
  .section:not(.hero):has(> .eyebrow)::before {
    top: var(--space-8);
    bottom: var(--space-8);
  }
}

/* Sections are separated by space and the rules, not by divider lines */
.seam {
  border: none;
  margin-block: var(--space-4);
}

.seam::before,
.seam::after {
  display: none;
}

/* ---------------------------------------------------------------------
   Blocks, not pills
   --------------------------------------------------------------------- */

.btn-primary,
.btn-secondary {
  border-radius: 0;
  font-weight: 500;
  font-size: 0.9375rem;
  letter-spacing: -0.005em;
  padding: 0.625rem 0.875rem;
}

.btn-primary:hover {
  background: transparent;
  color: var(--color-text);
  border-color: var(--color-text);
}

.btn-secondary {
  border-color: var(--color-text);
}

.btn-secondary:hover {
  background: var(--color-text);
  color: var(--color-bg);
  border-color: var(--color-text);
}

.card,
.context-artifact,
.demo-stat-chip {
  border-radius: 0;
}

/* ---------------------------------------------------------------------
   Header — breadcrumb path + bracketed current section
   --------------------------------------------------------------------- */

.site-header.is-scrolled {
  box-shadow: 0 1px 0 var(--color-hairline);
}

.site-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.site-path {
  font-family: var(--font-dos);
  font-size: 16px;
  line-height: 1;
  color: var(--color-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 18rem;
}


@media (max-width: 56rem) {
  .site-path {
    display: none;
  }
}

.site-nav-links a {
  position: relative;
}

/* Brackets are always present (transparent) so showing them never
   shifts the layout. */
.site-nav-links a::before,
.site-nav-links a::after {
  color: var(--color-accent);
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease-standard);
}

.site-nav-links a::before {
  content: "[";
  margin-right: 0.35em;
}

.site-nav-links a::after {
  content: "]";
  margin-left: 0.35em;
}

.site-nav-links a:hover::before,
.site-nav-links a:hover::after {
  opacity: 0.5;
}

.site-nav-links a[aria-current="page"]::before,
.site-nav-links a[aria-current="page"]::after {
  opacity: 1;
}

@media (max-width: 50rem) {
  .site-nav-links a::before,
  .site-nav-links a::after {
    display: none;
  }

  .site-nav-links a[aria-current="page"] {
    text-decoration: underline;
    text-underline-offset: 0.3em;
  }
}

/* ---------------------------------------------------------------------
   Registers — row selection feel
   --------------------------------------------------------------------- */

.case-register,
.case-row,
.impact-item {
  border-color: var(--color-hairline);
}

a.case-row:hover .case-index,
a.case-row:focus-visible .case-index {
  color: var(--color-accent);
}

.case-row:focus-visible .case-title {
  color: var(--color-link);
}

/* ---------------------------------------------------------------------
   Footer — block links + status bar
   --------------------------------------------------------------------- */

.site-footer {
  border-top: none;
}

.footer-links {
  flex-wrap: wrap;
  gap: 2px;
}

.footer-links a {
  display: inline-block;
  padding: 0.375rem 0.625rem;
  background: var(--color-text);
  color: var(--color-bg);
  font-family: var(--font-body);
  font-size: 0.875rem;
}

.footer-links a:hover {
  background: transparent;
  color: var(--color-text);
  box-shadow: inset 0 0 0 1px var(--color-text);
}

.status-bar {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2) var(--space-6);
  margin-top: var(--space-6);
  padding-top: var(--space-6);
  font-family: var(--font-dos);
  font-size: 16px;
  line-height: 1;
  color: var(--color-text);
}

/* A code page 437 double rule, clipped to the bar's width */
.status-bar::before {
  content: "════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  overflow: hidden;
  white-space: nowrap;
  color: var(--color-hairline);
}

.status-bar-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.status-bar-item.status-bar-path {
  gap: 0;
}

/* VGA text-mode cursor: a blinking underline in the last two scanlines */
.status-bar-path::after {
  content: "";
  display: inline-block;
  width: 8px;
  height: 2px;
  margin-left: 1px;
  align-self: flex-end;
  background: currentColor;
  animation: hero-status-blink 530ms step-end infinite;
}

.status-bar-clock:empty {
  display: none;
}

/* ---------------------------------------------------------------------
   Ink lines — text set on a bar of ink, one bar per line
   ---------------------------------------------------------------------
   Wrap the paragraph's text in a <span> inside .ink-lines: the inline
   background breaks with the text, and box-decoration-break: clone
   gives every line its own padded bar instead of one ragged block.
   Page-colour text on the ink stays ≥5.8:1 on every field. */

.ink-lines {
  line-height: 1.5;
}

.ink-lines > span {
  background: var(--color-text);
  color: var(--color-bg);
  padding: 0.12em 0.3em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* ---------------------------------------------------------------------
   Text mode — IBM VGA 8x16 in the places the site speaks as a machine
   --------------------------------------------------------------------- */

/* Homepage "thinking" line, with the VGA underline cursor */
.hero-status {
  font-family: var(--font-dos);
  font-size: 16px;
  line-height: 1;
  color: var(--color-text);
}

.hero-status::after {
  width: 8px;
  height: 2px;
  margin-left: 1px;
  border-right: none;
  background: currentColor;
  vertical-align: baseline;
  animation-duration: 530ms;
}

/* Register numbers: 01, 02, 03 */
.case-index {
  font-family: var(--font-dos);
  font-size: 16px;
  line-height: 1;
  padding-top: 0.35rem;
}

/* ---------------------------------------------------------------------
   Audit spec — the homepage Context Audit as raw DOS shell output
   ---------------------------------------------------------------------
   templates/components/audit-spec.html. A plain ink box of shell
   output: one font (IBM VGA, as in the footer prompt and Machine view),
   one size (16px), tight rows, reading as if
   `type context-audit.spec` had just been run.

   Drawn entirely in the site's own two colours so it belongs to the
   page it sits on: the box is solid page ink (like the buttons,
   footer links and .ink-lines), type is the page field colour, and inverse blocks (field behind ink) mark only the key
   facts — the three figures and the price. Flat, no border or shadow,
   like every other surface on the site. Field-on-ink is ≥5.8:1 on
   every page colour. */

.audit-spec {
  --shell-ink: var(--color-text);
  --shell-type: var(--color-bg);
  margin-block: var(--space-16) var(--space-4);
  background: var(--shell-ink);
  color: var(--shell-type);
  font-family: var(--font-dos);
  font-size: 16px;
  font-weight: 400;
  line-height: 18px;
  letter-spacing: 0;
  -webkit-font-smoothing: none;
  font-smooth: never;
}

/* Everything inside inherits the one size and weight */
.audit-spec * {
  font: inherit;
  letter-spacing: inherit;
  text-transform: none;
  color: inherit;
  margin: 0;
}

/* Body: blank lines between blocks are one row (18px) tall */
.shell-body {
  padding: 18px 16px;
  display: grid;
  gap: 18px;
}

@media (min-width: 48rem) {
  .shell-body {
    padding: 24px 24px;
  }
}

.shell-prompt {
  white-space: nowrap;
  overflow: hidden;
}

.shell-cursor {
  display: inline-block;
  width: 8px;
  height: 16px;
  vertical-align: -3px;
  background: var(--shell-type);
}

/* Steps: label + figure on one row, detail indented beneath */
.audit-spec-steps {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 18px;
}

.audit-spec-step {
  display: grid;
  grid-template-columns: 1fr;
  padding-left: 0;
}

/* Inverse blocks mark the key facts */
.audit-spec-figure,
.audit-spec-price-stat {
  background: var(--shell-type);
  color: var(--shell-ink);
  padding: 0 8px;
}

.audit-spec-figure {
  justify-self: start;
}

.audit-spec-title,
.audit-spec-desc {
  padding-left: 2ch;
}

@media (min-width: 40rem) {
  .audit-spec-step {
    grid-template-columns: 16ch 1fr;
  }

  .audit-spec-label {
    grid-column: 1;
  }

  .audit-spec-figure,
  .audit-spec-title,
  .audit-spec-desc {
    grid-column: 2;
  }

  .audit-spec-title,
  .audit-spec-desc {
    padding-left: 8px;
  }

  .audit-spec-desc {
    max-width: 64ch;
  }
}

.audit-spec-price-note {
  padding: 0 8px;
}

/* ---------------------------------------------------------------------
   Machine shell — the Machine view as a live DOS shell
   ---------------------------------------------------------------------
   templates/components/machine-shell.html. Same box as the audit spec:
   page ink behind page-field type, so it belongs to whatever colour the
   page is. */

.machine-view.machine-shell {
  max-width: var(--prose-width);
  font-family: var(--font-dos);
  font-size: 16px;
  --shell-ink: var(--color-text);
  --shell-type: var(--color-bg);
  background: var(--shell-ink);
  color: var(--shell-type);
  padding: 0;
  line-height: 18px;
  -webkit-font-smoothing: none;
  font-smooth: never;
}

.machine-shell * {
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  margin: 0;
}

/* Long commands wrap rather than clip at phone width */
.machine-shell .shell-prompt {
  white-space: normal;
  overflow-wrap: anywhere;
}

.machine-shell .shell-output {
  max-width: none;
  margin: 0;
  padding: 0;
  color: inherit;
  background: none;
  border: none;
  white-space: pre-wrap;
  word-break: break-word;
  overflow: visible;
}

/* Typing replay (main.js dosTypewriter): while .is-typing, characters are
   present but transparent until printed (.tc.on), inverse bars stay dark
   until their first character prints, and the cursor is the cell after
   the last printed character. Without JS none of these classes exist and
   the box simply shows its finished text. */
.is-typing .tb .tc {
  color: transparent;
}

.is-typing .tb .tc.on {
  color: inherit;
}

.audit-spec.is-typing .tb:not(.on) {
  background: transparent;
}

.is-typing .shell-cursor {
  visibility: hidden;
}

.audit-spec .tc.is-cursor,
.machine-shell .tc.is-cursor {
  background: var(--shell-type);
}

.audit-spec-figure .tc.is-cursor,
.audit-spec-price-stat .tc.is-cursor {
  background: var(--shell-ink);
}
