:root {
  --house-border-radius: 0.5em;

  /* housemd's stylesheet is written against `--ember`, its own accent token,
     which this app has never defined — so both tokens below that referenced it
     resolved to nothing from the day the editor was installed. `var()` with an
     undefined custom property is invalid at computed-value time, so the editor's
     caret colour, its link colour, and its selection highlight all silently fell
     back to whatever they inherited. Nothing looked broken enough to notice; an
     audit found it by grepping for the token's definition and not finding one.

     Mapped to this app's accent, at the right rung for each job: links and the
     caret are TEXT on a light card, so they take --spark-link (the deeper rung
     that clears AA — see application.css), while the selection tint is a 15%
     wash where the base --spark is correct. */
  --ember: var(--spark);

  --color-bg: var(--background);
  --color-link: var(--spark-link);
  --color-negative: var(--destructive);
  --color-positive: var(--success);
  --color-subtle: var(--muted);
  --color-selected-dark: color-mix(in oklch, var(--ember) 15%, var(--background));
  --color-ink-reversed: var(--destructive-foreground);
}

:where(house-md) {
  display: flex;
  flex-direction: column;
  flex-grow: 1;

  /* :invalid is constraint validation; aria-invalid is a server-rendered error.
     <house-md> is not a maquina input, so the engine paints neither. */
  &:invalid,
  &[aria-invalid="true"] {
    border: var(--color-negative) 2px solid;
  }
}

/* When the toolbar lives inside a `.markdown-body` review surface, pin it
   below the sticky page header (top-32 ≈ 8rem in the product brief layout)
   so it stays reachable while scrolling the editor, and hide it until focus
   lands inside the wrapper so it can't drift over the prose while you're
   only reading. `:focus-within` sits on `.markdown-body` rather than on
   `house-md` because the wrapper is the only ancestor the toolbar and the
   editor share — see Recuerd0 #1318 for why that, `visibility` over
   `display`, and the split transition timing are each load-bearing. */
.markdown-body :where(house-md-toolbar) {
  position: sticky;
  top: 8rem;
  z-index: 5;
  box-shadow: 0 1px 0 var(--border);
  opacity: 0;
  /* `visibility` is discrete — delay it by the fade on the way out, apply it
     instantly on the way in. `pointer-events` isn't animatable, so it flips
     at once and closes the window where a faded pill is still clickable. */
  visibility: hidden;
  pointer-events: none;
  transition: opacity 150ms ease, visibility 0s linear 150ms;

  @media (prefers-reduced-motion: reduce) {
    transition: none;
  }
}

.markdown-body:focus-within :where(house-md-toolbar) {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 150ms ease, visibility 0s;

  @media (prefers-reduced-motion: reduce) {
    transition: none;
  }
}

/* A COMPOSE surface is not a review surface, and both halves of the rule above
   are wrong on one. The seed page's card holds a single document and no prose,
   and its page header is not pinned (see `planning_documents/_new_seed`), so:

   Hiding until `:focus-within` left a blank 400px slab with no toolbar, no
   placeholder and no label inside it — the least-designed screen in the flow,
   one click from the most-designed one — and kept all seven buttons out of the
   tab order until focus was already inside the element they format.

   And 8rem was measured against the review layout. Here it pinned the toolbar
   underneath a 215px sticky header: 66% hidden on an empty document, 100% on a
   real one. Raising the offset would only re-tune a number that changes with
   the locale; removing the conflict is what fixes it. */
.markdown-body[data-editor="compose"] :where(house-md-toolbar) {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  top: 0.5rem;
  transition: none;
}

/* Toolbar — pill container with soft background; matches the brief's review surface. */
:where(house-md-toolbar) {
  --hover-size: 0;

  align-items: center;
  background-color: var(--muted);
  border-radius: 9999px;
  display: flex;
  gap: 0.125rem;
  margin: 0 auto 0.75rem;
  padding: 0.25rem 0.5rem;
  width: fit-content;

  :is(button, label) {
    align-items: center;
    appearance: none;
    background-color: transparent;
    border: none;
    border-radius: 9999px;
    color: var(--muted-foreground);
    cursor: pointer;
    display: inline-flex;
    flex-shrink: 0;
    height: 1.75rem;
    justify-content: center;
    margin: 0;
    padding: 0;
    transition: background-color 150ms ease, color 150ms ease;
    width: 1.75rem;

    :is(img, svg) {
      -webkit-touch-callout: none;
      block-size: 1rem;
      inline-size: 1rem;
      user-select: none;
    }

    /* `outline: none` here beat the app's baseline focus ring — house.css is
       unlayered, and unlayered CSS wins over `@layer components` at any
       specificity — so a keyboard user got a background change identical to
       hover, measured at 1.09:1 against the resting pill. The ring is INSET
       rather than the app's usual `outline-offset: 3px`: these are 28px circles
       2px apart, so an outward ring would collide with its neighbour's. It
       follows the pill radius, which an outward ring at this size does not. */
    &:where(:focus-visible) {
      background-color: var(--background);
      color: var(--foreground);
      outline: 2px solid var(--spark);
      outline-offset: -2px;
    }

    /* 28px is a mouse target. Where the pointer is coarse it is the smallest
       thing on the page and the seven of them sit 2px apart — keyed on the
       input method, not a width breakpoint, same reasoning as the tap-target
       rule in application.css. */
    @media (pointer: coarse) {
      height: 2.75rem;
      width: 2.75rem;
    }

    @media (hover: hover) {
      &:hover {
        background-color: var(--background);
        color: var(--foreground);
      }
    }

    &:where(:active) {
      background-color: var(--color-selected-dark);
      color: var(--foreground);
    }
  }
}

/* Markdown Content */
:where(.house-md-content) {
  caret-color: var(--color-link);
  flex-grow: 1;
  min-block-size: 50dvh;
  text-align: start;
  white-space: break-spaces;

  /* The editor is the primary input of the paste page and had NO focus
     indicator of any kind — no outline, no box-shadow, no border. The border
     stays suppressed (it would shift layout); the ring replaces the blanket
     `outline: none`. `:focus-visible` matches a contenteditable on pointer
     focus too, which is what a text surface wants. */
  &:focus,
  &:active {
    border: none;
    outline: none;
  }

  &:focus-visible {
    outline: 2px solid var(--spark);
    outline-offset: 4px;
    border-radius: var(--house-border-radius);
  }

  /* Housemd's parser wraps block-level markdown in <span class="..."> sentinels.
     Style each so the editor reflects markdown semantics live. */
  .h1 {
    display: inline-block;
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -0.025em;
    margin-block: 0.4em 0.2em;
  }
  .h2 {
    display: inline-block;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: -0.02em;
    margin-block: 0.4em 0.2em;
  }
  .h3 {
    display: inline-block;
    font-family: var(--font-display);
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: -0.02em;
    margin-block: 0.35em 0.15em;
  }
  .h4, .h5, .h6 {
    display: inline-block;
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 600;
    margin-block: 0.3em 0.1em;
  }
  .hr {
    color: var(--muted-foreground);
    letter-spacing: 0.5em;
  }
  .quote {
    color: var(--muted-foreground);
    font-style: italic;
  }
  .link {
    color: var(--color-link);
    text-decoration: underline;
    text-underline-offset: 2px;
  }
  .code {
    background-color: var(--muted);
    border-radius: 0.25rem;
    color: var(--foreground);
    font-family: var(--font-mono);
    font-size: 0.875em;
    padding: 1px 4px;
  }

  /* Fenced code blocks (```…```) — render as a continuous block with
     padding around the whole thing. Without `display: block` an inline
     .code span only paints the background where text sits, so multi-line
     code reads as separate inline runs instead of one unified box. */
  .code[data-fence] {
    display: block;
    margin: 0.5rem 0;
    padding: 0.5rem 0.75rem;
    white-space: pre-wrap;
    overflow-wrap: break-word;
  }
  .img {
    color: var(--muted-foreground);
    font-style: italic;
  }
  .comment {
    color: var(--muted-foreground);
    font-style: italic;
    opacity: 0.7;
  }
}

/* Uploads */
:where(house-md-upload) {
  border-radius: var(--house-border-radius);
  margin-block: 0.5ex;
  position: relative;

  &[status="failed"] {
    background-color: var(--color-negative);
    color: var(--color-ink-reversed);
    font-weight: bold;
    padding: 0.5em;
  }
}

:where(.md-close) {
  appearance: none;
  background-color: transparent;
  block-size: 1em;
  border: none;
  cursor: pointer;
  display: none;
  inset: 0.5em 0.5em auto auto;
  inline-size: 1em;
  outline: none;
  position: absolute;

  house-md-upload[status="failed"] & {
    color: var(--color-ink-reversed);
    display: inline-block;
  }

  &::before {
    color: var(--color-ink-reversed);
    content: '×';
    font-size: 24px;
    font-weight: bold;
    inset: 50% auto auto 50%;
    position: absolute;
    transform: translate(-50%, -50%);
  }
}

:where(.md-file) {
  font-weight: normal;

  house-md-upload[status="complete"] & {
    color: var(--color-positive);
  }
}

:where(.md-progress-bar) {
  -webkit-appearance: none;
  appearance: none;
  background-color: var(--color-subtle);
  block-size: 1ex;
  border-radius: var(--house-border-radius);
  display: block;
  inline-size: 100%;
  line-height: inherit;
  margin: 0;

  house-md-upload[status="failed"] & ,
  house-md-upload[status="complete"] & {
    display: none;
  }

  &::-webkit-progress-bar {
    background-color: var(--color-subtle);
    border-radius: var(--house-border-radius);
  }

  &::-webkit-progress-inner-element {
    border-radius: var(--house-border-radius);
  }

  &::-webkit-progress-value {
    background-color: var(--color-positive);
    border-radius: var(--house-border-radius);
  }

  &::-moz-progress-bar {
    background-color: var(--color-positive);
    border-radius: var(--house-border-radius);
  }
}

/* Turbo Drive navigation progress bar — brand spark instead of the #0076ff
   default. Turbo injects its default stylesheet as the first head child, so
   this app rule (loaded later in <head>) wins without !important. Spark is
   mode-invariant, so one declaration covers light and dark. */
.turbo-progress-bar {
  background-color: var(--spark);
}
