/* ===========================================================================
   Deflock — Scene
   ---------------------------------------------------------------------------
   One stylesheet, no build step. It carries, in order:

     1. the four self-hosted faces
     2. the design tokens
     3. the base layer
     4. the page furniture: header, footer, grain
     5. the structures: scenes, heroes, sections, shells, splits
     6. the type scale
     7. links, buttons and form fields
     8. the lists: rows, steps, definitions
     9. panels and asides
    10. motion, and what replaces it when a reader asks for less
    11. the page-specific treatments, which exist because the
        Content-Security-Policy forbids a style attribute

   A value appears once. Anything that could be reused is a token in :root.
   =========================================================================== */

/* --- 1. faces ---------------------------------------------------------------
   Self-hosted, because the footer promises the site loads nothing from a third
   party. IBM Plex Sans and Geist Mono are variable, so one file each covers
   every weight and the rule declares the axis rather than a single number. */

@font-face {
  font-family: "DM Serif Display";
  src: url("/assets/fonts/dm-serif-display-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Instrument Serif";
  src: url("/assets/fonts/instrument-serif-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("/assets/fonts/ibm-plex-sans-var.woff2") format("woff2");
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/geist-mono-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* --- 2. tokens ------------------------------------------------------------- */

:root {

  /* Surface. The page is black. Nothing is a lighter grey; depth comes from
     hairlines and from the photograph underneath. */
  --bg:            #000000;
  --bg-blank:      #05070a;   /* a scene still waiting for its photograph */
  --bg-raised:     rgba(255, 255, 255, 0.03);
  --bg-header:     rgba(0, 0, 0, 0.75);

  /* Ink. One colour, eight opacities, and no second text colour. */
  --ink:           #ffffff;
  --ink-90:        rgba(255, 255, 255, 0.90);
  --ink-85:        rgba(255, 255, 255, 0.85);
  --ink-80:        rgba(255, 255, 255, 0.80);
  --ink-75:        rgba(255, 255, 255, 0.75);
  --ink-70:        rgba(255, 255, 255, 0.70);
  --ink-65:        rgba(255, 255, 255, 0.65);
  --ink-60:        rgba(255, 255, 255, 0.60);
  --ink-55:        rgba(255, 255, 255, 0.55);
  --ink-50:        rgba(255, 255, 255, 0.50);

  /* Hairlines. Four weights for four jobs. */
  --line-faint:    rgba(255, 255, 255, 0.05);
  --line:          rgba(255, 255, 255, 0.10);
  --line-mid:      rgba(255, 255, 255, 0.12);
  --line-strong:   rgba(255, 255, 255, 0.15);
  --line-accent:   rgba(0, 184, 212, 0.30);

  /* Accent. The soft value carries links, because it has to stay readable on
     black across a paragraph. The bright value marks the one phrase per page
     that the page is about. */
  --accent:        #00B8D4;
  --accent-bright: #22D3EE;
  --accent-soft:   rgba(0, 184, 212, 0.80);

  /* State, used by the contact form notices. */
  --state-ok:      #0E8A5F;
  --state-risk:    #DC3D43;

  /* Faces. Four, four jobs, no overlap. */
  --face-display:  "DM Serif Display", Georgia, "Times New Roman", serif;
  --face-word:     "Instrument Serif", Georgia, serif;
  --face-text:     "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --face-mono:     "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Display sizes. Fluid, one weight, tracked tight. Line height falls as size
     rises: a 112px heading at 1.05 reads loose; the same heading at 0.92 reads
     as one block. */
  --display-1:     clamp(2.75rem, 7vw, 7rem);
  --display-3:     clamp(2.5rem, 5vw, 5rem);
  --display-scene: clamp(2.25rem, 4.6vw, 3.75rem);
  --head-section:  clamp(2rem, 4vw, 3.5rem);
  --head-block:    1.875rem;

  --lh-tightest:   0.92;
  --lh-tighter:    0.95;
  --lh-tight:      1.05;
  --track-display: -0.025em;

  /* Text sizes. */
  --t-lede:        1.125rem;
  --t-lede-lg:     1.25rem;
  --t-body:        1rem;
  --t-small:       0.875rem;
  --t-fine:        0.75rem;
  --t-mono:        0.6875rem;
  --t-script:      0.8125rem;
  --lh-prose:      1.625;
  --lh-body:       1.5;
  --lh-script:     1.75;

  --track-eyebrow: 0.14em;
  --track-mono:    0.08em;
  --track-accent:  0.20em;
  --track-script:  0.02em;

  /* Layout. Three widths, one gutter, one reading measure. */
  --shell-narrow:  64rem;
  --shell:         72rem;
  --shell-wide:    80rem;
  --gutter:        1.5rem;
  --measure:       42rem;
  --measure-tight: 36rem;

  /* Rhythm. */
  --bay:           6rem;
  --bay-tight:     5rem;
  --bay-close:     8rem;
  --hero-top:      clamp(9rem, 11vw, 11rem);
  --hero-bottom:   4rem;
  --scene-pad:     4rem;

  /* Shape. Almost nothing is rounded. */
  --radius-btn:    0.375rem;   /* deviates from stock Scene, which is a full pill */
  --radius-panel:  1rem;
  --radius-field:  0.5rem;

  /* Motion. */
  --ease-reveal:   cubic-bezier(0.165, 0.84, 0.44, 1);
  --hover-dur:     300ms;
  --reveal-rise:   0.55em;

  /* Media. */
  --media-opacity: 0.55;
  --media-opacity-hero: 0.65;
  --grain-opacity: 0.06;
  --grain-tile:    200px;

  /* The fixed header's height, used by anything that has to clear it. */
  --header-h:      5rem;

  color-scheme: dark;
}

/* --- 3. base --------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-h);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--face-text);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

img, video, svg { display: block; max-width: 100%; }

h1, h2, h3, p, ul, ol, dl, figure, pre { margin: 0; }

ul, ol { padding: 0; list-style: none; }

a { color: var(--accent-soft); text-decoration: none; transition: color var(--hover-dur); }
a:hover { color: var(--accent); }

::selection { background: var(--accent); color: #000; }

:focus-visible { outline: 2px solid var(--ink-70); outline-offset: 4px; }

/* The first thing in the tab order, hidden until it is focused. */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 60;
  background: var(--ink);
  color: #000;
  padding: 0.75rem 1.25rem;
  font-size: var(--t-small);
}
.skip:focus {
  left: 1rem;
  top: 1rem;
  color: #000;
}

/* --- 4. furniture ---------------------------------------------------------- */

/* One fixed film over the whole page, so every screen shares the same grain.
   Without it the black reads as screen black and the photographs look pasted
   on. The tile is generated, so no image file ships for it. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 10;
  pointer-events: none;
  opacity: var(--grain-opacity);
  mix-blend-mode: overlay;
  background-repeat: repeat;
  background-size: var(--grain-tile) var(--grain-tile);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='128' height='128'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='128' height='128' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}

/* Transparent over the first screen, solid once the page has moved. The change
   is the only thing that tells a reader they have left the top. */
.site-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 50;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background var(--hover-dur), border-color var(--hover-dur), backdrop-filter var(--hover-dur);
}
.site-header[data-scrolled="true"] {
  background: var(--bg-header);
  border-bottom-color: var(--line);
  backdrop-filter: blur(12px);
}
.site-header__bar {
  max-width: var(--shell-wide);
  margin-inline: auto;
  padding: 1rem var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

/* The site name, set in the one face that sets nothing else. */
.wordmark {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  font-family: var(--face-word);
  font-size: 1.5rem;
  letter-spacing: var(--track-display);
  color: var(--ink-90);
}
.wordmark:hover { color: var(--ink); }

.site-nav { display: flex; align-items: center; gap: 1.5rem; font-size: var(--t-small); }
.site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  color: var(--ink-60);
}
.site-nav a:hover,
.site-nav a[aria-current="page"] { color: var(--ink); }

/* The hidden attribute hides an element through a rule in the browser's own
   stylesheet, which any author rule setting display outranks. The menu and its
   button both set display, so without these two selectors the script can set
   hidden all it likes and nothing moves. */
.site-nav[hidden],
.nav-toggle[hidden] { display: none; }

/* The menu button appears only where the row of links will not fit. The markup
   ships with the nav open, so the menu still works with scripting off. */
.nav-toggle {
  display: none;
  min-height: 48px;
  padding: 0 0.25rem;
  border: 0;
  background: none;
  color: var(--ink-60);
  font-family: var(--face-mono);
  font-size: var(--t-fine);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--hover-dur);
}
.nav-toggle:hover { color: var(--ink); }

@media (max-width: 48rem) {
  .nav-toggle { display: inline-flex; align-items: center; }
  .site-nav {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding: 0.5rem var(--gutter) 1.25rem;
    background: var(--bg-header);
    border-bottom: 1px solid var(--line);
    backdrop-filter: blur(12px);
  }
  .site-nav a { width: 100%; font-size: var(--t-body); }
  .site-header__bar { position: relative; }
}

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

.site-footer {
  position: relative;
  z-index: 10;
  border-top: 1px solid var(--line);
  background: var(--bg);
  padding: var(--bay) var(--gutter) 3rem;
}
.site-footer__cols {
  max-width: var(--shell-wide);
  margin-inline: auto;
  display: grid;
  gap: 3rem 2.5rem;
}
@media (min-width: 40rem) { .site-footer__cols { grid-template-columns: 1fr 1fr; } }
@media (min-width: 64rem) { .site-footer__cols { grid-template-columns: 1.6fr 1.1fr 1fr 1fr; } }

.site-footer .wordmark { min-height: 0; font-size: 1.125rem; color: var(--ink); }
.site-footer .statement {
  margin-top: 1.25rem;
  max-width: 28rem;
  font-family: var(--face-display);
  font-size: 1.5rem;
  line-height: 1.15;
  letter-spacing: var(--track-display);
  color: var(--ink);
}
.site-footer h2 {
  margin-bottom: 1rem;
  font-family: var(--face-text);
  font-size: var(--t-fine);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--track-mono);
  color: var(--ink-50);
}
.site-footer ul { display: grid; gap: 0.5rem; font-size: var(--t-small); }
.site-footer li a { color: var(--ink-70); }
.site-footer li a:hover { color: var(--ink); }
.site-footer__base {
  max-width: var(--shell-wide);
  margin: 5rem auto 0;
  border-top: 1px solid var(--line);
  padding-top: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
  font-size: var(--t-small);
  color: var(--ink-50);
}

/* --- 5. structures --------------------------------------------------------- */

.shell         { width: 100%; max-width: var(--shell);        margin-inline: auto; padding-inline: var(--gutter); }
.shell--narrow { max-width: var(--shell-narrow); }
.shell--wide   { max-width: var(--shell-wide); }

.section        { border-top: 1px solid var(--line); padding-block: var(--bay); }
.section--tight { padding-block: var(--bay-tight); }
.section--close { padding-block: var(--bay-close); }

/* A section that fills the screen and carries its own photograph. The home page
   is built from these; no other page uses them, because a page of full screens
   is a page nobody finishes. */
.scene {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 100svh;
  overflow: hidden;
  border-bottom: 1px solid var(--line-faint);
  padding-block: var(--scene-pad);
}
/* A scene whose content is short enough that a full screen would be mostly
   empty. It takes the room it needs and stops. */
.scene--snug { min-height: 0; }

.scene__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: var(--media-opacity);
}
/* Top and bottom are darkened hardest, so the heading and the section edge sit
   on something close to black while the middle keeps its detail. */
.scene__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(0,0,0,0.45), rgba(0,0,0,0.15), rgba(0,0,0,0.85));
}
.scene__inner { position: relative; z-index: 20; }

/* The top of a page that is not the home page. Same treatment as a scene, but
   it ends where the reading starts. */
.hero {
  position: relative;
  overflow: hidden;
  padding: var(--hero-top) var(--gutter) var(--hero-bottom);
}
.hero__media { position: absolute; inset: 0; pointer-events: none; }
.hero__media > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: var(--media-opacity-hero);
}
.hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,0.60), rgba(0,0,0,0.35), #000);
}
.hero__inner { position: relative; }

/* Column splits. Every one collapses to a single column below 64rem. */
.split { display: grid; gap: 3rem; }
@media (min-width: 64rem) {
  .split              { grid-template-columns: 1fr 1fr; }
  .split--wide-right  { grid-template-columns: 1fr 1.6fr; gap: 4rem; }
  .split--label       { grid-template-columns: 260px 1fr; gap: 3rem; }
  .split--form        { grid-template-columns: 1.3fr 1fr; gap: 4rem; }
}

/* --- 6. type --------------------------------------------------------------- */

.display-1, .display-3, .h-scene, .h-section, .h-block {
  font-family: var(--face-display);
  font-weight: 400;
  letter-spacing: var(--track-display);
  text-wrap: balance;
}
.display-1 { font-size: var(--display-1);     line-height: var(--lh-tightest); }
.display-3 { font-size: var(--display-3);     line-height: var(--lh-tighter); }
.h-scene   { font-size: var(--display-scene); line-height: var(--lh-tight); }
.h-section { font-size: var(--head-section);  line-height: var(--lh-tight); max-width: 48rem; }
.h-block   { font-size: var(--head-block);    line-height: 1.2; }

/* The one phrase a page is about. Once per page. */
.accent { color: var(--accent-bright); }

.lede {
  margin-top: 2rem;
  max-width: var(--measure);
  font-size: var(--t-lede);
  line-height: var(--lh-prose);
  color: var(--ink-75);
  text-wrap: pretty;
}
.lede--lg    { font-size: var(--t-lede-lg); }
.lede--tight { margin-top: 1.5rem; font-size: var(--t-body); }

.prose { max-width: var(--measure); color: var(--ink-80); font-size: var(--t-lede); line-height: var(--lh-prose); }
.prose p { margin-bottom: 1.5rem; text-wrap: pretty; }
.prose p:last-child { margin-bottom: 0; }

.note { color: var(--ink-65); font-size: var(--t-small); line-height: var(--lh-prose); max-width: var(--measure-tight); text-wrap: pretty; }
.fine      { color: var(--ink-50); font-size: var(--t-fine); line-height: var(--lh-prose); }
.fine--wide{ max-width: 48rem; }

/* One line in the display face, where the page needs to slow down. */
.quote {
  font-family: var(--face-display);
  font-size: 1.5rem;
  line-height: 1.375;
  letter-spacing: var(--track-display);
  color: var(--ink-85);
  max-width: 48rem;
  text-wrap: balance;
}
@media (min-width: 40rem) { .quote { font-size: 1.875rem; } }

/* Sits above a heading and names the section. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin-bottom: 1.25rem;
  font-size: var(--t-fine);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--track-eyebrow);
  color: var(--ink-60);
}
.eyebrow .dot {
  display: block;
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 12px var(--accent);
}

/* Mono, for anything that is data rather than language. */
.label-mono {
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: var(--track-mono);
  text-transform: lowercase;
  color: var(--ink-70);
}
/* --- 7. links, buttons, fields --------------------------------------------- */

/* The standard onward link: underlined, with an arrow that steps away on
   hover. */
.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 45px;
  color: var(--ink-80);
  font-size: var(--t-body);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.arrow-link:hover { color: var(--ink); }
.arrow-link svg { width: 1rem; height: 1rem; transition: transform var(--hover-dur); }
.arrow-link:hover svg { transform: translate(2px, -2px); }

.plain-link { color: var(--accent-soft); text-decoration: underline; text-underline-offset: 4px; }
.plain-link:hover { color: var(--accent); }

/* Small, spaced, cyan. For a link to a directory or a document rather than to
   another page of this site. */
.accent-link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 44px;
  font-size: var(--t-fine);
  text-transform: uppercase;
  letter-spacing: var(--track-accent);
  color: var(--accent-soft);
}
.accent-link:hover { color: var(--accent); }
.accent-link svg { width: 0.875rem; height: 0.875rem; transition: transform var(--hover-dur); }
.accent-link:hover svg { transform: translate(2px, -2px); }

/* Two buttons, and no third. White is the thing to do; outlined is the other
   thing. The corner is square-ish rather than a full pill, which is where this
   site departs from stock Scene. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border: 0;
  border-radius: var(--radius-btn);
  padding: 0.75rem 1.5rem;
  font-family: inherit;
  font-size: var(--t-small);
  background: var(--ink);
  color: #000;
  cursor: pointer;
  transition: background var(--hover-dur);
}
.pill:hover { background: var(--ink-90); color: #000; }
.pill--ghost {
  background: transparent;
  color: var(--ink);
  border: 1px solid rgba(255, 255, 255, 0.30);
  transition: border-color var(--hover-dur);
}
.pill--ghost:hover { background: transparent; border-color: var(--ink); color: var(--ink); }
.pill:disabled { opacity: 0.6; cursor: not-allowed; }
.pill-row { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 2.25rem; }

/* Fields. A hairline box on a five per cent white fill. */
.field { display: block; margin-bottom: 1.5rem; }
.field > label { display: block; margin-bottom: 0.75rem; font-size: var(--t-small); font-weight: 500; }
.field .hint {
  display: block;
  margin-top: 0.25rem;
  font-size: var(--t-fine);
  font-weight: 400;
  color: var(--ink-50);
}
.field .req { color: var(--accent-soft); }
.field input, .field textarea, .field select {
  display: block;
  width: 100%;
  appearance: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-field);
  background: rgba(255, 255, 255, 0.05);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--t-body);
  line-height: 1.5;
  padding: 0.625rem 0.75rem;
  transition: border-color var(--hover-dur);
}
.field select {
  /* The arrow is drawn here because a select cannot carry a pseudo-element. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-opacity='0.5' stroke-width='1.5'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 1.125rem;
  padding-right: 2.5rem;
}
.field option { background: #111; color: var(--ink); }
.field input:hover, .field textarea:hover, .field select:hover { border-color: rgba(255, 255, 255, 0.20); }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: 2px solid var(--accent);
  outline-offset: 0;
  border-color: transparent;
}
.field textarea { min-height: 9rem; resize: vertical; }
.field--bad input, .field--bad textarea, .field--bad select { border-color: var(--state-risk); }
.field__error { display: block; margin-top: 0.5rem; font-size: var(--t-small); color: var(--state-risk); }

.field-pair { display: grid; gap: 1.5rem; }
@media (min-width: 40rem) { .field-pair { grid-template-columns: 1fr 1fr; } }

/* The honeypot. It is in the markup for a robot and out of the way of a person
   and a screen reader both. */
.trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* What the form says back. No box: a coloured rule and a heading is enough. */
.notice {
  max-width: var(--measure);
  border-left: 2px solid var(--line-strong);
  padding-left: 1.25rem;
  margin-bottom: 3rem;
}
.notice h2 {
  font-family: var(--face-display);
  font-weight: 400;
  font-size: 1.5rem;
  letter-spacing: var(--track-display);
  margin-bottom: 0.5rem;
}
.notice p { color: var(--ink-70); line-height: var(--lh-prose); }
.notice--good { border-left-color: var(--state-ok); }
.notice--good h2 { color: var(--state-ok); }
.notice--bad  { border-left-color: var(--state-risk); }
.notice--bad h2 { color: var(--state-risk); }

/* --- 8. lists -------------------------------------------------------------- */

/* A list where a short name sits beside a long explanation. The name column is
   fixed, so the explanations align down the page. The rule between rows is the
   one coloured line on the site. */
.rows > li {
  display: grid;
  gap: 0.75rem;
  padding-block: 1.5rem;
  align-items: start;
}
.rows > li + li { border-top: 1px solid var(--line-accent); }
@media (min-width: 40rem) {
  .rows > li { grid-template-columns: 200px 1fr; gap: 2rem; }
}
.rows .row-name {
  display: inline-flex;
  align-items: start;
  gap: 0.5rem;
  font-family: var(--face-display);
  font-size: 1.3125rem;
  letter-spacing: var(--track-display);
  color: var(--accent);
}
a.row-name:hover { opacity: 0.8; color: var(--accent); }
.rows .row-name svg { width: 1.125rem; height: 1.125rem; margin-top: 0.3rem; flex: none; opacity: 0.4; transition: all var(--hover-dur); }
a.row-name:hover svg { opacity: 1; transform: translate(2px, -2px); }
.rows p { color: var(--ink-80); font-size: var(--t-lede); line-height: var(--lh-prose); text-wrap: pretty; }

/* Stages of a process, side by side, each opened by a cyan rule. No numbers:
   the order is the reading order. */
.steps { display: grid; gap: 3rem; margin-top: 3rem; }
@media (min-width: 40rem) { .steps { grid-template-columns: repeat(3, 1fr); gap: 2.5rem; } }
.steps > li { border-top: 1px solid var(--line-accent); padding-top: 1.5rem; }
.steps h3 {
  font-family: var(--face-display);
  font-weight: 400;
  font-size: 1.25rem;
  letter-spacing: var(--track-display);
}
@media (min-width: 40rem) { .steps h3 { font-size: 1.5rem; } }
.steps p { margin-top: 1rem; color: var(--ink-75); text-wrap: pretty; }

/* Facts about the thing, each opened by a strong hairline. Two columns, or
   three when the answers are short. */
.defs { display: grid; gap: 3rem; margin-top: 3.5rem; }
@media (min-width: 40rem) { .defs { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 40rem) { .defs--three { grid-template-columns: repeat(3, 1fr); } }
.defs > div { border-top: 1px solid var(--line-strong); padding-top: 1.5rem; }
.defs h3 {
  margin-bottom: 0.75rem;
  font-family: var(--face-display);
  font-weight: 400;
  font-size: 1.25rem;
  letter-spacing: var(--track-display);
}
/* 16px rather than the 14px stock Scene uses, because these paragraphs carry
   argument rather than annotation. */
.defs p { color: var(--ink-70); font-size: var(--t-body); line-height: var(--lh-prose); }
.defs p strong { color: var(--ink-85); font-weight: 600; }

/* --- 9. panels and asides -------------------------------------------------- */

/* The one raised surface on the site: a hairline box with the faintest wash
   across it. It closes a page, or it holds the form. */
.panel {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-panel);
  background: linear-gradient(to bottom right, var(--bg-raised), transparent);
  padding: 2.5rem;
}
@media (min-width: 40rem) { .panel { padding: 3.5rem; } }
.panel--form { padding: 2rem; }
@media (min-width: 40rem) { .panel--form { padding: 2.5rem; } }

/* Short notes beside the form. On a wide screen they hang off a left rule; on a
   narrow one they drop below with a rule on top. */
.sidenote { align-self: start; border-top: 1px solid var(--line); padding-top: 2.5rem; display: grid; gap: 2.5rem; }
@media (min-width: 64rem) {
  .sidenote { border-top: 0; border-left: 2px solid var(--line); padding: 0 0 0 3rem; }
}
.sidenote h3 {
  font-family: var(--face-display);
  font-weight: 400;
  font-size: 1.25rem;
  line-height: 1.2;
  letter-spacing: var(--track-display);
}
.sidenote p { margin-top: 1rem; color: var(--ink-70); line-height: var(--lh-prose); max-width: 28rem; text-wrap: pretty; }

/* --- 10. motion ------------------------------------------------------------ */

/* A heading arrives one word at a time. The script splits the words; this is
   what they look like before it animates them. A page with scripting off never
   gets the ready flag and shows every heading as written. */
[data-reveal] .word { display: inline-block; will-change: transform, opacity; }
[data-reveal][data-reveal-ready]:not([data-reveal-done]) .word { opacity: 0; transform: translateY(var(--reveal-rise)); }

/* A still photograph that never quite stops. The move is slow enough that a
   reader cannot see it happening and long enough that it never repeats while
   they are looking. */
.drift        { animation: drift 70s ease-in-out infinite alternate; transform-origin: 65% 40%; }
.drift--mid   { animation-duration: 95s; animation-direction: alternate-reverse; transform-origin: 60% 50%; }
@keyframes drift {
  from { transform: scale(1.02) translate(0, 0); }
  to   { transform: scale(1.08) translate(-1.2%, 0.8%); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  html { scroll-behavior: auto; }
  .drift { animation: none; }
  [data-reveal][data-reveal-ready]:not([data-reveal-done]) .word { opacity: 1; transform: none; }
}

/* --- 11. page treatments ---------------------------------------------------
   The Content-Security-Policy on this site has no 'unsafe-inline', so a style
   attribute would be dropped. Every offset, mask and mono block below would
   have been one in the prototypes. */

/* Home hero. The pole stands on the right and its left edge dissolves into the
   page, so the heading has black to sit on rather than a straight cut. */
.scene__media--pole {
  inset: 0 0 0 auto;
  width: 70%;
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 22%);
          mask-image: linear-gradient(to right, transparent 0, #000 22%);
}

/* The court. Its vignette is baked into the file, so it needs no mask, only
   placing: centred vertically, starting about under the word "program". */
.scene__media--court {
  inset: 12% 0 12% auto;
  width: 58%;
  height: auto;
  max-height: 76%;
  margin-block: auto;
}

/* The flag on Get Involved. It starts below the fixed header and fades in from
   the top so it never collides with the menu. */
.hero__media > img.hero__media--flag {
  /* 6rem rather than the header's own 5rem: the extra rem keeps the top of the
     flag clear of the menu instead of tucked right under it. */
  inset: 6rem 0 0 auto;
  width: 70%;
  height: calc(100% - 6rem);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 22%);
          mask-image: linear-gradient(to bottom, transparent 0, #000 22%);
}

/* A scene still waiting for its photograph. It holds the shape and prints the
   shot it is waiting for in the corner. Delete the note element and the scene
   is simply black. */
.scene__media--blank {
  background: var(--bg-blank);
  display: grid;
  place-items: end;
  padding: 1rem 1.25rem;
}
.photo-note {
  font-family: var(--face-mono);
  font-size: var(--t-mono);
  letter-spacing: var(--track-mono);
  text-transform: lowercase;
  color: rgba(255, 255, 255, 0.3);
  text-align: right;
}

/* A hairline that opens a block rather than separating two. */
.rule-top        { border-top: 1px solid var(--line-strong); padding-top: 1.5rem; }
.rule-top--faint { border-top-color: var(--line); }

/* The meeting dates, printed from the MEETINGS array as one line. */
.dateline {
  font-family: var(--face-mono);
  font-size: var(--t-lede);
  letter-spacing: var(--track-mono);
  color: var(--ink-85);
  margin-top: 1.5rem;
}

/* A commissioner's email and phone, set in mono so they are easy to copy and
   easy to read back over a phone. */
.seat-contact { font-family: var(--face-mono); font-size: var(--t-small); color: var(--ink-70); }

/* Our own number, which is the one on the site a reader is actually meant to
   tap. An inline link is about 18px tall, so it gets the same 44px target as
   every other control. */
.callnumber {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--face-mono);
  font-size: var(--t-body);
  color: var(--ink-85);
}
.callnumber:hover { color: var(--ink); }
.seat-contact:hover { color: var(--ink); }
.seat-sep { color: var(--ink-50); }
.rows p strong { color: var(--ink-90); font-weight: 600; }

/* A script somebody is going to read aloud or paste into an email. It keeps its
   line breaks and takes no box: the label column beside it is the frame. */
.script {
  white-space: pre-wrap;
  font-family: var(--face-mono);
  font-size: var(--t-script);
  letter-spacing: var(--track-script);
  line-height: var(--lh-script);
  color: var(--ink-75);
}

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

.mt-s  { margin-top: 1.5rem; }
.mt-m  { margin-top: 2.5rem; }
.mt-l  { margin-top: 3.5rem; }
.mt-xl { margin-top: 4.5rem; }

/* --- print -----------------------------------------------------------------
   Somebody will print the scripts and the records letter. Browsers drop the
   background by default, so the page has to come back to ink on paper. */

@media print {
  :root { --ink: #000; --ink-90: #000; --ink-85: #111; --ink-80: #222; --ink-75: #222;
          --ink-70: #333; --ink-65: #333; --ink-60: #444; --ink-55: #444; --ink-50: #555;
          --line: #ccc; --line-strong: #999; --line-accent: #999; --line-faint: #ddd; }
  body { background: #fff; color: #000; }
  .grain, .site-header, .scene__media, .scene__scrim, .hero__media, .hero__scrim,
  .pill-row, .site-footer__cols { display: none; }
  .scene, .hero { min-height: 0; padding: 1.5rem 0; }
  .section { padding-block: 1.5rem; }
  .accent, .rows .row-name { color: #000; }
  .panel { border: 1px solid #999; background: none; }
  a { color: #000; text-decoration: underline; }
  .script { font-size: 10pt; color: #000; }
}
