/* Niagara Assembly — a plain document with one drawn box around it.
 *
 * The reference is a near-unstyled page: one left-aligned column, ink on
 * paper, no imagery. Everything decorative is carried by the Rough.js
 * frame, so this file's job is mostly restraint.
 *
 * The border rules come in pairs. The plain rule is the fallback; the
 * `.sketched` rule removes it once assets/js/sketch.js has successfully
 * drawn. If that script 404s or throws, the page keeps every border here.
 */

/* Self-hosted so the hand face is the same on every device. The old stack
   headed by Comic Sans MS resolved to Bradley Hand on macOS and iOS, and to
   generic `cursive` — a script face — on Android and Linux. See
   assets/fonts/README.md. font-display: block rather than swap, because a
   flash of the fallback would flash a different aesthetic, not just
   different metrics. */
@font-face {
  font-family: 'Comic Neue';
  src: url('../fonts/comic-neue-latin-400-normal.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: block;
}
@font-face {
  font-family: 'Comic Neue';
  src: url('../fonts/comic-neue-latin-700-normal.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: block;
}

:root {
  --ink:      #17181a;
  --ink-soft: #55585d;
  --paper:    #f7f6f3;
  --rule:     #c9c6bf;

  --measure: 46rem;
  --edge:    0.5rem;   /* how far the nav and footer sit inside the box's lines */

  /* Icons centre on their own box; text sits on a baseline with descender
     space reserved below it. The nav labels have no descenders, so their
     optical centre is above the line box's and an icon centred on the line
     box reads low. Measured against the cap-height midpoint at 12px. */
  --icon-lift: 0.5px;
  --board:   62rem;   /* the board is denser and earns more width */

  /* Prose is a system sans, per the reference's neutrality. The hand face
     is confined to interactive chrome so the drawn frame and the drawn
     type agree with each other while the prose stays serious.

     Comic Neue is shipped with the site, so the names after it are only
     reached if the woff2 fails to load — Comic Sans MS before the generic
     because it is the closer match. */
  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --hand: 'Comic Neue', 'Comic Sans MS', 'Segoe Print', cursive;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* Light is the default, deliberately — not `prefers-color-scheme`. Dark is
   opt-in via the toggle, which sets data-theme on <html> and remembers the
   choice. A visitor whose system is dark still gets the light page first,
   because the drawn box and the plain-document look were designed on
   paper. */
:root[data-theme="dark"] {
  --ink:      #e9e7e2;
  --ink-soft: #a3a099;
  --paper:    #16171a;
  --rule:     #3a3c40;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 2.5rem 1.25rem 4rem;
  background: var(--paper);
  color: var(--ink);
  font: 1rem/1.65 var(--sans);
}

/* Top navigation ------------------------------------------------------ */
/* Sits ABOVE the drawn box, sharing its max-width and centring so the two
   line up at both edges, then inset by --edge so the brand and the last
   icon sit just inside the drawn lines rather than on them. The footer
   uses the same inset, so the three edges agree. */

.topnav {
  display: flex;
  align-items: baseline;
  gap: 1.5rem;
  max-width: var(--measure);
  margin: 0 auto .6rem;
  padding: 0 var(--edge);
}
.topnav--board { max-width: var(--board); }

.topnav__brand {
  font: 800 1.0625rem/1 var(--sans);
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--ink);
}

/* margin-left:auto pins the group right; the parent's padding is the gap
   between the last item and the box edge below it. */
.topnav__links {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 1.5rem;
}
.topnav__links a {
  font: .75rem/1 var(--sans);
  letter-spacing: .01em;
  text-decoration: none;
  color: var(--ink-soft);
}
.topnav__links a:hover { color: var(--ink); text-decoration: underline; }

/* Half ink, half paper. Both halves are tokens, so the rectangle inverts
   itself when the theme flips — no second icon, no state class. */
.themetoggle {
  margin-left: .15rem;
  width: 26px;
  height: 14px;
  padding: 0;
  border: 1px solid var(--ink);
  border-radius: 2px;
  background: linear-gradient(to right, var(--ink) 0 50%, var(--paper) 50% 100%);
  cursor: pointer;
  flex: none;
}
.themetoggle:hover { outline: 1px solid var(--rule); outline-offset: 2px; }

/* Pulled closer to each other than the words are, so the pair reads as one
   group rather than as two more nav items. */
.topnav__icon { display: flex; align-items: center; margin-left: -0.65rem; }

/* Lifted off the line box onto the glyphs' optical centre. position/top
   rather than a margin, so nothing else in the row moves. */
.topnav__icon,
.themetoggle { position: relative; top: calc(-1 * var(--icon-lift)); }
.topnav__icon:first-of-type { margin-left: 0; }
.topnav__icon:hover { color: var(--ink); }
.topnav__links a.topnav__icon:hover { text-decoration: none; }
.topnav__links a[aria-current="page"] { color: var(--ink); font-weight: 600; }

@media (max-width: 34rem) {
  .topnav { flex-wrap: wrap; gap: .6rem 1rem; }
  .topnav__links { margin-left: 0; flex-wrap: wrap; gap: .6rem 1rem; }
}

/* Position is relative so sketch.js can absolutely position its SVG. */
.frame {
  position: relative;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 3rem 2.5rem;
  border: 1.4px solid var(--ink);
}
.frame--board { max-width: var(--board); padding: 2rem 2rem 3rem; }
.sketched .frame { border-color: transparent; }

.sketch-svg { position: absolute; pointer-events: none; overflow: visible; }

h1 {
  font: 400 clamp(1.9rem, 6vw, 2.6rem)/1.1 var(--sans);
  letter-spacing: -0.02em;
  margin: 0 0 2rem;
}
h2 { font: 600 1.05rem/1.3 var(--sans); margin: 2.5rem 0 .75rem; }
h3 { font: 600 1rem/1.3 var(--sans); margin: 0 0 .35rem; }

p { margin: 0 0 1.15em; max-width: 40rem; }
a { color: var(--ink); text-underline-offset: 2px; }

ul.plain { list-style: none; padding: 0; margin: 0 0 1.5rem; }
ul.plain li { margin: 0 0 .55rem; }
ul.plain li::before { content: '- '; color: var(--ink-soft); }

/* Board chrome ------------------------------------------------------- */
/* One power bar, one subnav beneath it, then a persistent filter bar that
   is separate from both. Each is its own drawn box. */

.nav {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 1.75rem;
  padding: .9rem 1.25rem;
  margin: 0 0 .75rem;
  border: 1.4px solid var(--ink);
}
.sketched .nav { border-color: transparent; }

.nav__item {
  font: 400 clamp(1.25rem, 3.4vw, 1.9rem)/1 var(--sans);
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--ink-soft);
}
.nav__item[aria-current="page"] { color: var(--ink); }

.subnav {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 1.1rem;
  padding: .55rem 1.25rem;
  margin: 0 0 .75rem;
  border: 1.4px solid var(--ink);
}
.sketched .subnav { border-color: transparent; }

.subnav__item {
  font: .875rem/1.4 var(--sans);
  text-decoration: none;
  color: var(--ink-soft);
}
.subnav__item[aria-current="true"] { color: var(--ink); font-weight: 600; }

.filters {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  align-items: center;
  padding: .6rem 1.25rem;
  margin: 0 0 2rem;
  border: 1.4px solid var(--rule);
}
.sketched .filters { border-color: transparent; }

.filters input[type="search"] { flex: 1 1 14rem; min-width: 10rem; }
.filters input, .filters select {
  padding: .35rem .5rem;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--rule);
  font: .8125rem/1.4 var(--sans);
}
.filters label.check {
  display: flex; align-items: center; gap: .35rem; margin: 0;
  font: .8125rem/1.4 var(--sans);
}
.filters label.check input { width: auto; }

.board__count { font: .75rem/1 var(--mono); color: var(--ink-soft); margin: 0 0 1rem; }
.board__empty { color: var(--ink-soft); }

.card {
  position: relative;
  margin: 0 0 1rem;
  padding: 1rem 1.25rem;
  border: 1.4px solid var(--rule);
}
.sketched .card { border-color: transparent; }

.card__meta { margin: 0 0 .3rem; font: .6875rem/1 var(--mono);
              letter-spacing: .08em; text-transform: uppercase;
              color: var(--ink-soft); }
.card__title { font: 700 1rem/1.3 var(--hand); margin: 0 0 .35rem; }
.card__by,
.card__when,
.card__where { margin: 0 0 .2rem; font: .875rem/1.4 var(--mono); color: var(--ink-soft); }
.card__specs { margin: 0 0 .2rem; font: .875rem/1.4 var(--mono); color: var(--ink-soft); }
/* Price carries weight because it is what a reader decides on before
   reading anything else. */
.card__price { margin: .35rem 0 .2rem; font: 600 .9375rem/1.3 var(--sans); }
.card__desc { margin: .6rem 0 .4rem; }
.card__link,
.card__contact { margin: 0 0 .2rem; font: .8125rem/1.4 var(--mono); }

/* Member notes on a listing. Indented and ruled so they read as replies
   to the card rather than as part of what was posted. */
.card__comments { list-style: none; margin: .8rem 0 0; padding: .5rem 0 0 .9rem;
                  border-top: 1px dotted var(--rule); }
.card__comment { margin: 0 0 .4rem; font: .8125rem/1.5 var(--sans); }
.card__comment-by { font: 600 .6875rem/1 var(--mono); letter-spacing: .06em;
                    text-transform: uppercase; color: var(--ink-soft);
                    display: block; margin-bottom: .15rem; }

/* Forms -------------------------------------------------------------- */

fieldset {
  position: relative;
  margin: 0 0 2rem;
  padding: 1.5rem 1.25rem;
  border: 1.4px solid var(--ink);
}
.sketched fieldset { border-color: transparent; }

legend { font: 700 .95rem/1 var(--hand); padding: 0 .4rem; }

label { display: block; margin: 0 0 .9rem; font: .8125rem/1.4 var(--hand); }
label input, label select, label textarea {
  display: block;
  width: 100%;
  margin-top: .3rem;
  padding: .45rem .55rem;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--rule);
  font: .9375rem/1.4 var(--sans);
}
textarea { min-height: 6rem; resize: vertical; }

.opt { color: var(--ink-soft); font-weight: 400; }
.fineprint { font: .75rem/1.5 var(--sans); color: var(--ink-soft); max-width: 34rem; }

/* Full width, so it reads as another field in the stack rather than as a
   second action competing with Send. */
.reveal {
  display: block;
  width: 100%;
  margin: 0 0 .9rem;
  padding: .45rem .55rem;
  background: transparent;
  color: var(--ink-soft);
  border: 1px dashed var(--rule);
  font: .8125rem/1.4 var(--hand);
  text-align: left;
  cursor: pointer;
}
.reveal:hover { color: var(--ink); border-color: var(--ink); }
.reveal::before { content: '+ '; }
.reveal[aria-expanded="true"]::before { content: '\2212 '; }
.reveal[aria-expanded="true"] { color: var(--ink); border-style: solid; }

button[type="submit"] {
  padding: .5rem 1.1rem;
  background: transparent;
  color: var(--ink);
  border: 1.4px solid var(--ink);
  font: .9375rem/1 var(--hand);
  cursor: pointer;
}

.status { min-height: 1.4em; font: .8125rem/1.5 var(--sans); color: var(--ink-soft); }
.status[data-state="error"] { color: var(--ink); font-weight: 600; }

/* Site footer --------------------------------------------------------- */
/* Centred under the drawn box, on one line. The SVG is inline rather than
   a file so it inherits currentColor and follows the dark-mode ink token
   without a second asset to keep in step. */

.sitefoot {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: .5rem;
  max-width: var(--measure);
  margin: 1.1rem auto 0;
  padding: 0 var(--edge);
  font: .75rem/1.5 var(--sans);
  color: var(--ink-soft);
}
.topnav--board ~ .sitefoot { max-width: var(--board); }

.sitefoot a:has(svg) { position: relative; top: calc(-1 * var(--icon-lift)); }
.sitefoot a { color: var(--ink-soft); text-decoration: none; }
.sitefoot a:hover { color: var(--ink); text-decoration: underline; }
.sitefoot svg { display: block; }
.sitefoot__sep { color: var(--rule); }

/* Mobile ------------------------------------------------------------- */
/* The drawn box and each fieldset carry desktop padding on all four sides.
   On a 390px screen that is most of the width spent on margins, so the
   insets shrink — not to nothing, because the drawn border needs room to
   sit off the text, but to about a third. */

@media (max-width: 40rem) {
  body { padding: 1.25rem .55rem 2.5rem; }

  .frame { padding: 1.4rem .9rem; }
  .frame--board { padding: 1.1rem .7rem 1.8rem; }

  fieldset { padding: 1rem .75rem; margin-bottom: 1.25rem; }

  .card { padding: .85rem .9rem; }

  .nav { gap: 1rem; padding: .7rem .85rem; }
  .subnav { gap: .8rem; padding: .5rem .85rem; }
  .filters { padding: .5rem .85rem; }

  h1 { margin-bottom: 1.25rem; }
  h2 { margin-top: 1.75rem; }
}

[hidden] { display: none !important; }
