/*
 * MAARS component styles — Manhattan Area Amateur Radio Society, KSØMAN.
 * Visual direction: revision 3, "Tuned" (DESIGN.md, locked).
 *
 * THE IDEA
 * Amateur radio is a record-keeping culture. Every contact is logged: date,
 * time in UTC, callsign, frequency, mode. This Society's 48-year archive is a
 * logbook, so the site states what is true NOW, each fact carrying when it was
 * last checked, and then the record. The one bold element is the propagation
 * scene; everything else is deliberately quiet.
 *
 * WHAT REVISION 3 CHANGED, AND WHY. The owner's words, which win over every
 * guideline below them: scrap the top header and remake it with a new idea;
 * modern, for a ham radio club expecting something new; soft, and smooth.
 *
 *   THE MASTHEAD IS A RECEIVER. Section 10. The analogue dial is gone and the
 *   text masthead with it; the top of every page is now a slim live spectrum
 *   and waterfall tuned to the club's own 147.255 MHz machine, with KSØMAN
 *   resting in it. It is the one image that reads as "radio" to a
 *   thirty-year-old and a ninety-year-old at the same time, and it is soft and
 *   smooth by its nature rather than by decoration: a continuous heat map,
 *   with no hard edge anywhere in it, dissolving into the page at both edges.
 *   It is ambient, not bold — the propagation scene in section 9 is still the
 *   page's one large moment and the band never competes with it.
 *
 *   SOFT AND SMOOTH IS NOT THE CARD KIT. The failure mode of a soft-and-smooth
 *   brief is a page chopped into identical rounded boxes, one radius
 *   everywhere, the same grey shadow under each, a gradient wash on anything
 *   that looked empty. This file answers it by varying with ROLE, and by
 *   refusing far more often than it accepts:
 *     · RADIUS IS A STATEMENT ABOUT WHAT A THING IS. 16px on a major surface,
 *       10px on a control, 999px on the one token whose shape is its whole
 *       geometry, and ZERO on data. The archive log, the specification and the
 *       facet lists are square, and section 5 says why in as many words.
 *     · SHADOWS ARE NAVY-TINTED, NEVER GREY, AND ONLY ON THINGS GENUINELY
 *       RAISED. Two things on this site qualify: the mobile navigation
 *       overlay, which really does float over the page, and the buttons a
 *       reader presses. A table is not raised. A row is not raised. A band is
 *       not raised. The navigation row is not raised, and section 10c refuses
 *       it there on purpose, at the point where a shadow was easiest to reach
 *       for.
 *     · GRADIENTS CARRY MEANING OR THEY DO NOT APPEAR. There are exactly two
 *       in this file and both are signal strength: the waterfall itself, and
 *       the masthead's fallback, whose bright column is where 147.255 sits in
 *       the span. There is no decorative wash anywhere.
 *     · MOTION IS 200ms ON ONE CURVE, ON USER-TRIGGERED CHANGES ONLY. No
 *       scroll-triggered entrances. No hover lift on every block.
 *
 *   THE PALETTE SOFTENED AND KEPT ITS IDENTITY. Section 1b is the brief's own
 *   nine-name table, verbatim: ink #191933, ground #F4F5FA, the hairline
 *   #DDE0EE, the old lavender calmed to --haze #E8EAF6, and a new --navy-soft
 *   #3B3BA8 so a hover is a real value step instead of a thicker underline.
 *   Dark mode redefines those nine names and nothing else.
 *
 *   TEXT ON A SURFACE NOBODY CONTROLS. The identity sits on a waterfall, whose
 *   pixels run from near-black to full white and change every 80ms. Contrast
 *   against the average pixel is not a measurement, so section 10b computes
 *   the scrim against the WORST pixel the map can emit — pure white — and the
 *   alphas there are the output of that arithmetic, not a look.
 *
 * WHAT REVISION 2 CHANGED, AND WHY. Revision 1 shipped and was measured.
 *
 *   NO SHOUTED LABELS. Every tracked-out capitalised eyebrow is gone —
 *   STANDING FACTS, NEXT MEETING, MEETING, REPEATER, NET, COMPUTED, SOURCED,
 *   THE RECORD. A label that earns its place is sentence case, quieter ink and
 *   no letter-spacing, and it is never larger than the value it labels. Most
 *   of them turned out not to earn it: the heading above a block already says
 *   what the block is, so the label was deleted rather than restyled.
 *
 *   RULES, NOT BOXES. A hairline between two rows says the same thing a border
 *   round each of them says, in one line instead of eight, and it does not
 *   nest. Revision 1 was a tinted panel holding white cards holding bordered
 *   chips: three frames deep before a reader reached a fact. At most one
 *   bordered container per screen now, and only where it genuinely holds
 *   something apart (the archive's filter panel). No dashed edges anywhere: a
 *   dash reads as unfinished, not as provisional.
 *
 *   THE PROVENANCE LINE IS FURNITURE. One quiet line under the value —
 *   "Sourced. Last checked January 12, 2024 — 977 days ago." — in the same
 *   quiet ink as any other note. Colour only when the fact is genuinely stale,
 *   and the grade word carries the meaning on its own, so nothing is lost in
 *   greyscale or to a reader who cannot see the hue.
 *
 *   THE DATA FACE IS FOR FIGURES. Fira Code goes on .maars-fig and on <code>,
 *   which is callsigns, frequencies, tones, offsets, counts and money. A prose
 *   date is a sentence and stays in the reading face.
 *
 *   ONE SPACING SCALE. Section 1b declares five steps and this file uses no
 *   other vertical length. A component owns the space inside itself; the band
 *   it sits in owns the space around it. Nothing pads a padded thing.
 *
 *   ONE COLUMN. Section 3 is the whole layout: a centred column, one left
 *   edge, one right edge, at every width.
 *
 * AUDIENCE
 * Licensed amateurs aged 30 to 90, read on phones in parking lots and on iPads
 * in a church basement, and shown to a professional club. Legibility beats
 * fashion every time. Body text never below 18px, line-height 1.65, measure
 * 66–72ch, every interactive target at least 48px, a 3px focus ring that is
 * never removed, and no weight below 400.
 *
 * INK POLICY — every ratio below is computed with the WCAG relative-luminance
 * formula, not estimated.
 *   light  navy #00008C on paper 15.23:1 · on ground 13.99:1 · on haze 12.72:1
 *          navy-soft #3B3BA8 on paper 8.83:1 · on ground 8.11:1 · on haze 7.37:1
 *          magenta #990066 on paper 8.25:1 · on ground 7.58:1 · on haze 6.88:1
 *          rust #8F2C00 on paper 8.31:1 · on ground 7.63:1 · on haze 6.94:1
 *          ink #191933 on ground 15.71:1 · on haze 14.27:1 · paper on ink 17.10:1
 *          meta #46496B on paper 8.66:1 · on ground 7.95:1 · on haze 7.23:1
 *   dark   ink #EDEDF7 on ground 16.70:1 · on paper 15.52:1
 *          navy #9FA0F2 8.12:1 · navy-soft #C8C9FA 12.20:1
 *          magenta #F09FD0 9.78:1 · rust #F2A07A 9.33:1
 *          haze band #23234A carries ink at 12.80:1
 *   band   white on the masthead scrim at its thinnest 7.97:1, readout 5.82:1,
 *          both computed against a PURE WHITE waterfall pixel (section 10b)
 *
 * COLOUR IS NEVER THE SIGNAL. A freshness grade is carried by the WORD —
 * Measured, Sourced, Unverified — spelled out in the reading face at the head
 * of the provenance line. Revision 1 carried it in three drawn channels as
 * well (a fill, a frame, a marker box) and the result was a chip that shouted
 * at a reader about a fact nobody had re-measured. The word survives
 * greyscale, deuteranopia, a photocopier and a screen reader, and it is the
 * only channel this file relies on. Hue is used once, for the stale state, and
 * never alone: a stale line also says "Unverified", or prints a date years
 * old, or says "No check on record".
 *
 * CLASS VOCABULARY. Every selector here is a class something actually emits:
 * the render callbacks in maars-core/inc/blocks.php, the block templates in
 * ../../templates and ../../parts, or the log-line contract documented in
 * section 5. Nothing here styles a name no file writes.
 *
 * !important POLICY. Three places, in file order, each commented at the point
 * of use, and nowhere else. Every one of them is beating an !important or an
 * inline style that this file cannot reach on specificity:
 *   1. section 3's flush-left rule, because WordPress's constrained layout
 *      centres a block with `margin-left: auto !important` and a reading
 *      measure is a cap on a line, not an instruction to centre a column;
 *   2. the prefers-reduced-motion kill switch, which has to beat an inline
 *      animation a block or the editor brought with it;
 *   3. the dark band at the end of this file, because WordPress prints its
 *      preset colour utilities (.has-ink-background-color and friends) with
 *      !important of its own, and there is no other way to keep a dark band
 *      dark in both colour schemes without styling a component inside a media
 *      query, which the brief forbids.
 * Everything else beats WordPress's `:root :where(...)` rules on specificity
 * alone — :where() counts as zero, so `:root body` and `:root :is(h1, h2, h3)`
 * are enough.
 */

/* ---------------------------------------------------------------------------
 * 0. The three faces, self-hosted, zero third-party requests.
 *
 * Verified by render, not assumed: Twenty Twenty-Five ships these files inside
 * the image, so they are served from the same origin as the page and no
 * request ever leaves the box. There is no @import, no Google Fonts and no CDN.
 *
 *   Platypi   display — a contemporary serif with real character. Professional
 *                       without being stuffy.
 *   Manrope   body    — geometric sans, wide apertures, holds up at 18px for a
 *                       reader in their eighties.
 *   Fira Code data    — ITS ZERO IS NATIVELY SLASHED. That is the whole point:
 *                       it is how a ham writes KSØMAN. Manrope's zero is not,
 *                       so every callsign, frequency, tone, offset, date and
 *                       dollar amount renders in Fira Code.
 *
 * All three are variable fonts with a weight axis; the ranges below are the
 * axes the files actually carry, which is tighter than the 100–900 theme.json
 * declares for the same files. Nothing in this stylesheet asks for a weight
 * below 400.
 *
 * theme.json registers these faces too, and that registration is the canonical
 * one for the editor and the font library. These declarations are not a
 * duplicate of it for its own sake: the first src here is RELATIVE to this
 * stylesheet, so the faces still resolve when WordPress is installed in a
 * subdirectory, and they make the type correct in the standalone harnesses
 * (tests/test_contrast.py, tests/test_webgl.py) that load this file with no
 * WordPress around it at all. The absolute path follows as the second source.
 * ------------------------------------------------------------------------- */

@font-face {
	font-family: "Manrope";
	src: url("../../../twentytwentyfive/assets/fonts/manrope/Manrope-VariableFont_wght.woff2") format("woff2"),
	     url("/wp-content/themes/twentytwentyfive/assets/fonts/manrope/Manrope-VariableFont_wght.woff2") format("woff2");
	font-weight: 200 800;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Platypi";
	src: url("../../../twentytwentyfive/assets/fonts/platypi/Platypi-VariableFont_wght.woff2") format("woff2"),
	     url("/wp-content/themes/twentytwentyfive/assets/fonts/platypi/Platypi-VariableFont_wght.woff2") format("woff2");
	font-weight: 300 800;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Fira Code";
	src: url("../../../twentytwentyfive/assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2") format("woff2"),
	     url("/wp-content/themes/twentytwentyfive/assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2") format("woff2");
	font-weight: 300 700;
	font-style: normal;
	font-display: swap;
}

/* ---------------------------------------------------------------------------
 * 1. Tokens.
 *
 * Every colour this stylesheet uses is a custom property declared in the base
 * (non-media) blocks below. The dark block at the end of this section
 * redefines the same names and nothing else — it never introduces a name that
 * exists only inside a media query, because a token born in a media query is a
 * token that is undefined for half the audience, and it never styles a
 * component, because a component styled inside a media query is a component
 * that drifts.
 *
 * 1a. The theme.json preset mirror, written at zero specificity with :where()
 * so a real WordPress global-styles block (`:root`, 0-1-0) still wins and the
 * site editor keeps control. On a bare harness page with no WordPress
 * stylesheet — which is how tests/test_contrast.py and tests/test_webgl.py
 * load these components — these are what everything resolves against.
 * ------------------------------------------------------------------------- */

:where(:root) {
	/*
	 * The preset names, carrying revision 3's values. theme.json still holds
	 * revision 1's hexes for ink, ground and lavender; section 1b-iv points
	 * the presets at the table below so one palette reaches the page whether
	 * or not theme.json has caught up, and names theme.json as the place to
	 * make it permanent.
	 */
	--wp--preset--color--navy: #00008c;
	--wp--preset--color--magenta: #990066;
	--wp--preset--color--lavender: #e8eaf6;
	--wp--preset--color--ink: #191933;
	--wp--preset--color--paper: #ffffff;
	--wp--preset--color--ground: #f4f5fa;
	--wp--preset--color--alarm: #a5171b;

	/* The three faces, mirrored from theme.json (slugs display / body / data) so
	   a bare page has the same type as the site. Each falls through to a
	   same-genre system stack if a woff2 has not arrived yet. */
	--wp--preset--font-family--display:
		"Platypi", "Iowan Old Style", "Palatino Linotype", Palatino,
		"Book Antiqua", "Century Schoolbook", Georgia, "Times New Roman", serif;
	--wp--preset--font-family--body:
		"Manrope", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
		Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", "Noto Sans",
		Arial, sans-serif;
	--wp--preset--font-family--data:
		"Fira Code", ui-monospace, SFMono-Regular, "SF Mono", "Cascadia Mono",
		"Segoe UI Mono", Menlo, Consolas, "Liberation Mono", "DejaVu Sans Mono",
		monospace;
}

/* 1b. The brief's own palette and scale. These are the names the rest of this
 * file is built from; a component never writes a hex. */

:root {
	color-scheme: light dark;

	/* --- 1b-i. THE BRIEF'S OWN TABLE, VERBATIM ----------------------------
	 *
	 * DESIGN.md revision 3 prints nine colours in a table, one hex and one
	 * role each. These are those nine names, in that order, with nothing
	 * renamed and nothing added. They are the source. Every --maars-* colour
	 * below is either an alias for one of them or a surface derived from them
	 * and measured against them, and no component anywhere in this file
	 * writes a hex.
	 *
	 * WHAT REVISION 3 MOVED, and why it is safe:
	 *   ink     #14142B -> #191933   still 17.10:1 on paper, 15.71:1 on ground
	 *   ground  #F6F6FB -> #F4F5FA   a shade cooler; paper still lifts off it
	 *   rule    #D7D7E4 -> #DDE0EE   a calmer hairline, see --maars-rule-firm
	 *   lavender #DBDBFB -> --haze #E8EAF6   the same fill, quieted
	 *   --navy-soft #3B3BA8 is new: a second navy for hover and secondary
	 *   emphasis, 8.83:1 on paper, so a state change is carried by a real
	 *   value step and not by the underline alone.
	 *
	 * Navy is NOW. Magenta is THE RECORD. They are never swapped.
	 */
	--navy: #00008c;        /* anchor, links, headings   15.23:1 paper · 13.99:1 ground */
	--navy-soft: #3b3ba8;   /* hover, secondary emphasis  8.83:1 paper ·  8.11:1 ground */
	--magenta: #990066;     /* the archive, and only the archive                        */
	--ink: #191933;         /* body text                 17.10:1 paper · 15.71:1 ground */
	--paper: #ffffff;       /* raised surfaces                                          */
	--ground: #f4f5fa;      /* page ground, cool, softened off-white                    */
	--haze: #e8eaf6;        /* quiet fills, the old lavender, calmed                    */
	--rust: #8f2c00;        /* stale only                 8.31:1 paper ·  7.63:1 ground */
	--rule: #dde0ee;        /* hairlines                                                */

	/* --- 1b-ii. The working names. Aliases, not second opinions. ---------- */
	--maars-navy: var(--navy);
	--maars-navy-soft: var(--navy-soft);
	--maars-magenta: var(--magenta);
	--maars-ink: var(--ink);
	--maars-paper: var(--paper);
	--maars-ground: var(--ground);
	--maars-haze: var(--haze);
	--maars-rust: var(--rust);
	--maars-rule: var(--rule);
	/* The name the 2,700 lines below were written against. Revision 3 renamed
	   the fill, not the fill's job, so the old name is kept pointing at the
	   new one rather than edited out of a hundred places. */
	--maars-lavender: var(--haze);

	/* --- Derived surfaces and hairlines. Never load-bearing for text. ----- */
	--maars-meta: #46496b;          /* secondary prose  8.66:1 paper · 7.95:1 ground */
	--maars-sunk: #eceef8;          /* hover ground, sunken rows */
	--maars-rust-wash: #fbf2ec;     /* the stale dateline's ground  rust 7.52:1 */
	--maars-band: #191933;          /* the one dark band (the hero) */
	--maars-band-edge: transparent; /* the band needs no frame on a pale page */
	--maars-on-band: #ffffff;       /* text on the dark band        17.10:1 */
	--maars-on-band-link: #dbdbfb;  /* links on the dark band       12.66:1 */
	/* The quiet ink on the dark band. --maars-meta there measures 2.08:1 and
	   rust 2.17:1, so a provenance line printed in either would be the same
	   class of failure this file exists to keep out. */
	--maars-on-band-meta: #b9bdd8;  /* notes on the dark band        9.23:1 */
	--maars-space: #05050f;         /* letterbox behind the WebGL2 canvas */

	/*
	 * A SECOND HAIRLINE, and the one place this file argues with the table.
	 * --rule #DDE0EE measures 1.21:1 against the page ground. That is right
	 * for a separator whose job is to be felt rather than seen — between two
	 * paragraphs of a footer, under a facet row. It is not enough for the
	 * lines that hold the archive's columns in register, which a reader in
	 * their eighties runs a finger down: those need to be visible, not
	 * implied. --maars-rule-firm is the same hue, one step down, at 1.45:1,
	 * and it is used ONLY where a rule is structure. Nothing here is a box.
	 */
	--maars-rule-firm: #ccd1e6;

	/* --- 1b-iii. THE MASTHEAD BAND — the receiver. ------------------------
	 *
	 * The band is an instrument face and stays dark in both colour schemes,
	 * the way the hero does, so these are tokens rather than a component rule
	 * inside a media query.
	 *
	 * --maars-scope-floor is the noise floor the waterfall is painted on and
	 * the colour the band falls back to if the canvas never arrives.
	 * --maars-scope-veil is the scrim colour. Its ALPHA is the load-bearing
	 * number: at 0.72 over a PURE WHITE pixel — the brightest thing a
	 * waterfall can possibly emit — the composited background measures
	 * L=0.0817, so white text on it is 7.97:1 and the quiet readout
	 * #D7DBF4 is 5.82:1. Both clear 4.5:1 against the worst case rather than
	 * against the average, which is the only way a scrim can be claimed to
	 * work on a surface whose pixels nobody controls.
	 */
	--maars-scope-floor: #05081f;
	--maars-scope-veil: 5, 8, 31;   /* the veil's RGB; the alphas live in §10 */
	/*
	 * THE IDENTITY SITS ON ITS OWN PLATE, so its contrast is a constant rather
	 * than a bet on what the waterfall happens to paint. Revision 3's first cut
	 * put white text over a hole the script erased in the band; the hole showed
	 * the light page ground, so the wordmark came out white-on-near-white at a
	 * measured 1.13:1 -- the very failure this rebuild exists to fix, rebuilt.
	 * Navy on the plate is 13.99:1 and cannot drift, with canvas or without.
	 */
	--maars-scope-plate: rgba(244, 245, 250, 0.94);
	--maars-on-scope: #00008c;      /* 13.99:1 on the plate */
	--maars-on-scope-meta: #191933; /* 15.70:1 on the plate */

	/* --- Focus. 3px navy, 2px offset, never removed. The halo is a second
	   ring in the opposite value so the outline is still visible when the
	   element itself is navy — a navy ring on a navy button is not a ring. -- */
	--maars-focus: var(--maars-navy);
	--maars-focus-halo: var(--maars-paper);

	/* --- Type -------------------------------------------------------------
	   The reading face is asked for by both slugs theme.json has used for it,
	   newest first, before falling through to the mirror above: a face this
	   whole design depends on must not vanish because a preset was renamed. */
	--maars-font-display: var(--wp--preset--font-family--display);
	--maars-font-text: var(--wp--preset--font-family--body,
		var(--wp--preset--font-family--text));
	--maars-font-data: var(--wp--preset--font-family--data);

	/* 18px floor at 320px, 20px by 1100px. Not 16. The reader is 78. */
	--maars-text-body: clamp(1.125rem, 1.085rem + 0.2vw, 1.25rem);
	--maars-text-data: clamp(1.125rem, 1.09rem + 0.18vw, 1.25rem);
	--maars-text-lede: clamp(1.25rem, 1.18rem + 0.36vw, 1.5rem);
	--maars-text-h3: clamp(1.3125rem, 1.22rem + 0.46vw, 1.625rem);
	--maars-text-h2: clamp(1.5rem, 1.33rem + 0.86vw, 2.125rem);
	--maars-text-h1: clamp(1.875rem, 1.56rem + 1.6vw, 3rem);
	/* Secondary prose — a caption, a provenance line, a footnote. Flat 18px: it
	   is the floor, and it is never allowed to drift under it to make room. */
	--maars-text-note: 1.125rem;
	/*
	 * A field label: "Date", "Callsign", "Next meeting". Also 18px, because the
	 * floor is the floor and a label is text a 78-year-old has to read. It is
	 * made quiet by CASE, WEIGHT and INK — sentence case, 600, meta — and never
	 * by shrinking it under the floor or tracking it out into capitals. It is
	 * always smaller than the value it labels, because the value is 20px body
	 * or larger.
	 */
	--maars-text-label: 1.125rem;
	--maars-leading: 1.65;
	--maars-measure: 68ch;          /* 66–72ch */

	/* --- Space. ONE scale, and the only vertical lengths in this file. ----
	 *
	 * Revision 1 had no scale: a band padded 2.75rem held a card padded 1.35rem
	 * holding a chip padded 0.45rem, and every one of those was a clamp() of
	 * its own. The homepage came out 6,363px tall for about a screen and a half
	 * of information. The rule now is that a component owns the space INSIDE
	 * itself and nothing else, the band it sits in owns the space AROUND it,
	 * and both of them spend it out of these five steps.
	 */
	--maars-space-1: 0.35rem;   /* a line and the line under it */
	--maars-space-2: 0.6rem;    /* inside a row */
	--maars-space-3: 1rem;      /* between rows */
	--maars-space-4: 1.5rem;    /* between a block and the next block */
	--maars-space-5: clamp(1.5rem, 1.25rem + 1vw, 2rem);   /* between bands */

	/* --- Shape: A RADIUS SCALE BY ROLE, NOT ONE NUMBER EVERYWHERE ---------
	 *
	 * The owner asked for soft and smooth. The failure mode that request
	 * produces is the generic card kit: every block chopped into an identical
	 * rounded box with one radius and the same grey shadow under it. The
	 * brief's answer, and this file's, is that the radius is a statement about
	 * WHAT A THING IS:
	 *
	 *   16px  a major surface — something a reader could imagine picking up:
	 *         the scene's canvas, a document image, the original-file panel.
	 *   10px  a control — a button, a search field, a band selector. Smaller,
	 *         because a control is smaller and a 16px corner on a 48px button
	 *         eats a third of its edge.
	 *  999px  a pill — a thing whose shape IS its whole geometry: the current
	 *         page number. There are very few of these and none of them was
	 *         invented to use the value up.
	 *      0  DATA. A table is not a surface and a row is not a card. The
	 *         archive log, the specification list and the facet lists are set
	 *         square, because a column of records that curves at the corners
	 *         stops reading as a column of records.
	 */
	--maars-radius-surface: 16px;
	--maars-radius-control: 10px;
	--maars-radius-pill: 999px;
	--maars-radius-data: 0;
	/* The name the older rules were written against, pointed at the control
	   step: everything that carried it was a control or a focus ring. */
	--maars-radius: var(--maars-radius-control);

	/* --- Shadow: NAVY-TINTED, AND ONLY ON THINGS GENUINELY RAISED --------
	 *
	 * Straight off the brief, and grey is not in it: a grey shadow under a
	 * navy-and-white page is the one that reads as a template. The list of
	 * things that carry it is deliberately three items long — the mobile
	 * navigation overlay, which really does float over the page, and the two
	 * buttons a reader presses. A table is not raised. A row is not raised. A
	 * band is not raised. A fact is not raised. Section 10c says so again at
	 * the point where it would have been easiest to reach for one.
	 */
	--maars-shadow: 0 1px 2px rgba(10, 10, 60, 0.05),
		0 10px 30px rgba(10, 10, 60, 0.07);
	--maars-shadow-lifted: 0 2px 6px rgba(10, 10, 60, 0.10),
		0 18px 48px rgba(10, 10, 60, 0.16);

	--maars-gutter: clamp(1rem, 0.6rem + 2vw, 2rem);
	--maars-column: 72rem;          /* the one column; see section 3 */
	--maars-target: 48px;
	--maars-hairline: 1px;

	/* --- Motion: ONE curve, one duration, user-triggered changes only. ----
	 * 200ms and cubic-bezier(.2,.7,.3,1), the brief's own numbers: a curve
	 * that leaves quickly and arrives slowly, which is what "smooth" means
	 * when it is not a synonym for "slow". Nothing on this site animates on
	 * load, nothing animates on scroll, and no block lifts on hover. The one
	 * ambient motion on the page is the waterfall in the masthead.
	 */
	--maars-motion: 200ms;
	--maars-ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* 1b-iv. ONE PALETTE ON THE PAGE.
 *
 * WordPress prints theme.json's palette as `:root{--wp--preset--color--*}`,
 * and theme.json is pinned by the interface contract to revision 1's hexes —
 * ink #14142B, ground #FBFBFD, lavender #DBDBFB. Revision 3 softened all
 * three. Left alone, a page would carry two inks: #191933 wherever this file
 * names a token and #14142B wherever a template carries `has-ink-color`.
 *
 * Two inks eight tenths of a percent apart is not a visible defect, and that
 * is exactly why it would survive for years. So the presets are re-pointed at
 * the table, at `:root:root` (0-2-0), which outranks the `:root` block
 * WordPress prints whichever order the two stylesheets load in — the same
 * device section 3 uses for the layout sizes and section 1c for dark mode.
 *
 * This is a bridge, not a home. The palette belongs in theme.json, where the
 * site editor can see it; when theme.json is updated to the revision 3 table
 * this block becomes a no-op and can go. It sets colour names and nothing
 * else, so it cannot drift into styling a component.
 */

:root:root {
	--wp--preset--color--navy: var(--navy);
	--wp--preset--color--magenta: var(--magenta);
	--wp--preset--color--lavender: var(--haze);
	--wp--preset--color--ink: var(--ink);
	--wp--preset--color--paper: var(--paper);
	--wp--preset--color--ground: var(--ground);
}

/* 1c. Dark scheme. TOKENS ONLY. No component may be styled in here.
 *
 * `:root:root` (and the body twin) outrank whatever selector WordPress printed
 * its preset block with, whichever order the two stylesheets load in. Every
 * name set here is also set above, so nothing is undefined in light. The
 * preset variants are the ones the contract pins; ink and paper genuinely
 * trade places, which is what keeps has-ink-color text and
 * has-paper-background-color cards correct in both schemes without a single
 * component rule. */

@media (prefers-color-scheme: dark) {
	:root:root,
	:root:root body {
		/*
		 * THE BRIEF'S NINE NAMES, REDEFINED AND NOTHING ELSE. This is the
		 * whole of dark mode: the same table, the same roles, different
		 * values. No selector in this media query names a component, so
		 * nothing can drift between the two schemes.
		 */
		--navy: #9fa0f2;        /* 8.12:1 on ground */
		--navy-soft: #c8c9fa;   /* hover goes brighter on a dark page. 12.20:1 */
		--magenta: #f09fd0;     /* 9.78:1 on ground */
		--ink: #ededf7;         /* 16.70:1 on ground */
		--paper: #14142a;
		--ground: #0c0c18;
		--haze: #23234a;        /* ink on it 12.80:1 */
		--rust: #f2a07a;        /* 9.33:1 on ground, still far from magenta */
		--rule: #3d3d63;

		/* The preset mirror follows the table, so has-ink-color text and
		   has-paper-background-color surfaces stay correct with no component
		   rule anywhere. Ink and paper genuinely trade places. */
		--wp--preset--color--navy: var(--navy);
		--wp--preset--color--magenta: var(--magenta);
		--wp--preset--color--ink: var(--ink);
		--wp--preset--color--paper: var(--paper);
		--wp--preset--color--ground: var(--ground);
		/* The old lavender preset points at the calmed fill, lifted to sit on
		   #0C0C18 instead of the 1.2:1 disaster a naive inversion produces. */
		--wp--preset--color--lavender: var(--haze);
		--wp--preset--color--alarm: #ff9e7a;

		/* Derived surfaces. Every one of them is measured against the table
		   above, not inverted from the light value and hoped for. */
		--maars-rule-firm: #4c4c78;  /* structure, not decoration. 1.53:1 on ground */
		--maars-meta: #b9bfd8;       /* 10.64:1 on ground */
		--maars-sunk: #1b1b38;
		--maars-rust-wash: #26130c;  /* rust on it 8.54:1 */
		/* The band is lifted off the ground rather than sunk into it: on a dark
		   page "a darker slab" is not a band, it is nothing. Ink on it is
		   15.52:1, and the edge token draws the frame the value alone cannot. */
		--maars-band: #14142a;
		--maars-band-edge: #3d3d63;
		--maars-on-band: #ededf7;   /* 15.52:1 on the band */
		--maars-on-band-link: #dbdbfb; /* 13.36:1 — the light lavender, not the band */
		--maars-on-band-meta: #b9bdd8; /* 9.74:1 on the band */
		--maars-space: #05050f;

		/*
		 * THE MASTHEAD DOES NOT INVERT. A receiver's screen is dark in a lit
		 * room and dark in a dark one; the band is the same instrument face in
		 * both schemes, and saying so here — as a token — is what keeps it out
		 * of a component rule inside a media query. The floor drops a shade so
		 * the band still separates from a #0C0C18 page.
		 */
		--maars-scope-floor: #04061a;
		--maars-scope-veil: 4, 6, 26;
		--maars-scope-plate: rgba(233, 235, 245, 0.95);
		--maars-on-scope: #00008c;
		--maars-on-scope-meta: #191933;

		/*
		 * A navy-tinted shadow is invisible on a dark page, because a shadow
		 * is a value step and there is no value below #0C0C18 to step to. On
		 * dark, the same raised things are separated by a deeper, wider one.
		 */
		--maars-shadow: 0 1px 2px rgba(0, 0, 0, 0.5),
			0 10px 30px rgba(0, 0, 0, 0.55);
		--maars-shadow-lifted: 0 2px 6px rgba(0, 0, 0, 0.6),
			0 18px 48px rgba(0, 0, 0, 0.65);

		--maars-focus: #9fa0f2;     /* still navy — the dark variant. 8.12:1 on ground */
		--maars-focus-halo: #0c0c18;
	}
}

/* ---------------------------------------------------------------------------
 * 2. Document floors.
 *
 * Written with :where() — zero specificity — so theme.json, the site editor
 * and a block's own settings still win. These are what a bare page falls back
 * to, and they are the accessibility floor the brief makes non-negotiable.
 * ------------------------------------------------------------------------- */

:where(*, *::before, *::after) {
	box-sizing: border-box;
}

:where(html) {
	/* clip, not hidden: nothing scrolls sideways at 390px, sticky still works. */
	overflow-x: clip;
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
}

/*
 * `:root body` scores 0-1-1, which beats the `:root :where(body)` rule
 * WordPress prints for styles.color and styles.typography — :where() counts as
 * zero, so one element name on top of :root is enough and no !important is
 * needed. The body background is an explicit token, never inherited from the
 * host: a transparent body borrows whatever ground is behind it.
 */
:root body {
	background-color: var(--maars-ground);
	color: var(--maars-ink);
	font-family: var(--maars-font-text);
	font-size: var(--maars-text-body);
	font-weight: 400;
	line-height: var(--maars-leading);
	-webkit-font-smoothing: antialiased;
}

/* Headings. Display serif for the three that carry a section; the small three
   are field labels and stay in the text face, which is how theme.json has
   them. 0-1-1 again, for the same reason as body. */
:root :is(h1, h2, h3) {
	font-family: var(--maars-font-display);
	font-weight: 600;
	letter-spacing: -0.01em;
	line-height: 1.15;
	text-wrap: balance;
}

:root :is(h4, h5, h6) {
	font-family: var(--maars-font-text);
	font-weight: 700;
	line-height: 1.25;
}

:where(h1) { font-size: var(--maars-text-h1); }
:where(h2) { font-size: var(--maars-text-h2); }
:where(h3) { font-size: var(--maars-text-h3); }

/* Prose. A long line is the commonest reason an older reader loses their
   place, so the measure is capped wherever text runs. */
:where(p, li, dd, blockquote) {
	overflow-wrap: break-word;
	text-wrap: pretty;
}

:where(.maars-main) :where(p, li, blockquote) {
	max-width: var(--maars-measure);
}

:where(strong, b) {
	font-weight: 700;
}

:where(img, svg, video, iframe, canvas) {
	max-width: 100%;
}

/*
 * The visually-hidden class. maars-core/inc/blocks.php names this as "the
 * theme's visually-hidden class" and puts the label a screen reader is still
 * owed inside it — "Next meeting: " before the computed date, now that the
 * printed eyebrow is gone. WordPress ships a .screen-reader-text of its own in
 * the block library, but a theme whose markup depends on a class must define
 * it: if that stylesheet is ever dequeued, the label must go quiet, not land
 * in the middle of the page.
 *
 * clip-path, not display:none and not width:0 — the text has to stay in the
 * accessibility tree and stay reachable to a screen reader's cursor.
 */
.screen-reader-text {
	border: 0;
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	white-space: nowrap;
	width: 1px;
}

/* A table or a code block may be wider than the page; it gets its own scroller
   so the document body never does. */
:where(.maars-main) :where(pre, table) {
	display: block;
	max-width: 100%;
	overflow-x: auto;
}

/* Links. Navy is NOW, and an underline is not decoration — it is the second
   channel, for a reader who cannot see the hue at all. */
:where(a) {
	text-underline-offset: 0.18em;
	text-decoration-thickness: max(1px, 0.06em);
}

:where(.maars-main, .maars-header, .maars-footer) :where(a:hover) {
	text-decoration-thickness: max(2px, 0.11em);
}

/*
 * FOCUS. 3px solid navy, 2px offset, on every interactive element, never
 * removed and never reduced to a colour change. The halo is a second ring in
 * the opposite value that fills the offset gap, so the outline is still a ring
 * when the element itself is navy.
 */
:where(a, button, summary, input, select, textarea, [tabindex], [role="button"]):focus-visible {
	border-radius: var(--maars-radius-control);
	outline: 3px solid var(--maars-focus);
	outline-offset: 2px;
	box-shadow: 0 0 0 2px var(--maars-focus-halo);
}

/* A browser without :focus-visible still gets the ring. */
@supports not selector(:focus-visible) {
	:where(a, button, summary, input, select, textarea, [tabindex]):focus {
		outline: 3px solid var(--maars-focus);
		outline-offset: 2px;
		box-shadow: 0 0 0 2px var(--maars-focus-halo);
	}
}

/*
 * 48px targets wherever a finger is expected. The brief's floor, and the
 * reason it is 48 and not 44: a 70-year-old thumb on a bus.
 *
 * A LINK INSIDE A SENTENCE IS NOT IN THIS LIST. "Check <a>meetings and
 * events</a> before you rely on it" is prose, and giving that anchor a 48px
 * box would open a hole in the line it sits in and push the sentence apart.
 * WCAG 2.5.5 exempts an inline link for exactly that reason. What is in the
 * list is everything a reader aims at: navigation, buttons, pagination, a term
 * in a facet list, an entry's title, the masthead, a breadcrumb.
 */
:where(.wp-block-navigation) :where(a, button),
.maars-skywave__control,
:where(.maars-main, .maars-footer) :where(.wp-block-button__link, .wp-element-button),
:where(.maars-dateline, .maars-next-meeting, .maars-fact, .maars-skywave)
	:where(button, [role="button"], summary) {
	align-items: center;
	display: inline-flex;
	justify-content: center;
	min-height: var(--maars-target);
	min-width: var(--maars-target);
	padding-inline: 0.9rem;
}

/*
 * And the targets that are text rather than controls: the masthead, an entry's
 * title in a list, a term, a breadcrumb, the link out of a log row. These get
 * the 48px height and nothing else — no centring, no minimum width and no side
 * padding, because each one is a line of type that has to start where the type
 * around it starts. The height is what a finger needs; the rest would move the
 * words.
 */
.maars-masthead__wordmark a,
.maars-entry__title a,
.maars-index__title a,
.maars-log__title a,
.maars-log__kind a,
.maars-doc-record__kind a,
.maars-doc-record__yearterm a,
.maars-breadcrumb a,
.maars-doc-record__back a,
.maars-doc-nav a,
.maars-news__more a,
/* The one link out of the on-the-air section. Measured at 1440px before it was
   added here: 565 x 27px, the only control on the front page under the 48px
   floor — everything else on that page already cleared it. It is a standalone
   line of type, so it belongs in this list rather than in the control list
   above. */
.maars-onair__more a,
.maars-termlist a {
	align-items: center;
	display: inline-flex;
	min-height: var(--maars-target);
}

/* Form controls in the archive filters are targets too, and a 16px input is
   what makes iOS zoom the page on focus. */
:where(.maars-main) :where(input[type="search"], input[type="text"], select, button) {
	font-family: var(--maars-font-text);
	font-size: var(--maars-text-body);
	min-height: var(--maars-target);
}

/* ---------------------------------------------------------------------------
 * 3. THE COLUMN. One centred column, one left edge, one right edge, at every
 *    width. This section is the whole layout.
 *
 * THE BUG THIS FIXES. Revision 1's archive page sat left of centre with a dead
 * gutter down the right-hand side, and the cause was two column widths on one
 * page. WordPress's constrained layout gives a band's children
 * `max-width: var(--wp--style--global--content-size)` with auto side margins,
 * while a band marked alignwide gets the much larger wide-size. So the
 * masthead's text was centred inside a 68ch column starting 241px in, and the
 * filter panel and the log beneath it started at 64px and ran to 1216px. Two
 * left edges, 177px apart, and a right-hand gutter that belonged to neither.
 *
 * Worse, content-size was declared in `ch`, which resolves against each
 * element's OWN font size: the 18px eyebrow measured 735px and the 20px lede
 * measured 797px, so even the centred column had a ragged right edge.
 *
 * THE FIX. Both layout sizes become 100%, so every band and every child of a
 * band fills the one column that .maars-main establishes, and WordPress's auto
 * side margins resolve to zero because nothing is narrower than its parent any
 * more. Text is held to a reading measure by section 2 instead — a cap on the
 * paragraph, not a centring of it, so a paragraph starts at the same left edge
 * as the heading above it. `:root:root` is 0-2-0 and beats the `:root` block
 * WordPress prints these in, whichever order the two stylesheets load in.
 *
 * functions.php passes this file to add_editor_style(), so these two lines also
 * take effect inside the block editor. That is intended: the editor then lays a
 * band out the way a visitor will see it. Anyone who wants the editor's content
 * width back changes it here, in one place, and gets the front end with it.
 * ------------------------------------------------------------------------- */

:root:root {
	--wp--style--global--content-size: 100%;
	--wp--style--global--wide-size: 100%;
}

/*
 * THE SIDE INSET. The header and footer bands are full-bleed, so the hairline
 * that closes each of them runs the width of the window; main is the column
 * itself. Each of the three is inset by one gutter, and nothing inside them
 * adds a second one.
 */
.maars-main > *,
.maars-footer {
	padding-inline: var(--maars-gutter);
}

/*
 * THE HEADER IS NOT IN THAT LIST ANY MORE, AND THAT IS REVISION 3.
 *
 * The masthead band is a receiver face and has to reach both edges of the
 * window: an instrument that stops 32px short of the glass is a picture of an
 * instrument. A padded header cannot hold one — the band would either inherit
 * the inset or have to fight its way out of it with a negative margin against
 * WordPress's `margin-left: auto !important`, which is a fight nobody wins
 * cleanly.
 *
 * So the region stops being padded and each ROW inside it carries its own
 * inset instead: the navigation gets the gutter and the column cap below, the
 * band opts out of both, and the identity inside the band re-applies them so
 * the callsign still starts on the one left edge that every heading, every log
 * row and the colophon start on. Measured at 1440px: 176px, all of them.
 */

.maars-main {
	margin-inline: auto;
	max-width: var(--maars-column);
	width: 100%;
}

/*
 * And the cap, which is the part revision 1 had wrong. The content of the
 * header and of the footer is capped to the COLUMN MINUS ITS GUTTERS — that
 * is, to exactly the width of main's content — so the masthead, every band on
 * the page and the colophon share one left edge and one right edge at every
 * viewport width. Capping them to the full column instead, as revision 1 did,
 * put the footer's columns a whole gutter to the left of everything above
 * them: a 32px step at the bottom of every page.
 *
 * `width: 100%` matters: without it a grid or flex parent can size one of
 * these to its content and the auto margins then centre a column narrower than
 * the page, which is the defect at the head of this section in miniature.
 */
.maars-footer > * {
	margin-inline: auto;
	max-width: calc(var(--maars-column) - 2 * var(--maars-gutter));
	width: 100%;
}

/*
 * A row of the header. Same content width as main — the full column, padded by
 * one gutter — rather than main's width with the gutter already subtracted,
 * because this element now carries the padding itself. Below about 1150px both
 * resolve to the viewport minus two gutters, which is why the navigation keeps
 * its inset at 390px where revision 2's rule would have left it flush against
 * the glass the moment the header stopped being padded.
 */
.maars-header > * {
	margin-inline: auto;
	max-width: var(--maars-column);
	padding-inline: var(--maars-gutter);
	width: 100%;
}

/* And the one row that is not a row: the band. It opts out of both. */
.maars-header > .maars-masthead {
	/* The masthead stays in the page column so the identity lines up with every
	   other heading on the site. Only the two painted layers below bleed. */
	margin-inline: 0;
	max-width: none;
	padding-inline: 0;
	width: auto;
}

/*
 * A band's own content also fills the band. This repeats the fix above for the
 * case where WordPress's layout stylesheet is not present at all — the
 * standalone harnesses in tests/ load this file with no WordPress around it —
 * and it is written with :where() so that any component rule below, and any
 * reading measure, still wins.
 */
:where(.maars-main, .maars-header, .maars-footer)
	:where(.is-layout-constrained, .is-layout-flow, .wp-block-column)
	> :where(div, section, aside, figure, form, ul, ol, nav, h1, h2, h3, h4, hr) {
	max-width: 100%;
}

/*
 * AND THE LEFT EDGE ITSELF. The first of this file's three !important
 * declarations, and the one that finishes the defect described above.
 *
 * WordPress's constrained layout does not only cap a child's width, it centres
 * it: `margin-left: auto !important; margin-right: auto !important`, with the
 * !important in core, where it has been since 5.9. So the moment a paragraph
 * carries a reading measure of its own — which every paragraph on this site
 * does, because a 1,088px line is unreadable — that paragraph is centred
 * inside its band while the heading above it is not, and the page grows a
 * second left edge and a dead gutter down the right. That is precisely the
 * defect: on the archive the heading sat at 112px, the lede at 207px and the
 * document list at 80px. Three left edges on one page.
 *
 * A measure is a CAP on a line of text, not an instruction to centre a block,
 * and there is no way to say so over an !important except with one. So: inside
 * the three page regions, a child of a constrained container is flush. Its
 * measure still holds, because this touches margins and nothing else.
 */
.maars-main > *,
:is(.maars-main, .maars-header, .maars-footer) :where(.is-layout-constrained) > * {
	margin-inline: 0 !important;
}

/* ---------------------------------------------------------------------------
 * 4. Motion. ONE curve and ONE duration: 200ms on cubic-bezier(.2,.7,.3,1),
 *    and only on a change the reader asked for — a hover, a focus, a press.
 *
 * Nothing animates on load. Nothing animates on scroll: there are no fade-ups
 * here, because a page that withholds its own content until the reader scrolls
 * far enough is a page that is slower to read than a static one, and on a phone
 * in a parking lot it is a page that never finishes. No block lifts on hover,
 * because a hover lift on everything is a page where nothing is raised.
 *
 * The single ambient motion on the site is the waterfall in the masthead, and
 * it is decorative, aria-hidden and slow — one frame every 80ms, not sixty a
 * second. Under prefers-reduced-motion it draws one still frame and stops, and
 * everything else here stops too, including anything a block or the editor
 * brought with it.
 * ------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-delay: -1ms !important;      /* beats an inline/animated block style */
		animation-duration: 1ms !important;
		animation-iteration-count: 1 !important;
		scroll-behavior: auto !important;
		transition-delay: 0ms !important;
		transition-duration: 0ms !important;
	}
}

/* ===========================================================================
 * 5. THE LOG LINE.
 *
 * One recurring row in real logbook conventions: fixed columns, tabular
 * figures, slashed zeros, a hairline between entries. It carries the archive
 * index and the record strip on a single document. It encodes that this
 * Society keeps records, and it does it with rules and alignment rather than
 * with boxes. The one bold element on the site is the propagation scene in
 * section 9; a log row that competed with it would be a log row calmed.
 *
 * It no longer carries the computed meeting or the freshness chip. Both were
 * facts dressed as table rows, under labels in capitals, and neither is a row
 * in a list of anything. See sections 6 and 8.
 *
 * ---------------------------------------------------------------------------
 * THE VOCABULARY, which is shared with maars-core/inc/blocks.php (which
 * documents the same names at the top of that file) and with the block
 * templates. Two shapes, because a log has two:
 *
 *   A COLUMNED LOG — many entries, the same fields in the same order.
 *     .maars-log          the group. Sets --maars-log-columns for everything
 *                         inside it.
 *     .maars-log__head    the ruled column head. Hidden below the breakpoint,
 *                         where each field labels itself instead.
 *     .maars-log__col     one heading in that head (+ --col-date, --col-type,
 *                         --col-title).
 *     .maars-log__entries the list the rows sit in.
 *     .maars-log__row     one entry. Grid, aligned to the head above it.
 *     .maars-log__date, __kind, __title    the three fields.
 *     .maars-log__pagination  the numbered control under the list.
 *
 *   A LABELLED LINE — one record, a field at a time. Usable standalone: the
 *   skywave band list is a group of these with no .maars-log__row anywhere, so
 *   NONE of the line rules are scoped under .maars-log.
 *     .maars-log__line    one line. The field name inside it is a
 *                         .maars-fieldname; the value is whatever the template
 *                         puts there.
 *     .maars-log__header  a strip of such lines above a document.
 *     .maars-log__cell    one label-over-value pair inside that strip.
 *
 * Column widths are a custom property, so a template sets its own shape
 * without a new class: --maars-log-columns on the .maars-log element. The
 * default is the archive's — date, type, document.
 *
 * The figure span, .maars-fig, is emitted by the plugin around every callsign,
 * frequency, tone, offset, date, day count and dollar amount. It is what puts
 * a figure in the data face wherever it appears, including inside a sentence.
 * ======================================================================== */

/*
 * THE FIGURE, and the whole of the data face.
 *
 * Fira Code, because its zero is natively slashed — the Society writes its
 * callsign KSØMAN and the type honours it — and tabular, because a column of
 * figures that does not line up is a column nobody checks.
 *
 * A FIGURE IS A CALLSIGN, A FREQUENCY, A TONE, AN OFFSET, A GRID SQUARE, A
 * COUNT OR AN AMOUNT OF MONEY. It is nothing else. Revision 1 put the data
 * face on whole elements — the archive's Date and Type columns, the news date,
 * the band list, the computed meeting — and the result was prose set in a
 * monospace: "Friday, October 9, 2026 at 6:30 P.M." reading like a part
 * number, and the word "Minutes" reading like a file name. A date written out
 * in words is a sentence.
 *
 * So the face is applied to two things and no others: .maars-fig, the span the
 * plugin wraps a figure in, and <code>, which is what a template writes round
 * a figure inside a sentence. <time> is deliberately NOT in this list: a
 * <time> holds "January 12, 2024", which is prose with a machine-readable
 * attribute attached, and the plugin marks the figures inside it itself.
 */
.maars-fig,
:where(.maars-main, .maars-header, .maars-footer) :where(code, kbd) {
	font-family: var(--maars-font-data);
	font-size: 1em;
	font-variant-numeric: slashed-zero tabular-nums;
	font-feature-settings: "zero" 1, "tnum" 1;
}

/* The callsign in the masthead is a figure that happens to be the identity.
   The block already wraps it in .maars-fig, so this is belt and braces for a
   build where the wrapper has not arrived yet. */
.maars-masthead__call {
	font-family: var(--maars-font-data);
	font-variant-numeric: slashed-zero tabular-nums;
	font-feature-settings: "zero" 1, "tnum" 1;
}

/*
 * A record locator — the name, format and size of the original file in the
 * archive — is a figure in the logbook sense: it is copied, compared and typed
 * back in, so it is set in the face that makes a zero a zero.
 */
.maars-original__file {
	font-family: var(--maars-font-data);
	font-variant-numeric: slashed-zero tabular-nums;
	font-feature-settings: "zero" 1, "tnum" 1;
}

/*
 * Everything else that holds a number keeps the tabular, slashed FIGURES
 * without changing FACE, so a year in a list still lines up with the year
 * under it and a zero is still never an O, while the words around it stay in
 * the reading face where they belong.
 */
.maars-log,
.maars-log__line,
.maars-log__date,
.maars-dateline__headline,
.maars-dateline__detail,
.maars-next-meeting__date,
.maars-next-meeting__rule,
.maars-fact__chip,
.maars-entry__date,
.maars-news__date,
.maars-doc-record__date,
.maars-skywave__band,
.maars-skywave__control,
.maars-spec,
.maars-termlist,
.maars-lastreviewed__line {
	font-variant-numeric: slashed-zero tabular-nums;
	font-feature-settings: "zero" 1, "tnum" 1;
}

:where(.maars-main, .maars-header, .maars-footer) :where(code, kbd) {
	background-color: transparent;
	padding: 0;
}

/* ---------------------------------------------------------------------------
 * 5a. The columned log.
 * ------------------------------------------------------------------------- */

.maars-log {
	/*
	 * date | type | document — the archive's shape, and the default. A template
	 * with different fields sets its own value on the .maars-log element, which
	 * the archive does.
	 *
	 * Every track is a minmax() with a floor of 0. Written as fixed widths, a
	 * row cannot shrink below the sum of them plus its gaps, and between the
	 * stacking breakpoint at 640px and about 700px the last column hangs past
	 * the edge of the page and is clipped — measured at 640px on the
	 * four-column version of this list, where the head's "Original file" ended
	 * at 670 in a 640px window. A track that cannot shrink is a track that
	 * overflows.
	 */
	--maars-log-columns: minmax(0, 8rem) minmax(0, 10.5rem) minmax(0, 1fr);
	--maars-log-gap: var(--maars-space-4);

	/*
	 * ZERO. THE DATA STEP, AND IT IS WRITTEN OUT RATHER THAN LEFT OUT.
	 *
	 * This is where a soft-and-smooth brief goes wrong. The archive is 26
	 * years of documents in a ruled list, and rounding it — the list, the
	 * rows, the head — turns a record into a stack of cards and costs the one
	 * thing the shape was carrying: that these are entries in a logbook, and a
	 * reader can run a finger straight down the date column without the eye
	 * being pulled off it at every corner. A table is not a surface. A row is
	 * not a card. It gets no radius, no fill, no frame and no shadow, and the
	 * declaration is here, explicitly, so that the next person to soften this
	 * page has to delete a sentence rather than fill a gap.
	 */
	border-radius: var(--maars-radius-data);
	color: var(--maars-ink);
}

/*
 * The list furniture is removed only where the group really is a list. The
 * archive's .maars-log is the query wrapper, which is also a child of
 * .maars-main and therefore carries the page gutter from section 3; zeroing
 * padding on every .maars-log stripped that gutter and left the whole log
 * standing 32px to the left of every other band on the page.
 */
:where(ul, ol).maars-log,
.maars-log__entries {
	list-style: none;
	margin-block: 0;
	padding-inline-start: 0;
}

/*
 * The head and the rows share one column template, which is what makes them
 * line up. The doubled class scores 0-2-0 so it beats WordPress's own
 * `.is-layout-flex{display:flex}`, which these blocks also carry — no
 * !important needed, and the inline flex-basis the template writes simply
 * stops applying once the element is a grid.
 */
.maars-log__head.maars-log__head,
.maars-log__row.maars-log__row {
	column-gap: var(--maars-log-gap, clamp(0.75rem, 0.45rem + 1.1vw, 1.5rem));
	display: grid;
	grid-auto-columns: minmax(0, auto);
	/* The fallback is repeated rather than inherited: a row is usable on its
	   own, with no .maars-log ancestor, and an undefined custom property here
	   would drop the whole declaration and quietly unstack the columns. */
	grid-template-columns: var(--maars-log-columns,
		minmax(0, 8rem) minmax(0, 10.5rem) minmax(0, 1fr));
	row-gap: 0.35rem;
	/* Data. See the note on .maars-log above. */
	border-radius: var(--maars-radius-data);
}

.maars-log__head {
	align-items: end;
}

.maars-log__row {
	align-items: stretch;
	/*
	 * 200ms on the one curve, and it changes two things a reader asked for by
	 * putting a pointer on the row. It does NOT lift: a hover lift on every
	 * row is a page where nothing is raised, and a row that rises under a
	 * finger on a touch screen rises under every finger, all the way down.
	 */
	transition: background-color var(--maars-motion) var(--maars-ease),
		box-shadow var(--maars-motion) var(--maars-ease);
}

/*
 * Every field is a full-height cell that centres its own text, so the columns
 * still read across the row and the entry clears the 48px target floor. The
 * alternative — baseline alignment with a 22px line of text in a 55px row —
 * leaves the document link, which IS the row's affordance, as a strip a third
 * of the height the brief requires.
 */
.maars-log__row > * {
	align-items: center;
	display: flex;
	margin-block: 0;
	min-height: var(--maars-target);
	min-width: 0;
}

/* The link fills its cell rather than sitting inside it. */
.maars-log__title a {
	align-items: center;
	display: flex;
	min-height: var(--maars-target);
}

/*
 * Hover and focus. The inset rule is the cursor mark down the left edge of the
 * entry — the same gesture as a finger held against a line in a paper log. It
 * is an inset rule, not a drop shadow; this file ships no shadow beyond a
 * hairline, which is what the brief allows.
 */
.maars-log__row:hover,
.maars-log__row:focus-within {
	background-color: var(--maars-sunk);
	box-shadow: inset 4px 0 0 0 var(--maars-magenta);
}

/* The ruled column head is four quiet labels, not four small headlines. The
   rule under it is drawn by the template and is the only line it needs. */
.maars-log__col {
	align-self: end;
}

/*
 * Each heading is bound to the column it heads rather than relying on document
 * order, so a cell added to the head can never slide the whole rule out of
 * step with the entries beneath it. The mapping belongs with the default
 * --maars-log-columns above: date, type, document.
 */
.maars-log__col-date { grid-column: 1; }
.maars-log__col-type { grid-column: 2; }
.maars-log__col-title { grid-column: 3; }

/*
 * The three fields. The date is the one piece of data on the row — 01 Mar 1999
 * and 12 Jan 2024 occupy the same width, so twenty of them make a column a
 * reader can run a finger down — and the template asks for the data face on it
 * alone. The kind of document is a NOUN: reading face, sentence case, no
 * tracking. Revision 1 set it in Fira Code and in capitals, so "Minutes" read
 * like a file name.
 */
.maars-log__date,
.maars-log__kind {
	color: var(--maars-ink);
	line-height: 1.45;
	margin: 0;
}

.maars-log__date {
	white-space: nowrap;
}

.maars-log__title {
	font-family: var(--maars-font-text);
	margin: 0;
	overflow-wrap: break-word;
}

.maars-log__title a {
	color: var(--maars-navy);
	text-decoration-thickness: max(1px, 0.06em);
}

/*
 * Pagination under a log. The page NUMBERS are figures and the template asks
 * for the data face on those alone; "Newer documents" and "Older documents"
 * are words and stay in the reading face, which is why nothing here sets a
 * family. Every control is a 48px target on both axes.
 */
.maars-log__pagination a,
.maars-log__pagination .page-numbers {
	align-items: center;
	display: inline-flex;
	justify-content: center;
	min-height: var(--maars-target);
	min-width: var(--maars-target);
	padding-inline: 0.6rem;
}

.maars-log__pagination .page-numbers.current {
	background-color: var(--maars-magenta);
	/*
	 * THE ONE PILL ON THE SITE. A page number is a token: a short figure whose
	 * whole geometry is its shape, with no content that could be cut by a
	 * curve. That is what the 999px step is for, and it is spent here and
	 * nowhere else. Nothing was rounded into a pill to use the value up — the
	 * freshness grade is a word in a sentence, the facet count is a bare text
	 * node WordPress gives no element to, and neither is a chip.
	 */
	border-radius: var(--maars-radius-pill);
	color: var(--maars-paper);          /* 8.25:1 */
	font-weight: 700;
	min-width: var(--maars-target);
}

/* ---------------------------------------------------------------------------
 * 5b. The labelled line.
 *
 * Deliberately NOT scoped under .maars-log: the freshness chip is one of these
 * standing on its own, inside a fact card or inline in a figure caption.
 * ------------------------------------------------------------------------- */

.maars-log__line {
	align-items: baseline;
	column-gap: var(--maars-space-3);
	display: flex;
	flex-wrap: wrap;
	margin: 0;
	row-gap: 0.2rem;
}

/* A group of lines is ruled like a log: a hairline between entries, none
   above the first. Components with a frame of their own — the chip — reset
   this in section 6, which is why section 6 comes after this one. */
.maars-log > .maars-log__line + .maars-log__line,
.maars-log__entries > .maars-log__line + .maars-log__line {
	border-block-start: var(--maars-hairline) solid var(--maars-rule-firm);
	padding-block-start: 0.6rem;
}

/*
 * THE QUIET LABEL. This is the replacement for every tracked-out capitalised
 * eyebrow revision 1 carried — STANDING FACTS, NEXT MEETING, MEETING, REPEATER,
 * NET, COMPUTED, SOURCED, THE RECORD — and it is the only label treatment left
 * in this file.
 *
 * Sentence case, because that is how the word is written in the markup and how
 * a reader reads it. No letter-spacing, because tracking is what turned these
 * into signage. 600 rather than 700, because the weight only has to separate
 * the label from its value. 18px, because the floor is the floor: a label is
 * made quiet by case, weight and ink, never by dropping under the size a
 * seventy-year-old can read.
 *
 * .maars-log__col   is the archive's ruled column head: Date, Type, Document.
 * .maars-fieldname  is a field name in a record strip: "Document date".
 * Both are written in sentence case by the template, and neither carries a
 * colour here — the templates set their own, magenta for the record's own
 * column head and ink for a field name, and both are measured.
 */
.maars-log__col,
.maars-fieldname {
	flex: none;
	font-family: var(--maars-font-text);
	/* 18px, and this is the declaration that enforces it: the archive's head
	   carries an inline 1rem, but that is set on the HEAD, and a value a child
	   inherits always loses to one declared on the child itself. */
	font-size: var(--maars-text-label);
	font-weight: 600;
	letter-spacing: normal;
	line-height: 1.4;
	margin: 0;
	text-transform: none;
}

/* A field name is the quieter of the two: it labels one value rather than a
   whole column, so it does not take the extra weight. */
.maars-fieldname {
	font-weight: 400;
}

/*
 * The record strip above a single document: a row of label-over-value cells.
 * Each cell is its own small stack, so the strip reflows by dropping cells to
 * the next line rather than by squeezing any of them.
 */
.maars-log__header {
	align-items: start;
	column-gap: var(--maars-space-5);
	row-gap: 1rem;
}

.maars-log__cell {
	display: grid;
	gap: 0.25rem;
	margin: 0;
	min-width: 0;
}

.maars-log__cell > * {
	margin: 0;
}

/* ---------------------------------------------------------------------------
 * 5c. The log line on a phone.
 *
 * Below 640px a row stops being a row. It does NOT become a squeezed table and
 * it does NOT scroll sideways: each entry becomes a stack, one field per line,
 * and the column head goes away because at that width it has nothing to head.
 * The fields still read in logbook order — date, type, document, file — and
 * each one that is not the title says what it is.
 *
 * The doubled class is the same 0-2-0 trick as above: it has to beat both
 * WordPress's layout rule and the grid set in 5a, and it does it on
 * specificity rather than with !important.
 * ------------------------------------------------------------------------- */

@media (max-width: 39.99em) {
	/* Grid, not block and not a column flexbox: `order` has to work so the
	   document leads the stack, and a grid item ignores the inline flex-basis
	   the template wrote for the wide layout, which in a column flexbox would
	   have become a 9rem-tall date. */
	.maars-log__row.maars-log__row {
		display: grid;
		grid-template-columns: minmax(0, 1fr);
		row-gap: 0.15rem;
	}

	.maars-log__row > * {
		display: block;
		min-height: 0;
		padding-block: 0.15rem;
	}

	/* A field that names itself. The label is drawn from data-label when a
	   template supplies one; the title needs none, because it is the entry. */
	.maars-log__row > [data-label] {
		align-items: baseline;
		column-gap: 0.75rem;
		display: grid;
		grid-template-columns: minmax(0, 7.5rem) minmax(0, 1fr);
	}

	/* Sentence case, meta ink, the reading face: the same quiet label as
	   everywhere else. The template writes data-label="Date", not "DATE". */
	.maars-log__row > [data-label]::before {
		color: var(--maars-meta);
		content: attr(data-label);
		font-family: var(--maars-font-text);
		font-size: var(--maars-text-label);
		font-weight: 600;
		letter-spacing: normal;
		text-transform: none;
	}

	/* The document leads the stack, at reading size. */
	.maars-log__title {
		font-size: var(--maars-text-lede);
		font-weight: 600;
		order: -1;
		padding-block-end: 0.35rem;
	}

	.maars-log__date {
		white-space: normal;
	}

	/* The column head has nothing left to head. Doubled class again, to beat
	   the 0-2-0 grid rule in 5a. */
	.maars-log__head.maars-log__head {
		display: none;
	}

	/* A labelled line stacks too: the field name sits over its value rather
	   than beside it, which is the only thing that fits at 390px. */
	.maars-log__line {
		column-gap: var(--maars-space-2);
	}

	.maars-fieldname {
		flex-basis: 100%;
		min-width: 0;
	}
}

/* ===========================================================================
 * 6. THE FRESHNESS SYSTEM.
 *
 * The reason this site exists. Every standing fact states how far anyone has
 * checked it, and the site must never look current when it is not.
 *
 * WHAT REVISION 1 GOT WRONG HERE. The provenance line was a bordered, coloured
 * chip with a grade word in tracked capitals, a drawn marker box, an
 * explanatory sentence, an internal archive path and a date — four lines of
 * furniture, framed, sitting under a one-line fact and outweighing it. It read
 * as an alarm. It is not an alarm. "Nobody has re-measured the repeater since
 * January 2024" is an honest description of the evidence, and the club is
 * better served by a page that says so quietly than by a page that flashes.
 *
 * WHAT IT IS NOW. One line, in the quiet ink every other note on the site uses:
 *
 *     Sourced. Last checked January 12, 2024 — 977 days ago.
 *
 * THE WORD IS THE SIGNAL. Measured / Sourced / Unverified, spelled out, in the
 * reading face, first on the line. It survives greyscale, deuteranopia, a
 * photocopier and a screen reader, because it is a word. Colour is used for
 * exactly one thing — the stale state — and it is never the only thing saying
 * so, because a stale line also says "Unverified" or prints a date years old.
 * What each grade means is explained once on the page, in a footnote, rather
 * than repeated beside every fact; the plugin puts it in a title attribute for
 * a reader who wants it in place.
 *
 * Emitted by maars_render_fact_block(): .maars-fact, --measured/--sourced/
 * --unverified, .is-stale, __body, __chip, __chip--<grade>, __grade, __detail,
 * __checked, plus data-grade and data-verified-on.
 * ======================================================================== */

/*
 * A fact is not a box. It has no frame, no fill and no rule down its edge: it
 * is a piece of text with a quiet line under it saying how well it is known.
 * Revision 1's dashed left border is gone entirely — a dash reads as
 * unfinished, and it was drawn in the grade's colour, which made the colour
 * the signal after all.
 *
 * Where two facts do sit directly against each other with nothing between
 * them, a hairline separates them. A rule between two rows says what a box
 * round each of them says, and it does not nest.
 */
.maars-fact {
	display: grid;
	gap: var(--maars-space-2);
	margin: 0;
}

.maars-fact + .maars-fact {
	border-block-start: var(--maars-hairline) solid var(--maars-rule);
	margin-block-start: var(--maars-space-3);
	padding-block-start: var(--maars-space-3);
}

.maars-fact__body {
	display: grid;
	gap: var(--maars-space-2);
	margin: 0;
}

.maars-fact__body > :first-child { margin-block-start: 0; }
.maars-fact__body > :last-child { margin-block-end: 0; }

.maars-fact__body p {
	margin: 0;
	max-width: var(--maars-measure);
}

/*
 * THE PROVENANCE LINE. One line, under the fact it grades, in the same quiet
 * ink as any other note on the page: no border, no fill, no padding, no
 * marker. It is furniture. The fact is what the reader came for.
 *
 * 8.66:1 on paper, 8.04:1 on ground, 6.41:1 on lavender — quiet is a matter of
 * weight and size here, never of a grey nobody can read.
 */
.maars-fact__chip {
	color: var(--maars-meta);
	display: block;
	font-family: var(--maars-font-text);
	font-size: var(--maars-text-note);
	font-weight: 400;
	line-height: 1.5;
	margin: 0;
	max-width: var(--maars-measure);
}

/*
 * The grade word: Measured / Sourced / Unverified. It leads the line and it
 * carries the whole meaning on its own, which is why it is spelled out rather
 * than drawn. 600 is enough to make it the first thing read on the line; it is
 * not a different colour from the sentence it starts, because a word that has
 * to be seen in colour to be understood is not a word.
 */
.maars-fact__grade {
	font-weight: 600;
}

.maars-fact__detail,
.maars-fact__checked {
	color: inherit;
	font-weight: 400;
}

/*
 * STALE. The one place colour is spent in this system, and it is never spent
 * alone: a stale line already says "Unverified", or prints a check date years
 * old, or says "No check on record". Rust — 8.31:1 on paper, 7.71:1 on ground,
 * 6.15:1 on lavender — and nothing about it says alarm. There is no red on
 * this site's facts, because "nobody has re-measured it" is not an error.
 *
 * The grade selector is on the chip as well as the fact: the chip appears on
 * its own in the skywave caption, with no .maars-fact wrapper to carry state.
 */
/*
 * FINAL PASS: rust is now spent only where a date has actually aged.
 *
 * The rule below used to colour every unverified chip as well, and on the
 * homepage that was three provenance lines out of three — a hue on everything
 * signals nothing, and rust on every fact read as a page full of warnings. The
 * brief is exact about this: colour it only when genuinely stale.
 *
 * "Unverified / no check on record" is a statement about the evidence, not
 * about decay; blocks.php says so in as many words. So it keeps the quiet meta
 * ink and the word carries it, which is the argument the rest of this section
 * already makes. The attribute selector is the test: maars/fact writes
 * data-verified-on ONLY when a real date was printed, so this fires exactly
 * when a check date exists AND has aged past the threshold — the one case
 * where a reader is being told something the word alone does not say.
 */
.maars-fact.is-stale[data-verified-on] .maars-fact__chip {
	color: var(--maars-rust);
}

/*
 * And on the dark band, where rust measures 2.17:1 and meta 2.08:1, the line
 * takes the band's own quiet ink at 9.73:1. The grade is still the word, so
 * nothing is lost by the hue going away here.
 */
.maars-hero .maars-fact__chip,
.has-ink-background-color .maars-fact__chip {
	color: var(--maars-on-band-meta);
}

/* ---------------------------------------------------------------------------
 * 7. maars/dateline — how long since the Society last filed anything.
 *
 * The old site looked current on 12 September 2026 while its newest content
 * was dated 16 January 2024. This block is the structural fix: the page states
 * its own age before it states anything else. Past the threshold it changes
 * band and colour, but it never becomes a warning box — the sentence is the
 * alarm, and the sentence is enough.
 *
 * Emitted: .maars-dateline, --fresh/.is-fresh, --stale/.is-stale,
 * --empty/.is-empty, __headline, __detail, data-state, data-maars-days,
 * data-maars-threshold. The wrapper is role="status".
 * ------------------------------------------------------------------------- */

/*
 * Not a box. A marked note: one solid rule down the left edge and the text
 * beside it, which is the same device the archive uses for its gaps note, so
 * the site has one way of marking something rather than three. The band it
 * sits in provides the space around it; it provides none of its own.
 */
.maars-dateline {
	--maars-dateline-accent: var(--maars-navy);
	border-inline-start: 4px solid var(--maars-dateline-accent);
	color: var(--maars-ink);
	display: grid;
	gap: var(--maars-space-1);
	margin: 0;
	padding-inline-start: var(--maars-space-3);
}

.maars-dateline__headline {
	color: var(--maars-dateline-accent);
	font-family: var(--maars-font-display);
	font-size: clamp(1.25rem, 1.1rem + 0.7vw, 1.5rem);
	font-weight: 700;
	letter-spacing: -0.01em;
	line-height: 1.25;
	margin: 0;
	max-width: 42ch;
	text-wrap: balance;
}

.maars-dateline__detail {
	color: var(--maars-meta);
	font-size: var(--maars-text-note);
	line-height: 1.55;
	margin: 0;
	max-width: var(--maars-measure);
}

.maars-dateline a {
	color: var(--maars-navy);
}

/* Inside the threshold. Navy, because navy is NOW. 15.23:1 on paper. */
.maars-dateline--fresh,
.maars-dateline.is-fresh {
	--maars-dateline-accent: var(--maars-navy);
}

/*
 * Past the threshold. The rule and the headline go rust, and a wash is laid
 * behind the note so the state survives greyscale without the hue. The edge
 * stays solid: a dashed edge this heavy reads as hazard tape, and this is the
 * site telling the truth about itself, which is the most credible thing on the
 * page. The sentence is the alarm, and the sentence is enough.
 */
.maars-dateline--stale,
.maars-dateline.is-stale {
	--maars-dateline-accent: var(--maars-rust);
	background-color: var(--maars-rust-wash);
	padding-block: var(--maars-space-2);
	padding-inline-end: var(--maars-space-3);
}

.maars-dateline--stale .maars-dateline__detail,
.maars-dateline.is-stale .maars-dateline__detail {
	color: var(--maars-ink);       /* 16.33:1 on the wash */
}

/* Nothing published at all. Neutral: an empty archive is a fact, not a fault. */
.maars-dateline--empty,
.maars-dateline.is-empty {
	--maars-dateline-accent: var(--maars-rule);
}

.maars-dateline--empty .maars-dateline__headline,
.maars-dateline.is-empty .maars-dateline__headline {
	color: var(--maars-ink);
}

/* ---------------------------------------------------------------------------
 * 8. maars/next-meeting — THE ONE THING A VISITOR CAME FOR.
 *
 * Somebody opening this site on the second Thursday of the month came to find
 * out when the meeting is. So it is the largest thing on the page and it is
 * stated once. Revision 1 stated it twice at equal weight — a boxed card
 * reading NEXT MEETING, and a row underneath repeating the second-Friday rule
 * — and set the date in the data face, where "Friday, October 9, 2026 at
 * 6:30 P.M." read like a part number.
 *
 * It is a sentence, so it is in the reading face. It is the answer, so it is
 * set at display size in navy, which is this site's colour for NOW. It is not
 * a row in a log and it is not in a box: there is nothing to separate it from,
 * because it is first.
 *
 * The label is gone from the page and lives in .screen-reader-text, which the
 * plugin writes: a reader hearing the page linearly still gets "Next meeting:"
 * before the date, and nobody has to read the word NEXT MEETING in capitals to
 * understand that a date under a club masthead is a meeting.
 *
 * The rule that computed the date follows it, quietly. It is there so a member
 * can check the arithmetic — that is the whole argument for computing the date
 * instead of typing it — but it is provenance, so it is set like provenance.
 *
 * Emitted: .maars-next-meeting, --unknown/.is-unknown, __date, __rule,
 * __rule-text.
 * ------------------------------------------------------------------------- */

.maars-next-meeting {
	color: var(--maars-ink);
	display: grid;
	gap: var(--maars-space-1);
	margin: 0;
}

/* Navy on paper 15.23:1, on ground 14.14:1. Display face, because this is the
   one line on the page that is allowed to be a headline. */
.maars-next-meeting__date {
	color: var(--maars-navy);
	font-family: var(--maars-font-display);
	font-size: clamp(1.75rem, 1.35rem + 2vw, 2.75rem);
	font-weight: 700;
	letter-spacing: -0.015em;
	line-height: 1.15;
	margin: 0;
	max-width: 20ch;
	text-wrap: balance;
}

/* Provenance, in the same quiet ink as a freshness line, because that is what
   it is: 8.66:1 on paper, 8.04:1 on ground. */
.maars-next-meeting__rule {
	color: var(--maars-meta);
	font-size: var(--maars-text-note);
	line-height: 1.5;
	margin: 0;
	max-width: var(--maars-measure);
}

.maars-next-meeting__rule-text {
	font-family: var(--maars-font-text);
}

/* No date could be computed. Rust, not red, and the sentence the block writes
   says so in words. */
.maars-next-meeting--unknown .maars-next-meeting__date,
.maars-next-meeting.is-unknown .maars-next-meeting__date {
	color: var(--maars-rust);         /* 8.31:1 on paper */
}



/* ---------------------------------------------------------------------------
 * 9. maars/skywave — the WebGL2 propagation scene.
 *
 * The canvas is the one picture on the site and it is a diagram, not a photo:
 * no text ever sits on it. Everything it teaches is also written out in the
 * fallback, which is in the DOM at all times and therefore in the
 * accessibility tree and in `curl`, whether or not WebGL2 exists.
 *
 * Emitted: .maars-skywave, --fallback, __canvas, __controls, __control,
 * __control-band, __control-freq, __caption, __chip, __fallback,
 * __fallback-title, __prose, __noscript, __bands, __band, __band--<id>.
 * ------------------------------------------------------------------------- */

/*
 * No frame and no fill. The canvas is a dark rectangle on a dark band and it
 * is its own edge; a hairline box round it was a box round a box, and on the
 * hero it drew a second frame 12px inside the band's own.
 */
.maars-skywave {
	color: inherit;
	display: grid;
	gap: var(--maars-space-2);
	margin: 0;
	max-width: 100%;
	padding: 0;
}

.maars-skywave__canvas {
	background-color: var(--maars-space);
	/* A major surface: the one picture on the site, and the largest single
	   object on any page. 16px. */
	border-radius: var(--maars-radius-surface);
	display: block;
	height: auto;
	max-width: 100%;
	touch-action: pan-y;    /* drag to orbit, but the page must still scroll */
	width: 100%;
}

/* The canvas is keyboard-operable — arrows orbit, +/- zoom — so it must show
   focus like anything else that answers a key. */
.maars-skywave__canvas:focus-visible {
	outline: 3px solid var(--maars-focus);
	outline-offset: -3px;
}

.maars-skywave__controls {
	display: flex;
	flex-wrap: wrap;
	gap: var(--maars-space-1);
	list-style: none;
	margin: 0;
	padding: 0;
}

.maars-skywave__controls > li {
	margin: 0;
}

/* Buttons, not links: they change what is drawn, they do not navigate. */
.maars-skywave__control {
	background-color: var(--maars-paper);
	border: 2px solid var(--maars-navy);
	/* A control, not a pill: a 48px button holding two lines of type, where a
	   999px corner would eat a quarter of each end and a 16px one would fight
	   the canvas above it. */
	border-radius: var(--maars-radius-control);
	color: var(--maars-navy);
	cursor: pointer;
	/* The band and the frequency inside the button are .maars-fig and carry the
	   data face themselves; the button is not a figure. */
	font-family: var(--maars-font-text);
	font-size: var(--maars-text-note);
	font-variant-numeric: slashed-zero tabular-nums;
	font-weight: 600;
	gap: 0.6ch;
	transition: background-color var(--maars-motion) var(--maars-ease),
		border-color var(--maars-motion) var(--maars-ease),
		color var(--maars-motion) var(--maars-ease);
}

.maars-skywave__control:hover {
	background-color: var(--maars-haze);
	border-color: var(--maars-navy-soft);
}

.maars-skywave__control[aria-pressed="true"] {
	background-color: var(--maars-navy);
	color: var(--maars-paper);
}

/* Not colour alone: the chosen band also carries a marker. The alt text is
   empty so a screen reader is not told about a triangle it cannot use. */
.maars-skywave__control[aria-pressed="true"]::before {
	content: "\25B8\00A0";
}

@supports (content: "a" / "b") {
	.maars-skywave__control[aria-pressed="true"]::before {
		content: "\25B8\00A0" / "";
	}
}

.maars-skywave__control-band {
	font-weight: 700;
}

.maars-skywave__control-freq {
	font-weight: 400;
}

.maars-skywave__caption {
	color: var(--maars-ink);
	display: grid;
	font-family: var(--maars-font-text);
	font-size: var(--maars-text-note);
	gap: var(--maars-space-1);
	justify-items: start;
	line-height: 1.55;
	margin: 0;
	max-width: var(--maars-measure);
}

/* The caption's provenance line is a span in the markup and a line in the
   layout. Everything else about it is .maars-fact__chip. */
.maars-skywave__chip {
	display: block;
}

/* The scene in words. Always in the DOM; shown when WebGL2 is missing. */
.maars-skywave__fallback {
	display: none;
}

.maars-skywave--fallback .maars-skywave__canvas,
.maars-skywave--fallback .maars-skywave__controls {
	display: none;
}

.maars-skywave--fallback .maars-skywave__fallback,
.maars-skywave__noscript {
	background-color: var(--maars-haze);
	/* A filled panel is a surface. It carries no shadow: it is set INTO the
	   dark band, not lifted off it, and a shadow on a dark ground is a value
	   step there is no value left to take. */
	border-radius: var(--maars-radius-surface);
	color: var(--maars-ink);
	display: grid;
	font-size: var(--maars-text-body);
	gap: var(--maars-space-2);
	line-height: var(--maars-leading);
	padding: var(--maars-space-3);
}

.maars-skywave noscript {
	display: block;
}

.maars-skywave__fallback-title {
	font-weight: 700;
	margin: 0;
	max-width: 62ch;
}

.maars-skywave__prose {
	margin: 0;
	max-width: var(--maars-measure);
}

/*
 * The static band list. It is the log line again, in its smallest form: four
 * records, hairline between them, figures in the data face. Not buttons —
 * nothing can be switched here, so nothing may look switchable.
 */
.maars-skywave__bands {
	display: grid;
	list-style: none;
	margin: 0;
	padding: 0;
}

/* A list of four records with a hairline between them: the log line in its
   smallest form, and the only rules in the scene. */
.maars-skywave__band {
	font-size: var(--maars-text-note);
	line-height: 1.5;
	margin: 0;
	padding-block: var(--maars-space-2);
}

.maars-skywave__band + .maars-skywave__band {
	border-block-start: var(--maars-hairline) solid var(--maars-rule-firm);
}

/* 80, 40 and 20 metres all do the same thing: the wave comes back. */
.maars-skywave__band--80m,
.maars-skywave__band--40m,
.maars-skywave__band--20m {
	color: var(--maars-ink);            /* 13.34:1 on lavender */
}

/* 2 m is the teaching point — line of sight, no skip — so it is the one entry
   that reads differently, and it reads differently in weight, not only in hue. */
.maars-skywave__band--2m {
	color: var(--maars-magenta);        /* 6.10:1 on lavender */
	font-weight: 600;
}

.maars-skywave__band[data-current="1"] {
	font-weight: 700;
}

.maars-skywave__band[data-current="1"]::after {
	content: "\00A0\2190\00A0shown";
	font-weight: 400;
}

@supports (content: "a" / "b") {
	.maars-skywave__band[data-current="1"]::after {
		content: "\00A0\2190\00A0shown" / "";
	}
}

/* ===========================================================================
 * 10. THE MASTHEAD — THE BAND IS A RECEIVER.
 *
 * THE IDEA. The analogue dial is gone. What every licensed amateur reads now,
 * whether they came up on a Drake in 1974 or bought an RTL-SDR dongle last
 * month, is a WATERFALL: the spectrum trace with the heat map scrolling under
 * it, the face of an IC-7300 and the output of a twenty-dollar dongle. It is
 * the one picture that says "radio" to a thirty-year-old and a ninety-year-old
 * in the same second, and it is soft and smooth because that is physically
 * what it is — a continuous map of signal strength with no edge anywhere in
 * it. Nobody had to round its corners to make it feel modern.
 *
 * So the masthead is not a banner and not a logo lockup. It is a slim
 * receiver, tuned to 147.255 MHz — the Society's own machine, not a stock
 * frequency — with the identity resting in it.
 *
 * AND IT IS NOT THE PAGE'S BOLD MOMENT. The WebGL2 propagation scene in
 * section 9 is, it stays that, and a masthead that competed with it would have
 * cost the site the one large thing it is allowed. This band is ambient
 * chrome: 150–190px, about twelve frames a second, aria-hidden, nothing to
 * click. Under prefers-reduced-motion the script draws one still frame; under
 * no script at all the fallback gradient in 10a is what a reader sees, which
 * is a masthead and not an error.
 *
 * ---------------------------------------------------------------------------
 * WHAT THIS SECTION STYLES, and it is exactly what maars_render_masthead_block()
 * emits — no name here is invented and none is left over:
 *
 *   .maars-masthead              the band, full-bleed, faded top and bottom
 *     + --fallback               no script, or no 2D context: canvas removed
 *     canvas.maars-masthead__canvas     aria-hidden, decorative, inert
 *     .maars-masthead__inner            the column: gutter and cap live here
 *       .maars-masthead__identity       the real text resting in the band
 *         .maars-masthead__wordmark     MAARS, the link home, display face
 *         .maars-masthead__call         KSØMAN, data face, inside .maars-fig
 *         .maars-masthead__society      the long name, body face
 *       .maars-masthead__caption        below the band, on the page ground
 *         .maars-masthead__place        Manhattan, Kansas
 *         .maars-masthead__note         "…is a drawing…not a live receiver."
 *
 * THE DIVISION OF LABOUR WITH waterfall.js, stated once so neither side does
 * the other's job twice. The SCRIPT owns the inside of the picture: it fades
 * its own top and bottom edges (14px and 26px), and it clears the band behind
 * `.maars-masthead__identity` with a 64px feather so the identity has calm
 * ground under it. This STYLESHEET owns the floor that clearing reveals, the
 * fallback that stands in when there is no script, the type, and a scrim that
 * guarantees the contrast floor even if the clearing never happens. Nothing
 * here masks the canvas: the script already did, and two fades on one edge is
 * how an edge stops being soft.
 * ======================================================================== */

/* ---------------------------------------------------------------------------
 * 10a. The band, the floor, and the fallback — which are one thing.
 *
 * The canvas is painted over a floor drawn in CSS. That floor is also the
 * fallback, which is why there is no separate "no canvas" picture to keep in
 * step with anything: no script, script not yet run, and script running are
 * the same image getting progressively more detailed, rather than three
 * different failures.
 * ------------------------------------------------------------------------- */

.maars-masthead {
	/*
	 * 150–190px, the brief's band. Slim on a phone, never a hero. The block
	 * passes the same bound to the canvas as a height attribute so the strip
	 * is never wildly wrong in the moment before layout.
	 */
	--maars-scope-height: clamp(150px, 9.5rem + 2vw, 190px);
	/* How far the identity's last line sits above the bottom of the band. The
	   scrim below is written against this same name, so the veil ends exactly
	   where the text ends and the two cannot drift apart. */
	--maars-scope-pad: 1.6rem;

	/*
	 * THE FLOOR AND THE FALLBACK. A dark navy field with one broad bloom of
	 * signal at 62% of the width, where 147.255 sits in the 500kHz span the
	 * canvas draws. That is a gradient carrying a meaning — this is what
	 * signal strength looks like — which is the only kind this file allows;
	 * there is no decorative wash anywhere in this stylesheet.
	 */
	--maars-scope-fallback:
		radial-gradient(42% 104% at 62% 96%,
			rgba(126, 146, 255, 0.42) 0%,
			rgba(64, 72, 200, 0.22) 44%,
			rgba(8, 12, 56, 0) 78%),
		radial-gradient(86% 76% at 16% 4%,
			rgba(60, 76, 186, 0.2) 0%,
			rgba(8, 12, 56, 0) 72%),
		linear-gradient(to bottom, #0a1044 0%, #070c33 48%, #04061f 100%);

	/*
	 * BOTH VERTICAL EDGES DISSOLVE. The band does not end in a line, because a
	 * line is the one thing a waterfall never has. The fade is written in
	 * pixels rather than percentages and matches waterfall.js's own FADE_TOP
	 * and FADE_BOTTOM exactly, so the floor and the picture on top of it go
	 * out together instead of leaving a rim of one behind the other.
	 */
	--maars-scope-fade: linear-gradient(to bottom,
		rgba(0, 0, 0, 0) 0,
		rgba(0, 0, 0, 1) 14px,
		rgba(0, 0, 0, 1) calc(100% - 26px),
		rgba(0, 0, 0, 0) 100%);

	/*
	 * Transparent, not a colour: the band dissolves into whatever the header
	 * is painted with, which is the paper preset and therefore correct in both
	 * colour schemes with no rule inside a media query.
	 */
	background-color: transparent;
	isolation: isolate;
	position: relative;
}

/* The floor. A layer rather than a background on the band itself, so the fade
   can mask it and the header's own surface shows through at both edges. */
.maars-masthead::before {
	background-image: var(--maars-scope-fallback);
	content: "";
	height: var(--maars-scope-height);
	inset-block-start: 0;
	/* Bleed to the viewport without dragging the column with it. */
	inset-inline-start: calc(50% - 50vw);
	inline-size: 100vw;
	-webkit-mask-image: var(--maars-scope-fade);
	mask-image: var(--maars-scope-fade);
	pointer-events: none;
	position: absolute;
	z-index: 0;
}

/*
 * THE READING SCRIM, and the arithmetic behind its one load-bearing number.
 *
 * A waterfall is a heat map: its pixels run from a near-black noise floor to
 * the palest thing in its ramp, and nothing in CSS knows which one is behind a
 * given letter at a given second. Contrast against the AVERAGE pixel is not a
 * measurement, it is a hope. So the identity is measured against the WORST
 * pixel the map can emit — the top of waterfall.js's noise ramp, #E8EAF6, the
 * site's own haze — and made to clear 4.5:1 against that.
 *
 * Composited at alpha a, veil rgb(5, 8, 31) over #E8EAF6 (L 0.8266):
 *
 *     a = 0.45  ->  L 0.216   white 3.95:1   FAILS
 *     a = 0.55  ->  L 0.158   white 5.04:1
 *     a = 0.58  ->  L 0.138   white 5.59:1   <- the weakest point under a glyph
 *     a = 0.62  ->  L 0.114   white 6.40:1   <- the floor the scrim holds
 *
 * Every glyph on this band therefore clears 4.5:1 against a pixel the
 * instrument would have to be saturated to produce, which is the only honest
 * way to make the claim on a surface whose content nobody controls.
 *
 * It is a SOFTENING, not a panel. It ramps in through the trace region, holds
 * across the waterfall where the identity sits, and goes out again exactly at
 * --maars-scope-pad, which is where the last line of type ends. There is no
 * edge on it in any direction.
 *
 * With waterfall.js mounted this is mostly redundant — the script has already
 * cleared the band behind the identity — and over that cleared floor it is
 * imperceptible, a shade of navy on a shade of navy. It is here for the case
 * where the clearing is not configured, and for the seconds before it is.
 */
.maars-masthead::after {
	background-image: linear-gradient(to bottom,
		rgba(var(--maars-scope-veil), 0) 0%,
		rgba(var(--maars-scope-veil), 0.1) 12%,
		rgba(var(--maars-scope-veil), 0.46) 20%,
		rgba(var(--maars-scope-veil), 0.62) 27%,
		rgba(var(--maars-scope-veil), 0.62) calc(100% - var(--maars-scope-pad)),
		rgba(var(--maars-scope-veil), 0) 100%);
	content: "";
	height: var(--maars-scope-height);
	inset-block-start: 0;
	inset-inline: 0;
	pointer-events: none;
	position: absolute;
	z-index: 2;
}

/*
 * The canvas. Decorative, aria-hidden, inert: no reader has to hit it, drag it
 * or tab to it. It is NOT masked here — waterfall.js fades its own edges and
 * clears its own hole behind the identity, and a second fade laid over the
 * first is how a soft edge turns back into a visible one.
 */
.maars-masthead__canvas {
	display: block;
	height: var(--maars-scope-height);
	inset-block-start: 0;
	inset-inline-start: calc(50% - 50vw);
	pointer-events: none;
	position: absolute;
	width: 100vw;
	z-index: 1;
}

/* No script, or no 2D context. The floor underneath is already the picture. */
.maars-masthead--fallback .maars-masthead__canvas {
	display: none;
}

/* ---------------------------------------------------------------------------
 * 10b. The column inside the band.
 *
 * The band is full-bleed; its CONTENT is not. This is where the gutter and the
 * column cap that section 3 took off the header come back, so the callsign
 * starts on the same left edge as the meeting date, the archive's first column
 * and the colophon. Measured at 1440px: 176px, every one of them.
 * ------------------------------------------------------------------------- */

.maars-masthead__inner {
	/* Clear the band, then return to the page column. The masthead itself is
	   full bleed so the instrument has no margin; its inner content must line
	   up with every other heading on the site, not with the bleed edge. */
	padding-block-start: var(--maars-scope-height);
	margin-inline: auto;
	max-width: var(--wp--style--global--wide-size, 1180px);
	padding-inline: var(--maars-gutter, 1.25rem);
	margin-inline: auto;
	max-width: var(--maars-column);
	padding-inline: var(--maars-gutter);
	position: relative;
	width: 100%;
	z-index: 3;
}

/*
 * The identity reserves the band's own height and sits at the bottom of it, in
 * the waterfall, with the trace running clear above. It is real text: the site
 * this one replaces set the club's name in an unlabelled GIF, so the Society
 * was invisible to a screen reader and to search for twenty years.
 */
.maars-masthead__identity {
	align-content: end;
	display: grid;
	gap: 0.1rem;
	justify-items: start;
	min-height: 0;
	/* Clear the band. The canvas and the floor are absolutely positioned across
	   the top of the masthead at --maars-scope-height, so the identity has to
	   start below them. (The diagram above names a .maars-masthead__inner that
	   the emitted markup does not have, which is why this lives here.) */
	padding-block-start: calc(var(--maars-scope-height) + 1.1rem);
	/*
	 * Line up with the page column. The masthead bleeds edge to edge so the
	 * instrument has no margin, but the identity must start where every other
	 * heading starts. Measured on the live site: the header's container is
	 * 1152px wide with 32px of its own padding, which puts content at x=176 in
	 * a 1440px window, while the callsign sat at x=0.
	 *
	 * The theme's wide-size and content-size both resolve to 100% here, so they
	 * cannot express the column; --maars-column carries it instead and this box
	 * is given the same container as main rather than a padding guess.
	 */
	box-sizing: border-box;
	inline-size: 100%;
	margin-inline: auto;
	max-inline-size: var(--maars-column, 1152px);
	padding-inline: var(--maars-gutter);
	/* Back into the page column. The masthead is full bleed so the instrument
	   has no margin, but the identity must line up with every other heading on
	   the site rather than with the bleed edge. (.maars-masthead__inner is
	   named in the diagram above but is not in the emitted markup, so the
	   column lives here, on the element that actually exists.) */
	/*
	 * THE IDENTITY SITS UNDER THE BAND, NOT ON IT.
	 *
	 * Two earlier attempts put it inside the instrument: white text over a hole
	 * the script erased (measured 1.13:1, white on near-white) and then a
	 * translucent plate, which smeared the spectrum behind it and collided with
	 * the frequency ticks. Both were solving a problem that only existed
	 * because the text was in the picture.
	 *
	 * The band is now a clean instrument, edge to edge, with nothing over it.
	 * The identity reads beneath it on the page ground, where navy is 13.99:1
	 * and cannot drift. The masthead is still a receiver; this is its caption.
	 */
	background: none;
	box-shadow: none;
	/* NOT a padding-block shorthand: it sits after the band-clearing
	   padding-block-start above and would silently reset it, which is how the
	   identity ended up drawn on top of the waterfall. */
	padding-block-end: 0;
	/*
	 * SHRINK TO THE WORDS. This is the one declaration that decides whether
	 * there is a waterfall on this page at all.
	 *
	 * waterfall.js clears the band behind whatever `clearSelector` finds — the
	 * block points it at this element — so this box's WIDTH is the width of
	 * the hole. Left as a block, it is the whole 1,152px column, and the
	 * script dutifully erased the entire instrument: rendered at 1440px the
	 * band came back a flat navy slab with a scrap of trace showing at each
	 * end and the carrier at 62% gone completely. With max-content it is 475px
	 * of type, the hole is the type plus its 64px feather, and the carrier —
	 * the one thing the band exists to show — is in the clear.
	 *
	 * max-width caps it again at 390px, where max-content is wider than the
	 * screen and the Society's name has to be allowed to wrap.
	 */
	max-width: 100%;
	width: max-content;
}

/*
 * MAARS. The quietest of the three lines and the only one that is a link: it
 * is the way home, and it is the club's initials rather than its identity. 18px
 * floor, 48px target, display face.
 */
.maars-masthead .maars-masthead__wordmark {
	color: var(--maars-on-scope);
	font-family: var(--maars-font-display);
	font-size: clamp(1.125rem, 1.05rem + 0.35vw, 1.3125rem);
	font-weight: 600;
	letter-spacing: 0.02em;
	line-height: 1.2;
	margin: 0;
}

.maars-masthead__wordmark a {
	align-items: center;
	color: inherit;
	display: inline-flex;
	min-height: var(--maars-target);
	text-decoration: none;
	transition: color var(--maars-motion) var(--maars-ease);
}

.maars-masthead__wordmark a:hover,
.maars-masthead__wordmark a:focus-visible {
	text-decoration: underline;
	text-decoration-thickness: max(2px, 0.08em);
	text-underline-offset: 0.18em;
}

/*
 * KSØMAN, and the whole reason Fira Code is in this system: its zero is
 * natively slashed, which is how the Society writes its own callsign and how
 * every logbook in the club writes it. Manrope's zero is not. Platypi's is
 * not. The block wraps the callsign in .maars-fig, which is what actually
 * applies the face — section 5 owns that rule and this owns the size.
 *
 * Prose never gets this face. A slashed zero in a sentence is a part number.
 */
.maars-masthead .maars-masthead__call {
	color: var(--maars-on-scope);
	font-size: clamp(1.875rem, 1.25rem + 2.1vw, 2.75rem);
	font-weight: 600;
	letter-spacing: 0.005em;
	line-height: 1.08;
	margin: 0;
}

/* The Society's name. The reading face, at lede size, and white: it is the
   club's name, not a subtitle, and a grey line under a large heading is the
   first thing to disappear on an iPad in a church basement. */
.maars-masthead .maars-masthead__society {
	color: var(--maars-on-scope);
	font-family: var(--maars-font-text);
	font-size: var(--maars-text-lede);
	font-weight: 500;
	line-height: 1.25;
	margin: 0;
	max-width: 34ch;
}

/*
 * THE BAND IS A DRAWING, AND THE SITE SAYS SO.
 *
 * This is the honest voice the rest of the site is built on, applied to the
 * masthead: a site whose whole argument is that it will never look current
 * when it is not cannot open with an instrument pretending to read the air.
 * So the note stays, and it is placed BELOW the band, on the page ground,
 * where its contrast is a fixed measurable number (meta on ground, 7.95:1)
 * rather than a claim about a surface that changes every 80ms.
 */
.maars-masthead__caption {
	column-gap: var(--maars-space-4);
	display: flex;
	flex-wrap: wrap;
	padding-block: var(--maars-space-2) 0;
	row-gap: 0.15rem;
}

.maars-masthead__place {
	color: var(--maars-ink);
	font-size: var(--maars-text-note);
	line-height: 1.5;
	margin: 0;
}

.maars-masthead__note {
	color: var(--maars-meta);           /* 7.95:1 on ground */
	flex: 1 1 24rem;
	font-size: var(--maars-text-note);
	line-height: 1.5;
	margin: 0;
	max-width: var(--maars-measure);
}

/*
 * The band is dark in both colour schemes, so a focus ring on it cannot be
 * navy: navy on this floor measures 1.2:1, and a ring nobody can see is not a
 * ring. Overriding the two focus TOKENS on the component — not inside a media
 * query — is the same device the hero uses in section 11, for the same reason.
 * It is scoped to the identity so the caption below, which sits on the page
 * ground, keeps the navy ring every other link on the site has.
 */
.maars-masthead__identity {
	--maars-focus: var(--maars-on-scope);
	--maars-focus-halo: var(--maars-scope-floor);
}

/* ---------------------------------------------------------------------------
 * 10c. The navigation, on its own quiet row beneath the band.
 *
 * Below the band, never inside it. Seven links laid over a moving heat map is
 * the failure mode of every hero image ever shipped: the contrast changes
 * underneath the words frame by frame, so either the links get a scrim — a box,
 * on the one surface in this design that has no edges — or somewhere in the
 * animation they become unreadable. Down here they sit on the page ground,
 * navy on #F4F5FA at 13.99:1, and nothing moves behind them.
 *
 * AND THE PLACE WHERE A SHADOW WAS NOT USED. This row is the most obvious
 * candidate on the site for a soft drop shadow: it is a navigation bar, and
 * every template kit in the world gives one a shadow. It does not get one,
 * because it is not raised — it is part of the page, level with it, and a
 * shadow under it would be a drawing of a depth that is not there. The shadow
 * token is spent in 10d and section 11 on the two things that genuinely float.
 * ------------------------------------------------------------------------- */

.maars-navbar {
	border-block-start: 0;
	margin-block-start: 0;
	padding-block: var(--maars-space-1);
}

.maars-nav {
	font-family: var(--maars-font-text);
	font-weight: 700;
}

.maars-nav a {
	border-radius: var(--maars-radius-control);
	color: var(--maars-navy);
	text-decoration: none;
	/* 200ms, one curve, and only on a change the reader asked for. */
	transition: color var(--maars-motion) var(--maars-ease);
}

.maars-nav a:hover,
.maars-nav a:focus-visible {
	color: var(--maars-navy-soft);
	text-decoration: underline;
	text-decoration-thickness: max(2px, 0.08em);
}

/* ---------------------------------------------------------------------------
 * 10d. The mobile navigation overlay — the one panel on this site that floats.
 *
 * Core's overlay menu is a real dialog: it is drawn over the page, the page is
 * still there underneath it, and it can be dismissed. That is what "raised"
 * means, and it is the only surface in this stylesheet that earns the brief's
 * shadow. 16px, because a full panel is a major surface, and navy-tinted
 * rather than grey, because grey under a navy-and-white page is the tell.
 * ------------------------------------------------------------------------- */

.maars-nav .wp-block-navigation__responsive-container.is-menu-open {
	border-radius: var(--maars-radius-surface);
	box-shadow: var(--maars-shadow-lifted);
}

.maars-nav .wp-block-navigation__responsive-container-open,
.maars-nav .wp-block-navigation__responsive-container-close {
	border-radius: var(--maars-radius-control);
	transition: background-color var(--maars-motion) var(--maars-ease),
		color var(--maars-motion) var(--maars-ease);
}

/* The hairline that closes the whole header. The band above it dissolves into
   the page rather than ending in a line, so this is the only rule the region
   draws, and it is drawn in the token so it follows the colour scheme. */
.maars-header {
	border-block-end: var(--maars-hairline) solid var(--maars-rule);
}

/* ---------------------------------------------------------------------------
 * 11. Page furniture: main, sections, the hero, news, the archive teaser.
 * ------------------------------------------------------------------------- */

.maars-site-header,
.maars-site-footer {
	display: block;
}

.maars-main {
	display: block;
	padding-block-end: var(--maars-space-5);
}

.maars-front,
.maars-archive,
.maars-index {
	display: block;
}

.maars-section__title {
	margin-block: 0 0.75rem;
}

/*
 * There is no eyebrow rule here, and that is deliberate. Revision 1 had one on
 * nearly every block — STANDING FACTS, NEXT MEETING, THE RECORD — and not one
 * of them said anything the heading underneath it did not. The best eyebrow is
 * no eyebrow, so the class is gone from the templates and the rule is gone
 * from here.
 */

.maars-archive__masthead {
	display: block;
}

/*
 * THE HERO — the one dark band on the site.
 *
 * Its surface is a token, not a preset, so it stays dark in both colour
 * schemes. See the note at the end of this file for why that needs one
 * !important and why it is the only way to do it without styling a component
 * inside a media query.
 */
.maars-hero {
	background-color: var(--maars-band);
	border-block: var(--maars-hairline) solid var(--maars-band-edge);
	color: var(--maars-on-band);
	/* On a dark band a navy focus ring measures 1.18:1 and is not a ring.
	   Overriding the token here — not in a media query — keeps the rule
	   visible on the only surface where navy fails. */
	--maars-focus: var(--maars-on-band-link);
	--maars-focus-halo: var(--maars-band);
	padding-block: var(--maars-space-5);
}

/* h2 scale, not h1: the largest thing on the front page is the meeting date,
   and a section heading that outran it would be arguing with the brief. */
.maars-hero__title {
	color: inherit;
	font-family: var(--maars-font-display);
	font-size: var(--maars-text-h2);
	font-weight: 700;
	margin-block: 0;
	max-width: 22ch;
}

.maars-hero__lede {
	color: inherit;
	font-size: var(--maars-text-lede);
	line-height: 1.5;
	margin-block: 0.75rem 0;
	max-width: var(--maars-measure);
}

.maars-hero__stage {
	margin-block-start: var(--maars-space-3);
}

/*
 * Only the caption sits on the band. The fallback and the noscript panels are
 * lavender panels of their own and carry ink; colouring their prose for the
 * band would have put white on lavender at 1.36:1 for exactly the readers who
 * have no WebGL2 and no JavaScript — the ones who can least afford it.
 */
.maars-hero .maars-skywave__caption {
	color: var(--maars-on-band);
}

/*
 * The bands. One step off the scale, the same one for every band, and the only
 * vertical space between two sections. Revision 1 gave each band its own
 * clamp() and then let the components inside them add margins of their own on
 * top; that is how a homepage reaches 6,363px.
 */
.maars-about,
.maars-news,
.maars-archive-teaser {
	padding-block: var(--maars-space-5);
}

/* ---------------------------------------------------------------------------
 * 11b. The front page.
 *
 * Revision 1 opened with a lavender panel holding three white cards, each card
 * holding a bordered chip, each row labelled MEETING or REPEATER or NET in
 * tracked capitals, and the second-Friday rule stated twice. Three frames deep
 * and 6,363px tall.
 *
 * Revision 2 is two bands and no boxes at all. The lede answers the question
 * that brought the visitor — when is the meeting — and on the air states the
 * two standing facts as what they are: a specification and a schedule, ruled
 * apart, each carrying its own provenance line. Lavender is not spent on
 * either; it is left for the panels that need a surface of their own.
 * ------------------------------------------------------------------------- */

/* THE LEDE. The meeting, and the least furniture that can carry it. */
.maars-lede {
	color: var(--maars-ink);
	padding-block: var(--maars-space-5);
}

/*
 * The headline is deliberately subordinate to the date under it. A member who
 * already knows what MAARS is should be able to read past this line, and the
 * template sets it at 1.375–1.75rem to make that possible.
 */
.maars-lede__title {
	margin: 0;
	max-width: 34ch;
}

/* The venue. Body-large, because it is the second half of the answer. */
.maars-lede__venue {
	line-height: 1.5;
	margin: 0;
	max-width: var(--maars-measure);
}

/* What is known about the venue, and what a member should do about it. */
.maars-lede__note {
	color: var(--maars-meta);           /* 8.66:1 on paper, 8.04:1 on ground */
	font-size: var(--maars-text-note);
	line-height: 1.55;
	margin: 0;
	max-width: var(--maars-measure);
}

/* ON THE AIR. Two entries, a hairline between them, no box around either. */
.maars-onair {
	color: var(--maars-ink);
	padding-block: var(--maars-space-5);
}

/* Size and leading are the template's, which sets them inline; the heading
   conventions in section 2 own the face. This owns the space around it. */
.maars-onair__name {
	margin: 0;
}

.maars-onair__prose {
	line-height: var(--maars-leading);
	margin: 0;
	max-width: var(--maars-measure);
}

/*
 * THE SPECIFICATION. Revision 1 wrote this as one sentence stitched out of
 * middle dots: "KSØMAN · 147.255 MHz out, 147.855 MHz in · +600 kHz · CTCSS
 * 88.5 Hz on both ends · open to all licensed amateurs." A specification is
 * not a sentence. It is a list of labelled values, and it is set as one: the
 * field name in quiet ink on the left, the figure beside it, a hairline
 * between rows and no box anywhere.
 *
 * The label is an inline-block with a minimum width rather than a grid column,
 * because the value is a run of text and <code> elements inside one list item
 * — a grid would make five items out of it and lose the sentence.
 */
.maars-spec {
	border-radius: var(--maars-radius-data);
	display: grid;
	list-style: none;
	margin: 0;
	padding: 0;
}

.maars-spec li {
	line-height: 1.5;
	margin: 0;
	max-width: var(--maars-measure);
	padding-block: var(--maars-space-1);
}

/* Structure, not decoration: this rule is what separates one field of the
   repeater's specification from the next, so it takes the firmer hairline. */
.maars-spec li + li {
	border-block-start: var(--maars-hairline) solid var(--maars-rule-firm);
}

.maars-spec strong {
	color: var(--maars-meta);           /* the quiet label, 8.66:1 on paper */
	display: inline-block;
	font-size: var(--maars-text-label);
	font-weight: 600;
	min-width: 7.5rem;
	padding-inline-end: var(--maars-space-2);
}

/*
 * On a phone the label column is a line of its own. 7.5rem of the 390px screen
 * left about 180px for the value, so "147.855 MHz, a +600 kHz offset" broke
 * after the frequency and the remainder hung back at the left margin, under
 * the label, reading as a fifth field.
 */
@media (max-width: 29.99em) {
	.maars-spec strong {
		display: block;
		min-width: 0;
		padding-inline-end: 0;
	}
}

/*
 * The separator between two entries. WordPress's own separator is a 2px border
 * at 40% opacity, which is a grey nobody chose; this is the same hairline
 * every other rule on the site is drawn with.
 */
.maars-hairline {
	background-color: transparent;
	border: 0;
	border-block-start: var(--maars-hairline) solid var(--maars-rule);
	height: 0;
	margin-block: var(--maars-space-3);
	opacity: 1;
	width: 100%;
}

/*
 * THE MECHANISM, EXPLAINED ONCE. Revision 1 explained what the grades mean in
 * the lede, again in a panel footnote, and again in a bordered chip beside
 * every single fact. This is the one telling, at the foot of the facts, where
 * a reader who has just met a check date can use it.
 */
.maars-footnote {
	color: var(--maars-meta);
	font-size: var(--maars-text-note);
	line-height: 1.55;
	margin: 0;
	max-width: var(--maars-measure);
}

.maars-about__actions {
	margin-block-start: var(--maars-space-3);
}

/*
 * BUTTONS. 10px, because a button is a control; 48px tall; no gradient,
 * because a gradient on a button carries no meaning and this file only draws
 * the ones that do.
 *
 * It does take the shadow, and it is one of only two things on the site that
 * do. A button is the one element a reader is invited to PRESS, and a press is
 * a claim about depth: the navy-tinted shadow is what makes that claim, and
 * lifting it on hover is what answers it. The lift is 200ms on the one curve
 * and it moves nothing — the shadow deepens, the button stays exactly where it
 * was, so no line of type shifts under a reader's finger.
 */
:where(.maars-main, .maars-footer) .wp-block-button__link {
	border-radius: var(--maars-radius-control);
	box-shadow: var(--maars-shadow);
	font-family: var(--maars-font-text);
	font-size: var(--maars-text-body);
	font-weight: 700;
	text-decoration: none;
	transition: background-color var(--maars-motion) var(--maars-ease),
		box-shadow var(--maars-motion) var(--maars-ease);
}

:where(.maars-main, .maars-footer) .wp-block-button__link:hover {
	box-shadow: var(--maars-shadow-lifted);
	text-decoration: underline;
	text-decoration-thickness: max(2px, 0.09em);
}

.maars-news__list {
	gap: var(--maars-space-4);
}

.maars-news__date,
.maars-entry__updated {
	color: var(--maars-meta);
	font-size: var(--maars-text-note);
	line-height: 1.5;
}

.maars-news__more {
	font-weight: 600;
	margin-block-start: var(--maars-space-3);
}

/* An empty list says so in words rather than leaving a tidy gap a reader
   mistakes for activity. The words are enough; it needs no box. */
.maars-empty {
	line-height: var(--maars-leading);
}

.maars-empty__title {
	font-weight: 700;
	margin-block: 0 var(--maars-space-1);
}

.maars-empty__search {
	margin-block-start: var(--maars-space-3);
}

/* ---------------------------------------------------------------------------
 * 12. The archive — the record. Magenta lives here.
 * ------------------------------------------------------------------------- */

.maars-archive__lede,
.maars-index__termdesc {
	font-size: var(--maars-text-lede);
	line-height: 1.5;
	max-width: var(--maars-measure);
}

/* The gaps are part of the record and are not papered over. */
.maars-archive__gaps {
	border-inline-start: 4px solid var(--maars-magenta);
	line-height: var(--maars-leading);
	max-width: var(--maars-measure);
	padding-inline-start: 1rem;
}

/*
 * NARROWING THE LIST. Revision 1 fenced the search field and the two facet
 * lists inside a bordered panel, so the archive opened with a box holding
 * boxes above a list. It is a ruled band now, like every other band on the
 * page: the rule above it is drawn by the template and is all the separation
 * it needs.
 */
.maars-archive__narrow {
	padding-block-end: var(--maars-space-4);
}

.maars-filters__title {
	margin-block: 0 var(--maars-space-2);
}

.maars-filters__facets {
	margin-block-start: var(--maars-space-3);
}

.maars-facet__title {
	margin-block: 0 var(--maars-space-1);
}

/*
 * THE TERM LISTS, and the bug they carried.
 *
 * WordPress's categories block writes the count as a bare text node AFTER the
 * link: <li><a>Meeting Minutes</a> (3)</li>. Revision 1 gave that anchor
 * `display: flex` to make it a 48px target, which made it a block, which threw
 * the count onto a line of its own — so the list read
 *
 *     Minutes
 *     (3)
 *
 * and a reader scanning four document types saw eight items. THE ANCHOR MUST
 * NEVER BE THE FLEX CONTAINER. The row is the <li>, the anchor stretches
 * inside it, and the count sits at the end of the row where it belongs.
 *
 * The list is held to about 22rem so the count lands near its term rather than
 * a column away, and the ruled rows make it read as a column of records. Above
 * 48em the 26-year list runs in two columns, so it is 13 rows tall instead of
 * 26 — a facet list nobody can see the bottom of is a facet list nobody uses.
 */
.maars-termlist {
	border-radius: var(--maars-radius-data);
	display: grid;
	font-family: var(--maars-font-text);
	list-style: none;
	margin: 0;
	max-width: 22rem;
	padding: 0;
}

.maars-termlist li {
	align-items: center;
	border-block-end: var(--maars-hairline) solid var(--maars-rule-firm);
	border-radius: var(--maars-radius-data);
	column-gap: var(--maars-space-3);
	display: flex;
	justify-content: space-between;
	margin: 0;
	min-height: var(--maars-target);
}

.maars-termlist a {
	align-items: center;
	align-self: stretch;
	color: var(--maars-navy);
	display: flex;
	flex: 1 1 auto;
	transition: color var(--maars-motion) var(--maars-ease);
}

.maars-termlist a:hover {
	color: var(--maars-navy-soft);
	text-decoration-thickness: max(2px, 0.11em);
}

/*
 * The count keeps the row's own ink, and there is no rule for it here because
 * there is nothing to hang one on: WordPress writes it as a bare text node
 * inside the <li>, with no element and no class round it, so it cannot be
 * selected at all. It is 18px on the page ground at 16.74:1, it sits at the
 * end of its row, and .maars-termlist below puts it in tabular figures so
 * (160) and (6) line up down the column. A rule that cannot match is worse
 * than no rule, because the next person believes it.
 */

@media (min-width: 48em) {
	.maars-termlist--year {
		column-gap: var(--maars-space-4);
		/* TWO. Twelve was a typo and it was catastrophic: each <li> became a
		   1/12th-width cell, so every "1998 (4)" wrapped one character to a
		   line and the whole facet shattered into a field of loose digits.
		   Rendered and looked at, not inferred. */
		grid-template-columns: repeat(2, minmax(0, 1fr));
		max-width: 34rem;
	}
}

.maars-facet__note {
	color: var(--maars-meta);
	font-size: var(--maars-text-note);
	line-height: 1.5;
	margin-block-start: var(--maars-space-2);
	max-width: 46ch;
}

.maars-filters__search {
	margin-block-end: var(--maars-space-3);
}

.maars-filters__search .wp-block-search__input {
	border: 2px solid var(--maars-navy);
	border-radius: var(--maars-radius-control);
	background-color: var(--maars-paper);
	color: var(--maars-ink);
	padding: 0.6rem 0.75rem;
	transition: border-color var(--maars-motion) var(--maars-ease);
}

.maars-filters__search .wp-block-search__input:hover {
	border-color: var(--maars-navy-soft);
}

.maars-filters__search .wp-block-search__button {
	background-color: var(--maars-navy);
	border: 2px solid var(--maars-navy);
	border-radius: var(--maars-radius-control);
	box-shadow: var(--maars-shadow);
	color: var(--maars-paper);
	font-family: var(--maars-font-text);
	font-weight: 700;
	padding-inline: 1rem;
	transition: background-color var(--maars-motion) var(--maars-ease),
		border-color var(--maars-motion) var(--maars-ease),
		box-shadow var(--maars-motion) var(--maars-ease);
}

.maars-filters__search .wp-block-search__button:hover {
	background-color: var(--maars-navy-soft);
	border-color: var(--maars-navy-soft);
	box-shadow: var(--maars-shadow-lifted);
}

/*
 * A document in the list. Where a template emits .maars-log this is the log
 * line proper; where it still emits the stacked article, the article keeps the
 * same manners — a hairline between entries, the figures in the data face —
 * so the two never look like two different sites.
 */
.maars-archive__loop,
.maars-index__loop,
.maars-news__loop {
	display: block;
}

.maars-archive__list,
.maars-index__list,
.maars-news__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

/*
 * An entry in a list. The archive's .maars-doc is also a .maars-log__row and
 * draws its own hairline in the template, so the rule here is written only for
 * the entries that are not log lines — the news and index loops.
 *
 * A LIST ITEM IN A LOOP IS NOT PROSE. Section 2 caps every li inside main at
 * the reading measure, which is right for a bulleted list in an article and
 * wrong for a query loop, where WordPress wraps each entry in an <li>: it
 * cropped every row of the archive to 68ch and left a dead gutter down the
 * right of all fourteen pages. A row fills its list.
 */
.maars-log li,
.maars-log__entries > li,
.wp-block-post-template > li {
	max-width: 100%;
}

.maars-entry {
	border-block-end: var(--maars-hairline) solid var(--maars-rule-firm);
	border-radius: var(--maars-radius-data);
	padding-block: var(--maars-space-3);
}

.maars-entry:last-child {
	border-block-end: 0;
}

.maars-doc {
	margin: 0;
}

/* The dateline row on a news or index entry: a field name, the date it was
   published, a field name, the date it was last touched. Figures stay tabular
   so the two dates line up; neither is given the data face, because a date
   written out in words is a sentence. */
.maars-entry__when {
	row-gap: var(--maars-space-1);
}

.maars-entry__date,
.maars-entry__updated {
	margin: 0;
}

.maars-entry__title,
.maars-index__title,
.maars-archive__title {
	margin-block: 0 0.4rem;
}

/* A picture is a surface — the one place a 16px corner is simply what the
   object looks like, rather than a decision about it. */
.maars-entry__image img {
	border-radius: var(--maars-radius-surface);
}

.maars-entry__body {
	line-height: var(--maars-leading);
	max-width: var(--maars-measure);
}

/* How the list was made, said once, at the foot of it. */
.maars-archive__provenance {
	color: var(--maars-meta);           /* 8.04:1 on ground */
	line-height: var(--maars-leading);
	margin-block-start: var(--maars-space-4);
	max-width: var(--maars-measure);
}

/* The way into the record: a band like the two above it, separated by a rule
   rather than fenced off in a card. Magenta carries the heading and the button
   inside it, which is all the marking it needs. */
.maars-archive-teaser {
	border-block-start: var(--maars-hairline) solid var(--maars-rule);
	color: var(--maars-ink);
}

/* ---------------------------------------------------------------------------
 * 13. A single document from the record.
 * ------------------------------------------------------------------------- */

.maars-single-doc {
	display: block;
}

.maars-breadcrumb,
.maars-doc-record__back {
	font-weight: 600;
	margin-block: 0 1rem;
}

.maars-doc-record {
	display: block;
}

.maars-doc-record__title {
	margin-block: 0.35rem 1rem;
}

/* The header strip: when the document is dated, what it is, and what year of
   the record it belongs to. Three facts, above the text, every time. It is a
   .maars-log__header, so its cells come from section 5. */
.maars-doc-record__meta {
	display: flex;
}

/*
 * The document's date and its kind are values, and they are set as values: the
 * reading face, sentence case, no tracking. Revision 1 put both in Fira Code
 * under capitalised labels, so "Minutes" read like a file name. The year is a
 * figure and carries .maars-fig, which is what puts it — and only it — in the
 * data face.
 */
.maars-doc-record__date,
.maars-doc-record__kind,
.maars-doc-record__yearterm {
	margin: 0;
}

.maars-doc-record__kind a,
.maars-doc-record__yearterm a {
	color: var(--maars-magenta);        /* 8.25:1 on paper — the record */
}

.maars-doc-record__vouch {
	line-height: var(--maars-leading);
	margin: 0;
	max-width: var(--maars-measure);
}

.maars-doc-record__body {
	line-height: var(--maars-leading);
}

.maars-doc-record__body > * {
	max-width: var(--maars-measure);
}

.maars-doc-record__image img {
	border-radius: var(--maars-radius-surface);
}

.maars-doc-record__rule {
	background-color: var(--maars-rule);
	border: 0;
	height: 1px;
	margin-block: var(--maars-space-5);
}

/* Older and newer, named the way the archive names them: "previous" in a list
   that runs newest first is the OLDER document, and saying so is the whole
   point of these two labels. */
.maars-doc-nav {
	font-weight: 600;
	gap: 1rem;
}

.maars-doc-nav__older,
.maars-doc-nav__newer {
	flex: 1 1 16rem;
	min-width: 0;
}

.maars-doc-nav__newer {
	text-align: end;
}

.maars-doc-nav a {
	align-items: center;
	display: inline-flex;
	min-height: var(--maars-target);
}

/* The original file is the authority; the transcription is only how you find
   it. Magenta, because this is the record talking. */
.maars-original {
	border-radius: var(--maars-radius-surface);
	display: block;
	margin-block: var(--maars-space-5);
}

.maars-original__title {
	margin: 0;
}

/* Three fields — file, format, size — as one log line. A dash is an entry in a
   log, and it means no entry; nothing here pretends to a figure it has not
   got. */
.maars-original__file {
	color: var(--maars-ink);
	line-height: 1.4;
	margin: 0;
	overflow-wrap: anywhere;
}

.maars-original__actions {
	margin-block: 1.25rem 0;
}

.maars-original__get .wp-block-button__link {
	min-height: var(--maars-target);
}

.maars-original__note {
	line-height: var(--maars-leading);
	margin-block-start: 1.25rem;
	max-width: var(--maars-measure);
}

/* ---------------------------------------------------------------------------
 * 14. The footer.
 * ------------------------------------------------------------------------- */

.maars-footer {
	border-block-start: var(--maars-hairline) solid var(--maars-rule);
	padding-block: var(--maars-space-5);
}

/*
 * The constitutional note. Not boilerplate: Article III makes the reflector
 * the official organ, so a silent website is not a governance failure and must
 * not pretend to be the channel of record.
 */
/*
 * REVISION 2, FINAL PASS — the lavender plate is gone.
 *
 * This was the last tinted panel on the site, 1,088 x 245px of pale lavender
 * at the foot of every page, and it was the second-boldest thing on any
 * screen after the propagation scene. The brief allows one bold element and
 * this was not it.
 *
 * Nothing is lost by removing it. A quotation is already marked as one by the
 * quotation marks round it, by the display face it is set in and by the
 * citation underneath naming Article III and the date it was revised. What is
 * left is the same device the archive's gap note uses: a rule down the edge,
 * turned ninety degrees from the hairlines that separate rows. The site now
 * has exactly one filled block on it, and it is the scene.
 */
.maars-official-organ {
	border-inline-start: 3px solid var(--maars-navy);
	color: var(--maars-ink);
	display: grid;
	gap: var(--maars-space-1);
	margin-block-end: var(--maars-space-4);
}

.maars-official-organ__quote {
	font-family: var(--maars-font-display);
	font-size: var(--maars-text-lede);
	font-weight: 600;
	line-height: 1.4;
	margin: 0;
	max-width: 52ch;
}

.maars-official-organ__cite {
	line-height: var(--maars-leading);
	margin: 0;
	max-width: var(--maars-measure);
}

/*
 * The Society as a postal body: name, callsign, county, and nothing that
 * identifies a person. The site this one replaces published four officers'
 * e-mail addresses, seven telephone numbers and a home address; none of it
 * came across, and the footer says so in words rather than leaving a gap.
 */
.maars-postal {
	display: grid;
	gap: 0;
	margin-block-start: var(--maars-space-4);
}

/* Name, callsign, county: three lines, because they are three facts. Revision
   1 joined them with middle dots. */
.maars-postal__identity,
.maars-postal__call,
.maars-postal__place {
	line-height: 1.45;
	margin: 0;
	max-width: var(--maars-measure);
}

.maars-postal__place {
	color: var(--maars-meta);           /* 8.04:1 on ground */
}

.maars-footer-columns {
	gap: var(--maars-space-4) var(--maars-space-5);
	margin-block-start: 0;
}

.maars-footer__heading {
	margin-block: 0 var(--maars-space-2);
}

.maars-footer__list {
	display: grid;
	gap: 0.1rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.maars-footer__list li {
	margin: 0;
}

.maars-footer__list a {
	align-items: center;
	display: flex;
	min-height: var(--maars-target);
	padding-block: 0.25rem;
}

.maars-footer__note {
	color: var(--maars-meta);
	line-height: var(--maars-leading);
	margin-block-start: var(--maars-space-2);
	max-width: 46ch;
}

.maars-footer__rule {
	background-color: var(--maars-rule);
	border: 0;
	height: 1px;
	margin-block: var(--maars-space-5);
}

/*
 * The last-reviewed line, set by a person at review time. The old site carried
 * "last verified 10/23/09" for fifteen years, which is the whole lesson in one
 * string: a stale date that is visible is worth more than a fresh page that is
 * lying.
 */
.maars-lastreviewed {
	display: grid;
	gap: var(--maars-space-1);
}

.maars-lastreviewed__line {
	line-height: var(--maars-leading);
	margin: 0;
	max-width: var(--maars-measure);
}

.maars-lastreviewed__copy {
	color: var(--maars-meta);
	line-height: var(--maars-leading);
	margin: 0;
	max-width: var(--maars-measure);
}

/* ---------------------------------------------------------------------------
 * 15. Print. The record has to survive a photocopier and a club binder.
 * ------------------------------------------------------------------------- */

@media print {
	:root body {
		background-color: #ffffff;
		color: #000000;
		font-size: 12pt;
	}

	.maars-dateline,
	.maars-archive-filters,
	.maars-original,
	.maars-log {
		background-color: transparent;
		border-color: #000000;
	}

	/* The provenance line prints as what it is on screen: one quiet sentence,
	   in black, under the fact. The grade word carries it, so nothing is lost
	   on a photocopier. */
	.maars-fact__chip,
	.maars-next-meeting__rule {
		color: #000000;
	}

	.maars-spec li + li,
	.maars-entry,
	.maars-log__row {
		border-color: #000000;
	}

	.maars-skywave__canvas,
	.maars-skywave__controls,
	.maars-doc-nav,
	.maars-archive-filters {
		display: none;
	}

	.maars-skywave__fallback {
		display: grid;
	}
}

/* ===========================================================================
 * 16. DARK SURFACES — headings and links. The fixed bug, kept fixed.
 * ---------------------------------------------------------------------------
 * theme.json sets elements.heading.text and elements.link.text to navy, which
 * WordPress emits as `:root :where(h1..h6){color:navy}`. An element rule like
 * that beats the colour a heading would otherwise inherit from its section, so
 * inside a dark group the h1 came out navy #00008C on ink #14142B: a measured
 * 1.18:1, far under the 3.0 that large text needs, and effectively invisible.
 *
 * That is the same failure as the white-on-white links on the site this one
 * replaces, so it is fixed at the surface rather than patched per block: any
 * heading on a dark surface follows the surface's own text colour, and links
 * there go lavender, which is legible on ink — 13.34:1 in light, 14.37:1 in
 * dark. The link colour is a TOKEN, not the lavender preset: the preset
 * inverts to a dark band in dark mode, which would have put a dark link back
 * on a dark surface and re-opened the bug from the other side.
 *
 * Specificity note: WordPress's rule scores 0-1-0 because :where() counts as
 * zero, so a single class plus an element name wins without !important.
 * ======================================================================== */

.has-ink-background-color :is(h1, h2, h3, h4, h5, h6),
.maars-hero :is(h1, h2, h3, h4, h5, h6),
.has-ink-background-color .wp-block-heading,
.maars-hero .wp-block-heading {
	color: inherit;
}

.has-ink-background-color a:not(.wp-element-button):not(.wp-block-button__link),
.maars-hero a:not(.wp-element-button):not(.wp-block-button__link) {
	color: var(--maars-on-band-link);
}

.has-ink-background-color a:not(.wp-element-button):hover,
.maars-hero a:not(.wp-element-button):hover {
	color: var(--maars-on-band);
}

/*
 * And the band itself.
 *
 * THE LAST OF THE THREE !important DECLARATIONS, and the reason:
 * WordPress prints its preset colour utilities as
 * `.has-ink-background-color{background-color:var(--wp--preset--color--ink) !important}`.
 * In dark mode the ink preset legitimately becomes #EDEDF7 — it is the text
 * colour, and swapping it with paper is what keeps every has-ink-color /
 * has-paper-background-color pairing correct without a single component rule
 * inside a media query. But it also turns the hero into a near-white slab on a
 * dark page. The brief forbids styling a component inside the dark-mode media
 * query, so the fix is a token — --maars-band, defined in both schemes — and
 * the only way a token can beat a WordPress !important utility is to carry one
 * of its own at higher specificity. 0-2-0 with !important, on exactly one
 * component, stated here.
 *
 * In light mode this is a no-op: --maars-band IS #191933, the ink preset.
 */
.maars-hero.has-ink-background-color {
	background-color: var(--maars-band) !important;
	color: var(--maars-on-band) !important;
}

/* ===========================================================================
 * 17. THE FRONT PAGE AT READING WIDTH — and the last of defect 8.
 *
 * Every band on this site is capped at the reading measure, 68ch, because a
 * 1,088px line is not readable. On a phone that cap does nothing; on a 1,440px
 * screen the column is 1,152px wide and the prose in it is 660px wide, so 42%
 * of the page is empty down its whole length and the page runs on for two
 * screens more than it has words for. Revision 1 answered the empty space by
 * growing the type and the padding, which is how the homepage reached 6,363px.
 * The answer is to put two bands where one was.
 *
 * TWO, never three. Half of 1,088px is about 48 characters, which is inside
 * the 45–75ch a person actually reads in; a third is 30 characters, which is a
 * newspaper column, and this page is read by people in their eighties on an
 * iPad. Legibility is the floor and the floor does not move to save pixels.
 *
 * The two are 5:7, not 6:6, and the wide side changes hands between the rows.
 * Prose needs the measure and a date or a list of titles does not: the
 * repeater's paragraphs and the founding story get seven twelfths (about 53
 * characters), the meeting date and the news list get five. Measured over the
 * whole page that one ratio is worth 190px against an even split, and it is
 * worth it in the other direction too — nothing on the page is now set
 * narrower than about 38 characters.
 *
 * WHAT SITS BESIDE WHAT is an editorial decision, not a packing problem:
 *
 *   row 1  the meeting  |  what is on the air. Both are "now", and they are
 *          the two things a member opens this site to check. The meeting stays
 *          in the first column and first in source order, at 44px against the
 *          26px heading beside it, so it is still the largest thing and still
 *          the first thing under the masthead. Beside it, the repeater's four
 *          figures are now on the same screen instead of a scroll below it.
 *   row 2  the scene, full width. It is the one bold element on the site and
 *          the one thing here that is better for being wide.
 *   row 3  the founding  |  recent news. Two quiet blocks of equal weight.
 *   row 4  the archive, full width, last, in its own colour. It is the largest
 *          thing the Society owns and it is the page's closing sentence.
 *
 * Below 64em none of this applies and the page is the single column it has
 * always been: at that width two columns of 48ch do not fit either.
 *
 * The lines BETWEEN the columns are rules, not boxes — the same hairline that
 * separates rows, turned ninety degrees. .maars-onair carries a top border
 * from the template for the single-column case; beside the meeting that border
 * would draw a line over one half of one row, so here it becomes the vertical
 * rule between the two. Nothing gains an edge it did not already have.
 * ------------------------------------------------------------------------- */

@media (min-width: 64em) {
	.maars-front {
		align-items: start;
		column-gap: var(--maars-space-5);
		display: grid;
		grid-template-columns: repeat(12, minmax(0, 1fr));
	}

	.maars-front > .maars-lede {
		grid-column: 1 / 6;
	}

	.maars-front > .maars-onair {
		border-block-start: 0;
		border-inline-start: var(--maars-hairline) solid var(--maars-rule);
		grid-column: 6 / -1;
		padding-inline-start: var(--maars-space-5);
	}

	.maars-front > .maars-hero {
		grid-column: 1 / -1;
	}

	.maars-front > .maars-about {
		border-block-start: var(--maars-hairline) solid var(--maars-rule);
		grid-column: 1 / 8;
	}

	.maars-front > .maars-news {
		border-block-start: var(--maars-hairline) solid var(--maars-rule);
		border-inline-start: var(--maars-hairline) solid var(--maars-rule);
		grid-column: 8 / -1;
		padding-inline-start: var(--maars-space-5);
	}

	.maars-front > .maars-archive-teaser {
		border-block-start: var(--maars-hairline) solid var(--maars-rule);
		grid-column: 1 / -1;
	}
}

/* ---------------------------------------------------------------------------
   Masthead identity: the column, settled.
   ---------------------------------------------------------------------------
   Measured on a real WordPress 7.1 render: the identity computed to
   inline-size 730px with margin-left 355px, because the box was shrink-to-fit
   and `margin-inline: auto` then centred it. The callsign landed at x=387 while
   the navigation began at x=176, so the masthead read as indented from the rest
   of the site.

   An earlier rule in this file set `max-width: max-content` to keep the box
   narrow, back when waterfall.js erased a hole in the band behind it. The band
   is no longer erased, so that constraint outlived its reason and is what makes
   the box shrink. Rather than hunt every interacting declaration, the final
   geometry is stated once, here, at the end of the cascade.

   1152px is --maars-column (72rem), the same column `main` uses: centred in a
   1440px window it starts at 144, and the 32px inner padding puts the text at
   176 — level with the navigation and with every heading below it.
--------------------------------------------------------------------------- */
.maars-masthead__identity {
	margin-inline: auto;
	max-width: var(--maars-column);
	width: min(100%, var(--maars-column));
}

