/* ==========================================================================
   Storefront styles for the Gift Studio.

   A scoped subset of the deck's design system. The comps are drawn against
   assets/system.css, which does not exist on the storefront - the site runs
   stock twentytwenty. Rather than load the whole deck stylesheet and fight the
   theme, this carries only what the bundle surfaces need, every rule under
   `.ngs` so nothing leaks into the rest of the site.

   Tokens match build/CONTRACT.md. Where a value here disagrees with the deck,
   the deck wins and this file is wrong.
   ========================================================================== */

.ngs {
  --ink-900:#1C1330; --ink-700:#3A2F52; --ink-600:#584B77; --ink-500:#6B6280;
  --ink-400:#9A93AC; --ink-300:#B4B6C0;
  --line:#E6E1EE; --line-strong:#D8D3E2; --line-soft:#F0EEF4;
  --paper:#FAF8F5; --white:#fff; --indigo-800:#180E30;
  --violet-500:#8D22C3; --violet-600:#7A1EAB; --violet-400:#A63FD8;
  --violet-300:#C77BE8; --violet-200:#E6CDF4; --violet-100:#F0E2F8; --violet-50:#F9F3FC;
  --gold-400:#E6C97A; --gold-700:#8A6B1F; --gold-300:#F0D8B8; --gold-100:#FAF3DC;
  --gold-600:#9A6414;
  --ok-fg:#1F6F4A; --ok-bg:#E6F2EC;
  --stop-fg:#A5201F; --stop-bg:#FBEBEB;
  --on-dark:#fff; --on-dark-muted:#CFC7DE;
  --r-xs:4px; --r-sm:8px; --r-md:12px; --r-lg:16px; --r-pill:999px;
  --s1:4px; --s2:6px; --s3:10px; --s4:14px; --s5:18px; --s6:24px; --s7:30px;
  --s8:36px; --s9:48px; --s10:64px; --s11:80px;
  --ui:'Radio Canada',system-ui,sans-serif;
  --display:'Poppins',system-ui,sans-serif;

  font-family: var(--ui);
  color: var(--ink-900);

  /* THE COMP'S BODY SIZE, and the reason every unsized line on these screens
     ran ~20% large until 0.46.2. `.ngs` set a family and a colour but never a
     size, so the block inherited `twentytwenty`'s 18px body. Every rule that
     names its own size (the headings, .ngs-lead, .ngs-sm) was already drawn
     from the deck and looked right, which is exactly why this hid for so long:
     the text that was wrong was the text nobody had written a size for --
     the money rows, the choice bodies, the tier lines.
     assets/system.css `body` is 15px/1.55. This is that, nothing more. */
  font-size: 15px;
  line-height: 1.55;

  /* THE COMP'S PROPORTION, not an arbitrary cap. The boards are 1280 wide with
     a 56px `.wrap` gutter, so the comp's content is 1168px. A 1120px cap with
     an 18px gutter matched neither: at 1280 it was close, and on a wide display
     the page sat in a narrow column with everything else as margin.

     56px is the comp's gutter exactly. The cap is 1440 rather than 1280 because
     the boards say nothing about screens wider than the one they were drawn on,
     and holding the page at 1168px on a 1920 display is the gutter problem
     again. At 1280 this is pixel-identical to the board. */
  max-width: 1440px;
  margin: 0 auto;
  padding: var(--s8) 56px;
}
.ngs *, .ngs *::before, .ngs *::after { box-sizing: border-box; }

.ngs-h1 { font-family: var(--display); font-weight: 700; font-size: clamp(28px,4vw,42px); line-height: 1.12; margin: 0; letter-spacing: -.01em; }
.ngs-h2 { font-family: var(--display); font-weight: 700; font-size: clamp(20px,2.4vw,27px); line-height: 1.2; margin: 0; }
.ngs-h3 { font-family: var(--display); font-weight: 700; font-size: 17px; line-height: 1.3; margin: 0; }
.ngs-lead { font-size: 16px; line-height: 1.55; color: var(--ink-600); margin: var(--s3) 0 0; max-width: 56ch; }
.ngs-sm   { font-size: 13.5px; line-height: 1.5; color: var(--ink-600); margin: 0; }
.ngs-xs   { font-size: 12px; color: var(--ink-500); margin: 0; }

.ngs-head { margin-bottom: var(--s8); }

/* The featured bundle, held up out of the ground. */
.ngs-feature {
  display: flex; gap: var(--s8); align-items: center;
  background: var(--white); border-radius: var(--r-md);
  padding: var(--s8); border: 1px solid var(--line);
  box-shadow: 0 1px 2px rgba(28,19,48,.04), 0 12px 28px rgba(28,19,48,.07);
}
.ngs-feature > .art { flex: 0 0 42%; }
.ngs-feature-body { flex: 1 1 auto; display: flex; flex-direction: column; gap: var(--s5); min-width: 0; }

/* The moments grid - 4:5 tiles, exactly as the comp draws them. */
.ngs-grid { display: grid; grid-template-columns: repeat(auto-fill,minmax(190px,1fr)); gap: var(--s6); margin-top: var(--s8); }
.ngs-card { display: flex; flex-direction: column; gap: var(--s4); text-decoration: none; color: inherit; }
.ngs-card:hover .art { transform: translateY(-3px); box-shadow: 0 10px 24px rgba(28,19,48,.16); }
.ngs-card .art { transition: transform .22s cubic-bezier(.4,0,.2,1), box-shadow .22s cubic-bezier(.4,0,.2,1); }

.ngs-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; letter-spacing: .02em;
  padding: 4px 11px; border-radius: var(--r-pill);
  background: var(--violet-100); color: var(--violet-500);
}
.ngs-chip--gold { background: rgba(230,201,122,.22); color: var(--gold-700); }
.ngs-chips { display: flex; flex-wrap: wrap; gap: var(--s2); }

/* Money. The struck-through full price sits beside the bundle price, never under it. */
.ngs-money { display: flex; align-items: baseline; gap: var(--s4); flex-wrap: wrap; }
.ngs-price { font-family: var(--display); font-weight: 700; font-size: 26px; letter-spacing: -.01em; }
.ngs-was   { font-size: 14px; color: var(--ink-400); text-decoration: line-through; text-decoration-thickness: 1px; }
.ngs-save  { font-size: 13px; font-weight: 600; color: var(--gold-700); }

.ngs-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); font-size: 13px; color: var(--ink-500); }
.ngs-meta .sep { width: 3px; height: 3px; border-radius: 50%; background: var(--ink-400); display: inline-block; }

/* THE THEME STYLES THE BARE `button` TYPE, and the three declarations below are
   there to undo it. twentytwenty's `button, .button, input[type=submit]` rule sets
   `text-transform: uppercase` and `letter-spacing: 0.0333em` among a dozen other
   things - and a CLASS only beats a TYPE on the properties it actually declares.
   `.ngs-btn` set font, padding, radius and border, so those won.
   `text-transform` it never mentioned, so the theme's won.

   The result shipped from phase B onward: every button on every Gift Studio
   surface rendered in CAPS on the real site - ACCEPT THIS GIFT, OPEN MY GIFT,
   SAVE AND FINISH LATER - while every comp and every local preview showed
   sentence case. Nobody saw it for the reason 0.9.6 already wrote down: A PREVIEW
   WITHOUT THE THEME CANNOT SHOW A THEME CONFLICT. It took a screenshot of a real
   private window.

   Same shape as the `.ngs section` trap from 0.9.5. When this stylesheet relies
   on a default, check what twentytwenty does to that element type first. */
.ngs-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--ui); font-size: 14.5px; font-weight: 600;
  padding: 12px 22px; border-radius: var(--r-pill);
  border: 1px solid transparent; cursor: pointer; text-decoration: none;
  text-transform: none; letter-spacing: normal; line-height: 1.25;
  transition: transform .16s cubic-bezier(.4,0,.2,1), box-shadow .16s cubic-bezier(.4,0,.2,1);
}
.ngs-btn--gift  { background: linear-gradient(140deg,#F0DDA6,#E6C97A); color: #3A2A05; box-shadow: 0 1px 2px rgba(0,0,0,.08); }
.ngs-btn--quiet { background: transparent; color: var(--ink-700); border-color: var(--line); }
.ngs-btn:hover  { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(28,19,48,.13); }

/* THE SECOND THEME LEAK, and a sibling of the CAPS bug that shipped for four
   phases. twentytwenty sets `text-decoration: underline` on `button:hover`,
   `button:focus`, `.button:hover` and `input[type=submit]:hover` (style.css ~867).
   That selector is (0,1,1); `.ngs-btn`'s own `text-decoration: none` is (0,1,0), so
   the theme wins and EVERY Gift Studio button has underlined on hover on the real
   site since phase B.

   The CAPS fix did not cover it, and the specificity arithmetic is why: the theme's
   `text-transform: uppercase` sits on plain `button` at (0,0,1) and loses to a
   class, but adding `:hover` buys it a point and flips the comparison. Two bugs,
   one cause, and only one of them was visible in a screenshot.

   `.ngs-btn:hover` is (0,2,0) and wins. Site-wide here rather than per screen,
   because the leak is site-wide. */
.ngs-btn:hover,
.ngs-btn:focus,
.ngs-btn:active { text-decoration: none; }
.ngs-actions { display: flex; flex-wrap: wrap; gap: var(--s3); }

/* THE THIRD THEME LEAK, and the first one that only shows on a phone.
   twentytwenty's `*, ::before, ::after` sets BOTH `word-break: break-word` and
   `overflow-wrap: break-word` (style.css ~2.8), so the rule lands on every
   element the Gift Studio renders and nothing here was ever written to expect it.

   The two are not the same thing, and the difference is the whole bug:
   `overflow-wrap: break-word` only breaks a word that would otherwise overflow,
   and leaves the element's MIN-CONTENT width at the longest word.
   `word-break: break-word` drops min-content to ONE CHARACTER - so any flex item
   holding text will shrink to a single column of letters rather than refuse.

   On dev at 360px that rendered the compose stepper as `C h o o s e` stacked
   vertically beside its 01, and the Back button as `Bac` over `k`. On a desktop
   pane there is always room, so it was invisible for eleven versions. Found by
   opening the page on a phone, which is the fourth time on this build.

   Reset `word-break` ONLY. The theme's `overflow-wrap` is kept deliberately: a
   recipient's long email address in the preview still has to break somewhere, and
   that is the declaration that does it without collapsing anything. */
.ngs,
.ngs * { word-break: normal; }

/* An empty state that says something, rather than rendering nothing. */
.ngs-empty {
  border: 1px dashed var(--line); border-radius: var(--r-md);
  padding: var(--s8); text-align: center; color: var(--ink-600); background: var(--paper);
}

@media (max-width: 760px) {
  .ngs-feature { flex-direction: column; align-items: stretch; padding: var(--s6); }
  .ngs-feature > .art { flex: 0 0 auto; }
}

/* ==========================================================================
   0.5.0 — the three surfaces.

   The hero is a bleed: it has to escape .ngs's own max-width and padding, and
   it does that with a viewport-width trick rather than by being moved out of
   the wrapper, so one shortcode still produces one block an editor can place.
   ========================================================================== */

.ngs { --indigo-900:#120B22; --indigo-700:#241546; --on-dark:#EDE9F5;
       --on-dark-muted:#CFC7DE; --s7:30px; --s9:48px; --r-lg:16px; }

/* --- THE OVERLAY HEADER'S CLEARANCE -----------------------------------------
   The site header is `neoyug-header-map`'s, not the theme's: `position: fixed`,
   64px (48 on mobile), solid dark, and its clearance setting is **"each template
   reserves its own"**. The plugin pads nothing, so a surface that opens with a
   heading instead of a full-bleed hero loses its first 64px underneath a bar.

   That is exactly what screen 09 did on dev: "Make it personal" sat at 36px
   against a header whose bottom is 64 - the page title of the gift flow's entry
   point, a third of the way behind a dark bar, on a light page. Measured, then
   looked at, then fixed.

   `--ny-clear` is the plugin's OWN published variable for this, on `:root`, and
   using it means the 48px mobile value and any future change come for free. The
   `0px` fallback is the honest default: no header-map, no overlay, no clearance
   needed.

   ONLY the surfaces that need it. The collection page and the storefront grid
   open with a full-bleed hero that is MEANT to run under the header - the site's
   own templates do the same, and their inner wraps clear the bar instead. Adding
   this to `.ngs` wholesale would put a 64px white gap above those heroes. */
/* CLEARANCE PLUS A GAP, and the two are not the same thing (Kunal, 2026-10-07:
   "the header and first text on page doesn't have enough distance").

   `--ny-clear` is EXACTLY the header's height - 64px desktop, 48 mobile - so on
   its own it only stops the title hiding behind the bar. Measured on dev: the
   header's bottom at 64 and the first element's top at 64. Not one pixel between
   a fixed dark bar and the page's opening line.

   `--s9` on top of it is the breathing room, and it is added rather than baked in
   so the plugin's own 48px mobile value keeps working. */
.ngs-compose,
.ngs-sent { padding-top: calc(var(--ny-clear, 0px) + var(--s9)); }

/* The theme spaces the elements this renders inside, and it does it with
   PADDING as well as margin: twentytwenty gives `section` 80px top and bottom,
   which put 208px of dead air between the paths and the band. Resetting only
   the margins fixed nothing on the site and looked fixed locally, because a
   preview without the theme cannot show a theme conflict.
   NOTE the selectors: `.ngs section` (class + type) outranks `.ngs-section`
   (class alone), so each spacing rule has to match that weight or the reset
   silently wins and the sections collapse to zero instead. */
.ngs section { margin: 0; padding: 0; }
.ngs section.ngs-section { margin-top: var(--s9); margin-bottom: 0; }
.ngs section.ngs-section:first-child { margin-top: 0; }

/* Same story for the list and its rows: the theme indents `ol` and spaces
   `li`, and this list is a layout, not prose. */
.ngs .ngs-paths-list { margin: var(--s7) 0 0; padding: 0; list-style: none; }
.ngs .ngs-prow { margin: 0; }
.ngs-muted { color: var(--ink-500); }
.ngs-head--row { display: flex; justify-content: space-between;
                 align-items: flex-end; gap: var(--s6); flex-wrap: wrap; }
.ngs-quiet { font-size: 14px; color: var(--violet-500); text-decoration: none; }
.ngs-quiet:hover { text-decoration: underline; }

/* ---- the hero ---------------------------------------------------------- */

/* A DELIBERATE HEIGHT, not a ratio.
   `aspect-ratio: 16/9` on a 100vw band locks height to the VIEWPORT WIDTH, so
   the wider the monitor the taller the hero -- 1103px at 1960px, headline below
   the fold. Capping that ratio only traded the problem for a crop nobody chose.
   80vh is the thing actually wanted: the same height on every monitor, always
   four fifths of the screen, with the next section's edge showing to say there
   is more. object-fit:cover on the field below crops to fill it, which is what
   a full-bleed band has always done.
   The 16:9 upload is still the right commission -- it simply no longer dictates
   how tall the band is. Brief the art with the subject away from the top and
   bottom edges, because those are what a taller viewport trims. */
.ngs-hero {
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-bottom: var(--s9);
  height: 80vh;
  overflow: hidden;
  background: var(--indigo-900);
  isolation: isolate;
}

/* THE HEADER SITS ON THE HERO, without this plugin touching the header.
   neoyug-header-map renders it `position: fixed`, 49px tall, z-index 9999 -- so
   it already floats over whatever is beneath it. The only thing between them was
   this wrapper's own 36px of padding, which left a 19px strip of page background
   showing below the header and above the band. Cancelling OUR padding for a hero
   that leads the page closes that strip: the band then begins at 32px, the
   header covers to 49px, and the two meet with no seam.
   Only the first child, and only this plugin's own spacing. The header's code
   and settings are not ours to change. */
.ngs > .ngs-hero:first-child { margin-top: calc(-1 * var(--s8)); }

.ngs-fields, .ngs-field { position: absolute; inset: 0; }
.ngs-field { opacity: 0; transition: opacity .6s ease; }
.ngs-field.is-on { opacity: 1; }
.ngs-field .art { width: 100%; height: 100%; border-radius: 0; }
.ngs-field .ngs-art-img,
.ngs-field img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* A banner slide with a phone image of its own is a <picture>, and <picture> is
   an inline box by default - so the <img>'s `height: 100%` above would resolve
   against auto and the slide would render at the file's own height inside a box
   that is 80vh tall. One rule, or the second image breaks the first. */
.ngs-field picture { display: block; width: 100%; height: 100%; }

/* Lower 46% only. Heavy enough to hold the type, light enough to leave the
   photograph visible, which is the whole point of a bleed. The dependency this
   creates on the commissioned hero is real and is recorded in DECISIONS 33b. */
/* The three stops are now ONE number with two ratios, so Design & Sections can
   strengthen or weaken the whole gradient with a single control and an UNSET
   control reproduces the three values this rule has always had: .94 at the
   bottom, .88 (.936 of it) at 24%, .40 (.426 of it) at 46%. Written this way
   rather than as three settings because they are one decision - how much of the
   photograph the white text is allowed to cost. */
.ngs-scrim {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top,
              rgba(10,6,22, calc(var(--ngs-hero-overlay, .94)))        0%,
              rgba(10,6,22, calc(var(--ngs-hero-overlay, .94) * .936)) 24%,
              rgba(10,6,22, calc(var(--ngs-hero-overlay, .94) * .426)) 46%,
              transparent 62%);
}

.ngs-hero-copy {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 0 56px var(--s8);
  color: var(--white);
}
.ngs-hero-title {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(30px, 4.2vw, 54px); line-height: 1.06;
  letter-spacing: -0.032em; margin: 0; max-width: 16ch; color: var(--white);
}
.ngs-hero-row {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: var(--s8); margin-top: var(--s5); flex-wrap: wrap;
}
.ngs-hero-line {
  margin: 0; max-width: 44ch; color: var(--on-dark-muted);
  font-size: 17px; line-height: 1.5;
}
.ngs-hero-actions { display: flex; align-items: center; gap: var(--s5); flex: none; }
.ngs-arrows { display: flex; gap: var(--s2); }
/* No circles. A filled disc with a ring round it is two decorations doing one
   job, and on a painted hero they read as buttons borrowed from another site.
   The glyph alone is the control; the 44px target is kept because the target is
   not the decoration. */
.ngs-arrow {
  width: 44px; height: 44px; border-radius: 0; cursor: pointer;
  background: transparent; color: var(--white);
  border: 0; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 22px; line-height: 1; font-family: var(--ui);
  opacity: .78; transition: opacity .18s ease, transform .18s ease;
}
.ngs-arrow:hover, .ngs-arrow:focus-visible { background: transparent; opacity: 1; }
.ngs-arrow[disabled], .ngs-arrow[aria-disabled="true"] { opacity: .32; cursor: default; }
.ngs-btn--on-dark {
  background: rgba(255,255,255,.10); color: var(--white);
  border: 1px solid rgba(255,255,255,.28);
}
.ngs-btn--on-dark:hover { background: rgba(255,255,255,.18); }

/* At phone width a 16:9 is a 219px strip, so serve the registered 4:5 and let
   the copy sit under the image rather than on a sliver of it. DECISIONS 33b. */
@media (max-width: 900px) {
  .ngs { padding-left: 24px; padding-right: 24px; }
}

@media (max-width: 767px) {
  /* A shade shorter on a phone, where 80vh of picture leaves nothing of the
     page in view and the scroll reads as a dead end. */
  .ngs-hero { height: 72vh; }
  .ngs-hero-copy { padding: 0 20px var(--s6); }
  /* ONE ROW, CENTRED (client, 2026-10-23). `width: 100%` makes the actions the
     only item on their line, so `.ngs-hero--bottom-center`'s centring stops
     reaching them - it centres the ROW, and the row is now full width. They
     centre themselves instead. `nowrap` is the other half: wrapping put "Send a
     gift card" on a line of its own, left aligned under the first button, which
     read as two unrelated controls rather than a pair. They fit side by side at
     390 with the tighter gap. */
  .ngs-hero-actions {
    width: 100%; flex-wrap: nowrap; justify-content: center; gap: var(--s3);
  }
  .ngs-hero-actions .ngs-btn { white-space: nowrap; }
}

/* ROOM TO SHRINK, OR `nowrap` TAKES THE ENDS OFF. Measured on dev at 320px,
   which is an iPhone SE: the pair came to 338px of a 320px screen and sat at
   x -9 with its right edge at 329, so both rounded ends were clipped by the
   hero's own `overflow: hidden`. The page did not scroll sideways and nothing
   reported an error - the buttons were simply cut, at both ends, on the
   narrowest phones anybody still uses.
   0.77.19 is what did it: `nowrap` keeps the pair together, and a pair that
   cannot wrap has to be able to get smaller instead. */
@media (max-width: 380px) {
  .ngs-hero-actions { gap: var(--s2); }
  .ngs-hero-actions .ngs-btn { padding: 10px 12px; font-size: 13px; }
}

/* ---- single paths ------------------------------------------------------ */

.ngs-grid--paths { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }

.ngs-path {
  display: flex; flex-direction: column; gap: var(--s4);
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--white); padding: var(--s5);
}
.ngs-path .art { border-radius: var(--r-sm); }
.ngs-path-body { flex: 1 1 auto; }
.ngs-path-foot {
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--line);
}
.ngs-path.is-off .ngs-h4, .ngs-path.is-off .ngs-kind { color: var(--ink-400); }
.ngs-h4 { font-family: var(--display); font-size: 17px; font-weight: 600;
          line-height: 1.34; letter-spacing: -0.01em; margin: 4px 0 0; }
.ngs-kind { font-family: var(--ui); font-size: 11px; font-weight: 600;
            letter-spacing: .12em; text-transform: uppercase; color: var(--violet-500); }
.ngs-kind--gold { color: var(--gold-400); }
.ngs-btn--sm { padding: 7px 12px; font-size: 13px; }

/* ---- the gift card band ------------------------------------------------ */

.ngs-band {
  display: flex; align-items: center; gap: var(--s8); flex-wrap: wrap;
  background: var(--indigo-700); color: var(--on-dark);
  border-radius: var(--r-lg); padding: var(--s8);
}
.ngs-band .ngs-h1, .ngs-band .ngs-lead { color: var(--white); }
.ngs-band .ngs-lead { color: var(--on-dark-muted); max-width: 40ch; }
/* `min-width: 0` is not decoration. A flex item defaults to `min-width: auto`,
   which refuses to shrink below its CONTENT's minimum - so this basis of 320px
   inside a band that has 240px to give on a 360px phone did not shrink, it
   overflowed, and the band clipped it. Same cause in three places on this
   screen; see the note above `.ngs-face`. */
.ngs-band-body { flex: 1 1 320px; min-width: 0; }
.ngs-band .ngs-chips { margin-top: var(--s5); }
.ngs-band .ngs-chip { background: rgba(255,255,255,.10); color: var(--on-dark);
                      border-color: rgba(255,255,255,.28); }
.ngs-band .ngs-chip--gold { background: var(--gold-400); color: var(--ink-900);
                            border-color: var(--gold-400); }
.ngs-band .ngs-actions { margin-top: var(--s6); }

/* A FIXED FLEX BASIS IS A WIDTH THAT A PHONE DOES NOT HAVE, and this is the
   family bug behind three of them - the card face here, `.ngs-band-body` above
   and `.ngs-money-col` on the collection band.

   `.ngs-band` is 312px wide on a 360px screen and spends 72px of it on padding,
   so an item asking for 300px with `flex: 0 0` - shrink ZERO - gets 300px and
   hangs 60px out of its own band. The band does not scroll, so the card simply
   ran off the right edge of the cream panel. Reported from a phone on
   2026-10-21 with a screenshot; invisible at every width the comps are drawn at.

   `0 1 300px` keeps the basis and hands back the shrink. On a desktop, where
   there is room, nothing shrinks and the face is 300px exactly as before.

   `.ngs-preview .ngs-face` sets `flex: none` and is unaffected - that override
   exists because the preview is a COLUMN, where this basis would be a height. */
.ngs-face {
  flex: 0 1 300px; max-width: 100%; aspect-ratio: 8 / 5; border-radius: var(--r-md);
  background: linear-gradient(145deg, #2E1B57, #160D2B);
  border: 1px solid rgba(255,255,255,.14);
  padding: var(--s5); display: flex; flex-direction: column;
  justify-content: space-between;
}
.ngs-face-top { display: flex; justify-content: space-between; align-items: center; }
.ngs-logo { font-family: var(--display); font-weight: 600; font-size: 12px;
            letter-spacing: .06em; color: var(--white); }
.ngs-logo i { font-style: normal; color: var(--gold-400); }
.ngs-face-amount { font-family: var(--display); font-size: 22px; font-weight: 600;
                   color: var(--white); margin-top: 4px; }

@media (prefers-reduced-motion: reduce) {
  .ngs-field { transition: none; }
}

/* ==========================================================================
   0.9.0 — screen 05, inside a collection.
   ========================================================================== */

/* Screen 05 used to run wider than the landing page. It does not any more:
   both boards are 1280, so both pages are the same width. */
.ngs--wide { max-width: 1440px; }

/* ---- the hero: the stack ----------------------------------------------- */

/* EDGE TO EDGE, as comp 05 draws it (client, 2026-10-06). On the board the hero
   is a direct child of `.board` with no `.wrap` around it, so it runs the full
   1280 and carries the gutter itself as padding; this shipped as an inset panel
   with a 16px radius instead, which is a card on a page rather than the ground
   the page stands on.

   Same break-out as `.ngs-hero` above, deliberately: two full-bleed techniques in
   one stylesheet is one too many, and that one is already proven on the landing
   page against this theme.

   The radius goes with the inset. A rounded corner is a statement that the thing
   has an edge, and this one no longer does. */
.ngs-chero {
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-bottom: var(--s9);
  background: var(--indigo-700);
  color: var(--on-dark);
  border-radius: 0;
  /* The comp's own figures were var(--s10) down, 56px in -- the same 56px gutter
     `.ngs` uses, so the title lines up with every heading below it. The gutter is
     untouched; the floor came up to var(--s8) on 2026-10-23, because with the
     copy top-aligned the leftover space all lands at the bottom and 64px of it
     under a 372px picture is a hero that keeps going after it has finished. */
  padding: var(--s10) 56px var(--s8);
}

/* IT LEADS THE PAGE, so it runs UNDER the site header exactly as the landing
   hero does -- cancel this plugin's own top padding and let the dark ground meet
   the dark bar with no strip of page background between them.

   Then put the clearance back as the hero's OWN padding, so the first thing
   inside it (the way back) clears the bar instead of hiding behind it.
   `--ny-clear` is the header plugin's published answer to "how much space must a
   template reserve", which is 64px here and 48 on a phone; the header's code and
   settings are not ours to change and this does not touch either. */
.ngs > .ngs-chero:first-child {
  margin-top: calc(-1 * var(--s8));
  padding-top: calc(var(--ny-clear, 0px) + var(--s7));
}

/* --- The split hero (0.77.7) ----------------------------------------------
   Two halves that meet: the picture on the left, floor to ceiling, and the
   words on the right on the collection's own ground. The halves are the same
   height because they are grid tracks, which is the whole reason this shape
   was chosen - a photograph and three lines of text are never the same height
   on their own, and every attempt to make them agree left a hole somewhere.

   1.4fr to 1fr, not 1fr to 1fr: the picture is what the page is selling and
   the words are a heading, three chips and a paragraph, so the picture gets
   the larger share. At 1440 that is 840 against 600.

   The picture half runs under the site header on purpose, as an edge-to-edge
   hero should. Only the panel reserves `--ny-clear`, because only the panel
   has something in it to read. ------------------------------------------- */
/* TWO ROWS NOW: a band, then the two halves (client, 2026-10-23 - "move the
   image down and have a little bit of purple on the top", then "in that purple
   space, we can add back to gifts").

   The band is the hero's own ground showing above both halves, and the way back
   lives in it. That is better than where it was for a reason beyond taste: the
   link was absolutely positioned ON the photograph, which is why it needed a
   pill behind it to stay legible. On indigo it needs nothing, so the pill goes
   and it is the same plain link the rest of the site uses.

   The hero carries the header clearance now, so the panel does not - which is
   what puts the title's top in line with the picture's rather than a notch
   below it. */
.ngs-chero--split {
  position: relative;
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  grid-template-rows: auto 1fr;
  align-items: stretch;
  padding: 0;
  /* JUST THE CLEARANCE (client, 2026-10-23: "can we make this less tall"). The
     extra var(--s5) on top of `--ny-clear` was 18px of nothing, and the hero
     already bleeds 32px UP under the header, so the gap between the header's
     bottom edge and the link measured 50px on dev. What it cannot go below is
     the header's own 64px plus a 33px link: push further and the link is under
     the bar again, which is what 0.77.15 just fixed. */
  padding-top: var(--ny-clear, 0px);
  min-height: 460px; overflow: hidden;
}

/* The way back sits at the hero's top left, over the picture, rather than
   inside the panel - where it was a third of the way across the page on a line
   of its own. The pill is the whole legibility answer: 13px of text gets a
   ground the size of itself, and the picture keeps the rest of its light. */
/* MARGIN FOR THE INSET, never the other thing, and the comment saying so has to
   live OUT HERE: `tests/smoke-card-paths.php` reads the first `.ngs-giftbar {`
   rule in this file and fails on four property names anywhere inside its braces,
   comments included. Its own note says as much. The assertion is right in
   spirit - "Back to Gifts" is a link and not a box - and an inset written as
   margin says the same thing without arguing with it.

   IN THE BAND, across the full width, in normal flow. It was absolutely
   positioned over the picture until 0.77.14, which is why it carried a pill and
   why it kept ending up a pixel from the edge of the screen - `left` fighting
   `.ngs-giftbar-back`'s own `margin-left: -10px`, an optical pull meant for a
   link that lines up with a title beneath it. Here it does line up with one
   again, so the pull is right and is left alone. */
.ngs-chero--split > .ngs-giftbar {
  grid-column: 1 / -1; grid-row: 1;
  margin: 0 56px var(--s3);
}
/* The pill that used to be here is GONE, and it should have gone in 0.77.14 -
   that release moved the link off the photograph and into the band, said the
   pill was unnecessary, and then left these two rules behind. A translucent dark
   lozenge on dark indigo is not very visible, which is exactly why it survived a
   measurement pass: `backgroundColor` still read `rgba(18,10,36,.52)` on dev
   while the changelog said it did not. The link is the site's plain one now. */
/* THE CLEARANCE LIVES HERE, BECAUSE THIS IS THE RULE THAT WINS. `.ngs-chero--split`
   carries `padding-top: calc(var(--ny-clear) + var(--s5))` thirty lines above, and
   this selector is three classes to its one - so `padding-top: 0`, written when the
   clearance belonged to the PANEL, silently zeroed it the moment the band was added.
   Measured on dev: `--ny-clear` resolving to 64px, the site header's bottom edge at
   64, and "Back to Gifts" at 32. Underneath it.

   It is the same value, in the one place that can set it. */
.ngs > .ngs-chero--split:first-child {
  padding-top: calc(var(--ny-clear, 0px) + var(--s5));
}
/* 16:9, FULL STOP (client, 2026-10-23: "can we use 16x9 aspect ratio for these
   images?").

   0.77.12 gave the picture a 420px floor, which stopped it being stretched into
   a portrait but still let the panel pull it taller than its own shape - and
   anything taller than 16:9 is `object-fit: cover` cropping the sides off a
   16:9 photograph. The only way a 16:9 picture is never cropped by this layout
   is for the layout to ask for 16:9 and nothing else.

   `align-self: start` is what makes that possible: the track can be taller than
   the picture when the copy is long, and the picture keeps its shape and sits at
   the top of it rather than stretching to fill. The ground under it is the
   hero's own indigo, which is the panel's colour too - a short picture in a tall
   hero reads as one band, not as a gap. */
.ngs-chero--split .ngs-chero-art {
  position: relative;
  aspect-ratio: 16 / 9;
  align-self: start;
  grid-row: 2;
}
.ngs-chero--split .ngs-chero-panel { grid-row: 2; }
/* `.art` carries `aspect-ratio` from `art--16x9`, which is right everywhere
   else and wrong here: this one is told its height by the grid row. */
.ngs-chero--split .ngs-chero-art .art {
  position: absolute; inset: 0;
  width: 100%; height: 100%; aspect-ratio: auto; border-radius: 0;
}
/* TOP ALIGNED, with a tick of space above the title (client, 2026-10-23).
   Centred was right while the panel held a back link, a title, three chips and
   two lines; with a paragraph in it the block is tall enough that centring just
   pushed it off the top edge it should start from. */
.ngs-chero--split .ngs-chero-panel {
  display: flex; flex-direction: column; justify-content: flex-start;
  /* NO TOP PADDING AT ALL. The hero's own padding carries the header clearance
     now, and the band sits above this, so anything here would be a margin above
     the title - which is the thing that was asked to go. */
  padding: 0 56px var(--s8);
  min-width: 0;
}
.ngs-chero--split .ngs-chero-panel .ngs-chero-title { margin-top: 0; }
/* `flex: 1 1 260px` was a WIDTH basis in the old row and is a HEIGHT basis in
   this column, so the copy block claimed 260px of panel whatever it held: at
   420px wide that was a 260px box around one line, and the hero came out 736
   tall with the words ending at 420. The basis is the row's, and the row is
   gone. */
.ngs-chero--split .ngs-stack-copy { flex: none; margin-top: var(--s6); }
/* Above the stacked width the paragraph is whole and the toggle is not drawn at
   all - there is nothing on a laptop for it to reveal. */
.ngs-who-more { display: none; }

/* Stacked, picture first, below the width where two columns stop being two
   readable columns. The picture takes its own ratio back, because a track
   height is the one thing it no longer has. */
/* STACKED UNDER 1100px, NOT 860. At 1000 the panel was 417px wide holding a
   seventy-word paragraph - seven lines, a 647px hero, and a picture made to
   match it. The breakpoint is not about the screen fitting two columns, it is
   about the COPY fitting one of them. */
@media (max-width: 1100px) {
  .ngs-chero--split > .ngs-giftbar { grid-column: 1; grid-row: 1; margin: 0 var(--s5) var(--s3); }
  .ngs-chero--split .ngs-chero-art { grid-row: 2; }
  .ngs-chero--split .ngs-chero-panel { grid-row: 3; }
  /* `!important` beats an INLINE style, which is the only thing it is here for.
     `collection_hero_height` is printed on the element by `style_for()`, and a
     minimum that reads as a sensible band beside a picture becomes a hole under
     one: stacked, the picture has already taken its own height and the panel
     takes what it needs. Measured at 420px before this line: hero 736 with the
     copy ending at 420. */
  .ngs-chero--split { grid-template-columns: 1fr; min-height: 0 !important; }
  .ngs-chero--split .ngs-chero-art { order: -1; aspect-ratio: auto; align-self: stretch; }
  /* THE CAP IS GONE, because a cap is a crop: 420px across a 1000px screen is
     2.38:1, which is `object-fit: cover` taking the top and bottom off a 16:9
     photograph. Stacked, the picture is its own shape at the full width, and the
     hero is as tall as that makes it. */
  .ngs-chero--split .ngs-chero-art .art {
    position: relative; aspect-ratio: 16 / 9; height: auto;
  }
  /* EDGE TO EDGE ON A PHONE TOO. `@media (max-width: 767px) { .ngs-chero {
     padding: var(--s7) var(--s5) } }` is the OLD hero's rule and it still wins
     over `.ngs-chero--split { padding: 0 }` by coming later in the file - so the
     picture was 354px wide inside a 390px screen, with indigo rails either side,
     while the same hero is full bleed on a desktop. Measured on dev. */
  /* `.ngs .ngs-chero--split`, two classes, because the rule it has to beat sits
     LATER in this file - `@media (max-width: 767px) { .ngs-chero { ... } }` at
     one class. Order would decide it otherwise, and order is the thing that made
     this inset in the first place. */
  .ngs .ngs-chero--split { padding-left: 0; padding-right: 0; }

  /* TIGHTER, BECAUSE THE WHOLE HERO WAS 817px OF AN 844px SCREEN. The picture is
     only 199 of that: the rest is a title at desktop size, two rows of chips and
     a sixty-word paragraph set at 17px. None of those is wrong on a laptop and
     all three are too big in a phone's first view, where nothing of "What is
     inside" ever appeared. */
  .ngs-chero--split .ngs-chero-panel { padding: var(--s5) var(--s5) var(--s6); }
  .ngs-chero--split .ngs-chero-title { font-size: 26px; }
  .ngs-chero--split .ngs-stack-copy { margin-top: var(--s4); }
  .ngs-chero--split .ngs-stack-copy .ngs-h1 { font-size: 21px; }
  .ngs-chero--split .ngs-stack-copy .ngs-lead { font-size: 15.5px; line-height: 1.5; }

  /* FOUR LINES, THEN A WAY TO READ THE REST. `-webkit-line-clamp` is the only
     thing that truncates on a line boundary rather than a character count, and
     it is supported everywhere that matters; where it is not, the paragraph
     simply shows in full, which is what it did before this rule. */
  .ngs-who--long .ngs-lead {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4;
    overflow: hidden;
  }
  .ngs-who--long:has(input:checked) .ngs-lead {
    display: block; -webkit-line-clamp: none; overflow: visible;
  }
  .ngs-who-more {
    display: inline-flex; align-items: center; min-height: 44px;
    font-family: var(--ui); font-size: 14px; font-weight: 600;
    color: var(--on-dark); text-decoration: underline; cursor: pointer;
  }
  .ngs-who-more input { position: absolute; opacity: 0; width: 1px; height: 1px; }
  .ngs-who-more .ngs-who-more-shut { display: none; }
  .ngs-who--long:has(input:checked) .ngs-who-more-open { display: none; }
  .ngs-who--long:has(input:checked) .ngs-who-more-shut { display: inline; }
  .ngs-who-more:has(input:focus-visible) { outline: 2px solid var(--gold-400); outline-offset: 3px; }
  .ngs-chero--split .ngs-chips--facts { margin-top: var(--s4); gap: var(--s2); }
  .ngs-chero--split { padding-top: calc(var(--ny-clear, 0px) + var(--s4)); }

}

.ngs-chero-top { display: flex; gap: var(--s3); flex-wrap: wrap; }
.ngs-chero-title {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(28px, 3.6vw, 48px); line-height: 1.08;
  letter-spacing: -0.03em; color: var(--white);
  margin: var(--s5) 0 0;
}
.ngs-chips--facts { margin-top: var(--s5); }
.ngs-chero .ngs-chip--dark {
  background: rgba(255,255,255,.10); color: var(--on-dark);
  border-color: rgba(255,255,255,.26);
}

/* TOP ALIGNED, AND IT WAS CENTRED (client, 2026-10-23: "so much dead space").
   The artwork is tall and the copy beside it is three lines, so centring put
   118px of empty hero above the words and the same below - which reads as a
   band that has not been filled rather than as breathing room. Aligned to the
   top, the copy starts where the picture starts and the space collects in one
   place at the bottom instead of two. */
.ngs-stack-row {
  display: flex; align-items: flex-start; gap: var(--s9);
  margin-top: var(--s7); flex-wrap: wrap;
}

/* ---------------------------------------------------------------------------
   THE STACK, rebuilt from comp 05 rather than adjusted towards it.

   The comp is three `.art` elements in one relative box. The two behind are
   absolutely positioned ON THEMSELVES -- no wrapper -- so the `aspect-ratio`
   that `art--16x9` already carries decides their height, and a narrower frame
   is a shorter frame. That is the whole composition: a fanned hand of cards,
   each sliding out to the right and down a little.

   Every previous version wrapped each frame in a positioned div, pinned it top
   AND bottom, and told the art inside to fill it. The wrapper then stretched to
   the container and the frames came out TALLER than the front -- a box behind a
   box. Five releases were spent tinting that instead of measuring it.

   Comp 05's own numbers, inline on the elements:
     container   flex: 0 0 52%;  padding: 0 0 var(--s7) 0
     near frame  inset: 18px -22px 0 44px;  opacity: 1
     far frame   inset: 36px -44px 0 88px;  opacity: .9
     all three   border-radius: var(--r-md); box-shadow: 0 0 0 1px rgba(255,255,255,.14)
   `bottom` is written as 0 there and is NOT honoured, because the ratio decides
   the height; it is left out here so the intent cannot be misread again.
   --------------------------------------------------------------------------- */

/* 52% OF A 1328px ROW IS A 691px PICTURE, and that is what was making this hero
   738px tall (client, 2026-10-23, twice: "there is so much dead space"). The
   copy beside it is a heading and two lines - 111px - so the artwork set the
   row's height and left 308px of empty ground under the words. Top-aligning
   moved that hole from two places into one; it did not close it, because the
   picture was never the thing that needed the room.

   Capped rather than re-proportioned, so the row still gives the picture the
   larger share on a laptop and simply stops it growing on a wide screen, where
   a percentage would have gone on getting taller for nothing. */
.ngs-stack {
  position: relative;
  flex: 0 1 44%;
  max-width: 440px;
  min-width: 300px;
  padding: 0 0 var(--s7) 0;
  /* The far frame reaches 44px past this box, so without the margin it eats the
     row gap: measured at 1223px, FOUR pixels between the picture and the copy. */
  margin-right: 44px;
}

.ngs-stack .art {
  border-radius: var(--r-md);
  box-shadow: 0 0 0 1px rgba(255,255,255,.14);
}

/* The front sits in normal flow and sizes itself; the wrapper only raises it. */
.ngs-stack-front { position: relative; z-index: 2; }

/* Top and the two sides only. No `bottom`, no `height`: the ratio decides. */
.ngs-stack-back { position: absolute; }
/* The comp's offsets, and they only work with DARK frames -- see below. */
.ngs-stack-back--1 { top: 18px; left: 44px; right: -22px; }
.ngs-stack-back--2 { top: 36px; left: 88px; right: -44px; }

/* THE FRAMES BEHIND CARRY NO PICTURE, AND THEY ARE DARK. Both halves matter.
   NO PICTURE: they used to render artwork -- the other paths' until 0.41.0, the
   front's own after it -- and either way what a reader sees of them is the EDGE
   of a photograph, twice. One clashed, the other read as the same picture
   duplicated. They are flat panels in the collection's own `--deep`, so there is
   no second image and no hue that can fight the front.

   DARK, because the composition depends on it and 0.44.x proved it the hard way.
   A back frame peeks 22px and 44px past the front and finishes 6px and 11px
   below it. Dark on a dark band, that reads as an edge -- which is the whole
   effect, and why comp 05 can get away with offsets this small. Make the same
   frames LIGHTER than the band and the identical geometry becomes two bright
   vertical bars down the side and a 500px shelf underneath: nothing moved, and
   it looked broken. Translucent white at a tenth was tried and withdrawn.

   So: `--deep` flat, one hairline, no tint and no shadow. If these ever need to
   be light, the offsets have to shrink with them -- the two are not independent.

   The gradient layers are switched off rather than the class removed: `.art`
   still supplies the 16:9 that gives each frame its height and the corner
   radius, which is the entire geometry. Only the painting goes. */
.ngs-stack-back::before,
.ngs-stack-back::after { content: none; }
/* TRANSLUCENT BLACK, not the collection's own tone. `var(--deep)` made them
   solid brown cards behind a brown photograph -- a second colour competing with
   the front. Black at a fraction only DARKENS the band beneath, so the frames
   take their colour from the page and read as shadow with an edge rather than
   as objects with a hue of their own. The far one is darker, so the two step
   away from the front rather than sitting at the same depth.
   Still dark, which is the part that matters: at a 22px peek, dark reads as an
   edge and light reads as a bar. See the offsets above. */
.ngs-stack-back--1 { background: rgba(0,0,0,.38); }
.ngs-stack-back--2 { background: rgba(0,0,0,.55); }

.ngs-stack-copy { flex: 1 1 260px; min-width: 0; }
.ngs-stack-copy .ngs-h1 { color: var(--white); }
.ngs-stack-copy .ngs-lead { color: var(--on-dark-muted); margin-top: var(--s4); }

/* ---- what is inside ----------------------------------------------------- */

.ngs-chip--ok   { background: #E8F5EC; color: #1C5B33; border-color: #BFE3CB; }
.ngs-chip--mute { background: var(--paper); color: var(--ink-500); border-color: var(--line); }

.ngs-measure { max-width: 46ch; }

/* A COLLECTION ROW IS NOT A COLUMN (client, 2026-10-06: "can we make the text
   underneath the product in collections wider so it doesn't look so bulky and
   long?"). `.ngs-measure`'s 46ch is a reading measure for a narrow column, and
   `.ngs-prow` is a full-width row with a 132px thumbnail and a price rail -- so
   the blurb was wrapping at 46 characters with several hundred pixels of empty
   row beside it, and a four-line paragraph became eight.

   76ch is still a measure, not "as wide as it goes": past about 80 characters a
   line is genuinely harder to track back from. It simply stops pretending the
   row is a column. */
.ngs-prow .ngs-measure { max-width: 76ch; }
.ngs-body { font-size: 15px; line-height: 1.6; margin: var(--s3) 0 0; }
/* `.ngs-meta-line` was here and is gone with the "4 sessions" line it styled
   (0.77.11), the same way `.dropzone` and the numbering's rules went: removed
   rather than left styling nothing. */


.ngs-paths-list { list-style: none; margin: var(--s7) 0 0; padding: 0; }
/* --- Choosing several paths on a collection (0.77.9) ----------------------
   `set`, NOT `pick`: `.ngs-pick` and `.ngs-pickbar` belong to the browse
   basket and `data-ngs-pick` to the wp-admin chooser. Same page, three
   components, so the names stay apart - this is the list at the top of phase
   C's block gaining a fourth entry rather than ignoring it.

   The tick sits in the column the numbered disc used to hold, which is the one
   place on the row where a reader already expects something small and square.

   The input is hidden rather than styled: a native checkbox cannot be given a
   22px rounded box and a gold fill in every browser, and `:checked + span` can.
   `opacity: 0` on a box still in flow, never `display: none`, so it keeps its
   size and its focus - which is what a keyboard needs. */
/* Where "4 sessions" used to be (0.77.11): under the description, at the start
   of the body column, which is where the eye already is when it finishes
   reading. It carries its own words, because a bare checkbox on a row that also
   has a "Gift this path" button reads as a second opinion about that button. */
/* The two quiet actions on one line under the description. They wrap on a
   narrow row rather than squeezing, because neither is worth clipping. */
.ngs-prow-actions {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--s3) var(--s5); margin-top: var(--s3);
}
/* 44px TALL ON PURPOSE. The box itself is 20px, which is a mouse target and not
   a thumb one - every other control on this row already clears 44 and this was
   the only one that did not. The min-height does it rather than a bigger box,
   because the TICK should stay 20px: it is the label beside it that gives a
   thumb somewhere to land. */
.ngs-prow-pick {
  display: inline-flex; align-items: center; gap: var(--s2);
  cursor: pointer; position: relative;
  min-height: 44px; padding-right: var(--s2);
}
.ngs-prow-pick input {
  position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; margin: 0; opacity: 0; cursor: pointer;
}
.ngs-prow-pick-say {
  font-family: var(--ui); font-size: 12.5px; color: var(--ink-500);
}
.ngs-prow-pick input:checked ~ .ngs-prow-pick-say { color: var(--ink-900); font-weight: 600; }
.ngs-prow-tick {
  flex: none; pointer-events: none;
  width: 20px; height: 20px; border-radius: var(--r-xs);
  border: 1.5px solid var(--line-strong); background: var(--white);
  transition: background .15s ease, border-color .15s ease;
}
.ngs-prow-tick::after {
  content: ""; display: block;
  width: 5px; height: 9px; margin: 1px auto 0;
  border: solid var(--indigo-900); border-width: 0 2px 2px 0;
  transform: rotate(45deg) scale(0);
  transition: transform .15s ease;
}
.ngs-prow-pick input:checked + .ngs-prow-tick {
  background: var(--gold-400); border-color: var(--gold-400);
}
.ngs-prow-pick input:checked + .ngs-prow-tick::after { transform: rotate(45deg) scale(1); }
.ngs-prow-pick input:focus-visible + .ngs-prow-tick {
  outline: 2px solid var(--violet-500); outline-offset: 2px;
}

/* Sticky, so it is reachable from anywhere in the list rather than only from
   the end of it. On paper with a line above, because it is the page's own
   furniture rather than an overlay floating on the rows. */
/* A CARD THAT FLOATS, not a band across the page (client, 2026-10-23: "looks
   broken"). On `--paper` with a hairline above it, against a page that is also
   paper, it read as a smudge rather than as furniture: the eye could not tell
   whether it was a bar, a section edge or a rendering fault. White, bordered,
   rounded and lifted, it is obviously a thing that sits on top of the list. */
.ngs-setbar {
  position: sticky; bottom: var(--s4); z-index: 4;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--s4);
  margin-top: var(--s6);
  margin-bottom: max(var(--s4), env(safe-area-inset-bottom, 0px));
  padding: var(--s4) var(--s4) var(--s4) var(--s5);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--e3);
}
.ngs-setbar-say {
  font-family: var(--ui); font-size: 14px; color: var(--ink-700); margin: 0;
}

/* ROOM FOR SOMEBODY ELSE'S BUTTON. `ht-ctc-chat`, the WhatsApp bubble, is
   `position: fixed` in the bottom right with `z-index: 99999999`, and this bar
   pins to the bottom of the same corner. Measured at 390px: the bubble covered
   the right 26px of "Gift these together", and at that z-index it does not
   merely sit on top, it TAKES THE TAP. The primary action of the picker was
   partly dead on a phone.
   Reserving the corner is the honest fix available here: the bubble belongs to
   another plugin and its z-index is not ours to argue with. */
@media (max-width: 767px) {
  .ngs-setbar { padding-right: 72px; }
}
.ngs-setform.is-picking .ngs-setbar-say { color: var(--ink-900); font-weight: 600; }

/* NOT `.ngs-setform:not(.is-picking)`, which would hide the bar for a browser
   with no JavaScript and leave it no way to submit at all. `--js` is added by
   `ngs-set.js` on startup, so this rule only ever applies where something is
   running that can put the bar back. */
.ngs-setform--js:not(.is-picking) .ngs-setbar { display: none; }
/* NOT `opacity: .5` ON THE GOLD, which is what made the button look like it
   had failed to load. A disabled control should read as "not yet", so it takes
   a flat quiet surface instead of a washed-out version of the live one. */
.ngs-setbar .ngs-btn[disabled] {
  background: var(--line-soft); color: var(--ink-500);
  box-shadow: none; cursor: default; pointer-events: none;
}

.ngs-prow {
  display: flex; align-items: flex-start; gap: var(--s6);
  padding: var(--s6) 0; border-top: 1px solid var(--line);
}
.ngs-prow:last-child { border-bottom: 1px solid var(--line); }

/* The index column: a numbered disc with a rule running down from it, so three
   rows read as an ordered walk rather than as three stacked cards. */
/* BACK IN 0.77.10, having been removed in 0.77.5 (client: "I liked the old
   design with the purple circle and the line"). The sentence claiming an order
   was the thing that was wrong; the discs and the rule were the row's rhythm,
   and taking them out went further than the complaint did. */
.ngs-prow-index { display: flex; flex-direction: column; align-items: center;
                  align-self: stretch; flex: none; gap: var(--s3); }
.ngs-prow-n {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: var(--violet-100); color: var(--violet-500);
  font-family: var(--ui); font-size: 12.5px; font-weight: 600;
}
.ngs-prow-rule { width: 1px; flex: 1 1 auto; background: var(--line); }

/* 132px, as the comp draws it. Smaller and the row reads as a list item. */
.ngs-prow-art { flex: 0 0 132px; }
.ngs-prow-art .art { border-radius: var(--r-sm); }
.ngs-prow-body { flex: 1 1 auto; min-width: 0; }
.ngs-prow-body .ngs-h3 { margin: 5px 0 0; }

/* Four separate decisions - when, how much, give it, read more - so they stack
   rather than flattening into one row. */
.ngs-prow-col {
  flex: 0 0 168px; display: flex; flex-direction: column;
  align-items: flex-start; gap: var(--s4);
}
.ngs-prow-col .ngs-h4 { margin: 0; }
.ngs-prow.is-off .ngs-h3,
.ngs-prow.is-off .ngs-kind { color: var(--ink-400); }

/* ---- take the whole collection ------------------------------------------ */

.ngs-band--bundle { align-items: stretch; }
.ngs-band--bundle .ngs-band-body {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--s5);
}
.ngs-band--bundle .ngs-lead { margin: 0; max-width: 44ch; }
/* FOUR THUMBS ARE 334px AND THE BAND HAS 240, so they wrap rather than shrink.
   Shrinking them was the other option and is worse: these are the collection's
   actual artwork, and four squashed thumbnails read as a rendering fault where
   two rows of two read as a layout. A collection of three still fits on one row
   at 360px, which is why the phone screenshot that found this showed three. */
.ngs-band-thumbs { display: flex; gap: var(--s3); flex-wrap: wrap; }
.ngs-band-thumbs .art { width: 76px; flex: 0 0 76px; border-radius: var(--r-sm); }
.ngs-hint { margin: 0; font-size: 13px; color: var(--on-dark-muted); opacity: .85; }
/* The third of the fixed bases. Same `0 1` for the same reason, and `min-width`
   because this one holds a <dl> whose rows are `justify-content: space-between`
   - without it the price column kept its content's minimum and pushed "₹8,497"
   past the panel's own edge, which is what the phone screenshot showed. */
.ngs-band--bundle .ngs-money-col {
  flex: 0 1 300px; min-width: 0; background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.16);
  border-radius: var(--r-md); padding: var(--s6);
}
.ngs-money-rows { margin: 0; }
.ngs-money-rows > div {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--s4); padding: 5px 0;
}
.ngs-money-rows dt { color: var(--on-dark-muted); font-size: 14px; margin: 0; }
.ngs-money-rows dd { margin: 0; color: var(--white); font-variant-numeric: tabular-nums; }

/* 72px of horizontal padding out of a 360px screen is a fifth of the width
   spent on nothing. The shrink fixes above make the band CORRECT at --s8; this
   makes it readable. Desktop keeps the comp's padding untouched. */
@media (max-width: 560px) {
  .ngs-band { padding: var(--s6); gap: var(--s6); }
}
.ngs-money-total dd {
  font-family: var(--display); font-size: 22px; font-weight: 600;
  letter-spacing: -0.022em;
}
.ngs-money-save dd { color: var(--gold-400); }
.ngs-actions--stack { flex-direction: column; align-items: stretch; gap: var(--s3); }
.ngs-actions--stack .ngs-btn { justify-content: center; }

.ngs-aside {
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: var(--s6); max-width: 620px;
}
.ngs-aside .ngs-h3 { margin: 0 0 var(--s3); }

@media (max-width: 767px) {
  .ngs-chero { padding: var(--s7) var(--s5); border-radius: 0; }
  .ngs-stack { flex: 1 1 100%; }
  .ngs-prow { flex-wrap: wrap; gap: var(--s4); }
  .ngs-prow-art { flex: 0 0 96px; }
  .ngs-prow-col { flex: 1 1 100%; flex-direction: row; flex-wrap: wrap;
                  align-items: center; justify-content: space-between; }
}

/* ==========================================================================
   0.9.3 — the fidelity pass. Icons, and the gift card band as the comp draws
   it: a CREAM card with a dark face inside, not a dark band.
   ========================================================================== */

.ngs-i {
  width: 16px; height: 16px; flex: none;
  vertical-align: -3px; display: inline-block;
}
.ngs-chip .ngs-i { margin-right: 2px; }
.ngs-btn .ngs-i { margin-right: 6px; }
.ngs-quiet .ngs-i { margin-left: 2px; vertical-align: -3px; }

.ngs-btn--lg { padding: 13px 22px; font-size: 15px; }

/* The gift card band. `.lit` is --paper in the deck, so this is a cream card
   sitting on the page, with the card object itself the only dark thing in it. */
.ngs-band--lit {
  background: var(--paper);
  color: var(--ink-900);
  border: 1px solid var(--line);
  box-shadow: 0 10px 30px rgba(28,19,48,.07);
}
.ngs-band--lit .ngs-h1 { color: var(--ink-900); }
.ngs-band--lit .ngs-lead { color: var(--ink-600); }
.ngs-band--lit .ngs-chip {
  background: var(--white); color: var(--ink-700); border-color: var(--line);
}
.ngs-band--lit .ngs-chip--gold {
  background: var(--gold-400); color: var(--ink-900); border-color: var(--gold-400);
}
.ngs-face-top { display: flex; justify-content: space-between; align-items: center; }
.ngs-face-spark { color: var(--gold-400); display: inline-flex; }

/* ==========================================================================
   Phase C: screens 09, 10 and 11.

   The comps are drawn against the deck's assets/system.css, which the storefront
   does not load. Everything below is the subset those three screens need,
   transcribed from the same rules rather than re-invented - where a value here
   disagrees with the deck, the deck is right and this file is wrong.

   Toggles are REAL RADIOS wrapped in labels, not the comps' `<button
   aria-pressed>`: a single-choice group should be one control to a screen reader
   and should work with no JavaScript. The visual states are driven by
   `:has(input:checked)` with a server-rendered `.is-on` beside it, so the first
   paint is correct before any script runs.
   ========================================================================== */

/* SELECTOR WEIGHT, and it is not pedantry. `.ngs section` and the theme's own
   `ol` / `li` rules are class+type or type selectors, so a bare class here loses
   to them: .ngs-sent-panel as a class alone had its 64px margin and its 24px
   padding reset to zero by `.ngs section { margin:0; padding:0 }` five hundred
   lines above, and screen 11's panel rendered with its artwork touching its own
   border. 0.9.5 hit exactly this and left the note at that rule; this is the
   second time, so the rules below carry the weight rather than the hope.

   NAMES THAT WERE ALREADY TAKEN, and the reason they are not reused:
     .ngs-field  is the hero carousel's ARTWORK field (.ngs-fields > .ngs-field.is-on).
                 A form field here is .ngs-formfield. Redefining it absolutely
                 positioned every input on screen 09 to the size of the viewport
                 at opacity 0 - the form rendered, and was invisible. Found by
                 opening the page, which is the third time on this build.
     .ngs-hint   is dark-surface copy (--on-dark-muted at .85 opacity). Help text
                 under a form field is .ngs-help.
     .ngs-measure is 46ch; screen 11's lead wants the deck's 64ch, so it is
                 .ngs-measure-lg rather than a redefinition that would narrow or
                 widen something already shipped. */

.ngs-rule { height: 1px; background: var(--line); border: 0; margin: var(--s6) 0; }
.ngs-measure-lg { max-width: 64ch; margin-left: auto; margin-right: auto; }
.ngs-h5 { font-family: var(--display); font-size: 15px; font-weight: 600; margin: 0; }
.ngs-i--sm { width: 15px; height: 15px; }
.ngs-i--lg { width: 22px; height: 22px; }
.ngs-i--xl { width: 26px; height: 26px; }

/* --- The stepper. A real sequence, so a real ordered list. --------------- */
.ngs ol.ngs-stepper { display: flex; align-items: center; gap: var(--s3); list-style: none; margin: var(--s6) 0 0; padding: 0; }
.ngs li.ngs-step { display: flex; align-items: center; gap: var(--s2); margin: 0; }
.ngs-step-num {
  width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; flex: none;
  font-family: var(--ui); font-size: 11px; font-weight: 600;
  background: var(--line); color: var(--ink-700);
}
.ngs-step-label { font-family: var(--ui); font-size: 13px; color: var(--ink-500); }
.ngs-step--done .ngs-step-num { background: var(--violet-100); color: var(--violet-600); }
.ngs-step--done .ngs-step-label { color: var(--ink-700); }
.ngs-step--on .ngs-step-num { background: var(--violet-500); color: var(--white); }
.ngs-step--on .ngs-step-label { color: var(--ink-900); font-weight: 600; }
.ngs li.ngs-step-sep { width: 26px; height: 1px; background: var(--line-strong); flex: none; list-style: none; margin: 0; }

/* The stepper on a phone. Four steps, three rails and six gaps come to 417px of
   content in the 327px a 375px screen leaves after the gutters, so SOMETHING has
   to give and the question is only what. The labels do not: a stepper whose words
   are abbreviated or dropped stops being the thing it is for.

   So the numerals and the type come down a notch, and the RAILS become the slack
   - `flex: 1 1 6px` instead of a fixed 26px, which lets them close up to whatever
   is left over and keeps all four labels whole and on one line down to 360px.

   Below 340px even that runs out, and the rails go rather than the words: the row
   becomes `space-between`, which reads as a sequence on its own. Verified on dev
   at 320, 360 and 375px - no horizontal scroll at any of the three.

   This only works because of the `word-break` reset above. Without it the labels
   shrink to one letter a line long before the rails are asked for anything. */
@media (max-width: 600px) {
  .ngs ol.ngs-stepper { gap: var(--s2); }
  .ngs li.ngs-step    { gap: var(--s1); }
  .ngs-step-num       { width: 20px; height: 20px; font-size: 10px; }
  .ngs-step-label     { font-size: 12px; }
  .ngs li.ngs-step-sep { width: auto; min-width: 6px; flex: 1 1 6px; }
}
@media (max-width: 340px) {
  .ngs ol.ngs-stepper  { gap: 0; justify-content: space-between; }
  .ngs li.ngs-step-sep { display: none; }
}

/* --- Screen 09 ----------------------------------------------------------- */
.ngs-cols { display: grid; grid-template-columns: minmax(0,1fr) 396px; gap: var(--s8); align-items: start; }
@media (max-width: 900px) { .ngs-cols { grid-template-columns: minmax(0,1fr); } }

.ngs ol.ngs-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s9); }
.ngs li.ngs-step-block { margin: 0; padding: 0; }
.ngs-step-head { display: flex; align-items: baseline; gap: var(--s4); }
.ngs-step-index { font-weight: 400; color: var(--ink-500); font-variant-numeric: tabular-nums; }
.ngs-step-sub { margin-top: var(--s3); }

/* Chips that choose. The check is in the markup and CSS decides when it shows,
   so the state cannot disagree with the input. */
.ngs-chips--choose { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s5); }
.ngs-chip--choose { position: relative; cursor: pointer; background: var(--line-soft); color: var(--ink-700); }
.ngs-chip--choose input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.ngs-chip--choose .ngs-check { display: none; }
.ngs-chip--choose.is-on,
.ngs-chip--choose:has(input:checked) { background: var(--violet-500); color: var(--white); }
.ngs-chip--choose.is-on .ngs-check,
.ngs-chip--choose:has(input:checked) .ngs-check { display: inline-flex; }
.ngs-chip--choose:has(input:focus-visible) { outline: 2px solid var(--violet-400); outline-offset: 2px; }

/* The four themes. 5:4 swatches, as specified. */
.ngs-themes { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: var(--s4); margin-top: var(--s5); }
@media (max-width: 700px) { .ngs-themes { grid-template-columns: repeat(2, minmax(0,1fr)); } }
.ngs-theme { display: flex; flex-direction: column; gap: var(--s2); cursor: pointer; }
.ngs-theme input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ngs-theme .swatch { display: block; }
.ngs-theme-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); font-size: 13px; }
.ngs-theme-name.is-on { font-weight: 700; }
.ngs-theme:has(input:checked) .swatch { box-shadow: 0 0 0 2px var(--violet-500), 0 0 0 5px var(--violet-100); }
.ngs-theme:has(input:focus-visible) .swatch { outline: 2px solid var(--violet-400); outline-offset: 4px; }

.ngs-help { font-family: var(--ui); font-size: 12.5px; color: var(--ink-500); line-height: 1.5; margin: 0; }
.ngs-help--icon { display: flex; gap: var(--s2); align-items: flex-start; margin-top: var(--s2); }
.ngs-help--icon .ngs-i { color: var(--ink-400); flex: none; margin-top: 2px; }

/* Fields. */
.ngs-grid2 { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: var(--s5); margin-top: var(--s5); }
@media (max-width: 600px) { .ngs-grid2 { grid-template-columns: minmax(0,1fr); } }
.ngs-formfield { display: flex; flex-direction: column; gap: 7px; margin-top: var(--s5); }
.ngs-grid2 .ngs-formfield { margin-top: 0; }
.ngs-label { font-family: var(--ui); font-size: 12.5px; font-weight: 500; color: var(--ink-600); }
.ngs-input {
  font-family: var(--ui); font-size: 14.5px; color: var(--ink-900);
  background: var(--white); border: 1px solid var(--line-strong);
  border-radius: var(--r-sm); padding: 11px 13px; width: 100%;
  /* The theme sets `letter-spacing: -0.015em` on the bare input types and this
     class never mentioned it, so every field in the build has been tracking
     slightly tight on the real site. Same leak as the button's uppercase. */
  letter-spacing: normal;
  transition: border-color .16s cubic-bezier(.4,0,.2,1), box-shadow .16s cubic-bezier(.4,0,.2,1);
}
.ngs-input:hover { border-color: var(--ink-300); }
.ngs-input:focus { outline: none; border-color: var(--violet-400); box-shadow: 0 0 0 3px var(--violet-100); }
textarea.ngs-input { resize: vertical; min-height: 96px; }
.ngs-formfield--error .ngs-input { border-color: var(--stop-fg); }
.ngs-error-text { font-family: var(--ui); font-size: 12.5px; color: var(--stop-fg); }
.ngs-error-banner {
  font-family: var(--ui); font-size: 13.5px; color: var(--stop-fg);
  background: var(--stop-bg); border-radius: var(--r-sm);
  padding: var(--s4) var(--s5); margin: 0 0 var(--s6);
}
/* Unused since 0.46.3: "Save and finish later" is gone, so nothing renders a
   .ngs-saved notice. Kept with NGS_Compose's `later` branch, which it pairs
   with -- they go back together or not at all. */
.ngs-saved {
  font-family: var(--ui); font-size: 13.5px; color: var(--ok-fg);
  background: var(--ok-bg); border-radius: var(--r-sm);
  padding: var(--s4) var(--s5); margin: 0 0 var(--s6);
}

/* Choice rows. */
.ngs-choice {
  display: flex; gap: var(--s3); align-items: center;
  padding: var(--s4); border: 1px solid var(--line-strong);
  border-radius: var(--r-md); background: var(--white); cursor: pointer;
  transition: border-color .16s cubic-bezier(.4,0,.2,1), background .16s cubic-bezier(.4,0,.2,1);
}
.ngs-choice input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ngs-choice:hover { border-color: var(--violet-300); }
.ngs-radio {
  width: 18px; height: 18px; border-radius: 50%; flex: none;
  border: 1.5px solid var(--line-strong); background: var(--white);
  display: grid; place-items: center;
}
.ngs-choice.is-on,
.ngs-choice:has(input:checked) {
  border-color: var(--violet-500); box-shadow: 0 0 0 1px var(--violet-500);
  background: var(--violet-50);
}
.ngs-choice.is-on .ngs-radio,
.ngs-choice:has(input:checked) .ngs-radio { border-color: var(--violet-500); }
.ngs-choice.is-on .ngs-radio::after,
.ngs-choice:has(input:checked) .ngs-radio::after {
  content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--violet-500);
}
.ngs-choice:has(input:focus-visible) { outline: 2px solid var(--violet-400); outline-offset: 2px; }
.ngs-arrive .ngs-grid2 { margin-top: 7px; }
.ngs-when { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: var(--s5); margin-top: var(--s5); }
.ngs-when.is-hidden { display: none; }
.ngs-when .ngs-formfield { margin-top: 0; }

.ngs-btn--primary { background: var(--violet-500); color: var(--white); }
.ngs-btn--primary:hover { background: var(--violet-600); }
.ngs-btn--block { width: 100%; }
.ngs-compose-actions { display: flex; gap: var(--s3); margin-top: var(--s8); }

/* Back and Continue, side by side, on a 360px screen. At the full --lg padding
   the pair wants 346px and gets 312, so Continue was wrapping to two lines while
   Back sat at its natural width - the quiet button taking the same height as the
   primary one. Trimming the padding a notch fits both on one line, and the
   primary takes the slack so it stays the bigger target of the two.

   Stacking them was the other option and is not taken: it would put the quiet
   Back ABOVE the primary, and reversing them in CSS would leave the tab order
   saying the opposite of what the screen shows. */
@media (max-width: 600px) {
  .ngs-compose-actions .ngs-btn--lg    { padding: 12px 16px; font-size: 14px; }
  .ngs-compose-actions .ngs-btn--primary { flex: 1 1 auto; justify-content: center; }
}

/* The preview. One box, so nothing nests - the email mock is the only card in
   the column (comp 09's rail). */
.ngs-preview { position: sticky; top: var(--s6); display: flex; flex-direction: column; gap: var(--s4); }
@media (max-width: 900px) { .ngs-preview { position: static; } }
.ngs-card-plain {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: 0 1px 2px rgba(28,19,48,.05);
}
.ngs-email { overflow: hidden; }
.ngs-email-top {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  background: var(--indigo-800); color: var(--on-dark); padding: var(--s3) var(--s4);
}
.ngs-email-top .ngs-logo { font-size: 13px; }
.ngs-email-theme { font-family: var(--ui); font-size: 11px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: var(--gold-400); }
.ngs-email-field { border-radius: 0; }
.ngs-email-body { display: flex; flex-direction: column; gap: var(--s4); padding: var(--s6) var(--s5) var(--s5); }
.ngs-email-themeline { font-size: 14.5px; line-height: 1.55; color: var(--ink-600); margin: 0; min-height: 1.55em; }
.ngs-email-msg { font-size: 14.5px; line-height: 1.55; color: var(--ink-700); margin: 0; min-height: 1.55em; }
.ngs-preview-foot { padding-top: var(--s3); }
.ngs-preview-foot .ngs-h5 { margin-top: var(--s5); }
.ngs-preview-foot p { margin-top: var(--s2); }

/* Screen 10 had a block here - a page heading, a stepper, a billing note, a gold
   gift panel and a GST row. All of it is CUT: a gift does not morph the checkout,
   it just appears as a row in Your order (DECISIONS 48). The rules those styles
   served are gone, so the styles are too rather than left to rot. */

/* --- Screen 11. The deck's success state, so gold is allowed. ----------- */
.ngs-sent { max-width: 760px; margin: 0 auto; }
.ngs-sent-head { display: flex; flex-direction: column; align-items: center; gap: var(--s5); text-align: center; }
.ngs-sent-mark {
  width: 58px; height: 58px; border-radius: 50%; display: grid; place-items: center;
  background: var(--gold-100); color: var(--gold-700);
  box-shadow: inset 0 0 0 1px var(--gold-300);
}
.ngs section.ngs-sent-panel {
  margin-top: var(--s10); padding: var(--s6);
  border: 1px solid var(--gold-300); border-radius: var(--r-lg); background: var(--white);
}
.ngs-sent-object { display: flex; gap: var(--s5); align-items: flex-start; }
.ngs-sent-thumb { flex: 0 0 88px; border-radius: var(--r-sm); }
.ngs-sent-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--s3); }
.ngs-sent-title-row { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s4); }
/* The status chip is a label, not a paragraph. Without this it wrapped to
   "Sche / dule / d" on the live page beside a two-line gift title - a flex item
   with no basis will happily shrink to its narrowest word. */
.ngs-sent-title-row .ngs-chip { flex: none; white-space: nowrap; }
.ngs-sent-number { color: var(--ink-500); margin: 8px 0 0; }
.ngs-meta-item { display: inline-flex; align-items: center; gap: 6px; }
.ngs-meta-item .ngs-i { color: var(--ink-400); }
.ngs-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; display: inline-block; }
.ngs-dot--ok { background: var(--ok-fg); }
.ngs-sent-support { margin-top: var(--s6); text-align: center; }
.ngs-sent-again { margin-top: var(--s9); display: flex; justify-content: center; }
.ngs-again-card {
  padding: var(--s6); max-width: 360px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: var(--s3);
}
.ngs-again-card .ngs-i { color: var(--ink-400); }
.ngs-again-card .ngs-h4 { margin-top: var(--s2); }

/* ==========================================================================
   Screen 20. Buy credit for yourself (NGS_Buy_Credit_View, templates/buy-credit.php).

   A payment screen, so it is quiet by intent: no gold, no artwork, and violet
   appears once, on the button that commits the charge.

   THE THEME LEAKS THAT THIS SECTION UNDOES, found by reading twentytwenty's
   stylesheet rather than guessing (line numbers are style.css 2.8):

     button, .button, input[type=submit]   (~835)  text-transform: UPPERCASE and
        letter-spacing: .0333em. This is the real rule behind every button in the
        build rendering in CAPS. `.ngs-btn` already declares text-transform:none
        and letter-spacing:normal above, so "Add credit" inherits normal case; it
        is the SAME class, not a new button style, so there is nothing to forget.

     button:hover, button:focus            (~860)  text-decoration: underline.
        `.ngs-btn` sets text-decoration:none at (0,1,0) but `button:hover` is
        (0,1,1) and wins, so on the real site a hovered button underlines. Not
        covered by the existing rule, so it is set again here at higher weight.

     label { display:block; margin:0 0 .5rem; font-size:1.6rem }  (~690)
        gives each amount choice a stray half-rem of margin-bottom.

     dt { font-weight:700 }, dt + dd { margin-top:.5rem }          (~526)
        bolds the summary labels and pushes every figure down from its label.

     ul / li margins and bullets, select { font-size:1em } with a native arrow.

   Every selector below is rooted at `.ngs` or a class on the screen, so none of
   it reaches the rest of the site, and carries enough weight to beat a bare type
   selector (the lesson of `.ngs section`, 0.9.5).
   ========================================================================== */

.ngs-bc-head { margin-bottom: var(--s8); max-width: 620px; }

.ngs-bc-cols { display: grid; grid-template-columns: minmax(0,1fr) 360px; gap: var(--s8); align-items: start; }
@media (max-width: 900px) { .ngs-bc-cols { grid-template-columns: minmax(0,1fr); } }

.ngs-bc-main { display: flex; flex-direction: column; gap: var(--s9); }

/* The comp's t-h3 and t-h4. The store's own .ngs-h3 is 17px, which is the compose
   steps' size; the comp draws these headings larger and this one follows the comp. */
.ngs .ngs-bc-h3 { font-family: var(--display); font-size: 22px; line-height: 1.26; font-weight: 600;
                  letter-spacing: -0.016em; margin: 0 0 var(--s4); }
.ngs .ngs-bc-h4 { font-family: var(--display); font-size: 17px; line-height: 1.34; font-weight: 600;
                  letter-spacing: -0.01em; margin: 0 0 var(--s4); }

/* The comp's .panel. */
.ngs-panel { background: var(--white); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--s6); }
.ngs-panel--stack { display: flex; flex-direction: column; gap: var(--s5); }

/* Three-up when there are three amounts; the column count is set from the number
   actually configured so two amounts do not leave a gap and four wrap cleanly. */
.ngs-bc-tiers { display: grid; grid-template-columns: repeat(var(--ngs-bc-cols,3), minmax(0,1fr)); gap: var(--s5); }
@media (max-width: 700px) { .ngs-bc-tiers { grid-template-columns: minmax(0,1fr); } }
/* The comp top-aligns the radio with a two-line body; .ngs-choice centres it. */
.ngs .ngs-bc-tier { align-items: flex-start; margin: 0; text-align: left; }
.ngs-bc-tier .ngs-radio { margin-top: 1px; }
.ngs-bc-tier-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--s1); }
.ngs-bc-amount { font-family: var(--display); font-size: 17px; line-height: 1.34; font-weight: 600;
                 letter-spacing: -0.01em; color: var(--ink-900); }
.ngs-bc-sub { font-family: var(--ui); font-size: 12.5px; line-height: 1.5; color: var(--ink-500); }

/* The native select arrow, replaced by the comp's drawn chevron. */
.ngs select.ngs-input {
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  font-size: 14.5px; line-height: 1.4; cursor: pointer; padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%236B6D78' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center;
}
.ngs-bc-measure { max-width: 64ch; }

/* Terms and conditions. The soft rule between points belongs to the item, so a point
   that is not printed takes its rule with it. */
.ngs ul.ngs-bc-points { list-style: none; margin: 0; padding: 0; }
.ngs ul.ngs-bc-points li { margin: 0; padding: var(--s4) max(0px, calc(100% - 64ch)) var(--s4) 0; color: var(--ink-900);
                           border-top: 1px solid var(--line-soft); }
.ngs ul.ngs-bc-points li:first-child { padding-top: 0; border-top: 0; }
/* (the 64ch measure is right padding, so the rule still runs the panel's full width) */
.ngs ul.ngs-bc-points li:last-child { padding-bottom: 0; }

/* The summary. Light-surface twin of .ngs-money-rows, which is drawn for the dark
   band and would print white on white here. */
.ngs dl.ngs-bc-money { margin: 0; }
.ngs .ngs-bc-row { display: flex; align-items: baseline; justify-content: space-between;
                   gap: var(--s4); padding: 9px 0; font-size: 13.5px; }
.ngs .ngs-bc-money dt { margin: 0; font-weight: 400; color: var(--ink-600); }
.ngs .ngs-bc-money dd { margin: 0; font-weight: 600; color: var(--ink-900); font-variant-numeric: tabular-nums; }
.ngs .ngs-bc-row--total { border-top: 1px solid var(--line-strong); margin-top: var(--s2); padding-top: var(--s4); }
.ngs .ngs-bc-row--total dt { font-family: var(--display); font-weight: 600; font-size: 15px; color: var(--ink-900); }
.ngs .ngs-bc-row--total dd { font-family: var(--display); font-size: 21px; letter-spacing: -0.022em; }

.ngs .ngs-bc-submit { margin-top: var(--s5); }
/* The per-screen underline fix that was here is GONE: the leak is site-wide, so it
   is fixed once on `.ngs-btn:hover` near the top of this file. Two rules for one bug
   is how one of them later gets deleted as dead and the bug comes back on the other
   screens only. */

/* ==========================================================================
   Phase E: screen 19, the wallet dashboard (`.ngs-wallet`, classes `.ngs-w-*`).

   TRANSCRIBED FROM THE COMP'S OWN RULES (assets/system.css `.panel`, `.stat`,
   `.table`, `.chip`, `.dot`, `.btn`; assets/art.css `.card-face`), pixel for
   pixel. The comp's spacing scale is NOT this file's: system.css has
   s2=8 s3=12 s4=16 s5=20 s6=24 s7=32 s8=40 s9=48 s10=64, where `.ngs` above has
   its own, smaller steps. So this section uses the comp's values as literals
   rather than `var(--sN)`, because a token that means two things is how a
   matching layout drifts.

   EVERY RULE CARRIES `.ngs-wallet` so it outranks the theme. twentytwenty styles
   the bare `table`, `th`, `td`, `button`, `input[type=text]` and `label` types,
   and a CLASS alone loses to an attribute-qualified type selector: this file has
   been bitten by that for buttons (CAPS), for `.ngs-input` (letter-spacing) and
   for `section` (80px padding). Buttons here restate `text-transform: none`,
   `letter-spacing: normal` and `text-decoration: none` on purpose.
   ========================================================================== */

.ngs-wallet {
  --ink-800:#2B2F42; --paper-warm:#FDFCFA; --violet-700:#6B1795;
  --warn-fg:#8A5A0B; --warn-bg:#FFF4E8; --warn-line:#F0D8B8;
  --text:'Lato',system-ui,sans-serif;
  /* The page opens with the account sub-nav, flush under the site header, so only
     the overlay header's clearance is padding; the comp's 40px sits below the nav. */
  padding-top: var(--ny-clear, 0px);
  padding-bottom: 64px;
}

/* --- the account sub-nav: full-bleed to the page's own edge, as the comp's is --- */
.ngs-wallet .ngs-w-account {
  display: flex; flex-wrap: wrap; gap: 32px;
  margin: 0 -56px; padding: 0 56px;
  background: var(--white); border-bottom: 1px solid var(--line);
}
.ngs-wallet .ngs-w-account a {
  font-family: var(--ui); font-size: 13.5px; font-weight: 400; color: var(--ink-600);
  padding: 15px 0; margin-bottom: -1px; text-decoration: none;
  border-bottom: 2px solid transparent;
}
.ngs-wallet .ngs-w-account a:hover { color: var(--ink-900); }
.ngs-wallet .ngs-w-account a[aria-current="page"] {
  font-weight: 600; color: var(--ink-900); border-bottom-color: var(--violet-500);
}

.ngs-wallet .ngs-w-body { padding-top: 40px; }

/* --- type --- */
.ngs-wallet .ngs-w-h1 {
  font-family: var(--display); font-size: 40px; line-height: 1.12; font-weight: 600;
  letter-spacing: -0.028em; color: var(--ink-900); margin: 0; text-transform: none;
}
.ngs-wallet .ngs-w-h3 {
  font-family: var(--display); font-size: 22px; line-height: 1.26; font-weight: 600;
  letter-spacing: -0.016em; color: var(--ink-900); margin: 0; text-transform: none;
}
.ngs-wallet .ngs-w-h4 {
  font-family: var(--display); font-size: 17px; line-height: 1.34; font-weight: 600;
  letter-spacing: -0.01em; color: var(--ink-900); margin: 0; text-transform: none;
}
.ngs-wallet .ngs-w-sm { font-family: var(--text); font-size: 13.5px; line-height: 1.55; margin: 0; }
.ngs-wallet .ngs-w-muted { color: var(--ink-500); }

/* More space above a heading than below it: a section's heading sits 16px off its
   content, and the sub-line under an h3 sits 8px off the heading. */
.ngs-wallet .ngs-w-sechead { margin: 0 0 16px; }
/* The line under "Cards not yet redeemed" that says what the list IS. It sits
   between a heading and its content, so it carries the heading's bottom margin
   and the heading gives its own up. */
.ngs-wallet .ngs-w-sechead + .ngs-w-sechead-note { margin: -8px 0 16px; }
.ngs-wallet .ngs-w-sechead .ngs-w-sm { margin-top: 8px; }

/* --- head --- */
.ngs-wallet .ngs-w-head {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 20px; flex-wrap: wrap; margin-bottom: 32px;
}
.ngs-wallet .ngs-w-head-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* --- the panel, and the stat inside it --- */
.ngs-wallet .ngs-w-panel {
  background: var(--white); color: var(--ink-900);
  border: 1px solid var(--line); border-radius: 16px; padding: 24px;
}
.ngs-wallet .ngs-w-panel--table { padding: 20px 8px 8px; }
.ngs-wallet .ngs-w-stack { display: flex; flex-direction: column; gap: 16px; }
.ngs-wallet .ngs-w-stack form { margin: 0; }
.ngs-wallet .ngs-w-field { display: flex; flex-direction: column; gap: 7px; }

.ngs-wallet .ngs-w-stats {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; margin-bottom: 32px;
}
.ngs-wallet .ngs-w-stat { display: flex; flex-direction: column; gap: 3px; }
.ngs-wallet .ngs-w-stat-label { font-family: var(--ui); font-size: 12px; font-weight: 500; color: var(--ink-500); }
.ngs-wallet .ngs-w-stat-value {
  font-family: var(--display); font-size: 27px; font-weight: 600; letter-spacing: -0.028em;
  color: var(--ink-900); line-height: 1.15; font-variant-numeric: tabular-nums;
}
.ngs-wallet .ngs-w-stat-value--date { font-size: 22px; }
.ngs-wallet .ngs-w-line { display: block; }
.ngs-wallet .ngs-w-stat-note { font-family: var(--text); font-size: 12.5px; color: var(--ink-500); }
.ngs-wallet .ngs-w-stat--warn .ngs-w-stat-value { color: var(--warn-fg); }

/* --- tabs: the comp's chips, as links --- */
.ngs-wallet .ngs-w-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 32px; }
.ngs-wallet .ngs-w-tab {
  display: inline-flex; align-items: center;
  font-family: var(--ui); font-size: 12.5px; font-weight: 500; line-height: 1.55;
  text-transform: none; letter-spacing: normal; text-decoration: none;
  padding: 5px 12px; border-radius: 999px; border: 1px solid transparent;
  background: var(--line-soft); color: var(--ink-700);
  transition: background .14s cubic-bezier(.22,.61,.36,1);
}
.ngs-wallet .ngs-w-tab:hover { background: var(--line); color: var(--ink-700); }
.ngs-wallet .ngs-w-tab.is-on,
.ngs-wallet .ngs-w-tab.is-on:hover { background: var(--violet-500); color: var(--white); }

/* --- the overview's two columns --- */
.ngs-wallet .ngs-w-cols {
  display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 40px; align-items: start;
}
.ngs-wallet .ngs-w-col { display: flex; flex-direction: column; gap: 48px; min-width: 0; }
.ngs-wallet .ngs-w-narrow { max-width: 420px; }
.ngs-wallet .ngs-w-faces {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 24px;
}

/* --- the tables: the comp's `.table` --- */
/* THE CREDIT TABLE SCROLLS SIDEWAYS ON A PHONE AND NOTHING SAID SO, which is
   the whole defect: `overflow-x: auto` was here on its own, one line, and the
   AMOUNT column - the number the screen exists to show - sat off the right edge
   with no sign it could be reached.

   IT CANNOT BE MADE TO FIT, and that was checked rather than assumed. At 360px
   the panel leaves 294px and the three columns want 361. Trimming the cell
   padding to 8px gets it to 313, still over, and squeezing a money column
   further would start breaking figures across lines, which is the worst way for
   a number to fail (the note on `.ngs-grid--browse` says the same thing about
   the catalog's price). So the scroller stays and gets an affordance instead.

   THE SHADOW APPEARS ONLY WHERE THERE IS MORE TO SEE. The two linear gradients
   are `background-attachment: local`, so they travel with the content and
   cover the shadow when that edge is reached; the two radials are `scroll`, so
   they stay pinned to the box. The pair cancels out at each end - no shadow at
   the left until you scroll right, none at the right once you arrive. Pure CSS,
   no script, and nothing to keep in sync with a scroll handler.

   `--white` IS THE PANEL'S OWN BACKGROUND, read off `.ngs-w-panel` rather than
   guessed: the scroller and the table are both transparent, so the covering
   gradient has to be the colour that is actually painted behind them. If that
   panel is ever recoloured this needs recolouring with it.

   STACKING THE TABLE INTO LABEL/VALUE ROWS is the other answer and is not taken
   here: it is a layout nobody has drawn, on a screen that is shipped, and it
   belongs in a comp rather than in a CSS pass. */
.ngs-wallet .ngs-w-scroll {
  overflow-x: auto;
  background:
    linear-gradient(to right, var(--white) 30%, rgba(255,255,255,0)) left center,
    linear-gradient(to left,  var(--white) 30%, rgba(255,255,255,0)) right center,
    radial-gradient(farthest-side at 0 50%,   rgba(28,19,48,.16), rgba(28,19,48,0)) left center,
    radial-gradient(farthest-side at 100% 50%, rgba(28,19,48,.16), rgba(28,19,48,0)) right center;
  background-repeat: no-repeat;
  background-size: 32px 100%, 32px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}
.ngs-wallet table.ngs-w-table {
  width: 100%; margin: 0; border: 0; border-collapse: collapse;
  font-family: var(--text); font-size: 13.5px; table-layout: auto;
}
.ngs-wallet .ngs-w-table th {
  font-family: var(--ui); font-size: 11px; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--ink-500);
  text-align: left; padding: 0 16px 8px; background: none;
  border: 0; border-bottom: 1px solid var(--line-strong); white-space: nowrap;
}
.ngs-wallet .ngs-w-table td {
  font-size: 13.5px; color: var(--ink-800); text-align: left; background: none;
  padding: 13px 16px; border: 0; border-bottom: 1px solid var(--line-soft); vertical-align: middle;
}
.ngs-wallet .ngs-w-table tbody tr:hover { background: var(--violet-50); }
.ngs-wallet .ngs-w-table tbody tr:last-child td { border-bottom: 0; }
.ngs-wallet .ngs-w-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ngs-wallet .ngs-w-table td .ngs-w-sm { display: block; margin-top: 2px; }
.ngs-wallet .ngs-w-change { font-weight: 700; }
.ngs-wallet .ngs-w-change.ngs-w-pos { color: var(--ok-fg); }
.ngs-wallet .ngs-w-change.ngs-w-held { color: var(--ink-500); }

/* --- chips and dots --- */
.ngs-wallet .ngs-w-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--ui); font-size: 12.5px; font-weight: 500; line-height: 1.55;
  padding: 5px 12px; border-radius: 999px; border: 1px solid transparent; white-space: nowrap;
}
.ngs-wallet .ngs-w-chip--neutral { background: var(--line-soft); color: var(--ink-700); }
.ngs-wallet .ngs-w-chip--warn { background: var(--warn-bg); color: var(--warn-fg); }
.ngs-wallet .ngs-w-chip--ok { background: var(--ok-bg); color: var(--ok-fg); }
.ngs-wallet .ngs-w-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; display: inline-block; }
.ngs-wallet .ngs-w-dot--warn { background: var(--warn-fg); }
.ngs-wallet .ngs-w-dot--ok { background: var(--ok-fg); }

/* A lapsed lot is drawn, and drawn quietly: its credit is no longer spendable and is
   no longer in "Available", so the row is a record rather than an offer. No amber -
   on this screen amber means "about to lapse", and this one already has. */
.ngs-wallet .ngs-w-row--lapsed td { color: var(--ink-500); }
.ngs-wallet .ngs-w-row--lapsed td.num { text-decoration: line-through; }

/* --- form controls. `input[type=text]` (0,1,1) beats a lone class, hence 0,2,1 --- */
.ngs-wallet label.ngs-label {
  display: block; margin: 0; font-family: var(--ui); font-size: 12.5px; font-weight: 500;
  letter-spacing: .005em; text-transform: none; color: var(--ink-600);
}
.ngs-wallet input.ngs-input {
  width: 100%; height: auto; margin: 0; box-shadow: none; -webkit-appearance: none; appearance: none;
  font-family: var(--text); font-size: 14.5px; line-height: 1.55; letter-spacing: normal;
  color: var(--ink-900); background: var(--white);
  border: 1px solid var(--line-strong); border-radius: 8px; padding: 11px 13px;
}
.ngs-wallet input.ngs-input::placeholder { color: var(--ink-400); }
.ngs-wallet input.ngs-input:hover { border-color: var(--ink-300); }
.ngs-wallet input.ngs-input:focus {
  outline: none; border-color: var(--violet-400); box-shadow: 0 0 0 3px var(--violet-100);
}

/* --- buttons. NEVER CAPS: restated here, not left to inherit --- */
.ngs-wallet .ngs-btn {
  text-transform: none; letter-spacing: normal; text-decoration: none;
  font-family: var(--ui); font-weight: 600; line-height: 1.25;
  transform: none; white-space: nowrap;
}
/* The per-screen underline rule that was here is gone: one rule, on `.ngs-btn:hover`
   near the top of this file. See the note there - and note it is DEFENSIVE, because
   wp-custom-css already neutralises the theme's underline site-wide. */
.ngs-wallet .ngs-btn--sm { padding: 8px 16px; font-size: 13px; }
.ngs-wallet .ngs-btn--block { display: flex; width: 100%; }
.ngs-wallet .ngs-btn--primary {
  background: var(--violet-500); color: var(--white); border-color: transparent;
  box-shadow: 0 2px 4px rgba(0,0,0,.05), 0 4px 10px rgba(0,0,0,.05);
}
.ngs-wallet .ngs-btn--primary:hover {
  background: var(--violet-600); color: var(--white);
  box-shadow: 0 4px 8px rgba(0,0,0,.05), 0 10px 22px rgba(0,0,0,.07);
}
.ngs-wallet .ngs-btn--quiet {
  background: var(--white); color: var(--ink-800); border-color: var(--line-strong);
  box-shadow: 0 1px 2px rgba(0,0,0,.05), 0 1px 1px rgba(0,0,0,.04);
}
.ngs-wallet .ngs-btn--quiet:hover {
  background: var(--paper-warm); color: var(--ink-800); border-color: var(--ink-300);
  box-shadow: 0 1px 2px rgba(0,0,0,.05), 0 1px 1px rgba(0,0,0,.04);
}
.ngs-wallet .ngs-btn:active { transform: translateY(1px); }
.ngs-wallet :focus-visible { outline: 2px solid var(--violet-500); outline-offset: 2px; border-radius: 4px; }

/* --- the gift card object: the one thing on this screen allowed any gold.
   Pure CSS, so there is no artwork slot to be empty. A gradient never stands
   alone: `background-color` carries the face if the image layers do not paint. --- */
.ngs-wallet .ngs-w-face {
  position: relative; overflow: hidden; aspect-ratio: 8 / 5; border-radius: 12px;
  background-color: #1A1036;
  background-image:
    radial-gradient(70% 90% at 16% 8%, rgba(230,201,122,.30), transparent 60%),
    radial-gradient(60% 80% at 92% 96%, rgba(141,34,195,.42), transparent 62%),
    linear-gradient(152deg, #2E2056 0%, #1A1036 54%, #241646 100%);
  color: var(--white);
  box-shadow: 0 4px 9px rgba(0,0,0,.22), 0 9px 18px rgba(0,0,0,.24),
              inset 0 0 0 1px rgba(230,201,122,.34);
  padding: 20px; display: flex; flex-direction: column; justify-content: space-between;
}
.ngs-wallet .ngs-w-face::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23g)'/%3E%3C/svg%3E");
  opacity: .12; mix-blend-mode: overlay;
}
.ngs-wallet .ngs-w-face > * { position: relative; z-index: 1; }
.ngs-wallet .ngs-w-face-top { display: flex; justify-content: space-between; align-items: center; }
.ngs-wallet .ngs-w-face-logo {
  display: flex; align-items: baseline; gap: 1px;
  font-family: var(--display); font-weight: 700; font-size: 12px; letter-spacing: .055em;
}
.ngs-wallet .ngs-w-face-logo b { color: var(--white); font-weight: 700; }
.ngs-wallet .ngs-w-face-logo i { color: var(--violet-300); font-style: normal; font-weight: 700; }
.ngs-wallet .ngs-w-spark { color: var(--gold-400); }
.ngs-wallet .ngs-w-face-amount {
  font-family: var(--display); font-size: 22px; line-height: 1.26; font-weight: 600;
  letter-spacing: -0.016em; color: var(--white);
}
/* The card code is read off the card and typed into a field, so it is set in the
   UI's tabular figures with the letter-spacing a grouped code wants. */
.ngs-wallet .ngs-w-face-code {
  font-variant-numeric: tabular-nums;
  letter-spacing: .04em;
}

.ngs-wallet .ngs-w-face-meta {
  display: flex; justify-content: space-between; gap: 12px; margin-top: 12px;
  font-family: var(--text); font-size: 12.5px; line-height: 1.5; color: var(--gold-300);
}

/* Visually hidden, but read aloud. Own class: the theme's `.screen-reader-text`
   is the theme's to keep. */
.ngs-wallet .ngs-w-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* --- "what this credit can do" --- */
.ngs-wallet .ngs-w-point { display: flex; align-items: flex-start; gap: 12px; }
.ngs-wallet .ngs-w-tick { width: 16px; height: 16px; margin-top: 3px; color: var(--violet-500); }
.ngs-wallet .ngs-w-tick--stop { color: var(--stop-fg); }

/* --- an empty state: a quiet panel, centred, in the comp's idiom --- */
.ngs-wallet .ngs-w-empty {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px;
  padding: 32px 24px;
}
.ngs-wallet .ngs-w-empty .ngs-i { color: var(--ink-400); }
.ngs-wallet .ngs-w-empty-title {
  font-family: var(--display); font-size: 15px; font-weight: 600; color: var(--ink-900); margin: 4px 0 0;
}

/* --- previous / next --- */
.ngs-wallet .ngs-w-pager {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 16px; margin-top: 20px;
}
.ngs-wallet .ngs-w-pager-side--end { display: flex; justify-content: flex-end; }

@media (max-width: 1000px) {
  .ngs-wallet .ngs-w-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ngs-wallet .ngs-w-cols { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  .ngs-wallet .ngs-w-account { margin: 0 -24px; padding: 0 24px; gap: 24px; overflow-x: auto; flex-wrap: nowrap; }
  .ngs-wallet .ngs-w-account a { white-space: nowrap; }
}
@media (max-width: 560px) {
  .ngs-wallet .ngs-w-stats { grid-template-columns: minmax(0, 1fr); }
  .ngs-wallet .ngs-w-h1 { font-size: 32px; }
  .ngs-wallet .ngs-w-faces { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) {
  .ngs-wallet .ngs-w-tab { transition: none; }
}

/* The gift-card band is one link, so it has to behave like one: inherit the
   band's own colours rather than the document's link colour, and lift a little
   on hover so the whole block reads as the target instead of the button alone.
   The chips inside are a picture of what a card is, not a chooser -- the amount
   is picked on the card page -- so nothing in here takes a pointer of its own. */
.ngs .ngs-band--go { text-decoration: none; color: inherit; display: flex; cursor: pointer; }
.ngs .ngs-band--go:hover,
.ngs .ngs-band--go:focus-visible { transform: translateY(-2px); }
.ngs .ngs-band--go { transition: transform .18s ease, box-shadow .18s ease; }
.ngs .ngs-band--go:hover { box-shadow: 0 14px 30px -18px rgba(10,6,22,.55); }
.ngs .ngs-band--go:focus-visible { outline: 2px solid var(--gold-600); outline-offset: 3px; }
.ngs .ngs-band--go .ngs-chip,
.ngs .ngs-band--go .ngs-btn { pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .ngs .ngs-band--go { transition: none; }
  .ngs .ngs-band--go:hover,
  .ngs .ngs-band--go:focus-visible { transform: none; }
}

/* ---------------------------------------------------------------------------
   SCREEN 07 — CHOOSE AN AMOUNT
   Three tiers, the send/keep question, and the card the buyer is about to buy.
   It reuses .ngs-cols and .ngs-preview from the personalise screen, because it
   is the same two-column shape one step earlier; only the left column is new.
   --------------------------------------------------------------------------- */

.ngs-amount-main { min-width: 0; }

.ngs-tiers {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s5); margin-top: var(--s7);
}
@media (max-width: 720px) { .ngs-tiers { grid-template-columns: minmax(0, 1fr); } }

/* A TIER IS A RADIO YOU PRESS. It was an <article> holding its own submit
   button, so "chosen" could only ever be a server state and the filled purple
   button on the chosen card did double duty as a selected MARKER and as the
   primary ACTION. Now the whole card is the <label>, the only submit on the
   screen is Continue, and the state is drawn from the live input.

   RINGED AND DOTTED, not merely tinted -- a tint alone reads as "disabled" at
   least as often as it reads as "selected", which is most of what was wrong. */
.ngs-tier {
  display: flex; flex-direction: column;
  padding: var(--s6);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  cursor: pointer;
  font-size: 15px; /* the bare-<label> leak again */
  transition: border-color .16s cubic-bezier(.4,0,.2,1), box-shadow .16s cubic-bezier(.4,0,.2,1);
}
/* Hidden the same way `.ngs-choice input` is; `.ngs-radio` is what the eye gets.
   Its own rule, because this is a <label> that is not a `.ngs-choice`. */
.ngs-tier input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.ngs-tier-head { display: flex; align-items: center; gap: var(--s3); }
.ngs-tier:hover { border-color: var(--violet-300); }
.ngs-tier.is-on,
.ngs-tier:has(input:checked) {
  border-color: var(--violet-500);
  box-shadow: 0 0 0 1px var(--violet-500);
}
.ngs-tier.is-on .ngs-radio,
.ngs-tier:has(input:checked) .ngs-radio { border-color: var(--violet-500); }
.ngs-tier.is-on .ngs-radio::after,
.ngs-tier:has(input:checked) .ngs-radio::after {
  content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--violet-500);
}
.ngs-tier:has(input:focus-visible) { outline: 2px solid var(--violet-400); outline-offset: 2px; }
/* These were <div>/<p> and are <span> now, because a <label> may not contain the
   block-level flow content this screen wants. `display:block` says out loud what
   the tags no longer imply. */
.ngs-tier-amount { display: block; font-size: 30px; font-weight: 700; line-height: 1.1; letter-spacing: -.01em; }
/* .t-sm in the comp, which is 13.5px -- not the body size. The bottom margin goes
   with the button it used to clear. */
.ngs-tier-line   { display: block; margin: var(--s5) 0 0; font-size: 13.5px; }

/* The comp sets this with .t-h3, which is 22px. `.ngs-h3` cannot supply it:
   this file has .ngs-h3 and .ngs-h4 BOTH at 17px, so the deck's h3 step does
   not exist here and every .ngs-h3 on every screen is really an h4. Sizing it
   on the screen's own class fixes this heading without moving the others --
   the collapsed step is a real problem but it is not screen 07's to fix. */
.ngs-amount-who { margin-top: var(--s11); font-size: 22px; line-height: 1.26; }

/* The "choose who this is for" sentence. As a child of the grid it would take a
   column and shove "Send it to someone" into the second. */
.ngs-amount-whoerr { margin-top: var(--s5); }

/* ---------------------------------------------------------------------------
   The credit confirmation, which shares `.ngs-sent` with the gift one and needs
   three things on top of it: a balance that reads as the answer, the way on to
   the wallet, and the line that says we are taking them there.
   --------------------------------------------------------------------------- */
.ngs-sent-money { margin-top: var(--s7); max-width: 420px; }
.ngs-sent-go    { margin-top: var(--s7); }
.ngs-sent-auto  { margin-top: var(--s3); }

.ngs-choices {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s4); margin-top: var(--s5);
}
@media (max-width: 720px) { .ngs-choices { grid-template-columns: minmax(0, 1fr); } }

/* The comp's .choice: s4 of padding, s3 of gap, the stronger line and the
   medium radius. Ours was a step loose on all four.

   `font-size` is here because a .ngs-choice is a <label>, and twentytwenty
   sizes bare `label` -- the same leak as the uppercase `button` this file
   already defends against, landing these at 16px inside a 15px column. The
   comp's .choice simply inherits the body, so this says the body's size out
   loud rather than relying on winning an inheritance it does not get. */
/* ---------------------------------------------------------------------------
   `.ngs-choice` WAS DECLARED TWICE IN THIS FILE, and that is what broke the
   selected state on screen 07 (Kunal, 2026-10-07).

   This block redeclared the control ~570 lines after the real one, which left two
   rules competing to say "chosen": the server-printed `--on` class, which came
   from the SAVED DRAFT and therefore could not move, and `:has(input:checked)`,
   which follows the click. After any click they were on different boxes, so BOTH
   wore the violet border and the violet ring and the only thing telling them
   apart was a 4%-lightness tint.

   The `--on` class is deleted. One source of truth: `:has(input:checked)`, with
   `.is-on` kept in step by `ngs-amount.js` for browsers without `:has()` - the
   same pair screen 20 has always used. Nothing server-rendered paints selection.

   What screen 07 genuinely needs that the shared control does not give it is
   kept, and it is three declarations.
   --------------------------------------------------------------------------- */
.ngs-choices .ngs-choice {
  align-items: flex-start;
  /* `font-size` because .ngs-choice is a <label>, and twentytwenty sizes bare
     `label` -- the same leak as the uppercase `button` this file already defends
     against, landing these at 16px inside a 15px column. */
  font-size: 15px;
}
.ngs-choices .ngs-choice .ngs-radio { margin-top: 2px; }
.ngs-choice-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

/* The comp puts this column's Preview, face, summary, hint and Continue inside
   one .panel, and leaves "What it buys" outside it on the page. Screen 09 is
   deliberately the opposite -- its rail says "the email mock is the only card
   in the column", a frame around the frame being chrome -- and 09 and 07 share
   .ngs-preview. So the panel is a wrapper on 07's markup, NOT a rule on
   .ngs-preview, or it would grow a box around 09's email too. */
.ngs-amount-panel {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s6);
}

/* The card face, reused from the storefront's gift-card band so the object a
   buyer sees here is the object they saw there. The band laid it out as an item
   in a ROW, so its `flex: 0 0 300px` is a width there -- and a HEIGHT here,
   where .ngs-preview is a column. That basis beat `aspect-ratio: 8 / 5` and the
   card rendered 396x300 (4:3) instead of the comp's 8:5. `flex: none` hands the
   ratio back; nothing else about the face changes. */
.ngs-preview .ngs-face { margin-top: var(--s4); flex: none; }
/* Screen 07 dropped its card face and its heading, so the money list is now the
   panel's first child and was carrying the margin that sat under the heading. */
.ngs-amount-panel > .ngs-money:first-child { margin-top: 0; }

/* `.ngs-money` IS ALREADY TAKEN. The storefront's price line claims it up at the
   top of this file -- `display:flex; flex-wrap:wrap; align-items:baseline` --
   for the price/was/save trio. This <dl> is a different object with the same
   name, and because the rule below only set a margin, the dl stayed a wrapping
   flex row: the four rows sat two-per-line, label and value jammed together,
   instead of four full-width rows with the value on the right. `display:block`
   is what actually fixes this screen's summary; the rest is the comp's
   .money-row (assets/system.css) transcribed. */
.ngs-preview .ngs-money { display: block; margin: var(--s5) 0 0; }
.ngs-money-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s4); padding: 9px 0; font-size: 13.5px;
}
.ngs-money-row dt { color: var(--ink-600); }
.ngs-money-row dd { margin: 0; font-variant-numeric: tabular-nums;
                    color: var(--ink-900); font-weight: 600; }
.ngs-money-row--total {
  border-top: 1px solid var(--line-strong);
  margin-top: var(--s2); padding-top: var(--s4);
}
.ngs-money-row--total dt { font-family: var(--display); font-weight: 600;
                           font-size: 15px; color: var(--ink-900); }
.ngs-money-row--total dd { font-family: var(--display); font-size: 21px;
                           letter-spacing: -.022em; }
.ngs-hint { margin-top: var(--s4); color: var(--ink-700); font-size: 13.5px; }
.ngs-amount-continue { margin-top: var(--s5); }

/* The comp's gold rule beside the closing note. */
.ngs-preview .ngs-preview-foot {
  margin-top: var(--s6); padding-left: var(--s5);
  border-left: 2px solid var(--gold-400);
}


/* ==========================================================================
   The gift bar, and screen 06
   ========================================================================== */

/* THE WAY BACK OFF A GIFT SURFACE (client, 2026-10-06: "there is no back button
   on collections, gift card, or events and programs sadhana individual page").

   One component, two skins. As a band of its own it is comp 05 and 06's white
   strip; inside the collection hero it is the same row drawn on the dark ground,
   because a white band above that hero would reopen the seam the edge-to-edge
   rule above exists to close.

   THE LINK COMES FIRST in the markup and in the row. The comp puts the mode
   sentence on the left and the link on the right, which reads well on a 1280
   board and badly on a phone, where the thing a member is looking for would be
   the second line. Back first, mode second, and the mode drops out below 720. */
/* NO BOX (Kunal, 2026-10-07: "ensure the Back to Gifts section doesn't have that
   outline anywhere and is left aligned with the left most section").

   It was a white panel with a 1px border, a 16px radius and 24px of horizontal
   padding, which put the link's text 25px INSIDE the column every other thing on
   the page starts at - measured on dev at 1512: the box opened at 85 and the link
   at 110, against an h1 and a stepper at 85 and the site's own logo at 81. A way
   OUT of a screen drawn as a panel also reads as a piece OF it.

   Flush now, so the link, the stepper and the heading share one left edge. */
.ngs-giftbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s5); flex-wrap: wrap;
  margin-bottom: var(--s8);
}

.ngs-giftbar-back {
  display: inline-flex; align-items: center; gap: var(--s2);
  font-family: var(--ui); font-size: 13.5px; font-weight: 500;
  color: var(--ink-700); text-decoration: none;
}
.ngs-giftbar-back:hover { color: var(--ink-900); text-decoration: underline; }

.ngs-giftbar-mode {
  display: inline-flex; align-items: center; gap: var(--s3);
  font-family: var(--ui); font-size: 14px; font-weight: 600;
  color: var(--ink-900);
}
.ngs-giftbar-mode .ngs-i { color: var(--gold-600); }

/* Inside the hero: no panel, no border, nothing between the link and the ground.
   The negative left margin is an optical pull: the padding is hit area, not
   indent, so the text lines up with the title below it rather than sitting a
   notch to its right. */
.ngs-giftbar--on-dark {
  margin: 0 0 var(--s7);
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
}
.ngs-giftbar--on-dark .ngs-giftbar-back {
  color: var(--on-dark-muted);
  margin-left: -10px;
  padding: 6px 10px;
  border-radius: var(--r-sm);
}
.ngs-giftbar--on-dark .ngs-giftbar-back:hover {
  color: var(--white);
  background: rgba(255,255,255,.10);
  text-decoration: none;
}
.ngs-giftbar--on-dark .ngs-giftbar-mode { color: var(--on-dark-muted); font-weight: 500; }
.ngs-giftbar--on-dark .ngs-giftbar-mode .ngs-i { color: var(--gold-400); }

@media (max-width: 720px) {
  /* The sentence is context, the link is a control. On a phone the control
     survives and the context does not. */
  .ngs-giftbar-mode { display: none; }
}

/* ---- screen 06, the grid ------------------------------------------------ */

.ngs-browse .ngs-bc-head { margin-bottom: var(--s7); }

.ngs-browse-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s5); flex-wrap: wrap;
  padding-bottom: var(--s5);
  border-bottom: 1px solid var(--line);
}

/* Empty until ngs-browse.js fills it. `[hidden]` is restated because `.ngs-chips`
   sets `display:flex` above and a class beats the attribute's UA rule. */
.ngs-chips--filter[hidden] { display: none; }
.ngs-chips--filter { gap: var(--s2); }

/* A FILTER CHIP IS A `<button>`, and twentytwenty styles the bare element:
   `text-transform: uppercase` and a letter-spacing with it. The storefront has
   been bitten by this exact rule three times (CLAUDE.md: every .ngs-btn in the
   build rendered in CAPS from phase B to 0.13.5), so these are restated on
   purpose rather than inherited and hoped about. A class beats an unqualified
   type selector, so restating is enough.

   Found in tests/preview-browse.html before this ever reached a page -- which is
   what that file is for. */
.ngs-chip--filter {
  cursor: pointer;
  background: var(--line-soft);
  color: var(--ink-700);
  border: 1px solid transparent;
  font-family: var(--ui);
  text-transform: none;
  letter-spacing: normal;
  text-decoration: none;
}
.ngs-chip--filter:hover,
.ngs-chip--filter:focus,
.ngs-chip--filter:active { text-decoration: none; }
.ngs-chip--filter:hover { background: var(--line); }
.ngs-chip--filter[aria-pressed="true"] { background: var(--violet-500); color: var(--white); }
.ngs-chip--filter:focus-visible { outline: 2px solid var(--violet-400); outline-offset: 2px; }

/* The toggle is not one of the choices, so it does not look like one: outlined
   rather than filled, as comp 06 draws it. */
.ngs-chip--toggle {
  margin-left: auto;
  background: transparent;
  border-color: var(--line-strong);
  color: var(--ink-600);
}
.ngs-chip--toggle:hover { background: var(--line-soft); }
.ngs-chip--toggle[aria-pressed="true"] {
  background: var(--violet-50); border-color: var(--violet-300); color: var(--violet-600);
}

.ngs-browse-count { flex: none; color: var(--ink-500); font-variant-numeric: tabular-nums; }

/* Comp 06 is five up. `.ngs-grid--paths` is four, which is right on screen 03
   where the strip is a sample and wrong here where it is the catalog. 196px puts
   five across a 1280 board with the page's own 56px gutters, which is the comp. */
.ngs-grid--browse {
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: var(--s5);
}

/* THE FOOT WRAPS, and it has to at this width. Comp 06's button says "Add" and
   ours says "Gift this path" (see NGS_Render::browse() for why the comp's
   multi-select is not built), which does not fit beside a price in a 196px card
   -- the price broke mid-figure, "₹2,58 / 0" on two lines, which is the worst
   way for a number to fail. The price keeps its line and the button drops below
   it when there is no room, which is the same pair in the same order either way.

   Seen in tests/preview-browse.html. It would not have shown on screen 03: those
   cards are 220px and the same markup fits there. */
.ngs-grid--browse .ngs-path-foot { flex-wrap: wrap; }
.ngs-grid--browse .ngs-path-foot > .ngs-h4 { white-space: nowrap; }
.ngs-grid--browse .ngs-path-foot > .ngs-btn { flex: 1 1 auto; justify-content: center; }

/* A filtered-out card. `hidden` alone loses to the grid's own `display`. */
.ngs-grid--browse .ngs-path[hidden] { display: none; }

/* ---- choosing several paths, and reading about one ---------------------- */

/* "About this path" sits with the title and the date, not with the price: it is
   information about the thing, and the foot is where the decisions are. Pushed
   to the bottom of the body so it lines up across a row of cards whose titles
   run to different lengths. */
.ngs-path-about {
  display: inline-flex; align-items: center; gap: 4px;
  margin-top: var(--s3);
  font-size: 12.5px;
}
.ngs-path-body { display: flex; flex-direction: column; align-items: flex-start; }
.ngs-path-body .ngs-path-about { margin-top: auto; padding-top: var(--s3); }
.ngs-path.is-off .ngs-path-about { color: var(--ink-500); }

/* THE ADD TOGGLE. `.ngs-pick` replaces the card's own gift link when the script
   is running, so it inherits `.ngs-btn--gift` and only states the difference:
   unchosen it is quiet, chosen it is the gold the gift itself is marked in.
   Restates the type rules for the same reason .ngs-chip--filter does -- this is
   a <button> where the thing it replaced was an <a>, and twentytwenty styles the
   bare element. */
.ngs-pick {
  text-transform: none;
  letter-spacing: normal;
  background: transparent;
  color: var(--ink-700);
  border: 1px solid var(--line-strong);
  box-shadow: none;
}
.ngs-pick:hover { background: var(--line-soft); color: var(--ink-900); }
.ngs-pick.is-on {
  background: linear-gradient(140deg,#F0DDA6,#E6C97A);
  color: #3A2A05;
  border-color: transparent;
}
.ngs-pick:focus-visible { outline: 2px solid var(--violet-500); outline-offset: 2px; }

/* A chosen card says so without being read: the gold edge is the same mark the
   button carries, so the two cannot disagree about what is in the gift. */
.ngs-path:has(.ngs-pick.is-on) {
  border-color: var(--gold-400);
  box-shadow: 0 0 0 1px var(--gold-400);
}

/* THE SELECTION BAR. Fixed, because the grid is long and a decision made at the
   bottom of it must not need a scroll back to act on. It is hidden whenever
   nothing is chosen, so it costs an empty page nothing. */
.ngs-pickbar {
  position: fixed; z-index: 40;
  left: 50%; transform: translateX(-50%);
  bottom: var(--s6);
  display: flex; align-items: center; gap: var(--s5);
  padding: var(--s4) var(--s5) var(--s4) var(--s6);
  background: var(--indigo-800);
  color: var(--on-dark);
  border-radius: var(--r-pill);
  box-shadow: 0 10px 34px -10px rgba(10,6,22,.6);
  max-width: calc(100vw - 2 * var(--s5));
}
.ngs-pickbar[hidden] { display: none; }
.ngs-pickbar-count {
  font-family: var(--ui); font-size: 14px; font-weight: 600; white-space: nowrap;
}
.ngs-pickbar-clear {
  background: none; border: 0; padding: 4px 2px; cursor: pointer;
  font-family: var(--ui); font-size: 13px; text-transform: none;
  letter-spacing: normal; text-decoration: underline;
  color: var(--on-dark-muted);
}
.ngs-pickbar-clear:hover { color: var(--white); }
.ngs-pickbar .ngs-btn { white-space: nowrap; }

/* The bar floats over the last row of cards, so the grid ends above it rather
   than underneath it. */
.ngs-browse .ngs-grid--browse { padding-bottom: 88px; }

@media (max-width: 560px) {
  .ngs-pickbar {
    left: var(--s4); right: var(--s4); transform: none;
    max-width: none; justify-content: space-between; gap: var(--s3);
    padding-left: var(--s5);
  }
  /* The count is the thing that is reassuring; Clear is the thing that is rarely
     wanted. On a phone the button and the count survive. */
  .ngs-pickbar-clear { display: none; }
}


/* ==========================================================================
   DESIGN & SECTIONS, 0.68.0. Everything below is a var() whose FALLBACK is the
   value this stylesheet already had, so an operator who has typed nothing gets
   byte-identical rendering and the comps stay the source. Nothing here applies
   until `NGS_Design_Settings` emits the property.
   ========================================================================== */

/* The two grids take their whole track list from PHP, because the unset grid is
   auto-fill and the set one is a fixed count - `repeat(auto-fill, minmax(0,1fr))`
   is not expressible, so one bare number could not have served both. */
.ngs-grid--journey {
  grid-template-columns: var(--ngs-journey-tracks, repeat(auto-fill, minmax(190px, 1fr)));
  gap: var(--ngs-journey-gap, var(--s6));
}
/* `:not(.ngs-grid--browse)` IS LOAD-BEARING. Screen 06's catalog carries BOTH
   classes - `ngs-grid ngs-grid--paths ngs-grid--browse` - and its own five-up
   196px rule sits ABOVE this block in the file, so an unqualified
   `.ngs-grid--paths` here would win on order and quietly put the catalog back to
   four across. The design control is for the storefront's strip, which is the
   section the setting names; the catalog's density was a separate decision with
   its own note a few hundred lines up. */
.ngs-grid--paths:not(.ngs-grid--browse) {
  grid-template-columns: var(--ngs-path-tracks, repeat(auto-fill, minmax(220px, 1fr)));
}

/* A COUNT AN OPERATOR TYPES IS A DESKTOP COUNT, and the field says so. Six
   across is a reasonable answer on a 1440px screen and an unreadable one on a
   phone, so the narrow widths take the floor back regardless of what is set -
   the same shape as every other responsive rule in this file, and the reason
   the help text can promise it. */
@media (max-width: 900px) {
  .ngs-grid--journey,
  .ngs-grid--paths:not(.ngs-grid--browse) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .ngs-grid--journey,
  .ngs-grid--paths:not(.ngs-grid--browse) { grid-template-columns: minmax(0, 1fr); }
}

/* A background video REPLACES the slides rather than sitting behind them, so
   the fields go. They still RENDER - the carousel, the arrows and the title
   swap all read them, and removing them would point the arrows at nothing. */
.ngs-hero-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0;
}
.ngs-hero--video .ngs-fields { display: none; }
.ngs-hero--video .ngs-scrim { z-index: 1; }
.ngs-hero--video .ngs-hero-copy { z-index: 2; }

/* Where the buttons sit. Centre is the default and is what the comp draws, so
   it is the only one of the three that changes nothing. */
.ngs-hero--bottom-center .ngs-hero-row { justify-content: center; }
.ngs-hero--bottom-center .ngs-hero-line { margin-left: auto; margin-right: auto; }
.ngs-hero--bottom-left .ngs-hero-row { justify-content: flex-start; }
.ngs-hero--bottom-right .ngs-hero-row { justify-content: flex-end; }

/* ONE IMAGE IS NOT A CAROUSEL, so nothing cross-fades and the transition would
   only ever fire on the first paint. The class is also the honest signal in the
   markup that this banner does not rotate. */
.ngs-hero--still .ngs-field { transition: none; }

/* Title and line off. The copy block keeps its padding so the buttons stay off
   the bottom edge, and `pointer-events` is handed back to the controls alone so
   an invisible block does not eat clicks on the artwork behind it. */
.ngs-hero-copy--quiet { pointer-events: none; }
.ngs-hero-copy--quiet .ngs-hero-row { margin-top: 0; }
.ngs-hero-copy--quiet .ngs-hero-actions,
.ngs-hero-copy--quiet .ngs-arrows { pointer-events: auto; }

/* The three sections that can be recoloured. `color: inherit` is what carries a
   text colour down to the heading and the lead, which both set their own. */
.ngs-section--journey .ngs-h1, .ngs-section--journey .ngs-lead,
.ngs-section--paths .ngs-h1, .ngs-section--paths .ngs-lead,
.ngs-section--gift-card .ngs-h1, .ngs-section--gift-card .ngs-lead { color: inherit; }

/* Optional band artwork. There is no comp for it, so it is sized to sit above
   the card face rather than compete with it. */
.ngs-gift-card-artwork {
  display: block; width: 100%; max-width: 220px; height: auto;
  border-radius: var(--r-md); margin-bottom: var(--s5);
}

/* An uploaded card face. It BACKS the drawn one rather than replacing it
   (0.77.3), so the gradient goes and everything else stays: the same 8:5 box at
   the same flex basis, the same border, and the same padding holding the lockup
   where it already was. Keeping `.ngs-face`'s basis is what makes this swap
   invisible to the band's layout, including the `0 1 300px` that stops the face
   hanging off a 360px screen.

   The picture is taken OUT OF FLOW rather than made a flex item, so the face's
   `justify-content: space-between` still sees exactly the two children it was
   written for. A background-image would have done the same job without the
   `<img>`, and the element is kept because `loading="lazy"` and `decoding` are
   worth more here than the saved node: this picture is below the fold on a
   phone.

   AND THE SCRIM IS NOT DECORATION. The first upload was a pale photograph, and
   white text on it is unreadable without one - which is the whole reason the
   drawn face was a dark gradient in the first place. It is heavier at the top
   and bottom, where the lockup and the amount sit, and almost absent across the
   middle, so the picture is still the thing you see. */
.ngs-face--art {
  background: #160D2B; overflow: hidden; position: relative;
}
.ngs-face--art .ngs-face-img {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover;
  border-radius: inherit;
}
.ngs-face--art::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  border-radius: inherit; pointer-events: none;
  background: linear-gradient(180deg,
    rgba(18, 10, 36, .58) 0%,
    rgba(18, 10, 36, .14) 42%,
    rgba(18, 10, 36, .14) 58%,
    rgba(18, 10, 36, .72) 100%);
}
.ngs-face--art > :not(.ngs-face-img) { position: relative; z-index: 2; }
