/* ============================================================================
 * skin-neu.css — Neumorphism. HAND-WRITTEN, and deliberately not in skins.css.
 *
 * skins.css is generated and states its own contract: "Colour-only:
 * radius/spacing untouched." Neumorphism is not a palette. It is a SURFACE
 * treatment — the panel and the page are the same colour, and what separates
 * them is a pair of shadows, one light from the top-left and one dark from the
 * bottom-right, instead of a border. Putting that in the generated file would
 * either break its contract or be erased the next time it is generated.
 *
 * THE FAILURE MODE, NAMED SO IT IS NOT REPEATED. Neumorphism goes wrong by
 * being beautiful and unreadable: everything drifts toward one mid-grey, text
 * loses contrast, and a focused field looks identical to an unfocused one. So:
 *
 *   · the INK is not softened. Text keeps the base theme's contrast.
 *   · borders are not removed, they are made to match the ground — which means
 *     a high-contrast or forced-colours display still gets a real edge.
 *   · focus keeps a visible ring. A soft shadow is not a focus indicator.
 *   · anything that is a STATE rather than a surface — a red overdue cell, a
 *     green paid one, a danger button — keeps its colour. Those carry meaning
 *     and are not decoration.
 * ==========================================================================*/

[data-skin="neu"] {
  /* The ground and the panel are the SAME. That is the whole idea: shapes are
     extruded from one continuous surface rather than laid on top of it. */
  --bg: #e8ecf2;
  --panel: #e8ecf2;
  --panel-2: #e2e7ee;
  --ink: #2b3442;              /* full-strength text — this is what keeps it readable */
  --ink-soft: #5d6675;
  --line: #dbe1e9;
  --line-strong: #c7cfda;
  /* MEASURED against the panel these sit on (#e8ecf2), not eyeballed. Lifting
     the ground from white to a mid grey costs every accent about a fifth of its
     contrast, which is precisely how this style ends up beautiful and
     unreadable. Both of these are real running text — --brand is the ACTIVE nav
     item, --accent is links and small labels — and both failed AA on the panel:
         --brand   #3f6cd4 → 4.11:1        --accent  #0f7a8a → 4.25:1
     Each is walked darker along its own hue only until it clears 4.5, so the
     palette is unchanged to the eye and correct to a contrast checker. */
  --brand: #3b66c7;              /* was #3f6cd4 · 4.11 → 4.53 */
  --brand-2: #6d8fe0;            /* 2.66 — a GRADIENT STOP, chart fill and tile
                                    background, never text on the panel. Left as
                                    the light end of the gradient on purpose;
                                    darkening it to pass would flatten every
                                    gradient to fix a colour nobody reads. */
  --accent: #0e7584;             /* was #0f7a8a · 4.25 → 4.55 */
  --good: #1c7a44;
  --warn: #9a5b08;
  --bad: #c02b2b;
  --radius: 18px;
  --r-sm: 12px;

  /* ── THE ELEVATION LADDER ────────────────────────────────────────────────
   * Ported from ai-aidubooking (apps/site/styles/themes.css, the canonical
   * [data-theme="neu"] block), which had already solved the thing this file
   * got wrong.
   *
   * THE BUG IT NAMES: one elevation used everywhere. A 6px offset with a 14px
   * blur is a convincing bevel on a 500px card and an indistinct smudge on a
   * 30px chip — so small controls dissolve into their own shadow while the
   * panels behind them look right. That is precisely what `--shadow` was doing
   * here, on everything from a tag to a page-wide panel.
   *
   * Three rungs, each roughly doubling, blur always ~2x the offset. Holding
   * that ratio is what keeps one soft light source consistent across sizes;
   * vary it per element and the page stops looking lit from one direction.
   *
   *   nu-1   under ~44px    tags, chips, small buttons, dots
   *   nu-2   44-160px       buttons, inputs, selects, avatars
   *   nu-3   panels, cards, modals
   *
   * Both shadow colours are bare triplets so the alpha is tunable in one
   * place. The dark one is THE GROUND AT ABOUT 30% LESS LIGHT, not grey — a
   * neutral-grey shadow on a blue-tinted sheet reads as dirt. */
  --nu-d: 149 165 195;
  --nu-l: 255 255 255;

  --nu-1:  4px  4px  8px rgb(var(--nu-d) / .70),
          -3px -3px  6px rgb(var(--nu-l) / .80);
  --nu-2:  7px  7px 14px rgb(var(--nu-d) / .70),
          -6px -6px 12px rgb(var(--nu-l) / .85);
  --nu-3: 14px 14px 30px rgb(var(--nu-d) / .62),
         -11px -11px 24px rgb(var(--nu-l) / .88);

  --nu-1-in: inset  2px  2px  4px rgb(var(--nu-d) / .70),
             inset -2px -2px  4px rgb(var(--nu-l) / .90);
  --nu-2-in: inset  5px  5px 10px rgb(var(--nu-d) / .70),
             inset -4px -4px  9px rgb(var(--nu-l) / .92);
  --nu-3-in: inset  9px  9px 18px rgb(var(--nu-d) / .68),
             inset -8px -8px 16px rgb(var(--nu-l) / .92);

  /* THE FACE STRADDLES THE GROUND, it does not sit above it. The booking notes
     are worth repeating because it is the mistake that makes the whole style
     look cheap: if the face runs BRIGHTER than the page at its lit corner, the
     object stops looking extruded from the sheet and starts looking like a
     glossy pill dropped onto it. Ground #e8ecf2, face a few points either side,
     no borders — the shadows alone carry the form. */
  --nu-face: linear-gradient(145deg, #edf1f7, #dfe4ec);
  --nu-well: linear-gradient(145deg, #dde2ea, #eef1f7);

  /* `--shadow` stays, pointed at the panel rung, so every existing rule that
     asks for it keeps working untouched. The rungs below re-assign it by size. */
  --shadow: var(--nu-3);
  --neu-in: var(--nu-2-in);
}

/* The dark side of the same idea. Neumorphism in the dark is a real look, and
   leaving it out would mean the skin silently fights whoever has dark mode on. */
[data-skin="neu"][data-theme="dark"],
[data-skin="neu-dark"] {
  --bg: #232733;
  --panel: #232733;
  --panel-2: #272c39;
  /* #e9edf5 measured 12.70:1 here — over the comfort ceiling documented in
     style.css's dark block, and the glare it causes is worse on this skin than
     on the flat one, because every surface is already a soft gradient and the
     bloom off the type has nowhere crisp to stop. 10.91:1 instead. */
  --ink: #d6dde9;
  --ink-soft: #a3acbd;
  /* --ph and --on-fill were NOT declared here, and both matter. [data-skin]
     can be set on its own: "neu-dark" is a skin the user picks, not a theme, so
     it applies with data-theme absent, and the two names then fell through to
     the LIGHT :root — --on-fill resolving to #fff put white text on --brand
     #7ea3f0 at 2.50:1, a straight AA failure on every filled chip and primary
     button in the skin. Declared here, they follow the skin either way. */
  --ph: #8f99ad;         /* 5.20:1 on --panel, 4.87:1 on --panel-2 */
  --on-fill: #171b24;    /* dark ink for bright fills — 6.04:1 at its worst */
  --line: #2b3040;
  --line-strong: #3a4152;
  --brand: #7ea3f0;
  --brand-2: #9db9f5;
  --accent: #4fc3d6;
  --good: #45c98a;
  --warn: #e0a445;
  --bad: #f0736a;
  --radius: 18px;
  --r-sm: 12px;
  /* The same ladder, in the dark. These MUST be defined here: the size rules
     below ask for var(--nu-1..3) unconditionally, and a missing custom property
     makes box-shadow invalid at compute time — every surface in dark neu would
     lose its shadow entirely. Same offsets and blurs, only the two colours
     change: the "dark" side is near-black and the "light" side is a lifted grey,
     because in the dark the highlight is the scarcer of the two and doing it in
     white blows the edge out. */
  --nu-d: 12 15 22;
  --nu-l: 58 66 84;

  --nu-1:  4px  4px  8px rgb(var(--nu-d) / .60),
          -3px -3px  6px rgb(var(--nu-l) / .45);
  --nu-2:  7px  7px 14px rgb(var(--nu-d) / .62),
          -6px -6px 12px rgb(var(--nu-l) / .48);
  --nu-3: 14px 14px 30px rgb(var(--nu-d) / .66),
         -11px -11px 24px rgb(var(--nu-l) / .50);

  --nu-1-in: inset  2px  2px  4px rgb(var(--nu-d) / .60),
             inset -2px -2px  4px rgb(var(--nu-l) / .45);
  --nu-2-in: inset  5px  5px 10px rgb(var(--nu-d) / .62),
             inset -4px -4px  9px rgb(var(--nu-l) / .48);
  --nu-3-in: inset  9px  9px 18px rgb(var(--nu-d) / .66),
             inset -8px -8px 16px rgb(var(--nu-l) / .50);

  --nu-face: linear-gradient(145deg, #272c39, #1f232e);
  --nu-well: linear-gradient(145deg, #1e222c, #282d3a);

  --shadow: var(--nu-3);
  --neu-in: var(--nu-2-in);
}

/* ---- the surfaces themselves ------------------------------------------- */
[data-skin^="neu"] .card,
[data-skin^="neu"] .stat {
  border-color: var(--line);            /* matches the ground; still a real edge in forced-colours */
  box-shadow: var(--shadow);
}
/* ── the rungs, applied by SIZE ──────────────────────────────────────────────
   The whole point of the ladder. A tag and a page-wide panel must not carry the
   same shadow, or the small thing dissolves into its own smudge while the big
   one looks right. Everything here is scoped to [data-skin^="neu"] and lives in
   THIS file, so no module's own stylesheet is touched — the rules simply win by
   specificity while the skin is on, and vanish with it.
   Both themes use the same rungs: the tokens carry the colour difference. */
[data-skin^="neu"] .tag,
[data-skin^="neu"] .chip,
[data-skin^="neu"] .pill,
[data-skin^="neu"] .btn.sm,
[data-skin^="neu"] .tb-icon { box-shadow: var(--nu-1); }

[data-skin^="neu"] .btn { border-color: var(--line); box-shadow: var(--nu-2); }

[data-skin^="neu"] .modal,
[data-skin^="neu"] .side { box-shadow: var(--nu-3); }

/* ── the capability cards ────────────────────────────────────────────────────
   These were the one screen still drawn flat: bordered white boxes sitting ON
   the soft ground rather than extruded from it, which is the single thing that
   makes neumorphism look half-applied. The tree is three sizes, so it takes
   three rungs — the card, the root node you give the app, and the smaller
   output nodes it hands back.
   Scoped here rather than in css/homecards.css so that module is untouched;
   the shapes and spacing are entirely its own, only the surface changes. */
[data-skin^="neu"] .hc-card {
  background: var(--nu-face);
  border: 0;
  box-shadow: var(--nu-3);
}
[data-skin^="neu"] .hc-n {
  background: var(--nu-face);
  border: 0;
  box-shadow: var(--nu-1);
}
[data-skin^="neu"] .hc-n-in { box-shadow: var(--nu-2); }
/* Pressed, not painted: the one interaction this material explains better than
   a flat design. Hover lifts, the tap sinks it into the sheet. */
[data-skin^="neu"] button.hc-n:hover { box-shadow: var(--nu-2); border: 0; }
[data-skin^="neu"] button.hc-n:active { box-shadow: var(--nu-1-in); transform: none; }
/* The connector rails are drawn against the old bordered look; on this ground
   the strong line reads as a scratch. */
[data-skin^="neu"] .hc-row-in,
[data-skin^="neu"] .hc-row-out { border-color: var(--line); }
/* PRESSED IS PRESSED IN. The one interaction neumorphism actually explains
   better than a flat design: an active control sinks into the surface. */
[data-skin^="neu"] .btn:active,
[data-skin^="neu"] .btn.primary { box-shadow: var(--neu-in); }
[data-skin^="neu"] .btn:hover { border-color: var(--brand-2); }

/* Inputs are carved IN rather than raised — the reverse of a button, which is
   how a person tells "I type here" from "I press here" without reading. */
[data-skin^="neu"] input:not([type=checkbox]):not([type=radio]),
[data-skin^="neu"] select,
[data-skin^="neu"] textarea {
  border-color: var(--line);
  box-shadow: var(--neu-in);
  background: var(--panel);
}
/* ...and a glyph sitting INSIDE one of those wells is ETCHED INTO it, not laid
   on top of it. The search icon was the case that made this obvious — as a
   colour emoji it read as a sticker dropped into the field, which is the exact
   failure this file's header names: the surface is supposed to be one continuous
   sheet, and anything painted onto it breaks that in a way no amount of tinting
   fixes.
   THE DIRECTION IS NOT ARBITRARY. The rule directly above uses --neu-in, which
   is var(--nu-2-in): the dark inset sits at +5/+5 and the light inset at -4/-4.
   Every `-in` token in this file follows that same sign convention (--nu-1-in is
   +2/+2 dark against -2/-2 light), so a recess here is always lit from the
   TOP-LEFT, and the interior wall that catches the light is the BOTTOM-RIGHT
   one. Hence the white at +1/+1 and the faint dark above it at -1/-1, which is
   the lip of the groove. Reverse the pair and the icon pops out of the sheet
   instead of into it.
   drop-shadow and not box-shadow: box-shadow traces the <svg>'s bounding
   RECTANGLE, drop-shadow traces the drawn strokes, and only the second reads as
   a line cut into the surface rather than a shadowed tile.
   Scoped to the skin because --nu-d/--nu-l exist only under it (they are defined
   twice, once for light and once for dark, so this survives both); with any
   other skin on, .gs-ico keeps the flat --ink-soft glyph style.css gives it and
   no `filter` is declared at all. Specificity: 0-0-3-1 (attribute + two classes
   + element) against style.css's 0-0-2-1, and this file loads later regardless. */
[data-skin^="neu"] .gs-ico svg.lu {
  filter: drop-shadow(1px 1px 0 rgb(var(--nu-l) / .95))
          drop-shadow(-1px -1px 1px rgb(var(--nu-d) / .55));
}
/* A SOFT SHADOW IS NOT A FOCUS INDICATOR. Keyboard focus keeps a real ring, in
   the accent colour, on top of whatever the surface is doing. */
[data-skin^="neu"] :focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* ---- what must NOT go soft ---------------------------------------------
   A state is not a surface. An overdue fee, a failed pupil, a danger button and
   a warning bar carry meaning in their colour; flattening them into the mid-tone
   would make the skin prettier and the app wronger. */
[data-skin^="neu"] .btn.danger { border-color: var(--bad); color: var(--bad); }
[data-skin^="neu"] .tag { box-shadow: none; }
[data-skin^="neu"] .fc-grid td.fc-cell,
[data-skin^="neu"] .att-reg td,
[data-skin^="neu"] table.data td,
[data-skin^="neu"] table.data th { box-shadow: none; }

/* ---- THE SIDEBAR --------------------------------------------------------
   The nav was the last piece of chrome still drawn flat: a tinted rectangle for
   the page you are on, a grey fill on hover, and nothing else — so the one
   control a person uses more than any other was the one that did not belong to
   the rest of the app.

   WHICH WAY EACH STATE GOES, and why:
     · the page you are ON is pressed IN. That is this file's own rule for an
       active control ("an active control sinks into the surface"), and it is the
       right metaphor here too — the current page is the button that is still
       held down. It keeps the accent colour, because that is what makes it
       findable at a glance and a shadow is not a colour.
     · a row you are POINTING AT lifts slightly. Raised means "you may press
       this"; pressed means "this one is already pressed".
   Both use the nu-1 rung, not nu-2: a nav row is about 34px tall, and the ladder
   at the top of this file puts anything under ~44px on nu-1. A heavier shadow on
   a short row is the smudge that made small controls look broken before. */
[data-skin^="neu"] .nav a,
[data-skin^="neu"] .nav-advtoggle { transition: box-shadow .14s ease, background .14s ease, color .14s ease; }

[data-skin^="neu"] .nav a:hover,
[data-skin^="neu"] .nav-advtoggle:hover {
  background: var(--panel);
  box-shadow: var(--nu-1);
}
[data-skin^="neu"] .nav a.active,
[data-skin^="neu"] .nav-advtoggle.active {
  background: var(--panel);
  box-shadow: var(--nu-1-in);
}
/* Pressed AND pointed at is still pressed — without this the hover raise wins on
   the row you are already on, and the current page appears to pop out from under
   the cursor. */
[data-skin^="neu"] .nav a.active:hover,
[data-skin^="neu"] .nav-advtoggle.active:hover { box-shadow: var(--nu-1-in); }

/* THE SUB-LIST IS NOT A SURFACE OF ITS OWN.
   This rule used to press the whole open group into the sidebar (--nu-1-in), on
   the reasoning that a recess reads as nesting without needing a border. That
   was true in isolation and wrong in place: the rows INSIDE the group already
   carry the depth — the page you are on is pressed in, the row you point at
   lifts (the block above) — so an expanded heading drew a depression inside a
   depression. Reported from the Students group, where the selected row looked
   like a chip floating in a well, and the ladder at the top of this file only
   ever allows one level of depth at a time.
   The wrapper is now flat and depth belongs solely to the rows. The left indent
   and the row padding stay exactly as they were, so nothing inside moves: with
   the hairline suppressed on the line below, that indent is the only thing left
   saying these rows belong to the heading above them. border-radius is kept
   because the drag-lane background in style.css lands on this same element. */
[data-skin^="neu"] .nav-adv { border-left-color: transparent; }
[data-skin^="neu"] .nav-adv.open {
  border-radius: var(--r-sm, 8px);
  box-shadow: none;
  padding: 4px 4px 4px 10px;
}
/* A separator between raised things wants to be a groove, not a line. */
[data-skin^="neu"] .nav-sep {
  height: 2px; background: transparent;
  box-shadow: inset 0 1px 1px rgb(var(--nu-d) / .55), inset 0 -1px 1px rgb(var(--nu-l) / .85);
}

/* ---- PAPER IS NOT CHROME ------------------------------------------------
   The rule below already said the right thing — "the skin stops at the edge of
   the page" — and then only enforced it inside @media print. But a school reads
   the document on SCREEN first: the transfer certificate, the mark sheet and the
   report card are previewed, checked and corrected long before anyone presses
   print, and that preview IS the piece of paper.

   What that cost, reported with a screenshot of a leaving certificate: every
   filled value on one is an <input> overlaid on the printed line (.cert-ov).
   The input rule above gives every input an opaque panel background and an inset
   shadow — and `[data-skin^="neu"] input` (0-1-1) outranks
   `.cert-ov { background: transparent }` (0-1-0). So each value became a raised
   grey pill painted over the certificate's own words:

     "Certified that ▓▓▓▓▓▓ Son/Daughter of ▓▓▓▓▓▓ an inhabitant of ▓▓▓▓▓▓"

   The document was unreadable — and it is the document a child carries to their
   next school.

   So the skin stops at the edge of the page on screen too. Only what the SKIN
   added is undone: the shadows on surfaces, and the background it painted under
   controls. Everything the document's own stylesheet does is untouched, because
   that is the paper's design and not this file's business.

   TWO THINGS THIS GOT WRONG THE FIRST TIME, both measured on the running app:

   1. THE LIST WAS SHORT. It named the eight pages that were on screen when the
      certificate was reported. Nine more surfaces are paper by the same
      definition — a page-sized white sheet the school prints — and every one of
      them was still handing its fields the grey pill:
        .result-sheet  the consolidated results sheet (A4/A3, its own drop shadow)
        .sr-page       the college Subject Registration Form
        .awc-cert      an award certificate, 297x210mm
        .cd-card       the card being drawn in the card designer
        .fee-receipt   a fee receipt, which is a document a parent keeps
        .sum-doc       the printable class summary
      Measured before the change, on every one of the six: fields computed
      `background: rgb(232, 236, 242)` and `inset 5px 5px 10px …`. Identical to
      the certificate in the screenshot.

      PAGES ONLY — never a wrapper that HOLDS pages. .result-doc, .rc-print and
      .cnote-print are those wrappers, and listing them looked equivalent and was
      not: every page inside a listed element is a descendant, so `.result-doc *`
      matched `.result-sheet` and flattened the very paper shadow point 2 below is
      about. Caught by measuring — .result-sheet still read `none` after the fix
      that was supposed to restore it. Each wrapper holds only pages that are
      listed here in their own right, so nothing is lost by leaving them out.

   2. IT FLATTENED THE PAPER ITSELF. The selector included the page element, so
      `box-shadow: none` also killed the drop shadow the DOCUMENT's own stylesheet
      gives it — .result-sheet's `0 2px 16px rgba(0,0,0,.14)`, .cnote-page's
      `0 2px 14px`, .awc-cert's `0 4px 22px`. That shadow is not the skin bleeding
      in; it is what makes a sheet look like paper lying on a desk, and this file
      had already said it was none of its business. So the rule now applies to
      what is INSIDE the page — `> *` territory — and leaves the page alone.
      Checked: none of these roots also carries `.card` or `.stat`, so the skin
      puts no shadow on them and there is nothing here left to undo. */
[data-skin^="neu"] :is(.cert-page, .sheet, .st-page, .cnote-page, .qp-paper, .rc-stage, .idc-card, .af-card,
                       .result-sheet, .sr-page, .awc-cert, .cd-card, .fee-receipt, .sum-doc) * {
  box-shadow: none;
  text-shadow: none;
}
/* A control ON the paper is part of the paper: it must show its value and
   nothing else. The document's own hover/focus tint still applies — this removes
   only the surface the skin painted underneath it. */
[data-skin^="neu"] :is(.cert-page, .sheet, .st-page, .cnote-page, .qp-paper, .rc-stage, .idc-card, .af-card,
                       .result-sheet, .sr-page, .awc-cert, .cd-card, .fee-receipt, .sum-doc)
  :is(input:not([type=checkbox]):not([type=radio]), select, textarea) {
  /* box-shadow HAS to be repeated here, not left to the blanket `… *` rule
     above. That rule is 0-2-0 (attribute + :is-of-classes + `*`), while the
     skin's own input rule is 0-3-1 — attribute, two :not()s and an element —
     so the blanket loses and the carved-in shadow survived on a transparent
     background: the pills were gone and the dents were still there. Measured,
     not guessed: computed style still read `inset 5px 5px 10px` on all 19
     fields of the certificate after the first attempt. */
  box-shadow: none;
  background: transparent;
  border-color: currentColor;
}

/* ---- THE FRONT PAGE -----------------------------------------------------
   aidued.com's landing page was the last flat surface: white cards with hairline
   borders sitting ON the soft ground rather than extruded from it, which is
   exactly the half-applied look the capability cards were fixed for above.

   IT IS SCOPED HERE, NOT EDITED THERE, AND THAT IS NOT A PREFERENCE. The front
   page is GENERATED — js/landing.js is built from a preview file that is not in
   the repo, and the standing rule is regenerate, never hand-edit. A skin rule
   written into the generated file would be erased by the next regeneration and
   would also outlive the skin. So it lives in the skin's own file, scoped under
   .lp7 (the wrapper landing.js puts round everything it owns), and it appears
   and disappears with the skin like every other rule here.

   MEASURED FIRST, because a selector that matches nothing is invisible work:
   on the signed-OUT page `document.documentElement.dataset.skin` is already
   "neu" and .lp7 is present, so these match. The class names below were read off
   the live page, not guessed — the landing page uses short unprefixed names
   (.mod, .panel, .claim) inside .lp7 rather than an lp7- prefix.

   WHAT WAS ALREADY RIGHT AND IS LEFT ALONE: the buttons. `.btn` is the app's own
   class and the rule near the top of this file already reaches inside .lp7, so
   every button on the front page was measured carrying --nu-2 before this block
   existed. Adding a second rule for them would be a copy that could drift. */
/* ── THE GROUND ITSELF, WHICH IS WHAT THE FIRST PASS MISSED ─────────────────
   Adding shadows to the front page did almost nothing, and the reason is worth
   writing down: the page was WHITE and the cards were WHITE. A raised shadow on
   white-over-white is a smudge. Neumorphism is not a shadow you add, it is one
   continuous surface that things are pushed out of and pressed into — and that
   only starts working once the ground stops being paper.

   .lp7 carries its own palette (landing.js defines --paper/--tint/--line on it,
   independent of the app's tokens), so the whole redesign is FOUR token
   remappings rather than a fight with eighty-three rules. Every existing rule
   that says `background:var(--paper)` then lands on the neu ground for free, and
   the generated file is still never touched.

   --line goes to the ground colour rather than to `transparent`: a border that
   still occupies its 1px keeps every layout exactly where it was, and on this
   material an edge is drawn with light instead of ink anyway. Anything that
   genuinely needs to read as a division becomes a groove further down. */
[data-skin^="neu"] .lp7 {
  --paper: #e8ecf2;                /* was #ffffff — the ground everything is extruded from */
  --tint:  #e4e9f0;                /* was #eff6fc — a section band, now a shade of the ground */
  --tint2: #eaeef4;                /* was #f7fafd */
  --line:  #e8ecf2;                /* was #dfe8f1 — hairlines stop being ink */

  /* CONTRAST, MEASURED RATHER THAN HOPED FOR. Lifting the ground off white costs
     every colour about a fifth of its contrast — this file's own header says so,
     and it is exactly how the style ends up beautiful and unreadable. Computed
     against #e8ecf2, four of the landing's text colours came out under AA:
        --faint  2.46   --warn 2.86   --good 3.67   --bad 4.41
     Three of those were ALREADY under AA on white (2.91 / 3.40 / 4.36), so this
     is not damage the skin did — but it is damage the skin would inherit, and
     they are real running text: .st.g/.w/.b are status lines, --good is the ✓ on
     every tick list, --faint is the photo captions and "was" lines.
     Each walked darker along its own hue only until it clears 4.5, so the page
     looks unchanged to the eye and correct to a contrast checker.
     --ink 13.91, --navy 11.38 and --blue 4.83 all pass untouched.

     AND THEN MEASURED AGAIN ON THE REAL SURFACE, which caught a miss. The first
     pass compared against the FLAT ground #e8ecf2, but body text sits on a card,
     and a card face is --nu-face — a gradient running to #dfe4ec at its dark
     end. Against that, --soft fell to 4.29 and the corrected --faint to 4.20:
     both back under AA, on the surface most of the page's prose actually sits
     on. Re-walked against the darkest end rather than the average, because the
     bottom-right corner of every card is where the text is faintest and that is
     the corner nobody checks. */
  --soft:  #576779;                /* was #5a6b7d · flat 4.89, card face 4.54 */
  --faint: #5d6772;                /* was #8a99a9 · flat 4.85, card face 4.51 */
  --good:  #0d7a54;                /* 3.67 → 4.51 */
  --warn:  #9b5c14;                /* 2.86 → 4.50 */
  --bad:   #c2392a;                /* 4.41 → 4.53 */

  background: var(--paper);
}

/* A band that was a different white is now a different DEPTH. The two hairlines
   that separated it become one soft groove, which is how this material divides
   things — and the hero's white-to-tint gradient flattens to the ground on its
   own once both stops are the same colour. */
[data-skin^="neu"] .lp7 :is(.sec.tint, .sec.after) {
  border-top: 0; border-bottom: 0;
  box-shadow: inset 0 1px 2px rgb(var(--nu-d) / .30), inset 0 -1px 2px rgb(var(--nu-l) / .55);
}

[data-skin^="neu"] .lp7 .nav {
  background: var(--panel);
  backdrop-filter: none;                  /* the ground and the bar are one surface; blur implies two */
  box-shadow: inset 0 -1px 1px rgb(var(--nu-d) / .45), inset 0 -2px 2px rgb(var(--nu-l) / .70);
}
/* A nav link is 31px — under the ladder's ~44px line, so nu-1, and only on
   hover. At rest these are words, not controls, and giving every one of them a
   resting shadow turns a header into a row of buttons. */
[data-skin^="neu"] .lp7 .lk { border-radius: var(--r-sm, 12px); transition: box-shadow .14s ease, background .14s ease; }
[data-skin^="neu"] .lp7 .lk:hover { background: var(--panel); box-shadow: var(--nu-1); }

/* The four pills under the hero — "Your format, kept", "Works offline". They are
   31px, so nu-1 by the ladder, and their hairline border becomes the ground
   because on this material an edge is drawn with light rather than ink. The
   999px radius is the page's own and is left exactly as it is.

   TARGETED BY POSITION, NOT BY NAME, because they have no class: they are bare
   <span> children of .chips. The first attempt styled `.claim` on the assumption
   that it was these — it is not. `.lp7 .short .claim` is a DASHED SEPARATOR over
   a line of italic prose ("A class of 40, printed, in the time it takes to make
   tea."), and raising a sentence into a pill is exactly the kind of damage that
   guessing at class names does. Read off the live page, not inferred. */
[data-skin^="neu"] .lp7 .chips > span {
  background: var(--nu-face);
  border-color: transparent;
  box-shadow: var(--nu-1);
}

/* The card decks. Sized by the ladder, not by what they are called:
   .mod is 141px → nu-2; .panel 356, .p4 381 and .reccard 551 → nu-3. */
[data-skin^="neu"] .lp7 .mod {
  background: var(--nu-face); border: 0; border-radius: var(--radius);
  box-shadow: var(--nu-2);
}
[data-skin^="neu"] .lp7 :is(.panel, .reccard) {
  background: var(--nu-face); border-color: transparent;
  box-shadow: var(--nu-3);
}
/* .p4 and .short each carry ONE coloured edge that is a state marker, so only
   the other three sides are neutralised. `border-color: transparent` on the
   shorthand looked equivalent and was not: the landing sets a base
   `border-top:4px solid var(--blue)` and then recolours children 2-4 with
   :nth-child. The blanket rule out-specified the BASE but not the nth-child
   overrides, so cards 2, 3 and 4 kept their green/amber/navy and card ONE lost
   its blue — one card in four, silently, which is exactly the kind of thing a
   glance at a screenshot does not catch. Measured: p4_0 was rgba(0,0,0,0). */
[data-skin^="neu"] .lp7 .p4 {
  background: var(--nu-face); box-shadow: var(--nu-3);
  border-right-color: transparent; border-bottom-color: transparent; border-left-color: transparent;
  border-top: 4px solid var(--blue);
}
[data-skin^="neu"] .lp7 .short {
  border-top-color: transparent; border-right-color: transparent; border-bottom-color: transparent;
  border-left: 4px solid var(--blue);
}
/* .p4 keeps its 4px top edge, and .short keeps its 4px LEFT edge. Those are
   STATE markers — each names which of the four things the card is about, and
   they are colour-coded in sequence — and this file's own rule is that a state
   is not a surface. Only the hairline round the rest of the card goes. */
[data-skin^="neu"] .lp7 .short {
  background: var(--nu-face);
  box-shadow: var(--nu-2);
}

/* The quoted callout is PRESSED IN, not raised. It is an aside — something the
   page steps into rather than hands you — and this material can say that where a
   flat design can only tint a box. Its own blue tint is kept at a whisper so the
   recess still reads as the same surface. */
[data-skin^="neu"] .lp7 .cipher {
  background: var(--nu-well);
  border-color: transparent;
  box-shadow: var(--nu-1-in);
}

/* The dashed rule over the closing line of a story card. A separator between
   raised things wants to be a groove, not a dash — same decision as .nav-sep. */
[data-skin^="neu"] .lp7 .short .claim {
  border-top: 0;
  padding-top: 16px;
  box-shadow: inset 0 1px 1px rgb(var(--nu-d) / .45), inset 0 2px 2px rgb(var(--nu-l) / .75);
}

/* ── THE DARK BAND ──────────────────────────────────────────────────────────
   .sec.navy is a deliberate dark section and it STAYS dark — inverting it to the
   light ground would flatten the one rhythm change the page has. But neumorphism
   in the dark is a real look, and this file already carries the palette for it:
   near-black for the shadow, a lifted grey for the highlight, because in the
   dark the highlight is the scarcer of the two and doing it in white blows the
   edge out. So the cards inside it are extruded from the NAVY rather than
   floating on it as translucent rectangles. */
[data-skin^="neu"] .lp7 .sec.navy .sg,
[data-skin^="neu"] .lp7 .sec.navy .never {
  background: rgba(255, 255, 255, .04);
  border-color: transparent;
  box-shadow: 7px 7px 14px rgba(4, 14, 26, .55), -6px -6px 12px rgba(255, 255, 255, .055);
}
[data-skin^="neu"] .lp7 .sec.navy .sg .ic {
  box-shadow: inset 2px 2px 4px rgba(4, 14, 26, .55), inset -2px -2px 4px rgba(255, 255, 255, .07);
}
/* The "show me more" pill on the dark band: raised, and pressed when tapped. */
[data-skin^="neu"] .lp7 .more-wide > summary {
  border-color: transparent;
  box-shadow: 4px 4px 8px rgba(4, 14, 26, .5), -3px -3px 6px rgba(255, 255, 255, .06);
}
[data-skin^="neu"] .lp7 .more-wide[open] > summary {
  box-shadow: inset 2px 2px 4px rgba(4, 14, 26, .55), inset -2px -2px 4px rgba(255, 255, 255, .06);
}

/* PRESSED IS PRESSED IN, on the front page too. The app's own .btn rule already
   gives these --nu-2 at rest; what it cannot give them is the tap, because
   .btn-p/.btn-o are the landing's classes and its own :hover rules would win. */
[data-skin^="neu"] .lp7 :is(.btn-p, .btn-o):active { box-shadow: var(--nu-1-in); }
[data-skin^="neu"] .lp7 .btn-o { border-color: transparent; background: var(--nu-face); }

/* ---- THE JOURNEY, WHERE THE DEPTH CARRIES THE ARGUMENT -------------------
   The before/after stages are the one place on this page where the material is
   doing semantic work rather than decoration: the PROBLEM is pressed into the
   surface and the SOLUTION is raised out of it. A reader takes the pair in
   before reading a word, which is what lets the page carry a dozen modules
   without becoming a wall.

   landing.js already ships a flat fallback for both sides — a tint and a soft
   inner line — so the meaning survives with the skin off. These rules replace
   that approximation with the real thing rather than adding a second one. */
[data-skin^="neu"] .lp7 .stage {
  background: var(--nu-face);
  box-shadow: var(--nu-3);
}
[data-skin^="neu"] .lp7 .side.was {
  background: var(--nu-well);
  box-shadow: var(--nu-2-in);
}
[data-skin^="neu"] .lp7 .side.now {
  background: var(--nu-face);
}
/* The step number is a small round control, so nu-1 by the ladder, and it keeps
   the brand fill because it is what makes the sequence findable at a glance. */
[data-skin^="neu"] .lp7 .stage-n { box-shadow: var(--nu-1); }
/* A status badge is a STATE, not a surface — this file's own rule — so it keeps
   its colour and takes no shadow at all. */
[data-skin^="neu"] .lp7 .badge { box-shadow: none; }

/* THE PHOTOGRAPH IS NOT CHROME. .hero-photo carries its own 0 26px 60px drop
   shadow from the page's design, and the paper rule above applies unchanged:
   the skin stops at the edge of an image. Listing it here, doing nothing, so
   that the next person to read this block knows it was considered and left. */

/* Print is ink on paper. Every one of these shadows would come out as grey
   mud on a mark sheet, so the skin stops at the edge of the page. */
@media print {
  [data-skin^="neu"] * { box-shadow: none !important; }
}
