/* ===========================================================================
   lg.* — the new component layer
   ---------------------------------------------------------------------------
   WHAT THIS IS

   A second, independent CSS layer that sits ON TOP of a.css without being part
   of it. a.css is 3,300 lines of unprefixed, unscoped selectors (.container,
   .panel, .button, .content) accumulated over years; every new rule added to it
   has to be checked against everything already there. This layer does not touch
   it and does not extend it.

   THE RULES OF THE LAYER

   1. Every class starts "lg-". That matches the --lg- custom properties in
      tokens.css and, more importantly, guarantees no collision with a.css,
      which prefixes nothing.

   2. BEM: .lg-block, .lg-block__element, .lg-block--modifier. Two underscores
      and two hyphens, always, so the structure is readable from the class name
      alone.

   3. Values come from tokens.css. A literal colour, radius or font in this
      layer is a bug unless there is a comment saying why.

   4. Components never set their own outer margin or position. The page places
      them; they only describe themselves. That is what makes them reusable
      across grammar, reading, listening, dictation and vocabulary.

   5. No !important, ever. If something here loses to a.css, the selector is
      wrong or the markup is nested inside legacy markup that should be moved
      out. Both are worth fixing rather than papering over.

   HOW A PAGE OPTS IN

   Set $lg_components before including includes/header.php:

       $lg_components = array( "section-header", "score-card" );
       include ("includes/header.php");

   header.php always links this file, then one css/lg.<name>.css per entry.
   Adding a component means adding a file and naming it — no edit to header.php.

   This file holds only what more than one component needs: the box model, the
   button, and the small print. Anything used by exactly one component lives in
   that component's own file.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   Anchor offset under the sticky header

   .header is position:sticky; top:0 (a.css:70), so an in-page jump puts the
   target at the very top of the viewport - underneath the header - and the
   first line or two of the section is hidden behind it.

   scroll-padding-top on the scroll container fixes every anchor on the page
   at once, including ones this layer knows nothing about and including the
   initial jump when a URL arrives with a #hash. Preferred over putting
   scroll-margin-top on each target, which only helps the targets someone
   remembered.

   THE VALUE IS MEASURED, NOT GUESSED

   The header has no fixed height: it is sized by the logo, which changes at
   five breakpoints (110px to 210px wide), and it grows again when one of the
   alert bars in includes/header.php is showing. Any constant here would be
   wrong at some width or for some visitor.

   So includes/header.php sets --lg-header-offset from the real offsetHeight
   and keeps it up to date on resize. The value below is only the fallback for
   the moment before that runs, and for a visitor with no JavaScript - it is
   deliberately on the generous side, because overshooting a heading by a few
   pixels is invisible and undershooting hides it.

   The extra 1rem is breathing room: landing with the heading flush against
   the header reads as clipped even when nothing is covered.
   --------------------------------------------------------------------------- */
:root {
	--lg-header-offset: 5.5rem;
}

html {
	scroll-padding-top: calc(var(--lg-header-offset) + 1rem);
}

/* Border-box for this layer only. a.css is content-box in most places and
   changing that globally would move several hundred boxes; scoping it to
   lg-prefixed elements gets the sane model without touching the old page. */
[class^="lg-"],
[class*=" lg-"],
[class^="lg-"] *,
[class*=" lg-"] * {
	box-sizing: border-box;
}

/* Paragraph sizing stays with the block, not with a.css.

   a.css:30 sets `p { font-size: var(--lg-font-size-p) }` - 1.0625em, the
   x-height correction for DM Sans - on every <p> on the site. Inside this
   layer that correction has already been applied by the block, which states
   its own size in rem, so a <p> child multiplied it a second time: the
   section header body rendered at 1.05rem x 1.0625, visibly larger than the
   lead beside it, which has no <p> because its text arrives untagged.

   Reset rather than matched per component. Editorial HTML from the language
   files can put a <p> inside any prose slot in this layer, so every one of
   them was one stored tag away from the same bug - .lg-score-card__note
   already was.

   Only the size is reset; margins stay with the component that wants them.

   :not([class]) matters. The layer renders four paragraphs of its own with a
   class and a declared size - __eyebrow, __title, __subtitle, __lead - and a
   bare `[class^="lg-"] p` outspecifies all of them at (0,1,1) against (0,1,0),
   which would reset the eyebrow from 0.8rem to whatever it inherits. Only
   UNCLASSED paragraphs are editorial HTML, and only those are reset. */
[class^="lg-"] p:not([class]),
[class*=" lg-"] p:not([class]) {
	font-size: inherit;
}

/* ---------------------------------------------------------------------------
   Button

   Shares nothing with a.css's .button, which carries a gradient, a 5px radius
   and a text-shadow from an older visual language. These are flat pills.

   <button> does not inherit font-family, so it is set explicitly here rather
   than relying on the cascade — the same trap a.css:443 documents.
   --------------------------------------------------------------------------- */
.lg-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	padding: 0.85rem 1.6rem;
	border: 1px solid transparent;
	border-radius: 999px;
	font-family: var(--lg-font);
	font-size: 0.95rem;
	font-weight: 600;
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.lg-btn:hover,
.lg-btn:focus-visible {
	text-decoration: none;
}

/* Keyboard focus stays visible even though the mouse ring is suppressed —
   :focus-visible means pointer users never see it. */
.lg-btn:focus-visible {
	outline: 2px solid var(--lg-red);
	outline-offset: 2px;
}

.lg-btn--primary {
	background-color: var(--lg-red);
	color: var(--lg-text-inverse);
}

.lg-btn--primary:hover {
	background-color: var(--lg-red-hover);
	color: var(--lg-text-inverse);
}

.lg-btn--ghost {
	background-color: var(--lg-surface);
	border-color: var(--lg-border);
	color: var(--lg-text);
}

.lg-btn--ghost:hover {
	background-color: var(--lg-bg);
	border-color: var(--lg-border-strong);
	color: var(--lg-text);
}

/* Quieter than --ghost: no fill of its own, for the foot of a card that is
   already a white surface. */
.lg-btn--quiet {
	background-color: transparent;
	border-color: var(--lg-border);
	color: var(--lg-text);
	font-weight: 500;
}

.lg-btn--quiet:hover {
	background-color: var(--lg-bg);
	color: var(--lg-text);
}

.lg-btn--block {
	display: flex;
	width: 100%;
}

.lg-btn__icon {
	flex: 0 0 auto;
	width: 1.15em;
	height: 1.15em;
}

/* ---------------------------------------------------------------------------
   Small print
   --------------------------------------------------------------------------- */
.lg-meta {
	color: var(--lg-text-muted);
	font-size: 0.95rem;
	line-height: 1.4;
}

/* Visible to a screen reader, not on screen. For labels the design carries by
   position or colour but that have to be spoken. */
.lg-sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ---------------------------------------------------------------------------
   Missing data

   Never render an empty component silently. If a caller cannot supply what a
   block needs, the block says so on screen, in place, and names the reason —
   a blank space on a page looks like a layout bug and gets debugged as one,
   which costs far more than an ugly box during development.

   Not hidden in production on purpose: an empty score card in front of a
   learner is already a failure, and one that is visible gets fixed.
   --------------------------------------------------------------------------- */
.lg-missing {
	display: block;
	padding: 0.75rem 1rem;
	border: 1px dashed var(--lg-bad-text);
	border-radius: var(--lg-radius);
	background-color: var(--lg-bad-bg);
	color: var(--lg-bad-text);
	font-family: var(--lg-font);
	font-size: 0.85rem;
	line-height: 1.4;
}

.lg-missing code {
	font-family: monospace;
	font-size: 0.95em;
}

/* ---------------------------------------------------------------------------
   lg-preview-note — "what you are looking at is not real"

   For a screen rendered from invented data so it can be worked on: today the
   grammar result under ?view=preview, which is otherwise indistinguishable
   from a finished sheet.

   Gold rather than the red of .lg-missing above. Nothing is broken here and a
   red panel would send whoever sees it looking for the fault; gold is the
   colour this layer already uses for "here is a fact about your progress",
   which is the right register for "here is a fact about this page".

   Beside .lg-missing rather than inside the result's own stylesheet: the next
   screen to grow a preview will want the same banner, and it should not have
   to reach into lg.result.css for it.
   --------------------------------------------------------------------------- */
.lg-preview-note {
	display: block;
	margin-bottom: 1rem;
	padding: 0.75rem 1rem;
	border: 1px dashed var(--lg-score-text);
	border-radius: var(--lg-radius);
	background-color: var(--lg-score-track);
	color: var(--lg-score-text);
	font-family: var(--lg-font);
	font-size: 0.85rem;
	line-height: 1.4;
}

.lg-preview-note code {
	font-family: monospace;
	font-size: 0.95em;
}

/* ===========================================================================
   lg-badge — a short tag on a card
   ---------------------------------------------------------------------------
   In core, not in one component's file: the suggestion cards and the topic
   cards both use it, and the second to need it should not have to import the
   first one's stylesheet.

   Three tones, and the tone carries temperature rather than meaning: gold is
   "something you have already touched", coral is "this one is pitched at you
   now", neutral is plain metadata with nothing to say.
   =========================================================================== */

.lg-badge {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	padding: 0.3rem 0.7rem;
	border-radius: 999px;
	font-size: 0.8rem;
	font-weight: 600;
	line-height: 1.3;
	white-space: nowrap;
}

.lg-badge svg {
	width: 0.85em;
	height: 0.85em;
}

/* Gold — you have been here before. "Improve your score", "Popular". */
.lg-badge--gold {
	background-color: var(--lg-score-track);
	color: var(--lg-score-text);
}

/* Coral — this one is pitched at you. "Matches your last sheet",
   "Finish it". Uses the error tints as a base because they are the only warm
   red pair in the tokens that clears contrast; the meaning here is not an
   error and the wording never suggests one. */
.lg-badge--coral {
	background-color: var(--lg-bad-bg);
	color: var(--lg-bad-text);
}

/* Neutral — nothing to say yet. */
.lg-badge--neutral {
	background-color: var(--lg-surface-alt);
	color: var(--lg-text-muted);
}

/* A long German reason ("Passend zum letzten Blatt") next to the icon leaves
   no room for either. The icon is decorative, so it goes first. */
@media (max-width: 380px) {

	.lg-badge {
		font-size: 0.75rem;
		padding: 0.25rem 0.55rem;
	}
}
