/* wetland.io — the whole look of the site lives in this one file.
   It uses your computer's normal fonts and colors and follows light/dark mode.
   This is a friendly place to experiment: change a number or a color, save,
   and refresh the page to see what happens. You can't break anything permanent. */

:root {
  color-scheme: light dark;
  --accent: SeaGreen;        /* the site's one highlight color — try changing it! */
  --gap: 14px;
  /* Form + panel surfaces, spelled out as real colors so they follow dark mode
     reliably. Safari renders the CSS "Field"/"Canvas" system keywords light even
     on a dark page, which left the text boxes stark white. */
  --field-bg: #ffffff;
  --field-fg: #1c1c1e;
  --field-border: #c6c6c8;
  --field-ph: #8e8e93;
  --panel-bg: #f2f2f7;
}
@media (prefers-color-scheme: dark) {
  :root {
    --field-bg: #1c1c1e;
    --field-fg: #ececed;
    --field-border: #3a3a3c;
    --field-ph: #8e8e93;
    --panel-bg: #2c2c2e;
  }
}

body {
  font-family: system-ui, sans-serif;
  line-height: 1.4;
  max-width: 1100px;
  margin: 0 auto;
  padding: 1rem;
}

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

/* The `hidden` attribute must win even over flex/block display rules below. */
[hidden] { display: none !important; }

/* ---- header ------------------------------------------------------------- */
header.site { margin: 0 0 1rem; }
header.site h1 { font-size: 1.2rem; margin: 0; }
header.site h1 a { color: inherit; text-decoration: none; }

/* The wordmark: DOS Rebel figlet art of the site name (see WORDMARK in index.js).
   It uses the page's own ink colour, so it follows light/dark mode for free. Like
   bitchat.free's banner it's a bounded block, capped at 530px and left-aligned in
   the column so it lines up with the tagline below. The fit script sizes the art
   to fill that box; `overflow: hidden` keeps the unscaled 12px fallback tidy if
   that script never runs. */
header.site h1.wordmark { max-width: 530px; line-height: 1; }
header.site h1.wordmark a { display: block; }
.banner {
  margin: 0; font-size: 12px; line-height: 1.06; white-space: pre; overflow: hidden;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; color: inherit;
}
/* A hidden copy of the wordmark, laid out at a fixed size purely so its width can
   be measured (the fit script divides the header width by it). Off-screen, not
   `display:none`, because a hidden element has no measurable width. */
.measure {
  position: absolute; left: -99999px; top: 0; visibility: hidden;
  font-size: 100px; line-height: 1.06; white-space: pre;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

header.site .tagline { font-size: .9rem; opacity: .8; margin: .6rem 0 0; }
/* Site links get their own row below the tagline, in the normal link colour. */
header.site .sitelinks { display: flex; flex-wrap: wrap; gap: .9rem; margin: .35rem 0 0; font-size: .82rem; }
header.site .sitelinks a { color: var(--accent); text-decoration: none; }
header.site .sitelinks a:hover { text-decoration: underline; }

/* ---- home feed: a masonry of tiles (ported from the old gallery) --------- */
/* No-JS fallback is CSS columns; with JS the tiles flow into balanced columns. */
.gallery { column-width: 250px; column-gap: var(--gap); }
.gallery.masonry { column-width: auto; display: flex; align-items: flex-start; gap: var(--gap); }
.gallery.masonry .col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--gap); }
@media (max-width: 560px) {
  .gallery { column-width: auto; column-count: 2; column-gap: 10px; }
  .gallery.masonry, .gallery.masonry .col { gap: 10px; }
}

.work {
  display: block;
  width: 100%;
  break-inside: avoid;
  margin: 0 0 var(--gap);
  text-decoration: none;
  color: inherit;
}
.gallery.masonry .work { margin: 0; }
.work figure { margin: 0; }
.work img { width: 100%; height: auto; display: block; border-radius: 4px; }
.work figcaption { padding: .25rem 0 0; font-size: .85rem; }
.work figcaption small { display: block; opacity: .6; }

/* a text-only post (no picture) still gets a tile */
.work.textonly { border: 1px solid color-mix(in srgb, currentColor 20%, transparent); border-radius: 6px; padding: .6rem .7rem; }
.work.textonly p { margin: .3rem 0 0; font-size: .85rem; opacity: .8; }

/* little play triangle on video tiles */
.work .play { position: relative; display: block; }
.work .play::after {
  content: "\25B6";
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  font-size: 2rem; color: #fff; text-shadow: 0 0 6px rgba(0,0,0,.8);
}

/* ---- one post page ------------------------------------------------------ */
nav.crumb { font-size: .9rem; margin: 0 0 1rem; opacity: .8; }
nav.crumb a { color: inherit; }
.post h1 { margin: 0 0 .3rem; }
.post .when { font-size: .85rem; opacity: .6; margin: 0 0 1rem; }
/* A post picture never grows taller than the viewport, and is held a little
   under full height so the next picture peeks in at the bottom (a cue that there
   is more to scroll to). width/height stay auto so the aspect ratio is kept. */
.post img { max-width: 100%; max-height: 82vh; width: auto; height: auto; display: block; margin: 0 0 var(--gap); border-radius: 4px; }
.post .embed { position: relative; padding-top: 56.25%; margin: 0 0 var(--gap); }
.post .embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.post .body { max-width: 62ch; }
.post .body p { margin: 0 0 .8rem; }
.post .links { margin: 1.2rem 0 0; }
.post dl.meta { display: grid; grid-template-columns: max-content 1fr; gap: .15rem .75rem; font-size: .9rem; margin: 1rem 0; }
.post dl.meta dt { opacity: .6; }
.post dl.meta dd { margin: 0; }

/* Previous / next post. Bare ← → arrows sitting at the top of the header, pinned
   to the left and right edges so they stay in the same place on every post (the
   ← → arrow keys, wired up on the post page, do the same two moves): left goes to
   the newer post, right to the older one. */
.postnav { display: flex; gap: 1rem; margin: 0 0 1.1rem; font-size: 1.2rem; line-height: 1; }
.postnav a { color: var(--accent); text-decoration: none; padding: .1rem .2rem; }
.postnav a:hover { opacity: .65; }
.postnav .prev { margin-right: auto; }
.postnav .next { margin-left: auto; }

/* Desktop: offset the title, date, meta and prev/next into a sticky sidebar and
   let the pictures run full-height down the main column (scroll down for more).
   The grid is a single tall row, so the sidebar can stay put (sticky) while the
   pictures scroll past it. Below 900px it collapses back to one column. */
@media (min-width: 900px) {
  .post {
    display: grid;
    grid-template-columns: minmax(200px, 260px) minmax(0, 1fr);
    column-gap: clamp(2rem, 4vw, 3.5rem);
    align-items: start;
  }
  .post-head { grid-column: 1; position: sticky; top: 1rem; align-self: start; }
  .post-main { grid-column: 2; min-width: 0; }
  /* keep the prose easy to read, but let the pictures fill the column and reach
     full height rather than being boxed to the text measure */
  .post-main .body { max-width: none; }
  .post-main .body :is(p, h1, h2, h3, ul, ol, blockquote) { max-width: 62ch; }
}

/* ---- forms and buttons (login + compose) -------------------------------- */
.card { max-width: 42rem; }
label.field { display: block; margin: 0 0 .9rem; font-size: .9rem; }
label.field span { display: block; opacity: .7; margin: 0 0 .2rem; }
input[type=text], input[type=password], input[type=date], input[type=search], textarea {
  font: inherit; width: 100%; box-sizing: border-box;
  padding: .4rem .5rem; border: 1px solid var(--field-border); border-radius: 5px;
  background: var(--field-bg); color: var(--field-fg);
}
input::placeholder, textarea::placeholder { color: var(--field-ph); }
textarea { min-height: 9rem; resize: vertical; }
button, .btn {
  font: inherit; cursor: pointer; padding: .45rem .9rem;
  border: 1px solid var(--accent); border-radius: 6px;
  background: var(--accent); color: #fff; text-decoration: none;
}
button.ghost, .btn.ghost { background: transparent; color: var(--accent); }
.row { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
.hint { font-size: .8rem; opacity: .6; }
.error { color: Crimson; font-size: .9rem; }

/* ---- /admin homescreen: a grid of apps ---------------------------------- */
/* Each tile carries its own --tint (set inline in home.js). The plain
   background is a fallback for browsers without color-mix. */
.springboard {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(86px, 1fr));
  gap: 1.2rem .5rem; max-width: 34rem; margin: 1.4rem 0 0;
}
.app { display: flex; flex-direction: column; align-items: center; gap: .45rem; text-decoration: none; color: inherit; }
.app .glyph {
  width: 58px; height: 58px; border-radius: 15px; display: grid; place-items: center;
  color: var(--tint, var(--accent));
  background: var(--panel-bg);
  background: color-mix(in srgb, var(--tint, var(--accent)) 14%, var(--panel-bg));
  border: 1px solid color-mix(in srgb, var(--tint, var(--accent)) 28%, transparent);
  transition: transform .12s ease;
}
.app:hover .glyph { transform: translateY(-2px); }
.app:active .glyph { transform: scale(.94); }
.app svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.app .name { font-size: .78rem; line-height: 1.2; text-align: center; opacity: .85; }
@media (prefers-reduced-motion: reduce) { .app .glyph { transition: none; } }

/* ---- /media-dl: paste a link, pick a shelf, watch it land --------------- */
.dl-ask { display: flex; gap: .6rem; margin: 1.2rem 0 .4rem; max-width: 42rem; }
.dl-ask input { flex: 1; }
.dl-preview { max-width: 42rem; margin: 1rem 0 0; }
.dl-card {
  display: flex; gap: .9rem; align-items: flex-start;
  background: var(--panel-bg); border-radius: 10px; padding: .8rem; margin: 0 0 .8rem;
}
.dl-card img { width: 96px; height: 96px; object-fit: cover; border-radius: 6px; flex: none; }
.dl-meta { display: flex; flex-direction: column; gap: .25rem; min-width: 0; }
.dl-meta small { opacity: .7; }
.dl-jobs { max-width: 42rem; margin: 1.6rem 0 0; display: flex; flex-direction: column; gap: .7rem; }
.dl-job { background: var(--panel-bg); border-radius: 10px; padding: .7rem .8rem; display: flex; flex-direction: column; gap: .4rem; }
.dl-job-head { display: flex; gap: .6rem; align-items: baseline; justify-content: space-between; }
.dl-job-head strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dl-job-head small { opacity: .65; flex: none; }
/* State classes are prefixed: a bare .error here would pick up the site's own
   .error utility and repaint the whole row. */
.dl-job.dl-error .dl-job-head small { color: Crimson; opacity: 1; }
.dl-job.dl-done .dl-job-head small { color: var(--accent); opacity: 1; }
.dl-bar { height: 6px; border-radius: 3px; background: var(--field-border); overflow: hidden; }
.dl-bar span { display: block; height: 100%; background: var(--accent); transition: width .4s ease; }
@media (prefers-reduced-motion: reduce) { .dl-bar span { transition: none; } }
@media (max-width: 460px) { .dl-ask { flex-wrap: wrap; } .dl-ask input { min-width: 100%; } }

/* the strip of images you've added while composing */
#images { display: flex; flex-wrap: wrap; gap: .5rem; margin: .3rem 0 .6rem; }
#images figure { margin: 0; width: 120px; }
#images img { width: 120px; height: 90px; object-fit: cover; border-radius: 4px; display: block; }
#images input { width: 100%; font-size: .75rem; margin-top: .2rem; }
.uploader { border: 1px dashed GrayText; border-radius: 6px; padding: .7rem; margin: 0 0 .9rem; }

/* ---- captions under pictures (post page + inline photos) ----------------- */
/* Body figures come through the HTML sanitizer as a plain <figure> (the editor's
   class is stripped), so target the bare element, not figure.inline — otherwise
   the browser default 40px figure indent would push in-body photos to the right
   of the lead image instead of lining their left edges up. */
.post figure.lead, .post .body figure { margin: 0 0 var(--gap); }
.post figure figcaption, .post .body figcaption {
  font-size: .8rem; opacity: .65; padding: .25rem 0 0; max-width: 62ch;
}
.post .body figure img { margin: 0 0 .25rem; }

/* ---- the rich-text (WYSIWYG) editor ------------------------------------- */
.editor { border: 1px solid var(--field-border); border-radius: 6px; margin: 0 0 .9rem; overflow: hidden; }
.toolbar { display: flex; flex-wrap: wrap; gap: .2rem; padding: .35rem; border-bottom: 1px solid color-mix(in srgb, currentColor 15%, transparent); background: var(--panel-bg); }
.toolbar button {
  font: inherit; min-width: 2rem; padding: .2rem .45rem; cursor: pointer;
  background: var(--field-bg); color: var(--field-fg); border: 1px solid transparent; border-radius: 4px;
}
.toolbar button:hover { border-color: var(--accent); }
.toolbar button[disabled] { opacity: .4; cursor: default; }
.toolbar .toggle { margin-left: auto; }
.codeview {
  display: block; width: 100%; min-height: 11rem; box-sizing: border-box;
  padding: .6rem .7rem; border: 0; background: var(--field-bg); color: var(--field-fg);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .8rem;
  line-height: 1.5; resize: vertical; outline: none;
}
.editable {
  min-height: 11rem; padding: .6rem .7rem; background: var(--field-bg); color: var(--field-fg);
  line-height: 1.5; outline: none;
}
.editable:focus { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent); }
.editable h1 { font-size: 1.5rem; margin: .4rem 0; }
.editable h2 { font-size: 1.25rem; margin: .4rem 0; }
.editable h3 { font-size: 1.05rem; margin: .4rem 0; }
.editable figure.inline { margin: .4rem 0; }
.editable figure.inline img { max-width: 220px; height: auto; border-radius: 4px; display: block; }
.editable figcaption { font-size: .8rem; opacity: .6; }

/* ---- picture cards in the compose screen -------------------------------- */
#images { display: flex; flex-wrap: wrap; gap: .8rem; margin: .5rem 0 1rem; }
#images .imgcard { margin: 0; width: 232px; display: flex; flex-direction: column; gap: .5rem; border: 1px solid color-mix(in srgb, currentColor 18%, transparent); border-radius: 10px; padding: .6rem; }
/* the chosen cover gets a clear accent ring */
#images .imgcard:has(input[name=cover_key]:checked) { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
/* show the whole photo (letterboxed, never cropped), but cap how tall it gets */
#images .imgcard img { width: 100%; height: auto; max-height: 300px; object-fit: contain; border-radius: 7px; display: block; background: color-mix(in srgb, currentColor 7%, transparent); }
#images .imgcard input[type=text] { width: 100%; font: inherit; font-size: .85rem; padding: .4rem .5rem; }
.imgcard-btns { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; }
.imgcard-btns .ghost { padding: .4rem .7rem; font-size: .8rem; }
/* cover toggle: an outlined pill that fills solid when this photo is the cover */
.coverpick { display: inline-flex; align-items: center; gap: .3rem; cursor: pointer; font-size: .8rem; padding: .4rem .7rem; border: 1px solid var(--accent); border-radius: 7px; color: var(--accent); white-space: nowrap; user-select: none; }
.coverpick input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.coverpick:has(input:checked) { background: var(--accent); color: #fff; font-weight: 600; }

/* ---- image studio ------------------------------------------------------- */
.studio { border: 1px solid color-mix(in srgb, currentColor 15%, transparent); border-radius: 8px; padding: 1rem 1.1rem; margin: 0 0 1.25rem; }
.studio h3 { margin: 0 0 .3rem; }
.studio textarea { min-height: 5.5rem; }
.studio-result { max-width: 100%; height: auto; border-radius: 6px; display: block; margin: .6rem 0; }
#ai-input-preview { max-width: 220px; height: auto; border-radius: 4px; margin: .3rem 0; }
.palette-row { display: flex; align-items: center; flex-wrap: wrap; gap: .4rem; margin: .3rem 0 .6rem; }
.swatch { display: inline-flex; align-items: center; }
.swatch input[type=color] { width: 30px; height: 26px; padding: 0; border: 1px solid GrayText; border-radius: 4px; background: none; cursor: pointer; }
.swatch button { font: inherit; border: none; background: none; cursor: pointer; opacity: .5; padding: 0 .15rem; }
.swatch button:hover { opacity: 1; }
#d-canvas { background: repeating-conic-gradient(color-mix(in srgb, currentColor 12%, transparent) 0% 25%, transparent 0% 50%) 50% / 20px 20px; }
#d-canvas[width="0"] { display: none; }

/* ---- media library picker (compose) ------------------------------------- */
.lib-modal { width: min(760px, 94vw); max-height: 82vh; border: 1px solid var(--field-border); border-radius: 10px; padding: 0; background: var(--panel-bg); color: var(--field-fg); }
.lib-modal::backdrop { background: rgba(0, 0, 0, .45); }
.lib-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .7rem 1rem; border-bottom: 1px solid color-mix(in srgb, currentColor 15%, transparent); position: sticky; top: 0; background: var(--panel-bg); }
.lib-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: .5rem; padding: 1rem; overflow-y: auto; }
.lib-thumb { padding: 0; border: 1px solid color-mix(in srgb, currentColor 15%, transparent); border-radius: 6px; background: none; cursor: pointer; overflow: hidden; aspect-ratio: 1; }
.lib-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.lib-thumb:hover { border-color: var(--accent); }

/* ---- newsletter subscribe form + home footer --------------------------- */
.subscribe { display: flex; gap: .5rem; flex-wrap: wrap; margin: .6rem 0; max-width: 30rem; }
.subscribe input[type=email] { flex: 1; min-width: 12rem; }
.home-footer { margin: 2.2rem 0 1rem; padding-top: 1.1rem; border-top: 1px solid color-mix(in srgb, currentColor 12%, transparent); }

/* ---- mobile first: bigger tap targets, no iOS zoom-on-focus ------------- */
@media (max-width: 640px) {
  body { padding: .8rem; }
  button, .btn { padding: .6rem 1rem; min-height: 44px; }
  select { min-height: 44px; }
  /* 16px form controls stop iOS from zooming the page when a field is focused */
  input[type=text], input[type=password], input[type=date], input[type=search],
  textarea, select, .imgcard input[type=text], .codeview { font-size: 16px; }
  .row { gap: .5rem; }
  .toolbar button { min-height: 40px; min-width: 2.6rem; }
  /* one photo card per row, filling the phone width, with big tap targets */
  #images .imgcard { width: 100%; }
  #images .imgcard img { max-height: 340px; }
  .imgcard-btns { gap: .45rem; }
  .imgcard-btns .ghost, .coverpick { padding: .45rem .7rem; font-size: .85rem; min-height: 38px; }
  .lib-grid { grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); }
  header.site .sitelinks { font-size: .95rem; }
}

/* ---- admin dashboard list ----------------------------------------------- */
.postlist { list-style: none; padding: 0; margin: 1rem 0; }
.postlist li { display: flex; align-items: center; gap: .7rem; padding: .4rem 0; border-bottom: 1px solid color-mix(in srgb, currentColor 12%, transparent); }
.postlist img { width: 56px; height: 42px; object-fit: cover; border-radius: 3px; }
.postlist .grow { flex: 1; min-width: 0; }
.postlist .grow small { opacity: .55; }
.postlist .draft { font-size: .7rem; border: 1px solid GrayText; border-radius: 4px; padding: 0 .3rem; opacity: .7; }
