/*
// © Copyright 1990-2026 Toptronic® Ltd, all rights reserved; no part of
// this document may be reproduced, modified or stored in a retrieval system,
// or transmitted in any form or by any means, electronic, mechanical,
// photocopying, recording or otherwise, without the prior written permission
// of Toptronic Limited. For copyright inquiries: jacques@toptronic.com
 */
/*
 * PLWS :: Plazdiez Website - Session 0104 layer (glossary page presentation)
 * Project: Paul Lambourn Web Site (PLWS) - www.plazdiez.co.za
 * Generated/Updated on: 2026-09-17T14:11:41+10:00
 * Audience: Jacques (hardware/C bg), Ryan (14), Ava (9), Students (15-23),
 *           and the Master's-level reader who wants the "why".
 *
 * WHAT THIS FILE IS: the presentation upgrade of the Glossary page only.
 * Linked on glossary.html AFTER css/styles_010.css; it only ADDS to that
 * layer. New file, not an edit, because /css/* is served immutable for a
 * year and a returning visitor keeps the old bytes.
 *
 * THE EIGHT JOBS: 1 hero cover, 2 toolbar card (sticky >=900px only),
 * 3 glossary table, 4 Customers Talks, 5 anchors/highlight/pulse/back-to-top,
 * 6 phones (card layout kept, no sideways scrollbar), 7 print, 8 reduced
 * motion.
 *
 * COLOURS: a colour is only valid for the surface it was chosen for.
 * --clr-steel (#8a94a6) is for DARK surfaces (3.06:1 on white fails AA);
 * --gl-muted (#5f6774, 5.71:1 on white) is for LIGHT surfaces. On the new
 * ink hero panel they swap: steel is 5.92:1 on ink, gl-muted only 3.17:1.
 * Every pair below is checked against its surface; the ratio is written
 * beside the rule.
 * -- Jacques: choose the colour for the surface, like a material spec.
 * -- Ava: dark words on light paper, light words on dark ink.
 * -- Ryan: contrast ratio = how far apart two colours are in brightness;
 *    4.5:1 is the minimum for ordinary text.
 */

/* ============ SECTION 0: FIVE LOCAL VALUES ============
   styles_010.css already defines --gl-muted and --gl-rule; this block adds
   only new names. -- Ryan: named constants - change one line, every rule
   that uses it changes with it. */
:root {
  --gl-ink-soft: #2b2f36;                 /* body copy on white: 13.44:1 */
  --gl-pill-bg: #f4f5f5;                  /* opaque pill: keeps 5.23:1 on a tinted row */
  --gl-tint-hover: rgba(232,160,32,0.10); /* amber wash: text still 16.85:1 / 5.31:1 */
  --gl-tint-mark: rgba(232,160,32,0.30);  /* search highlight: ink on it 14.31:1 */
  --gl-tint-flash: rgba(232,160,32,0.25); /* deep-link pulse: even --gl-muted stays 4.70:1 */
}

/* ============ SECTION 1: THE HERO BAND (the cover) ============
   The shared .page-hero is a quiet centred band; here it becomes an opaque
   ink panel with an amber rule, so every colour inside is judged against
   #14161a, not the page background. */
.gl-hero {
  max-width: none;                 /* the shared .page-hero is capped at 800px */
  padding: var(--sp-2xl) var(--sp-lg);
  background: var(--clr-ink);
  color: var(--clr-paper);         /* 16.95:1 on ink */
  border-top: 4px solid var(--clr-brand);
  border-bottom: none;             /* the amber rule replaces the shared hairline */
  border-radius: var(--radius-lg);
}
.gl-hero .eyebrow {                /* amber letterspaced capitals: 8.18:1 on ink */
  color: var(--clr-brand);
  font-size: 0.78rem;
  letter-spacing: 0.2em;
}
/* clamp(): 1.9rem..2.9rem, else 4vw. The plain 2.4rem line is the 2017
   fallback (an engine without clamp() drops the second declaration). */
.gl-hero .gl-hero-title {
  font-size: 2.4rem;
  font-size: clamp(1.9rem, 4vw, 2.9rem);
  line-height: 1.12;
  color: var(--clr-paper);
  text-wrap: balance;              /* ignored cleanly on engines without it */
}
/* 62ch is the measure the eye follows. opacity back to 1: the shared
   .page-hero p dims to 85%, fine on paper, not wanted on the ink panel. */
.gl-hero .gl-hero-lead {
  max-width: 62ch;
  margin: 0 auto;
  font-size: 1.05rem;
  line-height: 1.65;
  opacity: 1;
  color: var(--clr-paper);         /* 16.95:1 */
}
/* The note is the quiet voice: --clr-steel (5.92:1 on ink), NOT --gl-muted
   (only 3.17:1 on this panel - it was chosen for white). */
.gl-hero .gl-hero-note {
  max-width: 62ch;
  margin: var(--sp-md) auto 0;
  font-size: 0.9rem;
  line-height: 1.55;
  opacity: 1;
  color: var(--clr-steel);         /* 5.92:1 on ink */
}

/* ============ SECTION 2: THE TOOLBAR CARD ============
   One input, one Clear, the category pills and the live count, all on ONE
   white card. -- Jacques: a front panel - one plate, all the controls. */
.gl-bar {
  background: #fff;
  border: 1px solid var(--gl-rule);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--sp-md);
}
/* The magnifier is two CSS shapes, not a picture: a data-URI image would be
   an external resource and the page CSP is default-src 'self'. A 13px ring
   is the lens, a 2px bar rotated 45deg the handle; both are out of the click
   path so tapping the lens still focuses the field. The lens sits at a fixed
   15px from the top because the 44px input is the first flex line, so its
   centre is always y=22. */
.gl-search-row { position: relative; }
.gl-search-row::before,
.gl-search-row::after { content: ""; position: absolute; pointer-events: none; }
.gl-search-row::before {           /* the round lens */
  left: 17px; top: 15px; width: 13px; height: 13px;
  border: 2px solid var(--gl-muted); border-radius: 50%;
}
.gl-search-row::after {            /* the handle */
  left: 28px; top: 26px; width: 2px; height: 8px;
  background: var(--gl-muted);
  transform: rotate(-45deg); transform-origin: top left;
}
/* One hairline edge at rest; amber edge + a hard ink ring when focused. The
   RING is ink on purpose: amber on white is only 2.22:1, not enough for a
   focus indicator, so amber carries the border and halo, ink the ring. */
.gl-search {
  padding-left: 42px;
  border-width: 1px;
  border-color: rgba(20,22,26,0.18);
  transition: border-color var(--trans-fast), box-shadow var(--trans-fast);
}
.gl-search:focus,
.gl-search:focus-visible {
  outline: 2px solid var(--clr-ink); outline-offset: 2px;
  border-color: var(--clr-brand);
  box-shadow: 0 0 0 5px rgba(232,160,32,0.30);
}
/* The browser's own "x" inside the field would duplicate the Clear button. */
.gl-search::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
/* Clear stays a quiet outline button; hover adds the amber wash, the keyboard
   ring is ink so it is always visible. */
.gl-clear {
  border-width: 1px;
  border-radius: var(--radius-sm);
  transition: border-color var(--trans-fast), background-color var(--trans-fast);
}
.gl-clear:hover { background: var(--gl-tint-hover); }
.gl-clear:focus-visible { outline: 2px solid var(--clr-ink); outline-offset: 2px; }
/* Pills: styles_010.css draws the pill and fills the pressed state with ink
   (paper on ink, 16.95:1); this layer adds the amber hover wash and the ring. */
.gl-chip {
  background: #fff;
  border-color: rgba(20,22,26,0.16);
  transition: background-color var(--trans-fast), border-color var(--trans-fast);
}
.gl-chip:hover { background: var(--gl-tint-hover); }
.gl-chip:focus-visible { outline: 2px solid var(--clr-ink); outline-offset: 2px; }
/* The live count rides on the same line as the pills on a wide screen, which
   keeps the pinned card one line shorter. */
.gl-count { font-size: 0.8rem; line-height: 1.4; color: var(--gl-muted); } /* 5.71:1 */

/* --- the card sticks on a wide screen only ------------------------------
   Below 900px it scrolls with the page (a pinned panel would eat a phone
   screen). z-index 5 puts it above the table's sticky header (z-index 2 in
   styles_010.css). Sticky is bounded by its own parent, the .gl-tools
   section, so it releases the top as soon as that section scrolls past - it
   does not follow the reader down 181 rows. */
@media screen and (min-width: 900px) {
  .gl-bar {
    position: sticky;
    top: var(--header-height-shrink, 56px);
    z-index: 5;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px var(--sp-md);
  }
  .gl-search-row { flex: 1 1 100%; margin-bottom: 0; }
  .gl-chips { flex: 1 1 auto; }
  .gl-count { flex: 0 0 auto; margin-top: 0; }
}
/* Engines from before flex "gap" (2017) glue the lines together, so the
   spacing is put back as margins - the same trick styles_004.css uses. */
@supports not (gap: 1rem) {
  @media screen and (min-width: 900px) {
    .gl-search-row { margin-bottom: 10px; }
    .gl-count { margin-left: var(--sp-md); }
  }
}

/* ============ SECTION 3: THE GLOSSARY TABLE ============
   A quiet reference table: white ground, hairline rules, a whisper of zebra,
   amber only where the reader's attention already is. */
.gl-table { background: #fff; border: 1px solid var(--gl-rule); box-shadow: var(--shadow-sm); }
.gl-table caption { padding: 0 0 var(--sp-md); font-size: 0.85rem; color: var(--gl-muted); } /* 5.34:1 on paper */
/* Taller rows and hairline rules: 14px keeps a 181-row list scannable while
   every row stays an easy thumb target. */
.gl-table th,
.gl-table td { padding: 14px 16px; border-bottom: 1px solid var(--gl-rule); }
.gl-table tbody tr:last-child th,
.gl-table tbody tr:last-child td { border-bottom: none; }
/* The sticky header keeps the ink ground from styles_010.css and gains a 2px
   amber underline drawn with box-shadow, because a border on a sticky cell
   inside a border-collapse table is not painted reliably by every engine. */
.gl-table thead th {
  padding-top: 12px; padding-bottom: 12px;
  font-size: 0.76rem; letter-spacing: 0.1em;
  box-shadow: inset 0 -2px 0 var(--clr-brand);
}
.gl-table tbody tr:nth-child(even) { background: rgba(20,22,26,0.03); } /* zebra: gl-muted still 5.37:1 */
/* The term cell. Archivo is self-hosted in ONE weight (700), so asking for
   more would only smear a synthetic bold - emphasis comes from size and the
   amber marker instead. */
.gl-term { font-size: 1.02rem; font-weight: 700; color: var(--clr-ink); }
.gl-mean { max-width: 62ch; line-height: 1.5; color: var(--gl-ink-soft); } /* 13.44:1 */
.gl-cat-col { color: var(--gl-muted); font-size: 0.9rem; }
/* The category as a pill. The background is OPAQUE on purpose: a see-through
   pill would change colour on a tinted row and could drop --gl-muted below
   4.5:1. It wraps to a second line rather than widening the cell, so a long
   label can never force a sideways scrollbar. */
.gl-cat-pill {
  display: inline-block;
  padding: 3px 10px;
  font-size: 0.76rem; font-weight: 600; letter-spacing: 0.03em;
  color: var(--gl-muted);          /* 5.23:1 on the pill background */
  background: var(--gl-pill-bg);
  border: 1px solid rgba(20,22,26,0.10);
  border-radius: 999px;
}
/* Hover and keyboard focus share one look. The pointer case is gated behind
   (hover: hover) so a touch screen does not keep a stuck highlight. */
@media (hover: hover) {
  .gl-table tbody tr:hover { background: var(--gl-tint-hover); }
  .gl-table tbody tr:hover .gl-term { box-shadow: inset 3px 0 0 var(--clr-brand); }
  .gl-table tbody tr:hover .gl-anchor { opacity: 1; }
}
.gl-table tbody tr:focus-within { background: var(--gl-tint-hover); }
.gl-table tbody tr:focus-within .gl-term { box-shadow: inset 3px 0 0 var(--clr-brand); }
.gl-table tbody tr:focus-within .gl-anchor { opacity: 1; }
/* A deep link lands the row clear of the sticky header. Same value on the
   phone, where nothing is sticky - harmless there. */
.gl-table tbody tr {
  scroll-margin-top: calc(var(--header-height-shrink, 56px) + var(--sp-lg));
  transition: background-color var(--trans-fast);
}
.gl-empty { color: var(--gl-muted); }

/* ============ SECTION 4: "CUSTOMERS TALKS" ============
   The second table answers a different question, so it is marked as a
   different thing: an amber rule over its heading and a filled-amber header
   row instead of the ink one. Text on amber is near-black (8.18:1). */
.gl-talks-head { max-width: 70ch; border-top: 4px solid var(--clr-brand); padding-top: var(--sp-lg); }
.gl-talks .gl-table thead th {
  background: var(--clr-brand);
  color: var(--clr-brand-ink);     /* 8.18:1 */
  box-shadow: inset 0 -2px 0 rgba(20,22,26,0.18);
}
/* The quote column. A large opening quotation mark is drawn with ::before,
   never typed into the page: a typed character would need translating and
   could be mangled on the way through a dictionary. The mark is a CSS escape
   (\201C), so this file stays ASCII. Below 820px the phone card layout prints
   the column label in this same position with a more specific rule, so the
   mark gives way to the label. */
.gl-talk-asked { position: relative; padding-left: 22px; font-style: italic; color: var(--clr-ink); }
.gl-talk-asked::before {
  content: "\201C";
  position: absolute; left: 0; top: -0.15em;
  font-family: var(--font-heading);
  font-size: 2.4rem; line-height: 1; font-style: normal;
  color: var(--clr-brand-deep, #8f5d00);   /* 5.62:1 on white */
}
.gl-talk-meant { font-weight: 600; }   /* the decoding line reads one step heavier */
/* styles_010.css already gives this column the amber left rule and the arrow
   marker; this layer only makes the rule a little firmer and the body text a
   shade softer than pure ink. */
.gl-talk-demand { border-left-width: 4px; padding-left: 16px; color: var(--gl-ink-soft); } /* 13.44:1 */

/* ============ SECTION 5: THE SMALL PARTS ============
   The copy-link anchor, the search highlight, the deep-link pulse and the
   back-to-top button. */

/* --- the copy-link anchor, inside each term cell -------------------------
   A real button with an aria-label, so it is in the accessibility tree from
   the start; the CSS only decides whether the eye sees it. opacity - never
   visibility or display - is what hides it: the other two would take it out
   of the tab order and there would be no way to reach it without a mouse.
   -- Ava: a little door handle that only appears when you walk up to the row
      - but a keyboard visitor can always find it.
   30x30px is comfortably above the 24x24px minimum of WCAG 2.5.8. */
.gl-anchor {
  position: relative;
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 30px; height: 30px;
  margin-left: var(--sp-sm); padding: 0;
  vertical-align: middle;
  color: var(--gl-muted);          /* 5.71:1 on white - icons need only 3:1 */
  background: none;
  border: 1px solid rgba(20,22,26,0.14);
  border-radius: var(--radius-sm);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--trans-fast), color var(--trans-fast), border-color var(--trans-fast);
}
/* The mark is two CSS rings: a chain link, drawn in the current colour, with
   no character that any translation could break.
   -- Ryan: two rounded rectangles turned 45 degrees, half a link apart. */
.gl-anchor::before,
.gl-anchor::after {
  content: ""; position: absolute;
  width: 11px; height: 7px;
  border: 2px solid currentColor; border-radius: 4px;
  transform: rotate(-45deg);
}
.gl-anchor::before { left: 5px; top: 9px; }
.gl-anchor::after { left: 10px; top: 14px; }
.gl-anchor:hover { color: var(--clr-ink); border-color: var(--clr-ink); }
.gl-anchor:focus-visible { opacity: 1; outline: 2px solid var(--clr-ink); outline-offset: 2px; }
/* On a touch screen there is no hover, so the anchor is shown quietly all the
   time - otherwise it would exist and be untappable in practice. */
@media (hover: none) { .gl-anchor { opacity: 0.6; } }

/* --- a deep link pulses the row ------------------------------------------ */
.gl-flash { animation: gl-pulse 1.6s ease-out; }
@keyframes gl-pulse {
  0%   { background-color: var(--gl-tint-flash); }
  70%  { background-color: var(--gl-tint-flash); }
  100% { background-color: rgba(232,160,32,0); }
}

/* --- the search highlight ------------------------------------------------
   Only ever wrapped around text inside the term and the meaning columns, and
   always in near-black on the amber wash, so a highlighted word is easier to
   read than the line around it, not harder. */
.gl-mark { padding: 0 2px; color: var(--clr-ink); background: var(--gl-tint-mark); border-radius: 2px; font-weight: 600; } /* 14.31:1 */

/* --- the back-to-top button ---------------------------------------------
   Ink button, amber hairline, a CSS chevron and the dictionary word, fixed
   bottom-right, 44px tall, clear of the phone's rounded corners and home bar
   through env(safe-area-inset). The plain 16px line comes first and the
   max() line after it, so an engine without env()/max() keeps the simple
   value. The hidden state is the default: the CSS owns the look and
   js/glossary_003.js only adds a class. The list below accepts the "shown"
   names this codebase already uses (is-visible on the cards, .open on the
   dropdown) - a name outside the list would leave the button hidden, which
   is the one thing to check after a change to the script. */
.gl-top {
  position: fixed;
  right: 16px;
  right: max(16px, env(safe-area-inset-right));
  bottom: 16px;
  bottom: max(16px, env(safe-area-inset-bottom));
  z-index: 20;
  display: inline-flex;
  align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px;
  max-width: calc(100vw - 32px);
  padding: 0 15px;
  font: inherit;
  font-size: 0.82rem; font-weight: 600; letter-spacing: 0.02em;
  text-align: center;
  color: var(--clr-paper);         /* 16.95:1 on ink */
  background: var(--clr-ink);
  border: 2px solid var(--clr-brand);
  border-radius: 999px;            /* the site's round idiom: a 44px circle
                                      that can still hold a translated word */
  box-shadow: var(--shadow-md);
  cursor: pointer;
  opacity: 0; visibility: hidden;
  transform: translateY(10px);
  transition: opacity var(--trans-normal), transform var(--trans-normal),
              background-color var(--trans-fast), visibility 0s;
}
.gl-top::before {                  /* the chevron, drawn with borders */
  content: "";
  width: 8px; height: 8px;
  margin: 2px 8px 0 0;
  border-left: 2px solid currentColor; border-top: 2px solid currentColor;
  transform: rotate(45deg);
}
.gl-top.is-visible, .gl-top.is-shown, .gl-top.show, .gl-top.open,
.gl-top.is-on, .gl-top.is-active, .gl-top.gl-top-visible,
.gl-scrolled .gl-top { opacity: 1; visibility: visible; transform: none; }
.gl-top:hover { color: var(--clr-brand-ink); background: var(--clr-brand); } /* ink on amber: 8.18:1 */
.gl-top:focus-visible { outline: 3px solid var(--clr-ink); outline-offset: 3px; }

/* ============ SECTION 6: PHONES AND NARROW SCREENS (820px and below) ============
   The card layout in styles_010.css stays: every row is a small card, each
   cell prints its own column label from data-label. This block only tightens
   the new parts, and nothing here can widen the page, so no sideways
   scrollbar appears. -- Ava: on a phone each term is a little flash card;
   nothing moves sideways. */
@media screen and (max-width: 820px) {
  .gl-hero { padding: var(--sp-xl) var(--sp-md); border-radius: var(--radius-md); }
  .gl-hero .gl-hero-title { font-size: 1.9rem; }
  .gl-bar { padding: var(--sp-sm); }          /* smaller card */
  .gl-search { padding-left: 38px; }          /* magnifier moves in with it */
  .gl-search-row::before { left: 13px; }
  .gl-search-row::after  { left: 24px; }
  /* The term becomes a full-width line above its own values; without this a
     table cell inside a block row is squeezed to the width of its text. */
  .gl-term { display: block; width: auto; font-size: 1.05rem; }
  .gl-cat-pill { padding: 2px 9px; font-size: 0.72rem; }
  /* styles_010.css prints the column label in the ::before of every value
     cell, so the decorative quotation mark steps aside and the quote column
     loses its indent. */
  .gl-talk-asked { padding-left: 0; }
  .gl-talk-demand { border-left-width: 3px; padding-left: 12px; }
  .gl-top { right: 12px; bottom: 12px; }
  .gl-table tbody tr { scroll-margin-top: 12px; }
}

/* ============ SECTION 7: PRINT - the handout ============
   On paper the glossary is a reference sheet: no search, no buttons, no
   shadows, black on white (a printer usually drops background colour, and
   pale text on a dropped background prints as nothing at all), the header
   row repeated on every page and no row cut in half by a page break. This is
   the only place in this file where !important is allowed, because a printed
   sheet has to beat the screen rules. */
@media print {
  @page { margin: 16mm; }
  .gl-tools, .gl-top, .gl-anchor, .gl-chips { display: none !important; }
  /* The cover becomes plain paper. */
  .gl-hero { padding: 0 0 8mm; background: none !important; border-top: 3px solid #000; border-radius: 0; }
  .gl-hero .eyebrow, .gl-hero .gl-hero-title, .gl-hero .gl-hero-lead,
  .gl-hero .gl-hero-note { color: #000 !important; opacity: 1 !important; max-width: none; }
  .gl-table { box-shadow: none !important; border-color: #999 !important; }
  .gl-table caption { color: #000 !important; }
  .gl-table thead { display: table-header-group; }   /* repeat on every page */
  .gl-table thead th {
    position: static;
    background: #fff !important; color: #000 !important;
    box-shadow: none !important;
    border-bottom: 1px solid #999 !important;
  }
  .gl-table tbody tr:nth-child(even),
  .gl-table tbody tr:hover,
  .gl-table tbody tr:focus-within { background: none !important; }
  .gl-table tbody tr { scroll-margin-top: 0; }
  .gl-table tr, .gl-table th, .gl-table td {
    page-break-inside: avoid; break-inside: avoid;
    border-color: #bbb !important;
  }
  .gl-term { box-shadow: none !important; }
  .gl-mean, .gl-talk-demand { color: #000 !important; }
  .gl-cat-pill { color: #000 !important; background: none !important; border-color: #999 !important; }
  .gl-talk-asked::before { color: #000 !important; }
  .gl-talks .gl-table thead th { background: #eee !important; color: #000 !important; }
}

/* ============ SECTION 8: CALM - reduced motion, and the no-JS note ============
   A visitor who asked for less movement gets no pulse, no slide-in and no
   fades. The sticky toolbar is deliberately NOT touched: it is a position,
   not an animation, and turning it off would move the controls for that
   visitor. -- Ryan: "prefers-reduced-motion" is the visitor telling the
   browser, once, "please stop things moving"; we simply obey. */
@media (prefers-reduced-motion: reduce) {
  .gl-flash { animation: none; }
  .gl-top, .gl-anchor, .gl-search, .gl-clear, .gl-chip, .gl-table tbody tr { transition: none; }
  .gl-top { transform: none; }
}
/* The message shown when JavaScript is switched off: the amber signature of
   the page, still a plain readable box. */
.gl-nojs { border-left: 3px solid var(--clr-brand); color: var(--clr-ink); }

/* Content continues in css/styles_012.css if this file ever reaches 480 lines. */
