/* ===========================================================================
   lg.texts — the reading section's "Texts for you" grid
   ---------------------------------------------------------------------------
   NO NEW COMPONENT. These cards are lg_suggestion_card()'s, built by
   _components/lg-category-texts.php, inside lg_suggestions() — the same
   renderer and the same grid the grammar page uses. This file is the handful
   of differences a text has from an exercise, and nothing else:

       .lg-texts                     the wrapper this page puts round it
         .lg-suggestions             (lg.suggestions.css owns everything here)
           .lg-suggestions__grid
             a.lg-card               no .lg-card__head — see below

   Everything is scoped under .lg-texts so the grammar grid is untouched. TWO
   screens put that wrapper round these cards - the reading overview's "Texts
   for you" strip, and the result screen a finished text opens - so the same
   card looks the same in both places, which is the whole reason the wrapper
   exists rather than a page-level selector.

   WHY THE LAYOUT RULES SAY :not(.lg-card--wide)

   The result screen leads with ONE card across the full column - "Continue
   with" - and lg.suggestions.css lays that one out as a grid with the icon
   beside the text. The rules below re-flow .lg-card__body into a wrapping row,
   at the same specificity as the ones that make the wide card a column, and
   this file loads last: without the :not() they would win and flatten it. The
   wide card is already right; only the grid cards need re-flowing.

   WHY A CARD HERE HAS NO HEAD

   A grammar card leads with an icon circle and a reason badge: "Beliebt",
   "Verbessern". It needs them, because one grammar sheet looks much like
   another and the badge is the only thing saying why this one is on screen.

   A text says what it is in its own first line, which the card prints. So the
   adapter passes "icon" => "", lg_suggestion_card() drops the head, and the
   card is what the mockup draws — title, that first line, one row of facts.
   =========================================================================== */

/* --- Two columns, not three --------------------------------------------- */
/* lg.suggestions.css fills the row with as many 275px cards as fit, which is
   right for a grammar card: its body is a topic name and a sheet number, and
   three across a content column is a comfortable read.

   A text card carries a sentence of the text itself. At 275px that sentence
   wraps to four or five words a line and the card stops being scannable, so
   the floor is raised rather than the count fixed — auto-fill still drops to
   one column on a phone without a media query of its own. */
.lg-texts .lg-suggestions__grid {
	grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
}

/* Below 400px a 360px minimum would overflow the screen: auto-fill honours the
   minimum even when only one column fits. Back to the container's width. */
@media (max-width: 420px) {

	.lg-texts .lg-suggestions__grid {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* --- One line each, faded at the cut ------------------------------------- */
/* The title and the teaser each get exactly one line. Anything longer is cut,
   and the cut is a FADE rather than an ellipsis: three dots announce that
   something was removed, where a fade just stops — which is the truer thing to
   say about the first sentence of a text, since there was never a promise to
   show all of it.

   Every card in a row is then the same height whatever its title does, which
   is what the fade is really buying: a grid of cards that ends level.

   mask-image, with the -webkit- prefix beside it for older WebKit. Where
   neither is honoured, overflow:hidden still clips — a hard edge instead of a
   soft one, which is a worse cut and not a broken card.

   min-width:0 because both are flex items of .lg-card__body: without it a
   flex item refuses to shrink below its content and the text pushes the card
   wider instead of being clipped. This is the whole reason a nowrap that
   "should work" often does not. */
.lg-texts .lg-card__title-text,
.lg-texts .lg-card__sub {
	display: block;
	min-width: 0;
	max-width: 100%;
	white-space: nowrap;
	overflow: hidden;
	-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent 100%);
	        mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent 100%);
}

/* The title is a row now: the text, then the padlock. The text shrinks and
   fades; the padlock never does, which is the point of it being a sibling.

   align-items:baseline so the lock sits on the title's baseline, as it did
   when it was inline. */
.lg-texts .lg-card__title {
	display: flex;
	align-items: baseline;
	min-width: 0;
}

/* flex:1 1 auto, NOT 0 1 auto, and this is the whole trick.

   A mask fades the last 2.5rem of the ELEMENT, not of the text in it. Let the
   text box shrink-wrap and a short title's box ends exactly where its last
   letter does — so the fade lands on real glyphs and a title that fits is
   dimmed for no reason. Filling the row instead puts that 2.5rem over empty
   space, where fading nothing is invisible, and min-width:0 still lets a long
   title shrink and clip.

   The same reasoning is why .lg-card__sub needs nothing here: it is already
   flex:0 0 100% further down, so its box is always the full row. */
.lg-texts .lg-card__title-text {
	flex: 1 1 auto;
}

/* Pushed to the end of the title line rather than sitting against the last
   letter, which is what filling the row above costs. It reads as a status mark
   on the card and lands in the same place on every card, which is easier to
   scan down a grid than a padlock that moves with the length of the name. */
.lg-texts .lg-card__lock {
	flex: 0 0 auto;
	margin-left: auto;
	padding-left: 0.4em;

	/* .lg-card__title is a flex row here, which ignores vertical-align and
	   aligns on its own baseline instead. A box with no in-flow text has its
	   bottom edge for a baseline, so the padlock would stand on the title's
	   baseline and rise most of its height above the letters. align-self is
	   the flex spelling of the vertical-align:middle the base rule sets for
	   the block contexts.

	   The negative vertical margins from the base rule carry over and do the
	   same work here: a flex line is as tall as its tallest item's OUTER box,
	   so at 10px outer the padlock no longer sets the height of the row. */
	align-self: center;
}

/* --- The facts line ------------------------------------------------------ */
/* What is left on it: the CEFR pill, and "Dialog" for a conversation. The word
   count and the "PDF" marker have both gone — the count because it was the one
   fact here a reader could not act on, the marker because it is a link at the
   end of the line now.

   .lg-card__meta is styled in lg.suggestions.css as a single ellipsised line,
   which is right for a grammar card and wrong here. Allowed to wrap instead. */
.lg-texts .lg-card__meta {
	white-space: normal;
	overflow: visible;
	text-overflow: clip;
}


/* --- A locked text ------------------------------------------------------- */
/* .lg-card--locked fades the whole card, which is the grammar behaviour and
   stays. A padlock sits beside the title as well — .lg-card__lock, styled in
   lg.suggestions.css because it belongs to the card rather than to reading.

   No worksheet link on a locked card: the whole card is already the upsell
   trigger and a second one beside it is one target too many. See
   lg_suggestion_card(), which is where that is decided. */

/* --- One row for the facts and the bar ----------------------------------- */
/* One line under the teaser: the CEFR pill, the bar with its figure, and the
   worksheet link at the far end. In the markup the first two are separate
   elements — .lg-card__foot and .lg-card__progress, in that order —
   so the card body becomes a wrapping flex row and the title and teaser are
   told to take a full line each. Nothing is reordered, only laid out.

   flex-wrap matters: on a narrow card the bar drops under the facts instead of
   being squeezed to nothing, which is what a fixed two-column grid would do. */
.lg-texts .lg-card:not(.lg-card--wide) .lg-card__body {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: 0.0rem;
}

.lg-texts .lg-card:not(.lg-card--wide) .lg-card__title,
.lg-texts .lg-card:not(.lg-card--wide) .lg-card__sub {
	flex: 0 0 100%;
}

/* align-items:center, not the body's baseline: the CEFR pill has padding and
   the words beside it do not, so a shared baseline sits the pill low against
   them. */
.lg-texts .lg-card:not(.lg-card--wide) .lg-card__foot {
	order: 1;
	flex: 0 0 auto;
	align-items: center;
	margin-top: 0.9rem;
   margin-right:0.8rem;
}

/* A FOOT WITH NOTHING VISIBLE IN IT HAS TO GO, not merely be empty.

   lg_suggestion_card() emits the foot whenever there is a level, a meta line
   OR a state — and the state is always set here, because it is the dash that
   shows beside the bar. The rule above then hides the foot's copy of it. So a
   text with no CEFR level and no "Dialog" ends up with a foot containing only
   a hidden span: zero width, but still a flex item, and the body's
   column-gap:0.85rem still falls between it and the bar. The bar started
   0.85rem in from the title above it, on those cards and no others.

   display:none is what removes it, since column-gap is not applied around an
   item that is not laid out. Zeroing its width or margins would not have
   helped — the gap is between items, not inside them.

   :has() is the only way to ask "does this contain anything worth showing";
   the two classes named are exactly the two the renderer emits conditionally.
   Where :has() is unsupported the whole selector is dropped and the card falls
   back to the small indent, which is the state before this rule. */
.lg-texts .lg-card:not(.lg-card--wide) .lg-card__foot:not(:has(.lg-card__level, .lg-card__meta)) {
	display: none;
}

/* margin-top:auto is what pins the bar to the foot of a grammar card. Here the
   bar is not at the foot — it is beside the facts — so it would push the whole
   row down the card. padding-top goes with it for the same reason. */
.lg-texts .lg-card:not(.lg-card--wide) .lg-card__progress {
	order: 2;
	flex: 1 1 8rem;
	min-width: 6rem;
	margin-top: 0.9rem;
	padding-top: 0;
}

/* The figure travels with the bar, as it already does on a wide card, and the
   foot's copy of it goes — otherwise the same number is on the line twice. */
.lg-texts .lg-card:not(.lg-card--wide) .lg-card__progress-value {
	display: inline-block;
}

.lg-texts .lg-card:not(.lg-card--wide) .lg-card__state {
	display: none;
}

/* An unread text keeps its track — empty — with a dash where the figure would
   be. .lg-card__progress--empty is still on the element and still means "no
   score yet"; it simply no longer hides anything.

   It used to draw neither, on the reasoning that an empty bar beside the words
   "Not started" said the same thing twice. That was true of the words. With a
   dash instead, the bar is the only thing on the line carrying the shape of
   the row, and without it the cards in a grid stop lining up: a started text
   showed a bar where an unread one showed nothing, and the eye read the
   ragged column as a layout fault rather than as a difference in progress.

   The fill is not emitted at 0% (see lg_suggestion_card()), so the track is
   drawn empty rather than with a zero-width sliver. */

/* --- The shorter bar ----------------------------------------------------- */
/* 80px, not "whatever is left". The track used to take all the room the row
   had, which on a wide card drew a 200px bar to say "25%" — a measurement
   instrument where a small indicator was wanted. Capped, it reads as a mark
   beside the figure, and the space it gives back is where the worksheet link
   now sits. */
.lg-texts .lg-card__track {
	max-width: 80px;
}

/* --- The worksheet link -------------------------------------------------- */
/* lg_suggestion_card() wraps the card and this link in .lg-card-row when there
   is a worksheet: the two are SIBLINGS, because an <a> inside an <a> is
   invalid and browsers unnest it. See the note in that function.

   The wrapper is what the grid lays out, so it has to behave exactly like the
   card did — hence height:100%, which is what keeps cards in a row the same
   height now that one more element sits between them and the grid. */
.lg-card-row {
	position: relative;
	display: block;
	height: 100%;
}

.lg-card-row > .lg-card {
	height: 100%;
}

/* Pinned to the card's bottom-right corner, which is where the facts line
   ends. The offsets are .lg-card's own padding (1.15rem 1.25rem 1.1rem), so
   the pill sits on the same baseline grid as everything inside it.

   Positioned rather than laid out: it is outside the card in the markup, and
   putting it in the flow would mean either a wrapper row inside the card - a
   second <a> again - or a grid the card does not otherwise need. */
.lg-texts .lg-card__pdf {
	position: absolute;
	right: 1.25rem;
	bottom: 1.1rem;
	z-index: 1;
	padding: 0.35rem 0.7rem;
	font-size: 0.85rem;
}

.lg-texts .lg-card__pdf svg {
	width: 0.9rem;
	height: 0.9rem;
}

/* The transition lives on the element, not in the :hover rule below it: with
   it only on hover the pill animates up and then snaps back. */
.lg-texts .lg-card__pdf {
	transition: transform 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}

/* Room for it, reserved in the flow so the bar can never run underneath. The
   pill is absolutely positioned and therefore invisible to the row; without
   this the percentage and the worksheet would overlap on a narrow card. */
.lg-texts .lg-card--has-pdf .lg-card__progress {
	margin-right: 5.5rem;
}

/* The card lifts on hover and the pill would stay behind, so it travels with
   it. Same transform as a.lg-card:hover in lg.suggestions.css; the timing is
   set on the element above. */
.lg-texts a.lg-card:hover ~ .lg-card__pdf {
	transform: translateY(-2px);
}
