/* Hallmark · macrostructure: Marquee Hero · polish: HP1 vertical rail (tide mark)
 * genre: editorial · theme: custom "Tideline"
 *   vibe: sea fog, tidal ink, one marigold run hard, elegy
 *   paper oklch(97.2% 0.009 82) · accent oklch(68% 0.168 55), at the gamut edge
 *   display Fraunces (roman) + body Newsreader + furniture Karla
 *   axes: paper-band light · display-style soft-serif · accent-hue warm
 * nav: N6 masthead, always open, the name as the largest type on the site
 * footer: thin full-width strip
 * enrichment: hand-built SVG shoreline + three CC BY photographs
 * motion: draw-in · rail · reveal · wheel smoothing
 * contrast: pass (40-41) · slop: pass (42-45) · honest: pass (46)
 * chrome: pass (47) · tokens: pass (48) · responsive: pass (49) · mobile: pass (34, 50-57)
 *
 * Site for H. J. Thomas, poet. Static: no framework, no build step.
 * The rule that governs the content: no unpublished poem appears here.
 */

@import url("tokens.css?v=8");

/* ================================================================
   Reset and base
   ================================================================ */

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

html {
  /* clip, not hidden: hidden would break the fixed masthead and the rail. */
  overflow-x: clip;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  overflow-x: clip;
  margin: 0;
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 400;
  line-height: var(--lh-prose);
  font-optical-sizing: auto;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--color-selection); color: var(--color-ink); }

h1, h2, h3 {
  font-family: var(--font-display);
  font-style: normal;          /* headings are roman, always */
  font-weight: 500;
  line-height: var(--lh-tight);
  margin: 0;
  overflow-wrap: anywhere;
  min-width: 0;
  text-wrap: balance;
}

p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
em { font-style: italic; }
img { max-width: 100%; display: block; }
svg { max-width: 100%; }
a { color: inherit; }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

:focus-visible {
  /* Instant. Never transitioned: a keyboard user needs it the moment
     focus lands. */
  outline: var(--rule-thick) solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.skip {
  position: absolute;
  left: var(--space-md);
  top: calc(-1 * var(--space-3xl));
  z-index: calc(var(--z-sticky-nav) + 1);
  padding: var(--space-sm) var(--space-md);
  background: var(--color-ink);
  color: var(--color-paper);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: top var(--dur-micro) var(--ease-out);
}
.skip:focus-visible { top: var(--space-md); }

/* Brand marks, drawn as lines so they sit with the rest of the page
   rather than looking pasted in from an icon library. */
.glyph {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ================================================================
   Wrapper
   ================================================================ */

.head__in,
.hero__in,
.sec__in {
  width: 100%;
  max-width: 74rem;
  margin-inline: auto;
  padding-inline: clamp(1.125rem, 0.6rem + 2.6vw, 3rem);
}

/* ================================================================
   Masthead · N6
   The name is the largest type on the site, bigger than any heading in
   the body, and it is the only mark: there is no logo. The sections stay
   visible at every width: no disclosure, no hamburger, nothing to open.
   ================================================================ */

.head {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--z-sticky-nav);
  background: color-mix(in oklab, var(--color-paper) 90%, transparent);
  border-block-end: var(--rule-hair) solid var(--color-rule);
}

@supports (backdrop-filter: blur(1px)) {
  .head { backdrop-filter: blur(12px) saturate(1.15); }
}

.head__in {
  min-height: var(--head-h);
  display: grid;
  align-items: center;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "name"
    "nav";
  column-gap: var(--space-md);
  row-gap: var(--space-2xs);
  padding-block: var(--space-xs);
}

.head__name {
  grid-area: name;
  /* Body serif, not the display face. See --font-mast in tokens.css. */
  font-family: var(--font-mast);
  font-optical-sizing: none;
  font-variation-settings: "opsz" var(--opsz-mast);
  font-size: var(--text-mast);
  font-weight: 500;
  line-height: var(--lh-mast);
  letter-spacing: -0.012em;
  white-space: nowrap;
}
.head__name a {
  text-decoration: none;
  border-block-end: var(--rule-fat) solid transparent;
  transition: border-color var(--dur-micro) var(--ease-out);
}
.head__name a:hover { border-block-end-color: var(--color-accent); }

.head__nav { grid-area: nav; }
.head__nav ul {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xs);
}
.head__nav a {
  display: inline-block;
  font-family: var(--font-ui);
  font-size: clamp(0.6875rem, 0.60rem + 0.42vw, 0.95rem);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--color-muted);
  text-decoration: none;
  white-space: nowrap;             /* clickable text never wraps */
  padding-block: var(--space-xs);
  border-block-end: var(--rule-thick) solid transparent;
  transition: color var(--dur-micro) var(--ease-out),
              border-color var(--dur-micro) var(--ease-out);
}
.head__nav a:hover { color: var(--color-ink); border-block-end-color: var(--color-rule-2); }
.head__nav a:active { color: var(--color-accent-2); }
.head__nav a[aria-current="true"] {
  color: var(--color-ink);
  border-block-end-color: var(--color-accent);
}

@media (min-width: 62rem) {
  .head__in {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "name nav";
    column-gap: var(--space-xl);
    row-gap: 0;
    padding-block: var(--space-sm);
  }
  .head__nav ul {
    justify-content: flex-end;
    gap: clamp(var(--space-md), 1.8vw, var(--space-xl));
  }
}

/* ================================================================
   The tide mark · HP1
   Fills marigold into rose as the page is read. Native CSS scroll
   timeline, so there is no scroll listener and nothing to stall.
   Browsers without it get the line already full.
   ================================================================ */

.rail { display: none; }

@media (min-width: 82rem) {
  .rail {
    display: block;
    position: fixed;
    inset-block-start: 30vh;
    inset-inline-start: clamp(var(--space-lg), calc((100vw - 74rem) / 2 + var(--space-sm)), 42rem);
    z-index: var(--z-rail);
    pointer-events: none;
  }
  .rail__track {
    width: 3px;
    height: 44vh;
    background: var(--color-rule);
    border-radius: var(--radius-pill);
    overflow: hidden;
  }
  .rail__fill {
    width: 100%;
    height: 100%;
    transform-origin: top center;
    background: linear-gradient(180deg, var(--color-accent), var(--color-rose));
  }
}

@supports (animation-timeline: scroll()) {
  @media (min-width: 82rem) {
    .rail__fill {
      transform: scaleY(0);
      animation: rail-fill linear both;
      animation-timeline: scroll(root block);
    }
  }
}

@keyframes rail-fill {
  from { transform: scaleY(0); }
  to   { transform: scaleY(1); }
}

@media (prefers-reduced-motion: reduce) {
  .rail__fill { animation: none; transform: scaleY(1); }
}

/* ================================================================
   Shared furniture
   The accent is a line language rather than a wash: a tick, an
   underline, a waterline, a rail, and exactly one filled button.
   ================================================================ */

.tick {
  display: block;
  width: 2.75rem;
  height: var(--rule-fat);
  background: var(--color-accent);
  border-radius: var(--radius-pill);
  margin-block-end: var(--space-md);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;                /* 44px floor, shared with inputs */
  padding: var(--space-xs) var(--space-lg);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  border: var(--rule-hair) solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color var(--dur-micro) var(--ease-out),
              color var(--dur-micro) var(--ease-out),
              border-color var(--dur-micro) var(--ease-out);
}

.btn--primary {
  background: var(--color-accent);
  color: var(--color-accent-ink);
  border-color: var(--color-accent);
}
.btn--primary:hover {
  background: var(--color-accent-2);
  border-color: var(--color-accent-2);
  color: var(--color-paper);
}
.btn--primary:active {
  background: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-paper);
}
.btn--primary:disabled,
.btn--primary[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }

.btn--quiet {
  background: none;
  color: var(--color-ink);
  border-color: var(--color-rule-2);
}
.btn--quiet:hover  { background: var(--color-paper-2); border-color: var(--color-ink-2); }
.btn--quiet:active { color: var(--color-accent-2); border-color: var(--color-accent-2); }
.btn--quiet:disabled,
.btn--quiet[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }

/* ================================================================
   Hero · Marquee
   Left-biased on purpose: nothing here sits on a shared centre axis.
   ================================================================ */

.hero {
  padding-block-start: calc(var(--head-h) + var(--space-xl));
  padding-block-end: var(--space-4xl);
}

.hero__in {
  display: grid;
  gap: var(--space-2xl);
  align-items: center;
}

@media (min-width: 64rem) {
  .hero__in {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.16fr);
    gap: var(--space-3xl);
  }
  /* Let the drawing run out to the wrapper edge. It cancels the container
     padding exactly, so it can never push the page wider. */
  .hero__fig { margin-inline-end: calc(-1 * clamp(1.125rem, 0.6rem + 2.6vw, 3rem)); }
}

.hero__say {
  font-family: var(--font-display);
  font-size: var(--text-say);
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: -0.014em;
  max-width: 24ch;
  color: var(--color-ink);
  text-wrap: balance;
}

.hero__sub {
  margin-block-start: var(--space-lg);
  max-width: 40ch;
  font-size: var(--text-sm);
  color: var(--color-muted);
}

.hero__do {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
  margin-block-start: var(--space-xl);
}

.hero__credit {
  margin-block-start: var(--space-xl);
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  font-weight: 500;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.hero__credit .tick { width: 1.75rem; margin-block-end: var(--space-xs); }

/* --- The drawing ---------------------------------------------- */

.hero__fig { margin: 0; }

.shore {
  display: block;
  width: 100%;
  height: auto;
  color: var(--color-ink-2);
}

/* The strokes draw themselves in on load, in the order you would draw them:
   horizon, land, then the water. Delays are named rather than counted by
   nth-child, so the drawing can be rearranged without silently reshuffling
   the timing. */
.shore__p {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: shore-draw var(--dur-draw) var(--ease-out) forwards;
}
.shore__p.d-horizon  { animation-delay: 0ms; }
.shore__p.d-island   { animation-delay: 180ms; }
.shore__p.d-skerry   { animation-delay: 300ms; }
.shore__p.d-headland { animation-delay: 380ms; }
.shore__p.shore__tide { animation-delay: 520ms; }
.shore__p.d-sea1 { animation-delay: 620ms; }
.shore__p.d-sea2 { animation-delay: 720ms; }
.shore__p.d-sea3 { animation-delay: 820ms; }
.shore__p.d-sea4 { animation-delay: 920ms; }

.shore__moon {
  opacity: 0;
  animation: shore-fade var(--dur-long) var(--ease-out) 1100ms forwards;
}

/* Cirrus. Each streak has its own speed, and a negative delay so they are
   already spread across the sky on load rather than filing in from the left.
   The outer svg clips, so nothing needs to be hidden at the edges. */
.cloud { animation: shore-drift 96s linear infinite; }
.cloud--1 { animation-duration: 86s;  animation-delay: -22s; }
.cloud--2 { animation-duration: 118s; animation-delay: -74s; }
.cloud--3 { animation-duration: 98s;  animation-delay: -46s; }
.cloud--4 { animation-duration: 134s; animation-delay: -99s; }

.cloud__p {
  opacity: 0;
  animation: shore-fade var(--dur-long) var(--ease-out) 1300ms forwards;
}

/* Swell. A long, shallow sway with a slight lift, each line out of phase with
   the others so the sea never moves as one block. It starts once the drawing
   has finished drawing itself. */
.wave { animation: shore-swell 17s var(--ease-in-out) 3.6s infinite; }
.shore__sea .wave:nth-child(1) { animation-duration: 14s; animation-delay: 3.6s; }
.shore__sea .wave:nth-child(2) { animation-duration: 19s; animation-delay: 4.4s; }
.shore__sea .wave:nth-child(3) { animation-duration: 16s; animation-delay: 3.9s; }
.shore__sea .wave:nth-child(4) { animation-duration: 22s; animation-delay: 5.0s; }
.wave--tide { animation-duration: 27s; animation-delay: 3.2s; }

/* Nothing is animating while the drawing is off screen. */
.shore.is-still .cloud,
.shore.is-still .wave { animation-play-state: paused; }

@keyframes shore-draw  { to { stroke-dashoffset: 0; } }
@keyframes shore-fade  { to { opacity: 1; } }
@keyframes shore-drift { from { transform: translateX(-300px); } to { transform: translateX(720px); } }
@keyframes shore-swell {
  0%   { transform: translate(0, 0); }
  50%  { transform: translate(9px, -1.5px); }
  100% { transform: translate(0, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .shore__p { animation: none; stroke-dashoffset: 0; }
  .shore__moon { animation: none; opacity: 1; }
  .cloud__p { animation: none; opacity: 1; }
  .cloud, .wave { animation: none; transform: none; }
}

.hero__cap {
  margin-block-start: var(--space-md);
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-neutral);
}

/* ================================================================
   Sections
   Whitespace is the divider; a hairline marks the seam. Each section
   opens with the marigold tick directly above its heading, stacked in
   one column. No eyebrow, no numbering.
   ================================================================ */

.sec {
  padding-block: var(--space-3xl);
  border-block-start: var(--rule-hair) solid var(--color-rule);
  scroll-margin-block-start: calc(var(--head-h) + var(--space-sm));
}

.sec--poem { background: var(--color-paper-2); }
.sec--about { padding-block-end: 0; }
.sec--contact { border-block-end: var(--rule-hair) solid var(--color-rule); }

.sec__head {
  display: block;                    /* tick and heading share one column */
  max-width: var(--measure);
  margin-block-end: var(--space-2xl);
}

.sec__title {
  font-size: var(--text-title);
  letter-spacing: -0.012em;
}


/* ================================================================
   The poem
   Line breaks are content. Never justified, never hyphenated. A line
   too long for the viewport turns with a hanging indent, the way a
   printed book handles it, rather than reflowing as prose.
   ================================================================ */

.poem { max-width: 46rem; }

/* The poem is the centrepiece, so its section is the one place on the page
   where the column is centred rather than flush left. The head sits on the
   same left edge as the verse, so it reads as one page rather than two. */
@media (min-width: 64rem) {
  .sec--poem .poem { margin-inline: auto; max-width: 46rem; }
}

/* With the section head gone, the poem's own title is the section heading,
   and it opens the same way every other section does: tick, then heading. */
.poem__title {
  font-size: var(--text-title);
  font-weight: 500;
  letter-spacing: -0.012em;
  margin-block-end: var(--space-xl);
}

.poem__body {
  font-size: clamp(1rem, 0.90rem + 0.44vw, 1.42rem);
  line-height: var(--lh-verse);
  color: var(--color-ink);
  text-align: left;
  hyphens: none;
  -webkit-hyphens: none;
}

/* Each line is its own block, so the negative indent cancels the padding on
   the line the poet wrote and applies only to a line the viewport turns.
   Doing this with <br> and text-indent indents every line after the first,
   which silently rewrites the poem. */
.poem__line {
  display: block;
  padding-inline-start: 1.35em;
  text-indent: -1.35em;
}

.poem__stanza + .poem__stanza { margin-block-start: 1.35em; }

.poem__credit {
  margin-block-start: var(--space-2xl);
  padding-block-start: var(--space-md);
  border-block-start: var(--rule-hair) solid var(--color-rule);
  max-width: 54ch;
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  line-height: 1.7;
  color: var(--color-muted);
}

/* ================================================================
   Collections
   ================================================================ */

.coll { display: grid; gap: var(--space-3xl); }

.coll__item {
  display: grid;
  gap: var(--space-lg);
  padding-block-start: var(--space-lg);
  border-block-start: var(--rule-hair) solid var(--color-rule);
}

@media (min-width: 56rem) {
  .coll__item {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
    column-gap: var(--space-2xl);
    align-items: start;
  }
}

.coll__fig { margin: 0; }
.coll__fig img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-md);
  background: var(--color-paper-3);
}

/* Attribution sits beside the photograph it credits, not buried in a
   colophon. It is a licence condition, so it is never hidden. */
.fig__credit,
.band__credit {
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  line-height: 1.5;
  color: var(--color-neutral);
}
.fig__credit { margin-block-start: var(--space-xs); }

.fig__credit a,
.band__credit a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--color-rule-2);
  text-underline-offset: 2px;
  transition: color var(--dur-micro) var(--ease-out),
              text-decoration-color var(--dur-micro) var(--ease-out);
}
.fig__credit a:hover,
.band__credit a:hover { color: var(--color-accent-2); text-decoration-color: var(--color-accent-2); }
.fig__credit a:active,
.band__credit a:active { color: var(--color-accent-2); }

.coll__title {
  font-size: var(--text-md);
  font-weight: 500;
  letter-spacing: -0.006em;
}

.coll__status {
  margin-block-start: var(--space-2xs);
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent-2);
}

.coll__body {
  margin-block-start: var(--space-md);
  max-width: var(--measure-n);
  font-size: var(--text-sm);
  color: var(--color-ink-2);
}

/* ================================================================
   Prose
   Justified with hyphenation only where the column is wide enough to
   justify without rivers. Ragged right everywhere below that.
   ================================================================ */

.prose { max-width: var(--measure); }
.prose p + p { margin-block-start: var(--space-md); }
.prose p { color: var(--color-ink-2); }

@media (min-width: 48rem) {
  .prose p {
    text-align: justify;
    hyphens: auto;
    -webkit-hyphens: auto;
    hyphenate-limit-chars: 6 3 3;
  }
}

.prose a,
.poem__credit a,
.contact__email a,
.colo__bit a {
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  transition: text-decoration-color var(--dur-micro) var(--ease-out),
              color var(--dur-micro) var(--ease-out);
}
.prose a:hover,
.poem__credit a:hover,
.contact__email a:hover,
.colo__bit a:hover {
  color: var(--color-accent-2);
  text-decoration-color: var(--color-accent-2);
}
.prose a:active,
.poem__credit a:active,
.contact__email a:active,
.colo__bit a:active { color: var(--color-accent-2); }

/* ================================================================
   The photographic band, edge to edge under the About column
   ================================================================ */

/* The band is full-bleed and the reading rail is fixed, so the two cross.
   The photograph is given a stacking context above the rail, so the rail
   passes behind the picture rather than drawing a line across it. Done with
   stacking order rather than by fading the rail out on a scroll observer:
   this needs no JavaScript, no observer and no motion, so it still holds
   when any of those are unavailable. */
.band {
  margin: var(--space-3xl) 0 0;
  position: relative;
  z-index: var(--z-band);
}

.band img {
  width: 100%;
  height: auto;
  aspect-ratio: 21 / 9;
  max-height: 52vh;
  object-fit: cover;
  object-position: center 62%;
  background: var(--color-paper-3);
}

.band__cap {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-md);
  padding: var(--space-sm) clamp(1.125rem, 0.6rem + 2.6vw, 3rem);
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.band__credit { letter-spacing: 0.02em; text-transform: none; }

/* ================================================================
   Elsewhere
   ================================================================ */

/* ================================================================
   Get in touch
   The address and the four accounts sit in one column, the form in the
   other. Every route to him is in a single place.
   ================================================================ */

.contact {
  display: grid;
  gap: var(--space-2xl);
  align-items: start;
}

@media (min-width: 56rem) {
  .contact {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    column-gap: var(--space-3xl);
  }
}

.contact__email {
  font-family: var(--font-display);
  font-size: var(--text-md);
  word-break: break-word;
}

.links {
  display: grid;
  gap: 0;
  margin-block-start: var(--space-lg);
}

.links__item { border-block-start: var(--rule-hair) solid var(--color-rule); }
.links__item:last-child { border-block-end: var(--rule-hair) solid var(--color-rule); }

.links__a {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2xs) var(--space-sm);
  padding-block: var(--space-sm);
  text-decoration: none;
}
.links__a .glyph {
  color: var(--color-accent-2);
  transition: color var(--dur-micro) var(--ease-out);
}
.links__a:hover .glyph { color: var(--color-accent); }

.links__name {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  border-block-end: var(--rule-thick) solid transparent;
  transition: border-color var(--dur-micro) var(--ease-out),
              color var(--dur-micro) var(--ease-out);
}
.links__a:hover .links__name { border-block-end-color: var(--color-accent); }
.links__a:active .links__name { color: var(--color-accent-2); }

.links__handle {
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  color: var(--color-neutral);
  word-break: break-word;
}

.form { display: grid; gap: var(--space-md); max-width: 32rem; }


.field { display: grid; gap: var(--space-2xs); }

.field__label {
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.field__input {
  width: 100%;
  min-height: 2.75rem;                 /* matches .btn exactly */
  padding: var(--space-xs) var(--space-sm);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--color-ink);
  background: var(--color-paper);
  /* Border width never changes between states, or the layout shifts. */
  border: var(--rule-hair) solid var(--color-rule-2);
  border-radius: var(--radius-sm);
  outline: var(--rule-thick) solid transparent;   /* reserved, no jump on focus */
  outline-offset: 1px;
  transition: border-color var(--dur-micro) var(--ease-out),
              background-color var(--dur-micro) var(--ease-out);
}
.field__input--area { min-height: 8rem; resize: vertical; }

.field__input:hover { border-color: var(--color-ink-2); }
.field__input:focus-visible { outline-color: var(--color-focus); border-color: var(--color-ink-2); }
.field__input:disabled { opacity: 0.55; cursor: not-allowed; background: var(--color-paper-3); }
.field__input[aria-invalid="true"] { border-color: var(--color-error); background: var(--color-paper-2); }

.field__help {
  min-height: 1lh;                     /* reserved, so an error cannot shove the page */
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  line-height: 1.5;
  color: var(--color-error);
}

.form__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
  margin-block-start: var(--space-xs);
}

.form__status {
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  line-height: 1;
  color: var(--color-muted);
}
.form__status[data-tone="error"]   { color: var(--color-error); }
.form__status[data-tone="success"] { color: var(--color-success); }

/* ================================================================
   Colophon · a thin strip, edge to edge
   ================================================================ */

.colo { border-block-start: var(--rule-thick) solid var(--color-accent); }

.colo__in {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2xs) var(--space-lg);
  padding: var(--space-xs) clamp(1.125rem, 0.6rem + 2.6vw, 3rem);
}

.colo__bit {
  font-family: var(--font-ui);
  font-size: var(--text-2xs);
  line-height: 1.5;
  color: var(--color-muted);
}
.colo__k {
  color: var(--color-neutral);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  margin-inline-end: var(--space-2xs);
}

.colo__soc {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
}
.colo__soc a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.85rem;
  height: 1.85rem;
  color: var(--color-neutral);
  border-radius: var(--radius-sm);
  transition: color var(--dur-micro) var(--ease-out);
}
.colo__soc a:hover  { color: var(--color-accent-2); }
.colo__soc a:active { color: var(--color-accent); }
.colo__soc .glyph { width: 1.05rem; height: 1.05rem; }

@media (max-width: 47.99rem) {
  .colo__in { justify-content: flex-start; }
}

/* ================================================================
   Section reveal
   The hidden state is added by script, never by this stylesheet, so a
   page without JavaScript shows everything. An inline failsafe in the
   head strips it on a timer if the observer never fires.
   ================================================================ */

.js-reveal .sec,
.js-reveal .hero__text,
.js-reveal .hero__fig {
  opacity: 0;
  transform: translateY(10px);
}

.js-reveal .is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur-long) var(--ease-out),
              transform var(--dur-long) var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
  .js-reveal .sec,
  .js-reveal .hero__text,
  .js-reveal .hero__fig { opacity: 1; transform: none; }
  .js-reveal .is-in { transition: opacity 140ms linear; }
}
