@charset "UTF-8";
/* ============================================================
   DW Design System — SHARED VISUAL PRIMITIVES
   Output target: ../css/primitives.css
   ------------------------------------------------------------
   The canonical, UNSCOPED `.lp-*` primitive vocabulary, shared
   by every dw* surface (theme + plugins, both sites). Each
   primitive composes purely from the token kernel (tokens.css),
   so it follows the active theme automatically.

   These are CLASS primitives — they only style elements that
   opt in by using the class, so hoisting them unscoped is purely
   additive: a site that doesn't use a class is unaffected.

   Depends on: dwtheme-tokens (--ink/--ink-mute/--line/--bg-2/
   --accent/--read/--font-*). Loaded after tokens.

   NOTE: the bare-element heading treatment (h1–h6 → sans) is
   deliberately NOT here — it stays scoped to body.dwlatinprayerdesign
   in the LP overlay to avoid colliding with dushanwegner.com's
   Customizer font system. Class primitives carry no such risk.
   ============================================================ */
/* ── Uppercase micro type — TWO rules, split by ROLE ──────────
   Every uppercase micro label on the site comes from one of these
   two, and the difference between them is whether the reader can
   TAP it. Naming something and offering a choice are different
   jobs, so they get different tracking: a label is read once and
   can afford to be airy; a control is scanned as a set and its
   options must read as words, not as spaced-out letters.

   Two more uppercase-micro roles follow below — .lp-badge and
   .lp-chip — because the gate distinguishes them by SHAPE, not by
   type: outlined = static classifier, filled = interactive filter.
   Those four are the closed set. If a new uppercase micro label is
   none of them, it is not a micro label. */
/* (1) EYEBROW — a quiet label that NAMES something. Not interactive.
   Sans, --fs-micro, 600, 0.16em up-tracking, muted, --lh-snug.
   Section eyebrows, group heads, kickers, rail labels, card meta.

   It states its own line-height because a label is not prose: left to
   inherit, a wrapping eyebrow takes the READING leading (1.7) meant for
   long-form, and the up-tracking that makes one line look deliberate
   makes three look like a paragraph of shouting. --lh-snug is the ramp's
   step for compact multi-line UI, and a single-line eyebrow is unmoved
   by it. */
.lp-eyebrow {
  font-family: var(--font-sans);
  font-size: var(--fs-micro);
  font-weight: 600;
  line-height: var(--lh-snug);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
  /* A label breaks EVENLY or not at all. Greedy wrapping is right for prose,
     where the reader's eye is travelling anyway, and wrong for a short label,
     where it strands the last word on a line of its own — on a phone the Mass
     page's day label read "TODAY'S MASS · THURSDAY, AUGUST 20," / "2026". A
     one-line eyebrow is unaffected. */
  text-wrap: balance;
}

.lp-eyebrow--accent {
  color: var(--rubric);
}

/* For an eyebrow sitting on CHROME rather than on the page — the rail, where
   the muted grey drops below comfortable contrast against the sidebar's own
   surface. A colour modifier, not a second eyebrow: size, weight and tracking
   stay the primitive's. */
.lp-eyebrow--strong {
  color: var(--ink);
}

/* A SECONDARY run inside an eyebrow — the feast date in "TODAY'S ROSARY ·
   14 AUGUST". Not a second label: it shares the label's size, tracking and
   transform, and only steps back in weight and colour, so the pair reads as
   one line with a quieter tail. */
.lp-eyebrow--soft {
  font-weight: var(--fw-medium);
  color: var(--ink-mute);
}

/* (2) OPTION LABEL — the label ON a control the reader chooses from:
   segmented options, toggle buttons, filter chips. Same size and
   colour as the eyebrow (both are UI chrome), but MUCH tighter
   tracking, because these are read as a SET of competing words —
   "EN DE ES", "AUTO LIGHT DARK" — where 0.16em pushes each option
   so wide the group stops reading as a row of choices. 0.07em is
   the gate's own eyebrow tracking and the industry floor for
   legible uppercase UI labels.

   The ACTIVE option is marked by weight + the accent, never by a
   size change — a control whose options change width on selection
   makes the whole row shift under the thumb. */
.lp-optlabel {
  font-family: var(--font-sans);
  font-size: var(--fs-micro);
  font-weight: var(--fw-medium);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.lp-optlabel:hover {
  color: var(--ink);
}

.lp-optlabel.is-active,
.lp-optlabel[aria-pressed=true],
.lp-optlabel[aria-selected=true] {
  font-weight: var(--fw-bold);
  color: var(--rubric);
}

/* (3) BADGE — an OUTLINED static classifier. It labels a thing that
   is already on screen ("Ordinary" / "Proper") and cannot be
   clicked. Outline rather than fill is the whole signal: in the
   gate, filled means interactive.
   (4) CHIP — a FILLED interactive filter ("Blindness", "Courage").
   Tighter again than the badge, because chips appear in dense rows
   and each one is a whole word rather than a one-word classifier.

   These two own TYPE and COLOUR only. Geometry — radius, padding —
   stays with the consumer, because LP squares its chips (round is
   for buttons) while other surfaces may not. */
.lp-badge {
  font-family: var(--font-sans);
  font-size: var(--fs-micro);
  font-weight: var(--fw-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-mute);
  background: transparent;
}

.lp-badge--accent {
  color: var(--rubric);
}

.lp-chip {
  font-family: var(--font-sans);
  font-size: var(--fs-micro);
  font-weight: var(--fw-medium);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--rubric);
  background: var(--rubric-tint);
}

/* ── Brand lockup — NOT an eyebrow ────────────────────────────
   The wordmark and its chip. They look like uppercase micro type
   and are therefore easy to sweep into the eyebrow rule — do not.
   A lockup's letterspacing is HAND-SET as part of drawing the
   mark (the LP wordmark is Jost with DW's own tracking), so it is
   the one place a bespoke value is intent rather than drift.

   What IS shared: the family, the uppercase, and the fact that
   the tracking is declared ONCE per lockup instead of re-derived
   at each callsite. Set --lp-lockup-track to the drawn value. */
.lp-lockup {
  font-family: var(--brand);
  text-transform: uppercase;
  letter-spacing: var(--lp-lockup-track, 0.22em);
}

/* Canonical italic eyebrow — small italic muted line (Latin subtitle). */
.lp-eyebrow-it {
  font-family: var(--font-sans);
  font-style: italic;
  font-size: var(--fs-small);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-mute);
  margin: 0;
}

.lp-eyebrow-it--accent {
  color: var(--rubric);
}

/* ── Disclosure / chevron primitive ───────────────────────────
   A <details> row with a rotating chevron. Token-driven → theme
   for free. (Mirrors the wgnrstyle gate.) */
.lp-chev {
  display: inline-block;
  width: 0.5em;
  height: 0.5em;
  border-right: 2px solid var(--ink-mute);
  border-bottom: 2px solid var(--ink-mute);
  transform: rotate(-45deg); /* points right (closed) */
  transition: transform 0.16s ease;
  flex: none;
  margin-top: 0.45em;
}

@media (prefers-reduced-motion: reduce) {
  .lp-chev {
    transition: none;
  }
}
/* ── THE navigation chevron ───────────────────────────────────
   The site's ONE directional chevron, emitted ONLY by dwtheme_chevron()
   (inc/chevron.php). Every prev/next/up/back/pager/rail-row control
   renders this — no bare ← ↑ → « » glyphs, no second SVG anywhere.
   It is a LINK mark: bare (no box, no border), in the key colour
   (--rubric → oxblood in light, brick at night), inheriting size from
   its context. Direction = a rotation of the one right-pointing path. */
.dw-chev {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 0;
  color: var(--rubric); /* key colour, theme-switched */
  flex: none;
  transition: transform 0.16s ease;
}
.dw-chev svg {
  width: 0.6em; /* scales with the surrounding text */
  height: auto;
  display: block;
}
.dw-chev--right {
  transform: rotate(0deg);
}
.dw-chev { /* base glyph points right */ }
.dw-chev--left {
  transform: rotate(180deg);
}
.dw-chev--up {
  transform: rotate(-90deg);
}
.dw-chev--down {
  transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
  .dw-chev {
    transition: none;
  }
}
/* ── THE video mark, inline placement ─────────────────────────
   "This version carries a video." One mark, emitted ONLY by
   dwtheme_video_mark_html() (inc/article-card.php) — no second play
   glyph anywhere. Two placements: over a list-row thumb (.dw-row-play,
   article-cards.scss) and here, inline in a line of text after the label
   it qualifies — the language links of the dwmultilang siblings widget,
   where it says which language's version comes with a video.
   It is a MARK, not a control: no box of its own, no hover state — it
   stays hoverable only so its title surfaces. Sized in em so it rides
   the type it sits in, and it trails its label: the leading space
   belongs to the mark, so no callsite has to remember it. */
.dw-vid {
  display: inline-block;
  width: 1.15em; /* the glyph is 28×20 → 1.4 : 1 */
  height: 0.82em;
  margin-left: 0.3em;
  vertical-align: -0.08em; /* optically centred on the x-height */
  line-height: 0;
}
.dw-vid svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* ── THE notice page ──────────────────────────────────────────
   A page with nothing to READ, only something to say: the missing
   page, a thank-you, a "this moved". Centred, and that is the
   whole rule — there is no column of prose here for the eye to
   track down a left edge, just a short message that IS the page,
   so it sits where the eye already is. Prose pages keep their
   left edge; this is the exception that has to earn itself, and
   it earns itself by being three lines long.
   It centres text only: any list or grid further down the page
   is a different element and keeps its own alignment.
   Narrower than the reading measure (--read is 720) on purpose:
   centred text has no straight left edge for the eye to return
   to, so every line has to be found again, and long centred
   lines are the way that goes wrong. The measure belongs to the
   NOTICE, not to the status code — a 404 whose body is a card
   index is a different content type and keeps an index width. */
.dw-notice {
  max-width: 550px;
  margin-inline: auto;
  text-align: center;
}

/* ── THE standalone illustration ──────────────────────────────
   A picture that carries the page's OWN message instead of
   illustrating an article beside it — the missing-page drawing is
   the case that named it. Deliberately not the lead image
   (16:9, full measure, hairline border): a picture of this kind
   arrives with its own edge — a frame, a mat, a paper ground — so
   a border around it would only frame the frame. Hence no chrome,
   and no rounding, because a picture is not a control.
   The CAP is the whole rule. At the full reading measure a
   portrait illustration pushes the very sentence it illustrates
   off the screen, so it stops at a width that reads as an aside
   to the text rather than as the page. Centred, because it
   belongs to the column and not to either of its edges. */
.dw-figure {
  margin: 1.25rem auto;
  /* On a phone a portrait illustration at full column width stops being an
     illustration and becomes the page — the reader scrolls past a picture to
     reach the sentence it belongs to. Sixty percent keeps it an aside to the
     words, and it is also what leaves --tilt room for its corners. */
  width: 60%;
  max-width: 360px;
}
@media (min-width: 768px) {
  .dw-figure {
    width: 100%; /* the cap does the limiting once there is room */
  }
}
.dw-figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 0;
}

/* Pinned askew — the picture hangs like something taped to a wall rather than
   printed into the page. Reach for it when the illustration is an OBJECT (a
   drawing, a photo, a card) and the page can afford to be light; never on a
   diagram or anything the reader has to read, where a tilt is just noise.
   A rotation does not change the box the layout reserved, so the corners
   would swing outside it: the block-margin below pays for the height the
   rotated picture gains, and the primitive's own width cap pays for the
   width. Keep both if this angle is ever changed.
   The margin is set by the EYE, not by that geometry — at -7deg the
   corners only need about 21px, but a tilted picture reads as tilted
   only if it has room to lean into; crowd it against the text above and
   it looks like a mistake rather than a choice. */
.dw-figure--tilt {
  transform: rotate(-7deg);
  margin-block: 3.25rem;
}

.lp-disclosure {
  border-bottom: 1px solid var(--rule);
}
.lp-disclosure:first-child {
  border-top: 1px solid var(--rule);
}
.lp-disclosure > summary {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  justify-content: space-between;
  padding: 14px 0;
  cursor: pointer;
  list-style: none;
}
.lp-disclosure > summary::-webkit-details-marker {
  display: none;
}
.lp-disclosure > summary::marker {
  content: "";
}
.lp-disclosure > summary:active {
  opacity: 0.7;
}
.lp-disclosure[open] > summary .lp-chev {
  transform: rotate(45deg);
}
.lp-disclosure { /* points down */ }
.lp-disclosure__body {
  flex: 1 1 auto;
  min-width: 0;
}
.lp-disclosure__panel {
  padding: 0 0 12px;
}
.lp-disclosure {
  /* --bare: the disclosure IS a block that already draws its own rule and its
     own padding — a Mass part, a card, a section that was made openable after
     the fact. It takes the behaviour (the summary row, the chevron, the press
     dip) and none of the chrome, so the container's spacing survives being made
     a <details> and two hairlines never stack. Same idea as
     .dwlp-prayers-head--flush: a variant for "my neighbour already drew it". */
}
.lp-disclosure--bare {
  border-bottom: 0;
}
.lp-disclosure--bare:first-child {
  border-top: 0;
}
.lp-disclosure--bare > summary {
  padding: 0;
}

/* ── Button — the ONE primitive ───────────────────────────────
   Flat, bordered, theme-aware; accent on hover/active. Same family
   as the language-switcher chip. */
.lp-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  font-family: var(--font-sans);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: 0.02em;
  border: 1px solid var(--rule);
  background: var(--bg-2);
  /* Foreground rides a custom property so ONE rule can restore the button's own
     colour wherever a stronger ancestor rule (e.g. `.entry-content a`) would
     otherwise repaint it — see the content-link guard in the LP variants. Every
     state/variant sets --lp-btn-fg, never `color` directly. */
  --lp-btn-fg: var(--ink);
  color: var(--lp-btn-fg);
  cursor: pointer;
  text-decoration: none;
  border-radius: 0;
  line-height: 1.2;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.lp-btn:hover, .lp-btn:focus {
  --lp-btn-fg: var(--rubric);
  border-color: var(--rubric);
  text-decoration: none;
}
.lp-btn {
  /* Active/selected — solid accent (same as the switcher active chip). */
}
.lp-btn.is-active, .lp-btn[aria-pressed=true] {
  background: var(--rubric);
  border-color: var(--rubric);
  --lp-btn-fg: #fff;
}
.lp-btn {
  /* Large — the ONE page-level call to action: a page whose whole purpose is a
     single act (join the beta group, get the app) gets one unmissable target.
     Scales the one button up (padding + the body type step) rather than
     inventing a second button. Goes full-width on a phone, where the thumb
     target should span the measure; stays inline from --bp-s up. Use at most
     once per page — a second --lg on the same view means neither is primary. */
}
.lp-btn--lg {
  padding: 16px 28px;
  font-size: var(--fs-body);
  font-weight: 600;
  display: flex;
  width: 100%;
  justify-content: center;
}
@media (min-width: 520px) {
  .lp-btn--lg {
    display: inline-flex;
    width: auto;
  }
}

/* ── Card ──────────────────────────────────────────────────── */
.lp-card {
  background: var(--bg);
  border: 1px solid var(--rule);
  padding: 20px;
  transition: border-color 0.15s;
}

.lp-card--hover:hover {
  border-color: var(--ink-mute);
}

/* ── Language switcher — the ONE switcher look ─────────────────
   Bordered-chip bar; theme-aware accent active state. */
.lp-lang-switcher {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.lp-lang-switcher a,
.lp-lang-switcher button {
  font: inherit;
  font-size: var(--fs-small);
  line-height: 1.2;
  padding: 4px 10px;
  border: 1px solid var(--rule);
  border-radius: 0;
  background: var(--bg-2);
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.lp-lang-switcher a:hover, .lp-lang-switcher a:focus,
.lp-lang-switcher button:hover,
.lp-lang-switcher button:focus {
  border-color: var(--rubric);
  color: var(--rubric);
  text-decoration: none;
}
.lp-lang-switcher a.active,
.lp-lang-switcher button.active {
  background: var(--rubric);
  color: #fff;
  border-color: var(--rubric);
}
.lp-lang-switcher .active {
  background: var(--rubric);
  color: #fff;
  border-color: var(--rubric);
}
