/* ==========================================================================
   Schooling — the only place the copied interface is overridden.

   THERE IS NO LAYOUT IN THIS FILE. `base.css` and `portal.css` are
   `portal-frontend`'s, byte for byte, and they are loaded before this one: the
   bar, the rail, the blocks, the cards, the meters, the graph, the lesson
   list, the exam paper and the certificate all come from there, and the
   instruction for this interface is that it looks EXACTLY like the portal.

   IT USED TO HOLD A WHOLE STYLESHEET. This application had screens of its own
   before the portal's were copied in, written to the same palette and the same
   vocabulary — `.lessons`, `.node`, `.graph`, `.option`, `.question`,
   `.search`. Those screens are gone and the class names are not: the copied
   markup uses the same words, so every one of those rules landed on the
   portal's elements and won, because this file is loaded last. On the screen
   that was a line drawn between lessons the portal does not draw, a hover that
   stopped short of the edge of the panel, a graph laid out by two stylesheets
   at once. None of it is visible in a diff of `portal.css`, which is identical;
   all of it is visible side by side with app.codeschool.ing, which is how it
   was found.

   So the rule now is the one the header always claimed and the contents did
   not keep: THIS FILE MAY ONLY OVERRIDE, AND EVERY OVERRIDE IS ARGUED FOR
   BELOW. Anything that merely styles something is a change to `portal.css`,
   made there and taken back to the portal.

   What is left is accessibility, and nothing else. Every rule below is a WCAG
   failure in the copied stylesheet — one colour used as text, three elements
   dimmed with `opacity`, one control six pixels short of a target. All of them
   are the portal's, all of them were found by a check the portal does not run,
   and all of them are worth taking back.

   THE STYLES FOR THE THREE QUESTION TYPES THE PORTAL DOES NOT HAVE are not
   here: they are not overrides of anything, and they are in `exercises.css`.
   ========================================================================== */

/* ---------- A BLUE THAT PASSES, AND STAYS A BLUE ----------

   `portal.css` sets a dozen pieces of small text in `--phosphor-dim`. On the
   dark page that is #33549e on #0a0e14 — 2.67:1, where WCAG AA asks 4.5:1 for
   text this size — and on the light one #6c86c9 on #f2f4f9, which is 3.24:1.
   Axe reports every one: the rail's track heading, the count beside a course,
   the lesson numbers, the level on a map card, a course's meta line, the word
   that says a course is open to you.

   IT IS A REAL DEFECT AND IT IS THE PORTAL'S. Copying the file brought it here,
   which is the argument FOR copying rather than against it: two interfaces
   sharing a stylesheet share the finding, and this one was found by a check the
   other side does not run.

   THE FIX IS A BLUER BLUE AND NOT A GREY, and that is a correction to two
   earlier attempts at it. The first set these to `--paper-dim` — accessible,
   and the palette's colour for secondary text — and the result read as a duller
   interface than the portal's, because in the portal they are ACCENTS: the
   track a student is on, how far through a lesson they are, which course is
   open to them next. Taking the colour out took the meaning with it. The second
   used `--phosphor`, which is right about the colour and wrong about the
   weight: `--phosphor` is what a FINISHED course is drawn in, and an available
   one drawn in the same blue is a state that no longer says anything.

   So: one step between them, defined here because it is a correction and not a
   palette. It clears 4.5:1 in both themes, against the page and against the
   certificate's own sheet, and it stays visibly below `--phosphor`, which keeps
   done, current and available three different things.

     dark  #4f7de0 — 4.92:1 on #0a0e14, 4.57:1 on the sheet
     light #4468c4 — 4.74:1 on #f2f4f9, 5.22:1 on white

   Every accessibility rule here is a rule and not a preference (X-05), so this
   is not optional and the copy is not "byte for byte" in effect. It is the one
   divergence, it is listed here, and it is small enough to re-apply if the file
   is copied again. */
:root{--phosphor-mid:#4f7de0}
html[data-theme="light"]{--phosphor-mid:#4468c4}

/* AND THE WASH THE ACCENT'S OWN TEXT SITS ON, named here so it can be measured.

   THE NAME IS NOT `--tint-accent`, and that is not fussiness: the console has a
   token by that name already, at a different alpha, for tinting its own chips.
   Two stylesheets in one product using one name for two values is a collision
   waiting for the day something reads both — which is exactly what `accent.js`
   now does, on two hosts.

   `portal.css` and `base.css` write `rgba(91,140,255,.07)` as a literal behind a
   right verdict, a chosen-and-correct option and the track tab that is on. Over
   the light page that composites to a surface DARKER than the page — and a
   colour that just cleared 4.5:1 against `--ink` lands at 4.32:1 on it.

   `accent.js` measures the accent against every surface it can land on and
   reads those surfaces from the stylesheet rather than carrying colours of its
   own. This is that surface, given a name so it can be read.

   IT IS THE LIGHTEST OF SEVERAL AND NOT THE ONLY ONE. The same wash is written
   at .1, .12 and .16 behind other accent-coloured text — an open fork tab, the
   language picker's current language, a right dot on the exam wizard — and each
   of those sits further from the page than this one. They are not measured here:
   this is the surface the failure was found on, and picking a stricter one would
   move every school's accent on the strength of a screen nobody has looked at.
   The day axe reports one of them, this value moves to it.

   IT IS A DUPLICATE OF A VALUE IN THE COPIED FILES, and that is the rule
   working rather than failing: nothing is added to `base.css` or `portal.css`
   here, not even a fix, because an empty diff against `portal-frontend` is what
   makes the next duplicated-stylesheet bug findable. So the value is restated
   once, in the file that is allowed to hold it, next to the reason. If it ever
   changes over there, the accent is measured against a surface that no longer
   exists — which axe finds, because that is how this one was found. */
:root{--accent-wash:rgba(91,140,255,.07)}

.rail-tit,
.tc-count,
.ta-num,
.ta-count,
.ts-dur,
.ctx-arrow,
.card-cat,
.course-meta,
.lesson-num,
.lesson-sections,
.step-n,
.node-count,
.course-node .order,
.course-node .meta,
.eyebrow,
.track-summary i,
.cert-meta,
.cert-code,
.node-state[data-state="available"],
.field label,
/* THE EXAM PAPER'S OWN, and they are on this list for the reason the rest are:
   small mono text in `--phosphor-dim`. They arrive late because that screen
   could not be opened, and the first axe run that reached it reported them on
   every question of the paper.

   `.expr-label` is here without having been reported. It is the same colour at
   the same size, on the same screen, and it only stayed quiet because it is
   drawn for an expression question that names a `checkOperation` and the
   fixture's does not. Waiting for a fixture to grow that field before fixing a
   colour that is already wrong is how the other two got this far. */
.wz-count,
.ex-label,
.expr-label{color:var(--phosphor-mid)}
/* `.cert-meta` and `.cert-code` are on the certificate sheet, which paints its
   own background (#111721 dark, #ffffff light), so they are measured against
   that and not the page. `.cert-void .cert-code` keeps its struck-through grey
   — two classes beat one, and a revoked code should not read as an accent. */

/* ---------- AND THE SAME DEFECT AGAIN, AS OPACITY ----------

   `.cert-sample{opacity:.66}` dims the example certificate so that a fake
   cannot be mistaken for a real one — which is right, and is done three ways:
   a dashed frame, a muted colour and a seal in place of the type.

   OPACITY ON TEXT IS NOT A COLOUR. It multiplies every colour inside against
   whatever is behind, so the sample's own `--paper-dim` came out at 3.59:1 on
   the dark page and 2.94:1 on the light one. This repository has met that exact
   failure before, and the answer is the same: dim by naming the colour, never
   by fading the element.

   The frame and the seal still carry the meaning, which is what the portal's
   own comment says they are for. */
.cert-sample{opacity:1}
.cert-sample .cert-sheet,
.cert-sample .cert-brand b,
.cert-sample .cert-seal,
.cert-sample .cert-line{color:var(--paper-dim)}

/* ---------- AND THE SAME DEFECT TWICE MORE, ON SCREENS NOBODY COULD REACH ----

   Everything below was found the week the accessibility suite stopped checking
   the router's "page not found" and started checking the lesson and the exam.
   None of it is new; all of it had been shipping.

   `.step-pending` and `.rail-section.pending` dim a whole block to say
   "reserved, nothing to do here yet" and take their own title through the floor
   doing it. `--paper-dim` is 7.34:1 in the dark theme and 5.56:1 in the light
   one — comfortable — and at .55 it composites to 2.97:1 and 2.28:1.

   RAISING THE FIGURE DOES NOT RESCUE IT: in the light theme `--paper-dim` needs
   .95 before it passes, which is not dimming at all, and `--paper` at .6 still
   only reaches 3.97:1. So the block is quietened by colour — a border that
   recedes, a mark that goes grey — and the text keeps a value somebody
   measured. It looks the same and it can be read.

   These lived in `portal.css` for one release, which was a mistake worth
   naming: that file is the portal's byte for byte, and the whole reason the
   duplicated-stylesheet bug was findable at all is that a diff of it is empty.
   An accessibility divergence belongs on this list, where it is argued once and
   can be re-applied after the next copy. */
.step-pending{opacity:1;border-color:var(--wire)}
.step-pending .step-title,
.step-pending .step-n{color:var(--paper-dim)}
.step-pending:hover .step-title{color:var(--paper)}

.rail-section.pending{opacity:1}
.rail-section.pending .ts-title,
.rail-section.pending .ts-mark{color:var(--paper-dim)}
.rail-section.pending:hover .ts-title{color:var(--paper)}

/* THE THIRD SHAPE OF IT, on the matching question: a tile in a pair that closed
   CORRECTLY is faded to .65 to say it is done with, which puts its own text at
   4.4:1 on the light theme. Same answer as the other two — the tile keeps its
   tint and its border, and the words go to a colour.

   This said `.tile-right` and the comment said "a paired right-hand tile",
   which is the other meaning of that class: the column. The rule was written
   for the verdict and described as the column, and the column is what it hit. */
.tile-correct{opacity:1;color:var(--paper-dim)}

/* AND `.tile-taken` HAS THE SAME PROBLEM AND IS NOT FIXED HERE. A right-hand
   option already spoken for is faded to .4 — worse than the .65 this rule was
   written for, and on far more screens, since a lesson and a drill stopped
   checking each pair as it lands. The same treatment does not transfer: the
   correct state keeps a background tint when its opacity goes back to 1 and the
   taken state has none, so raising it would leave a used option looking
   untouched. It needs a tint chosen by somebody who can see it, which is a
   change to how the question looks and not a contrast repair. */

/* ---------- A TARGET BIG ENOUGH TO HIT ----------

   WCAG 2.2 adds 2.5.8: a control is at least 24 by 24, or has that much clear
   space around it. The ordering question's move-up and move-down buttons are 24
   by 18 and stacked against each other, so they fail on both counts — and they
   are the KEYBOARD AND POINTER path for that question, the thing that exists so
   ordering is not drag-and-drop. A control that only a steady hand can hit is
   the defect this question type was designed to avoid, arriving by the back
   door.

   Six pixels, on the axis they were short. */
.ord-arrow{height:24px}

/* ---------- THE DRILL ----------

   A screen the portal does not have, so there is nothing to override here and
   nothing to keep in step: these are new rules for a new screen, written in the
   vocabulary the copied stylesheet already uses. Kept as small as it looks —
   the question itself is drawn by the same renderers the lesson and the exam
   use, and it brings its own styling with it. What is left is the frame around
   one card. */
.drill{display:flex;flex-direction:column;gap:14px}
.drill-count{
  font-family:'IBM Plex Mono',monospace;font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--phosphor-mid);margin:0;
}
.drill-stage{min-height:120px}
.drill-foot{display:flex;justify-content:flex-end}
.drill-done{margin:0 0 6px}

/* ---------- MY ACCOUNT ----------

   Another screen the portal does not have — the account dropdown linked to it
   for as long as the dropdown existed and no route answered. New rules for a
   new screen, in the vocabulary the copied stylesheet already uses; the frame
   around it is `.view` and `.block`, which are that stylesheet's.

   AND THE VOCABULARY IS BORROWED, NOT SHARED. The enrolment list below was
   written as `.steps`, which is a word `portal.css` had already spent: there it
   is the row of section tabs at the top of a lesson, `display:flex` with
   `flex-wrap`. This file loads last, so a column laid out for two paragraphs of
   enrolment instructions became the layout of every lesson's tabs — stacked one
   under the other, on a screen this change never touched.

   That is the failure the header of this file describes, arriving again, and by
   the same route: a name the copied stylesheet already owns. `check-css` now
   fails on it, so the next one is caught by a tool rather than by somebody
   noticing that a screen looks different. */
.facts{display:grid;grid-template-columns:auto 1fr;gap:6px 18px;margin:0}
.facts dt{
  font-family:'IBM Plex Mono',monospace;font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--paper-dim);
}
.facts dd{margin:0;color:var(--paper)}

.enrol-steps{margin:0;padding-left:20px;display:flex;flex-direction:column;gap:14px}
.enrol-steps li{line-height:1.55}
.enrol-steps p{margin:8px 0}

/* THE SECRET IS SELECTABLE AND BIG ENOUGH TO READ OFF THE SCREEN, because the
   thing somebody does with it is type it into a phone held in the other hand. */
.secret{
  font-family:'IBM Plex Mono',monospace;font-size:1rem;letter-spacing:.12em;
  padding:10px 12px;border:1px solid var(--wire);border-radius:5px;
  background:var(--panel);user-select:all;overflow-wrap:anywhere;
}

.inline-form{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap}

/* TEN CODES, IN COLUMNS, EACH ONE SELECTABLE ON ITS OWN. A single block of
   text is copied whole or not at all, and somebody spending the ninth code
   wants that one. */
.codes{
  list-style:none;margin:12px 0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px;
}
.codes li{
  font-family:'IBM Plex Mono',monospace;font-size:.92rem;letter-spacing:.08em;
  padding:8px 10px;border:1px solid var(--wire);border-radius:4px;
  background:var(--panel);user-select:all;text-align:center;
}

.notice{font-size:.82rem;color:var(--paper-dim);min-height:1.2em;margin:0}
.notice.bad{color:var(--bad,#ff4d5e)}
.view-account .on{color:var(--phosphor)}

/* ---------- SOMEBODY IS LOOKING ----------

   A screen the portal does not have and could not: view-as-student is a console
   feature and the portal had no console. New rules for a new element, in the
   vocabulary the copied stylesheet already uses — and under a name that
   stylesheet does not own, which is what `tools/check-css` holds.

   IT IS RED AND IT IS AT THE TOP AND IT DOES NOT SCROLL AWAY. The verify banner
   below it is a nudge and can be dismissed; this is a statement that the work on
   the screen belongs to somebody else, and a restraint somebody can click away
   or scroll past is not a restraint. K-02 asks for it in the same breath as the
   audit and the expiry, because it is the only one of the three that acts while
   the thing is happening.

   THE COLOUR IS NOT THE MESSAGE. It says who is looking at whom, in words; the
   red is for the eye returning to a tab it left twenty minutes ago. */
.viewing-banner{
  position:sticky;top:0;z-index:60;
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:9px 16px;font-size:.82rem;
  background:var(--bad-solid,#c81f31);color:#fff;
  border-bottom:1px solid rgba(0,0,0,.35);
}
.viewing-banner[hidden]{display:none}
.vw-text{flex:1 1 auto;min-width:0}
.vw-status{font-size:.74rem;opacity:.9}

/* The one control, and it reads as a control on a red ground rather than as a
   link that happens to be there. `currentColor` so it stays legible whatever the
   ground becomes. */
.vw-stop{
  flex:0 0 auto;font:inherit;font-size:.76rem;cursor:pointer;
  background:transparent;color:inherit;border:1px solid currentColor;border-radius:4px;
  padding:4px 12px;
}
.vw-stop:hover:not(:disabled){background:rgba(255,255,255,.14)}
.vw-stop:disabled{opacity:.7;cursor:default}

/* ==========================================================================
   SOMETHING HERE IS WRONG — the report control, at the foot of a section.

   IT IS THE NOTE'S TWIN AND DELIBERATELY QUIETER. The note is the loud one:
   people are invited to write in the margin and it is a good thing when they
   do. This is a control that should be used rarely and be unmissable when it
   is needed, so it borrows the note's shape — a `details`, collapsed, at the
   end — and none of its colour until it is opened.

   THESE ARE OUR CLASSES AND THE PORTAL'S STYLESHEET DECLARES NONE OF THEM,
   which is what `tools/check-css` is for: laying out an element of theirs from
   here is the class of defect that moved the enrolment steps under each other.
   ========================================================================== */

.report{border-top:1px dashed var(--wire);padding-top:12px;margin-top:14px}
.report summary{
  cursor:pointer;font-family:'IBM Plex Mono',monospace;font-size:.72rem;
  color:var(--paper-dim);list-style:none;
}
.report summary::-webkit-details-marker{display:none}
.report summary:hover,.report[open] summary{color:var(--phosphor)}
.report summary:focus-visible{outline:1px solid var(--phosphor);outline-offset:3px}

.report-body{margin-top:12px}

/* A FIELDSET WITH A REAL LEGEND, not a paragraph and a group of inputs. Five
   radios sharing one question is exactly what the element is for, and it is
   what a screen reader announces the question from — the alternative is five
   controls whose common heading exists only visually. */
.report-why{display:flex;flex-direction:column;gap:7px;border:0;padding:0;margin:0}
.report-why legend{
  font-family:'IBM Plex Mono',monospace;font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--paper-dim);padding:0;margin-bottom:4px;
}
.report-pick{display:flex;gap:9px;align-items:flex-start;font-size:.86rem;cursor:pointer}
.report-pick input{margin-top:.25em;accent-color:var(--phosphor);flex:none}
.report-pick span{color:var(--paper);line-height:1.5}

.report-note{
  width:100%;margin-top:12px;padding:11px 13px;border-radius:5px;resize:vertical;
  background:var(--panel);border:1px solid var(--wire);color:var(--paper);
  font:inherit;font-size:.88rem;line-height:1.6;
}
.report-note:focus{outline:none;border-color:var(--phosphor)}

.report-foot{display:flex;align-items:center;gap:12px;margin-top:10px;flex-wrap:wrap}
.report-status{font-size:.68rem}

/* What it says once it has been said. It replaces the form rather than sitting
   under it: the gesture is finished, and a form still standing there invites
   the same report a second time. */
.report-said{font-size:.82rem;color:var(--paper-dim);line-height:1.6;max-width:60ch}

/* ==========================================================================
   WHAT YOU THOUGHT OF IT — the stars, and the four pairs behind them.

   IT IS OPEN WHERE THE BLOCK ABOVE IS CLOSED, which is the whole difference
   between the two. A report is opened by somebody who has found a defect; this
   is asked of everybody, so it has to be visible and has to cost one tap.

   THE RADIOS ARE HIDDEN AND NOT REMOVED. `display:none` would take them out of
   the tab order and out of the accessibility tree, which is exactly the control
   this refuses to build (X-05, X-06). They are clipped, they still focus, the
   arrow keys still move between them, and the ring is drawn on the label.
   ========================================================================== */

.rate{border-top:1px dashed var(--wire);padding-top:14px;margin-top:16px}

.rate-hide,
.rate-row input,
.rate-pair input{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

.rate-row{display:flex;align-items:center;gap:4px;border:0;padding:0;margin:0;flex-wrap:wrap}
.rate-row legend{
  font-family:'IBM Plex Mono',monospace;font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--paper-dim);padding:0;margin-bottom:6px;
}
.rate-row label{
  cursor:pointer;line-height:1;padding:2px;border-radius:3px;
  color:var(--wire);font-size:1.45rem;transition:color .12s;
}
.rate-row label:hover{color:var(--amber)}
.rate-row input:focus-visible+label{outline:1px solid var(--phosphor);outline-offset:2px}

/* Lit up to the number the fieldset carries. Written out rather than generated,
   because five rules that say what they do beat a selector nobody can read —
   and the scale is a constant this interface does not get to change on its own. */
.rate-row[data-stars="1"] label:nth-of-type(-n+1),
.rate-row[data-stars="2"] label:nth-of-type(-n+2),
.rate-row[data-stars="3"] label:nth-of-type(-n+3),
.rate-row[data-stars="4"] label:nth-of-type(-n+4),
.rate-row[data-stars="5"] label:nth-of-type(-n+5){color:var(--amber)}

/* THE SECOND LAYER, and it says out loud that it is optional. A block of four
   questions with no such line reads as a form somebody has to finish. */
.rate-invite{
  font-size:.76rem;color:var(--paper-dim);margin:14px 0 10px;line-height:1.6;max-width:60ch;
}

.rate-pair{
  display:flex;align-items:center;gap:10px;border:0;padding:0;margin:0 0 9px;flex-wrap:wrap;
}
.rate-pair legend{font-size:.8rem;color:var(--paper);padding:0;margin-bottom:5px}

/* THE TWO ENDS ARE THE QUESTION. A number between "too easy" and "too hard"
   means something; the same number under the word "depth" does not. */
.rate-end{font-size:.72rem;color:var(--paper-dim);flex:none;max-width:14ch;line-height:1.4}
.rate-dots{display:flex;gap:7px;align-items:center}
.rate-pair label{
  cursor:pointer;width:15px;height:15px;border-radius:50%;
  border:1px solid var(--wire);background:var(--panel);
  transition:background .12s,border-color .12s;
}
.rate-pair label:hover{border-color:var(--phosphor)}
.rate-pair input:checked+label{background:var(--phosphor);border-color:var(--phosphor)}
.rate-pair input:focus-visible+label{outline:1px solid var(--phosphor);outline-offset:2px}

.rate-said{
  font-size:.72rem;color:var(--paper-dim);margin-top:10px;
  font-family:'IBM Plex Mono',monospace;
}

/* On a phone the two ends and the dots stop fitting on one line, and a pair
   wrapped mid-scale is unreadable. The ends go to the outside of a grid row
   instead, which keeps the scale in one piece at any width. */
@media (max-width:520px){
  .rate-pair{display:grid;grid-template-columns:1fr auto 1fr;gap:8px}
  .rate-pair legend{grid-column:1 / -1}
  .rate-end{max-width:none}
  .rate-end:last-of-type{text-align:right}
}

/* ==========================================================================
   WHAT YOU HAVE BOUGHT — the purchase history, in "Your subscription".

   THE FACTS ABOVE IT ARE THE STATE AND THIS IS THE RECORD, and they answer
   different questions. "Runs to 12 March" is what somebody checks; "in June
   2026 you paid R$ 655,50 for a year in Pix, and it ran to June 2027" is what
   somebody needs when they are reconciling a card statement, disputing a
   charge, or trying to remember whether they renewed. A definition list cannot
   hold the second: it is several purchases with the same five fields, which is
   a table, and pretending otherwise is how the answer becomes a paragraph
   nobody reads.

   IT SCROLLS INSIDE ITS OWN BOX. Five columns do not fit a telephone and the
   page must never scroll sideways — the same rule, and the same shape, as
   `portal.css`'s comparison table, under names this file owns. `check-css`
   holds that boundary: laying out one of their elements from here is the
   defect that put every lesson's tabs under each other.
   ========================================================================== */

.bought{margin-top:18px}
.bought-scroll{
  overflow-x:auto;margin:0 -4px;padding:0 4px;
  scrollbar-width:thin;scrollbar-color:var(--wire) transparent;
}
.bought-table{width:100%;border-collapse:collapse;min-width:560px;font-size:.86rem}
.bought-table caption{
  font-family:'IBM Plex Mono',monospace;font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--paper-dim);text-align:left;padding-bottom:8px;
}
.bought-table th,.bought-table td{
  padding:9px 12px;text-align:left;border-bottom:1px solid var(--wire);vertical-align:top;
}
.bought-table thead th{
  font-family:'IBM Plex Mono',monospace;font-size:.64rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--paper-dim);font-weight:400;white-space:nowrap;
}
.bought-table tbody tr:last-child th,.bought-table tbody tr:last-child td{border-bottom:0}
/* The date leads every row and is the column an eye scans down, so it is the
   row's header rather than a cell — which is also what a screen reader reads
   back before each of the other four. */
.bought-table tbody th{font-weight:400;color:var(--paper);white-space:nowrap}
.bought-amount{white-space:nowrap}
/* WHAT IT WAS BEFORE THE DISCOUNT, struck through and quiet. A Pix sale is
   charged under the listed price, and somebody comparing their statement
   against the site needs to see the subtraction rather than wonder about it. */
.bought-was{display:block;font-size:.72rem;color:var(--paper-dim);text-decoration:line-through}

/* A PURCHASE THAT IS NOT PAID IS NOT A FAILURE AND IS NOT DRAWN AS ONE. Most
   of them are somebody who opened the form and thought better of it. The row
   is dimmed because it is not part of what they hold — not coloured, because
   there is nothing to warn about. */
.bought-open{color:var(--paper-dim)}
.bought-stage{
  font-family:'IBM Plex Mono',monospace;font-size:.62rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--paper-dim);
}

/* THE SEVEN DAYS, while somebody still has them.

   IT IS NOT A WARNING AND IS NOT DRAWN AS ONE. Nothing has gone wrong; a right
   the law gives is being stated on the screen where it is useful. A red box
   would read as "there is a problem with your payment", which is the opposite
   of what it says.

   IT IS NOT `.dim` EITHER. The sentences around it are asides; this one is the
   only thing on the block that expires, and quiet grey is how a deadline goes
   unread. So: the panel's own text, on a ground of its own, with a rule down
   the side to say it is a note rather than another fact in the list. */
.withdraw{
  margin:14px 0 0;padding:10px 12px;
  font-size:.84rem;line-height:1.6;color:var(--paper);
  background:var(--panel);border-left:2px solid var(--phosphor);border-radius:0 5px 5px 0;
}
.withdraw a{overflow-wrap:anywhere}

/* ---------- the tab that has been open since before the last release ----------

   AT THE FOOT AND FLOATING, which is the whole reason this is not one of the
   two banners at the top. Those are about the person — an address they have not
   confirmed, somebody looking at their screen — and both earn the space they
   take. This one is about the software, and pushing a lesson down the page to
   say so would cost more than what it reports.

   IT IS THE PANEL'S OWN COLOURS AND NOT A STATE COLOUR. `--amber` means "this
   went wrong or is about to" and red is what the viewing banner uses for a
   restraint; neither is true here. Nothing is broken, nothing is urgent, and a
   notice that shouted would be the second thing in this interface that cries
   wolf. The border is `--phosphor`, which is the brand and reads as "from us".

   THE BUTTON IS SPELLED OUT rather than reusing `.btn`. `portal.css` is the
   copied stylesheet and `.btn` is its class; a rule here naming it would land
   on every button in the interface, which is exactly the failure `check-css`
   exists to catch. */
.stale-banner{
  position:fixed;left:clamp(12px,3vw,24px);bottom:clamp(12px,3vw,24px);z-index:70;
  max-width:min(420px,calc(100vw - 24px));
  align-items:center;gap:12px;flex-wrap:wrap;
  padding:12px 14px;
  background:var(--panel);color:var(--paper);
  border:1px solid var(--wire);border-left:3px solid var(--phosphor);
  border-radius:8px;box-shadow:0 10px 30px rgba(0,0,0,.35);
  font-size:.84rem;line-height:1.5;
}
.stale-banner:not([hidden]){display:flex}
.sb-text{flex:1 1 220px;min-width:0}
.sb-reload{
  flex:0 0 auto;cursor:pointer;
  padding:7px 14px;border-radius:6px;
  font:inherit;font-weight:600;
  color:var(--ink);background:var(--phosphor);border:1px solid var(--phosphor);
}
.sb-reload:hover{filter:brightness(1.08)}


/* ==========================================================================
   The notice that the platform is being written.

   IT IS THE PANEL'S COLOURS WITH A PHOSPHOR EDGE, on the `stale-banner`'s
   reasoning and for the same reason: `--amber` means "this went wrong or is
   about to" and red is the viewing banner's restraint. Neither is true. Being
   unfinished is not a fault, and a notice that shouted would be the second
   thing in this interface crying wolf.

   IT CARRIES THE 64px ITSELF when it is shown. `.verify-banner` holds that
   margin to clear the fixed bar, and two elements both holding it would stack
   two gaps — the bug `body.banner-on .portal{padding-top:0}` already exists to
   avoid one layer down. So this one takes the margin and gives it up again for
   whichever banner comes next.
   ========================================================================== */
.dev-banner{
  margin-top:64px;
  align-items:center;gap:10px;flex-wrap:wrap;
  padding:9px clamp(16px,4vw,28px);
  background:var(--panel);
  border-bottom:1px solid var(--wire);
  box-shadow:inset 3px 0 0 var(--phosphor);
  font-size:.86rem;line-height:1.45;color:var(--paper-dim);
}
.dev-banner:not([hidden]){display:flex}
.db-text{flex:1 1 auto;min-width:0}
.db-text strong{color:var(--phosphor);font-weight:600}
/* WHICH BUILD THIS IS, at the far end of the same row. `.db-text` already takes
   the space, so this needs no margin of its own; it wraps under on a narrow
   screen because the banner does, which is where a version belongs anyway.

   IT IS SMALL AND RINGED, AND IT IS NOT FADED. The sentence beside it is the
   notice; this is the footnote somebody reads when they are reporting
   something, and a number competing with the words would be the banner arguing
   with itself. The first version said that with `opacity:.8`, which is the
   mistake the paragraph at the top of this block already warns about: it took
   `--paper-dim` to 3.90:1 on the light page, under AA's 4.5, and axe found it
   on every screen the banner is on — 42 of them.

   So the recession is the SIZE and the RING, which cost nothing anybody has to
   be able to see. The colour is the one the banner already uses for its second
   sentence: 6.12:1 light, 6.82:1 dark. */
.db-version{
  flex:0 0 auto;
  font-size:.82em;letter-spacing:.02em;
  color:var(--paper-dim);
  padding:1px 7px;
  border:1px solid var(--wire);border-radius:999px;
}
body.dev-on .verify-banner{margin-top:0}
body.dev-on .portal{padding-top:0}
