/*
 * scbt-article.css — the single article page: the article's category set above
 * a full-bleed picture whose top and bottom edges are arcs bitten inwards, then
 * a brand-coloured title and the text. Part of plg_system_scbtbrand. Loaded only
 * when the "Article hero" param is on; switch that off and every article page
 * returns to the template's stock centred, rounded, container-width picture.
 *
 * ---------------------------------------------------------------------------
 * WHAT IT STYLES, AND WHY NO TEMPLATE FILE WAS TOUCHED
 *
 * html/com_content/article/default.php:65 renders the full image BEFORE the
 * .article-header that holds the title, so picture → title → text is already
 * the order Joomla emits. Only the category is in the wrong place, and the fix
 * for that is `order`, not an override. Confirmed against real rendered HTML in
 * cache/com_content/, which is:
 *
 *   <div class="article-details">
 *     <meta itemprop="inLanguage" content="mk-MK">
 *     <div class="article-full-image float-none"><img src="…"></div>
 *     <div class="article-header"><h1 itemprop="headline">…</h1></div>
 *     <div class="article-can-edit d-flex flex-wrap justify-content-between"></div>
 *     …the plugin's own eyebrow lands here (default.php:104)…
 *     <div class="article-ratings-social-share …">…</div>
 *     <div itemprop="articleBody">…</div>
 *
 * The eyebrow is emitted by this plugin's onContentBeforeDisplay(), whose output
 * default.php:104 echoes as a direct child of .article-details — which is what
 * makes it an `order`-able flex item alongside the picture.
 *
 * SCOPE — TWO LAYERS, AND THE OUTER ONE IS PHP
 *
 * This sheet is NOT loaded on every page and then narrowed by a selector, the
 * way the other four are. The plugin's articleHeroActive() decides per request
 * whether to enqueue it at all: it must be the single article view, and the
 * article must be in one of the categories chosen in the params. So on a
 * Настани article, when only Соопштенија is chosen, none of these rules are on
 * the page in the first place. **A selector cannot express that** — the body
 * class carries the view but never the category.
 *
 * Every rule is still prefixed .view-article, the body class Helix builds from
 * the request's view (plugins/system/helixultimate/core/helixultimate.php:49).
 * That is now belt and braces rather than the mechanism, and it costs nothing.
 *
 * If the design does not appear, look in view-source for the <link> before
 * looking at the CSS: an absent stylesheet means the category filter did not
 * match, and a present one that does nothing means the body class is missing.
 * ---------------------------------------------------------------------------
 */


/* ---------------------------------------------------------------------------
 * 0. The page-title row above the article
 *
 * The template style's layout opens with an unnamed, full-width row holding one
 * column, the `title` position. Helix names an unnamed row after its index —
 * `'sp-section-' . ($key + 1)` in helixultimate.php's get_recursive_layout() —
 * so it renders as:
 *
 *   <section id="sp-section-1" class="…">
 *     <div class="row">
 *       <div id="sp-title" class="col-lg-12 …">      ← modules.php names this
 *         <div class="sp-column">…the title modules…
 *
 * The hero prints the category itself, so that row is a second heading over the
 * same page. Both hooks are used: the section is what the design wants gone, and
 * `#sp-title` is the position-named twin that survives the row being moved or
 * renamed — at which point the index-based id would silently stop matching.
 *
 * Note that the section only exists at all when something is published to
 * `title`: get_current_row() drops a module column with no modules, and
 * generate.php emits nothing for a row left with no columns.
 *
 * `block` is what both elements are anyway, so switching this off restores the
 * stock page exactly. A display keyword and not a boolean, for the reason given
 * against --scbt-blog-ends: CSS cannot switch a rule off from a custom property.
 * ------------------------------------------------------------------------- */

.view-article #sp-section-1,
.view-article #sp-title {
	display: var(--scbt-article-section, none);
}


/* ---------------------------------------------------------------------------
 * 1. Re-ordering, which is the only structural change on the page
 *
 * .article-details becomes a column flex container purely so `order` works on
 * its children. Everything not named below keeps order 0 and therefore keeps
 * its source order — title, then the can-edit strip, then the info block, the
 * social share row and the body.
 *
 * <meta itemprop="inLanguage"> is the first child and stays display:none from
 * the UA stylesheet, so it never becomes a flex item.
 *
 * min-width on the body is not cosmetic: a flex item's automatic minimum size
 * is its content, so one wide table or an SP Page Builder row with a fixed
 * width would push .article-details wider than its column instead of scrolling
 * inside it.
 * ------------------------------------------------------------------------- */

.view-article .article-details {
	display: flex;
	flex-direction: column;
}

.view-article .article-details > .scbt-article-eyebrow {
	order: -2;
}

.view-article .article-details > .article-full-image {
	order: -1;
}

.view-article .article-details > [itemprop="articleBody"] {
	min-width: 0;
}


/* ---------------------------------------------------------------------------
 * 2. The category, above the picture
 *
 * position:relative and a z-index because the label is allowed to sit INSIDE
 * the arc below it: the picture is pulled up by --scbt-article-label-overlap,
 * and without a stacking context of its own the label would be painted under
 * the picture where they meet.
 *
 * The colour falls through two levels — the administrator's own choice first,
 * then the plugin's brand colour, then a literal. Leave "Category colour" empty
 * in the params and this label follows any future rebrand on its own, exactly as
 * the blog titles and mod_scbt_news do.
 * ------------------------------------------------------------------------- */

.view-article .article-details > .scbt-article-eyebrow {
	position: relative;
	z-index: 1;
	margin: 0;
	text-align: var(--scbt-article-label-align, center);
	font-size: var(--scbt-article-label-size, 2.75rem);
	font-weight: 700;
	line-height: 1.1;
	text-transform: uppercase;
	color: var(--scbt-article-label-color, var(--scbt-brand, #E6007E));
}

.view-article .article-details > .scbt-article-eyebrow a {
	color: inherit;
}

.view-article .article-details > .scbt-article-eyebrow a:hover,
.view-article .article-details > .scbt-article-eyebrow a:focus,
.view-article .article-details > .scbt-article-eyebrow a:active {
	color: var(--scbt-brand-hover, #B3005F);
}

/*
 * Below 576px the container is the full screen less 30px, and a 2.75rem
 * uppercase label of a dozen Cyrillic capitals does not fit inside a 320px
 * phone. 0.7 brings СООПШТЕНИЈА back under that width at the default size, and
 * scales with the param rather than replacing it, so a smaller setting is not
 * silently overridden.
 */
@media (max-width: 575.98px) {
	.view-article .article-details > .scbt-article-eyebrow {
		font-size: calc(var(--scbt-article-label-size, 2.75rem) * 0.7);
	}
}

/*
 * The plugin emits the category itself, so Joomla's own copy of it — the
 * .category-name span inside the info block, shown when the menu item has
 * Show Category on — would appear a second time under the title.
 *
 * The property carries a display keyword rather than a boolean because CSS has
 * no way to switch a rule off from a custom property; the plugin sends `none`
 * while it is emitting its own label and `inline` when it is not. Same
 * mechanism as --scbt-blog-ends.
 *
 * The second selector is the separator: template.css:380-385 puts a "/" in a
 * ::before on every span that follows another one, and that ::before does not
 * care that the span before it is hidden — so without this the info block
 * would open with a stray slash.
 */
.view-article .article-details .article-info .category-name,
.view-article .article-details .article-info .category-name + span::before {
	display: var(--scbt-article-catdup, none);
}


/* ---------------------------------------------------------------------------
 * 3. The picture, edge to edge
 *
 * .article-details sits inside
 *   section#sp-main-body > .container > .container-inner > .row >
 *   main#sp-component.col-lg-12 > .sp-column
 * and nothing in that chain sets overflow, a transform or a filter, so an
 * element in it can be widened past its column. `margin-left: 50% - 50vw` puts
 * the left edge at the viewport edge because the container is centred: the
 * element's own centre is the viewport's centre, and half a viewport back from
 * there is zero.
 *
 * 100vw includes the scrollbar, so the picture overhangs the page by its width.
 * .body-innerwrapper already carries overflow-x:hidden (template.css:179-181),
 * which is what swallows the overhang and is why this does not add a sideways
 * scrollbar. Do NOT add overflow-x:hidden anywhere higher up to "make sure" —
 * it forces overflow-y to a non-visible value too and would slice the header's
 * dropdown panels off (§8.15).
 *
 * THE ONE THING THAT CAN BREAK THIS: the picture is as wide as the viewport
 * because #sp-component is col-lg-12, which it is only because the Main Body
 * row's `left` and `right` positions are empty and helixultimate.php:400-402
 * folds their six columns into the component. Publish a module to either and
 * the component becomes col-lg-9 or col-lg-6, the container stops being centred
 * on the picture, and it bleeds off to one side. Turn "Full-width picture" off
 * if a sidebar is ever added.
 *
 * float is !important because the div carries Bootstrap's .float-none /
 * .float-left / .float-right, which are themselves !important — the same single
 * exception scbt-blog.css makes, and for the same reason.
 * ------------------------------------------------------------------------- */

.view-article .article-details .article-full-image {
	position: relative;
	float: none !important;
	box-sizing: border-box;
	width: var(--scbt-article-width, 100vw);
	max-width: var(--scbt-article-width, 100vw);
	margin-left: var(--scbt-article-pull, calc(50% - 50vw));
	margin-right: var(--scbt-article-pull, calc(50% - 50vw));

	/* Pulls the picture up under the label so the label sits inside the arc,
	   the way the reference design has it. The param is a positive length and
	   the sign is applied here, so no negative value has to survive validation
	   in PHP. */
	margin-top: calc(-1 * var(--scbt-article-label-overlap, 0px));
	margin-bottom: var(--scbt-article-gap, 2.5rem);

	padding: 0;

	/* Holds the box open at one shape before the picture has loaded, so the
	   page does not jump as it arrives. padding-top and not aspect-ratio, for
	   the reason written down for mod_scbt_news and scbt-blog.css: the
	   percentage resolves against the element's own width, whereas
	   aspect-ratio on an unpositioned <img> hands the height back to
	   template.css:56-60's `img { height: auto }` and the reservation is lost.

	   "Original shape" sends 0px here and switches the image back into normal
	   flow with the two properties below, so the picture keeps its own
	   proportions and nothing is cropped. */
	padding-top: var(--scbt-article-ratio, 50%);

	text-align: left;
	border: 0;
	border-radius: 0;

	/*
	 * THE TWO ARCS.
	 *
	 * Measured off the reference design: the top edge of the picture sits at
	 * y=208 at both outer edges and y=343 at the centre, and the bottom edge at
	 * y=1181 and y=1046 — the same shape twice, sagging 135px across 1920px,
	 * or 7.03% of the width.
	 *
	 * That shape is a PARABOLA, not an ellipse. At the quarter point the
	 * measured pixel is 309; a parabola predicts 309.3 and an ellipse 325. So a
	 * white overlay with border-radius:50% — the usual way to fake a concave
	 * edge — comes out visibly flatter through the middle. A quadratic Bézier
	 * IS a parabola, so each arc is one `Q` command: from (0,0) to (100,0) with
	 * the control point at (50,200) passes through (50,100), which is the full
	 * depth at the centre and zero at both ends.
	 *
	 * Three mask layers rather than one image: a strip at the top and another at
	 * the bottom, each exactly the arc depth tall, with a solid fill between
	 * them. Sizing the strips in px (or vw) instead of stretching one image over
	 * the whole box is what keeps the sag equal to the setting at every picture
	 * height. preserveAspectRatio="none" lets each strip stretch to the full
	 * width; a stretched parabola is still a parabola.
	 *
	 * The shapes are painted WHITE, not black. A mask image referenced as an
	 * image uses its alpha channel (mask-mode: match-source resolves to alpha
	 * for anything that is not an SVG <mask> element), so black would work — but
	 * white is also correct under luminance masking, and costs nothing.
	 *
	 * max(0px, …) on the middle layer guards the case where the arc depth is
	 * more than half the picture's height: a negative mask-size would make the
	 * whole declaration invalid and drop the mask entirely, rather than
	 * degrading.
	 *
	 * Where masks are unsupported the picture simply renders as a rectangle —
	 * full-bleed and correctly proportioned, just without the arcs.
	 *
	 * These three are declared here and not emitted by the plugin because they
	 * are geometry, not a setting. Only the depth is a param.
	 */
	--scbt-article-arc-top: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpath d='M0 0 Q50 200 100 0 L100 100 L0 100 Z' fill='%23ffffff'/%3E%3C/svg%3E");
	--scbt-article-arc-bottom: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpath d='M0 100 Q50 -100 100 100 L100 0 L0 0 Z' fill='%23ffffff'/%3E%3C/svg%3E");
	--scbt-article-arc-fill: linear-gradient(#ffffff, #ffffff);

	-webkit-mask-image: var(--scbt-article-arc-top), var(--scbt-article-arc-fill), var(--scbt-article-arc-bottom);
	        mask-image: var(--scbt-article-arc-top), var(--scbt-article-arc-fill), var(--scbt-article-arc-bottom);

	/*
	 * Declared twice on purpose, plain calc() first and the max()-guarded form
	 * second. If a browser rejects max() here the guarded line is dropped and
	 * the plain one still stands — whereas dropping mask-size outright would
	 * leave the layers at `auto`, which for a sizeless SVG means 100% 100%: all
	 * three stretched over the whole picture, and arcs half its height deep.
	 * That is a far worse failure than the negative-size case the guard is for.
	 */
	-webkit-mask-size:
		100% var(--scbt-article-curve, 7vw),
		100% calc(100% - 2 * var(--scbt-article-curve, 7vw)),
		100% var(--scbt-article-curve, 7vw);
	-webkit-mask-size:
		100% var(--scbt-article-curve, 7vw),
		100% max(0px, calc(100% - 2 * var(--scbt-article-curve, 7vw))),
		100% var(--scbt-article-curve, 7vw);
	        mask-size:
		100% var(--scbt-article-curve, 7vw),
		100% calc(100% - 2 * var(--scbt-article-curve, 7vw)),
		100% var(--scbt-article-curve, 7vw);
	        mask-size:
		100% var(--scbt-article-curve, 7vw),
		100% max(0px, calc(100% - 2 * var(--scbt-article-curve, 7vw))),
		100% var(--scbt-article-curve, 7vw);

	-webkit-mask-position: top center, center center, bottom center;
	        mask-position: top center, center center, bottom center;

	-webkit-mask-repeat: no-repeat;
	        mask-repeat: no-repeat;
}

/*
 * With a shape chosen the image is absolutely positioned and object-fit decides
 * what happens to the parts that do not fit; with "Original shape" the two
 * properties below come back as `relative` and `auto`, the image returns to
 * normal flow, and object-fit becomes inert.
 *
 * display:block beats the stock `display:inline-block` at
 * template.css:405-408 — which is only visible in the original-shape case, as
 * the baseline gap under an inline image — and height/max-width beat
 * template.css:56-60's `img { max-width:100%; height:auto }`. All three are
 * class selectors against element selectors, so no !important is needed.
 */
.view-article .article-details .article-full-image img {
	display: block;
	position: var(--scbt-article-img-position, absolute);
	top: 0;
	left: 0;
	width: 100%;
	height: var(--scbt-article-img-height, 100%);
	max-width: none;
	border-radius: 0;
	object-fit: var(--scbt-article-fit, cover);
	object-position: center;
}

/* Helix's own article image field wraps the box in a link rather than putting
   one inside it, so the wrapper must not collapse. The same two shapes
   scbt-blog.css handles. */
.view-article .article-details .article-full-image > a {
	display: block;
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}


/* ---------------------------------------------------------------------------
 * 4. The title
 *
 * template.css:395-397 sets the size at (0,2,1); the .view-article prefix puts
 * these at (0,3,1), which wins without !important — and this sheet loads after
 * the merged bundle anyway. The colour has no stock rule to beat; the heading
 * simply inherits the body's #252525 today.
 *
 * The colour falls through the same two levels as the category label above.
 * ------------------------------------------------------------------------- */

.view-article .article-details .article-header {
	margin: 0;
}

.view-article .article-details .article-header h1,
.view-article .article-details .article-header h2 {
	margin: 0 0 1.25rem;
	font-size: var(--scbt-article-title-size, 2.25rem);
	font-weight: 700;
	line-height: 1.2;
	color: var(--scbt-article-title-color, var(--scbt-brand, #E6007E));
}

.view-article .article-details .article-header h1 a,
.view-article .article-details .article-header h2 a {
	color: var(--scbt-article-title-color, var(--scbt-brand, #E6007E));
}

.view-article .article-details .article-header h1 a:hover,
.view-article .article-details .article-header h2 a:hover,
.view-article .article-details .article-header h1 a:focus,
.view-article .article-details .article-header h2 a:focus {
	color: var(--scbt-brand-hover, #B3005F);
}
