/*
Theme Name: MYS 2026
Theme URI: https://madeyaskinny.com
Author: Made Ya Skinny
Description: Block theme for Made Ya Skinny. Content lives in post_content and is
edited through the block editor, WP-CLI, or the REST API — never in template files.
Version: 1.1
Requires at least: 6.5
Tested up to: 7.1
Requires PHP: 7.4
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: mys-2026
Tags: block-theme, one-column, custom-colors, custom-logo, wide-blocks
*/

/*
 * Everything visual is in theme.json. This file only carries what theme.json
 * cannot express.
 */

/* Compliance disclaimers. Legible, never hidden — LegitScript reviewers look for
   disclosures that a patient can actually read, not grey 10px small print. */
.mys-disclaimer {
	border-left: 4px solid var(--wp--preset--color--brand);
	background: var(--wp--preset--color--blush);
	padding: 0.9rem 1.1rem;
	margin: 1.5rem 0;
	font-size: 0.95rem;
	color: var(--wp--preset--color--ink);
}

.mys-disclaimer em {
	font-style: normal;
}

/* Before/after scan comparison.
   Base state is two stacked figures — that is what shows with JavaScript off, and
   it is a complete comparison on its own. before-after.js adds .mys-ba--live and
   the rules below turn the pair into a wipe. */
.mys-ba {
	display: grid;
	gap: 1rem;
	margin: 1.5rem 0;
}

.mys-ba__pane {
	margin: 0;
}

.mys-ba__pane img {
	display: block;
	width: 100%;
	height: auto;
}

.mys-ba__pane figcaption {
	font-size: 0.9rem;
	padding-top: 0.4rem;
	color: var(--wp--preset--color--ink);
}

.mys-ba--live {
	--mys-ba-split: 50%;
	display: block;
	position: relative;
	overflow: hidden;
}

.mys-ba--live .mys-ba__pane--before {
	position: relative;
}

/* The after image sits on top and is revealed from the left as the handle moves
   right, so dragging toward the after caption uncovers the after scan. */
.mys-ba--live .mys-ba__pane--after {
	position: absolute;
	inset: 0;
	clip-path: inset( 0 calc( 100% - var( --mys-ba-split ) ) 0 0 );
}

.mys-ba--live .mys-ba__pane figcaption {
	position: absolute;
	bottom: 0.75rem;
	padding: 0.3rem 0.7rem;
	background: rgba( 255, 255, 255, 0.92 );
	border-radius: 4px;
	font-size: 0.85rem;
	line-height: 1.3;
}

.mys-ba--live .mys-ba__pane--before figcaption {
	right: 0.75rem;
}

.mys-ba--live .mys-ba__pane--after figcaption {
	left: 0.75rem;
}

/* A pair whose two photographs are different shapes.

   The scan comparisons above are two exports of the same size, so each fills the
   width and the pair lines up on its own. The home page pairs do not: those are
   phone photographs a patient took months apart, and one of them is 290px wide
   against an after of 768px. Stretching the narrow one to fill would distort a
   person, and cropping it to match would take off the head and the feet.

   So the frame is given the shape of the after photograph and each picture is
   fitted to the frame's height instead of its width — the after against the left
   edge, the before against the right, which is where the wipe uncovers each of
   them. That is what the third-party widget this replaced did, and it is why two
   photographs of different shapes read as one comparison.

   --mys-ba-ratio is written per slider by build_home_from_live.py, from the
   after photograph's own pixel dimensions. */
.mys-ba--frame.mys-ba--live {
	aspect-ratio: var( --mys-ba-ratio, 3 / 4 );
	background: #fff;
}

.mys-ba--frame.mys-ba--live .mys-ba__pane img {
	position: absolute;
	top: 0;
	width: auto;
	height: 100%;
	max-width: none;
}

.mys-ba--frame.mys-ba--live .mys-ba__pane--before {
	position: absolute;
	inset: 0;
}

.mys-ba--frame.mys-ba--live .mys-ba__pane--before img {
	right: 0;
	min-width: 100%;
	object-fit: cover;
	object-position: center 20%;
}

.mys-ba--frame.mys-ba--live .mys-ba__pane--after img {
	left: 0;
}

/* The captions come off the picture once the wipe is running.

   They stay in the markup and stay readable to a screen reader, and with
   JavaScript off they are ordinary captions under two stacked figures. What
   they cannot do is sit on the photograph: "After We Made Her Skinny - Lost 37
   lbs!" is wider than the slice the handle leaves it, so at a 60% split it ran
   straight through "Before Made Ya Skinny" and neither one could be read. The
   widget this replaced did not print them on the picture either.

   The pounds are still on the page, in the line under each name, where a
   disclaimer can sit next to them. */
.mys-ba--frame.mys-ba--live .mys-ba__pane figcaption {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip-path: inset( 50% );
	white-space: nowrap;
}

/* The seam. Purely decorative — the range input below is the real control. */
.mys-ba--live::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: var( --mys-ba-split );
	width: 2px;
	background: var( --wp--preset--color--brand );
	pointer-events: none;
}

.mys-ba__range {
	position: absolute;
	left: 0;
	width: 100%;
	top: 50%;
	transform: translateY( -50% );
	margin: 0;
	background: transparent;
	-webkit-appearance: none;
	appearance: none;
}

.mys-ba__range:focus-visible {
	outline: 3px solid var( --wp--preset--color--brand );
	outline-offset: 4px;
}

.mys-ba__range::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	width: 2.5rem;
	height: 2.5rem;
	border-radius: 50%;
	border: 3px solid #fff;
	background: var( --wp--preset--color--brand );
	cursor: ew-resize;
}

.mys-ba__range::-moz-range-thumb {
	width: 2.5rem;
	height: 2.5rem;
	border-radius: 50%;
	border: 3px solid #fff;
	background: var( --wp--preset--color--brand );
	cursor: ew-resize;
}

.mys-ba__range::-webkit-slider-runnable-track {
	background: transparent;
}

.mys-ba__range::-moz-range-track {
	background: transparent;
}

/* Skip link — keyboard users land on content, not on the nav every time.
   The rule that hides it until it is focused lives in mirror.css, because this
   stylesheet is not enqueued on a mirrored page. */
.skip-link:focus {
	position: fixed;
	top: 1rem;
	left: 1rem;
	z-index: 999999;
	padding: 0.75rem 1rem;
	background: var(--wp--preset--color--brand);
	color: #fff;
	border-radius: 4px;
}

/* Verified Google reviews (T-04). One column on a phone, three across on a laptop;
   auto-fit rather than a fixed count so a review that runs long is not squeezed. */
.mys-reviews {
	display: grid;
	gap: 1.25rem;
	grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
	margin-block: 1.5rem;
}

.mys-review {
	padding: 1.25rem 1.5rem;
	border: 1px solid rgba(0, 0, 0, 0.08);
	border-radius: 10px;
	background: #fff;
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
}

.mys-review-stars {
	margin: 0 0 0.5rem;
	color: #f0a202;
	font-size: 1.1rem;
	letter-spacing: 0.1em;
}

.mys-review .wp-block-quote {
	margin: 0;
	padding: 0;
	border: 0;
	font-style: normal;
}

.mys-review cite {
	display: block;
	margin-top: 0.75rem;
	font-size: 0.85rem;
	font-style: normal;
	opacity: 0.7;
}

/* mys:rotator:start */
/* GENERATED by scripts/build_rotator.py — edit content/_rotator_phrases.json, not this.
 * 9 phrases x 2s each = a 18s cycle.
 *
 * This is CSS and not the setInterval the old site used, for three reasons: an
 * inline <script> is the first thing an import or a security plugin strips,
 * JavaScript that has not run yet leaves the sentence visibly hanging at "it's
 * about", and a phrase list belongs in page content an editor can see rather than
 * buried in a script tag.
 */
.mys-rotator {
	position: relative;
	/* The phrases are absolutely positioned, so the container has no natural
	 * height. Without this the block collapses and the page jumps. */
	min-height: 1.4em;
	margin: 0 0 1rem;
	font-size: clamp(1.75rem, 6vw, 3.125rem);
	font-weight: 700;
	line-height: 1.3;
	text-align: center;
}

.mys-rotator-phrase {
	position: absolute;
	inset: 0;
	opacity: 0;
	animation: mys-rotate 18s linear infinite;
}

@keyframes mys-rotate {
	0%      { opacity: 0; transform: translateY(0.3em); }
	2.000%  { opacity: 1; transform: translateY(0); }
	9.000%  { opacity: 1; transform: translateY(0); }
	11.111%  { opacity: 0; transform: translateY(-0.3em); }
	100%    { opacity: 0; transform: translateY(-0.3em); }
}

/* Motion that cannot be stopped is a problem for people who get motion sickness
 * or who cannot read a line before it leaves. For them the first phrase simply
 * stays put, which still finishes the sentence. */
@media (prefers-reduced-motion: reduce) {
	.mys-rotator-phrase { animation: none; }
	.mys-rotator-phrase:first-child { opacity: 1; }
}
/* mys:rotator:end */

/* Cropped Styku before/after figure (.mys-scan).
   Two bodies side by side inside one image, so it wants to be wider than the
   text column and it must not be allowed to grow past its own pixels — an
   upscaled 3D avatar goes soft, and a soft body scan looks like a retouched
   one. The white gutter between the halves is part of the file, so no extra
   padding is needed here. */
.mys-scan {
	margin: 2rem auto;
	max-width: 748px;
}

.mys-scan img {
	display: block;
	width: 100%;
	height: auto;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 6px;
}

.mys-scan figcaption {
	font-size: 0.9rem;
	line-height: 1.5;
	padding-top: 0.6rem;
	color: var(--wp--preset--color--muted);
	text-align: left;
}

/* Standing regulatory disclosures ------------------------------------------
   Injected into post_content by scripts/legitscript_pass.py, not written by
   hand, so the class is the only thing holding them together. They land at the
   end of a mirrored page — after live's own footer, which is where a legal note
   belongs — and without a rule here they render as unstyled full-bleed body
   text against a page that has finished.

   Deliberately quiet: this has to be legible and findable, not persuasive. A
   disclosure styled to be ignored is the thing a reviewer notices. */
.mys-regulatory-notice {
  max-width: 72ch;
  margin: 1.5rem auto 2.5rem;
  padding: 1rem 1.25rem;
  border-top: 1px solid rgba(0, 0, 0, .12);
  color: #4a4a4a;
  background: #fafafa;
  font-size: .8125rem;
  line-height: 1.6;
}

/* The "3 Easy Steps" block, sized so it cannot push the page sideways.
 *
 * These rules already existed in mirror.css, which only loads on a page whose
 * template is page-mirror. The block lives on the home page and the home page
 * is not one, so the photographs rendered at their natural 1140px and 1024px
 * inside a 390px phone. Chrome laid the whole document out at 1440px to fit
 * them and zoomed out, which is why DJ's phone showed a shrunken desktop page
 * that "looked nothing like the original".
 *
 * Duplicated here rather than moved: mirror.css carries other rules that only
 * make sense once live's own stylesheet is loaded, and this block needs its
 * sizing wherever it appears. style.css loads on every page.
 */
.mys-step__photo {
	display: block;
	width: 100%;
	/* height:auto is not decoration. Every one of these images carries a height
	   attribute, which a browser treats as a real height, and aspect-ratio is
	   ignored when both dimensions are already definite. */
	height: auto;
	max-width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	object-position: center;
}

/* Nothing inside the block may be wider than the block. A single oversized
   child is all it takes to widen the document, and the page has no horizontal
   scrollbar to warn anyone — it just silently zooms out. */
.mys-steps-block img,
.mys-steps-block video,
.mys-steps-block iframe {
	max-width: 100%;
}

/* Blog posts had no side padding on a phone.
 *
 * theme.json sets contentSize 760px and no root padding, and the block editor's
 * `is-layout-constrained` only ever applies a max-width. At 1440px that is fine
 * — 760px of text sits in the middle of the screen with air either side. At
 * 390px the constraint does nothing at all, because 390 is already under 760,
 * so the article ran flush to both edges of the phone: the first character of
 * every line touched the left bezel and words broke against the right one.
 *
 * Caught 2026-09-12 by looking at a 390px screenshot of
 * /blog/why-pcos-blocking-semaglutide-tirzepatide-results-insulin-resistance-hormone-panel/
 * rather than by any gate — no audit here measures margins, and the page is
 * "correct" by every other check. It affected all 190 published posts.
 *
 * Scoped to the two blocks that only exist on the post template. The
 * live-mirrored pages carry their own layout and their <main> has none of these
 * classes, so they are untouched; this was verified against /calendar/ (mirror)
 * and /boost-and-enhance/ (theme page) before shipping.
 *
 * 800px rather than the editor's 781px breakpoint: a 768px tablet in portrait
 * has the same problem, and nothing between 760 and 800 gains anything from
 * being flush to the edge.
 */
@media (max-width: 800px) {
	main > .wp-block-post-date,
	main > .wp-block-post-content,
	main > .wp-block-post-title {
		box-sizing: border-box;
		padding-left: 20px;
		padding-right: 20px;
	}
}
