/* Shared, brand-neutral strip above every example page. Uses system fonts on purpose — it belongs to no example's brand. */
/* Example pages load only their own stylesheet plus this one, so they never inherited
   readyastro.css's reset and kept the UA default body margin — an 8px white frame around
   every example page on every device. Found on a phone by Andy, 2026-09-14. */
body.ex { margin: 0; }
/* Scroll lock while an example's phone menu is open (2026-09-24): src/scripts/menu.js toggles the class, as on the real
   site, where readyastro.css carries the same rule. Here because this is the one stylesheet every example page loads. */
html.is-menu-open, html.is-menu-open body { overflow: hidden; touch-action: none; }
/* system-ui first is intended (Andy's decision, 2026-09-22): the sample bar is ReadyAstro speaking, not the sample
   design, and looking like the visitor's own OS is what separates the two. Not a missing web font — do not "fix" it. */
.sample-bar { position: relative; z-index: 60; display: flex; align-items: center; gap: 16px; min-height: 36px; padding: 6px 16px; background: #111114; color: #EDEAE6; font: 500 12px/1.35 system-ui, -apple-system, "Segoe UI", sans-serif; letter-spacing: 0; }
.sample-bar a { color: #FFFFFF; text-decoration: none; }
.sample-bar a:hover { text-decoration: underline; text-underline-offset: 2px; }
.sample-bar__back { white-space: nowrap; display: inline-flex; align-items: center; min-height: 24px; }
/* The skip link (2026-09-28): parked above the page until it takes focus, then a pill over the bar's left end, as .skip is
   on the real site. The bar's own ground and white, and the white ring .sample-bar :focus-visible gives it below. */
.sample-skip { position: absolute; left: 16px; top: -100px; z-index: 1; padding: 5px 14px; border-radius: 999px; background: #111114; font: 600 14px/1.35 system-ui, -apple-system, "Segoe UI", sans-serif; white-space: nowrap; }
.sample-skip:focus { top: 3px; }
.sample-lang__item { display: inline-flex; align-items: center; justify-content: center; min-width: 24px; min-height: 24px; }
.sample-bar__note { margin: 0 auto; color: #C9C4BE; text-align: center; }
.sample-lang { display: inline-flex; gap: 6px; align-items: center; }
.sample-lang__item.is-current { color: #FFFFFF; font-weight: 700; }
.sample-lang a.sample-lang__item { color: #C9C4BE; }
.sample-lang__sep { color: #9A958F; }
.sample-bar :focus-visible { outline: 2px solid #FFFFFF; outline-offset: 2px; }
.demo-note { font-size: 13px; line-height: 1.4; margin-top: 10px; } /* no opacity: it silently lowers contrast */
/* Inline field errors on the demo forms (added 2026-09-21). Deliberately colour-free: each example has its own
   palette, and a red would be a new unchecked pair on seven backgrounds — and colour alone would fail 1.4.1 anyway.
   The marker is weight + a rule, and currentColor inherits a contrast already measured. */
/* display:block because it is a <span> living inside a <label> field wrapper; margin 0 because every wrapper
   is a grid and its own gap spaces the message from the input. */
.demo-err { display: block; margin: 0; padding-left: 10px; border-left: 3px solid currentColor; font-weight: 700; font-size: 14px; line-height: 1.4; }
.demo-err[hidden] { display: none; }
.is-validated :invalid { outline: 2px solid currentColor; outline-offset: 1px; }
/* Scoped to .ex so it OUT-RANKS the page's own button rule. At (0,1,0) this lost to every example's .cp-btn,
   .pw-btn, .vm-btn, .cc-btn — same specificity, and the brand stylesheet loads after this one, so the later rule
   won and an aria-disabled submit still showed cursor: pointer on all four example pages with forms. Measured
   2026-09-22, not read off the source. Third instance of this shape here, after `.pw a` out-ranking .pw-btn--orange
   (rule 14) and `.ra-strip p` out-ranking .ra-strip__by — except those two were resets that needed LESS weight,
   and this is a state that needs MORE. .cp-cal__day:disabled already sets the same cursor at (0,2,0). */
.ex [aria-disabled="true"] { cursor: not-allowed; }
/* system-ui first is intended (2026-09-22): the toast is ReadyAstro speaking, not the sample — it should look like the OS. */
.demo-toast { position: fixed; left: 50%; bottom: 24px; z-index: 70; max-width: min(92vw, 520px); transform: translate(-50%, 16px); opacity: 0; padding: 14px 18px; border-radius: 12px; background: #111114; color: #FFFFFF; font: 500 14px/1.45 system-ui, -apple-system, "Segoe UI", sans-serif; transition: opacity .3s ease, transform .3s ease; pointer-events: none; }
.demo-toast.is-on { opacity: 1; transform: translate(-50%, 0); }
.ph { position: relative; margin: 0; overflow: hidden; background: repeating-linear-gradient(-45deg, rgba(0,0,0,.05) 0 10px, rgba(0,0,0,0) 10px 20px), var(--ph-bg, #D9D6D0); display: grid; place-items: end start; }
.ph[data-ratio="16/9"] { aspect-ratio: 16 / 9; } .ph[data-ratio="3/2"] { aspect-ratio: 3 / 2; } .ph[data-ratio="4/3"] { aspect-ratio: 4 / 3; } .ph[data-ratio="4/5"] { aspect-ratio: 4 / 5; } .ph[data-ratio="1/1"] { aspect-ratio: 1 / 1; }
/* system-ui first is intended (2026-09-22): a placeholder label is ReadyAstro speaking, not the sample — it should look like the OS. */
/* Element-qualified on purpose (2026-09-24): div.ph > span.ph__label is (0,2,2), the weight figure.ph > figcaption.ph__label had,
   so this chrome colour out-ranks a brand rule written the usual way, `.xx .ph__label` (0,2,0). A bare .ph > .ph__label
   (0,2,0) would tie one and lose on load order (the brand sheet loads after this one), silently retinting the label on
   every placeholder of that brand. The label is ReadyAstro speaking; a brand tints its placeholder through --ph-bg only.
   The .pw/.cc/.mg .ph__label tints were three such rules: they never applied (removing them moved no pixel), and under
   the bare selector all three retinted their labels. They were removed 2026-09-24; the weight stays for the next one. */
div.ph > span.ph__label { font-style: normal; text-align: left; margin: 12px; padding: 6px 10px; border-radius: 6px; background: rgba(17,17,20,.78); color: #FFFFFF; font: 500 12px/1.35 system-ui, -apple-system, "Segoe UI", sans-serif; max-width: calc(100% - 24px); }
div.ph .ph__tag { font-weight: 700; }
@media (max-width: 640px) { .sample-bar { flex-wrap: wrap; justify-content: space-between; } .sample-bar__note { order: 3; flex-basis: 100%; text-align: left; margin: 0; } }

/* ReadyAstro's own strip, above the honesty label on every example page (added 2026-09-21).
   Neutral chrome like the sample bar — it belongs to ReadyAstro, not to the fictional business above it —
   except the CTA, which is the one place on an example page the brand asserts itself. system-ui first is intended
   here too (2026-09-22); what must not vary with the visitor's font is the layout, below.
   Colours are set per component on purpose: a blanket `.ra-strip a { color: #FFF }` would out-specify the
   CTA and put white on coral at 3.19:1, which is the exact bug rule 1 ("coral is a fill, never text") exists for. */
/* Row layout is decided by the viewport, never by the rendered width of the text (Andy, 2026-09-22). With flex-wrap
   the font decided: at 390px the CTA joined the "Next" row in Segoe UI (Windows) and took its own row in Linux's
   wider system-ui — ~30px apart on the page's one conversion CTA — and at 561–700px the whole strip went one row or
   two the same way. Grid areas pin each item to its row; text that does not fit wraps inside its own cell rather than
   moving a neighbour. ≤560px: by / next / CTA, the CTA a full-width row of its own; wider: one row, CTA at the end.
   Shrinkable tracks are minmax(0, …) — a bare 1fr keeps a min-content floor. To re-verify, force a much wider and a
   much narrower font-family on .ra-strip through CSSOM (the CSP refuses an injected <style>): the rows must not move. */
.ra-strip { display: grid; grid-template-columns: minmax(0, max-content) minmax(0, max-content) minmax(max-content, 1fr); grid-template-areas: "by next cta"; align-items: center; gap: 14px 24px; padding: 20px 16px; background: #1A1A1F; border-top: 1px solid #2E2E34; font: 500 15px/1.4 system-ui, -apple-system, "Segoe UI", sans-serif; color: #EDEAE6; }
/* Zero-specificity reset (rule 14). As `.ra-strip p` (0,1,1) it out-specified `.ra-strip__by` (0,1,0) and silently
   discarded a margin set there (2026-09-21) — which is why the CTA used to carry an auto margin instead. */
:where(.ra-strip) :where(p) { margin: 0; }
.ra-strip__by { grid-area: by; }
.ra-strip__next { grid-area: next; justify-self: start; }
.ra-strip__cta { grid-area: cta; justify-self: end; }
.ra-strip__by a, .ra-strip__next { color: #FFFFFF; }
.ra-strip__by a { text-decoration: underline; text-underline-offset: 2px; }
.ra-strip__next { display: inline-flex; align-items: center; gap: 6px; min-height: 24px; text-decoration: none; }
.ra-strip__next:hover { text-decoration: underline; text-underline-offset: 3px; }
.ra-strip__cta { display: inline-flex; align-items: center; justify-content: center; min-height: 40px; padding: 8px 20px; border-radius: 99px; background: #F05B35; color: #2A1F2D; font-weight: 600; text-decoration: none; transition: transform .2s ease-out, box-shadow .2s ease-out; }
.ra-strip__cta:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0, 0, 0, .45); } /* fill never changes: ink on coral is 4.69:1 at rest and on hover */
.ra-strip :focus-visible { outline: 2px solid #FFFFFF; outline-offset: 2px; }
@media (max-width: 560px) { .ra-strip { grid-template-columns: minmax(0, 1fr); grid-template-areas: "by" "next" "cta"; gap: 12px 16px; } .ra-strip__cta { justify-self: stretch; } }
@media (prefers-reduced-motion: reduce) { .ra-strip__cta:hover { transform: none; } }

/* honesty label — bottom of every example page. system-ui first is intended (2026-09-22): the label is ReadyAstro
   speaking, not the sample design, and looking like the visitor's OS is what separates the two. */
.honesty { background: #111114; color: #EDEAE6; font: 500 13px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif; padding: 14px 16px; text-align: center; }
.honesty p { margin: 0; }
.honesty a { color: #FFFFFF; font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
.honesty :focus-visible { outline: 2px solid #FFFFFF; outline-offset: 2px; }
/* Real photos: width/height attributes reserve space, CSS must let them scale. Zero specificity so page rules
   (object-fit: cover heroes, the before/after layers) still win. Found 2026-09-11: without this, photos stretched. */
:where(.ex) :where(img) { display: block; width: 100%; height: auto; }
