/*
 * Accessibility corrections to the approved design.
 *
 * WHY THIS FILE EXISTS SEPARATELY, AND WHY IT LOADS LAST
 *
 * The design's own tokens are served exactly as delivered and are loaded after the application's
 * stylesheet, so for every token name the two share, the DESIGN's value is the live one. That is
 * deliberate and correct — the design is the reference implementation. It also means a correction
 * cannot be made from the application's stylesheet, because its value is overridden before it is
 * ever used. This file is therefore linked last, and contains only what accessibility requires.
 *
 * WHAT IT CORRECTS, AND HOW IT WAS FOUND
 *
 * Every colour pair the design actually uses was measured against WCAG 2.1 AA. Twenty-one pairs were
 * checked across the paper, raised and sunk grounds, the four chip washes, and the night palette.
 * **One failed:**
 *
 *   --ink-faint #8d8577 on --paper #f7f1e3 = 3.24:1   (AA needs 4.5:1 for normal text)
 *
 * It is not a marginal call and it is not only for disabled controls, which WCAG exempts. The design
 * uses it for real text in three places, all of them in main.css:
 *
 *   .search input::placeholder   -> placeholder text
 *   .rail .count                 -> a count beside a filter
 *   the empty-state line         -> the sentence a reader sees when a filter matches nothing
 *
 * An empty state a reader cannot read is the worst of the three, because it is the only thing on the
 * screen at that moment.
 *
 * THE VALUE CHOSEN
 *
 * #655d51. Measured on every ground the design puts faint text on:
 *
 *   paper #f7f1e3        5.76:1
 *   paper-raised #fffdf8 6.38:1
 *   paper-sunk #efe6d2   5.23:1
 *   accent-wash #e2efe8  5.48:1
 *
 * The design's own --ink-muted (#6b6358) would also pass, but using it would make faint and muted
 * identical and lose a distinction the design draws on purpose. #655d51 keeps that distinction and
 * still clears 4.5:1 on the darkest ground with room to spare.
 *
 * This is the only change made to the delivered design's appearance, it is recorded here, and it
 * should be folded back into the design rather than carried as an override forever.
 */
:root {
  --ink-faint: #655d51;

  /*
   * --focus, CORRECTED FOR THE NIGHT GROUND — THE SECOND MEASURED FAILURE, AND IT IS THE SAME KIND.
   *
   * The design declares `--focus: #1b4f8a`, "never the accent, must be seen". It is excellent on paper
   * (7.36:1) and it fails on the night chrome: measured against `--night` #0f0d0b it is **2.34:1**, where
   * WCAG 2.2 SC 1.4.11 asks 3:1 of a focus indicator. `main.css` draws the ring as
   * `:focus-visible { outline: 3px solid var(--focus) }`, and the night grounds are not incidental — the
   * platform bar, the sticky masthead, the hero, the archive visual, the story doors and the citation band
   * are all night, and the masthead holds the whole main navigation. **A keyboard user's focus ring was
   * fading into the ground on the most-used control on the site.**
   *
   * WHY THIS IS ONE GLOBAL VALUE RATHER THAN A NIGHT-SCOPED RULE
   *
   * A rule scoped to the night containers would leave the light grounds on #1b4f8a and would be the smaller
   * change. It is not the correct one, for a reason that is about honesty rather than taste:
   * `/admin/design/` measures every pair from THE VALUES IN FORCE, and it reads this file to do it
   * (`parseDesignTokens(a11yCss)` merged over the design's own declarations, keyed by token NAME). A scoped
   * re-declaration would have been reported as the value on every ground, so the audit would have shown a
   * passing ratio for a ring the page does not paint. **A measurement that describes a different page is
   * worse than no measurement.**
   *
   * THE VALUE CHOSEN, #5f6ad6. It stays in the design's blue-indigo family and away from the emerald accent
   * and the gold brand, and it clears 3:1 on both grounds with margin to spare:
   *
   *   night  #0f0d0b   4.17:1
   *   paper  #f7f1e3   4.13:1
   *
   * #1b4f8a's 7.36:1 on paper is given up for it. That is the trade: the design's ring was tuned for the
   * light ground, and this site's navigation is on the dark one. **Like the --ink-faint correction above,
   * this belongs in the deliverable rather than in a served override forever.**
   */
  --focus: #5f6ad6;
}

/*
 * THE MARQUEE STOPS FOR THE KEYBOARD TOO.
 *
 * The design pauses its rotating name on hover only:
 *
 *   .sx-marquee:hover ul { animation-play-state: paused; }
 *
 * **`:hover` is not the keyboard's event.** A reader tabbing into one of the marquee's links focuses an
 * anchor that is still sliding, so the focus ring moves out from under the reader and the next Tab starts
 * from somewhere they did not leave. `:focus-within` is the keyboard's half of the same rule and it is the
 * whole fix — the design's own declaration is untouched and this is added beside it rather than replacing
 * it, so a pointer user sees exactly what the design drew.
 *
 * `prefers-reduced-motion` already switches the animation off in the design, so a reader who asks for no
 * motion never reaches this rule. This is for the reader who has motion on and a keyboard.
 */
.sx-marquee:focus-within ul {
  animation-play-state: paused;
}

/*
 * REFLOW — WCAG 2.2 SC 1.4.10. THE THIRD AND FOURTH MEASURED FAILURES, AND THEY ARE THE SAME DEFECT TWICE.
 *
 * The requirement is that content reflows to a 320 CSS-pixel viewport without two-dimensional scrolling. It
 * is measured, not argued: `scripts/sweep-overflow.mjs` drives real Chrome over every reachable page at 390,
 * 768 and 1440 px and reads `documentElement.scrollWidth` against `clientWidth`. Of 414 page-widths, **three
 * scrolled sideways and all three were at 390 px:**
 *
 *   /documents/                                                  +86 px
 *   /folklore-reader/                                           +150 px
 *   /the-rise-decline-and-potential-revival-of-akwa-blacksmithing-a-centuries-old-igbo-craft/   +242 px
 *
 * At 768 and 1440 px nothing scrolled sideways. The cause in both cases is the same shape, and it is a shape
 * the design had already guarded against in its WIDE rule and then dropped in its narrow one:
 *
 *   .sx-pdf-grid       base      grid-template-columns: repeat(3, minmax(0, 1fr))   <- guarded
 *                      <=60rem   grid-template-columns: repeat(2, 1fr)               <- guard dropped
 *                      <=40rem   grid-template-columns: 1fr                         <- guard dropped
 *
 *   .sx-reading-columns  base    grid-template-columns: 14rem minmax(0, 1fr)        <- guarded
 *                        <=60rem grid-template-columns: 1fr                          <- guard dropped
 *
 * `1fr` is `minmax(auto, 1fr)`, and that `auto` minimum is the item's **min-content** width — so a track
 * whose plain `1fr` was meant to mean "the column" silently becomes "whatever the widest unbreakable thing
 * in this item measures". `minmax(0, 1fr)` is the design saying what it meant.
 *
 * WHAT WAS ACTUALLY IN THE COLUMNS, WHICH IS THE HALF THE DESIGN COULD NOT HAVE KNOWN
 *
 * These are migrated WordPress records, and their content is not the design's example content. Three
 * different things were measured sitting in those tracks, and each needs its own answer:
 *
 *   /documents/       one record's title IS its filename — `capacity_building_for_traditional`, thirty-two
 *                     characters with no space in them, set at 1.35rem in the card's `<h3>`. The outer
 *                     track grew to 459 px inside a 358 px column; with the track corrected the title still
 *                     overflowed its own 245 px cell by 82 px.
 *   the article page  the body carries **raw URLs** as link text:
 *                     `https://independent.ng/anambra-community-seeks-revival-of-aw…` measures 658 px at
 *                     16.8 px. The track grew to 616 px inside a 358 px column.
 *   /folklore-reader/ a WordPress `[caption]` figure, and this one is a FIXED WIDTH rather than a long
 *                     token: the shortcode emits `<figure class="wp-caption alignnone" style="width:540px">`,
 *                     an inline width copied from the uploaded image. `img { max-width: 100% }` is already
 *                     in `main.css` and cannot help, because the image's containing block is the 540 px
 *                     figure. **A fixed width wider than its parent is the one cause here that no
 *                     `overflow-wrap` can touch**, and it is why the figure needs its own cap.
 *
 * **A URL is not a word and a filename used as a title is not a word either**, so breaking them is the
 * correct answer rather than a concession — and the design already agrees: `.cite-block` in `main.css` sets
 * `overflow-wrap: anywhere` for exactly this reason. `overflow-wrap: anywhere` rather than `break-word` is
 * deliberate: it is the value that also shrinks the element's min-content contribution, which is what stops
 * the track growing in the first place. It is applied to the containers migrated record text lands in rather
 * than to one measured element, because **the next record with a filename for a title has not been imported
 * yet**; on ordinary prose the declaration does nothing, since it only breaks a word that cannot fit a line
 * by itself. `word-break: break-all` would break ordinary prose mid-word and is not used anywhere here.
 *
 * THE GRID TRACK IS ALSO CORRECTED, AND IT HAS TO BE, because `overflow-wrap` cannot help a REPLACED
 * element or a fixed width, and only `minmax(0, 1fr)` tells the track it is allowed to be narrower than what
 * it holds. With the track at the column width the figure's own `max-width: 100%` scales the image, which is
 * what that declaration was always for.
 *
 * Nothing here changes a single design file, and none of these four screens is altered at 768 px or wider,
 * where the design's own guarded wide rules apply and were measured clean.
 */
@media (max-width: 60rem) {
  .sx-reading-columns,
  .sx-folk-reader-book .sx-reading-columns {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* The design's own two-column step, with the guard it dropped. */
@media (min-width: 40.0625rem) and (max-width: 60rem) {
  .sx-year-grid,
  .sx-pdf-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* The design's own one-column step, with the guard it dropped. */
@media (max-width: 40rem) {
  .sx-year-grid,
  .sx-pdf-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* A migrated record's own words: a raw URL, or a title that is a filename. */
.sx-reading-columns .prose,
.sx-reading-columns .sx-page,
.sx-reading-columns aside,
.sx-pdf-grid article,
.sx-publication-list article {
  overflow-wrap: anywhere;
}

/* A WordPress caption figure carries the uploaded image's width inline; cap it rather than obey it. */
.sx-reading-columns .prose figure,
.sx-pdf-grid figure {
  max-width: 100%;
}

.sx-reading-columns .prose figure img {
  height: auto;
}

/*
 * ── THE MASTHEAD LOGO WAS BEING SQUEEZED, AND THE CAUSE IS TWO RULES THAT ARE EACH CORRECT ALONE ────────
 *
 *   main.css:11      img { max-width: 100%; display: block }
 *   main.css:98      .wordmark { display: inline-flex; align-items: baseline; gap: var(--s-2) }
 *   showcase.css:19  .wordmark { align-items: center }
 *   showcase.css:20  .wordmark img { width: 34px; height: 34px; border-radius: 50% }
 *
 * ⚠️ **AN `img` INSIDE A FLEX CONTAINER IS A FLEX ITEM, AND A FLEX ITEM SHRINKS BY DEFAULT**
 * (`flex-shrink: 1`). **`max-width: 100%` then resolves against whatever space the flex line has left**,
 * rather than against the 34 px the design asked for — so as the masthead's own content grew (the nav, the
 * date, and on a narrow viewport the whole wrapped row), **the logo was compressed below its own size.**
 *
 * ⚠️ **AND THE DESIGN NEVER INTENDED A VARIABLE LOGO.** *It sets 34 px by 34 px and a circle, and the archive
 * serves a 512 × 512 square PNG through it, so the file is not the problem and never was* — measured: the
 * served image is **512 × 512, ratio 1.000**, 15,175 bytes. **The size was being decided by the layout rather
 * than by the design.**
 *
 * SO THE SIZE IS PINNED WHERE THE APPLICATION CONTROLS IT. *`apps/ozikoro/public/design/` is inviolable — it
 * is byte-identical to the deliverable and must stay so — and this sheet already loads **after** both of the
 * design's, which is where a rule that **corrects** the design rather than contradicting it belongs.*
 *
 * `max-width: none` is needed as well as `flex: 0 0 auto`, and neither alone is enough: **`flex` stops the
 * flex algorithm shrinking the box, and `max-width` stops the global `img` cap re-capping it once the box
 * has been sized.** *The 34 px itself is not repeated here — it is the design's, and duplicating a value
 * is how the two copies drift.*
 */
.wordmark img {
  flex: 0 0 auto;
  max-width: none;
}

/*
 * ── THE BACK-OFFICE LINK ON A DASHBOARD RAIL WAS THE SAME COLOUR AS THE RAIL ─────────────────────────
 *
 * The owner: *"the dashboard where it was written 'The administration — the archive's back office' was
 * invisible unless my cursor goes there"*.
 *
 * WHAT WAS PAINTED, MEASURED FROM THE VALUES IN FORCE
 *
 * The control is the rail's one back-office anchor, and the rail is night — `showcase.css:276` sets
 *
 *     aside.sx-dash-side { background: var(--night); color: var(--on-night) }
 *
 * while the anchor is dressed in `main.css`'s quiet-button class, which is written for paper:
 *
 *     main.css:130   .btn-quiet        { background: transparent; color: var(--ink); border-color: var(--rule-firm) }
 *     main.css:131   .btn-quiet:hover  { background: var(--paper-sunk); color: var(--ink-strong) }
 *
 * So on that rail the pair was
 *
 *     resting   --ink        #1d1a16 text on --night      #0f0d0b ground   1.12:1
 *     hover     --ink-strong #0f0d0b text on --paper-sunk #efe6d2 fill    15.63:1
 *
 * **The link was legible in exactly one state, and it is the state a keyboard user has to reach it to
 * cause and a touch-screen reader can never cause.** 1.12:1 is not dim text; it is text the same colour
 * as what is behind it.
 *
 * THE CORRECTION IS THE DESIGN'S OWN, NOT A NEW COLOUR
 *
 * `showcase.css` already corrects this class on the two other night grounds it lands on —
 * `.sx-reg-search .btn-quiet { color: var(--on-night); … }` (line 671) and `.sx-viewer-page
 * .btn-quiet { color: var(--cream); … }` (line 708). This is the third night ground and the one that was
 * missed, so the rule is written the same way: the resting colour becomes the rail's own foreground
 * (--on-night, **16.21:1** on --night) and the border the design's stronger-rule tone (--rule-firm,
 * **9.59:1** on --night). No new value is introduced.
 *
 * THE HOVER IS THE DESIGN'S OWN, AND IT HAS TO BE WRITTEN OUT, WHICH WAS NOT OBVIOUS.
 *
 * `main.css:131` already gives this class a hover — `--paper-sunk` fill, `--ink-strong` text, 15.63:1 — and
 * the intention was to leave it exactly as the design wrote it. **It does not survive the rule above**: the
 * resting rule is `.sx-dash-side .sx-mode-admin .btn-quiet` (three classes) and the design's hover is
 * `.btn-quiet:hover` (two), so the resting colour went on winning while the design's fill came through —
 * **cream text on a cream pill, measured 1.05:1, which is the original fault one interaction later.**
 *
 * Forcing the pseudo-state in Chrome and reading what it painted is what found this; nothing in the markup
 * or the diff shows it. So the hover is stated in the design's own values.
 *
 * ⚠️ SCOPED TO THE RAIL, BECAUSE THE SAME PARAGRAPH IS ALSO PUT ON PAPER. `fillModeSwitcher` places it
 * either inside `aside.sx-dash-side` (the nine rail dashboards — night) or at the head of
 * `<main class="wrap sx-section">` (the five rail-less dashboards — paper). On paper `--ink` is correct
 * and must not be touched, which is why this is a descendant selector and not a rule on `.sx-mode-admin`.
 */
.sx-dash-side .sx-mode-admin .btn-quiet {
  color: var(--on-night);
  border-color: var(--rule-firm);
}

.sx-dash-side .sx-mode-admin .btn-quiet:hover {
  color: var(--ink-strong);
}

/*
 * ── THE SIGNED-IN ITEM IN THE MASTHEAD, WHICH WAS A DARK PANEL SITTING IN THE MENU ──────────────────
 *
 * The owner: *"when i signed in and went to the front page, it scattered the menu."*
 *
 * WHAT WAS PAINTED
 *
 * `renderModeSwitcher` reuses the deliverable's own `details.sx-role-switch`, and `showcase.css:280`
 * draws that control as a card, because it was drawn for a dashboard SIDEBAR:
 *
 *     showcase.css:280  .sx-role-switch      { margin-top: var(--s-5); border: 1px solid rgba(201,168,76,.4);
 *                                              border-radius: var(--r-md); background: var(--night-2) }
 *     showcase.css:281  .sx-role-switch summary { padding: var(--s-3); color: var(--on-night); font-weight: 700 }
 *     showcase.css:283  .sx-role-switch a    { display: block; padding: var(--s-2); font-size: var(--t-sm) }
 *
 * **In `nav.nav` that is a 1.5rem top margin, a 0.75rem-padded bold summary, a gold border and a
 * night-2 fill — a box in a row of links.** `main.css:101` lets the row wrap, so a control several
 * hundred pixels wide pushed `About` and the account item onto a second line. The measurement that
 * matters is in the report; the cause is that one control was styled for the place it came from and not
 * the place it was put.
 *
 * THE CORRECTION MAKES IT AN ITEM IN THE NAV, WHICH IS WHAT IT IS
 *
 * The summary is given `main.css`'s own `.nav a` metrics (1rem, --on-night, 2px transparent underline,
 * --s-1 block padding) so it measures like the links beside it, and the panel is taken **out of flow**
 * and anchored under the item. **An open menu must not reflow the bar it opened from** — that is the
 * same fault one hover later, and it is why `position: absolute` rather than a taller `<li>`.
 *
 * The disclosure marker is redrawn rather than left as the platform's own triangle, because
 * `::marker` is not styled consistently and the design's vocabulary is a chevron.
 *
 * ⚠️ ONLY `.nav-modes-item`. `.sx-role-switch` is also the rail control and the rail-less screens'
 * control, where the design's own card styling is right — both are scoped separately below and neither
 * is touched.
 */
.nav-modes-item {
  position: relative;
  display: flex;
  align-items: center;
}

.nav-modes-item .sx-role-switch {
  margin-top: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}

.nav-modes-item .sx-role-switch > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: var(--s-1) 0;
  color: var(--on-night);
  font-size: 1rem;
  font-weight: 500;
  line-height: inherit;
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  list-style: none;
  cursor: pointer;
}

/* Safari and Chrome both draw their own marker on a summary; the design's is a chevron. */
.nav-modes-item .sx-role-switch > summary::-webkit-details-marker {
  display: none;
}

.nav-modes-item .sx-role-switch > summary::after {
  content: '';
  width: 0.4em;
  height: 0.4em;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-0.15em) rotate(45deg);
}

/* The design's own hover for a nav link, so this item behaves like the ones beside it. */
.nav-modes-item .sx-role-switch > summary:hover,
.nav-modes-item .sx-role-switch[open] > summary {
  color: var(--gold-bright);
  border-bottom-color: var(--gold);
}

.nav-modes-item .sx-role-switch[open] > summary::after {
  transform: translateY(0.1em) rotate(-135deg);
}

/*
 * THE PANEL, ANCHORED. `right: 0` rather than `left: 0` because the item is the last thing in the row
 * apart from nothing — a panel that grew to the right would leave the viewport on the archive's own
 * 1440px bar, and one that grows left stays under the control it came from.
 */
.nav-modes-item .sx-role-switch > div {
  position: absolute;
  top: calc(100% + var(--s-3));
  right: 0;
  z-index: 60;
  min-width: 16rem;
  max-height: min(70vh, 30rem);
  overflow: auto;
  padding: var(--s-2);
  border: 1px solid rgba(201, 168, 76, 0.4);
  border-radius: var(--r-md);
  background: var(--night-2);
  box-shadow: var(--shadow-lift);
}

/*
 * AT 40REM THE DESIGN TURNS THE MASTHEAD INTO A DISCLOSURE ITSELF — `showcase.css:658` hides `nav.nav`
 * and shows it only on `.masthead.menu-open`, as a two-column grid of full-width rows. **A floating
 * panel inside a grid cell is two panels fighting for the same pixels**, so at that width the panel goes
 * back into flow and the summary takes the same row metrics as every other item in that menu.
 */
@media (max-width: 40rem) {
  .nav-modes-item .sx-role-switch > summary {
    display: block;
    padding: 0.85rem 0.35rem;
    font-size: 1rem;
    border-bottom: 0;
  }

  .nav-modes-item .sx-role-switch > div {
    position: static;
    min-width: 0;
    max-height: none;
    margin: 0;
    padding: var(--s-2) 0.35rem var(--s-3);
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
  }
}

