/* Space Grotesk (variable, wght 300–700) — SIL OFL 1.1, see assets/fonts/OFL.txt */
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("fonts/space-grotesk-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Space Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("fonts/space-grotesk-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --bg: oklch(15% 0.012 260);
  --paper: oklch(19% 0.013 260);
  --paper-2: oklch(24% 0.02 260);
  --ink: oklch(94% 0.005 260);
  --muted: oklch(62% 0.02 260);
  --line: oklch(30% 0.02 260);
  --blue: oklch(85% 0.19 140);
  --blue-deep: oklch(75% 0.19 140);
  --violet: oklch(60% 0.16 300);
  --grad: linear-gradient(160deg, oklch(90% 0.19 140), oklch(80% 0.19 140));
  --danger: oklch(65% 0.18 25);
  --ok: oklch(70% 0.15 145);
  --radius: 10px;
  --radius-sm: 6px;
  /* Page container: header, main and flash messages share this width. */
  --page-width: 1320px;
  --page-gutter: clamp(1rem, 3vw, 2rem);
  /* Line length for running text inside a full-width card. */
  --measure: 78ch;
  /* Form fields keep a usable size inside a full-width card. */
  --form-width: 64rem;
  --shadow-sm: inset 0 1px 0 oklch(100% 0 0 / 0.04);
  --shadow-md: 0 8px 20px oklch(10% 0.01 260 / 0.35);
  --shadow-lg: 0 22px 48px oklch(5% 0.01 260 / 0.5);
  --focus: 0 0 0 3px oklch(85% 0.19 140 / 0.35);

  /* Derived surfaces and type — same palette, kept in one place. */
  --line-strong: oklch(38% 0.02 260);
  --surface-hover: oklch(27% 0.022 260);
  --sunken: linear-gradient(160deg, oklch(24% 0.02 260), oklch(16% 0.012 260));
  --sunken-inset: inset 0 2px 4px oklch(5% 0.01 260 / 0.6), inset 0 1px 0 oklch(100% 0 0 / 0.03);
  /* Text fields sit on --paper; the inner fade is --sunken. The outline is
     a step darker than muted labels so the box still reads without glowing. */
  --field: oklch(12% 0.012 260);
  --field-line: oklch(48% 0.02 260);
  --placeholder: oklch(72% 0.018 260);
  --raised: linear-gradient(160deg, oklch(24% 0.015 260), oklch(18% 0.012 260));
  --accent-ink: oklch(15% 0.02 140);
  --card-depth: inset 0 1px 0 oklch(100% 0 0 / 0.05), 0 8px 20px oklch(10% 0.01 260 / 0.35);
  --font-display: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, "IBM Plex Mono", "SFMono-Regular", Menlo, monospace;
}

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

html { color-scheme: dark; }

body {
  margin: 0;
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background:
    radial-gradient(900px 480px at 8% -12%, oklch(85% 0.19 140 / 0.07), transparent 60%),
    radial-gradient(800px 420px at 100% -6%, oklch(60% 0.16 300 / 0.09), transparent 55%),
    var(--bg);
  background-attachment: fixed;
  color: var(--ink);
  line-height: 1.55;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--blue); }
a:hover { color: var(--blue-deep); }

code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  color: var(--ink);
  background: var(--paper-2);
  padding: 0.08em 0.35em;
  border-radius: 4px;
  border: 1px solid var(--line);
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.site-header-inner {
  max-width: var(--page-width);
  margin: 0 auto;
  padding: 0.9rem var(--page-gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.site-logo {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  color: var(--ink);
  font-size: 1.05rem;
}
.site-logo:hover { color: var(--blue); }
.site-logo-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.85rem;
  height: 1.85rem;
  border-radius: 0;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
  background: oklch(85% 0.19 140);
  color: oklch(15% 0.01 140);
  box-shadow: none;
}
.site-logo-mark svg { width: 0.9rem; height: 0.9rem; stroke-width: 3; }
.site-nav {
  display: flex;
  align-items: center;
  gap: 1rem;
  font-family: var(--font-display);
  font-size: 0.9rem;
}
.site-nav a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.15s ease;
}
.site-nav a:hover { color: var(--ink); }
.site-nav-menu {
  position: relative;
}
.site-nav-menu > summary {
  list-style: none;
  cursor: pointer;
  color: var(--muted);
}
.site-nav-menu > summary::-webkit-details-marker { display: none; }
.site-nav-menu > summary::marker { content: none; }
.site-nav-menu > summary::after {
  content: " ▾";
  font-size: 0.75em;
}
.site-nav-menu > summary:hover,
.site-nav-menu[open] > summary { color: var(--ink); }
.site-nav-menu-list {
  position: absolute;
  right: 0;
  top: calc(100% + 0.4rem);
  margin: 0;
  padding: 0.35rem;
  min-width: 11rem;
  list-style: none;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  z-index: 30;
}
.site-nav-menu-list a {
  display: block;
  padding: 0.4rem 0.7rem;
  border-radius: 4px;
  white-space: nowrap;
}
.site-nav-menu-list a:hover {
  background: var(--surface-hover);
  color: var(--blue);
}
.site-nav-menu-list a[aria-current="page"] {
  background: oklch(55% 0.16 140 / 0.16);
  color: var(--ink);
  font-weight: 600;
}

/* Hamburger button — hidden above the mobile breakpoint, where the nav is
   a plain row. The bars fold into a cross while the panel is open. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  flex: none;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--paper-2);
  color: var(--ink);
  cursor: pointer;
}
.nav-toggle:hover {
  background: var(--surface-hover);
  border-color: var(--line-strong);
}
.nav-toggle:focus-visible {
  outline: none;
  box-shadow: var(--focus);
}
.nav-toggle-bars {
  position: relative;
  display: block;
  width: 1.15rem;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
}
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  background: currentColor;
}
.nav-toggle-bars::before { top: -0.375rem; }
.nav-toggle-bars::after { top: 0.375rem; }
.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  transition: transform 0.18s ease, background-color 0.18s ease;
}
.site-header[data-nav="open"] .nav-toggle-bars { background: transparent; }
.site-header[data-nav="open"] .nav-toggle-bars::before {
  transform: translateY(0.375rem) rotate(45deg);
}
.site-header[data-nav="open"] .nav-toggle-bars::after {
  transform: translateY(-0.375rem) rotate(-45deg);
}

.site-main {
  flex: 1;
  max-width: var(--page-width);
  width: 100%;
  margin: 0 auto;
  padding: 1.8rem var(--page-gutter) 2.5rem;
}
body.is-public .site-main {
  padding-bottom: 0;
}

.site-footer {
  border-top: 1px solid var(--line);
  padding: 1.4rem var(--page-gutter);
  text-align: center;
  color: var(--muted);
  font-size: 0.85rem;
}
.site-footer p { margin: 0; }

.page-head { margin-bottom: 1.6rem; }
.page-head h1 {
  margin: 0 0 0.4rem;
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 3.2vw, 2.35rem);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
  line-height: 1.18;
}
.page-head .count,
.page-head .lede {
  color: var(--muted);
  margin: 0;
  font-size: 1.05rem;
}
.lede { max-width: 46rem; }

/* --- Home hero: split copy / product preview --- */
.hero {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 2.5rem;
  align-items: center;
  margin-bottom: 2.2rem;
}
.hero-kicker {
  margin: 0 0 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  color: oklch(85% 0.19 140);
}
.hero .lede { max-width: 30rem; }
.hero-preview {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper-2);
  box-shadow: var(--card-depth);
  overflow: hidden;
}
.hero-preview-bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.55rem 0.75rem;
  border-bottom: 1px solid var(--line);
  background: oklch(18% 0.012 260);
}
.hero-preview-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--line-strong);
}
.hero-preview-title {
  margin-left: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--muted);
}
.hero-preview-body {
  padding: 1.4rem 1.1rem 1.2rem;
  text-align: center;
}
.hero-preview-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 5.5rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  background: linear-gradient(160deg, oklch(55% 0.16 140 / 0.12), transparent 65%), oklch(20% 0.015 260);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.hero-preview-pager {
  display: flex;
  justify-content: center;
  gap: 0.4rem;
  margin-top: 0.9rem;
}
.hero-preview-pager i {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--line-strong);
}
.hero-preview-pager i.is-on { background: oklch(85% 0.19 140); }

.hero-image {
  display: block;
  width: 100%;
  height: auto;
}

/* Live demo rotator, front page only: no card chrome, full width. The exact
   height is set by assets/demo-banner.js, which measures the iframe's own
   (same-origin) content once loaded — CSP blocks an inline style attribute,
   so the fixed height here is only the pre-JS fallback. overflow:hidden
   keeps that fallback from showing a scrollbar for the brief moment before
   the script corrects it. */
.demo-banner-strip {
  width: 100%;
  margin-top: 0.6rem;
}
.demo-banner-strip iframe {
  display: block;
  width: 100%;
  height: 142px;
  border: 0;
  overflow: hidden;
}

.home-points {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.2rem;
  margin-bottom: 1.2rem;
}
.home-points .card {
  margin-bottom: 0;
}
.home-points .card p:last-child { margin-bottom: 0; }
.home-point-icon {
  display: inline-flex;
  align-items: center;
  margin-bottom: 0.75rem;
  background: none;
  color: var(--blue);
}
.home-point-icon svg { width: 1.35rem; height: 1.35rem; }
.home-steps {
  margin: 0 0 1rem;
  padding-left: 1.2rem;
}
.home-steps li { margin: 0.35rem 0; }
.home-steps li:last-child { margin-bottom: 0; }
/* Wide viewport: the three steps sit side by side instead of one long column. */
@media (min-width: 900px) {
  .card > .home-steps {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.4rem;
    max-width: none;
    margin-bottom: 1.4rem;
    padding-left: 0;
    list-style: none;
    counter-reset: home-step;
  }
  .home-steps li {
    margin: 0;
    counter-increment: home-step;
  }
  .home-steps li::before {
    content: counter(home-step);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    margin-bottom: 0.5rem;
    border-radius: 50%;
    background: oklch(85% 0.19 140 / 0.16);
    color: oklch(85% 0.19 140);
    font-family: var(--font-mono);
    font-size: 0.8rem;
  }
}

/* Landing-page questions. Two columns once there is room for them, so six
   answers do not push the live demo banner far below the fold. */
.home-faq {
  display: grid;
  gap: 1.1rem 2rem;
}
.home-faq .home-faq-item h3 { margin: 0 0 0.35rem; }
.home-faq-item p {
  margin: 0;
  max-width: var(--measure);
  color: var(--muted);
}
@media (min-width: 900px) {
  .home-faq { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.crumb {
  margin: 0 0 0.8rem;
  font-size: 0.9rem;
  color: var(--muted);
}
.crumb a { text-decoration: none; }

.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem 1.35rem 1.4rem;
  margin-bottom: 1.2rem;
  color: var(--ink);
  box-shadow: var(--card-depth);
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.card:hover {
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.06), var(--shadow-lg);
  border-color: var(--line-strong);
}
.card h2, .card h3 {
  margin: 0 0 0.55rem;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--ink);
}
/* Card heading with an action on the same line (e.g. Existing ads → Add ad). */
.card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem 1rem;
  margin-bottom: 0.55rem;
}
.card-head h2 { margin-bottom: 0; }
.card > p:first-of-type { margin-top: 0; }
/* The container is wide, running text is not — keep the line length readable. */
.card > p,
.card > ul,
.card > ol { max-width: var(--measure); }
.card > p.hero-actions,
.card > p.admin-tip-actions,
.home-points .card > p { max-width: none; }

/* Tinted cards — one accent per home point, a deeper violet wash for wide sections. */
.card-tint-lime {
  background: linear-gradient(160deg, oklch(55% 0.16 140 / 0.16), transparent 60%), var(--paper);
  border-color: oklch(45% 0.1 140 / 0.35);
}
.card-tint-violet {
  background: linear-gradient(160deg, oklch(60% 0.16 300 / 0.16), transparent 60%), var(--paper);
  border-color: oklch(50% 0.12 300 / 0.35);
}
.card-tint-cyan {
  background: linear-gradient(160deg, oklch(65% 0.15 220 / 0.16), transparent 60%), var(--paper);
  border-color: oklch(55% 0.1 220 / 0.35);
}
.card-tint-deep {
  background: linear-gradient(160deg, oklch(28% 0.05 300 / 0.22), var(--paper)), var(--paper);
}
.card-tint-lime .home-point-icon { color: oklch(85% 0.19 140); }
.card-tint-violet .home-point-icon { color: oklch(80% 0.15 300); }
.card-tint-cyan .home-point-icon { color: oklch(80% 0.13 220); }

.auth-card {
  max-width: 34rem;
  margin-left: auto;
  margin-right: auto;
}
/* The helper lines below the form are the card's first <p>, so the generic
   `.card > p:first-of-type` reset would push them flush against the button.
   The doubled class keeps these ahead of that reset on specificity. */
.card.auth-card > form + p,
.card.auth-card > form + form,
.card.auth-card > p + p {
  margin-top: 1.25rem;
  margin-bottom: 0;
}
.card.auth-card > form + form + p { margin-top: 0.9rem; }
/* Keep the heading over the centred sign-in / register card. */
.site-main:has(> .auth-card) .page-head {
  max-width: 34rem;
  margin-left: auto;
  margin-right: auto;
}

.ticket-close-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.ticket-close-card h2 { margin-bottom: 0.2rem; }
.ticket-close-card p { margin: 0; }

.muted { color: var(--muted); }
.rotator-empty {
  padding: 1.5rem 3vw 2.2rem;
  text-align: center;
  color: var(--rotator-muted, var(--muted));
}
.rotator-closed-msg {
  margin: 0;
  font-size: 1.1em;
  font-weight: 600;
  color: var(--rotator-ink, var(--ink, #1c1f24));
}
.rotator-closed-from {
  margin: 0;
  font-size: 0.9em;
  color: var(--rotator-muted, var(--muted, #5c6370));
}
.rotator-closed-from a {
  color: var(--rotator-link, var(--blue, #24468f));
  font-weight: 650;
  text-decoration: underline;
  text-underline-offset: 0.12em;
}
.rotator-closed-from a:hover {
  color: var(--rotator-link-hover, var(--blue-deep, #1a3570));
}

.flash {
  max-width: var(--page-width);
  margin: 0.9rem auto 0;
  padding: 0.7rem 1rem;
  border-radius: var(--radius-sm);
  width: calc(100% - var(--page-gutter) * 2);
}
.flash-success {
  background: oklch(45% 0.1 145 / 0.22);
  color: oklch(86% 0.14 145);
  border: 1px solid oklch(50% 0.12 145 / 0.45);
}
.flash-error {
  background: oklch(45% 0.12 25 / 0.22);
  color: oklch(82% 0.13 25);
  border: 1px solid oklch(52% 0.14 25 / 0.45);
}

.grid-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem 1.2rem;
  align-items: start;
  /* Fields stay a comfortable size even though the card is now full width. */
  max-width: var(--form-width);
}
.grid-form .span2 { grid-column: 1 / -1; }
.grid-form label {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-family: var(--font-display);
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--ink);
}
.grid-form label.checkbox,
.grid-form label.radio {
  flex-direction: row;
  align-items: center;
  font-weight: 400;
  gap: 0.5rem;
}
.grid-form input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]):not([type="color"]),
.grid-form select,
.grid-form textarea {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-weight: 400;
  font-size: 1.05rem;
  padding: 0.9rem 1rem;
  min-height: 3.2rem;
  border: 2px solid var(--field-line);
  border-radius: var(--radius-sm);
  background: var(--sunken);
  box-shadow: var(--sunken-inset);
  color: var(--ink);
  width: 100%;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.grid-form textarea { min-height: 7rem; resize: vertical; }
.grid-form input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]):not([type="color"]):hover:not(:focus):not(:focus-visible),
.grid-form select:hover:not(:focus):not(:focus-visible),
.grid-form textarea:hover:not(:focus):not(:focus-visible) {
  border-color: oklch(58% 0.02 260);
}
/* Same :not() chain as the resting field rule, otherwise that rule wins and
   the lime focus ring never paints. */
.grid-form input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]):not([type="color"]):focus,
.grid-form input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]):not([type="color"]):focus-visible,
.grid-form select:focus,
.grid-form select:focus-visible,
.grid-form textarea:focus,
.grid-form textarea:focus-visible {
  outline: none;
  border-color: var(--blue);
  box-shadow: var(--focus), var(--sunken-inset);
}
/* Native <select> lists often ignore the page color-scheme and paint a light
   menu. The closed field stays light-on-dark; the options must not inherit
   --ink or the labels vanish on white. */
.grid-form select option,
.grid-form select optgroup {
  color-scheme: light;
  background-color: oklch(98% 0.005 260);
  color: oklch(20% 0.012 260);
}
.grid-form select option:checked,
.grid-form select option:hover {
  background-color: oklch(90% 0.04 140);
  color: oklch(18% 0.02 140);
}
.grid-form input::placeholder,
.grid-form textarea::placeholder { color: var(--placeholder); }
.grid-form input[type="file"] {
  padding: 0.5rem 0.65rem;
}
.grid-form input[type="file"]::file-selector-button {
  font-family: var(--font-display);
  font-size: 0.92rem;
  font-weight: 600;
  padding: 0.45rem 0.9rem;
  margin-right: 0.75rem;
  border: 0;
  border-radius: 4px;
  background: var(--grad);
  color: var(--accent-ink);
  cursor: pointer;
}
.grid-form input[type="checkbox"],
.grid-form input[type="radio"] {
  width: auto;
  margin: 0;
  accent-color: var(--blue);
}
.grid-form input[type="range"] {
  accent-color: var(--blue);
  width: 100%;
}

/* Switch: a checkbox drawn as a sliding toggle. The input keeps working as a
   checkbox (keyboard, form value); only its painting is replaced. */
.grid-form label.switch {
  flex-direction: row;
  align-items: center;
  font-weight: 400;
  gap: 0.65rem;
  cursor: pointer;
  width: fit-content;
}
.grid-form label.switch input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  width: 2.9rem;
  height: 1.65rem;
  margin: 0;
  cursor: pointer;
}
.switch-track {
  position: relative;
  flex: none;
  width: 2.9rem;
  height: 1.65rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--sunken);
  box-shadow: inset 0 2px 4px oklch(5% 0.01 260 / 0.6);
  transition: background 0.15s ease, border-color 0.15s ease;
}
.switch-track::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0.18rem;
  width: 1.2rem;
  height: 1.2rem;
  border-radius: 50%;
  background: oklch(80% 0.01 260);
  transform: translate(0, -50%);
  transition: transform 0.15s ease, background 0.15s ease;
}
.switch input[type="checkbox"]:checked + .switch-track {
  background: var(--grad);
  border-color: var(--blue-deep);
}
.switch input[type="checkbox"]:checked + .switch-track::after {
  background: var(--accent-ink);
  transform: translate(1.22rem, -50%);
}
.switch input[type="checkbox"]:focus-visible + .switch-track {
  outline: none;
  border-color: var(--blue);
  box-shadow: var(--focus);
}
.switch input[type="checkbox"]:disabled + .switch-track { opacity: 0.6; }
.switch input[type="checkbox"]:disabled ~ .switch-text { opacity: 0.6; }
.switch-text { font-family: var(--font-display); }
.switch-saving {
  font-size: 0.85rem;
  color: var(--muted);
}
@media (prefers-reduced-motion: reduce) {
  .switch-track,
  .switch-track::after { transition: none; }
}
.grid-form input[type="color"] {
  height: 3.2rem;
  width: 100%;
  max-width: 8rem;
  padding: 0.25rem;
  cursor: pointer;
  border-radius: var(--radius-sm);
  border: 2px solid var(--field-line);
  background: var(--field);
}
.grid-form button,
.btn {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 600;
  padding: 0.85rem 1.25rem;
  min-height: 3rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--grad);
  color: var(--accent-ink);
  text-decoration: none;
  cursor: pointer;
  box-shadow:
    0 1px 0 oklch(100% 0 0 / 0.5) inset,
    0 10px 22px oklch(85% 0.19 140 / 0.35),
    0 2px 4px oklch(10% 0.01 260 / 0.4);
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
.grid-form button:hover,
.btn:hover {
  color: var(--accent-ink);
  filter: brightness(1.08);
  transform: translateY(-1px);
  box-shadow:
    0 1px 0 oklch(100% 0 0 / 0.5) inset,
    0 14px 28px oklch(85% 0.19 140 / 0.42),
    0 2px 4px oklch(10% 0.01 260 / 0.4);
}
.grid-form button:active,
.btn:active {
  transform: translateY(0);
  filter: brightness(0.98);
}
.grid-form button:focus-visible,
.btn:focus-visible {
  outline: none;
  box-shadow: var(--focus);
}
/* `.grid-form button` would otherwise win on specificity and paint a delete
   button in the primary accent. */
.btn-danger,
.grid-form .btn-danger {
  background: linear-gradient(160deg, oklch(26% 0.04 25), oklch(19% 0.025 25));
  color: oklch(80% 0.13 25);
  border: 1px solid oklch(45% 0.1 25 / 0.5);
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 600;
  padding: 0.6rem 1rem;
  min-height: 2.6rem;
  border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.05);
  cursor: pointer;
}
.btn-danger:hover,
.grid-form .btn-danger:hover {
  background: linear-gradient(160deg, oklch(32% 0.06 25), oklch(23% 0.035 25));
  color: oklch(88% 0.13 25);
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.05);
  transform: none;
}
.btn-danger:focus-visible,
.grid-form .btn-danger:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px oklch(65% 0.18 25 / 0.35);
}

.rotator-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
  align-items: center;
}
.rotator-tabs a,
.rotator-tabs .rotator-tab-add {
  display: inline-block;
  padding: 0.4rem 0.8rem;
  border-radius: 4px;
  text-decoration: none;
  border: 1px solid var(--line);
  color: var(--ink);
  background: var(--raised);
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 600;
  min-height: 0;
  cursor: pointer;
}
.rotator-tabs a:hover,
.rotator-tabs .rotator-tab-add:hover {
  background: var(--surface-hover);
  color: var(--blue);
  border-color: var(--line-strong);
}
.rotator-tabs a[aria-current="page"] {
  background: var(--grad);
  border-color: transparent;
  color: var(--accent-ink);
  box-shadow: 0 6px 14px oklch(85% 0.19 140 / 0.25);
}
.rotator-tabs a[aria-current="page"]:hover { color: var(--accent-ink); }
.rotator-tabs .rotator-tab-add {
  border-style: dashed;
  border-color: oklch(55% 0.14 140 / 0.6);
  color: var(--blue);
  background: none;
}
.rotator-tabs .rotator-tab-add:focus-visible {
  outline: none;
  box-shadow: var(--focus);
}
.rotator-tabs-count {
  margin: 0.55rem 0 0;
  color: var(--muted);
  font-size: 0.9rem;
}

.app-dialog {
  width: min(34rem, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  box-shadow: var(--shadow-lg);
}
.app-dialog::backdrop {
  background: oklch(8% 0.01 260 / 0.66);
}
.app-dialog-panel {
  background: var(--paper);
  padding: 1.25rem 1.35rem 1.4rem;
  border-radius: var(--radius);
}
.app-dialog-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.8rem;
  margin-bottom: 0.85rem;
}
.app-dialog-head h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--ink);
}
.app-dialog-close {
  flex-shrink: 0;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--raised);
  color: var(--muted);
  font-size: 1.35rem;
  line-height: 1;
  cursor: pointer;
}
.app-dialog-close:hover {
  background: var(--surface-hover);
  color: var(--ink);
}
.app-dialog-close:focus-visible {
  outline: none;
  box-shadow: var(--focus);
}
.app-dialog-actions {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin-top: 0.4rem;
}
.grid-form input[readonly] {
  background: oklch(15% 0.012 260);
  color: var(--muted);
}

.embed-snippets {
  margin-top: 1.1rem;
  padding-top: 1.05rem;
  border-top: 1px solid var(--line);
}
.embed-snippets h3 {
  margin: 1rem 0 0.4rem;
  font-family: var(--font-display);
  font-size: 1rem;
}
.embed-snippets h3:first-child { margin-top: 0; }
.embed-snippet-label {
  display: block;
  font-family: var(--font-display);
  font-size: 0.92rem;
  font-weight: 500;
  margin: 0 0 0.35rem;
}
.embed-snippet {
  display: block;
  width: 100%;
  min-height: 9.5rem;
  margin: 0;
  padding: 0.85rem 1rem;
  resize: vertical;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--ink);
  background: var(--sunken);
  border: 2px solid var(--field-line);
  border-radius: var(--radius-sm);
  box-shadow: var(--sunken-inset);
  white-space: pre;
  overflow-x: auto;
}
.embed-snippet-short { min-height: 4.2rem; }
.embed-snippet-htaccess { min-height: 9.2rem; }
.embed-snippet:focus-visible {
  outline: none;
  border-color: var(--blue);
  box-shadow: var(--focus), var(--sunken-inset);
}
.embed-snippet-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 0.65rem;
}

.admin-tips-list { display: grid; gap: 1.2rem; }
.admin-tip-item {
  border-top: 1px solid var(--line);
  padding-top: 1.1rem;
}
.admin-tip-item:first-child {
  border-top: 0;
  padding-top: 0;
}
.admin-tip-preview-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.35rem;
}
.admin-affiliate-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.35rem;
}
.admin-affiliate-head .admin-tip-preview-label {
  margin-bottom: 0;
}
/* The ad's visibility reads at a glance: green when it runs, red when it does not. */
.admin-affiliate-state { font-weight: 700; }
.admin-affiliate-state.is-active { color: var(--ok); }
.admin-affiliate-state.is-inactive { color: var(--danger); }
.admin-affiliate-order {
  display: flex;
  gap: 0.4rem;
}
.admin-affiliate-order button {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.85rem;
  padding: 0.35rem 0.7rem;
  min-height: 2.2rem;
  border-radius: 4px;
  border: 1px solid var(--line);
  background: var(--raised);
  color: var(--ink);
  cursor: pointer;
}
.admin-affiliate-order button:hover:not(:disabled) {
  background: var(--surface-hover);
  color: var(--blue);
  border-color: var(--blue);
}
.admin-affiliate-order button:focus-visible {
  outline: none;
  box-shadow: var(--focus);
}
.admin-affiliate-order button:disabled {
  opacity: 0.4;
  cursor: default;
}
.admin-tip-actions { margin-top: 0.4rem; }
.admin-tip-delete { margin-top: 0.7rem; }

.sites-table-wrap { overflow-x: auto; }
.sites-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
}
.sites-table th,
.sites-table td {
  text-align: left;
  padding: 0.45rem 0.6rem 0.45rem 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.sites-table th {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 500;
}
.sites-table td:last-child,
.sites-table th:last-child {
  text-align: right;
  padding-right: 0;
}
.sites-forget { margin: 0; }
.sites-forget .btn-link { font-size: 0.9rem; }
.sites-state {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--muted);
}

.admin-ad-edit > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--blue);
  list-style: none;
  user-select: none;
}
.admin-ad-edit > summary::-webkit-details-marker { display: none; }
.admin-ad-edit > summary::marker { content: none; }
.admin-ad-edit-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  flex-shrink: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--raised);
  color: var(--blue);
  font-size: 1.35rem;
  font-weight: 600;
  line-height: 1;
}
.admin-ad-edit-icon::before { content: "+"; }
.admin-ad-edit[open] > summary .admin-ad-edit-icon::before { content: "−"; }
.admin-ad-edit > summary:hover .admin-ad-edit-icon,
.admin-ad-edit > summary:focus-visible .admin-ad-edit-icon {
  background: var(--surface-hover);
  border-color: var(--blue);
}
.admin-ad-edit > summary:focus-visible {
  outline: none;
}
.admin-ad-edit > summary:focus-visible .admin-ad-edit-icon {
  box-shadow: var(--focus);
}
.admin-ad-edit > .grid-form {
  margin-top: 1rem;
}

/* Accounts list — one compact row per user, expanded with the + control. */
.admin-user-item { padding-top: 0.7rem; }
.admin-user-details > summary {
  display: flex;
  width: 100%;
  color: var(--ink);
  font-weight: 500;
}
.admin-user-summary {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.35rem 0.9rem;
  min-width: 0;
}
.admin-user-name {
  font-family: var(--font-mono);
  font-size: 0.95rem;
  color: var(--ink);
}
.admin-user-email {
  font-size: 0.92rem;
  color: var(--muted);
  overflow-wrap: anywhere;
}
.admin-user-state {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: oklch(85% 0.17 140);
}
.admin-user-state.is-inactive { color: var(--muted); }
.admin-user-body { margin-top: 1.1rem; }
.admin-user-body > .grid-form { margin-top: 1rem; }
.admin-user-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 2rem;
  margin: 0 0 0.6rem;
}
.admin-user-meta dt {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.admin-user-meta dd {
  margin: 0.15rem 0 0;
  font-size: 0.95rem;
  color: var(--ink);
}
/* Keep the inputs on a row lined up even when one label carries a hint. */
.admin-user-form { align-items: stretch; }
.admin-user-form > label:not(.checkbox) > input { margin-top: auto; }
/* Same alignment for any grid form: the label text and its hint stay on top,
   the field itself drops to the bottom of the row so neighbours line up. */
.grid-form-aligned { align-items: stretch; }
.grid-form-aligned > label:not(.checkbox):not(.radio) > input,
.grid-form-aligned > label:not(.checkbox):not(.radio) > select { margin-top: auto; }

/* Avatar — the uploaded image or the account's initial, round in both cases.
   Used small in the site nav and large on the profile page. */
.user-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 50%;
  overflow: hidden;
  object-fit: cover;
  background: var(--paper-2);
  border: 1px solid var(--line);
  color: var(--muted);
  font-family: var(--font-display);
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1;
  vertical-align: middle;
}
.site-nav-me {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.site-nav-me:hover .user-avatar {
  border-color: var(--line-strong);
  color: var(--ink);
}

/* Profile page — identity block above the form, then the danger zone. */
.profile-identity {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.2rem;
}
.profile-identity p { margin: 0; }
.profile-username {
  font-family: var(--font-mono);
  font-size: 0.95rem;
  color: var(--muted);
}
.profile-avatar {
  width: 4.5rem;
  height: 4.5rem;
  font-size: 1.8rem;
}
.profile-avatar-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 1.2rem 1.5rem;
}
.profile-avatar-fields {
  flex: 1;
  min-width: 12rem;
}
.profile-avatar-fields > p { margin-top: 0; }
.profile-identity-name {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink);
}
.card-danger {
  background: linear-gradient(160deg, oklch(45% 0.14 25 / 0.14), transparent 60%), var(--paper);
  border-color: oklch(45% 0.1 25 / 0.5);
}
.card-danger h2 { color: oklch(82% 0.13 25); }
.otp-field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-family: var(--font-display);
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--ink);
}
.otp-field-name { color: var(--ink); }
.otp-boxes-row {
  display: flex;
  gap: 0.5rem;
  max-width: 22rem;
  margin-top: 0.15rem;
}
.grid-form .otp-boxes-row .otp-box {
  flex: 1 1 0;
  width: 2.75rem;
  min-width: 0;
  max-width: 3.2rem;
  padding: 0.55rem 0;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 1.45rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  caret-color: var(--blue);
}
@media (max-width: 480px) {
  .otp-boxes-row { gap: 0.35rem; }
  .grid-form .otp-boxes-row .otp-box {
    min-height: 2.8rem;
    font-size: 1.25rem;
  }
}

/* Buttons in a form action row (Cancel next to Save). */
.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
}

.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;
}

@media (max-width: 860px) {
  .hero { grid-template-columns: 1fr; gap: 1.6rem; }
  .hero .lede { max-width: 46rem; }
}

@media (max-width: 720px) {
  .grid-form { grid-template-columns: 1fr; }
  .grid-form .span2 { grid-column: auto; }
  .ticket-close-card { flex-direction: column; align-items: flex-start; }
  .page-head h1 { font-size: 1.5rem; }
  .home-points { grid-template-columns: 1fr; }
}

/* --- Mobile nav: the links move into a panel under the header ---
   Only for scripted documents (data-js is set from <head>), since the panel
   is opened by the hamburger button. Without scripting the nav keeps the
   wrapping row below. */
@media (max-width: 860px) {
  html[data-js] .nav-toggle { display: inline-flex; }
  html[data-js] .site-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 2;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0.2rem var(--page-gutter) 0.7rem;
    font-size: 0.98rem;
    background: var(--paper);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-lg);
    max-height: calc(100vh - 100%);
    max-height: calc(100dvh - 100%);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  html[data-js] .site-header[data-nav="open"] .site-nav { display: flex; }
  /* Backdrop over the page below the header. */
  html[data-js] .site-header[data-nav="open"]::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 100vh;
    height: 100dvh;
    z-index: 1;
    background: oklch(10% 0.01 260 / 0.5);
  }
  /* Rows big enough to hit, separated instead of spaced. */
  html[data-js] .site-nav > a,
  html[data-js] .site-nav .site-nav-menu > summary {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 0.15rem;
    border-bottom: 1px solid var(--line);
  }
  html[data-js] .site-nav > *:last-child > summary,
  html[data-js] .site-nav > a:last-child { border-bottom: 0; }
  /* The rotator submenu drops out of its dropdown box and simply indents. */
  html[data-js] .site-nav .site-nav-menu-list {
    position: static;
    min-width: 0;
    padding: 0 0 0.35rem 0.9rem;
    background: none;
    border: 0;
    box-shadow: none;
  }
  html[data-js] .site-nav .site-nav-menu-list a { padding: 0.55rem 0.55rem; }
}

@media (max-width: 480px) {
  html:not([data-js]) .site-header-inner { flex-wrap: wrap; row-gap: 0.5rem; }
  html:not([data-js]) .site-nav { width: 100%; gap: 0.85rem; }
}

@media (prefers-reduced-motion: reduce) {
  .nav-toggle-bars,
  .nav-toggle-bars::before,
  .nav-toggle-bars::after { transition: none; }
}

.hero-actions {
  display: flex;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin: 1.1rem 0 0;
}
.btn-secondary,
.app-dialog-actions .btn-secondary {
  background: var(--raised);
  color: var(--ink);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.06), 0 6px 14px oklch(10% 0.01 260 / 0.35);
}
.btn-secondary:hover,
.app-dialog-actions .btn-secondary:hover {
  background: var(--surface-hover);
  color: var(--ink);
  border-color: var(--line-strong);
  box-shadow: inset 0 1px 0 oklch(100% 0 0 / 0.06), 0 10px 20px oklch(10% 0.01 260 / 0.45);
}
.btn-link {
  background: none;
  border: 0;
  color: var(--blue);
  cursor: pointer;
  font: inherit;
  padding: 0;
  min-height: 0;
  box-shadow: none;
  text-decoration: underline;
}
.btn-link:hover,
.grid-form .btn-link:hover {
  background: none;
  color: var(--blue-deep);
  box-shadow: none;
  transform: none;
}

.muted-form { margin-top: 0.85rem; }

@media (prefers-reduced-motion: reduce) {
  .grid-form input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]):not([type="color"]),
  .grid-form select,
  .grid-form textarea,
  .embed-snippet,
  .grid-form button,
  .btn,
  .card {
    transition: none;
  }
}

/* The rotator background is picked by the owner and is often light, so links
   there follow the rotator theme instead of the app's lime accent. */
body.is-rotator a,
body.is-embed a {
  color: var(--rotator-link, var(--blue));
}
body.is-rotator a:hover,
body.is-embed a:hover {
  color: var(--rotator-link-hover, var(--blue-deep));
}

body.is-rotator {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
body.is-rotator .fl-affiliate {
  margin: 0;
  border: 0;
  width: 100%;
}
body.is-rotator .rotator-empty {
  margin: 0;
}
body.is-rotator .rotator-closed,
body.is-embed .rotator-closed {
  margin: 0;
  border: 0;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}
body.is-rotator .rotator-closed {
  flex: 1 1 auto;
  min-height: 100vh;
  padding: 1.5rem 1.25rem;
  font-size: 18px;
}
body.is-embed .rotator-closed {
  min-height: 100vh;
  padding: 0.6rem;
  font-size: 16px;
}

body.is-embed {
  min-height: 0;
  display: block;
  background: transparent;
}
body.is-embed .fl-affiliate {
  border: 0;
  padding: 0.6rem;
  background: transparent;
}
