/* atrium's furniture for post content: everything the editor can place
   follows the template's radius and grammar. Loaded after the site
   stylesheet, so these win ties with the typography defaults. */

/* Widget internals are excluded: each velocity widget carries its own
   radius keyed to the tokens, and clipping a third-party iframe (a tweet,
   a Spotify card) cuts the corners off the furniture it draws itself. */
.prose :where(img, video, iframe):not(.velocity-widget *) {
    border-radius: var(--radius-selector);
}

/* Code blocks separately, with the id: the Prism theme stylesheet loads
   after this file and carries a higher-specificity radius of its own. */
#post-body pre {
    border-radius: var(--radius-selector);
}

/* Tables. Typography's default is collapsed borders, and border-radius
   cannot clip a collapsed border grid: the corners square off exactly as the
   review screenshot showed. Separate borders, spacing zero, one outer border
   on the table itself, and the radius clips cleanly. */
.prose table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    border: 1px solid var(--color-base-300);
    border-radius: var(--radius-selector);
    overflow: hidden;
}
.prose table :where(th, td) {
    border: 0;
    border-bottom: 1px solid var(--color-base-300);
}
.prose table tr:last-child :where(th, td) {
    border-bottom: 0;
}
/* The header keeps the platform's full-primary treatment: brand ground,
   contrast text, the same table language as every other template. Tried at
   the 9% tint first, which collapsed into the 5% zebra and stopped reading
   as a header at all. The one-loud-object rule governs panels and CTAs, not
   a header strip inside content furniture. atrium contributes structure
   only: separate borders and clipped corners. */

/* Blockquotes. atrium separates by air and by edges, never by a rule, and the
   object it repeats most is a tinted panel. So a quote is a panel: the same
   9 percent primary the audio player's read-along and the tinted surfaces use,
   the selector radius, no bar at all, and the quote itself set in the display
   face at a size that makes it a pull quote rather than indented body text.
   This is what views/page.html and the approved atrium-post.html mockup have
   drawn all along.

   It replaces BQ-B (28 Aug 2026), which kept the platform's primary bar and
   softened it into an inset pill so it would not taper into crescents around
   the rounded corners. BQ-B was reached while atrium still DRESSED the shared
   furniture and its comment says so: "the platform's colour semantics stand,
   atrium contributes structure only". That rule was replaced the day atrium
   took over its last five borrowed surfaces, and a bar is the one thing
   atrium's own description rules out.

   Written against .prose rather than #post-body so a standing page's quotes
   match a post's. Unlayered and loaded after the site stylesheet, so it needs
   no !important: the platform's own rule left @layer components on 29 Aug and
   dropped the important flags that used to make this unwinnable. */
.prose blockquote {
    border-inline-start-width: 0;
    border-radius: var(--radius-selector);
    /* base-200 is the fallback for Safari 16, which has no color-mix: a
       neutral panel rather than no panel. */
    background: var(--color-base-200);
    background: color-mix(in srgb, var(--color-primary) 9%, transparent);
    padding: 1.5rem;
}
@media (min-width: 768px) {
    .prose blockquote {
        padding: 1.75rem;
    }
}
.prose blockquote p {
    font-family: var(--font-post-headings);
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.375;
    letter-spacing: -0.015em;
}
.prose blockquote > :first-child {
    margin-top: 0;
}
.prose blockquote > :last-child {
    margin-bottom: 0;
}

/* Galleries. The platform keeps the tiles themselves flush (radius 0,
   deliberate, in _gallery.scss), so the template contributes the same
   structure it gives tables: clipped outer corners. The clip sits on the
   first and last rows, not the container, because the caption below the
   images is part of the container and pushes its bottom edge past them.
   Rows are the only divs in the gallery; the captions are figcaptions. */
.prose .velocity-gallery .velocity-gallery-row {
    overflow: hidden;
}
.prose .velocity-gallery .velocity-gallery-row:first-of-type {
    border-top-left-radius: var(--radius-selector);
    border-top-right-radius: var(--radius-selector);
}
.prose .velocity-gallery .velocity-gallery-row:last-of-type {
    border-bottom-left-radius: var(--radius-selector);
    border-bottom-right-radius: var(--radius-selector);
}

/* The lifted opening image: the view renders it as the hero row, so the
   in-content copy hides. Its loading=lazy keeps the hidden copy from ever
   fetching, and the hero itself is the same URL the LCP preload warms. */
.atrium-lead-lifted > div[class*="se-image-container"]:first-child,
.atrium-lead-lifted > figure:first-child {
    display: none;
}

/* The contents rail's section indicator: the active link brightens and
   carries a short inset pill. It is the one rule-like mark atrium draws, and
   it earns the exception by being a position indicator rather than
   decoration: it says which section you are in, which nothing else on the
   page says. The classes are set by
   the platform scrollspy (toc.js): .active on the section being read,
   .parent-active on a parent whose subsection is active. The rail's start
   padding is the gutter the pill sits in. */
#toc-container a {
    display: inline-block;
    position: relative;
}
#toc-container a.active {
    color: var(--color-primary);
    font-weight: 500;
}
#toc-container a.active::before {
    content: "";
    position: absolute;
    left: -0.75rem;
    top: 0.2em;
    bottom: 0.2em;
    width: 3px;
    border-radius: var(--radius-selector);
    background: var(--color-primary);
}
#toc-container a.parent-active {
    color: var(--color-base-content);
    font-weight: 500;
}

/* The audio player's moving parts. Everything else about it is Tailwind in
   views/_tts.html; these three need pseudo-elements, which utilities cannot
   reach. Lifted from the shared component's inline <style> when atrium took
   the player over, so nothing here is new behaviour.

   The disc stays 36px to look at, but its tap target fills the pill's full
   48px height: a thumb-sized target for the listeners this feature exists for.
   z-index so the overlap beats the track's tap wrapper, which it only reaches
   into the padding of, never the visible bar. */
#tts-toggle {
    position: relative;
    z-index: 1;
}

#tts-toggle::after {
    content: '';
    position: absolute;
    inset: -6px;
}

/* The track: a real 4px bar. A progress element rather than a div, because
   cached copies of tts-player.js still drive one. */
#tts-progress.tts-track {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 4px;
    border: 0;
    border-radius: 9999px;
    overflow: hidden;
    background: color-mix(in srgb, currentColor 14%, transparent);
}

#tts-progress.tts-track::-webkit-progress-bar {
    background: transparent;
}

#tts-progress.tts-track::-webkit-progress-value {
    background: var(--color-primary);
    border-radius: 9999px;
}

#tts-progress.tts-track::-moz-progress-bar {
    background: var(--color-primary);
    border-radius: 9999px;
}

/* The paragraph being read. The same 9 percent primary the tinted panels and
   the search highlight use, so following along needs no new colour. */
.tts-current {
    background: color-mix(in srgb, var(--color-primary) 9%, transparent);
    border-radius: var(--radius-field);
    transition: background 0.3s;
}

/* The selected speed. tts-player.js sets this class name; the look is ours. */
#tts-speed-menu .menu-active {
    background: color-mix(in srgb, var(--color-primary) 15%, transparent);
    font-weight: 600;
}

/* Anchor jumps from the contents links land clear of the fixed navbar. */
#post-body :where(h2, h3, h4) {
    scroll-margin-top: 6rem;
}


