/* ============================================================
   omgfixmd shared components.
   Lives downstream of tokens.css. Every page loads this file, so
   rules here win against browser defaults but lose to any inline
   page CSS that follows — intended during migration. Once the
   inline duplicates are removed from a page, this file owns the
   component outright. New design for a shared pattern? Comes
   here first, never inline.
   ============================================================ */

/* ------------------------------------------------------------
   Self-hosted fonts. Loaded once via this file by every static
   page. The SPA shell (index.html) keeps its own inline copy as
   well — Inter + Hebrew variants — until that surface migrates
   too; the second declaration is a no-op (same family, same src).
   ------------------------------------------------------------ */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/inter.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('/fonts/jetbrains-mono.woff2') format('woff2');
}
@font-face {
  font-family: 'Noto Serif';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/noto-serif.woff2') format('woff2');
}

/* ------------------------------------------------------------
   Page baseline — static pages only. The SPA shell sets these
   itself and may diverge (it pins `overflow-y: scroll` to keep
   the scrollbar gutter reserved while React swaps modes). For
   static pages this is the floor.
   ------------------------------------------------------------ */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
}

body {
  font-family: var(--ui-font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-y: scroll;
}

/* ------------------------------------------------------------
   Static-page topbar — sticky brand row + "Try the app" CTA.
   Used verbatim on every static HTML (blog index, blog posts,
   manifesto, privacy, /for/lovable). The SPA topbar is a
   different surface (.topbar in index.html's inline styles)
   and stays inline for now.
   ------------------------------------------------------------ */

.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--topbar-blur);
  backdrop-filter: saturate(180%) blur(8px);
  -webkit-backdrop-filter: saturate(180%) blur(8px);
  border-bottom: 1px solid var(--border);
}
.topbar-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 10px 24px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  font-size: 14px;
  color: var(--ink);
  letter-spacing: -0.005em;
  text-decoration: none;
  padding: 4px 6px;
  margin: -4px -6px;
  border-radius: 6px;
  transition: background 120ms ease;
}
.brand:hover { background: var(--bg-sub); }
.brand .dot {
  width: 16px;
  height: 16px;
  border-radius: 4px;
  background: linear-gradient(135deg, #37352f 0%, #5c5b57 100%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
}
.brand .muted {
  color: var(--muted);
  font-weight: 400;
}
@media (max-width: 640px) {
  .brand .muted { display: none; }
}
.brand-omg, .brand-md { font-weight: 700; }
.top-actions { margin-inline-start: auto; }

.try-app {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  background: var(--ink);
  color: var(--text-on-emphasis);
  border-radius: 7px;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  transition: background 120ms ease;
}
.try-app:hover { background: #000; }
[data-theme="dark"] .try-app:hover { background: var(--text-secondary); }
.try-app .arrow {
  transition: transform 140ms ease;
  display: inline-block;
}
.try-app:hover .arrow { transform: translateX(2px); }

@media (max-width: 640px) {
  .topbar-inner { padding: 10px 16px; }
}

/* ------------------------------------------------------------
   Long-read post body. Used by every blog post + /manifesto +
   /for/lovable. The .wrap container caps the reading column;
   .eyebrow + article h1 + .byline build the post header; the
   rest is prose typography for `<article>`.
   Page-specific rules (e.g. .fail, .recipe) stay inline; only
   the shape of "an OMGfixMD long read" lives here.
   ------------------------------------------------------------ */

.wrap {
  max-width: 680px;
  margin: 0 auto;
  padding: 48px 24px 32px;
}

.eyebrow {
  display: inline-block;
  font-family: var(--ui-font);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 22px;
}

article h1 {
  font-family: var(--reading-font);
  font-size: 42px;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: 0 0 16px;
  text-wrap: balance;
}

.byline {
  font-family: var(--ui-font);
  font-size: 14px;
  color: var(--ink-2);
  margin: 0 0 32px;
}
.byline a {
  color: var(--ink-2);
  border-bottom: 1px solid var(--border);
  text-decoration: none;
}
.byline a:hover { color: var(--ink); }
.byline .sep {
  color: var(--border-strong);
  margin: 0 6px;
}

article {
  font-family: var(--reading-font);
  font-size: 18px;
  line-height: 1.7;
  color: var(--ink);
}
article p { margin: 0 0 1.1em; }
article p.lede {
  font-size: 20px;
  line-height: 1.5;
  margin: 0 0 1.1em;
}
article p.lede strong { font-weight: 600; }
article h2 {
  font-family: var(--reading-font);
  font-size: 26px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin: 2em 0 0.5em;
}
article h3 {
  font-family: var(--reading-font);
  font-size: 20px;
  font-weight: 600;
  line-height: 1.3;
  margin: 1.5em 0 0.4em;
}
article ul,
article ol {
  margin: 0 0 1.2em;
  padding-inline-start: 1.5em;
}
article li { margin: 0.35em 0; }
.doc li { white-space: pre-line; }
article strong { font-weight: 600; }
article em { font-style: italic; }
article code {
  font-family: var(--mono);
  font-size: 0.86em;
  background: var(--surface-0);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 1px 5px;
}
article pre {
  font-family: var(--mono);
  background: var(--surface-0);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
  overflow-x: auto;
  font-size: 14px;
  line-height: 1.55;
  margin: 0 0 1.4em;
}
article pre code {
  background: transparent;
  border: 0;
  padding: 0;
  font-size: 1em;
}
/* Auto-linked URLs inside code blocks. The `.code-link` class opts out of the
   prose highlighter-marker style (which targets a:not([class])) — a yellow
   band reads wrong over monospace. Restrained underline instead, thickening on
   hover so it still announces itself as interactive. */
article pre code a.code-link {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: color-mix(in oklab, var(--link-accent) 65%, var(--ink));
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  border-radius: 2px;
}
article pre code a.code-link:hover {
  text-decoration-thickness: 2px;
}
article pre code a.code-link:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 1px;
}
article hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: 2.2em 0;
}

@media (max-width: 640px) {
  .wrap { padding: 32px 20px 20px; }
  article h1 { font-size: 32px; }
  article {
    font-size: 17px;
    line-height: 1.65;
  }
  article p.lede { font-size: 19px; }
  article h2 { font-size: 22px; }
  article h3 { font-size: 18px; }
  article pre {
    font-size: 13px;
    padding: 12px 14px;
    border-radius: 6px;
  }
}

/* ------------------------------------------------------------
   TL;DR box — opens long reads with a single quotable summary.
   Same copy contract on every post: short enough that an LLM
   answering "what's this post about" can quote it whole.
   ------------------------------------------------------------ */

.tldr {
  border: 1px solid var(--border);
  background: var(--bg-sub);
  border-radius: 10px;
  padding: 18px 20px;
  margin: 0 0 1.8em;
  font-family: var(--ui-font);
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink);
}
.tldr-label {
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  display: block;
  margin: 0 0 8px;
}
.tldr p {
  margin: 0;
  font-family: var(--ui-font);
  font-size: 15px;
  line-height: 1.55;
}
.tldr code {
  font-family: var(--mono);
  font-size: 0.88em;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 1px 5px;
}

/* ------------------------------------------------------------
   In-post FAQ — "Before you paste." accordion on long reads.
   Identical markup + behavior as the homepage FAQ; the React
   component (HomepageFAQ.jsx) and these rules render the same
   semantic <details>/<summary> tree.
   ------------------------------------------------------------ */

.faq {
  max-width: 680px;
  margin: 48px auto 0;
  padding: 0 24px;
  font-family: var(--ui-font);
}
.faq h2 {
  font-family: var(--reading-font);
  font-size: 26px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin: 0 0 18px;
  color: var(--ink);
}
.faq details {
  border-top: 1px solid var(--border);
  padding: 18px 0;
}
.faq details:last-of-type { border-bottom: 1px solid var(--border); }
.faq summary {
  list-style: none;
  cursor: pointer;
  font-size: 17px;
  font-weight: 600;
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+';
  font-family: var(--mono);
  font-size: 20px;
  font-weight: 400;
  color: var(--muted);
}
.faq details[open] summary::after {
  content: '−';
  color: var(--ink-2);
}
.faq .answer {
  margin-top: 12px;
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink-2);
}
.faq .answer p { margin: 0 0 0.8em; }
.faq .answer p:last-child { margin-bottom: 0; }
.faq .answer code {
  font-family: var(--mono);
  font-size: 0.88em;
  background: var(--surface-0);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 1px 5px;
}

@media (max-width: 640px) {
  .faq { padding: 0 20px; }
  .faq h2 { font-size: 22px; }
  .faq summary { font-size: 16px; }
}

/* ------------------------------------------------------------
   Related-reading rail. Two-column on desktop, single on mobile.
   Cards inside use .post-card (defined above).
   ------------------------------------------------------------ */

.related {
  max-width: 880px;
  margin: 56px auto 0;
  padding: 0 24px;
}
.related .label {
  font-family: var(--ui-font);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 12px;
}
.related .cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

@media (max-width: 640px) {
  .related {
    padding: 0 20px;
  }
  .related .cards {
    grid-template-columns: 1fr;
    gap: 10px;
  }
}

/* ------------------------------------------------------------
   Post card — the one card that links to a post.
   One component, one variant. Used on:
     - /blog index (as .post-card)
     - in-post "Related reading" blocks (as .post-card .post-card--compact)
     - homepage Reading Cards (React) (as .post-card)
   ------------------------------------------------------------ */

.post-card {
  display: flex;
  flex-direction: column;
  padding: 28px 28px 24px;
  background: var(--bg);
  border: 1px solid var(--edge);
  border-radius: 14px;
  text-decoration: none;
  color: var(--ink);
  transition:
    border-color 200ms var(--ease-quiet),
    transform 260ms var(--ease-considered),
    box-shadow 260ms var(--ease-considered),
    background 200ms var(--ease-quiet);
}

.post-card:hover {
  border-color: var(--edge-strong);
  transform: translateY(-2px);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.03),
    0 14px 30px -20px rgba(55, 53, 47, 0.14);
}

.post-card:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 3px;
}

/* Eyebrow — .post-card__eyebrow is the preferred class; the short
   .eb alias is kept so the in-post related-reading markup can stay
   terse. Format is always "CATEGORY · N MIN READ", uppercased here
   so the markup can stay natural-case (better for JSON-LD / LLMs). */
.post-card__eyebrow,
.post-card .eb {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 14px;
}

/* Title — .post-card__title is preferred. Plain <h3> inside a card
   gets the same treatment, so markup can stay lean. */
.post-card__title,
.post-card h3 {
  font-family: var(--reading-font);
  font-size: 22px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0 0 10px;
  text-wrap: balance;
  /* The hover underline draws in the marker yellow — same --hl-fill
     as the hero's .mark band. Transparent at rest so nothing shifts
     when the color arrives. Thicker than a default underline because
     the yellow is pale by design. */
  text-decoration: underline 3px transparent;
  text-underline-offset: 3px;
  transition: text-decoration-color 260ms var(--ease-considered);
}

.post-card:hover .post-card__title,
.post-card:hover h3 {
  text-decoration-color: var(--hl-fill);
}

/* Description — .post-card__desc is preferred. Plain <p> inside a
   card inherits the same treatment. */
.post-card__desc,
.post-card p {
  font-family: var(--ui-font);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0 0 22px;
  flex: 1;
  text-wrap: pretty;
}

.post-card__desc code,
.post-card p code {
  font-family: var(--mono);
  font-size: 0.88em;
  background: var(--bg-sub);
  border: 1px solid var(--edge);
  border-radius: 3px;
  padding: 1px 5px;
}

/* CTA — .post-card__cta is preferred. The historical .more span
   inside the in-post related-reading markup is aliased so existing
   markup still renders. Note: the ::after arrow is on the class
   variant only; .more markup has the arrow baked into its text node,
   so doubling it would look wrong. */
.post-card__cta,
.post-card .more {
  font-family: var(--ui-font);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  text-decoration: none;
}

.post-card__cta::after {
  content: "→";
  color: var(--muted);
  transition:
    transform 200ms var(--ease-quiet),
    color 200ms var(--ease-quiet);
}

.post-card:hover .post-card__cta::after {
  transform: translateX(3px);
  color: var(--ink);
}

/* For legacy .more (arrow baked into the text), shift the whole span
   on hover instead — the character is part of the text node, we can't
   animate it independently. Subtle and still feels alive. */
.post-card:hover .more {
  color: var(--ink);
  transform: translateX(2px);
}
.post-card .more {
  transition:
    color 180ms var(--ease-quiet),
    transform 200ms var(--ease-quiet);
}

.post-card__meta {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: auto;
}

/* Compact — the in-post "Related reading" density. Same component,
   smaller breathing room and a slightly quieter title. */
.post-card--compact {
  padding: 20px 22px;
  border-radius: 12px;
}

.post-card--compact .post-card__title,
.post-card--compact h3 {
  font-size: 20px;
  line-height: 1.22;
  margin: 0 0 6px;
}

.post-card--compact .post-card__eyebrow,
.post-card--compact .eb {
  margin-bottom: 6px;
}

.post-card--compact .post-card__desc,
.post-card--compact p {
  font-size: 14px;
  line-height: 1.55;
  margin: 0 0 8px;
}

.post-card--compact:hover {
  transform: translateY(-1px);
}

/* Mobile — editorial cards get a hair less padding; compact cards
   stay tight. Title drops one step so two-line titles don't dominate
   a narrow viewport. */
@media (max-width: 640px) {
  .post-card {
    padding: 22px 22px 20px;
    border-radius: 12px;
  }
  .post-card__title,
  .post-card h3 {
    font-size: 20px;
  }
  .post-card--compact {
    padding: 18px 20px;
  }
  .post-card--compact .post-card__title,
  .post-card--compact h3 {
    font-size: 18px;
  }
}

/* ------------------------------------------------------------
   Body prose link — marker highlight.
   Design intent: a real highlighter ink-swipe, not a CSS underline
   pretending to be one. Three moves that separate this from the
   flat-band version:
     1. Translucent fill (color-mix with alpha) — paper shows
        through, so the mark reads as pigment absorbed into the
        page, not printed-plastic placed on top.
     2. Density variation — a two-stop gradient (slightly darker
        at the top "wet edge" where a marker tip lands, lightening
        as it bleeds down). This is how real marker ink looks when
        you swipe a highlighter across a word.
     3. The band sits *behind* the text (high on the line, covering
        the x-height), not below it. You read through the ink, the
        way a highlighter actually works.
   Animation: background-size / background-position DO animate
   (gradient-stop % don't). At rest the band is a narrow stripe
   sitting on the baseline; on hover it scales up to cover the
   x-height with a measured overshoot — the marker landing. One
   wild moment per surface, here.
   ------------------------------------------------------------ */

article a:not([class]),
.doc a:not([class]),
.tldr a:not([class]),
.post-body a:not([class]) {
  color: var(--ink);
  text-decoration: none;
  /* Translucent fill — same hue family as --hl-fill, but with alpha
     so ink absorbs into the paper. Top of the band is the "wet
     edge": ~3% darker, slightly more saturated. Bottom bleeds out
     to a softer wash. Not flat. */
  background-image: linear-gradient(
    175deg,
    color-mix(in oklab, var(--hl-fill) 82%, #b8860b) 0%,
    color-mix(in oklab, var(--hl-fill) 78%, transparent) 45%,
    color-mix(in oklab, var(--hl-fill) 64%, transparent) 100%
  );
  background-repeat: no-repeat;
  /* At rest: the band already covers the x-height so a link reads as
     a marked word, not a faint baseline underline — a bare URL in
     bold or RTL prose needs that affordance up front. Positioned at
     100% (bottom), 60% tall; floods to ~88% on hover via
     background-size. */
  background-position: 0 100%;
  background-size: 100% 60%;
  padding: 0 1px;
  border-radius: 1px;
  /* Tiny -0.5° skew gives the mark a hand-drawn feel. Applied to
     the background via a CSS custom property so text stays upright.
     Easier route: let the stripe itself stay horizontal but add a
     micro-offset at one edge via background-position. We use
     size/position — both animate natively. */
  transition:
    background-size 320ms var(--ease-overshoot),
    background-position 320ms var(--ease-overshoot),
    color 200ms var(--ease-quiet);
}

article a:not([class]):hover,
.doc a:not([class]):hover,
.tldr a:not([class]):hover,
.post-body a:not([class]):hover {
  /* Band floods from the resting 60% up to 88% (covering the
     x-height and a hair of the ascenders). The overshoot easing
     makes it settle, not snap. Position stays at bottom — the mark
     grows upward from the baseline, the way a highlighter would
     flood the word. */
  background-size: 100% 88%;
  background-position: 0 98%;
}

article a:not([class]):focus-visible,
.doc a:not([class]):focus-visible,
.tldr a:not([class]):focus-visible,
.post-body a:not([class]):focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ------------------------------------------------------------
   Sticky-note — one component, three uses.
   .audience-card sits in the homepage marketing grid; .verdict and
   .pullquote sit mid-prose in long reads. Same paper paint, same
   paper-shadow, same hover gesture (un-tilt + lift). Variants
   override only what differs: paper color (--note-bg), rest tilt
   (--note-tilt), hover-lift amplitude (--note-lift). The legacy
   class names stay as the variant selectors so existing markup
   keeps working without touch.
   ------------------------------------------------------------ */

.audience-card,
.verdict,
.pullquote,
.sample-note,
.shared-note {
  position: relative;
  border: 0;
  border-radius: 6px;
  background: var(--note-bg, var(--note-butter));
  transform: rotate(var(--note-tilt, -0.4deg));
  transform-origin: 50% 60%;
  box-shadow:
    0 1px 2px rgba(15, 15, 15, 0.05),
    0 4px 10px -2px rgba(15, 15, 15, 0.08),
    0 18px 32px -18px rgba(15, 15, 15, 0.18);
  color: #1a1a1a;
  transition:
    transform 240ms cubic-bezier(.2, .9, .2, 1),
    box-shadow 240ms ease;
}

.audience-card:hover,
.verdict:hover,
.pullquote:hover,
.sample-note:hover,
.shared-note:hover {
  transform: rotate(0deg) translateY(var(--note-lift, -3px));
  box-shadow:
    0 2px 4px rgba(15, 15, 15, 0.06),
    0 10px 22px -4px rgba(15, 15, 15, 0.13),
    0 28px 48px -20px rgba(15, 15, 15, 0.25);
}

/* In-post .verdict — quieter sit, butter, mid-prose. */
.verdict {
  --note-bg: var(--note-butter);
  --note-tilt: -0.35deg;
  --note-lift: -2px;
  margin: 1.6em 0 1.8em;
  padding: 14px 16px 15px;
  font-family: var(--ui-font);
  font-size: 15px;
  line-height: 1.55;
}

.verdict strong {
  display: block;
  margin-bottom: 3px;
  font-family: var(--ui-font);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(15, 15, 15, 0.62);
}

/* In-post .pullquote — editorial moment, blush, stronger tilt. */
.pullquote {
  --note-bg: var(--note-blush);
  --note-tilt: 0.6deg;
  --note-lift: -3px;
  margin: 2.6em 0 2.8em;
  padding: 26px 28px 28px;
  font-family: var(--reading-font);
  font-size: 20px;
  font-weight: 500;
  line-height: 1.45;
  letter-spacing: -0.005em;
}

/* Example banner — thin strip that rides inside the sticky .topbar on an
   example surface (a live, pre-marked sample). It carries the visitor to the
   matching tool page to learn how it works and get started. Because it lives
   inside .topbar it inherits the sticky-to-top behavior; the topbar's own
   bottom border sits below it, so a top border separates it from the brand row. */
.example-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  max-width: 1100px;
  margin: 0 auto;
  padding: 7px 24px;
  border-top: 1px solid var(--edge-subtle);
  font-size: 13px;
  color: var(--ink-2);
  text-decoration: none;
  transition: color 120ms ease, background 120ms ease;
}
.example-banner:hover { color: var(--ink); background: var(--bg-sub); }
.example-banner:focus-visible {
  outline: 2px solid var(--ring, var(--hl-edge));
  outline-offset: -2px;
}
.example-banner-tag {
  flex: none;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #7a4f00;
  background: var(--hl-fill);
  padding: 2px 7px;
  border-radius: 5px;
}
.example-banner-text strong { color: var(--ink); font-weight: 600; }
.example-banner-arrow {
  flex: none;
  transition: transform 140ms ease;
}
.example-banner:hover .example-banner-arrow { transform: translateX(2px); }
@media (max-width: 640px) {
  .example-banner { padding: 7px 16px; gap: 7px; font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .example-banner-arrow { transition: none; }
}

/* In-app .sample-note — instructional sticky pinned to the top of the
   review column when the user clicks "Try a sample". Blush paper so it
   sits warm against the yellow marker that the .strong inside its title
   uses, and stays out of the cool/green register where nothing else on
   the site lives. Slightly stronger lift than .verdict so it reads as
   "interactive UI element," not "in-prose callout." */
.sample-note {
  --note-bg: var(--note-blush);
  --note-tilt: -0.6deg;
  --note-lift: -3px;
  margin: 0 0 36px;
  padding: 16px 44px 18px 20px;
  font-family: var(--ui-font);
  /* One-shot entrance: settles into rest tilt with a gentle overshoot
     on first paint. The single wild moment on this surface — never
     fires again, never on hover. */
  animation: sample-note-settle 520ms var(--ease-overshoot) both;
}

@keyframes sample-note-settle {
  0%   { opacity: 0; transform: rotate(0deg) translateY(-6px) scale(.985); }
  60%  { opacity: 1; }
  100% { opacity: 1; transform: rotate(var(--note-tilt)) translateY(0) scale(1); }
}

/* In-app .shared-note — the line the sharer wrote, pinned to the top of the
   review column when a recipient opens a shared link. Butter paper (the warm
   marker-yellow register) so it reads as a personal sticky from another person.
   Tilts the opposite way from the sample note. Reuses the sample-note eyebrow /
   dot / close sub-elements. */
.shared-note {
  --note-bg: var(--note-butter);
  --note-tilt: 0.6deg;
  --note-lift: -3px;
  margin: 0 0 36px;
  padding: 16px 44px 18px 20px;
  font-family: var(--ui-font);
  animation: sample-note-settle 520ms var(--ease-overshoot) both;
}

/* Sharer's name in the eyebrow slot — opts out of the eyebrow's uppercase /
   wide-tracking label register so a real name reads as a name. */
.shared-note-from {
  text-transform: none;
  letter-spacing: 0.005em;
  font-size: 12.5px;
  color: var(--ink);
}

.shared-note-body {
  margin: 0;
  font-family: var(--ui-font);
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* In-app .share-welcome — a quiet provenance byline above a shared doc, NOT a
   banner. No border, no fill, no full-width pill: just a small muted line that
   says who the doc came from, sitting like a byline over the title. It's the
   always-on companion to the sidebar "shared by" badge. The first time a
   recipient opens a shared doc it also carries a subtle "What is this?" text
   link; after that the link drops and only the byline stays. */
.share-welcome {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin: 0 0 18px;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--ui-font);
  font-size: 12px;
  line-height: 1.4;
  color: var(--muted);
  animation: share-welcome-in 320ms var(--ease-quiet) both;
}

@keyframes share-welcome-in {
  from { opacity: 0; transform: translateY(-3px); }
  to   { opacity: 1; transform: translateY(0); }
}

.share-welcome-text { text-align: start; }

/* Leading person marker — the same quiet bust as the sidebar "shared by" badge,
   so provenance reads consistently in both places. */
.share-welcome-icon {
  display: inline-flex;
  align-items: center;
  flex: none;
  color: var(--muted);
  opacity: 0.8;
}
.share-welcome-icon svg { display: block; }

/* The sharer's name — lifted a notch out of the muted line so it reads as a
   person, not boilerplate. dir="auto" in the markup keeps a Hebrew name laid
   out correctly inside the English byline. */
.share-welcome-from {
  color: var(--ink-2);
  font-weight: 600;
}

/* First-time explainer link — a subtle text link, never a chip. A hairline
   underline that warms to full ink on hover; the marker-yellow chip was too
   loud for a byline. */
.share-welcome-link {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--ink-2);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--border-strong);
  text-underline-offset: 3px;
  transition: color 120ms var(--ease-quiet), text-decoration-color 120ms var(--ease-quiet);
}
.share-welcome-link:hover { color: var(--ink); text-decoration-color: var(--ink); }
.share-welcome-link:focus-visible {
  outline: none;
  color: var(--ink);
  text-decoration-color: var(--ink);
  border-radius: 3px;
  box-shadow: 0 0 0 2px var(--ring);
}
.share-welcome-link svg { display: block; flex: none; opacity: 0.7; }

.sample-note-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--ui-font);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(15, 15, 15, 0.62);
  margin: 0 0 8px;
}

.sample-note-dot {
  position: relative;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #f5c518;
  flex: none;
  box-shadow: 0 0 0 0 rgba(245, 197, 24, 0.55);
  animation: sample-dot-pulse 1800ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

.sample-note-title {
  margin: 0 0 6px;
  font-family: var(--ui-font);
  font-size: 15.5px;
  font-weight: 500;
  line-height: 1.45;
  color: var(--ink);
}
.sample-note-title strong {
  font-weight: 600;
  background: var(--hl-fill);
  padding: 1px 4px;
  border-radius: 2px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

.sample-note-sub {
  margin: 0;
  font-family: var(--ui-font);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-2);
}
.sample-note-sub strong {
  color: var(--ink);
  font-weight: 600;
}

/* Dismiss control — top-right "×". Sized to the optical balance of the
   eyebrow row, not boxy. Hover darkens the ink, no background change;
   the sticky note's own un-tilt would be loud here, so we suppress it
   by keeping the paper still while the × responds. */
.sample-note-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: 4px;
  color: rgba(15, 15, 15, 0.42);
  cursor: pointer;
  transition: color 140ms ease, background 140ms ease;
}
.sample-note-close:hover {
  color: rgba(15, 15, 15, 0.78);
  background: rgba(15, 15, 15, 0.06);
}
.sample-note-close:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
  color: rgba(15, 15, 15, 0.78);
}
.sample-note-close svg { display: block; }

@media (max-width: 720px) {
  .pullquote { font-size: 18px; padding: 22px 22px 24px; }
  .verdict { padding: 13px 15px 14px; }
  .sample-note,
  .shared-note {
    padding: 14px 40px 15px 18px;
    margin-bottom: 28px;
  }
  .sample-note-title { font-size: 14.5px; }
  .sample-note-sub { font-size: 12.5px; line-height: 1.5; }
  .shared-note-body { font-size: 14.5px; }
}

/* ------------------------------------------------------------
   Page footer — single source. Two quiet rows: byline | nav,
   privacy tag | bug report. No pill, no underlined prose.
   <footer class="page-foot">
     <div class="page-foot-row">
       <span>Built by <a>Elad</a> in a fit of OMG.</span>
       <nav class="foot-nav">…links…</nav>
     </div>
     <div class="page-foot-row page-foot-row--quiet">
       <span>your document never leaves your browser</span>
       <a class="foot-nav-bug">Report a bug</a>
     </div>
   </footer>
   ------------------------------------------------------------ */

.page-foot {
  max-width: 880px;
  margin: 56px auto 0;
  padding: 22px 24px 40px;
  border-top: 1px solid var(--border);
  font-family: var(--ui-font);
  font-size: 13px;
  color: var(--muted);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.page-foot a {
  color: var(--ink-2);
  text-decoration: none;
  transition: color 140ms var(--ease-quiet);
}

.page-foot a:hover { color: var(--ink); }

.page-foot-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  align-items: center;
  justify-content: space-between;
}

.page-foot-row--quiet {
  font-size: 12.5px;
  opacity: 0.78;
}

.foot-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
}

/* Hidden under the workspace — a marketing footer beneath the review surface
   is the wrong note. Only the homepage runs the React app today, but the
   rule lives here so any future React page inherits it. */
body:has(.app.mode-review) .page-foot { display: none; }

@media (max-width: 720px) {
  .page-foot {
    padding: 20px 20px 32px;
  }
  .page-foot-row {
    align-items: flex-start;
  }
  .foot-nav { gap: 14px; }
}

/* ------------------------------------------------------------
   Reduced motion — every transition in this file collapses to 0.
   Color changes still apply (they're the semantic feedback); only
   the time-based motion is cut.
   ------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .post-card,
  .post-card__title,
  .post-card__cta::after,
  .audience-card,
  .verdict,
  .pullquote,
  .sample-note,
  article a:not([class]),
  .doc a:not([class]),
  .tldr a:not([class]),
  .post-body a:not([class]) {
    transition: none;
  }
  .audience-card,
  .verdict,
  .pullquote,
  .sample-note {
    transform: none;
    animation: none;
  }
  .audience-card:hover,
  .verdict:hover,
  .pullquote:hover,
  .sample-note:hover {
    transform: translateY(-1px);
  }
  .sample-note-dot {
    animation: none;
  }
  .post-card:hover {
    transform: none;
  }
  .post-card:hover .post-card__cta::after {
    transform: none;
  }
}

/* ============================================================
   Dark mode overrides — shared components.

   These selectors flip surfaces, shadows, and chips that use raw
   values for legitimate reasons (semantic chips, opacity-based
   shadows, photographic dim). Token-bound rules elsewhere flip
   automatically via the [data-theme="dark"] block in tokens.css.
   ============================================================ */

/* ---- Topbar ----
   The blur background is var(--topbar-blur) — already flips. Keep
   the rule here as a no-op cue for future maintainers. */

/* ---- Post-card hover shadow ----
   Light shadow (rgba(55,53,47,0.14)) becomes invisible on dark.
   Use stronger black with lower offset; the surface lift does
   most of the work. */
[data-theme="dark"] .post-card {
  background: var(--surface-2);
}
[data-theme="dark"] .post-card:hover {
  background: var(--surface-3);
  border-color: var(--edge-strong);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.45),
    0 14px 30px -20px rgba(0, 0, 0, 0.55);
}

/* ---- Sticky notes (.audience-card / .verdict / .pullquote / .sample-note) ----
   Paper stays paper — we don't flip the cream/blush/sage hex.
   Two things happen in dark mode:
     1. Dim the whole element so the paper doesn't blast as a
        headlight against the near-black canvas.
     2. Re-pin --ink, --ink-2, --muted to literal dark values
        WITHIN the scope of the note. Children that read
        var(--ink) for text would otherwise resolve to the dark
        theme's off-white — invisible on the still-light paper. */
[data-theme="dark"] .audience-card,
[data-theme="dark"] .verdict,
[data-theme="dark"] .pullquote,
[data-theme="dark"] .sample-note,
[data-theme="dark"] .shared-note {
  filter: brightness(0.88) contrast(1.04);
  --ink:            #1a1815;
  --ink-2:          #4a463f;
  --muted:          #6b665e;
  --text-primary:   #1a1815;
  --text-secondary: #4a463f;
  --text-muted:     #6b665e;
}

/* ---- Photographs / screenshots ----
   Single blanket rule. Opt out with [data-no-dim] / .brand-asset. */
[data-theme="dark"] img:not([data-no-dim]):not(.brand-asset):not(.no-dim) {
  filter: var(--img-filter);
}

/* ---- Selection ---- */
[data-theme="dark"] ::selection {
  background: rgba(252, 211, 77, 0.32);
  color: var(--text-primary);
}

/* ---- Reduced motion: don't animate the theme transition ---- */
@media (prefers-reduced-motion: no-preference) {
  html {
    transition: background-color 200ms var(--ease-quiet),
                color 200ms var(--ease-quiet);
  }
}

/* ============================================================
   .skill-cta — prominent download pill for SKILL.md files,
   used on the launch-note blog page (and any future skill
   article that needs to break the inline-link-buried-in-prose
   pattern). Mirrors the .launch-banner-cta-primary vocabulary
   so the article CTA reads as the same call as the homepage
   banner: filled ink pill, marker-yellow .md glyph, hover lift.
   Sits as its own block — never inline inside a paragraph.

   .skill-cta-row pairs the pill with a quiet meta line
   (version · license · size) on the right; on mobile they
   stack with the pill above the meta.
   ============================================================ */
.skill-cta-row {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin: 28px 0 36px;
}
.skill-cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 22px 14px 18px;
  background: var(--ink);
  color: var(--text-on-emphasis);
  font-family: var(--ui-font);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  border-radius: 999px;
  line-height: 1;
  box-shadow:
    0 1px 2px rgba(15, 15, 15, 0.18),
    0 6px 16px -8px rgba(15, 15, 15, 0.35);
  transition:
    background-color 160ms var(--ease-quiet),
    transform 200ms var(--ease-considered),
    box-shadow 200ms var(--ease-considered);
}
.skill-cta:hover {
  background: #1f1d18;
  transform: translateY(-1px);
  box-shadow:
    0 2px 3px rgba(15, 15, 15, 0.22),
    0 12px 22px -10px rgba(15, 15, 15, 0.45);
}
.skill-cta:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 3px;
}
.skill-cta:active { transform: translateY(0); }
.skill-cta-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  color: var(--hl-fill);
  flex-shrink: 0;
}
.skill-cta-glyph svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.skill-cta-arrow {
  display: inline-block;
  transition: transform 200ms var(--ease-considered);
}
.skill-cta:hover .skill-cta-arrow { transform: translateX(2px); }
.skill-cta-meta {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: var(--muted);
}
[data-theme="dark"] .skill-cta:hover {
  background: #ffffff;
  box-shadow:
    0 2px 3px rgba(0, 0, 0, 0.45),
    0 12px 22px -10px rgba(0, 0, 0, 0.55);
}
@media (prefers-reduced-motion: reduce) {
  .skill-cta, .skill-cta-arrow { transition: none; }
}
@media (max-width: 600px) {
  .skill-cta-row { flex-direction: column; align-items: flex-start; gap: 10px; }
  .skill-cta { font-size: 14.5px; padding: 13px 20px 13px 16px; }
}

/* ============================================================================
   Static content-page rail (.site-rail)
   ----------------------------------------------------------------------------
   The unified docked sidebar for the static content pages (about / privacy /
   manifesto / blog index + posts). A deliberately LIGHTER sibling of the app's
   SPA rail (.doc-nav in index.html): it shares the spine — brand (Zone A) + the
   two tool links (Zone B) — but has no live Documents zone (static pages have
   no doc state), so it carries one site link (Blog), one primary CTA, and a
   theme toggle. Visual language matches the app rail via the shared tokens;
   keep the two in sync if either moves. Markup: <aside class="site-rail">,
   rendered AFTER <main> in source order and fixed-positioned, so the article
   stays crawl-first.
   ============================================================================ */
.site-rail {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  z-index: 91;
  width: var(--dock-w);
  max-width: 86vw;
  background: var(--surface-4);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  /* Off-canvas by default; .is-open (mobile) or the >=1024px docked rule
     below slides it in. */
  transform: translateX(-100%);
  transition: transform 240ms var(--ease-considered);
}
.site-rail.is-open { transform: translateX(0); box-shadow: 10px 0 40px rgba(15, 15, 15, 0.18); }
.site-rail-backdrop {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(15, 15, 15, 0.32);
  opacity: 0; pointer-events: none;
  transition: opacity 140ms ease-out;
}
.site-rail-backdrop.is-open { opacity: 1; pointer-events: auto; }

/* Zone A — identity. Wordmark links home; close (✕) rides the right on mobile. */
.site-rail-brand {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px 8px 16px;
}
.site-rail-logo {
  margin-inline-end: auto;
  display: inline-flex; align-items: center; gap: 8px;
  margin-left: -6px; padding: 4px 6px;
  border: none; background: transparent; border-radius: 7px;
  text-decoration: none;
  font-family: var(--ui-font); font-weight: 600; font-size: 14px;
  letter-spacing: -0.005em; color: var(--ink);
  transition: background 120ms ease;
}
.site-rail-logo:hover { background: var(--bg-sub); }
.site-rail-logo .dot {
  width: 16px; height: 16px; border-radius: 4px;
  background: linear-gradient(135deg, #37352f 0%, #5c5b57 100%);
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-size: 10px; font-weight: 700;
}
.site-rail-logo .brand-omg, .site-rail-logo .brand-md { font-weight: 700; }
.site-rail-logo .muted { color: var(--muted); font-weight: 400; }
.site-rail-close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  border: none; background: transparent; border-radius: 7px;
  color: var(--ink-2); cursor: pointer;
}
.site-rail-close:hover { background: var(--chip-bg); color: var(--ink); }

/* Shared nav-link treatment (Zone B tools + the Blog link). Mirrors the app
   rail's .doc-nav-link. */
.site-rail-nav { display: flex; flex-direction: column; gap: 2px; padding: 4px 8px 8px; }
.site-rail-link {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 8px;
  text-decoration: none;
  font-family: var(--ui-font); font-size: 13.5px; color: var(--ink-2);
  transition: background 120ms ease, color 120ms ease;
}
.site-rail-link svg { flex: 0 0 auto; color: var(--muted); transition: color 120ms ease; }
.site-rail-link:hover { background: var(--bg-sub); color: var(--ink); }
.site-rail-link:hover svg { color: var(--ink); }
.site-rail-link.is-active { background: var(--chip-bg); color: var(--ink); font-weight: 600; }
.site-rail-link.is-active svg { color: var(--ink); }
.site-rail-sep { height: 1px; margin: 4px 12px; background: var(--edge-subtle); }

/* "From the blog" — fills the rail's middle band with real discovery instead of
   dead space. Scrolls independently if the list outgrows the rail; the CTA +
   theme footer stay pinned below it. */
.site-rail-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 8px;
}
.site-rail-list-label {
  font-family: var(--mono);
  font-size: 10px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--muted);
  padding: 6px 10px 4px;
}
.site-rail-posts { display: flex; flex-direction: column; }
/* Each row: a small folded-page glyph + a 2-line-clamped title, so the list
   reads as a tidy set of articles, not a wall of text. */
.site-rail-post {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 7px 10px; border-radius: 8px;
  text-decoration: none; color: var(--ink-2);
  transition: background 120ms ease, color 120ms ease;
}
.site-rail-post:hover { background: var(--bg-sub); color: var(--ink); }
.site-rail-post-icon {
  flex: 0 0 auto; margin-top: 1px;
  color: var(--muted); transition: color 120ms ease;
}
.site-rail-post:hover .site-rail-post-icon { color: var(--ink); }
.site-rail-post-title {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-family: var(--ui-font); font-size: 12.5px; line-height: 1.35;
}

/* Primary CTA — the rail's one filled element. It now sits HIGH (right under
   the nav, above the blog list) so a reader sees it immediately; a bottom
   hairline + breathing room frame it as a deliberate block, not a stray button.
   The blog list scrolls below it. */
.site-rail-cta-wrap {
  padding: 8px 12px 12px;
  margin: 0 0 4px;
  border-bottom: 1px solid var(--edge-subtle);
}
.site-rail-cta-eyebrow {
  display: block;
  padding: 0 2px 6px;
  font-family: var(--ui-font);
  font-size: 10.5px; font-weight: 500; letter-spacing: 0.02em;
  color: var(--muted);
}
.site-rail-cta {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 11px 14px; border-radius: 9px;
  background: var(--ink); color: var(--surface-1);
  text-decoration: none;
  font-family: var(--ui-font); font-size: 14px; font-weight: 600;
  box-shadow: 0 1px 2px rgba(15, 15, 15, 0.14), 0 8px 18px -12px rgba(15, 15, 15, 0.35);
  transition: opacity 120ms ease, transform 160ms var(--ease-considered);
}
.site-rail-cta:hover { opacity: 0.9; transform: translateY(-1px); }
@media (prefers-reduced-motion: reduce) { .site-rail-cta { transition: opacity 120ms ease; } }

/* Footer — theme only. */
.site-rail-foot { border-top: 1px solid var(--edge-subtle); padding: 8px; margin-top: 8px; }
.site-rail-theme {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 7px 10px; border-radius: 8px;
  border: none; background: transparent; cursor: pointer;
  color: var(--muted); font-family: var(--ui-font); font-size: 12.5px; text-align: start;
  transition: background 120ms ease, color 120ms ease;
}
.site-rail-theme svg { flex: 0 0 auto; }
.site-rail-theme:hover { background: var(--bg-sub); color: var(--ink); }

/* Mobile top bar — the hamburger trigger + brand + CTA, shown <1024px when the
   rail is off-canvas. Mirrors the app's mobile topbar geometry. */
.site-bar {
  position: sticky; top: 0; z-index: 80;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 14px;
  background: var(--surface-4); border-bottom: 1px solid var(--border);
}
.site-bar-burger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; margin-left: -4px;
  border: none; background: transparent; border-radius: 7px;
  color: var(--ink); cursor: pointer;
}
.site-bar-burger:hover { background: var(--bg-sub); }
.site-bar-brand {
  display: inline-flex; align-items: center; gap: 8px;
  text-decoration: none; color: var(--ink);
  font-family: var(--ui-font); font-weight: 600; font-size: 14px;
}
.site-bar-brand .dot {
  width: 16px; height: 16px; border-radius: 4px;
  background: linear-gradient(135deg, #37352f 0%, #5c5b57 100%);
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-size: 10px; font-weight: 700;
}
.site-bar-brand .muted { color: var(--muted); font-weight: 400; }
/* Filled pill — the only conversion affordance above the fold on mobile, so it
   carries the same intent as the desktop rail CTA, scaled down (not a faint
   tertiary link). */
.site-bar-cta {
  margin-inline-start: auto;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 7px;
  background: var(--ink); color: var(--surface-1);
  text-decoration: none;
  font-family: var(--ui-font); font-size: 12.5px; font-weight: 600;
  white-space: nowrap;
  transition: opacity 120ms ease;
}
.site-bar-cta:hover { opacity: 0.88; color: var(--surface-1); }

/* Desktop (>=1024px): rail is permanent furniture, the mobile bar hides, and
   the page content offsets by the rail width — the static mirror of the app's
   `.app.is-docked { padding-left: var(--dock-w) }`. */
@media (min-width: 1024px) {
  .site-rail { transform: translateX(0); }
  .site-rail-close, .site-bar { display: none; }
  body:has(.site-rail) { padding-inline-start: var(--dock-w); }
  /* The rail isn't part of the offset flow; cancel any backdrop. */
  .site-rail-backdrop { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .site-rail { transition: none; }
  .site-rail-backdrop { transition: none; }
}
