/* ==========================================================================
   lists.e-mail.nz — application stylesheet
   No framework, no build step: one file served from public/assets/css.
   The accent colour is overridden per request by a CSS variable in the layout.
   ========================================================================== */

:root {
  --accent: #2563eb;
  --accent-dark: #1d4ed8;
  --bg: #f6f7f9;
  --surface: #ffffff;
  --border: #e3e6ea;
  --text: #16191d;
  --muted: #6b7280;
  --danger: #b42318;
  --danger-bg: #fef3f2;
  --success: #067647;
  --success-bg: #ecfdf3;
  --warning: #b54708;
  --warning-bg: #fffaeb;
  --info-bg: #eff8ff;
  --radius: 9px;
  --shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .1);
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

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

/* ==========================================================================
   Dark mode
   Chosen by the user, remembered in a cookie, and rendered by the server onto
   <html data-theme="...">. Doing it that way rather than in script means the
   first paint is already right: a theme applied only by JavaScript shows a light
   flash to anyone who chose dark, on every single page load.

   Most of the block below overrides the variables. The rules after it restate
   the handful of places that hardcode a light colour instead of using one --
   table headers, input backgrounds, badge borders -- because those are precisely
   the ones that would otherwise stay white.
   ========================================================================== */
[data-theme="dark"] {
  color-scheme: dark;

  --accent: #7cb0ff;
  --accent-dark: #9cc4ff;
  --bg: #0e1116;
  --surface: #161a20;
  --border: #2b323c;
  --text: #e6eaf0;
  --muted: #9aa4b2;
  --danger: #ff9c90;
  --danger-bg: #2b1512;
  --success: #74d9a3;
  --success-bg: #0f2318;
  --warning: #f0b95f;
  --warning-bg: #2a1f0c;
  --info-bg: #101f2e;
  --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 1px 3px rgba(0, 0, 0, .6);
}

[data-theme="dark"] .nav a { color: var(--text); }
[data-theme="dark"] .nav a:hover,
[data-theme="dark"] .btn:hover,
[data-theme="dark"] .btn-ghost:hover,
[data-theme="dark"] .page-link:hover { background: #232a33; }
[data-theme="dark"] .btn { background: #1b2028; color: var(--text); }
[data-theme="dark"] thead th { background: #1b2028; }
[data-theme="dark"] tbody td { border-bottom-color: #232a33; }
[data-theme="dark"] tbody tr:hover { background: #191e25; }
[data-theme="dark"] .badge-muted { background: #232a33; }
/* The base .badge carries a hardcoded pale background and dark text, so a badge
   used without a colour modifier -- <span class="badge">, no badge-success -- was
   left as a light-mode chip on a dark page. */
[data-theme="dark"] .badge { background: #232a33; color: var(--text); }
/* .message-body hardcodes white, so every message read in dark mode was a
   full-width white panel with the dark-mode text colour on it. */
[data-theme="dark"] .message-body { background: #1b2028; }
/* Listed per type, not as a bare `input`: the base rules are input[type=text] and
   friends, which carry the SAME specificity as [data-theme="dark"] input. Equal
   specificity means source order decides, and the base rule is further down the
   file -- so every text field stayed WHITE in dark mode however this was written
   as a plain element selector. */
[data-theme="dark"] input[type=text],
[data-theme="dark"] input[type=email],
[data-theme="dark"] input[type=password],
[data-theme="dark"] input[type=number],
[data-theme="dark"] input[type=url],
[data-theme="dark"] input[type=search],
[data-theme="dark"] select,
[data-theme="dark"] textarea { background: #1b2028; border-color: #3a424e; color: var(--text); }
[data-theme="dark"] pre,
[data-theme="dark"] code { background: #1b2028; }
[data-theme="dark"] .alert-success,
[data-theme="dark"] .badge-success { border-color: #1f6f47; }
[data-theme="dark"] .alert-error,
[data-theme="dark"] .badge-danger { border-color: #7a3b33; }
[data-theme="dark"] .alert-warning,
[data-theme="dark"] .badge-warning { border-color: #7a5c22; }
[data-theme="dark"] .alert-info { border-color: #2a4a6b; color: var(--accent); }

/* The theme toggle: one icon at a time -- a sun while light, a moon while dark.
   A <button> inside a POST form, so it needs no JavaScript; both icons are in the
   markup and CSS shows one, so the button never depends on script to draw itself.
   See ThemeController for why the form matters here. */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--muted);
  cursor: pointer;
}
.theme-toggle:hover { color: var(--text); background: #f3f4f6; }
[data-theme="dark"] .theme-toggle:hover { background: #232a33; }
.theme-toggle svg { width: 16px; height: 16px; }
.theme-toggle .icon-moon { display: none; }
[data-theme="dark"] .theme-toggle .icon-sun { display: none; }
[data-theme="dark"] .theme-toggle .icon-moon { display: block; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

h1, h2, h3, h4 { margin: 0 0 .5em; line-height: 1.25; font-weight: 650; }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.2rem; }
h3 { font-size: 1.02rem; }
p { margin: 0 0 1em; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
hr { border: 0; border-top: 1px solid var(--border); margin: 1.25rem 0; }

.muted { color: var(--muted); }
.small { font-size: .85rem; }
.mono { font-family: var(--mono); font-size: .85em; }
.nowrap { white-space: nowrap; }
.center { text-align: center; }
.right { text-align: right; }
.inline { display: inline; }
.stack > * + * { margin-top: 1rem; }
.row { display: flex; gap: .75rem; flex-wrap: wrap; align-items: center; }
.row-between { display: flex; gap: .75rem; flex-wrap: wrap; align-items: center; justify-content: space-between; }
.grow { flex: 1 1 auto; }

.skip-link {
  position: absolute; left: -9999px;
  background: var(--surface); padding: .5rem .75rem; z-index: 100;
}
.skip-link:focus { left: .5rem; top: .5rem; }

/* ---------------------------------------------------------------- topbar -- */
.topbar { background: var(--surface); border-bottom: 1px solid var(--border); }
.topbar-inner {
  max-width: 1180px; margin: 0 auto; padding: .6rem 1rem;
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: .55rem; font-weight: 650; color: var(--text); }
.brand:hover { text-decoration: none; }
.brand-logo { height: 26px; width: auto; }
.brand-name { font-size: 1rem; }

.nav { display: flex; gap: .25rem; flex-wrap: wrap; flex: 1 1 auto; }
.nav a {
  padding: .4rem .65rem; border-radius: 6px; color: #374151; font-weight: 500; font-size: .93rem;
}
.nav a:hover { background: #f3f4f6; text-decoration: none; }
/* Mixed with the surface rather than white so the pill follows the theme. With
   white it stayed pale in dark mode with the dark-mode accent colour on top of
   it -- an active nav item that looked like a light-mode page leaking through. */
.nav a.active { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent-dark); }

.user-menu { display: flex; align-items: center; gap: .5rem; }
.user-chip { display: flex; align-items: center; gap: .45rem; color: var(--text); }
.user-chip:hover { text-decoration: none; }
.avatar {
  width: 28px; height: 28px; border-radius: 50%; background: var(--accent); color: #fff;
  display: grid; place-items: center; font-size: .72rem; font-weight: 650;
}
.user-email { font-size: .85rem; color: var(--muted); max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.pill {
  display: inline-block; min-width: 1.35em; padding: 0 .35em; border-radius: 999px;
  background: var(--danger); color: #fff; font-size: .72rem; font-weight: 650; text-align: center;
}

/* --------------------------------------------------------------- layout -- */
.container { max-width: 1180px; margin: 0 auto; padding: 1.25rem 1rem 3rem; }
.page-head { margin-bottom: 1.1rem; }
.page-head h1 { margin-bottom: .2rem; }
.page-head .muted { font-size: .92rem; }

.grid { display: grid; gap: 1rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1rem 1.1rem; box-shadow: var(--shadow);
}
.card h2, .card h3 { margin-top: 0; }
.card-tight { padding: .75rem .85rem; }

.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: .85rem 1rem; }
.stat-value { font-size: 1.55rem; font-weight: 650; line-height: 1.1; }
.stat-label { color: var(--muted); font-size: .82rem; text-transform: uppercase; letter-spacing: .04em; }

/* ---------------------------------------------------------------- flash -- */
.flashes { margin-bottom: 1rem; }
.alert { padding: .7rem .9rem; border-radius: var(--radius); border: 1px solid transparent; margin-bottom: .5rem; font-size: .92rem; }
.alert-success { background: var(--success-bg); border-color: #abefc6; color: var(--success); }
.alert-error { background: var(--danger-bg); border-color: #fecdca; color: var(--danger); }
.alert-warning { background: var(--warning-bg); border-color: #fedf89; color: var(--warning); }
.alert-info { background: var(--info-bg); border-color: #b2ddff; color: #175cd3; }

/* --------------------------------------------------------------- tables -- */
.table-wrap { overflow-x: auto; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); }
table { width: 100%; border-collapse: collapse; font-size: .92rem; }
thead th {
  text-align: left; padding: .6rem .75rem; background: #fafbfc; border-bottom: 1px solid var(--border);
  font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); font-weight: 650; white-space: nowrap;
}
tbody td { padding: .6rem .75rem; border-bottom: 1px solid #f0f1f3; vertical-align: top; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: #fcfcfd; }
td.actions { white-space: nowrap; }

.empty { padding: 2rem 1rem; text-align: center; color: var(--muted); }

/* --------------------------------------------------------------- badges -- */
.badge {
  display: inline-block; padding: .1rem .45rem; border-radius: 5px; font-size: .76rem; font-weight: 600;
  border: 1px solid var(--border); background: #f9fafb; color: #374151; white-space: nowrap;
}
/* Surface, not white, for the same reason as .nav a.active: with white the chip
   stayed pale in dark mode while its text took the dark-mode accent colour. */
.badge-accent { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); border-color: color-mix(in srgb, var(--accent) 30%, var(--surface)); color: var(--accent-dark); }
.badge-success { background: var(--success-bg); border-color: #abefc6; color: var(--success); }
.badge-danger { background: var(--danger-bg); border-color: #fecdca; color: var(--danger); }
.badge-warning { background: var(--warning-bg); border-color: #fedf89; color: var(--warning); }
.badge-muted { background: #f3f4f6; color: var(--muted); }

/* -------------------------------------------------------------- buttons -- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .35rem;
  padding: .48rem .8rem; border-radius: 7px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); font-size: .9rem; font-weight: 550;
  cursor: pointer; font-family: inherit; line-height: 1.2; text-decoration: none;
}
.btn:hover { background: #f9fafb; text-decoration: none; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-dark); border-color: var(--accent-dark); }
.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger:hover { background: #93261c; }
.btn-success { background: var(--success); border-color: var(--success); color: #fff; }
.btn-success:hover { background: #055c37; }
.btn-ghost { background: transparent; border-color: transparent; color: var(--muted); }
.btn-ghost:hover { background: #f3f4f6; color: var(--text); }
/* The refresh control sits inside a line of small print, where an inline-flex box
   rests on the baseline and so reads as sitting high beside the text. Middle-align
   it with the count it belongs to. The paginated shape needs nothing: there the
   control is a flex item of .pagination, which already centres its children. */
.refresh-link { vertical-align: middle; }
/* Delete is a <button> inside a <form>, and a form is a block element by default
   -- which pushed the button onto a second line under the View link. Inline keeps
   the two on one row, in this cell and on the messages screen alike, and the
   margin stops them touching now that the button is styled again. */
td.actions form { display: inline; margin-left: .35rem; }
.btn-sm { padding: .3rem .55rem; font-size: .82rem; }
.btn[disabled], .btn.disabled { opacity: .55; cursor: not-allowed; }
.btn-row { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }

/* ---------------------------------------------------------------- forms -- */
.form-grid { display: grid; gap: 1rem; }
.form-grid-2 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.field label, .field .label { display: block; font-weight: 600; font-size: .88rem; margin-bottom: .3rem; }
.field .help { color: var(--muted); font-size: .82rem; margin-top: .25rem; }
.field .error-text { color: var(--danger); font-size: .82rem; margin-top: .25rem; font-weight: 550; }

input[type=text], input[type=email], input[type=password], input[type=number], input[type=url], input[type=search], select, textarea {
  width: 100%; padding: .5rem .6rem; border: 1px solid #cfd4da; border-radius: 7px;
  background: #fff; color: var(--text); font: inherit; font-size: .92rem;
}
input:focus, select:focus, textarea:focus { outline: 2px solid color-mix(in srgb, var(--accent) 40%, white); border-color: var(--accent); }
input[aria-invalid=true], textarea[aria-invalid=true], select[aria-invalid=true] { border-color: var(--danger); }
textarea { min-height: 6rem; resize: vertical; font-family: var(--mono); font-size: .86rem; }
select { appearance: auto; }
.checkbox { display: flex; gap: .5rem; align-items: flex-start; font-size: .92rem; }
.checkbox input { width: auto; margin-top: .2rem; }
.form-actions { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; margin-top: .35rem; }
fieldset { border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem; margin: 0 0 1rem; }
legend { font-weight: 650; font-size: .9rem; padding: 0 .35rem; }

.filter-bar { display: flex; gap: .5rem; flex-wrap: wrap; align-items: flex-end; margin-bottom: 1rem; }
.filter-bar .field { min-width: 160px; }
.filter-bar input, .filter-bar select { min-width: 150px; }

/* ----------------------------------------------------------- pagination -- */
.pagination { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-top: 1rem; flex-wrap: wrap; }
/* The single-page count is a bare <p>, and the p rule above gives it no TOP
   margin, so it sat flush against the table's bottom edge while the paginated
   form had a 1rem gap. Same figure here, so both shapes sit identically -- and so
   the refresh control beside the count is not touching the table frame. */
.item-count { margin-top: 1rem; }
.pagination-links { display: flex; gap: .25rem; align-items: center; flex-wrap: wrap; }
.page-link { padding: .3rem .6rem; border: 1px solid var(--border); border-radius: 6px; background: var(--surface); font-size: .86rem; }
.page-link:hover { background: #f3f4f6; text-decoration: none; }
.page-link.current { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }

/* ---------------------------------------------------------- message view -- */
.message-headers { margin: 0 0 1rem; font-family: var(--mono); font-size: .82rem; }
.message-headers dt { color: var(--muted); margin-top: .35rem; }
.message-headers dd { margin: 0; word-break: break-word; }
.message-body {
  background: #fff; border: 1px solid var(--border); border-radius: var(--radius);
  padding: 1rem; white-space: pre-wrap; word-break: break-word; font-size: .92rem;
}
.message-body-html { white-space: normal; }
pre, code, .pre {
  font-family: var(--mono); font-size: .84rem; background: #f7f8f9; border: 1px solid var(--border);
  border-radius: 7px; padding: .6rem .7rem; overflow-x: auto; white-space: pre-wrap; word-break: break-word;
}

/* --------------------------------------------------------------- public -- */
.public-body { background: var(--bg); }
.public-topbar { padding: 1rem; display: flex; justify-content: center; }
.public-main { max-width: 460px; margin: 0 auto; padding: 1rem 1rem 3rem; }
.public-main-wide { max-width: 900px; }
.public-main .card { padding: 1.35rem 1.4rem; }
.public-hero { text-align: center; margin-bottom: 1.25rem; }
.public-hero h1 { font-size: 1.5rem; }

.footer { border-top: 1px solid var(--border); background: var(--surface); margin-top: 2rem; }
.footer .container { padding: .9rem 1rem; display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; font-size: .85rem; color: var(--muted); }
/* The footer is one line of three parts: the site name, the copyright, and the
   version. Giving the two outer parts equal flex puts the middle part on the
   row's centre line; without it the copyright would only sit between them, which
   is off-centre whenever the two ends differ in width. */
.footer .footer-side { flex: 1 1 auto; }
.footer .footer-middle { flex: 0 0 auto; text-align: center; }

/* ------------------------------------------------------------ responsive -- */
@media (max-width: 720px) {
  .topbar-inner { gap: .5rem; }
  .nav { order: 3; width: 100%; }
  .user-email { display: none; }
  h1 { font-size: 1.3rem; }
}
