/*
 * Application styles (Propshaft serves this file as-is at /assets/application.css).
 * Goal: a small, readable, classless-leaning baseline plus a few component classes
 * for the site chrome and the moderation queue. No framework — keep it minimal.
 */

:root {
  --color-bg: #fbfbfd;
  --color-surface: #ffffff;
  --color-text: #1c1c28;
  --color-muted: #6b7280;
  --color-border: #e3e3ea;
  --color-accent: #4338ca;
  --color-accent-dark: #312e81;
  --color-accent-soft: #eef0fb;
  --color-accent-2: #0ea5b7;          /* quantum cyan, used in gradients/accents */
  --color-accent-contrast: #ffffff;
  --color-danger: #b42318;
  --color-success: #067647;
  --radius: 8px;
  --radius-lg: 16px;
  --space: 1rem;
  --maxw: 64rem;
  --shadow-sm: 0 1px 2px rgba(16, 16, 40, .06);
  --shadow-md: 0 10px 30px rgba(16, 16, 40, .08);
  --font: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  color: var(--color-text);
  background: var(--color-bg);
}

main {
  display: block;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: calc(var(--space) * 2) var(--space);
}

h1, h2, h3 { line-height: 1.2; letter-spacing: -0.01em; }
h1 { font-size: 2rem; margin: 0 0 1rem; }
h2 { font-size: 1.35rem; margin: 1.5rem 0 .5rem; }
h3 { font-size: 1.1rem; margin: 1.25rem 0 .5rem; }

a { color: var(--color-accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---- Site header ---------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  padding: .75rem clamp(var(--space), 4vw, 2rem);
  background: rgba(255, 255, 255, .85);
  backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid var(--color-border);
}

/* Inner wrapper: holds the header content to the same central column as the footer. */
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space);
  flex-wrap: wrap;
  max-width: var(--maxw);
  margin: 0 auto;
}

.site-header__logo {
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: .6rem;
  color: var(--color-text);
}
.site-header__logo:hover { text-decoration: none; }
.site-header__mark {
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  border-radius: 10px;
  box-shadow: var(--shadow-sm);
}
.site-header__wordmark {
  display: inline-flex;
  flex-direction: column;
  line-height: 1.1;
}
.site-header__name {
  font-weight: 800;
  font-size: 1.3rem;
  letter-spacing: -0.02em;
}
.site-header__tagline {
  margin-top: .15rem;
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--color-muted);
}

/* The menu is a flex row: ordinary links on the left, the tools cluster on the right. */
.site-header__menu {
  display: flex;
  align-items: center;
  gap: 1.75rem;
}
.site-header__links {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.site-header__links a {
  color: var(--color-text);
  font-weight: 500;
  font-size: .95rem;
}
.site-header__links a:hover { color: var(--color-accent); text-decoration: none; }

/* Two-level navigation. A top-level item that heads a submenu reveals it on hover or
   keyboard focus (:focus-within), so the dropdown works without JavaScript. A
   label-only parent is a span styled to match the link siblings. */
.site-header__item { position: relative; }
.site-header__label {
  color: var(--color-text);
  font-weight: 500;
  font-size: .95rem;
  cursor: default;
}
.site-header__item--has-sub > a,
.site-header__item--has-sub > .site-header__label {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
}
/* Caret hint, drawn as a rotated square so it needs no glyph or image. */
.site-header__item--has-sub > a::after,
.site-header__item--has-sub > .site-header__label::after {
  content: "";
  width: .4rem;
  height: .4rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  opacity: .55;
}
.site-header__sub {
  position: absolute;
  top: calc(100% + .35rem);
  left: 0;
  z-index: 50;
  min-width: 12rem;
  margin: 0;
  padding: .35rem 0;
  list-style: none;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  opacity: 0;
  visibility: hidden;
  transform: translateY(.25rem);
  transition: opacity .15s ease, transform .15s ease, visibility .15s;
}
.site-header__item--has-sub:hover > .site-header__sub,
.site-header__item--has-sub:focus-within > .site-header__sub {
  opacity: 1;
  visibility: visible;
  transform: none;
}
.site-header__sub a {
  display: block;
  padding: .5rem 1rem;
  color: var(--color-text);
  font-size: .9rem;
  font-weight: 500;
  white-space: nowrap;
}
.site-header__sub a:hover { color: var(--color-accent); background: var(--color-accent-soft); text-decoration: none; }

/* The two quantum tools, set off from the plain links by a divider so they read as
   a distinct, attention-drawing pair. */
.site-header__tools {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding-left: 1.25rem;
  border-left: 1px solid var(--color-border);
}
.site-header__tool {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .4rem .85rem;
  font-weight: 600;
  font-size: .9rem;
  color: var(--color-accent) !important;
  background: var(--color-surface);
  border: 1px solid var(--color-accent);
  border-radius: 999px;
  transition: background .15s ease, color .15s ease, filter .15s ease;
}
.site-header__tool svg { width: 1.05rem; height: 1.05rem; flex: none; }
.site-header__tool:hover { background: var(--color-accent-soft); text-decoration: none; }
/* One filled, one outlined: a clear lead action without two loud buttons competing. */
.site-header__tool--primary {
  color: var(--color-accent-contrast) !important;
  background: var(--color-accent);
}
.site-header__tool--primary:hover { background: var(--color-accent); filter: brightness(1.08); }

/* Admin header: the gated admin/moderation layout swaps the public header for this
   one. The "Admin" tagline reads as a small accent badge, and the tools cluster is
   replaced by the signed-in user and a sign-out button. */
.site-header--admin .site-header__tagline {
  margin-top: .2rem;
  color: var(--color-accent);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-weight: 700;
}
.site-header__links a[aria-current="page"] { color: var(--color-accent); }

.admin-session { gap: .85rem; }
.admin-session__user {
  font-size: .85rem;
  font-weight: 500;
  color: var(--color-muted);
}
.admin-session form { margin: 0; }
.admin-session__signout {
  display: inline-flex;
  align-items: center;
  padding: .4rem .85rem;
  font: inherit;
  font-weight: 600;
  font-size: .9rem;
  color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-accent);
  border-radius: 999px;
  cursor: pointer;
  transition: background .15s ease, filter .15s ease;
}
.admin-session__signout:hover { background: var(--color-accent-soft); }

/* Mobile navigation toggle — hidden on desktop, CSS-only disclosure on mobile. */
.site-header__toggle,
.site-header__burger { display: none; }

/* ---- Site footer ---------------------------------------------------------- */
.site-footer {
  margin-top: calc(var(--space) * 4);
  padding: calc(var(--space) * 2.5) clamp(var(--space), 4vw, 2rem) var(--space);
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-muted);
  font-size: .9rem;
}
.site-footer__cols {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 2rem;
  max-width: var(--maxw);
  margin: 0 auto;
}
.site-footer__brand {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin: 0 0 .35rem;
  font-weight: 800;
  font-size: 1.15rem;
  color: var(--color-text);
}
.site-footer__mark {
  width: 1.85rem;
  height: 1.85rem;
  flex: none;
  border-radius: 8px;
}
.site-footer__muted { margin: 0; max-width: 28ch; }

/* Featured tool cards: both quantum tools with a one-line hook, so they keep pulling
   attention in the footer without crowding the link columns. */
.site-footer__tools {
  display: flex;
  flex-direction: column;
  gap: .6rem;
  margin-top: 1.1rem;
  max-width: 24rem;
}
.site-footer__tool {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .6rem .8rem;
  color: var(--color-text) !important;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  transition: border-color .15s ease, background .15s ease;
}
.site-footer__tool:hover {
  background: var(--color-accent-soft);
  border-color: var(--color-accent);
  text-decoration: none;
}
.site-footer__tool svg { width: 1.4rem; height: 1.4rem; flex: none; color: var(--color-accent); }
.site-footer__tool b { display: block; font-weight: 700; font-size: .92rem; line-height: 1.25; }
.site-footer__tool small { color: var(--color-muted); font-size: .8rem; }
.site-footer__heading {
  margin: 0 0 .6rem;
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--color-text);
}
.site-footer__col ul { margin: 0; padding: 0; list-style: none; }
.site-footer__col li { margin: .35rem 0; }
.site-footer__col a { color: var(--color-muted); }
.site-footer__col a:hover { color: var(--color-accent); }
.site-footer__legal {
  max-width: var(--maxw);
  margin: 2rem auto 0;
  padding-top: var(--space);
  border-top: 1px solid var(--color-border);
  font-size: .8125rem;
}
@media (max-width: 40rem) {
  .site-footer__cols { grid-template-columns: 1fr; gap: 1.5rem; }
}

/* ---- Flash messages ------------------------------------------------------- */
.flash {
  max-width: var(--maxw);
  margin: var(--space) auto 0;
  padding: .75rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}
.flash--notice { border-color: var(--color-success); color: var(--color-success); }
.flash--alert  { border-color: var(--color-danger);  color: var(--color-danger); }

/* ---- Forms ---------------------------------------------------------------- */
label { display: inline-block; font-weight: 600; margin-bottom: .25rem; }

input[type="text"],
input[type="number"],
input[type="email"],
input[type="password"],
textarea,
select,
trix-editor {
  width: 100%;
  padding: .5rem .625rem;
  font: inherit;
  color: inherit;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

textarea { resize: vertical; }

input:focus, textarea:focus, select:focus, trix-editor:focus {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
  border-color: var(--color-accent);
}

fieldset {
  margin: var(--space) 0;
  padding: .75rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}
legend { font-weight: 600; padding: 0 .375rem; }

/* ---- Admin WYSIWYG editor (TipTap) ---------------------------------------- */
/* A formatting toolbar above an editable surface that renders the body in the real
   .page__body / .trix-content styles, so editors see special elements (.lede,
   .features, .callout, …) as they'll appear on the site. */
.tiptap-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  padding: .5rem;
  border: 1px solid var(--color-border);
  border-bottom: none;
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--color-surface);
}
.tiptap-toolbar__group {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem;
}
.tiptap-toolbar__group + .tiptap-toolbar__group {
  padding-left: .75rem;
  border-left: 1px solid var(--color-border);
}
.tiptap-toolbar__btn {
  padding: .25rem .5rem;
  font-size: .8rem;
  line-height: 1.2;
  border: 1px solid var(--color-border);
  border-radius: calc(var(--radius) / 2);
  background: #fff;
  color: var(--color-text);
  cursor: pointer;
}
.tiptap-toolbar__btn:hover { background: var(--color-bg); }
/* Image-align buttons disable until an image is selected. */
.tiptap-toolbar__btn:disabled { opacity: .45; cursor: default; }
.tiptap-toolbar__btn:disabled:hover { background: #fff; }
.tiptap-toolbar__btn.is-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}
.tiptap-editor {
  border: 1px solid var(--color-border);
  border-radius: 0 0 var(--radius) var(--radius);
  background: var(--color-surface);
  padding: 1rem;
  min-height: 24rem;
  overflow: auto;
}
/* The ProseMirror surface fills the pane and shows a focus ring on the wrapper. */
.tiptap-editor .ProseMirror { outline: none; min-height: 22rem; }
/* Clicking an image selects its node; outline it so the Img ←/→ align buttons have
   a visible target. */
.tiptap-editor .ProseMirror-selectednode {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.tiptap-editor:focus-within {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}
/* The raw-HTML source toggle reuses the form textarea; give it a code look. */
.tiptap-editor + textarea[data-tiptap-target="source"]:not([hidden]),
textarea[data-tiptap-target="source"]:not([hidden]) {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: .85rem;
}

/* Checkbox/radio rows inside fieldsets read better inline. */
fieldset label {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  font-weight: 400;
  margin: 0 1rem .25rem 0;
}
fieldset input[type="checkbox"],
fieldset input[type="radio"] { width: auto; }

/* ---- AI page-draft panel (admin page form) --------------------------------- */
/* The "Draft/Rework with AI" fieldset. Its labels are ordinary field labels, so
   undo the inline checkbox-row treatment fieldsets get above. */
.page-draft { background: var(--color-surface); }
.page-draft label {
  display: inline-block;
  font-weight: 600;
  margin: 0 0 .25rem;
}
.page-draft > div { margin-bottom: .75rem; }
.page-draft__hint {
  margin: .25rem 0 1rem;
  color: var(--color-muted);
  font-size: .9rem;
}

/* Inline help under admin form fields. */
.form-hint {
  margin: .2rem 0 0;
  color: var(--color-muted);
  font-size: .85rem;
}

/* ---- Menu admin: the navigation tree editor ------------------------------- */
.admin-menu__intro {
  max-width: 60ch;
  color: var(--color-muted);
}
.admin-menu, .admin-menu--children {
  list-style: none;
  padding-left: 0;
  margin: 0;
}
.admin-menu__item { margin: .35rem 0; }
.admin-menu__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .75rem;
  padding: .5rem .75rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}
.admin-menu__title { font-weight: 600; }
.admin-menu__meta { color: var(--color-muted); font-size: .85rem; }
.admin-menu__hidden {
  font-size: .78rem;
  font-weight: 600;
  color: var(--color-danger);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.admin-menu__actions { margin-left: auto; display: flex; align-items: center; gap: .6rem; }
.admin-menu__actions form { margin: 0; }
/* Children are indented and connected to their parent by a left rule. */
.admin-menu--children {
  margin: .35rem 0 0 1.25rem;
  padding-left: .75rem;
  border-left: 2px solid var(--color-border);
}

/* ---- Buttons -------------------------------------------------------------- */
button,
input[type="submit"],
.button {
  display: inline-block;
  padding: .5rem .9rem;
  font: inherit;
  font-weight: 600;
  color: var(--color-accent-contrast);
  background: var(--color-accent);
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
}
button:hover,
input[type="submit"]:hover,
.button:hover { filter: brightness(1.08); text-decoration: none; }

/* button_to renders an inline <form>; keep them on one line and spaced. */
form.button_to { display: inline-block; margin: 0; }

/* Action Text's Trix toolbar renders its controls as <button> elements. The
   component button styling above must NOT bleed into them — Trix ships its own
   styling (actiontext.css). This scoped reset (more specific than the bare
   `button` selector) neutralises our look so Trix's wins. */
trix-toolbar button {
  display: inline-block;
  padding: 0 .5em;
  font-weight: 600;
  color: rgba(0, 0, 0, 0.6);
  background: transparent;
  border: none;
  border-radius: 0;
}

/* ---- Tables (e.g. admin/pages) -------------------------------------------- */
table {
  width: 100%;
  border-collapse: collapse;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
}
th, td {
  text-align: left;
  padding: .625rem .75rem;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}
thead th {
  background: #f3f3f7;
  font-size: .8125rem;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--color-muted);
}
tbody tr:last-child td { border-bottom: none; }

/* ---- Moderation queue ----------------------------------------------------- */
/* Editor pipeline controls (fetch now / regenerate a day) sit above the queue. */
.moderation-tools {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1.25rem;
  margin: 0 0 var(--space);
}
.moderation-tools h2 { margin-top: 0; }
.moderation-tools__row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1rem;
}
.moderation-tools__regenerate {
  display: flex;
  align-items: flex-end;
  gap: .5rem;
}

.moderation-item {
  display: block;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1.25rem;
  margin: 0 0 var(--space);
}

.moderation-item dl {
  display: grid;
  grid-template-columns: 9rem 1fr;
  gap: .25rem 1rem;
  margin: 0 0 1rem;
}
.moderation-item dt { font-weight: 600; color: var(--color-muted); }
.moderation-item dd { margin: 0; }

.moderation-item__actions {
  display: flex;
  gap: .5rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--color-border);
}
/* The "Reject" action is destructive — set it apart from the primary Approve. */
.moderation-item__actions form.button_to:last-child button {
  background: var(--color-surface);
  color: var(--color-danger);
  border-color: var(--color-danger);
}

#moderation_articles_empty { color: var(--color-muted); }

/* Narrow screens: stack the definition list. */
@media (max-width: 32rem) {
  .moderation-item dl { grid-template-columns: 1fr; gap: 0; }
  .moderation-item dt { margin-top: .5rem; }
}

/* ---- Public articles ------------------------------------------------------ */
.article-list {
  display: flex;
  flex-direction: column;
  gap: var(--space);
}

.article-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1.25rem;
}
.article-card__title { margin: 0 0 .25rem; font-size: 1.2rem; }
.article-card__summary { margin: .5rem 0; }

.article-card__meta,
.article__meta {
  margin: 0;
  color: var(--color-muted);
  font-size: .875rem;
}

/* Article show page */
.article > h1 { margin-bottom: .25rem; }
.article__body { font-size: 1.0625rem; }

/* Inline [n] citation markers in the digest body link straight to the source. */
.citation-ref {
  font-weight: 600;
  white-space: nowrap;
}

/* Paper-style numbered bibliography. */
.article__references {
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--color-border);
}
.article__references h2 { font-size: 1rem; color: var(--color-muted); }
.references { margin: 0; padding-left: 1.5rem; }
.references li { margin: .25rem 0; }
.references__source { color: var(--color-muted); }

/* Filterable term chips */
.tag {
  display: inline-block;
  margin: .125rem .25rem .125rem 0;
  padding: .15rem .6rem;
  font-size: .8125rem;
  color: var(--color-accent);
  background: #eef0fb;
  border-radius: 999px;
}
.tag:hover { text-decoration: none; filter: brightness(.97); }

.empty { color: var(--color-muted); }
.back-link { margin-top: 2rem; font-size: .9375rem; }

/* pagy's series nav: space the page links out and mark the current page. Pagy 43
   renders a <nav class="pagy series-nav"> of bare <a> elements (no .page wrappers);
   the current page is aria-current, gaps/ends are aria-disabled. */
.pagy.series-nav {
  display: flex;
  flex-wrap: wrap;
  gap: .375rem;
  margin-top: 1.5rem;
}
.pagy.series-nav a {
  display: inline-block;
  padding: .35rem .65rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  text-decoration: none;
}
.pagy.series-nav a[aria-current="page"] { background: var(--color-accent); color: var(--color-accent-contrast); border-color: transparent; }
.pagy.series-nav a[aria-disabled="true"] { color: var(--color-muted); }

/* ── Quantum-readiness tester ───────────────────────────────────────────────── */
.readiness { max-width: 46rem; }
.readiness__intro { color: var(--color-muted); }
.readiness__intro code { font-size: .9em; }

.readiness-form__row { display: flex; gap: .5rem; margin: 1.25rem 0; }
.readiness-form input[type="url"] {
  flex: 1;
  padding: .6rem .75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  font-size: 1rem;
}
.readiness-form input[type="submit"] {
  padding: .6rem 1.25rem;
  border: none;
  border-radius: var(--radius);
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-size: 1rem;
  cursor: pointer;
}
.readiness-form input[type="submit"]:hover { filter: brightness(.95); }

/* Spinner shown while the background probe runs. */
.readiness-status { display: flex; align-items: center; gap: .75rem; margin-top: 1.5rem; color: var(--color-muted); }
.spinner {
  width: 1.25rem; height: 1.25rem;
  border: 3px solid var(--color-border);
  border-top-color: var(--color-accent);
  border-radius: 50%;
  animation: readiness-spin .8s linear infinite;
}
@keyframes readiness-spin { to { transform: rotate(360deg); } }

/* Result banners + per-property detail. */
.readiness-result { margin-top: 1.5rem; }
.readiness-banner { padding: 1rem 1.25rem; border-radius: var(--radius); border: 1px solid transparent; }
.readiness-banner h2 { margin: 0 0 .25rem; font-size: 1.25rem; }
.readiness-banner p { margin: 0; }
.readiness-banner--success { background: #e7f6ee; border-color: var(--color-success); color: var(--color-success); }
.readiness-banner--error   { background: #fdeceb; border-color: var(--color-danger);  color: var(--color-danger); }

.readiness-detail { margin: 1.25rem 0 0; }
.readiness-detail__item { padding: 1rem 0; border-top: 1px solid var(--color-border); }
.readiness-detail dt { font-weight: 600; margin-bottom: .35rem; }
.readiness-detail dd { margin: 0; }
.readiness-detail dd p { margin: .4rem 0 0; color: var(--color-muted); font-size: .9375rem; }

.badge {
  display: inline-block;
  padding: .15rem .55rem;
  border-radius: 999px;
  font-size: .8125rem;
  font-weight: 600;
}
.badge--ok      { background: #e7f6ee; color: var(--color-success); }
.badge--bad     { background: #fdeceb; color: var(--color-danger); }
.badge--neutral { background: #eef0fb; color: var(--color-accent); }
.badge--unknown { background: #fff4e5; color: #92400e; }

.readiness-result__cached { margin-top: 1rem; color: var(--color-muted); font-size: .875rem; font-style: italic; }

.readiness-banner--unknown { background: #fff4e5; border-color: #92400e; color: #92400e; }

/* ── Quantum key cracker ────────────────────────────────────────────────────── */
.keycheck__safety {
  margin: 1rem 0 0;
  padding: .75rem 1rem;
  background: var(--color-accent-soft);
  border-radius: var(--radius);
  font-size: .9375rem;
  color: var(--color-accent-dark);
}

.key-form { margin: 1.25rem 0; }
.key-form__error {
  margin-bottom: .75rem;
  padding: .75rem 1rem;
  background: #fdeceb;
  border: 1px solid var(--color-danger);
  border-radius: var(--radius);
  color: var(--color-danger);
  font-size: .9375rem;
}

/* Drag-and-drop target. */
.key-dropzone {
  display: grid;
  place-items: center;
  gap: .25rem;
  padding: 1.75rem 1rem;
  text-align: center;
  border: 2px dashed var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  color: var(--color-muted);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.key-dropzone:hover,
.key-dropzone:focus-visible { border-color: var(--color-accent); outline: none; }
.key-dropzone.is-dragover { border-color: var(--color-accent); background: var(--color-accent-soft); }
.key-dropzone__hint { margin: 0; }
.key-dropzone__hint strong { color: var(--color-text); }
.key-dropzone__file { margin: 0; font-size: .85rem; color: var(--color-accent-dark); }

.key-form__field {
  width: 100%;
  margin-top: .75rem;
  padding: .6rem .75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: .85rem;
  resize: vertical;
}
.key-form__actions { margin-top: .75rem; }
.key-form__actions input[type="submit"] {
  padding: .6rem 1.25rem;
  border: none;
  border-radius: var(--radius);
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-size: 1rem;
  cursor: pointer;
}
.key-form__actions input[type="submit"]:hover { filter: brightness(.95); }

/* Crackable example keys under the form. */
.key-examples { margin-top: 1.5rem; padding-top: 1.25rem; border-top: 1px solid var(--color-border); }
.key-examples__lead { margin: 0 0 .75rem; color: var(--color-muted); font-size: .9375rem; }
.key-examples ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.key-examples__item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .5rem 1rem;
  padding: .75rem 1rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}
.key-examples__note { margin-left: .5rem; color: var(--color-muted); font-size: .85rem; }
.key-examples__actions { display: flex; align-items: center; gap: .9rem; }
.key-examples__load {
  padding: .4rem .85rem;
  border: 1px solid var(--color-accent);
  border-radius: var(--radius);
  background: var(--color-accent-soft);
  color: var(--color-accent-dark);
  font-size: .875rem;
  cursor: pointer;
}
.key-examples__load:hover { background: var(--color-accent); color: var(--color-accent-contrast); }

.key-result { margin-top: 1.5rem; }
.key-result__again { margin: 0 0 1rem; font-size: .9375rem; }
.key-result__code-title { margin-bottom: .25rem; }
.key-result__code-note { margin: 0 0 .75rem; color: var(--color-muted); font-size: .9375rem; }

/* Generated-script viewer: top lines shown, the rest clipped + faded until "See more". */
.code-block {
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
  background: #0f172a;
}
.code-block__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .5rem .85rem;
  background: #1e293b;
  color: #cbd5e1;
  font-size: .85rem;
}
.code-block__name { font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; }
.code-block__download {
  border: 1px solid #475569;
  border-radius: var(--radius);
  background: transparent;
  color: #e2e8f0;
  padding: .3rem .7rem;
  font-size: .8125rem;
  cursor: pointer;
}
.code-block__download:hover { background: #334155; }

.code-block__pre {
  margin: 0;
  padding: 1rem .85rem;
  max-height: 12.5rem;          /* ~ the top lines, the default fold */
  overflow: hidden;
  color: #e2e8f0;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: .8125rem;
  line-height: 1.5;
  white-space: pre;
  overflow-x: auto;
}
/* Fade the bottom edge while collapsed so it's clearly cut off. */
.code-block:not(.is-expanded) .code-block__pre {
  -webkit-mask-image: linear-gradient(180deg, #000 65%, transparent);
  mask-image: linear-gradient(180deg, #000 65%, transparent);
}
.code-block.is-expanded .code-block__pre { max-height: none; }

.code-block__toggle {
  display: block;
  padding: .55rem .85rem;
  background: #1e293b;
  color: #93c5fd;
  font-size: .85rem;
  text-align: center;
}
.code-block__toggle:hover { background: #334155; text-decoration: none; }

/* ── Marketing / CMS pages ──────────────────────────────────────────────────── */
/* Shared rich-text rhythm for CMS Page bodies. */
.page__body p { margin: 0 0 1rem; }
.page__body ul { padding-left: 1.25rem; }
.page__body li { margin: .4rem 0; }
.page__body > :first-child { margin-top: 0; }

/* The lede paragraph (first paragraph of a page) reads larger and lighter. */
.page__body .lede,
.lede {
  font-size: 1.25rem;
  line-height: 1.5;
  color: var(--color-text);
  margin-bottom: 1.25rem;
}

/* ---- Home hero ------------------------------------------------------------ */
/* The home Page body provides its own h1 + lede; we frame it with a soft
   gradient banner and surface the app's tools as call-to-action buttons. */
.page--home {
  position: relative;
  margin-top: -2rem;            /* hug the header; <main> already pads the page */
  padding: 3.5rem 0 1rem;
}
/* Scoped under .page__body so these out-specify actiontext.css's
   `.trix-content h1 { font-size: 1.2em }` reset (the hero h1 lives inside the
   rich-text body, which also carries .trix-content); without this the h1 shrinks
   below the h2. No width cap: the hero headline reads as a single line. */
.page--home .page__body h1 {
  font-size: clamp(2.25rem, 5vw, 3rem);
  font-weight: 800;
  background: linear-gradient(120deg, var(--color-accent-dark), var(--color-accent) 55%, var(--color-accent-2));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.page--home .page__body h2 { font-size: 1.35rem; }

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin: 2rem 0 1rem;
}

/* Ghost / secondary button variant for the marketing CTAs. */
.button--ghost {
  color: var(--color-accent);
  background: transparent;
  border-color: var(--color-border);
}
.button--ghost:hover { background: var(--color-accent-soft); filter: none; }

/* ---- Feature grid (cards inside a page body or hero) ----------------------- */
/* The card grids sit inside .page__body, whose `ul { padding-left: 1.25rem }`
   (list indent) would otherwise win on specificity and indent the grid. Scope these
   with .page__body so they out-specify it and align flush with the surrounding text. */
.page__body .features,
.features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.25rem;
  margin: 1.5rem 0;
  padding: 0;
  list-style: none;
}
/* Scoped with .page__body to out-specify actiontext.css's `.trix-content * { padding:0 }`
   reset (same element carries both classes), which would otherwise flatten the card padding. */
.page__body .feature,
.feature {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 1.5rem 1.6rem;
  box-shadow: var(--shadow-sm);
}
.feature h3 { margin: 0 0 .5rem; font-size: 1.05rem; }
.feature p { margin: 0; color: var(--color-muted); font-size: .95rem; }

/* ---- Profile / about layout ----------------------------------------------- */
.profile {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}
.page__body .profile__facts,
.profile__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1rem;
  margin: 1.5rem 0;
  padding: 0;
  list-style: none;
}
.page__body .profile__fact,
.profile__fact {
  padding: 1.35rem 1.4rem;
  background: var(--color-accent-soft);
  border-radius: var(--radius-lg);
}
.profile__fact strong { display: block; font-size: 1.4rem; line-height: 1.15; color: var(--color-accent-dark); }
.profile__fact span { display: block; margin-top: .35rem; font-size: .85rem; color: var(--color-muted); }

/* ---- Numbered steps (e.g. "How I work") ----------------------------------- */
/* Scoped with .page__body to out-specify actiontext.css's `.trix-content * { padding:0 }`. */
.page__body .steps,
.steps {
  list-style: none;
  counter-reset: step;
  display: grid;
  gap: .75rem;
  margin: 1.5rem 0;
  padding: 0;
}
.page__body .steps > li,
.steps > li {
  counter-increment: step;
  position: relative;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 1.2rem 1.4rem 1.2rem 3.75rem;
  box-shadow: var(--shadow-sm);
}
.steps > li::before {
  content: counter(step);
  position: absolute;
  left: 1.1rem;
  top: 1.2rem;
  display: grid;
  place-items: center;
  width: 1.9rem;
  height: 1.9rem;
  background: var(--color-accent-soft);
  color: var(--color-accent-dark);
  font-weight: 700;
  font-size: .9rem;
  border-radius: 999px;
}
.steps strong { display: block; margin-bottom: .15rem; }

/* ---- Callout / highlighted aside ------------------------------------------ */
.page__body .callout,
.callout {
  margin: 1.75rem 0;
  padding: 1.4rem 1.6rem;
  background: linear-gradient(120deg, rgba(67, 56, 202, .06), rgba(14, 165, 183, .07));
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-accent);
  border-radius: var(--radius);
}
.callout > :first-child { margin-top: 0; }
.callout > :last-child { margin-bottom: 0; }

/* ---- Image placeholder ------------------------------------------------------ */
/* Emitted by the AI page generator (and insertable from the TipTap toolbar) where a
   real image should go; its text describes the desired image. Deliberately loud —
   amber dashed frame, striped fill, all-caps banner — so an unreplaced placeholder
   cannot slip through review in the editor, and is unmistakably a placeholder if one
   ever reaches the public site. Colours are literal ambers, NOT the site palette,
   precisely so it never blends in with real content. */
.page__body .image-placeholder,
.image-placeholder {
  margin: 1.5rem 0;
  padding: 1rem 1.25rem;
  border: 2px dashed #d97706;
  border-radius: var(--radius);
  background: repeating-linear-gradient(45deg, #fffbeb, #fffbeb 12px, #fef3c7 12px, #fef3c7 24px);
  color: #92400e;
  font-style: italic;
}
.image-placeholder::before {
  content: "📷 Image placeholder — replace before publishing";
  display: block;
  margin-bottom: .35rem;
  font-style: normal;
  font-weight: 700;
  font-size: .72rem;
  letter-spacing: .07em;
  text-transform: uppercase;
}

/* ---- Body images ------------------------------------------------------------ */
/* Image alignment chosen in the TipTap editor travels as a class (img--left /
   img--right) because Action Text's sanitiser strips style attributes on render;
   a class survives, like the special-element classes above. Scoped to .trix-content,
   which every body surface carries: public page/article views and both admin editors,
   so the editor preview wraps text exactly like the live site. Floats cap at a
   percentage of the column so they scale responsively, and collapse to full-width
   blocks on narrow screens where text beside an image doesn't fit. */
.trix-content img.img--left,
.trix-content img.img--right,
.trix-content figure.img--left,
.trix-content figure.img--right {
  max-width: min(45%, 22rem);
  margin-bottom: .75rem;
}
.trix-content img.img--left,
.trix-content figure.img--left  { float: left;  margin-right: 1.5rem; }
.trix-content img.img--right,
.trix-content figure.img--right { float: right; margin-left: 1.5rem; }
/* Headings clear floats: a new section never starts wrapped around the previous
   section's image. */
.trix-content h2,
.trix-content h3 { clear: both; }

/* Captioned image: <figure><img><figcaption>. Reset the browser's default figure
   side margins (1em 40px) so it aligns with the body column; when floated, the
   align class on the figure carries the caption along with the image. */
.trix-content figure {
  margin: 1.5rem 0;
}
.trix-content figure.img--left,
.trix-content figure.img--right { margin-top: 0; }
.trix-content figure > img { display: block; }
.trix-content figcaption {
  margin-top: .4rem;
  font-size: .85rem;
  line-height: 1.4;
  color: var(--color-muted);
}

@media (max-width: 40rem) {
  .trix-content img.img--left,
  .trix-content img.img--right,
  .trix-content figure.img--left,
  .trix-content figure.img--right { float: none; max-width: 100%; margin: 1rem 0; }
}

/* ---- Contact card --------------------------------------------------------- */
.contact-card {
  display: grid;
  grid-template-columns: 8rem 1fr;
  gap: .5rem 1rem;
  margin: 1.5rem 0;
  padding: 1.5rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.contact-card dt { font-weight: 600; color: var(--color-muted); }
.contact-card dd { margin: 0; }

@media (max-width: 32rem) {
  .contact-card { grid-template-columns: 1fr; gap: .15rem; }
  .contact-card dd { margin-bottom: .75rem; }
}

/* ---- Mobile navigation ----------------------------------------------------- */
@media (max-width: 48rem) {
  .site-header__tagline { display: none; }

  .site-header__burger {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 2.5rem;
    height: 2.5rem;
    padding: .55rem;
    cursor: pointer;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
  }
  .site-header__burger span {
    height: 2px;
    background: var(--color-text);
    border-radius: 2px;
    transition: transform .2s ease, opacity .2s ease;
  }

  .site-header__menu {
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    max-height: 0;
    overflow: hidden;
    transition: max-height .25s ease;
  }
  /* Tall enough for an expanded tree with submenus; scroll if it still overflows. */
  .site-header__toggle:checked ~ .site-header__menu { max-height: 80vh; overflow-y: auto; }

  .site-header__links {
    flex-direction: column;
    align-items: stretch;
    gap: .25rem;
    padding: .75rem 0;
  }
  .site-header__links li { width: 100%; }
  .site-header__links a {
    display: block;
    padding: .6rem .25rem;
  }

  /* Submenus expand inline and indented rather than floating: the whole menu is
     already an open disclosure on mobile, so there is no hover to depend on. */
  .site-header__item { position: static; }
  .site-header__label { display: block; padding: .6rem .25rem; }
  .site-header__sub {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    min-width: 0;
    margin: 0;
    padding: 0 0 .25rem .85rem;
    background: transparent;
    border: 0;
    box-shadow: none;
  }
  .site-header__sub a { padding: .5rem .25rem; }

  /* Tools stack full-width below the links, divider becomes a top rule. */
  .site-header__tools {
    flex-direction: column;
    align-items: stretch;
    gap: .5rem;
    padding: .25rem 0 .5rem;
    border-left: 0;
    border-top: 1px solid var(--color-border);
  }
  .site-header__tool { justify-content: center; padding: .65rem .85rem; }

  /* Admin session cluster stacks like the tools: identity above a full-width button. */
  .admin-session__user { padding: .25rem; }
  .admin-session form { width: 100%; }
  .admin-session__signout { width: 100%; justify-content: center; padding: .65rem .85rem; }

  /* Animate the burger into an X when open. */
  .site-header__toggle:checked ~ .site-header__burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .site-header__toggle:checked ~ .site-header__burger span:nth-child(2) { opacity: 0; }
  .site-header__toggle:checked ~ .site-header__burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
}

/* ---- Scraper-resistant contact links -------------------------------------- */
/* Rendered by contact_controller.js as an inline flexbox: the real characters are
   shuffled in the DOM and reordered into reading order via each span's `order`. */
.contact-link {
  display: inline-flex;
  align-items: baseline;
  color: var(--color-accent);
  cursor: pointer;
}
.contact-link:hover { text-decoration: underline; }
.contact-link:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
/* Decoy characters: present in the DOM to pollute textContent, never shown. */
.contact-link__noise { display: none; }

.contact-noscript { color: var(--color-muted); font-size: .9rem; }

/* ---- Cookie consent banner ------------------------------------------------ */
/* Revealed by cookie_consent_controller.js on first visit; gates Google Analytics
   behind an explicit opt-in (EU ePrivacy/GDPR). Quantum-cyan accent edge nods to
   the site's theme without competing with page content. */
.cookie-banner {
  position: fixed;
  left: 50%;
  bottom: 1.25rem;
  transform: translateX(-50%);
  z-index: 1000;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
  width: min(46rem, calc(100% - 2rem));
  padding: 1.1rem 1.35rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-top: 3px solid var(--color-accent-2);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  transition: opacity .25s ease, transform .25s ease;
}
.cookie-banner--leaving { opacity: 0; transform: translate(-50%, 1rem); }
/* `display: flex` above would otherwise beat the UA [hidden] rule and keep the
   banner on screen; restore the attribute's hide so the controller can dismiss it. */
.cookie-banner[hidden] { display: none; }

.cookie-banner__body { flex: 1 1 18rem; }
.cookie-banner__title {
  margin: 0 0 .25rem;
  font-weight: 600;
  color: var(--color-text);
}
.cookie-banner__text {
  margin: 0;
  font-size: .9rem;
  line-height: 1.5;
  color: var(--color-muted);
}

.cookie-banner__actions {
  display: flex;
  gap: .6rem;
  flex: 0 0 auto;
}
.cookie-banner__btn {
  padding: .55rem 1.1rem;
  font-size: .9rem;
  font-weight: 600;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
}
.cookie-banner__btn--primary {
  color: var(--color-accent-contrast);
  background: var(--color-accent);
  border-color: var(--color-accent);
}
.cookie-banner__btn--primary:hover { filter: brightness(1.08); }
.cookie-banner__btn--ghost {
  color: var(--color-accent);
  background: var(--color-surface);
  border-color: var(--color-border);
}
.cookie-banner__btn--ghost:hover { background: var(--color-accent-soft); }

@media (max-width: 32rem) {
  .cookie-banner { bottom: 0; border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
  .cookie-banner__actions { width: 100%; }
  .cookie-banner__btn { flex: 1; }
}

/* ---- Admin statistics dashboard -------------------------------------------- */
.stats__head { margin-bottom: 1.5rem; }
.stats__sub { color: var(--color-muted); margin-top: .25rem; }

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: 1.25rem;
  margin-top: 1.25rem;
}

.stats-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 1.25rem 1.35rem 1.4rem;
}
.stats-card h2 { margin: 0 0 .35rem; font-size: 1.15rem; }
.stats-card h3 {
  margin: 1.4rem 0 .55rem;
  font-size: .8rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--color-muted);
}
.stats-card__metric { color: var(--color-muted); margin: 0; }
.stats-card__metric strong { color: var(--color-text); font-size: 1.4rem; }
.stats-card__totals { margin: .9rem 0 0; color: var(--color-muted); }

/* Line chart */
.stats-chart__svg { width: 100%; height: auto; display: block; margin: .25rem 0 .5rem; }
.stats-chart__grid { stroke: var(--color-border); stroke-width: 1; }
.stats-chart__line { stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.stats-chart__ylabel { fill: var(--color-muted); font-size: 11px; text-anchor: end; }
.stats-chart__xlabel { fill: var(--color-muted); font-size: 11px; }
.stats-chart__empty, .stats-bars__empty, .stats-empty {
  color: var(--color-muted);
  font-style: italic;
  margin: .5rem 0;
}

.stats-legend { display: flex; gap: 1.25rem; flex-wrap: wrap; margin: .25rem 0 .5rem; font-size: .85rem; }
.stats-legend__item { display: inline-flex; align-items: center; gap: .4rem; color: var(--color-muted); }
.stats-legend__swatch { width: .85rem; height: .85rem; border-radius: 3px; display: inline-block; }

/* Horizontal bar list */
.stats-bar {
  display: grid;
  grid-template-columns: minmax(6rem, 11rem) 1fr auto;
  align-items: center;
  gap: .6rem;
  margin: .35rem 0;
  font-size: .9rem;
}
.stats-bar__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stats-bar__track { background: var(--color-accent-soft); border-radius: 999px; height: .7rem; overflow: hidden; }
.stats-bar__fill { display: block; height: 100%; background: var(--color-accent); border-radius: 999px; min-width: 2px; }
.stats-bar__value { color: var(--color-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Recent tables */
.stats-table { width: 100%; border-collapse: collapse; margin-top: .25rem; font-size: .9rem; }
.stats-table th, .stats-table td { text-align: left; padding: .45rem .5rem; border-bottom: 1px solid var(--color-border); }
.stats-table th { color: var(--color-muted); font-weight: 600; font-size: .78rem; text-transform: uppercase; letter-spacing: .03em; }
.stats-table tr:last-child td { border-bottom: none; }

.stats-pill { display: inline-block; padding: .1rem .55rem; border-radius: 999px; font-size: .75rem; font-weight: 600; }
.stats-pill--good { color: var(--color-success); background: #e7f6ee; }
.stats-pill--bad { color: var(--color-danger); background: #fdecea; }

.stats-note { color: var(--color-muted); font-size: .82rem; margin: 0 0 .5rem; }
