/* ============================================================
   Scrived — Public marketing site
   ------------------------------------------------------------
   Inherits its type and accent system from scrived.css (the
   inside) so the outside feels like the same product — same
   Playfair display face, same old-gold accent, same ink ramp.

   What it does NOT inherit is the canvas. The app is warm cream
   paper; the public site is white, because it has to sell on
   screenshots and cream tints every screenshot sitting on it.
   The overrides below re-declare a handful of :root tokens on
   .marketing-body itself, and add the spacing / type / container
   scale the old marketing CSS hardcoded as literals.
   ============================================================ */

/* ---------- Marketing design tokens ----------
   Scoped to .marketing-body ONLY. Custom properties inherit down
   the element tree, so declaring --bg-page here binds it to this
   <body> and its descendants; :root keeps its own value for every
   other page. The authenticated app never puts `marketing-body` on
   <body> (it uses app-body / admin-body / auth-body / share-*-body
   / maintenance-body), so none of this can leak inside.

   No dark variants: layout.php force-sets data-theme="light" on
   <html> for marketing-body before first paint, so the dark palette
   can never apply out here. */
.marketing-body {
  /* canvas — white first, cream demoted to an accent band */
  --bg-page:   #ffffff;
  --bg-card:   #ffffff;
  --bg-paper:  #fbfaf7;
  --bg-rail:   #f4f2ec;

  /* marketing-only surfaces (no :root equivalent) */
  --m-band:        #f7f5f0;              /* alternating cream section */
  --m-band-line:   #ece7db;
  --m-nav-bg:      rgba(255, 255, 255, .86);
  --m-card-line:   #e7e3da;              /* hairline on a white card */
  --m-card-line-2: #d8d2c5;              /* hover / emphasis */
  --m-badge-bg:    #f4f1e9;
  --m-badge-ink:   #6a665e;
  /* gold NEW badge (What's-new spotlight, deep-dive cards, gallery) */
  --m-badge-new-bg:   #f5ead2;
  --m-badge-new-ink:  #8a6d2f;
  --m-badge-new-line: #e8d5a7;

  /* spacing scale — replaces the 90/80/64/28px literals */
  --m-s1: 4px;  --m-s2: 8px;   --m-s3: 12px; --m-s4: 16px; --m-s5: 24px;
  --m-s6: 32px; --m-s7: 48px;  --m-s8: 64px; --m-s9: 80px; --m-s10: 112px;
  --m-section-y: var(--m-s9);   /* vertical rhythm between sections */
  --m-gutter:    28px;          /* horizontal page gutter */
  --m-card-pad:  24px;

  /* type scale — replaces 56/38/20/19/17.5/15.5/13.5/12.5px */
  --m-fs-hero:    clamp(38px, 5.2vw, 58px);
  --m-fs-h2:      clamp(28px, 3.4vw, 40px);
  --m-fs-h3:      20px;
  --m-fs-h4:      17px;
  --m-fs-lead:    19px;
  --m-fs-body:    16px;
  --m-fs-sm:      14px;
  --m-fs-xs:      12.5px;
  --m-fs-eyebrow: 11px;
  --m-lh-tight: 1.06;
  --m-lh-head:  1.2;
  --m-lh-body:  1.62;
  --m-track-eyebrow: .14em;

  /* container / shape / elevation / z */
  --m-container:   1200px;   /* was 1180px, repeated in five places */
  --m-container-n: 760px;    /* narrow measure for prose + section subs */
  --m-radius:      14px;
  --m-radius-sm:   10px;
  --m-radius-pill: 999px;
  --m-shadow-card: 0 1px 2px rgba(24, 22, 18, .045);
  --m-shadow-lift: 0 10px 30px rgba(24, 22, 18, .08);
  --m-z-nav:     50;
  --m-z-overlay: 1200;

  margin: 0;
  background: var(--bg-page);
  color: var(--ink-1);
  font-family: var(--font-sans);
  font-size: var(--m-fs-body);
  line-height: var(--m-lh-body);
  -webkit-font-smoothing: antialiased;
}
@media (max-width: 960px) { .marketing-body { --m-section-y: var(--m-s8); } }
@media (max-width: 760px) {
  .marketing-body { --m-section-y: 56px; --m-gutter: 20px; --m-card-pad: 20px; }
}

/* Motion is decoration everywhere on this site — hover lifts, the
   hero's rotate, the carousel's smooth scroll. Honour the OS setting. */
@media (prefers-reduced-motion: reduce) {
  .marketing-body *,
  .marketing-body *::before,
  .marketing-body *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* The buttons come from scrived.css, which has no focus-visible ring.
   On a page whose primary action is a button, that's a real keyboard
   trap-in-the-dark — add one here rather than touching the app's CSS. */
.marketing-body .btn:focus-visible,
.marketing-body a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.marketing-shell { width: 100%; overflow-x: hidden; }

/* ---------- Header / nav ---------- */
.m-nav {
  position: sticky;
  top: 0;
  z-index: var(--m-z-nav);
  background: var(--m-nav-bg);
  backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--m-card-line);
}
.m-nav-inner {
  max-width: var(--m-container);
  margin: 0 auto;
  padding: var(--m-s3) var(--m-gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
.m-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 20px;
  color: var(--ink-1);
  text-decoration: none;
}
.m-brand .logo-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: var(--bg-topbar);
  color: #f5f1e6;
  border-radius: 6px;
  font-weight: 700;
  letter-spacing: .02em;
}
.m-brand-name { letter-spacing: .01em; }

/* Uploaded brand logo (see scrived.css) — in the marketing nav/footer and
   the maintenance card the .logo-mark span is itself the tile, so an <img>
   replacing it must drop that background and sit contained. Context in the
   selector keeps it ahead of the base `.m-brand .logo-mark { background }`. */
.m-brand img.logo-mark,
.maint-logo img.logo-mark {
  background: transparent;
  object-fit: contain;
}

/* ----- Two pricing cards (Free / one-time paid) + launch countdown -----
   Free is the actual, only sign-up entry point today (checkout requires an
   account); Paid is visually the "recommended" card — bigger shadow, solid
   CTA, always carries a ribbon (the launch-offer label when live, else a
   generic "Best value" tag) so it stands out even with no active discount. */
.m-onetime {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
  max-width: 940px;
  margin: 0 auto;
  align-items: start;
}
@media (max-width: 760px) {
  .m-onetime { grid-template-columns: 1fr; max-width: 460px; }
}
.m-onetime-card {
  position: relative;
  width: 100%;
  background: var(--bg-card, #fff);
  border: 1px solid var(--m-card-line, #e2dcd0);
  border-radius: var(--m-radius, 16px);
  padding: 34px 30px 28px;
  box-shadow: var(--m-shadow-card, 0 6px 20px rgba(0, 0, 0, .05));
  text-align: center;
}
.m-onetime-card.is-paid {
  box-shadow: var(--m-shadow-lift, 0 18px 50px rgba(0, 0, 0, .12));
}
.m-onetime-card.is-paid.has-offer { border-color: var(--accent, #8b6914); }
.m-onetime-ribbon {
  position: absolute;
  top: -13px;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  background: var(--accent, #8b6914);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: 999px;
}
.m-onetime-ribbon.is-muted {
  background: var(--bg-paper, #f5f3ee);
  color: var(--ink-3, #6b655c);
  border: 1px solid var(--line, #e2dcd0);
}
.m-onetime-price {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.m-onetime-was {
  font-size: 24px;
  color: var(--ink-3, #9a948a);
  text-decoration: line-through;
}
.m-onetime-now {
  font-size: 56px;
  font-weight: 800;
  line-height: 1;
  color: var(--ink-1, #1c1a17);
}
/* Free card's price is deliberately smaller — the paid card's number stays
   the visual "hero" of the section, keeping upgrade as the natural focus. */
.is-free .m-onetime-now { font-size: 40px; }
.m-onetime-period { font-size: 14px; color: var(--ink-3, #6b655c); }
/* Step-up ladder line ("Launch price — goes up to $119 on August 1").
   Replaced the JS countdown, which had no script behind it and rendered a
   frozen "ends in —" to everyone. Same amber chip look. */
.m-stepup {
  display: inline-block;
  margin: 16px auto 0;
  padding: 8px 14px;
  border-radius: 10px;
  background: rgba(139, 105, 20, .09);
  color: var(--accent, #8b6914);
  font-size: 14px;
  font-weight: 600;
}
.m-onetime-features {
  list-style: none;
  margin: 22px 0;
  padding: 0;
  text-align: left;
  display: grid;
  gap: 10px;
}
.m-onetime-features li {
  position: relative;
  padding-left: 28px;
  color: var(--ink-2, #33302b);
  font-size: 15px;
  line-height: 1.4;
}
.m-onetime-features li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--accent, #8b6914);
  font-weight: 800;
}
.m-onetime-fine {
  margin: 14px 0 0;
  font-size: 12.5px;
  color: var(--ink-3, #6b655c);
  line-height: 1.5;
}
/* Guarantee line under the buy button — first fine-print line, slightly
   more present than the rest; its link inherits the muted tone. */
.m-guarantee { margin-top: 12px; font-weight: 600; }
.m-guarantee a { color: inherit; text-decoration: underline; }
.m-guarantee a:hover { color: var(--accent, #8b6914); }

.m-nav-links {
  display: flex;
  align-items: center;
  gap: 26px;
}
.m-nav-links a {
  color: var(--ink-2);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  transition: color .15s ease;
}
.m-nav-links a:hover { color: var(--ink-1); }
.m-nav-links .m-nav-signin {
  border-left: 1px solid var(--line);
  padding-left: 24px;
  margin-left: -2px;
}
/* The generic `.m-nav-links a` rule is more specific than `.btn-primary`,
   so the nav's "Notify me" pill was inheriting ink-2 — dark text on the
   dark ink-1 button. Restore the button's own text colors here. */
.m-nav-links a.btn-primary,
.m-nav-links a.btn-primary:hover {
  color: #fff;
}

.m-nav-toggle {
  display: none;
  background: transparent;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  padding: 8px 10px;
  cursor: pointer;
}
.m-nav-toggle span {
  display: block;
  width: 18px;
  height: 2px;
  background: var(--ink-1);
  margin: 3px 0;
  border-radius: 1px;
  transition: transform .15s ease, opacity .15s ease;
}

@media (max-width: 760px) {
  .m-nav-links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--bg-page);
    border-bottom: 1px solid var(--line);
    flex-direction: column;
    align-items: stretch;
    padding: 16px 28px 22px;
    gap: 14px;
  }
  .m-nav-links.is-open { display: flex; }
  .m-nav-links .m-nav-signin { border-left: none; padding-left: 0; margin-left: 0; }
  .m-nav-toggle { display: inline-flex; }
}

/* ---------- Nav over the cinematic hero ----------
   marketing.js adds .is-over-hero while the hero artwork is behind the
   bar. Without this the sticky near-white nav reads as a bright strip
   pinned across the top of the picture. Nav z-index is 50, well above
   the artwork layer's 0, so it stays clickable throughout.
   Only the landing page can ever have .mk-hero-cinematic, so the blog,
   tools and legal pages are untouched. */
.m-nav.is-over-hero {
  /* Not fully transparent: a soft top-down scrim guarantees the links
     stay legible no matter which artwork gets uploaded next. */
  background: linear-gradient(180deg, rgba(12, 9, 6, .55) 0%, rgba(12, 9, 6, .28) 70%, rgba(12, 9, 6, 0) 100%);
  border-bottom-color: transparent;
  backdrop-filter: none;   /* blurring a fixed image per frame is not free */
}
.m-nav.is-over-hero .m-brand-name,
.m-nav.is-over-hero .m-nav-links a:hover { color: #fdfaf4; }
.m-nav.is-over-hero .m-nav-links a { color: #ece5d8; }
.m-nav.is-over-hero .m-nav-links .m-nav-signin { border-left-color: rgba(255, 255, 255, .28); }
.m-nav.is-over-hero .m-nav-links a.btn-primary,
.m-nav.is-over-hero .m-nav-links a.btn-primary:hover { color: #fff; }
.m-nav.is-over-hero .m-nav-toggle { border-color: rgba(255, 255, 255, .4); }
.m-nav.is-over-hero .m-nav-toggle span { background: #fdfaf4; }
.m-nav.is-over-hero a:focus-visible {
  outline-color: #f6e6bd;
  box-shadow: 0 0 0 5px rgba(0, 0, 0, .45);
}
/* The letter fallback from View::brandMark() is CSS-coloured, so it can
   follow the links. An admin-uploaded logo is a raster image of unknown
   colour and CANNOT be recoloured safely — a dark mark will vanish here.
   If that happens, either upload a light variant or uncomment the filter
   below (correct for a monochrome mark, wrong for a coloured one). */
.m-nav.is-over-hero .logo-mark:not(.logo-mark-img) {
  color: #fdfaf4;
  border-color: rgba(255, 255, 255, .4);
}
/* .m-nav.is-over-hero .logo-mark-img { filter: brightness(0) invert(1); } */

@media (max-width: 760px) {
  /* The open menu panel is an opaque white sheet below the bar, so its
     links must stay DARK even while the nav itself is over the artwork —
     otherwise the menu is light-on-light and effectively invisible. */
  .m-nav.is-over-hero .m-nav-links.is-open a { color: var(--ink-2); }
  .m-nav.is-over-hero .m-nav-links.is-open a:hover { color: var(--ink-1); }
  .m-nav.is-over-hero .m-nav-links.is-open a.btn-primary,
  .m-nav.is-over-hero .m-nav-links.is-open a.btn-primary:hover { color: #fff; }
  .m-nav.is-over-hero .m-nav-links.is-open .m-nav-signin { border-left-color: transparent; }
}

/* ---------- Hero ---------- */
.m-hero {
  max-width: var(--m-container);
  margin: 0 auto;
  padding: var(--m-s9) var(--m-gutter) 88px;
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: var(--m-s8);
  align-items: center;
}
@media (max-width: 960px) {
  .m-hero { grid-template-columns: 1fr; padding-top: 56px; padding-bottom: var(--m-s8); gap: var(--m-s7); }
}
.m-eyebrow {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: var(--m-fs-eyebrow);
  font-weight: 600;
  letter-spacing: var(--m-track-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 18px;
}
/* The hero and section headings clamp, so the old fixed-px sizes plus
   a 600px override are gone — one declaration now covers every width. */
.m-hero-title {
  font-family: var(--font-display);
  font-size: var(--m-fs-hero);
  line-height: var(--m-lh-tight);
  font-weight: 600;
  letter-spacing: -.01em;
  margin: 0 0 22px;
  color: var(--ink-1);
}
.m-hero-sub {
  font-family: var(--font-serif);
  font-size: var(--m-fs-lead);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 560px;
  margin: 0 0 var(--m-s6);
}

.m-hero-form {
  display: flex;
  gap: 8px;
  max-width: 480px;
  margin: 0 0 12px;
  flex-wrap: wrap;
}
.m-hero-form input[type="email"] {
  flex: 1;
  min-width: 200px;
  padding: 12px 16px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  font: inherit;
  font-size: 15px;
  background: var(--bg-card);
  color: var(--ink-1);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.m-hero-form input[type="email"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}
.m-hero-form .btn-primary,
.m-cta-form .btn-primary {
  padding: 12px 22px;
  font-size: 15px;
}
.m-hero-fineprint {
  margin: 0;
  font-size: 12.5px;
  color: var(--ink-3);
}

.m-flash {
  margin-top: 16px;
  padding: 10px 14px;
  border-radius: 6px;
  font-size: 14px;
}
.m-flash-ok    { background: #e6f5ea; color: #1e6b35; border: 1px solid #c4e4cf; }
.m-flash-error { background: #fde6e6; color: #8a1f1f; border: 1px solid #f4c4c4; }

/* Decorative editor mockup */
.m-hero-art {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
}
/* Variant used when the admin has uploaded a real hero screenshot
   (managed at /admin/screenshots). Slightly larger frame than the
   CSS mock-window and a subtle paper-shadow for visual lift. */
.m-hero-art-photo img {
  width: 100%;
  max-width: 560px;
  height: auto;
  display: block;
  border-radius: 10px;
  box-shadow: var(--shadow-paper);
  border: 1px solid var(--line);
}
.m-mock-window {
  width: 100%;
  max-width: 480px;
  background: var(--bg-paper);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: var(--shadow-paper);
  overflow: hidden;
  transform: rotate(-1deg);
  transition: transform .4s ease;
}
.m-mock-window:hover { transform: rotate(0deg); }
.m-mock-chrome {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  background: var(--bg-topbar);
  color: #f5f1e6;
  font-size: 12px;
}
.m-mock-chrome span {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: rgba(255,255,255,.18);
}
.m-mock-chrome em {
  margin-left: auto;
  font-style: normal;
  font-size: 11px;
  opacity: .8;
}
.m-mock-body {
  padding: 36px 44px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 320px;
  font-family: var(--font-serif);
}
.m-mock-h {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 600;
  color: var(--ink-1);
  text-align: center;
  letter-spacing: .04em;
}
.m-mock-line {
  height: 11px;
  background: linear-gradient(90deg, var(--line) 0%, var(--bg-rail) 100%);
  border-radius: 2px;
}
.m-mock-line.short  { width: 65%; }
.m-mock-line.medium { width: 85%; }

/* ============================================================
   Cinematic hero — full-bleed artwork held in place while the
   page scrolls over it.
   ============================================================
   Applies ONLY under .mk-hero-cinematic, which landing.php adds
   when the hero_bg_wide slot is filled. Everything above stays
   the fallback: delete the images in /admin/screenshots and the
   original white two-column hero returns untouched.

   Why a fixed ELEMENT and not `background-attachment: fixed` on
   the section: iOS Safari ignores that property outright (it
   renders as `scroll`), and where it is honoured it forces a
   full repaint on every scroll frame. A position:fixed element
   composites on the GPU and behaves identically everywhere.

   Stacking contract, and it is a contract — break either half
   and the artwork escapes the hero:
     .mk-hero-bg      z-index 0   (fixed, fills the viewport)
     .m-hero-inner    z-index 1   (the copy, over the art)
     .mk-below-hero   z-index 1   (opaque, scrolls up over it)
   `.m-section` sets no background of its own, so without the
   wrapper every section below would be transparent and the art
   would show through the whole page.
   ============================================================ */
.mk-hero-cinematic {
  /* Flip the palette tokens on the section rather than restyling
     anything: --ink-* and --accent inherit, so every existing
     .m-hero-title / .m-hero-sub / .m-eyebrow declaration resolves
     light with no new selectors and no duplicated rules.
     Marketing pages are force-set to data-theme="light" before
     first paint, so there is no dark variant to keep in sync. */
  --ink-1:  #fdfaf4;
  --ink-2:  #ece5d8;
  --ink-3:  #cfc6b6;
  --accent: #e8c882;   /* the gold, lifted for contrast on dark */

  position: relative;
  /* Full-bleed: cancel the container cap the fallback hero uses, and
     replace its two-column grid with a centred single column. */
  max-width: none;
  min-height: clamp(560px, 88vh, 900px);
  padding: clamp(96px, 18vh, 180px) var(--m-gutter) clamp(88px, 14vh, 150px);
  /* Behind the artwork while it decodes, and the colour a very
     wide viewport shows past the edges. Keep this close to the
     artwork's dominant tone — it is what prevents a white flash
     on a slow connection. */
  background: #14100c;
  overflow: hidden;
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.mk-hero-bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  background: #14100c;
  pointer-events: none;   /* never intercept a click meant for the copy */
}
.mk-hero-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}
/* Scrim. This is an accessibility requirement, not styling: the
   headline and subhead sit directly on the artwork, and whatever
   image is uploaded next has to stay legible. Darkest through the
   middle band where the copy lives, easing off at top and bottom
   so the art still reads. Target >=7:1 for the headline and
   >=4.5:1 for the subhead — the higher bar because this site's
   owner is dyslexic. If a future image misses it, DEEPEN THIS.
   Do not shrink or lighten the type to compensate. */
.mk-hero-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 75% at 50% 42%, rgba(12, 9, 6, .72) 0%, rgba(12, 9, 6, .34) 55%, rgba(12, 9, 6, 0) 100%),
    linear-gradient(180deg, rgba(14, 11, 8, .74) 0%, rgba(14, 11, 8, .52) 34%, rgba(14, 11, 8, .58) 72%, rgba(14, 11, 8, .82) 100%);
}

/* The copy column, centred and measure-capped. */
.mk-hero-cinematic .m-hero-inner {
  position: relative;
  z-index: 1;
  max-width: var(--m-container-n);
  margin: 0 auto;
}
.mk-hero-cinematic .m-hero-title,
.mk-hero-cinematic .m-hero-sub {
  margin-left: auto;
  margin-right: auto;
}
.mk-hero-cinematic .m-hero-sub {
  max-width: 620px;
  /* A hair more leading than the light hero: light-on-dark type
     needs the extra air to stop the lines closing up. */
  line-height: 1.6;
}
/* Lift the display type off the art so it never dissolves into a
   busy patch. Subtle — a heavy shadow reads as amateur at size. */
.mk-hero-cinematic .m-hero-title {
  text-shadow: 0 2px 18px rgba(0, 0, 0, .55);
}
.mk-hero-cinematic .m-hero-sub,
.mk-hero-cinematic .m-eyebrow {
  text-shadow: 0 1px 10px rgba(0, 0, 0, .5);
}
.mk-hero-cinematic .mk-hero-ctas {
  justify-content: center;
}
/* ⚠ The token flip at the top of this block is only safe for things that
   use --ink-* as TEXT. Buttons use it as a BACKGROUND:
     .btn         → background #fff; color var(--ink-1)
     .btn-primary → background var(--ink-1); color #fff
   so flipping --ink-1 light turned the primary CTA into near-white text on
   a near-white pill — an invisible button, which is exactly what shipped
   the first time. Pin both back to the real ink values.
   Literal hex on purpose: the whole point is to escape the flipped token,
   so var(--ink-1) here would just reintroduce the bug. Same class of
   mistake as the nav's .btn-primary override further up this file. */
.mk-hero-cinematic .btn {
  background: #fff;
  color: #1a1a1a;
}
.mk-hero-cinematic .btn-primary {
  background: #1a1a1a;
  border-color: #1a1a1a;
  color: #fff;
  /* A hairline and a drop shadow so the standard dark button still reads
     as a raised button against dark artwork instead of dissolving into
     it. Colour is untouched — this is definition, not a restyle. */
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .22), 0 8px 24px rgba(0, 0, 0, .45);
}
.mk-hero-cinematic .btn-primary:hover {
  background: #000;
  border-color: #000;
  color: #fff;
}
/* The secondary "See how it works" link and the trust line are the
   two lowest-contrast items in the hero — give them an explicit
   colour rather than letting them inherit --ink-3 at small size. */
.mk-hero-cinematic .mk-hero-secondary,
.mk-hero-cinematic .mk-hero-trust a {
  color: #e4dccd;
}
.mk-hero-cinematic .mk-hero-secondary:hover,
.mk-hero-cinematic .mk-hero-trust a:hover {
  color: #fdfaf4;
}
/* Focus rings must survive on dark: the shared rule uses --accent,
   which is now the lifted gold, but add a dark halo so the ring
   reads against a light patch of artwork too. */
.mk-hero-cinematic a:focus-visible,
.mk-hero-cinematic .btn:focus-visible {
  outline-color: #f6e6bd;
  box-shadow: 0 0 0 5px rgba(0, 0, 0, .45);
}

/* Everything below the hero: opaque, and stacked above the fixed
   artwork so it slides up and covers it. The footer lives inside
   this wrapper too — `.m-foot` has an opaque background but is not
   positioned, and a fixed layer paints above static backgrounds
   whatever the source order. */
.mk-below-hero {
  position: relative;
  z-index: 1;
  background: var(--bg-page);
}

@media (max-width: 760px) {
  .mk-hero-cinematic {
    min-height: clamp(480px, 76vh, 700px);
    padding-top: clamp(64px, 12vh, 110px);
    padding-bottom: clamp(56px, 10vh, 96px);
  }
}

/* ---------- Section base ---------- */
.m-section {
  padding: var(--m-section-y) var(--m-gutter);
  max-width: var(--m-container);
  margin: 0 auto;
}
/* The alternating band. On the white canvas this is the only place
   the old cream paper survives — it's what keeps the page from
   reading as a generic white SaaS scroll. */
.m-section-alt {
  max-width: none;
  background: var(--m-band);
  border-top: 1px solid var(--m-band-line);
  border-bottom: 1px solid var(--m-band-line);
}
.m-section-alt > * { max-width: var(--m-container); margin-left: auto; margin-right: auto; }

/* ---- Screenshots gallery — carousel (admin-managed at /admin/screenshots) ----
   3 slides on desktop, 2 on tablet, 1 on mobile (with a peek of
   the next slide for affordance). Uses CSS scroll-snap so touch
   swipe on mobile snaps naturally; arrow buttons scroll by exactly
   one slide width + gap so click-through lands on the same snap
   point.

   Slide widths use calc() rather than auto so the snap math stays
   predictable: each slide is (track - (gaps × visible-count - 1)) /
   visible-count, locking adjacent slides into identical positions.
*/
.m-section-gallery { padding-top: 56px; padding-bottom: 56px; }

.m-carousel {
  position: relative;
  max-width: 1180px;
  margin: 32px auto 0;
  /* Overflow hidden on the wrapper so arrows can sit at the edges
     without showing a horizontal scrollbar on the page. The TRACK
     inside still scrolls. */
}

.m-carousel-track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 24px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  /* Hide the WebKit scrollbar without losing scrollability. */
}
.m-carousel-track::-webkit-scrollbar { display: none; }

/* One slide per page on desktop + tablet. flex-basis alone is NOT
   enough to freeze the width: a flex item's default min-width:auto
   lets an image's intrinsic size push its slide wider (or narrower)
   than the track — which is exactly how odd-sized uploads made
   neighbors creep into view. Clamping min AND max to 100% makes every
   slide exactly track-width no matter what image is inside; the
   fixed-aspect frame (.m-gallery-item-trigger) handles the rest. */
.m-carousel-slide {
  flex: 0 0 100%;
  min-width: 100%;
  max-width: 100%;
  scroll-snap-align: start;
  margin: 0;
}

/* Mobile: one slide visible with a small peek of the next one as
   an affordance for swipeability. Track gets horizontal padding so
   the first/last slide doesn't bleed past the screen edge when
   snap-aligned to start. */
@media (max-width: 640px) {
  .m-carousel-track { padding: 0 8%; gap: 16px; }
  .m-carousel-slide { flex: 0 0 84vw; min-width: 84vw; max-width: 84vw; }
}

/* Small instructional hint shown under the "See Pendrilo in action."
   heading. Tells visitors the gallery is scrollable and that each
   image is clickable to open at full size — non-obvious because
   the thumbnails are zoomed in and look like they might just be
   decorative figures. */
.m-gallery-hint {
  text-align: center;
  color: var(--ink-3);
  font-size: 14px;
  line-height: 1.5;
  max-width: 560px;
  margin: 10px auto 0;
}

.m-gallery-item {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* The image sits INSIDE the fixed-aspect frame (the trigger button,
   below), letterboxed and centered via object-fit: contain — so any
   upload size/aspect works without changing the slide's geometry.
   The card chrome (border, radius, shadow) lives on the frame, not
   the img, so every tile looks identical regardless of image shape. */
.m-gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.m-gallery-item:hover .m-gallery-item-trigger {
  transform: translateY(-2px);
  box-shadow: var(--shadow-2);
}
.m-gallery-item figcaption {
  margin: 0;
  font-size: 13.5px;
  color: var(--ink-3);
  font-family: var(--font-serif);
  line-height: 1.5;
  font-style: italic;
  text-align: center;
}

/* Arrows: floated absolute-positioned circles half-overlapping the
   carousel edge. Hidden by default; shown only when the JS detects
   the track actually overflows (is-overflowing class). Disabled
   state when at the start/end of the scroll. */
.m-carousel-arrow {
  position: absolute;
  top: calc(50% - 12px);          /* tuned slightly above the caption */
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--bg-card);
  color: var(--ink-1);
  border: 1px solid var(--line);
  font-size: 22px;
  font-weight: 600;
  font-family: var(--font-sans);
  line-height: 1;
  cursor: pointer;
  z-index: 3;
  box-shadow: var(--shadow-1);
  display: none;                  /* shown via .is-overflowing below */
  align-items: center;
  justify-content: center;
  transition: background .15s ease, border-color .15s ease, transform .15s ease, opacity .15s ease;
}
.m-carousel.is-overflowing .m-carousel-arrow {
  display: inline-flex;
}
.m-carousel-arrow:hover {
  background: var(--accent-bg);
  border-color: var(--accent);
  transform: translateY(-50%) scale(1.05);
}
.m-carousel-arrow:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.m-carousel-arrow:disabled {
  opacity: .35;
  cursor: not-allowed;
  transform: translateY(-50%);
  background: var(--bg-card);
  border-color: var(--line);
}
.m-carousel-arrow-prev { left: -8px; }
.m-carousel-arrow-next { right: -8px; }

/* On very narrow screens hide the arrows entirely — swipe is the
   primary interaction, and arrows that close to the screen edge
   start to compete with the slides. */
@media (max-width: 480px) {
  .m-carousel.is-overflowing .m-carousel-arrow { display: none; }
}
/* The tile frame: a button (whole tile is the lightbox click target,
   keyboard-focusable, zoom-in cursor) AND the fixed-aspect box every
   image letterboxes into. aspect-ratio reserves the slide's height
   before the image even loads, so slides can't shift or drift off
   their snap points as differently-sized images arrive. */
.m-gallery-item-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 16 / 9;
  margin: 0;
  padding: 0;
  border: 1px solid var(--line);
  background: var(--bg-paper);
  cursor: zoom-in;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: var(--shadow-1);
  font: inherit;
  color: inherit;
  transition: transform .25s ease, box-shadow .25s ease;
}
.m-gallery-item-trigger:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* ---- Lightbox (gallery image modal) ---- */
.m-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease;
}
.m-lightbox.is-open {
  opacity: 1;
  pointer-events: auto;
}
.m-lightbox-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 17, 12, .88);
  backdrop-filter: blur(4px);
  cursor: zoom-out;
}
.m-lightbox-card {
  position: relative;
  margin: 0;
  z-index: 1;
  max-width: min(1100px, 92vw);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  transform: translateY(8px);
  transition: transform .25s ease;
}
.m-lightbox.is-open .m-lightbox-card {
  transform: translateY(0);
}
.m-lightbox-card img {
  display: block;
  max-width: 100%;
  max-height: 78vh;
  width: auto;
  height: auto;
  border-radius: 8px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, .55);
  background: var(--bg-paper);
}
.m-lightbox-caption {
  margin: 0;
  padding: 0 16px;
  text-align: center;
  font-family: var(--font-serif);
  font-size: 15.5px;
  font-style: italic;
  line-height: 1.55;
  color: #e8e3d8;
  max-width: 720px;
}
.m-lightbox-caption[hidden] { display: none; }
.m-lightbox-close {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .12);
  color: #fff;
  border: none;
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .15s ease, transform .15s ease;
}
.m-lightbox-close:hover {
  background: rgba(255, 255, 255, .22);
  transform: scale(1.05);
}
.m-lightbox-close:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
}

@media (max-width: 640px) {
  .m-lightbox { padding: 16px; }
  .m-lightbox-card img { max-height: 70vh; }
  .m-lightbox-close { top: 10px; right: 10px; width: 38px; height: 38px; font-size: 22px; }
}
.m-section-head { text-align: center; margin-bottom: 56px; }
.m-section-title {
  font-family: var(--font-display);
  font-size: var(--m-fs-h2);
  line-height: var(--m-lh-head);
  font-weight: 600;
  margin: 0 0 12px;
  color: var(--ink-1);
  letter-spacing: -.01em;
}
.m-section-sub {
  font-family: var(--font-serif);
  font-size: var(--m-fs-h4);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: var(--m-container-n);
  margin: 0 auto;
}
.m-section-empty {
  text-align: center;
  color: var(--ink-3);
  font-style: italic;
  padding: 32px;
}

/* The old six-pillar "Features grid" CSS (.m-feature-grid / .m-feature /
   .m-feature-icon) that lived here was removed in v2.24 — the VES
   redesign replaced those cards with the stage grid, and no view had
   referenced the classes since. */

/* ---------- Pricing ----------
   The monthly/yearly cadence switcher that used to sit here was
   removed with its JS handler: the site sells one one-time purchase,
   so there was nothing to switch between and no view emitted the
   markup. The live pricing UI is `.m-onetime*`, further up. */
.m-pricing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
  align-items: stretch;
}
.m-tier {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--bg-page);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 32px 28px;
  transition: transform .15s ease, box-shadow .15s ease;
}
.m-section-alt .m-tier { background: var(--bg-page); }
.m-tier.is-highlighted {
  border-color: var(--accent);
  box-shadow: 0 8px 24px rgba(139, 105, 20, 0.10), 0 1px 0 var(--accent-soft);
  transform: scale(1.02);
}
.m-tier-ribbon {
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--accent);
  color: #fff;
  padding: 4px 14px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
}
.m-tier-head { margin-bottom: 24px; }
.m-tier-name {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 600;
  margin: 0 0 4px;
  color: var(--ink-1);
}
.m-tier-tagline {
  font-family: var(--font-serif);
  font-size: 14px;
  color: var(--ink-3);
  margin: 0;
}
.m-tier-price {
  margin-bottom: 24px;
  min-height: 64px;
  display: flex;
  align-items: baseline;
}
.m-price {
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
}
.m-price[hidden] { display: none; }
.m-price-symbol {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 500;
  color: var(--ink-2);
  margin-right: 2px;
}
.m-price-amount {
  font-family: var(--font-display);
  font-size: 48px;
  font-weight: 600;
  color: var(--ink-1);
  line-height: 1;
}
.m-price-period {
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--ink-3);
  margin-left: 8px;
  align-self: end;
  padding-bottom: 6px;
}
.m-tier-features {
  list-style: none;
  margin: 0 0 28px;
  padding: 0;
  flex: 1;
}
.m-tier-features li {
  font-family: var(--font-serif);
  font-size: 15px;
  color: var(--ink-2);
  padding: 8px 0 8px 26px;
  position: relative;
}
.m-tier-features li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 8px;
  color: var(--accent);
  font-weight: 700;
}
.m-tier-cta {
  width: 100%;
  padding: 12px 20px;
  font-size: 15px;
}

/* ---------- FAQ ---------- */
.m-faq {
  max-width: 760px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.m-faq details {
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  padding: 0;
  transition: border-color .15s ease;
}
.m-faq details:hover { border-color: var(--line); }
.m-faq details[open] { border-color: var(--line); }
.m-faq summary {
  cursor: pointer;
  list-style: none;
  padding: 20px 24px;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 16px;
  color: var(--ink-1);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.m-faq summary::-webkit-details-marker { display: none; }
.m-faq summary::after {
  content: "+";
  font-size: 22px;
  font-weight: 300;
  color: var(--ink-3);
  transition: transform .15s ease;
}
.m-faq details[open] summary::after { content: "−"; }
.m-faq p {
  margin: 0;
  padding: 0 24px 22px;
  font-family: var(--font-serif);
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink-2);
}
.m-faq-more {
  max-width: 760px;
  margin: 20px auto 0;
  text-align: center;
  font-family: var(--font-serif);
  font-size: 15.5px;
  color: var(--ink-3);
}
.m-faq-more a { color: var(--accent, #8b6914); }

/* ---------- Closing CTA ---------- */
.m-cta {
  background: var(--bg-topbar);
  color: #f5f1e6;
  padding: 80px 28px;
}
.m-cta-inner { max-width: 720px; margin: 0 auto; text-align: center; }
.m-cta-title {
  font-family: var(--font-display);
  font-size: 36px;
  font-weight: 600;
  margin: 0 0 14px;
}
.m-cta-sub {
  font-family: var(--font-serif);
  font-size: 18px;
  margin: 0 0 32px;
  opacity: .85;
}
/* Guarantee reassurance in the closing band — sits between the sub line
   and the newsletter block, quieter than both. */
.m-cta-guarantee {
  margin: -18px 0 28px;
  font-size: 14px;
  letter-spacing: .01em;
  opacity: .75;
}
.m-cta-anchor {
  display: block;
  height: 0;
  scroll-margin-top: 140px;
}
.m-cta-form {
  display: flex;
  gap: 8px;
  max-width: 480px;
  margin: 0 auto;
  flex-wrap: wrap;
}
.m-cta-form input[type="email"] {
  flex: 1;
  min-width: 200px;
  padding: 14px 18px;
  border: 1px solid rgba(255,255,255,.18);
  border-radius: 8px;
  font: inherit;
  font-size: 15px;
  background: rgba(255,255,255,.06);
  color: #f5f1e6;
}
.m-cta-form input::placeholder { color: rgba(245,241,230,.5); }
.m-cta-form input:focus {
  outline: none;
  border-color: var(--accent-soft);
  background: rgba(255,255,255,.1);
}

/* ---------- Footer ----------
   Three tiers: brand block, four categorised link columns, bottom bar.
   The old single flat row of nine links gave every destination the
   same weight, which made the footer useless as navigation.
   `.m-foot` stays on the element as a stable hook. */
.m-foot {
  background: var(--m-band);
  border-top: 1px solid var(--m-band-line);
  padding: var(--m-s8) var(--m-gutter) var(--m-s6);
}
.m-foot-inner {
  max-width: var(--m-container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.3fr repeat(4, 1fr);
  gap: var(--m-s7) var(--m-s5);
  align-items: start;
}
@media (max-width: 960px) {
  .m-foot-inner { grid-template-columns: 1fr 1fr; gap: var(--m-s6) var(--m-s5); }
  .m-foot-brand { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .m-foot-inner { grid-template-columns: 1fr; }
}

.m-foot-brand .m-brand { margin-bottom: var(--m-s3); }
.m-foot-tagline {
  margin: 0;
  font-family: var(--font-serif);
  font-size: var(--m-fs-sm);
  line-height: 1.55;
  color: var(--ink-3);
  max-width: 30ch;
}

.m-foot-col h2 {
  margin: 0 0 var(--m-s3);
  font-family: var(--font-sans);
  font-size: var(--m-fs-eyebrow);
  font-weight: 700;
  letter-spacing: var(--m-track-eyebrow);
  text-transform: uppercase;
  color: var(--ink-2);
}
.m-foot-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.m-foot-col a {
  color: var(--ink-3);
  text-decoration: none;
  font-size: var(--m-fs-sm);
  transition: color .15s ease;
}
.m-foot-col a:hover { color: var(--ink-1); }

.m-foot-bottom {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--m-s3);
  padding-top: var(--m-s4);
  border-top: 1px solid var(--m-band-line);
}
/* ink-4 on white is ~2.9:1 — below AA even for fine print. ink-3 is
   the quietest tone that still passes, so fine print stops there. */
.m-foot-fineprint {
  margin: 0;
  font-size: var(--m-fs-xs);
  color: var(--ink-3);
}

/* ============================================================
   Contact page — public form with honeypot + anti-spam
   ============================================================ */
.m-contact-main { padding: 64px 28px 96px; }
.m-contact-wrap {
  max-width: 680px;
  margin: 0 auto;
}
.m-contact-head {
  text-align: center;
  margin-bottom: 36px;
}
.m-contact-head .m-eyebrow { margin-bottom: 10px; }
.m-contact-title {
  font-family: var(--font-display);
  font-size: 42px;
  font-weight: 600;
  margin: 0 0 12px;
  color: var(--ink-1);
  letter-spacing: -.01em;
}
.m-contact-sub {
  font-family: var(--font-serif);
  font-size: 17px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0;
}
.m-contact-sub a { color: var(--accent); text-decoration: none; }
.m-contact-sub a:hover { text-decoration: underline; }

.m-contact-form {
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  padding: 36px;
  margin-top: 24px;
  box-shadow: var(--shadow-1);
  display: flex;
  flex-direction: column;
  gap: 18px;
}
@media (max-width: 520px) { .m-contact-form { padding: 24px; } }
.m-contact-form .field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
@media (max-width: 520px) { .m-contact-form .field-row { grid-template-columns: 1fr; } }
.m-contact-form input[type="text"],
.m-contact-form input[type="email"],
.m-contact-form textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  font: inherit;
  font-size: 15px;
  background: var(--bg-card);
  color: var(--ink-1);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.m-contact-form textarea { resize: vertical; min-height: 140px; line-height: 1.55; }
.m-contact-form input:focus,
.m-contact-form textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}

/* Honeypot: position off-screen + size 0 so visitors never tab to or
   see it; bots fill every input they find. CSS display:none would
   also work but some bots filter that — off-screen is sneakier. */
.m-honeypot {
  position: absolute;
  left: -9999px;
  top: -9999px;
  height: 0;
  width: 0;
  overflow: hidden;
  opacity: 0;
}

.m-contact-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.m-contact-fineprint {
  font-size: 12.5px;
  color: var(--ink-3);
  flex: 1;
  min-width: 200px;
}
.m-contact-fineprint a { color: var(--accent); text-decoration: none; }
.m-contact-fineprint a:hover { text-decoration: underline; }

/* NOTE (2026-07 admin redesign): the admin LAYOUT primitives that used
   to live here (tab strips, tab rails, collapsible nav groups, cron/log
   viewers, nav badges) moved to the admin section of scrived.css so the
   admin chrome has one home and one 900px breakpoint. Page-specific
   admin component styles (tier rows, ticket threads, newsletter
   audience, announcement list, …) still live further down in this file.
   Upload both CSS files together. */

/* ============================================================
   Legal pages — Terms of Service + Privacy Policy
   Reading-comfort layout: narrow column, generous line-height,
   serif body to feel like a real document not a marketing surface.
   ============================================================ */
.legal-body { background: var(--bg-page); }
.legal-main {
  padding: 56px 28px 96px;
}
.legal-doc {
  max-width: 760px;
  margin: 0 auto;
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  padding: 56px 64px;
  box-shadow: var(--shadow-1);
}
@media (max-width: 600px) {
  .legal-doc { padding: 40px 28px; border-radius: 8px; }
  .legal-main { padding: 32px 16px 64px; }
}
.legal-head {
  text-align: left;
  margin-bottom: 36px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--line-soft);
}
.legal-head .m-eyebrow { margin-bottom: 10px; }
.legal-title {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 600;
  margin: 0 0 8px;
  color: var(--ink-1);
  letter-spacing: -.01em;
}
.legal-meta {
  margin: 0;
  font-size: 13px;
  color: var(--ink-3);
  font-style: italic;
}

.legal-prose {
  font-family: var(--font-serif);
  font-size: 16px;
  line-height: 1.7;
  color: var(--ink-2);
}
.legal-prose h2 {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 600;
  color: var(--ink-1);
  margin: 36px 0 14px;
  padding-top: 8px;
}
.legal-prose h2:first-child { margin-top: 0; padding-top: 0; }
.legal-prose h3 {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  color: var(--ink-1);
  margin: 28px 0 10px;
}
.legal-prose p {
  margin: 0 0 16px;
}
.legal-prose ul {
  margin: 0 0 18px;
  padding-left: 24px;
}
.legal-prose li {
  margin-bottom: 8px;
}
.legal-prose strong { color: var(--ink-1); font-weight: 600; }
.legal-prose a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
.legal-prose a:hover { color: var(--accent-soft); }
.legal-prose hr { border: none; border-top: 1px solid var(--line); margin: 28px 0; }

.legal-empty {
  font-family: var(--font-serif);
  font-style: italic;
  color: var(--ink-3);
  text-align: center;
  padding: 28px;
}
.legal-empty a { color: var(--accent); text-decoration: none; }
.legal-empty a:hover { text-decoration: underline; }

.legal-foot {
  margin-top: 40px;
  padding-top: 24px;
  border-top: 1px solid var(--line-soft);
  text-align: right;
}
.legal-partner-link {
  color: var(--ink-3);
  text-decoration: none;
  font-size: 14px;
  font-family: var(--font-sans);
}
.legal-partner-link:hover { color: var(--accent); }

/* Admin legal-editor textareas — bigger, monospaced so markdown
   structure is easy to scan. */
.admin-legal-textarea {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 13px;
  line-height: 1.55;
  white-space: pre;
}

/* ============================================================
   Maintenance page — same token system, accent overridable via
   the admin (see <style> block in marketing/maintenance.php).
   ============================================================ */
.maintenance-body {
  margin: 0;
  background: var(--bg-page);
  color: var(--ink-1);
  font-family: var(--font-sans);
  min-height: 100vh;
}
.maint-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.maint-preview-banner {
  background: #fbf1cf;
  color: #6b5210;
  border-bottom: 1px solid #efdf95;
  padding: 12px 24px;
  display: flex;
  align-items: center;
  gap: 16px;
  font-size: 13.5px;
  flex-wrap: wrap;
}
.maint-preview-banner strong { font-size: 14px; }
.maint-preview-banner span { flex: 1; }

.maint-main {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
}
.maint-card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow-2);
  padding: 56px 48px;
  max-width: 540px;
  width: 100%;
  text-align: center;
}
.maint-logo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 28px;
}
.maint-logo .logo-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  background: var(--maint-accent, var(--accent));
  color: #fff;
  border-radius: 12px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 28px;
}
.maint-title {
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 600;
  margin: 0 0 16px;
  color: var(--ink-1);
}
.maint-title::after {
  content: "";
  display: block;
  width: 48px;
  height: 3px;
  background: var(--maint-accent, var(--accent));
  margin: 18px auto 0;
  border-radius: 2px;
}
.maint-message {
  font-family: var(--font-serif);
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0 0 28px;
}
.maint-meta {
  list-style: none;
  margin: 0 0 32px;
  padding: 0;
  display: grid;
  gap: 14px;
  text-align: left;
  background: var(--bg-page);
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  padding: 18px 22px;
}
.maint-meta li {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.maint-meta-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.maint-meta-value {
  font-family: var(--font-serif);
  font-size: 15.5px;
  color: var(--ink-1);
}
.maint-meta-value a {
  color: var(--maint-accent, var(--accent));
  text-decoration: none;
}
.maint-meta-value a:hover { text-decoration: underline; }

.maint-footnote {
  margin: 0;
  font-size: 13px;
  color: var(--ink-4);
}
.maint-footnote a {
  color: var(--maint-accent, var(--accent));
  text-decoration: none;
}
.maint-footnote a:hover { text-decoration: underline; }

@media (max-width: 480px) {
  .maint-card { padding: 40px 28px; }
  .maint-title { font-size: 26px; }
}

/* ============================================================
   Admin extensions for the new site-settings / pricing pages.
   These piggyback on the existing .admin-card / .admin-form
   styles in scrived.css and only add what's specific here.
   ============================================================ */
.admin-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}
.admin-card-head .admin-card-title { margin: 0; }

/* ---- Bulk-action bar (168) — the Spam view's "empty the quarantine".
   A tinted strip above the table so a destructive sweep can never be
   mistaken for one more row action. The button only goes red on hover:
   a permanently-red control in a table full of them stops registering. */
.admin-bulk-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin: 0 0 16px;
  padding: 12px 14px;
  border: 1px solid var(--danger, #a93b2a);
  border-radius: 8px;
  background: rgba(169, 59, 42, .06);
}
.admin-bulk-note {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-2, #4a463f);
  max-width: 72ch;
}
/* ---- Offenders panel (169) — "what do I actually block?" ---- */
.admin-offenders {
  margin: 0 0 16px;
  padding: 14px;
  border: 1px solid var(--line, #e4e0d8);
  border-radius: 8px;
  background: var(--bg-rail, #faf8f4);
}
.admin-offenders-intro {
  margin: 0 0 12px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-2, #4a463f);
  max-width: 80ch;
}
.admin-offenders-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}
.admin-offender-head {
  margin: 0 0 8px;
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--ink-3, #6a665e);
}
.admin-offender-none { margin: 0; font-size: 12px; color: var(--ink-3, #6a665e); }
.admin-offender-list { list-style: none; margin: 0; padding: 0; }
.admin-offender-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  border-bottom: 1px solid var(--line-soft, #efece5);
}
.admin-offender-list li:last-child { border-bottom: none; }
.admin-offender-value {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  color: var(--ink-1, #211f1b);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.admin-bulk-danger { border-color: var(--danger, #a93b2a); color: var(--danger, #a93b2a); }
.admin-bulk-danger:hover {
  background: var(--danger, #a93b2a);
  border-color: var(--danger, #a93b2a);
  color: #fff;
}

.admin-toggle {
  flex-direction: row;
  align-items: center;
  gap: 10px;
  margin: 12px 0 18px;
}
.admin-toggle input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}
.admin-toggle span { font-size: 14px; color: var(--ink-1); }

.admin-form-grid-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 720px) { .admin-form-grid-3 { grid-template-columns: 1fr; } }

.admin-form-actions-split {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-top: 12px;
}

.admin-alert-warn {
  background: #fbf1cf;
  color: #6b5210;
  border: 1px solid #efdf95;
  padding: 12px 16px;
  border-radius: 6px;
  font-size: 14px;
}

.admin-tier-list { list-style: none; padding: 0; margin: 0; }
.admin-tier-row {
  border-bottom: 1px solid var(--line-soft);
  padding: 8px 0;
}
.admin-tier-row:last-child { border-bottom: none; }
.admin-tier-row summary {
  cursor: pointer;
  list-style: none;
  padding: 14px 4px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.admin-tier-row summary::-webkit-details-marker { display: none; }
.admin-tier-row details[open] > summary {
  border-bottom: 1px solid var(--line-soft);
  margin-bottom: 18px;
}
.admin-tier-name {
  font-weight: 500;
  color: var(--ink-1);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.admin-tier-prices {
  font-size: 13px;
  color: var(--ink-3);
  font-family: var(--font-serif);
}
.admin-tier-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--accent-bg);
  color: var(--accent);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
}
.admin-tier-chip-muted {
  background: var(--bg-rail);
  color: var(--ink-3);
}
.admin-dash { color: var(--ink-4); }

/* (The dark-theme overrides for .m-nav / .m-section-alt / .m-feature /
   .m-faq / .m-mock-line that used to sit here were removed. layout.php
   force-sets data-theme="light" on every marketing page before first
   paint, so they had been unreachable for some time — and they now
   fight the .marketing-body token block at the top of this file.) */

/* ============================================================
   Outbound-message UI: contact reply thread + reply form,
   per-user email modal, newsletter compose page. Each section
   reuses the existing .admin-card / .admin-form base styles
   and only adds what's specific to the feature.
   ============================================================ */

/* ---- Contact reply thread ---- */
.admin-thread-card { margin-top: 18px; }
.admin-thread {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.admin-thread-item {
  background: var(--bg-page);
  border: 1px solid var(--line-soft);
  border-left: 3px solid var(--accent);
  border-radius: 6px;
  padding: 14px 18px;
}
.admin-thread-item-failed { border-left-color: var(--danger); }
.admin-thread-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 8px;
  font-size: 13px;
  color: var(--ink-3);
  flex-wrap: wrap;
}
.admin-thread-from strong { color: var(--ink-1); }
.admin-thread-meta { font-variant-numeric: tabular-nums; }
.admin-thread-failed {
  color: var(--danger);
  font-weight: 600;
  cursor: help;
}
.admin-thread-subject {
  margin: 0 0 8px;
  font-size: 13.5px;
  color: var(--ink-2);
}
.admin-thread-subject strong { color: var(--ink-1); }
.admin-thread-body {
  font-family: var(--font-serif);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-1);
  white-space: pre-wrap;
  word-wrap: break-word;
}

/* ---- Reply / compose form ---- */
.admin-reply-card,
.admin-compose-card { margin-top: 18px; }
.admin-form-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 14px;
}
.admin-form-row > label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
  letter-spacing: .02em;
}
.admin-form-row input[type="text"],
.admin-form-row input[type="email"],
.admin-form-row textarea,
.admin-form-row select {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 14px;
  background: var(--bg-card);
  color: var(--ink-1);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.admin-form-row textarea {
  resize: vertical;
  min-height: 140px;
  font-family: var(--font-sans);
  line-height: 1.55;
}
.admin-form-row input[type="text"]:focus,
.admin-form-row input[type="email"]:focus,
.admin-form-row textarea:focus,
.admin-form-row select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}

.admin-newsletter-history { margin-top: 18px; }

/* ---- Newsletter compose toolbar (bold/italic/bulleted list) ---- */
.nl-toolbar {
  display: flex;
  gap: 6px;
  margin-bottom: 8px;
}
.nl-tool-btn {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  border: 1px solid var(--line);
  background: var(--bg-card);
  color: var(--ink-2);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  padding: 4px 10px;
}
.nl-tool-btn:hover { background: var(--bg-rail); border-color: var(--line-strong); color: var(--ink-1); }

/* ---- Site Images admin page (was "Screenshots") ---- */

/* Collapsible sections: every [data-collapse-key] box (the four cards
   plus each Page-slots group) pairs a .collapse-toggle button with a
   .collapse-body. Direct-child selectors keep a collapsed outer card
   from also styling the groups nested inside it. display:none rather
   than a max-height transition — these bodies hold unbounded grids. */
.collapse-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0;
  margin: 0;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
}
.admin-card-chevron {
  font-size: 12px;
  line-height: 1;
  color: var(--ink-3);
  transition: transform .15s ease;
}
.is-collapsed > .admin-card-head .admin-card-chevron,
.is-collapsed > .collapse-toggle .admin-card-chevron {
  transform: rotate(-90deg);
}
[data-collapse-key].is-collapsed > .collapse-body { display: none; }
.admin-card.is-collapsed .admin-card-head { margin-bottom: 0; }

/* Page-slots group headers: the h3 moved inside the toggle button, so
   its old margins live on the button now. */
.screenshot-group-toggle { margin: 22px 0 10px; width: 100%; }
/* button. prefix outranks the later .admin-card-subhead:first-of-type
   margin rule, which would otherwise re-add a top margin inside the
   toggle (every h3 is first-of-type within its own button). */
button.screenshot-group-toggle .admin-card-subhead { margin: 0; }
.screenshot-slot-group:first-of-type .screenshot-group-toggle { margin-top: 6px; }

/* Hero-shot preview */
.screenshot-preview {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  margin: 0 0 18px;
  background: var(--bg-paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.screenshot-preview-hero img {
  width: 100%;
  max-width: 560px;
  height: auto;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  display: block;
}
.screenshot-preview .screenshot-caption {
  margin: 0;
  font-size: 13px;
  color: var(--ink-3);
  font-style: italic;
}
.screenshot-preview .screenshot-actions {
  display: flex;
  justify-content: flex-start;
}

/* Named page slots (migration 102). Deliberately NOT .screenshot-grid:
   that id/class pair drives the gallery's drag-to-reorder script, and
   slots have a fixed position in the design — nothing to reorder. */
.admin-card-subhead {
  margin: 22px 0 10px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.admin-card-subhead:first-of-type { margin-top: 6px; }
.screenshot-slot-grid {
  list-style: none;
  padding: 0;
  margin: 0 0 8px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 14px;
}
.screenshot-slot {
  background: var(--bg-paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
}
.screenshot-slot.is-filled { border-color: var(--accent); }
.screenshot-slot-label {
  margin: 0 0 10px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-1);
}
.screenshot-slot-img {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--bg-card);
  margin-bottom: 10px;
}
.screenshot-slot-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.screenshot-slot-empty {
  margin: 0 0 10px;
  font-size: 12.5px;
  font-style: italic;
  color: var(--ink-3);
}
.screenshot-slot-form { margin: 0; }

/* Gallery tile grid (drag-to-reorder) */
.screenshot-grid {
  list-style: none;
  padding: 0;
  margin: 0 0 18px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
}
.screenshot-tile {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  background: var(--bg-paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: grab;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.screenshot-tile:hover { border-color: var(--line-strong); }
.screenshot-tile.is-dragging {
  opacity: .55;
  cursor: grabbing;
  border-color: var(--accent);
  box-shadow: 0 4px 12px rgba(0,0,0,.12);
}
.screenshot-tile-img {
  width: 100%;
  aspect-ratio: 16 / 10;
  background: var(--bg-card);
  border-radius: var(--radius-sm);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.screenshot-tile-img img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.screenshot-tile-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.screenshot-tile-form .field-tight {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.screenshot-tile-form .field-label {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink-3);
  letter-spacing: .02em;
  text-transform: uppercase;
}
.screenshot-tile-form input[type="text"] {
  padding: 6px 9px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 13px;
  background: var(--bg-card);
}
.screenshot-tile-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding-top: 4px;
}

/* Upload form — used for both hero + gallery panels. */
.screenshot-upload-form {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--line-soft);
}
.screenshot-upload-form input[type="file"] {
  padding: 8px 0;
  font-size: 13px;
}

/* ---- Announcements admin page ---- */
/* Each announcement is a <details> so the list collapses to a
   summary row by default; the admin clicks to expand the edit
   form. Kind shows as a colored pill on the left of the summary. */
.admin-announce-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.admin-announce-item {
  background: var(--bg-paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.admin-announce-item.is-paused {
  opacity: .65;
}
.admin-announce-item details > summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.admin-announce-item details > summary::-webkit-details-marker { display: none; }
.admin-announce-item details[open] > summary {
  border-bottom: 1px solid var(--line);
  background: var(--bg-card);
}
.admin-announce-pill {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  padding: 3px 10px;
  border-radius: 999px;
}
.admin-announce-pill-info    { background: #eef4f9; color: #1f4a6a; }
.admin-announce-pill-success { background: #eef7ec; color: #2d5a1f; }
.admin-announce-pill-warning { background: var(--accent-bg); color: var(--accent); }

.admin-announce-summary-text {
  flex: 1;
  font-size: 14px;
  color: var(--ink-1);
  line-height: 1.4;
}
.admin-announce-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--ink-3);
  flex-shrink: 0;
}
.admin-announce-form {
  padding: 16px;
  background: var(--bg-card);
}

/* ============================================================
   Support tickets — user-side + admin shared pieces (status pills
   and unread dots get used on both sides). The thread styling
   mirrors the contact-reply thread already in use in marketing.css
   so this slots in without new design language.
   ============================================================ */

/* Status pills — used in the ticket list rows and the detail
   header. Each maps to one of the four states; colors echo the
   announcement-kind palette so the visual language is coherent. */
.support-status-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  white-space: nowrap;
}
.support-status-pill-open        { background: #eef4f9; color: #1f4a6a; }
.support-status-pill-in_progress { background: var(--accent-bg); color: var(--accent); }
.support-status-pill-resolved    { background: #eef7ec; color: #2d5a1f; }
.support-status-pill-closed      { background: var(--bg-rail); color: var(--ink-3); }

/* Priority pill — same shape as the status pill, its own color scale.
   Deliberately quiet at the low end and loud at urgent so a ticket list
   scans by severity at a glance. */
.support-priority-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  white-space: nowrap;
}
.support-priority-pill-low      { background: var(--bg-rail); color: var(--ink-3); }
.support-priority-pill-normal   { background: #eef4f9; color: #1f4a6a; }
.support-priority-pill-high     { background: #fdf1de; color: #8a5a12; }
.support-priority-pill-urgent   { background: #fde6e6; color: #8a1f1f; }

/* Source / spam tags on admin ticket rows. "Contact" marks a guest ticket
   that came from the public contact form; "Spam" marks one the per-IP rate
   limit flagged. Smaller + quieter than the status/priority pills so they
   read as secondary metadata. */
.support-source-pill,
.support-spam-pill {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-radius: 999px;
  vertical-align: 1px;
  white-space: nowrap;
}
.support-source-pill { background: var(--bg-rail); color: var(--ink-3); }
.support-spam-pill   { background: #fde6e6; color: #8a1f1f; }

/* Small dot indicator. Used on the user's "Support" topbar link
   and admin's ticket-list rows. */
.support-unread-dot,
.topbar-unread-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  margin-right: 4px;
  vertical-align: middle;
}
.topbar-unread-dot {
  margin-left: 4px;
  margin-right: 0;
  background: var(--danger);
}

/* ---- User-side support pages ---- */
.support-main {
  max-width: 760px;
  margin: 0 auto;
  padding: 32px 24px 80px;
}
.support-hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 24px;
}
.support-title {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 600;
  margin: 0;
  color: var(--ink-1);
}
.support-sub {
  margin: 0;
  font-size: 14px;
  color: var(--ink-3);
  line-height: 1.5;
}

.support-empty {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 40px 28px;
  text-align: center;
  color: var(--ink-3);
}
.support-empty p { margin: 0; }
.support-empty-sub { font-size: 13px; margin-top: 8px !important; }

.support-card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 22px 24px;
  margin-bottom: 18px;
}
.support-card-title {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  margin: 0 0 12px;
  color: var(--ink-1);
}
.support-card-closed {
  background: var(--bg-rail);
  color: var(--ink-3);
  text-align: center;
  font-size: 13.5px;
}

.support-form .field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 14px;
}
.support-form .field-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
  letter-spacing: .02em;
}
.support-form input[type="text"],
.support-form textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 14px;
  background: var(--bg-card);
  color: var(--ink-1);
}
.support-form input[type="text"]:focus,
.support-form textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}
.support-form textarea {
  resize: vertical;
  min-height: 120px;
  line-height: 1.55;
}
.support-form-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 10px;
}

/* Ticket list — clickable rows w/ status pill on the right. */
.support-ticket-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.support-ticket-row {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.support-ticket-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 18px;
  text-decoration: none;
  color: var(--ink-1);
  transition: background .12s ease;
}
.support-ticket-link:hover { background: var(--bg-paper); }
.support-ticket-main {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  flex: 1;
}
.support-ticket-subject {
  font-weight: 600;
  font-size: 15px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.support-ticket-meta {
  font-size: 12.5px;
  color: var(--ink-3);
}

/* Conversation thread — used on both /support/{id} and
   /admin/support/{id}. Admin messages get a left-accent strip,
   user messages stay paper-color. */
.support-thread {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.support-thread-item {
  background: var(--bg-paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 18px;
}
.support-thread-item-admin {
  border-left: 3px solid var(--accent);
}
.support-thread-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 8px;
  font-size: 13px;
  gap: 12px;
}
.support-thread-head strong { color: var(--ink-1); }
.support-thread-time {
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
}
.support-thread-body {
  font-family: var(--font-serif);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-1);
  white-space: pre-wrap;
  word-wrap: break-word;
}

/* Admin filter form on the support list page sits on the right
   side of the card header. */
.admin-filter-form {
  margin-left: auto;
}
.admin-filter-form select {
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--bg-card);
  font: inherit;
  font-size: 13px;
}

/* Admin dashboard support card — recent tickets list. */
.admin-dashboard-tickets {
  list-style: none;
  padding: 0;
  margin: 12px 0 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.admin-dashboard-ticket-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: var(--ink-1);
  font-size: 13px;
  transition: background .12s ease;
}
.admin-dashboard-ticket-row:hover { background: var(--bg-paper); }
.admin-dashboard-ticket-subject {
  flex: 1;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ==========================================================
   Billing — subscription card on /settings, checkout pages
   (success + claim), admin billing config form.
   ========================================================== */

/* ----- Subscription card on /settings ----- */
.settings-sub-empty {
  color: var(--ink-3);
  font-size: 14.5px;
}
.settings-sub-summary {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 14px;
  padding: 14px 16px;
  background: var(--bg-paper, #f5f3ee);
  border: 1px solid var(--line-1, #e2dcd0);
  border-radius: 10px;
}
.settings-sub-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  font-size: 14.5px;
}
.settings-sub-label {
  color: var(--ink-3, #6a665e);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.settings-sub-value {
  color: var(--ink-1, #1a1a1a);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.settings-sub-pill {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  background: #eee9dd;
  color: #6a4d09;
}
.settings-sub-pill-active   { background: #dfead0; color: #2f5e16; }
.settings-sub-pill-trialing { background: #dfead0; color: #2f5e16; }
.settings-sub-pill-past_due { background: #fbe2d1; color: #9c4a0a; }
.settings-sub-pill-canceled { background: #ece8df; color: #5a5650; }
.settings-sub-pill-comped   { background: #ddeaf8; color: #1f4970; }

/* ----- /checkout/success and /checkout/claim ----- */
.checkout-main {
  min-height: 60vh;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 60px 20px 80px;
  background: var(--bg-page, #f5f3ee);
}
.checkout-card {
  max-width: 540px;
  width: 100%;
  background: var(--bg-card, #fff);
  border: 1px solid var(--line-1, #e2dcd0);
  border-radius: 16px;
  padding: 40px 36px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.04);
}
.checkout-title {
  font-family: var(--font-display, Georgia, serif);
  color: var(--accent, #8b6914);
  margin: 0 0 12px;
  font-size: 28px;
  letter-spacing: -0.01em;
}
.checkout-sub {
  color: var(--ink-2, #4a4641);
  font-size: 16px;
  line-height: 1.55;
  margin: 0 0 18px;
}
.checkout-sub-fine {
  color: var(--ink-3, #6a665e);
  font-size: 14px;
  margin: -6px 0 18px;
}
.checkout-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 22px;
}
.checkout-form .field input[disabled] {
  background: var(--bg-paper, #f5f3ee);
  color: var(--ink-3, #6a665e);
  cursor: not-allowed;
}
.checkout-form-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 4px;
}

/* ----- Admin billing form ----- */
.admin-fieldset {
  border: 1px solid var(--line-1, #e2dcd0);
  border-radius: 10px;
  padding: 14px 16px 8px;
  margin: 14px 0 8px;
  background: var(--bg-paper, #f5f3ee);
}
.admin-fieldset > legend {
  font-size: 12.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-3, #6a665e);
  padding: 0 6px;
}
.field-inline {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  font-size: 13px;
  color: var(--ink-3, #6a665e);
}
.field-inline input[type="checkbox"] {
  margin: 0;
}

/* ==========================================================
   Blog + Articles
   - Public /blog (index + tag + single article)
   - Admin /admin/articles (list + editor)
   ========================================================== */

/* ----- Public blog index ----- */
.blog-main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 60px 20px 80px;
}
.blog-head { text-align: center; margin-bottom: 32px; }
.blog-eyebrow {
  color: var(--ink-3, #6a665e);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin: 0 0 6px;
}
.blog-eyebrow a { color: inherit; text-decoration: none; }
.blog-eyebrow a:hover { color: var(--accent, #8b6914); }
.blog-title {
  font-family: var(--font-display, Georgia, serif);
  font-size: 40px;
  letter-spacing: -0.015em;
  margin: 0 0 8px;
  color: var(--ink-1, #1a1a1a);
}
.blog-sub {
  color: var(--ink-3, #6a665e);
  font-size: 16.5px;
  margin: 0 0 18px;
}
.blog-taglist {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
  max-width: 720px;
  margin: 18px auto 0;
}
.blog-tag-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--bg-paper, #f5f3ee);
  border: 1px solid var(--line-1, #e2dcd0);
  color: var(--ink-2, #4a4641);
  font-size: 13px;
  text-decoration: none;
  transition: background .12s ease, border-color .12s ease;
}
.blog-tag-link:hover { background: var(--bg-card, #fff); border-color: var(--accent, #8b6914); color: var(--accent, #8b6914); }
.blog-tag-link.is-active {
  background: var(--accent, #8b6914);
  border-color: var(--accent, #8b6914);
  color: #fff;
}
.blog-tag-count {
  background: rgba(0,0,0,0.08);
  border-radius: 999px;
  padding: 0 8px;
  font-size: 11px;
  font-weight: 600;
}
.blog-tag-link.is-active .blog-tag-count { background: rgba(255,255,255,0.25); }
/* Collapsed tag cloud (marketing.js). The toggle is the last flex child
   so it reads as one more pill at the end of the second row rather than
   a separate control under the list. */
.blog-tag-more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  background: transparent;
  border: 1px dashed var(--line-1, #e2dcd0);
  color: var(--ink-3, #6a665e);
  font: inherit;
  font-size: 13px;
  line-height: inherit;
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.blog-tag-more:hover {
  background: var(--bg-card, #fff);
  border-color: var(--accent, #8b6914);
  color: var(--accent, #8b6914);
}
.blog-tag-more:focus-visible {
  outline: 2px solid var(--accent, #8b6914);
  outline-offset: 2px;
}
/* [hidden] alone can't win against .blog-tag-link's display:inline-flex,
   so the collapsed pills need this explicitly — otherwise they stay
   visible AND keyboard-focusable. */
.blog-taglist .blog-tag-link[hidden],
.blog-taglist .blog-tag-more[hidden] { display: none; }
.blog-empty {
  text-align: center;
  color: var(--ink-3, #6a665e);
  padding: 60px 20px;
}

/* ----- Hero card ----- */
.blog-hero {
  margin: 0 0 36px;
  background: var(--bg-card, #fff);
  border: 1px solid var(--line-1, #e2dcd0);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 6px 28px rgba(0,0,0,0.04);
}
.blog-hero-link {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 0;
  text-decoration: none;
  color: inherit;
}
.blog-hero-image {
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--bg-paper, #f5f3ee);
}
.blog-hero-image img { width: 100%; height: 100%; object-fit: cover; display: block; }
.blog-hero-meta { padding: 36px 36px 30px; display: flex; flex-direction: column; justify-content: center; }
.blog-hero-title {
  font-family: var(--font-display, Georgia, serif);
  font-size: 30px;
  letter-spacing: -0.01em;
  margin: 8px 0 14px;
  color: var(--ink-1, #1a1a1a);
  line-height: 1.18;
}
.blog-hero-excerpt {
  color: var(--ink-2, #4a4641);
  font-size: 15.5px;
  line-height: 1.55;
  margin: 0 0 14px;
}
@media (max-width: 768px) {
  .blog-hero-link { grid-template-columns: 1fr; }
  .blog-hero-meta { padding: 24px; }
  .blog-hero-title { font-size: 24px; }
}

/* ----- Card grid ----- */
.blog-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
@media (max-width: 960px) { .blog-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .blog-grid { grid-template-columns: 1fr; } }
.blog-card {
  background: var(--bg-card, #fff);
  border: 1px solid var(--line-1, #e2dcd0);
  border-radius: 12px;
  overflow: hidden;
  transition: box-shadow .15s ease, transform .15s ease;
}
.blog-card:hover { box-shadow: 0 8px 22px rgba(0,0,0,0.06); transform: translateY(-2px); }
.blog-card-link { display: block; text-decoration: none; color: inherit; }
.blog-card-image { aspect-ratio: 16 / 10; overflow: hidden; background: var(--bg-paper, #f5f3ee); }
.blog-card-image img { width: 100%; height: 100%; object-fit: cover; display: block; }
.blog-card-body { padding: 18px 18px 20px; }
.blog-card-tags { display: inline-flex; gap: 6px; margin-bottom: 8px; flex-wrap: wrap; }
.blog-card-tag {
  background: var(--bg-paper, #f5f3ee);
  color: var(--ink-3, #6a665e);
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.blog-card-title {
  font-family: var(--font-display, Georgia, serif);
  font-size: 19.5px;
  line-height: 1.25;
  margin: 0 0 8px;
  color: var(--ink-1, #1a1a1a);
}
.blog-card-excerpt {
  color: var(--ink-2, #4a4641);
  font-size: 14.5px;
  line-height: 1.5;
  margin: 0 0 12px;
}
.blog-card-byline {
  color: var(--ink-3, #6a665e);
  font-size: 12.5px;
  margin: 0;
}
.blog-card-author { color: var(--ink-2, #4a4641); font-weight: 500; }

/* ----- Pager ----- */
.blog-pager {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  margin-top: 48px;
}
.blog-pager-status { color: var(--ink-3, #6a665e); font-size: 13.5px; }

/* ----- Single article ----- */
.article-main { max-width: 760px; margin: 0 auto; padding: 60px 20px 80px; }
.article-head { margin-bottom: 32px; text-align: center; }
.article-breadcrumb {
  color: var(--ink-3, #6a665e);
  font-size: 13px;
  letter-spacing: 0.04em;
  margin: 0 0 12px;
}
.article-breadcrumb a { color: inherit; text-decoration: none; }
.article-breadcrumb a:hover { color: var(--accent, #8b6914); }
.article-title {
  font-family: var(--font-display, Georgia, serif);
  font-size: 44px;
  letter-spacing: -0.015em;
  line-height: 1.12;
  margin: 0 0 12px;
  color: var(--ink-1, #1a1a1a);
}
@media (max-width: 600px) { .article-title { font-size: 30px; } }
.article-subtitle {
  font-family: var(--font-display, Georgia, serif);
  font-size: 20px;
  color: var(--ink-2, #4a4641);
  font-style: italic;
  margin: 0 0 16px;
  line-height: 1.4;
}
.article-byline {
  color: var(--ink-3, #6a665e);
  font-size: 14px;
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}
.article-byline-author { color: var(--ink-2, #4a4641); font-weight: 500; }
.article-byline > * + *::before { content: "·"; margin-right: 12px; color: var(--line-1, #e2dcd0); }
.article-cover { margin: 24px -20px 32px; }
.article-cover img {
  width: 100%;
  max-height: 480px;
  object-fit: cover;
  border-radius: 12px;
  display: block;
}
/* Prose typography for the rendered article HTML. This block is a
   CONTENT scope, not a page scope — it restyles bare tags (a, h2, p,
   ul, hr), so it must only ever be applied to the
   <div class="article-body"> wrapper around the article body.
   blog/show.php used to also put `article-body` on <body>, which leaked
   every rule below across the nav and footer (unstyled-looking gold
   underlined nav links, footer column headings blown up to 30px). The
   page-level class is now `article-page`. */
.article-body {
  font-family: 'Lora', Georgia, serif;
  font-size: 18px;
  line-height: 1.72;
  color: var(--ink-1, #1a1a1a);
}
.article-body > * + * { margin-top: 1.2em; }
.article-body h2 {
  font-family: var(--font-display, Georgia, serif);
  font-size: 30px;
  margin-top: 1.8em;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.article-body h3 {
  font-family: var(--font-display, Georgia, serif);
  font-size: 22px;
  margin-top: 1.6em;
  line-height: 1.25;
}
.article-body h4 {
  font-family: var(--font-display, Georgia, serif);
  font-size: 18px;
  margin-top: 1.5em;
}
.article-body p { margin: 1.2em 0; }
.article-body img {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
  display: block;
  margin: 1.6em auto;
}
.article-body blockquote {
  border-left: 3px solid var(--accent, #8b6914);
  padding: 6px 0 6px 22px;
  margin: 1.6em 0;
  font-style: italic;
  color: var(--ink-2, #4a4641);
}
.article-body code {
  background: var(--bg-paper, #f5f3ee);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.88em;
}
.article-body pre {
  background: #1d1c19;
  color: #f3eddf;
  padding: 18px 22px;
  border-radius: 10px;
  font-size: 14.5px;
  overflow-x: auto;
  line-height: 1.5;
}
.article-body pre code { background: none; padding: 0; color: inherit; }
.article-body a { color: var(--accent, #8b6914); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; }
.article-body ul, .article-body ol { padding-left: 1.5em; }
.article-body hr { border: none; border-top: 1px solid var(--line-1, #e2dcd0); margin: 2em 0; }

.article-tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 48px 0 24px;
  padding: 18px 0 0;
  border-top: 1px solid var(--line-1, #e2dcd0);
}
.article-tags-label { color: var(--ink-3, #6a665e); font-size: 13px; margin-right: 4px; }
.article-tag {
  display: inline-block;
  padding: 4px 11px;
  background: var(--bg-paper, #f5f3ee);
  border-radius: 999px;
  font-size: 13px;
  color: var(--ink-2, #4a4641);
  text-decoration: none;
}
.article-tag:hover { background: var(--accent, #8b6914); color: #fff; }

.article-share {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  margin: 24px 0;
}
.article-share-label { color: var(--ink-3, #6a665e); font-size: 13px; }
.article-share a { color: var(--accent, #8b6914); text-decoration: none; font-size: 14px; }
.article-share a:hover { text-decoration: underline; }

.article-related {
  margin-top: 64px;
  padding-top: 32px;
  border-top: 1px solid var(--line-1, #e2dcd0);
}
.article-related-title {
  font-family: var(--font-display, Georgia, serif);
  font-size: 24px;
  margin: 0 0 20px;
}
.article-related-grid {
  list-style: none;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
@media (max-width: 800px) { .article-related-grid { grid-template-columns: 1fr; } }

/* ----- Status pills (used in admin list + sidebar) ----- */
.article-status-pill {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: #eee9dd;
  color: #6a4d09;
}
.article-status-pill-draft     { background: #ece8df; color: #5a5650; }
.article-status-pill-published { background: #dfead0; color: #2f5e16; }
.article-status-pill-scheduled { background: #ddeaf8; color: #1f4970; }

/* ----- Admin article editor ----- */
.article-editor-main { padding-bottom: 80px; }
.article-editor-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 16px;
  flex-wrap: wrap;
}
.article-editor-head-actions { display: flex; gap: 8px; align-items: center; }
.admin-page-eyebrow {
  color: var(--ink-3, #6a665e);
  font-size: 13px;
  margin: 0 0 4px;
}
.admin-page-eyebrow a { color: inherit; text-decoration: none; }
.admin-page-eyebrow a:hover { color: var(--accent, #8b6914); }

.article-save-status {
  margin-left: 8px;
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 999px;
  background: #dfead0;
  color: #2f5e16;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.article-save-status[data-state="dirty"]  { background: #fbe2d1; color: #9c4a0a; }
.article-save-status[data-state="saving"] { background: #ddeaf8; color: #1f4970; }
.article-save-status[data-state="error"]  { background: #f6cccc; color: #8b1f1f; }

.article-editor-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 24px;
  align-items: start;
}
@media (max-width: 1100px) { .article-editor-layout { grid-template-columns: 1fr; } }

.article-editor-main-col .field { margin-bottom: 14px; }
.field-counter {
  margin-left: 6px;
  font-size: 11.5px;
  color: var(--ink-3, #6a665e);
  font-weight: 500;
}
.field-counter.is-over { color: #c93232; }

.article-editor-body-wrap {
  margin-top: 8px;
}
.article-editor-body-wrap .field-label { display: block; margin-bottom: 8px; }
#article-editor {
  background: var(--bg-card, #fff);
  border: 1px solid var(--line-1, #e2dcd0);
  border-bottom-left-radius: 10px;
  border-bottom-right-radius: 10px;
  min-height: 480px;
  font-family: 'Lora', Georgia, serif;
  font-size: 16.5px;
  line-height: 1.7;
}
.ql-toolbar.ql-snow {
  border: 1px solid var(--line-1, #e2dcd0);
  border-bottom: none;
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
  background: var(--bg-paper, #f5f3ee);
}
/* Sticky toolbar — stays at the top of the viewport while the
   editor body scrolls, so the formatting controls are always
   reachable from anywhere in a long article. Scoped to the
   article editor so other Quill mounts in the app (book editor,
   share-reader comments) aren't affected. */
.article-editor-body-wrap .ql-toolbar.ql-snow {
  position: sticky;
  top: 0;
  z-index: 5;
  /* Opaque background so editor text scrolling underneath doesn't
     bleed through the toolbar's spaces between buttons. */
  background: var(--bg-paper, #f5f3ee);
}

.article-editor-sidebar {
  display: flex;
  flex-direction: column;
  gap: 14px;
  position: sticky;
  top: 16px;
}
@media (max-width: 1100px) {
  .article-editor-sidebar { position: static; }
}
.article-editor-card {
  background: var(--bg-card, #fff);
  border: 1px solid var(--line-1, #e2dcd0);
  border-radius: 10px;
  padding: 14px 16px;
}
.article-editor-card-title {
  font-size: 12.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-3, #6a665e);
  margin: 0 0 10px;
}
.article-editor-card-sub {
  color: var(--ink-2, #4a4641);
  font-size: 13.5px;
  margin: 0;
}
.article-editor-form-actions { margin-top: 10px; }
.btn-block { width: 100%; display: block; text-align: center; }

/* Schedule card: what's already on the publishing calendar (v2.53) —
   the native date picker can't be marked, so the list + conflict
   warning live beside the field instead. */
.article-schedule-conflict {
  color: #a15c00;
  background: #fdf3e2;
  border: 1px solid #eed9b0;
  border-radius: 6px;
  padding: 6px 9px;
  margin: 0 0 8px;
}
.article-schedule-conflict[hidden] { display: none; }
.article-schedule-upcoming { margin-top: 10px; }
.article-schedule-upcoming-list {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
  max-height: 180px;
  overflow-y: auto;
  border-top: 1px solid var(--line, #e5decf);
}
.article-schedule-upcoming-list li {
  padding: 6px 2px;
  border-bottom: 1px solid var(--line-soft, var(--line, #efe9db));
  font-size: 12.5px;
  line-height: 1.4;
}
.article-schedule-upcoming-date {
  display: block;
  color: var(--ink-3, #6a665e);
  font-variant-numeric: tabular-nums;
  font-size: 11.5px;
}
.article-schedule-upcoming-title {
  display: block;
  color: var(--ink-1, #201d19);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.article-schedule-upcoming-title:hover { text-decoration: underline; }

.article-editor-cover {
  aspect-ratio: 16 / 10;
  background: var(--bg-paper, #f5f3ee);
  border: 1px dashed var(--line-1, #e2dcd0);
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 10px;
}
.article-editor-cover img { width: 100%; height: 100%; object-fit: cover; }
.article-editor-cover-empty {
  color: var(--ink-3, #6a665e);
  font-size: 13px;
  text-align: center;
  padding: 14px;
}

/* ==========================================================
   Landing page — section components (.mk-*)
   ----------------------------------------------------------
   These replaced the older .m2-* block. The split is now by
   role rather than by vintage:

     .m-*   shared public-site primitives — nav, section, hero,
            eyebrow, faq, footer. Used by /tools (6 pages) and
            the blog as well as the homepage, so they change
            carefully.
     .mk-*  homepage-only section components. Free to change.

   Everything below sits on the token block at the top of this
   file, so section rhythm and card chrome stay consistent
   without repeating literals.
   ========================================================== */

/* Keeps historical /#features links landing somewhere sensible now
   that the feature-pillar grid has become the stage grid. Zero-height
   so it never affects layout; scroll-margin clears the sticky nav. */
.mk-anchor-alias {
  display: block;
  height: 0;
  scroll-margin-top: 120px;
}

/* Shared media frame for every card image. The aspect-ratio is the
   important part: an uploaded screenshot and its CSS fallback occupy
   exactly the same box, so filling a slot in /admin/screenshots never
   reflows the page around it. */
.mk-media {
  position: relative;
  overflow: hidden;
  border-radius: var(--m-radius-sm);
  border: 1px solid var(--m-card-line);
  background: var(--bg-paper);
}
.mk-slot-img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ----- Hero ----- */
.mk-hero-title { letter-spacing: -.022em; margin: 14px 0 18px; }
.mk-hero-sub {
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0 0 var(--m-s5);
}
.mk-hero-ctas {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-wrap: wrap;
  margin: 0 0 18px;
}
.mk-hero-secondary {
  color: var(--ink-2);
  font-size: 15px;
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid var(--m-card-line-2);
  padding-bottom: 2px;
  transition: color .15s ease, border-color .15s ease;
}
.mk-hero-secondary:hover { color: var(--ink-1); border-color: var(--accent); }
.mk-hero-trust {
  margin: 0;
  font-size: var(--m-fs-xs);
  color: var(--ink-3);
}
.mk-hero-trust a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.mk-hero-trust a:hover { color: var(--accent); }

/* ----- Trust strip (under the hero) -----
   A quiet full-width rule rather than a section: it's reassurance in
   passing, not a claim that needs its own headline. */
.mk-trust {
  border-top: 1px solid var(--m-card-line);
  border-bottom: 1px solid var(--m-card-line);
  background: var(--m-band);
}
.mk-trust-inner {
  max-width: var(--m-container);
  margin: 0 auto;
  padding: var(--m-s5) var(--m-gutter);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--m-s5);
  list-style: none;
}
@media (max-width: 860px) { .mk-trust-inner { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 460px) { .mk-trust-inner { grid-template-columns: 1fr; } }
.mk-trust-inner li { display: flex; flex-direction: column; gap: 2px; }
.mk-trust-stat {
  font-family: var(--font-display);
  font-size: var(--m-fs-h4);
  font-weight: 600;
  color: var(--ink-1);
}
.mk-trust-label { font-size: var(--m-fs-xs); color: var(--ink-3); }

/* ----- Stage grid ("Pick by where your book is right now") -----
   Five self-select cards. auto-fit rather than a fixed 5 columns so
   the odd count degrades gracefully (5 → 3+2 → 2 → 1) instead of
   leaving one orphan on a row of its own at every width. */
.mk-stage-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--m-s5);
  list-style: none;
  margin: 0;
  padding: 0;
}
.mk-stage {
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
  border: 1px solid var(--m-card-line);
  border-radius: var(--m-radius);
  padding: var(--m-card-pad);
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.mk-stage:hover {
  transform: translateY(-3px);
  box-shadow: var(--m-shadow-lift);
  border-color: var(--m-card-line-2);
}
.mk-stage-media {
  aspect-ratio: 4 / 3;
  margin: calc(var(--m-card-pad) * -1) calc(var(--m-card-pad) * -1) var(--m-s4);
  border-radius: var(--m-radius) var(--m-radius) 0 0;
  border-width: 0 0 1px;
}
.mk-badge {
  align-self: flex-start;
  background: var(--m-badge-bg);
  color: var(--m-badge-ink);
  border-radius: var(--m-radius-pill);
  padding: 4px 11px;
  font-size: var(--m-fs-eyebrow);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  margin-bottom: 10px;
}
/* Gold treatment for freshly-shipped features — the deep-dive cards,
   the What's-new spotlight, and gallery captions prefixed "New:". */
.mk-badge-new {
  background: var(--m-badge-new-bg);
  color: var(--m-badge-new-ink);
  border: 1px solid var(--m-badge-new-line);
}
.mk-stage-title {
  font-family: var(--font-display);
  font-size: var(--m-fs-h3);
  font-weight: 600;
  margin: 0 0 6px;
  color: var(--ink-1);
}
.mk-stage-promise {
  font-family: var(--font-serif);
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0;
}
.mk-stage-hint {
  text-align: center;
  margin: var(--m-s6) 0 0;
  font-size: var(--m-fs-sm);
  color: var(--ink-3);
}
.mk-stage-hint a { color: var(--accent); }

/* ----- All-in-one card (under the stage grid) ----- */
.mk-allin {
  margin-top: var(--m-s6);
  background: var(--bg-card);
  border: 1px solid var(--m-card-line-2);
  border-radius: var(--m-radius);
  padding: var(--m-s7) var(--m-s6);
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--m-s6);
  box-shadow: var(--m-shadow-card);
}
@media (max-width: 760px) { .mk-allin { grid-template-columns: 1fr; text-align: center; } }
.mk-allin-title {
  font-family: var(--font-display);
  font-size: var(--m-fs-h3);
  font-weight: 600;
  margin: 6px 0 6px;
  color: var(--ink-1);
}
.mk-allin-sub {
  font-family: var(--font-serif);
  font-size: 15.5px;
  color: var(--ink-2);
  margin: 0;
}
.mk-allin-buy { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.mk-allin-price {
  font-size: 34px;
  font-weight: 800;
  line-height: 1;
  color: var(--ink-1);
}
/* Struck-through regular price — same data as the pricing card's
   .m-onetime-was, scaled to this smaller number. */
.mk-allin-was {
  font-size: 20px;
  font-weight: 600;
  color: var(--ink-3);
  text-decoration: line-through;
  margin-right: 6px;
}
.mk-allin-price small {
  display: block;
  font-size: var(--m-fs-xs);
  font-weight: 500;
  color: var(--ink-3);
  margin-top: 4px;
}

/* ----- "One cohesive studio" band ----- */
.mk-diff-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--m-s7);
}
@media (max-width: 800px) { .mk-diff-grid { grid-template-columns: 1fr; gap: var(--m-s6); } }
.mk-diff-col h3 {
  font-family: var(--font-display);
  font-size: var(--m-fs-h3);
  font-weight: 600;
  margin: 0 0 8px;
  color: var(--ink-1);
}
.mk-diff-col p {
  font-family: var(--font-serif);
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--ink-2);
  margin: 0;
}

/* ----- How it works (4 numbered steps) ----- */
.mk-steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--m-s5);
  list-style: none;
  /* `0 auto`, not `0`: this sits inside a full-width .m-section-alt band,
     where `.m-section-alt > *` caps children at --m-container and centers
     them with auto side margins. A bare `margin: 0` has equal specificity
     and comes later in this file, so it wins and pins the grid to the
     left edge while the section heading above stays centered. */
  margin: 0 auto;
  padding: 0;
  counter-reset: mk-step;
}
@media (max-width: 960px) { .mk-steps { grid-template-columns: repeat(2, 1fr); gap: var(--m-s6); } }
@media (max-width: 600px) { .mk-steps { grid-template-columns: 1fr; } }
.mk-step { display: flex; flex-direction: column; }
.mk-step-media {
  aspect-ratio: 3 / 2;
  margin-bottom: var(--m-s4);
}
.mk-step-n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--accent);
  color: var(--accent);
  border-radius: 50%;
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  margin-bottom: 10px;
}
.mk-step h3 {
  font-family: var(--font-display);
  font-size: var(--m-fs-h3);
  font-weight: 600;
  margin: 0 0 6px;
  color: var(--ink-1);
}
.mk-step p {
  font-family: var(--font-serif);
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0;
}

/* ----- Before / after ("Skip the hard part") -----
   Replaced the old div-based fake table. The argument is the same;
   showing it as two panels rather than a strike-through list means
   the "after" side can actually carry a picture of the product. */
.mk-compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--m-s5);
  align-items: start;
}
@media (max-width: 800px) { .mk-compare { grid-template-columns: 1fr; } }
.mk-compare-panel {
  background: var(--bg-card);
  border: 1px solid var(--m-card-line);
  border-radius: var(--m-radius);
  padding: var(--m-card-pad);
}
.mk-compare-panel.is-after { border-color: var(--accent); box-shadow: var(--m-shadow-lift); }
.mk-compare-label {
  display: inline-block;
  background: var(--m-badge-bg);
  color: var(--m-badge-ink);
  border-radius: var(--m-radius-pill);
  padding: 5px 13px;
  font-size: var(--m-fs-eyebrow);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  margin-bottom: var(--m-s4);
}
.is-after .mk-compare-label { background: var(--accent-bg); color: var(--accent); }
.mk-compare-media { aspect-ratio: 16 / 10; margin-bottom: var(--m-s4); }
.mk-compare-body {
  font-family: var(--font-serif);
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--ink-2);
  margin: 0 0 10px;
}
.mk-compare-note { margin: 0; font-size: var(--m-fs-xs); color: var(--ink-3); }
.mk-compare-punch {
  text-align: center;
  margin: var(--m-s7) auto 0;
  max-width: var(--m-container-n);
}
.mk-compare-punch strong {
  display: block;
  font-family: var(--font-display);
  font-size: var(--m-fs-h2);
  line-height: var(--m-lh-head);
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--ink-1);
  margin-bottom: 8px;
}
.mk-compare-punch span {
  font-family: var(--font-serif);
  font-size: var(--m-fs-h4);
  color: var(--ink-2);
}

/* ----- Testimonials (renamed from .m2-testimonial*) -----
   Renders only when admin-managed testimonials exist. */
.mk-quotes {
  list-style: none;
  padding: 0;
  margin: 0 auto;
  max-width: 1040px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 22px;
}
.mk-quote {
  position: relative;
  background: var(--bg-card);
  border: 1px solid var(--m-card-line);
  border-radius: var(--m-radius);
  padding: 30px 26px 24px;
  display: flex;
  flex-direction: column;
}
.mk-quote::before {
  content: "\201C";
  position: absolute;
  top: 6px;
  left: 18px;
  font-family: var(--font-display, Georgia, serif);
  font-size: 56px;
  line-height: 1;
  color: var(--accent);
  opacity: .35;
}
.mk-quote-text {
  margin: 14px 0 18px;
  font-family: var(--font-serif, Georgia, serif);
  font-size: 16.5px;
  line-height: 1.6;
  color: var(--ink-1);
}
.mk-quote-by {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--m-card-line);
}
.mk-quote-name { display: block; font-weight: 600; font-size: 14px; color: var(--ink-1); }
.mk-quote-role { display: block; margin-top: 2px; font-size: 13px; color: var(--ink-3); }

/* ----- Lead magnet -----
   Replaced the bare email input that used to sit inside the dark
   closing band. The free tier is the actual offer, so it gets a
   product card of its own rather than one line of small type. */
.mk-lead {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--m-s8);
  align-items: center;
}
@media (max-width: 800px) { .mk-lead { grid-template-columns: 1fr; gap: var(--m-s6); } }
.mk-lead-title {
  font-family: var(--font-display);
  font-size: var(--m-fs-h2);
  line-height: var(--m-lh-head);
  font-weight: 600;
  letter-spacing: -.01em;
  margin: 0 0 12px;
  color: var(--ink-1);
}
.mk-lead-sub {
  font-family: var(--font-serif);
  font-size: var(--m-fs-h4);
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0;
}
/* The #notify target. The no-JS subscribe path redirects to /#notify,
   so this anchor has to survive any future edit of this section. */
.mk-lead-anchor { display: block; height: 0; scroll-margin-top: 120px; }

.mk-lead-card {
  background: var(--bg-card);
  border: 1px solid var(--m-card-line-2);
  border-radius: var(--m-radius);
  padding: var(--m-card-pad);
  box-shadow: var(--m-shadow-lift);
}
.mk-lead-media { aspect-ratio: 3 / 2; margin-bottom: var(--m-s4); }
.mk-lead-name {
  font-family: var(--font-display);
  font-size: var(--m-fs-h3);
  font-weight: 600;
  margin: 0 0 2px;
  color: var(--ink-1);
}
.mk-lead-tag { margin: 0 0 var(--m-s4); font-size: var(--m-fs-sm); color: var(--accent); font-weight: 600; }
.mk-lead-desc {
  font-family: var(--font-serif);
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink-2);
  margin: 0 0 var(--m-s5);
}
.mk-lead-stats {
  list-style: none;
  margin: 0 0 var(--m-s5);
  padding: var(--m-s4) 0;
  border-top: 1px solid var(--m-card-line);
  border-bottom: 1px solid var(--m-card-line);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--m-s3);
  text-align: center;
}
.mk-lead-stats b {
  display: block;
  font-family: var(--font-display);
  font-size: var(--m-fs-h3);
  font-weight: 600;
  color: var(--ink-1);
}
.mk-lead-stats span { font-size: var(--m-fs-xs); color: var(--ink-3); }

/* Newsletter is the secondary ask — visually demoted under a rule so
   it can't compete with "Start writing free" above it. */
.mk-lead-news {
  margin-top: var(--m-s5);
  padding-top: var(--m-s4);
  border-top: 1px solid var(--m-card-line);
}
.mk-lead-news-label { margin: 0 0 10px; font-size: var(--m-fs-xs); color: var(--ink-3); }
.mk-lead-form { display: flex; gap: 8px; flex-wrap: wrap; }
.mk-lead-form input[type="email"] {
  flex: 1;
  min-width: 180px;
  padding: 11px 14px;
  border: 1px solid var(--m-card-line-2);
  border-radius: var(--radius);
  font: inherit;
  font-size: var(--m-fs-sm);
  background: var(--bg-page);
  color: var(--ink-1);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.mk-lead-form input[type="email"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}

.mk-lead-strip {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--m-s3) var(--m-s6);
  margin-top: var(--m-s7);
  padding-top: var(--m-s5);
  border-top: 1px solid var(--m-band-line);
  list-style: none;
  font-size: var(--m-fs-sm);
  color: var(--ink-3);
}
.mk-lead-strip li::before { content: "✓ "; color: var(--accent); font-weight: 700; }

/* ==========================================================
   CSS mock-ups — the fallback drawing behind every empty
   image slot (see partials/marketing_slot.php).
   ----------------------------------------------------------
   Twelve grey boxes on a fresh install would read as a broken
   site, so each card draws a suggestion of the real screen
   instead. Everything here is borders and gradients — no image
   files, and assets/img/ stays empty.
   ========================================================== */
.m-mock {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-paper);
  overflow: hidden;
}
.m-mock .m-mock-chrome { flex: 0 0 auto; }
.m-mock .m-mock-body {
  flex: 1;
  min-height: 0;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  font-family: var(--font-serif);
}
.m-mock .m-mock-h { font-size: 17px; letter-spacing: .03em; }
.m-mock .m-mock-h-sm { font-size: 13px; }
.m-mock .m-mock-line { height: 8px; }
.m-mock-rule {
  height: 1px;
  width: 40%;
  margin: 2px auto 4px;
  background: var(--accent);
  opacity: .5;
}

/* format — a two-page spread with a drop cap */
.m-mock-spread { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; height: 100%; }
.m-mock-page {
  display: flex;
  flex-direction: column;
  gap: 7px;
  background: var(--bg-card);
  border: 1px solid var(--m-card-line);
  border-radius: 3px;
  padding: 10px 9px;
}
.m-mock-cap {
  font-family: var(--font-display);
  font-size: 26px;
  line-height: .9;
  color: var(--accent);
  align-self: flex-start;
}

/* beta — margin comment bubbles */
.m-mock-note {
  align-self: flex-end;
  width: 58%;
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--accent-bg);
  border: 1px solid var(--m-card-line);
  border-radius: 8px;
  padding: 7px 8px;
}
.m-mock-note.is-second { width: 44%; }
.m-mock-note em { flex: 1; height: 6px; border-radius: 2px; background: var(--m-card-line-2); }
.m-mock-avatar {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--accent);
  opacity: .55;
}

/* export — file chips with progress bars */
.m-mock-file {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg-card);
  border: 1px solid var(--m-card-line);
  border-radius: 8px;
  padding: 11px 12px;
}
.m-mock-file b {
  font-family: var(--font-sans);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--ink-3);
  min-width: 34px;
}
.m-mock-bar { flex: 1; height: 5px; border-radius: 3px; background: var(--bg-rail); overflow: hidden; }
.m-mock-bar i { display: block; height: 100%; background: var(--accent); opacity: .6; }

/* launch — a dated checklist */
.m-mock-task { display: flex; align-items: center; gap: 9px; }
.m-mock-task .m-mock-line { flex: 1; }
.m-mock-task b {
  font-family: var(--font-sans);
  font-size: 9.5px;
  font-weight: 600;
  color: var(--ink-3);
  background: var(--bg-rail);
  border-radius: var(--m-radius-pill);
  padding: 3px 7px;
}
.m-mock-box {
  width: 12px;
  height: 12px;
  flex: 0 0 auto;
  border: 1px solid var(--m-card-line-2);
  border-radius: 3px;
}
.m-mock-box.is-done { background: var(--accent); border-color: var(--accent); opacity: .65; }

/* preview — a phone frame */
.m-mock-phone {
  width: 46%;
  min-width: 96px;
  margin: 0 auto;
  height: 100%;
  background: var(--bg-card);
  border: 1px solid var(--m-card-line-2);
  border-radius: 16px;
  padding: 14px 12px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

/* tabs — the "before" panel: four apps open at once */
.m-mock-tabs { display: flex; gap: 4px; margin-bottom: 6px; }
.m-mock-tab {
  flex: 1;
  height: 17px;
  display: flex;
  align-items: center;
  padding: 0 5px;
  border-radius: 4px 4px 0 0;
  background: var(--bg-rail);
  border: 1px solid var(--m-card-line);
  border-bottom: none;
}
.m-mock-tab i { width: 6px; height: 6px; border-radius: 50%; background: var(--ink-4); }
.m-mock-tab.is-a i { background: #a9713b; }
.m-mock-tab.is-b i { background: #5f7f9a; }
.m-mock-tab.is-c i { background: #7c8f5a; }
.m-mock-tab.is-d i { background: #9a6a8c; }

/* studio — the "after" panel: one window, rail plus content */
.m-mock-split { display: grid; grid-template-columns: 62px 1fr; gap: 10px; height: 100%; }
.m-mock-rail { display: flex; flex-direction: column; gap: 6px; }
.m-mock-rail span {
  height: 8px;
  border-radius: 2px;
  background: var(--bg-rail);
  border: 1px solid var(--m-card-line);
}
.m-mock-main { display: flex; flex-direction: column; gap: 7px; }

/* map — the relationship-map deep-dive card: dots joined by lines.
   Node colours reuse the four-app tab palette above. */
.m-mock-net { position: relative; height: 100%; min-height: 90px; }
.m-mock-node {
  position: absolute;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.12);
}
.m-mock-node.is-a { background: #a9713b; }
.m-mock-node.is-b { background: #5f7f9a; }
.m-mock-node.is-c { background: #7c8f5a; }
.m-mock-node.is-d { background: #9a6a8c; }
.m-mock-edge {
  position: absolute;
  height: 2px;
  border-radius: 1px;
  background: var(--m-card-line-2);
  transform-origin: left center;
}

/* board — the plot-board deep-dive card: colour rows × chapter cells */
.m-mock-board { display: flex; flex-direction: column; gap: 8px; }
.m-mock-brow { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
.m-mock-brow i { height: 16px; border-radius: 4px; background: var(--bg-rail); }
.m-mock-brow.is-a i.is-on { background: rgba(169,113,59,.55); }
.m-mock-brow.is-b i.is-on { background: rgba(95,127,154,.55); }
.m-mock-brow.is-c i.is-on { background: rgba(124,143,90,.55); }

/* ============================================================
   Free public tools (/tools + /tools/cover-calculator)
   ============================================================ */
.m-tools-main {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 24px 40px;
}
.m-tool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
  margin: 36px 0 60px;
}
.m-tool-card {
  display: block;
  background: var(--card, #fffdf8);
  border: 1px solid var(--line-soft, #e8e3d8);
  border-radius: 12px;
  padding: 26px 24px;
  text-decoration: none;
  color: var(--ink-1, #2c2a26);
  transition: border-color .15s ease, transform .15s ease;
}
.m-tool-card:hover {
  border-color: var(--accent, #8b6914);
  transform: translateY(-2px);
}
.m-tool-card h2 {
  margin: 0 0 10px;
  font-family: var(--font-display, Georgia, serif);
  font-size: 20px;
}
.m-tool-card p {
  margin: 0 0 14px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-2, #4a463e);
}
.m-tool-card-go {
  font-size: 14px;
  font-weight: 600;
  color: var(--accent, #8b6914);
}

/* ---- Calculator ---- */
.m-calc-section { padding-top: 20px; }
.m-calc-form {
  background: var(--card, #fffdf8);
  border: 1px solid var(--line-soft, #e8e3d8);
  border-radius: 12px;
  padding: 26px 24px 20px;
}
.m-calc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px 20px;
}
.m-calc-custom {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.m-calc-units label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-right: 18px;
  font-size: 14.5px;
  cursor: pointer;
}
.m-calc-units input { accent-color: var(--accent, #8b6914); }
.m-calc-actions { margin-top: 18px; }
.m-calc-error {
  display: block;
  margin-top: 4px;
  font-size: 13px;
  color: #a33b2e;
}
.m-calc-note {
  margin: 16px 0 0;
  padding: 10px 14px;
  background: #fbf1cf;
  border: 1px solid #efdf95;
  border-radius: 8px;
  font-size: 14px;
  color: #6b5210;
}

/* ---- Results ---- */
.m-calc-results { margin-top: 28px; }
.m-calc-results-title {
  font-family: var(--font-display, Georgia, serif);
  font-size: 24px;
  margin: 0 0 18px;
}
.m-calc-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  margin-bottom: 26px;
}
.m-calc-stat {
  background: var(--card, #fffdf8);
  border: 1px solid var(--line-soft, #e8e3d8);
  border-radius: 10px;
  padding: 14px 16px;
}
.m-calc-stat-label {
  display: block;
  font-size: 12.5px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-3, #6a665e);
  margin-bottom: 6px;
}
.m-calc-stat-value {
  display: block;
  font-size: 19px;
  font-weight: 650;
  color: var(--ink-1, #2c2a26);
  font-variant-numeric: tabular-nums;
}
.m-calc-diagram {
  margin: 0 0 26px;
  padding: 18px;
  background: #fff;
  border: 1px solid var(--line-soft, #e8e3d8);
  border-radius: 12px;
}
.m-calc-diagram svg { display: block; width: 100%; height: auto; }
.m-calc-diagram figcaption {
  margin-top: 12px;
  font-size: 13.5px;
  color: var(--ink-3, #6a665e);
  text-align: center;
}
.m-calc-copy-wrap { margin-bottom: 22px; }
.m-calc-copy {
  margin: 0 0 10px;
  padding: 16px 18px;
  background: #f6f3ea;
  border: 1px solid var(--line-soft, #e8e3d8);
  border-radius: 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13.5px;
  line-height: 1.7;
  color: var(--ink-1, #2c2a26);
  white-space: pre-wrap;
  user-select: all;
  -webkit-user-select: all;
}
.m-calc-download {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.m-calc-attrib {
  font-size: 13px;
  color: var(--ink-3, #6a665e);
  margin: 0;
}
.m-calc-prose p {
  max-width: 720px;
  font-size: 15.5px;
  line-height: 1.75;
  color: var(--ink-2, #4a463e);
  margin: 0 0 16px;
}
.m-tool-cta {
  text-align: center;
  background: var(--card, #fffdf8);
  border: 1px solid var(--line-soft, #e8e3d8);
  border-radius: 14px;
  padding: 36px 28px;
  margin-bottom: 60px;
}
.m-tool-cta p {
  max-width: 620px;
  margin: 0 auto 20px;
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--ink-2, #4a463e);
}
@media (max-width: 640px) {
  .m-calc-custom { grid-column: 1 / -1; }
}

/* ---- Shared bits for the 2026-07 tool batch (royalty / keywords /
       description / words-to-pages). Reuses the .m-calc-* layout. ---- */

/* Highlighted "best" stat card (better royalty tier, headline number) */
.m-calc-stat--best {
  border-color: var(--accent, #8b6914);
  box-shadow: 0 0 0 1px var(--accent, #8b6914) inset;
}
.m-calc-stat-sub {
  display: block;
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--ink-3, #6a665e);
}

/* Issue list shared by the keyword counter + description checker */
.m-issues {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.m-issues li {
  padding: 10px 14px;
  border-radius: 8px;
  font-size: 14px;
  line-height: 1.5;
}
.m-issue--warn {
  background: #fbf1cf;
  border: 1px solid #efdf95;
  color: #6b5210;
}
.m-issue--error {
  background: #f9e5e1;
  border: 1px solid #eac2ba;
  color: #8c3327;
}

/* Keyword byte meters */
.m-kw-slots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px 20px;
}
.m-kw-bytes {
  float: right;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-3, #6a665e);
}
.m-kw-bytes--over { color: #a33b2e; font-weight: 650; }
.m-kw-meter {
  height: 5px;
  margin-top: 6px;
  border-radius: 3px;
  background: var(--line-soft, #e8e3d8);
  overflow: hidden;
}
.m-kw-meter-fill {
  height: 100%;
  border-radius: 3px;
  background: var(--accent, #8b6914);
  transition: width .1s ease;
}
.m-kw-meter-fill--over { background: #a33b2e; }

/* Description checker */
.m-desc-counter {
  float: right;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-3, #6a665e);
}
.m-desc-counter--over { color: #a33b2e; font-weight: 650; }
.m-desc-fold {
  margin: 0;
  padding: 12px 16px;
  background: #f6f3ea;
  border: 1px solid var(--line-soft, #e8e3d8);
  border-radius: 8px;
  font-size: 14.5px;
  color: var(--ink-2, #4a463e);
}
.m-desc-preview {
  padding: 16px 18px;
  background: #fff;
  border: 1px solid var(--line-soft, #e8e3d8);
  border-radius: 10px;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--ink-1, #2c2a26);
  overflow-wrap: break-word;
}
.m-desc-preview p { margin: 0 0 10px; }
.m-desc-preview h4, .m-desc-preview h5, .m-desc-preview h6 { margin: 14px 0 6px; }
.m-desc-preview ul, .m-desc-preview ol { margin: 0 0 10px; padding-left: 22px; }

/* Admin-only draft/scheduled preview banner on /blog/{slug} */
.article-preview-banner {
  max-width: 720px;
  margin: 18px auto 0;
  padding: 12px 18px;
  background: #fbf1cf;
  border: 1px solid #efdf95;
  border-radius: 10px;
  font-size: 14px;
  color: #6b5210;
}
.article-preview-banner a {
  color: #6b5210;
  font-weight: 600;
}

/* ============================================================
   Episodes (/ledger)
   The YouTube channel's episode hub (reframed v3.22 from the
   old verdict ledger — the URL and the m-ledger-* chrome keep
   their names; every video description links to /ledger). One
   entry per episode: an embedded player when the URL parses,
   title, description, date, article link. Quiet, ruled
   separators; no new palette, no dark variants (marketing
   pages force light).
   ============================================================ */
.m-ledger-main {
  max-width: 760px;
  margin: 0 auto;
  padding: 0 24px 40px;
}
.m-episode-list {
  margin: 36px 0 0;
}
.m-episode {
  border-top: 1px solid var(--line-soft, #e8e3d8);
  padding: 36px 0;
  /* Anchor jumps (#ep-4) land clear of the sticky nav. */
  scroll-margin-top: 90px;
}
.m-episode-list .m-episode:last-child {
  border-bottom: 1px solid var(--line-soft, #e8e3d8);
}
.m-episode-video {
  position: relative;
  aspect-ratio: 16 / 9;
  margin: 0 0 18px;
  border-radius: 10px;
  overflow: hidden;
  background: #000;
}
.m-episode-video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.m-episode-title {
  margin: 0 0 8px;
  font-family: var(--font-display, Georgia, serif);
  font-size: 22px;
  line-height: 1.3;
  color: var(--ink-1, #2c2a26);
}
.m-episode-desc {
  margin: 0 0 12px;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-2, #4a463e);
}
.m-ledger-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  font-size: 14px;
  color: var(--ink-3, #6a665e);
}
.m-ledger-meta a {
  color: var(--ink-2, #4a463e);
  text-decoration: none;
  border-bottom: 1px solid var(--line-soft, #e8e3d8);
}
.m-ledger-meta a:hover { border-bottom-color: var(--ink-2, #4a463e); }
.m-ledger-empty {
  margin: 0;
  padding: 96px 0;
  text-align: center;
  font-family: var(--font-display, Georgia, serif);
  font-style: italic;
  font-size: 19px;
  color: var(--ink-3, #6a665e);
}
.m-ledger-subscribe {
  border-top: 1px solid var(--line-soft, #e8e3d8);
  margin-top: 48px;
  padding-top: 40px;
  text-align: center;
}
.m-ledger-empty + .m-ledger-subscribe { border-top: 0; margin-top: 0; padding-top: 0; }
.m-ledger-subscribe-title {
  margin: 0 0 8px;
  font-family: var(--font-display, Georgia, serif);
  font-size: 22px;
}
.m-ledger-subscribe-label {
  margin: 0 0 18px;
  font-size: 15px;
  color: var(--ink-2, #4a463e);
}
.m-ledger-subscribe .mk-lead-form { justify-content: center; max-width: 460px; margin: 0 auto; }
@media (max-width: 640px) {
  .m-episode { padding: 26px 0; }
  .m-episode-title { font-size: 19px; }
}

/* ==========================================================
   "What's new" (migration 203) — the landing spotlight, the
   /whats-new page, the hero ribbon, and the hub mock.
   ----------------------------------------------------------
   The gold badge itself (.mk-badge-new) lives next to .mk-badge
   with the other card primitives; everything below is layout
   for the two surfaces that showcase the entries.
   ========================================================== */

/* ----- Hero ribbon ----- */
.mk-hero-ribbon {
  /* flex (block-level) + fit-content, NOT inline-flex: the eyebrow
     span follows it inline, and an inline ribbon lands on the same
     line as "The complete writing studio". */
  display: flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  margin-bottom: 18px;
  padding: 6px 14px;
  border-radius: var(--m-radius-pill);
  background: var(--m-badge-new-bg);
  border: 1px solid var(--m-badge-new-line);
  color: var(--ink-1);
  font-size: var(--m-fs-sm);
  text-decoration: none;
  transition: border-color .15s ease, transform .15s ease;
}
.mk-hero-ribbon:hover { border-color: var(--m-badge-new-ink); transform: translateY(-1px); }
.mk-hero-ribbon-tag {
  font-size: var(--m-fs-eyebrow);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--m-badge-new-ink);
}
/* Cinematic hero: the cream pill would glow oddly on dark art, and the
   token flip up top makes --ink-1 unreliable as TEXT here (see the .btn
   comment in that block) — so pin a translucent light-on-dark pill. */
.mk-hero-cinematic .mk-hero-ribbon {
  margin-left: auto;   /* copy is centred over the art */
  margin-right: auto;
  background: rgba(0, 0, 0, .35);
  border-color: rgba(232, 200, 130, .55);
  color: #f5efe2;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .5);
  backdrop-filter: blur(3px);
}
.mk-hero-cinematic .mk-hero-ribbon-tag { color: #e8c882; }

/* ----- Landing spotlight ("New in Pendrilo") ----- */
.mk-new-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr));
  gap: var(--m-s5);
}
.mk-new-card {
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
  border: 1px solid var(--m-card-line);
  border-radius: var(--m-radius);
  padding: var(--m-card-pad);
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.mk-new-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--m-shadow-lift);
  border-color: var(--m-card-line-2);
}
.mk-new-media {
  aspect-ratio: 16 / 10;
  margin: calc(var(--m-card-pad) * -1) calc(var(--m-card-pad) * -1) var(--m-s4);
  border-radius: var(--m-radius) var(--m-radius) 0 0;
  border-width: 0 0 1px;
}
.mk-new-card-title {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.2vw, 25px);
  font-weight: 600;
  margin: 0 0 8px;
  color: var(--ink-1);
}
.mk-new-card-body {
  font-family: var(--font-serif);
  font-size: 15.5px;
  line-height: 1.62;
  color: var(--ink-2);
  margin: 0 0 4px;
}
.mk-new-bullets {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-family: var(--font-serif);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink-2);
}
.mk-new-bullets li {
  padding-left: 20px;
  position: relative;
}
.mk-new-bullets li::before {
  content: "✦";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--m-badge-new-ink);
  font-size: 11px;
  line-height: inherit;
}
.mk-new-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 18px;
  margin: var(--m-s4) 0 0;
  padding-top: var(--m-s4);
  border-top: 1px solid var(--m-card-line);
}
.mk-new-card .mk-new-actions { margin-top: auto; }
.mk-new-more {
  font-size: var(--m-fs-sm);
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid var(--m-card-line-2);
}
.mk-new-more:hover { color: var(--ink-1); border-bottom-color: var(--ink-2); }
.mk-new-all {
  margin: var(--m-s6) 0 0;
  text-align: center;
  font-size: var(--m-fs-sm);
}
.mk-new-all a {
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid var(--m-card-line-2);
}
.mk-new-all a:hover { color: var(--ink-1); border-bottom-color: var(--ink-2); }

/* Gallery captions: the badge sits inline before the text, so undo the
   card-primitive spacing it inherits from .mk-badge. */
figcaption .mk-badge-new {
  display: inline-block;
  margin: 0 4px 0 0;
  padding: 2px 8px;
  vertical-align: middle;
}

/* ----- /whats-new page ----- */
.mk-new-main {
  max-width: var(--m-container);
  margin: 0 auto;
  padding: 0 var(--m-gutter) var(--m-s9);
}
.mk-new-list {
  display: flex;
  flex-direction: column;
  gap: var(--m-s8);
  margin-top: var(--m-s7);
}
.mk-new-row {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: var(--m-s7);
  align-items: center;
}
/* Alternate the media side so a long history doesn't read as a table. */
.mk-new-row:nth-child(even) .mk-new-media { order: 2; }
.mk-new-row .mk-new-media {
  margin: 0;
  border-radius: var(--m-radius);
  border-width: 1px;
  box-shadow: var(--m-shadow-lift);
}
.mk-new-meta {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 10px;
}
.mk-new-meta .mk-badge { margin-bottom: 0; }
.mk-new-date { font-size: var(--m-fs-xs); color: var(--ink-3); }
.mk-new-title {
  font-family: var(--font-display);
  font-size: clamp(24px, 3vw, 32px);
  font-weight: 600;
  line-height: var(--m-lh-head);
  margin: 0 0 10px;
  color: var(--ink-1);
}
.mk-new-body {
  font-family: var(--font-serif);
  font-size: var(--m-fs-body);
  line-height: var(--m-lh-body);
  color: var(--ink-2);
  margin: 0;
}
.mk-new-empty {
  margin: 0;
  padding: 96px 0;
  text-align: center;
  font-family: var(--font-display);
  font-style: italic;
  font-size: 19px;
  color: var(--ink-3);
}
.mk-new-cta {
  border-top: 1px solid var(--m-card-line);
  margin-top: var(--m-s9);
  padding-top: var(--m-s8);
  text-align: center;
}
.mk-new-cta-title {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-size: 24px;
}
.mk-new-cta-label {
  margin: 0 auto 20px;
  max-width: var(--m-container-n);
  font-size: 15px;
  color: var(--ink-2);
}
@media (max-width: 860px) {
  .mk-new-row { grid-template-columns: 1fr; gap: var(--m-s5); }
  .mk-new-row:nth-child(even) .mk-new-media { order: 0; }
  .mk-new-list { gap: var(--m-s7); }
}

/* ----- hub mock — the public author page drawing ----- */
.m-mock-hub-head { display: flex; align-items: center; gap: 10px; }
.m-mock-hub-head .m-mock-line { flex: 0 1 46%; }
.m-mock-avatar-lg { width: 26px; height: 26px; }
.m-mock-covers { display: flex; gap: 8px; margin-top: 2px; }
.m-mock-covers i {
  width: 26%;
  aspect-ratio: 2 / 3;
  max-height: 52px;
  border: 1px solid var(--m-card-line-2);
  border-radius: 2px;
  background: linear-gradient(160deg, var(--bg-card) 55%, var(--accent-bg, var(--bg-rail)));
}
.m-mock-btn {
  align-self: flex-start;
  font-family: var(--font-sans);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--ink-2);
  background: var(--m-badge-new-bg);
  border: 1px solid var(--m-badge-new-line);
  border-radius: var(--m-radius-pill);
  padding: 4px 10px;
}
