/* Odd Duck Audio -- the whole site's styles, shared by every page.

   Self-hosted fonts: no third-party request, nothing to slow the first paint,
   and nothing that needs explaining in a privacy policy.

   Rubik Puddles for the names. Syne for the lines under them -- drawn for an
   arts centre, its letters disagree with each other on purpose, which reads as
   odd rather than as old. Inter does the work underneath, because a display
   face at 17px is just hard to read. */

@font-face { font-family: "Rubik Puddles"; src: url("/fonts/rubik-puddles-latin-400-normal.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Syne";  src: url("/fonts/syne-latin-800-normal.woff2")  format("woff2"); font-weight: 800; font-display: swap; }
@font-face { font-family: "Syne";  src: url("/fonts/syne-latin-600-normal.woff2")  format("woff2"); font-weight: 600; font-display: swap; }
@font-face { font-family: "Inter"; src: url("/fonts/inter-latin-400-normal.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Inter"; src: url("/fonts/inter-latin-600-normal.woff2") format("woff2"); font-weight: 600; font-display: swap; }

/* The yellow is taken off duckling down rather than off a colour wheel: pale
   and creamy where the light hits, warmer and deeper in the shade. The teal is
   the logo's badge, and is used for nothing else but the "free" tag. */
:root {
  --down-light: #fdf3c4;
  --down:       #f0d97e;
  --down-deep:  #c9a746;
  --ink:        #17150f;
  --bill:       #a85a15;   /* the bill and the feet, deepened until it is legible on the down */
  --rust:       #8c2f0d;
  --teal:       #4f9a86;
  --paper:      rgba(255, 252, 236, .62);
  --measure:    1040px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  color: var(--ink);
  font-family: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

body {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  padding: 0 20px 28px;
  background-color: var(--down);
}

/* The light on the down stays put while the page scrolls. A fixed layer rather
   than background-attachment: fixed, which iOS ignores and which smears the
   gradient over the full height of a long page. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* The down: two noise tiles laid over the light. They were live SVG
     feTurbulence filters until 27 Sep: a phone recalculated the whole-window
     noise on every repaint, and a tap on the face took 1.5 s to answer. Now
     they are pictures of the same filters (seeds 7 and 3, opacities .42 and
     .22 baked into their alpha), rendered with stitchTiles so the repeats
     have no seams. The fine tile comes at 1x and 2x so its grain matches the
     old filter on both kinds of screen; the first line is for browsers
     without image-set (Safari before 17). site/make_down.py remakes them. */
  background:
    url("/img/down-fine-2x.webp") 0 0 / 256px 256px repeat,
    url("/img/down-clumps.webp") 0 0 / 1024px 1024px repeat,
    radial-gradient(120% 90% at 50% 12%, var(--down-light) 0%, var(--down) 46%, var(--down-deep) 100%);
  background:
    image-set(url("/img/down-fine-1x.webp") 1x, url("/img/down-fine-2x.webp") 2x) 0 0 / 256px 256px repeat,
    url("/img/down-clumps.webp") 0 0 / 1024px 1024px repeat,
    radial-gradient(120% 90% at 50% 12%, var(--down-light) 0%, var(--down) 46%, var(--down-deep) 100%);
}

header.top, main, footer { position: relative; z-index: 1; width: 100%; max-width: var(--measure); margin-left: auto; margin-right: auto; }
main { flex: 1; }

a { color: var(--ink); text-underline-offset: .18em; text-decoration-thickness: 2px; }
a:hover { color: var(--bill); }
:focus-visible { outline: 3px solid var(--bill); outline-offset: 3px; }

/* ---------------------------------------------------------------- header */

header.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 0 10px;
}

.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; }
.brand img { width: 56px; height: 56px; display: block; }
.brand span {
  font-family: "Rubik Puddles", ui-sans-serif, system-ui, sans-serif;
  font-size: 1.35rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  line-height: 1;
  -webkit-text-stroke: .03em currentColor;
  paint-order: stroke fill;
}
.brand:hover { color: var(--ink); }
.brand:hover img { transform: rotate(-8deg); }
.brand img { transition: transform .2s; }

nav.links { display: flex; gap: 18px; font-weight: 600; }
nav.links a { text-decoration: none; border-bottom: 3px solid transparent; }
nav.links a:hover, nav.links a[aria-current="page"] { border-bottom-color: currentColor; color: var(--ink); }

/* ----------------------------------------------------------- type */

.wordmark {
  font-family: "Rubik Puddles", ui-sans-serif, system-ui, sans-serif;
  font-weight: 400;           /* the face has one weight, so weight comes from the stroke */
  line-height: 1;
  letter-spacing: .22em;      /* the stroke fattens the letters, so they need the room back */
  -webkit-text-stroke: .03em currentColor;
  paint-order: stroke fill;
  text-transform: uppercase;
  margin: 0;
}
.wordmark .bill { color: var(--bill); }

.line {
  font-family: "Syne", ui-sans-serif, system-ui, sans-serif;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0;
}

h2 {
  font-family: "Syne", ui-sans-serif, system-ui, sans-serif;
  font-weight: 800;
  font-size: 1.6rem;
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0 0 14px;
}

h3 { font-size: 1.05rem; font-weight: 600; margin: 0 0 4px; }

p { margin: 0 0 14px; }
p:last-child { margin-bottom: 0; }

.tag {
  display: inline-block;
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-weight: 600;
  font-size: .8rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: 3px 10px 2px;
  border: 3px solid var(--ink);
  background: var(--paper);
  white-space: nowrap;
}
.tag.free { background: var(--teal); color: #fff; border-color: var(--ink); }
.tag.soon { background: var(--ink); color: var(--down); }   /* not out yet: Doup, 27 Sep */

/* ----------------------------------------------------------- blocks */

.slab {
  background: var(--paper);
  border: 3px solid var(--ink);
  box-shadow: 6px 6px 0 var(--ink);
  padding: 22px 24px;
}

section { margin: 0 0 44px; }

/* ----------------------------------------------------------- home */

.hero { padding: 40px 0 30px; }
.hero .wordmark { font-size: clamp(3rem, 13vw, 7.2rem); margin-bottom: 22px; }
.hero .line { font-size: clamp(1.15rem, 3.8vw, 1.5rem); max-width: 26ch; }

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr)); gap: 26px; }   /* two across at full width: four cards sit two by two */

.card {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  background: var(--paper);
  border: 3px solid var(--ink);
  box-shadow: 6px 6px 0 var(--ink);
  transition: transform .12s, box-shadow .12s;
}
.card:hover { color: var(--ink); transform: translate(-2px, -2px); box-shadow: 8px 8px 0 var(--ink); }
.card:active { transform: translate(3px, 3px); box-shadow: 3px 3px 0 var(--ink); }

.card .pic { aspect-ratio: 5 / 4; overflow: hidden; border-bottom: 3px solid var(--ink); background: #fff; }
.card .pic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.card .pic img.top { object-position: 50% 0; }   /* a taller face whose point is at the top (Gasp's eye) */
.card .words { padding: 16px 18px 18px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.card .name {
  font-family: "Rubik Puddles", ui-sans-serif, system-ui, sans-serif;
  font-size: 2rem;
  line-height: 1.05;
  letter-spacing: .12em;
  text-transform: uppercase;
  -webkit-text-stroke: .03em currentColor;
  paint-order: stroke fill;
}
.card .name.long { font-size: min(2rem, 6.6vw); }   /* Trendelenburg: one word, no place to wrap */
.card .tags { display: flex; gap: 8px; flex-wrap: wrap; margin-top: auto; padding-top: 6px; }

.more { margin-top: 26px; font-weight: 600; }
h2.group { margin-top: 40px; }   /* the second group of cards on the home page */

/* A paid plugin's tag is the plain .tag -- ink on paper. Teal stays the free
   one's alone, so the two read apart at a glance. */

/* ----------------------------------------------------------- forms */

form.ask { display: flex; gap: 10px; flex-wrap: wrap; margin: 0 0 10px; }

form.ask input[type="email"] {
  flex: 1 1 14rem;
  min-width: 0;
  background: rgba(255,252,236,.75);
  border: 3px solid var(--ink);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  padding: 13px 15px;
  border-radius: 0;
}
form.ask input::placeholder { color: rgba(23,21,15,.5); font-weight: 500; }

button {
  background: var(--ink);
  color: var(--down);
  border: 3px solid var(--ink);
  font: inherit;
  font-weight: 800;
  padding: 13px 24px;
  border-radius: 0;
  cursor: pointer;
}
button:hover { background: var(--bill); border-color: var(--bill); }
button[disabled] { opacity: .5; cursor: default; background: var(--ink); border-color: var(--ink); }

.note { font-weight: 600; margin: 0; min-height: 1.55em; }
.note.bad { color: var(--rust); }

/* What a signup is for, beside every form (27 Sep): consent has to be read
   before it is given, so it sits under the button, not behind a link. */
.consent { font-size: .88rem; line-height: 1.45; margin: 0 0 6px; max-width: 46ch; }

/* Turnstile's tick box (27 Sep), on its own row under the field and button.
   Its iframe draws itself; this only gives it the row and keeps an empty one
   from taking space before the script arrives. */
form.ask .turnstile { flex: 1 1 100%; max-width: 100%; }
form.ask .turnstile:empty { display: none; }

.downloads { display: flex; flex-wrap: wrap; gap: 10px; margin: 6px 0 0; padding: 0; list-style: none; }
.downloads a {
  display: inline-block; text-decoration: none; font-weight: 800;
  border: 3px solid var(--ink); padding: 10px 16px; background: var(--down-light);
}
.downloads a:hover { background: var(--ink); color: var(--down); }

.signup { max-width: 640px; }
.signup .line { font-size: 1.25rem; margin-bottom: 16px; }

/* ----------------------------------------------------------- plugin page */

/* The picture does the talking: one column, the face as large as the page
   allows, then a name, one line and the form. Nothing explains the plugin. */
.object { max-width: 680px; margin: 0 auto; padding: 22px 0 40px; text-align: center; }

.face { margin: 0 0 34px; }
.face .frame { border: 3px solid var(--ink); box-shadow: 8px 8px 0 var(--ink); background: #fff; line-height: 0; }
.face img, .face video { width: 100%; height: auto; display: block; }
/* The face answers nothing, so a tap on it should cost nothing: no tap
   highlight to paint, and no hit on the video at all unless it has controls
   (the reduced-motion case, where site.js gives it play controls). */
.face video { -webkit-tap-highlight-color: transparent; }
.face video:not([controls]) { pointer-events: none; }

.object .wordmark { font-size: clamp(3rem, 12vw, 5.6rem); letter-spacing: .14em; margin: 0 0 16px; }
.object .wordmark.long { font-size: clamp(1.5rem, 7.4vw, 3.8rem); }   /* one word too long to wrap (Trendelenburg) */
.object .line { font-size: clamp(1.15rem, 3vw, 1.45rem); max-width: 30ch; margin: 0 auto 18px; }

.meta { display: flex; justify-content: center; align-items: center; gap: 14px; flex-wrap: wrap; margin: 0 0 30px; }
.controls-named { font-weight: 600; font-size: .85rem; letter-spacing: .14em; text-transform: uppercase; opacity: .7; }

.object .get { text-align: left; max-width: 520px; margin: 0 auto 22px; padding: 18px 20px 14px; }
.object .get form.ask { margin-bottom: 6px; }

.formats { font-size: .82rem; font-weight: 600; letter-spacing: .06em; opacity: .65; line-height: 1.6; }

/* ----------------------------------------------------------- about */

.page-head { padding: 34px 0 26px; }
.page-head .wordmark { font-size: clamp(2.6rem, 9vw, 4.6rem); letter-spacing: .14em; margin-bottom: 14px; }
.page-head .line { font-size: clamp(1.1rem, 2.6vw, 1.35rem); max-width: 36ch; }

.prose { max-width: 700px; }

.faq details { border-top: 3px solid var(--ink); padding: 14px 0; }
.faq details:last-child { border-bottom: 3px solid var(--ink); }
.faq summary { font-weight: 600; font-size: 1.05rem; cursor: pointer; list-style: none; display: flex; justify-content: space-between; gap: 16px; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; font-family: "Syne", sans-serif; font-weight: 800; font-size: 1.3rem; line-height: 1; }
.faq details[open] summary::after { content: "\2013"; }
.faq details p { margin: 10px 0 0; max-width: 64ch; }

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

footer {
  display: flex; flex-wrap: wrap; gap: 10px 24px; justify-content: space-between; align-items: center;
  font-size: .9rem; font-weight: 600; padding-top: 22px; border-top: 3px solid var(--ink);
}
footer nav { display: flex; gap: 18px; flex-wrap: wrap; }

/* ----------------------------------------------------------- small screens */


@media (max-width: 520px) {
  body { padding: 0 16px 24px; }
  .brand img { width: 46px; height: 46px; }
  .brand span { font-size: 1.05rem; letter-spacing: .1em; }
  nav.links { gap: 14px; }
  .slab { padding: 18px 18px; box-shadow: 4px 4px 0 var(--ink); }
  .card, .face .frame { box-shadow: 4px 4px 0 var(--ink); }
  button { width: 100%; }
}

@media (max-width: 400px) {
  .brand span { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .card, .brand img { transition: none; }
}

/* The buy button on a paid plugin's page: the same button, full width, above
   the email form (which becomes the 7-day trial once a release is out). */
button.buy { display: block; width: 100%; margin: 0 0 6px; }
.get .note#buy-note:empty { display: none; }

/* Direct downloads on a plugin's page (25 Sep): Windows first, from R2. */
.get .dl-head { margin: 0 0 4px; font-weight: 800; }
.get .downloads { margin: 0 0 6px; }
.get .dl-os { margin: 8px 0 2px; font-size: .9em; font-weight: 700; }
.get .dl-soon { margin: 0 0 14px; font-size: .9em; opacity: .8; }

/* What each plugin is, in plain words, under its name (Paul, 25 Sep). */
.kind { font-weight: 800; letter-spacing: .06em; text-transform: uppercase; font-size: .85rem; opacity: .75; }
.object .kind { margin: -6px 0 12px; }
.card .kind { margin: 2px 0 6px; }

/* A heading screen readers need but the page does not show. */
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* A plugin page's plain description, under the download box (Doup, 26 Sep). */
