/* ════════════════════════════════════════════════════════════════════════
   css/util.css — the three utility pages: /404, /privacy, /thank-you.
   service.tnaado.ca · links css/chrome.css, overrides nothing in it.

   ONE SHEET FOR THREE PAGES because they share a ground, a rail, a type scale
   and a hero band, and three copies of those is how the old site's twenty pages
   drifted apart. It is small on purpose: these pages carry no storm, no
   carousel and no script of their own.

   NO JAVASCRIPT IS REQUIRED BY ANYTHING IN HERE. That matters most on /404,
   where the visitor has already had one thing fail. Every rule paints from the
   served HTML: no reveal-on-scroll, no opacity:0 waiting for an observer, no
   class a script has to add. js/chrome.js is still loaded — it upgrades the nav
   into sheets — but with it blocked the page is a bar, a hero, its content, a
   full navigation tree and a full directory, in reading order.

   COLOUR, LOCKED AND MEASURED. --red #c8102e is 3.37:1 on ink and is used ONLY
   for rules, fills and display type >= 24px. Every small red text run on ink is
   --red-ink #ef5c6e (6.06:1); on bone it is --red-bone #a4132c (6.6:1). The old
   /404 used #a4132c — the BONE red — as its hover colour on an INK ground,
   which measures 2.55:1 and fails; that is the specific mistake this sheet does
   not reproduce. Body copy is --bone (17.4:1 on ink), secondary copy is
   --dim-ink #b9b3a6 (9.4:1). There is no rgba(bone, .4x) anywhere.

   THE HERO SCRIM IS DELIBERATELY HEAVY. Text sits in the lower half of the
   band, where the gradient reaches .97 — at that alpha the composite is
   effectively #0a0a0a whatever the photograph underneath is doing, so the
   contrast of the headline does not depend on which frame is used. The top of
   the band stays at .70 so it still reads as a photograph.
   ════════════════════════════════════════════════════════════════════════ */

:root {
  /* The brand, locked. css/chrome.css resolves its own locals from these, so
     defining them here is what makes the shared chrome paint correctly. */
  --ink:       #0a0a0a;
  --plate:     #0d0d0d;
  --plate-2:   #121212;
  --bone:      #f5f1e8;
  --bone-2:    #ebe5d8;
  --red:       #c8102e;   /* rules, fills, display >= 24px. NEVER small text. */
  --red-ink:   #ef5c6e;   /* 6.06:1 on ink  — the only small red on ink  */
  --red-bone:  #a4132c;   /* 6.6:1  on bone — the only small red on bone */
  --dim-ink:   #b9b3a6;   /* 9.4:1  on ink */
  --hair-ink:  rgba(245, 241, 232, .14);

  --serif: 'Fraunces', 'Times New Roman', Times, serif;
  --sans:  'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --mono:  'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --rail: 1136px;   /* the shared rail, so the column does not jump between
                       these pages and /work */
  --gut:  clamp(1.25rem, 4vw, 3rem);
  --ease: cubic-bezier(.22, 1, .36, 1);
}

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

html {
  overflow-x: clip;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.6;
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
}

.u-rail { width: 100%; max-width: var(--rail); margin: 0 auto; padding: 0 var(--gut); }

.u-vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

a { color: var(--bone); }

/* ══ THE HERO BAND ══════════════════════════════════════════════════════════
   A photograph, a scrim, a kicker, a headline and a lede. The image is a real
   <img> rather than a background so it can carry width/height, a srcset and
   fetchpriority — the old /404's hero had none of those and shifted layout on
   load. Grid rather than absolute positioning: one cell, both children stacked
   in it, so the band's height is the image's aspect and nothing is measured in
   script. */
.u-hero {
  position: relative;
  display: grid;
  isolation: isolate;
  background: var(--ink);
  border-bottom: 1px solid var(--hair-ink);
}
.u-hero__img {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  min-height: 34vh;
  max-height: 48vh;
  object-fit: cover;
  object-position: 50% 42%;
  display: block;
}
.u-hero__scrim {
  grid-area: 1 / 1;
  background: linear-gradient(180deg,
    rgba(10, 10, 10, .70) 0%,
    rgba(10, 10, 10, .86) 42%,
    rgba(10, 10, 10, .97) 78%,
    rgba(10, 10, 10, 1) 100%);
}
.u-hero__body {
  grid-area: 1 / 1;
  z-index: 1;
  align-self: end;
  padding-block: clamp(1.9rem, 4.2vw, 3.25rem);
}

/* The kicker. A 22px red rule, then mono caps — the site's own lead-in device.
   The rule is a FILL, which is the only thing --red is allowed to be at this
   size; the words beside it are bone, not red. */
.u-kicker {
  display: flex; align-items: center; gap: .7rem;
  margin: 0 0 1rem;
  font-family: var(--mono);
  font-size: .625rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--bone);
}
.u-kicker::before {
  content: ""; flex: 0 0 auto;
  width: 22px; height: 1px; background: var(--red);
}

.u-h1 {
  margin: 0;
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(2.25rem, 5.2vw, 3.5rem);
  line-height: 1.02;
  letter-spacing: -.015em;
}
/* Display type at this size clears the 3:1 large-text bar at 3.37:1, so the
   locked --red is allowed here and only here. */
.u-h1 em { font-style: italic; color: var(--red); }

.u-lede {
  margin: 1.1rem 0 0;
  max-width: 62ch;
  font-size: clamp(1rem, 1.6vw, 1.125rem);
  line-height: 1.62;
  color: var(--bone);
}
.u-lede a { color: var(--red-ink); text-decoration: underline; text-underline-offset: .18em; }
.u-lede strong { font-weight: 600; }

/* A hero with NO photograph, for /privacy and /thank-you. Neither page needs
   one: a legal reference document needs a table of contents, and a thank-you
   page needs to be short. The 404 keeps its frame because that is the one page
   where the visitor is being reassured rather than informed — and it means one
   image serves all three, so the other two make no image request at all. */
.u-hero--flat { display: block; background: var(--ink); }
.u-hero--flat .u-hero__body {
  padding-block: clamp(2rem, 4.2vw, 3.25rem) clamp(1.6rem, 3.2vw, 2.5rem);
}

/* ══ SECTIONS ═════════════════════════════════════════════════════════════ */
.u-sec { padding-block: clamp(2.25rem, 4.6vw, 4rem); }
.u-sec--plate { background: var(--plate); border-block: 1px solid var(--hair-ink); }

.u-h2 {
  margin: 0 0 1.6rem;
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(1.625rem, 3.1vw, 2.125rem);
  line-height: 1.12;
}
.u-h2 em { font-style: italic; color: var(--red); }

/* ══ /404 · THE SIX DESTINATIONS ═══════════════════════════════════════════
   Two buttons are not a recovery route. Someone who mistyped a URL or followed
   a dead link wants the page they were actually after, and the only thing
   offering it otherwise is the footer's whole directory, which is a haystack.
   Six named destinations: the four doors, plus the portfolio fork and contact.
   Hairlines between cells rather than boxes, so the group reads as an index. */
.u-routes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
            gap: 0 clamp(1.4rem, 3.4vw, 3rem); margin: 0; padding: 0; list-style: none; }
.u-routes > li { border-top: 1px solid var(--hair-ink); }
.u-routes > li:nth-child(-n+3) { border-top: 0; }
.u-routes a {
  display: block; padding: .95rem 0; text-decoration: none;
  transition: color .18s var(--ease);
}
.u-routes__t {
  display: block;
  font-family: var(--serif);
  font-size: 1.15rem;
  line-height: 1.25;
  color: var(--bone);
}
.u-routes__p {
  display: block; margin-top: .3rem;
  font-size: .875rem; line-height: 1.5;
  color: var(--dim-ink);
}
.u-routes a:hover .u-routes__t,
.u-routes a:focus-visible .u-routes__t { color: var(--red-ink); }
.u-routes a:focus-visible { outline: 2px solid var(--red-ink); outline-offset: 3px; }

@media (max-width: 860px) {
  .u-routes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .u-routes > li:nth-child(-n+3) { border-top: 1px solid var(--hair-ink); }
  .u-routes > li:nth-child(-n+2) { border-top: 0; }
}
@media (max-width: 520px) {
  .u-routes { grid-template-columns: 1fr; }
  .u-routes > li:nth-child(-n+2) { border-top: 1px solid var(--hair-ink); }
  .u-routes > li:first-child { border-top: 0; }
}

/* ══ /thank-you · WHAT HAPPENS NEXT ════════════════════════════════════════
   Three steps in a row, then one route onward. Numbered in mono so the order
   is unmissable — the whole job of this page is answering "and now what". */
.u-steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
           gap: clamp(1.4rem, 3vw, 2.6rem); margin: 0; padding: 0; list-style: none; }
.u-steps > li { padding-top: 1rem; border-top: 1px solid var(--red); }
.u-steps__n {
  margin: 0 0 .5rem;
  font-family: var(--mono); font-size: .6875rem; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--red-ink);
}
.u-steps__p { margin: 0; font-size: .9375rem; line-height: 1.6; color: var(--bone); }
@media (max-width: 720px) { .u-steps { grid-template-columns: 1fr; } }

/* One route onward, and only one. A thank-you page offering five things to do
   next is a thank-you page that does not know what it wants. */
.u-onward {
  display: inline-flex; align-items: center; gap: .6rem;
  margin-top: clamp(1.8rem, 4vw, 2.6rem);
  padding: .85rem 1.5rem;
  background: var(--red); color: var(--bone);
  font-family: var(--sans); font-size: .9375rem; font-weight: 500;
  letter-spacing: .01em; text-decoration: none;
  transition: background .18s var(--ease);
}
.u-onward:hover { background: #a30d25; }
.u-onward:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }

.u-aside { margin: 1.6rem 0 0; font-size: .875rem; line-height: 1.6; color: var(--dim-ink); }
.u-aside a { color: var(--red-ink); text-decoration: underline; text-underline-offset: .18em; }

/* ══ /privacy · THE PROSE ══════════════════════════════════════════════════
   A privacy policy is used to find ONE clause. So: a plain anchor list at the
   top, nothing hidden behind a click, no accordion, no script. Measured column
   width — 72ch is the outer edge of comfortable for legal copy. */
/* MEASURED, NOT ASSUMED. This was `74ch`, which reads as "74 characters" and is
   not. The `ch` unit is the advance width of the ZERO GLYPH, and in IBM Plex
   Sans the zero is markedly wider than average lowercase prose -- so at this
   page's 15px body size, 74ch computed to 710.4px and carried 104 to 111 real
   characters per line, measured on ten paragraphs of /privacy by dividing the
   rendered width by the canvas-measured average glyph width of the actual text.
   That is the worst line length on the site; comfortable reading is 45-75.
   34rem still measured 75-85 (avg 81), so 31rem: re-measured at 68-77, avg 73. Given in rem rather
   than a corrected ch figure so the next reader is not misled the same way. */
.u-prose { max-width: 31rem; }

.u-toc { margin: 0 0 clamp(2.2rem, 5vw, 3.2rem); padding: 1.4rem 0 0; border-top: 1px solid var(--red); }
.u-toc__k {
  margin: 0 0 .9rem;
  font-family: var(--mono); font-size: .625rem; font-weight: 500;
  letter-spacing: .2em; text-transform: uppercase; color: var(--dim-ink);
}
/* Column-major, not row-major. A reader scans a two-column index DOWN the
   first column, so the flow is set so the left column is S.01-S.07 and the
   right is S.08-S.14; the default row flow would have put 01 and 02 side by
   side and made the left column read 01, 03, 05. Seven rows is half of the
   fourteen sections and is updated with them. */
.u-toc__list { margin: 0; padding: 0; list-style: none;
               display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
               grid-template-rows: repeat(7, auto); grid-auto-flow: column;
               gap: .1rem 1.6rem; }
/* .u-prose is on the wrapper, so a bare `.u-toc__list a` ties on specificity
   with `.u-prose a` below and LOSES on order — measured: every entry in the
   contents list came out underlined. Scoped to beat it rather than reordered,
   because ordering is not a contract. */
.u-prose .u-toc__list a {
  display: flex; gap: .7rem; padding: .38rem 0;
  font-size: .9375rem; color: var(--bone); text-decoration: none;
}
.u-prose .u-toc__list a:hover { color: var(--red-ink); text-decoration: underline; }
.u-prose .u-toc__list a:focus-visible { outline: 2px solid var(--red-ink); outline-offset: 2px; }
.u-toc__n { flex: 0 0 auto; font-family: var(--mono); font-size: .75rem; color: var(--red-ink); }
@media (max-width: 560px) {
  .u-toc__list { grid-template-columns: 1fr; grid-template-rows: none; grid-auto-flow: row; }
}

.u-h3 {
  display: flex; align-items: baseline; gap: .6rem;
  margin: clamp(2rem, 4vw, 2.8rem) 0 .7rem;
  font-family: var(--sans); font-weight: 600;
  font-size: .8125rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--bone);
  scroll-margin-top: 7rem;   /* clears the fixed bar when the ToC jumps */
}
.u-h3__n { font-family: var(--mono); font-size: .75rem; font-weight: 500; color: var(--red-ink); }

.u-prose p { margin: 0 0 1rem; font-size: .9375rem; line-height: 1.72; color: var(--bone); }
.u-prose p:last-child { margin-bottom: 0; }
.u-prose strong { font-weight: 600; }
.u-prose a { color: var(--red-ink); text-decoration: underline; text-underline-offset: .18em; }
.u-prose code {
  font-family: var(--mono); font-size: .8125rem;
  padding: .08em .35em; background: var(--plate-2); color: var(--bone-2);
}
.u-prose ul { margin: 0 0 1rem; padding-left: 1.15rem; }
.u-prose li { margin-bottom: .5rem; font-size: .9375rem; line-height: 1.68; color: var(--bone); }
.u-stamp {
  margin: clamp(2.2rem, 5vw, 3rem) 0 0; padding-top: 1.1rem;
  border-top: 1px solid var(--hair-ink);
  font-family: var(--mono); font-size: .75rem; letter-spacing: .04em;
  color: var(--dim-ink);
}

@media (prefers-reduced-motion: reduce) {
  .u-routes a, .u-onward { transition: none !important; }
}
