/* ============================================================
   NumberGlyph — "the vault".

   The puzzle is a combination lock: the hidden number sits behind a door,
   the fingerprint cards are the gauges on the front of it, every guess is a
   turn of the dial, and each tile is a tumbler that either seats (green),
   catches (amber) or drops (steel). Winning opens the door.

   Scope: everything hangs off body.ng-vault and the game card .ngVault, so
   the site chrome (header, footer, ad slot, SEO cards) is untouched and the
   whole world can be removed by dropping one class.

   Theme contract: the site's --bg/--card/--text/--muted/--line still decide
   dark vs light. Every colour below resolves through a --vt-* token that is
   redeclared under :root[data-theme="light"], so the toggle keeps working.
   Selectors are prefixed with :root so they outrank the site's own
   `:root[data-theme="light"] .x` rules without leaning on !important —
   except where style-test.css already uses !important (tile fills, the two
   feedback pills), where matching it is the only option.
   ============================================================ */

:root body.ng-vault{
  --vt-display: 'Lilita One', 'Outfit', system-ui, sans-serif;

  /* steel */
  --vt-steel-0: #0a0c10;
  --vt-steel-1: #141920;
  --vt-steel-2: #1d2430;
  --vt-steel-3: #2a323f;
  --vt-brush:   rgba(255,255,255,.035);
  --vt-edge-hi: rgba(255,255,255,.10);
  --vt-edge-lo: rgba(0,0,0,.55);

  /* brass */
  --vt-brass:    #d9a441;
  --vt-brass-hi: #ffe08a;
  --vt-brass-lo: #7a5514;
  /* Filled brass (buttons, active pill): light enough at every stop for
     dark ink, in both themes. */
  --vt-fill-hi:  #ffe08a;
  --vt-fill:     #d9a441;
  --vt-fill-lo:  #c08f2e;
  --vt-fill-ink: #1a1200;
  --vt-line:     rgba(217,164,65,.26);
  --vt-line-soft:rgba(217,164,65,.14);

  /* ink */
  --vt-ink: #f3efe6;
  --vt-dim: #a89f8f;

  /* tumbler states */
  --vt-set-hi:   #7dffb0;
  --vt-set:      #2fd374;
  --vt-set-lo:   #17954d;
  --vt-set-2:    #17954d;
  --vt-set-ink:  #04140a;
  --vt-set-glow: rgba(47,211,116,.42);
  --vt-catch:    #f5bd3a;
  --vt-catch-2:  #b8801a;
  --vt-catch-ink:#1a1200;
  --vt-catch-glow: rgba(245,189,58,.36);
  --vt-cold:     #6fb3ff;
  --vt-alarm:    #ff4d5e;
  --vt-alarm-glow: rgba(255,77,94,.35);
  --vt-led-off:  #343a45;

  --vt-drop: rgba(0,0,0,.5);
  --vt-glow-scale: 1;
}

:root[data-theme="light"] body.ng-vault{
  --vt-steel-0: #e9ebef;
  --vt-steel-1: #ffffff;
  --vt-steel-2: #f4f5f8;
  --vt-steel-3: #e4e7ec;
  --vt-brush:   rgba(0,0,0,.025);
  --vt-edge-hi: rgba(255,255,255,.9);
  --vt-edge-lo: rgba(20,16,8,.14);

  /* Brass as ink on pale steel has to sit at 4.5:1, so both text brasses
     drop to the same burnished tone; the fills below keep the gold. */
  --vt-brass:    #8a5c0a;
  --vt-brass-hi: #8a5c0a;
  --vt-brass-lo: #5e3f05;
  --vt-fill-hi:  #f6d178;
  --vt-fill:     #d9a441;
  --vt-fill-lo:  #b8801a;
  --vt-fill-ink: #1a1200;
  --vt-line:     rgba(120,84,14,.30);
  --vt-line-soft:rgba(120,84,14,.16);

  --vt-ink: #1a1712;
  --vt-dim: #5d5647;

  --vt-set-hi:   #5ee89a;
  --vt-set:      #1a9d54;
  --vt-set-lo:   #1a9d54;   /* gradient floor; the darker --vt-set-2 is border only */
  --vt-set-2:    #12703b;
  --vt-set-ink:  #04140a;
  --vt-set-glow: rgba(23,149,77,.28);
  --vt-catch:    #f2b429;
  --vt-catch-2:  #c98a10;
  --vt-catch-ink:#241800;
  --vt-catch-glow: rgba(201,138,16,.28);
  --vt-cold:     #2a63d8;
  --vt-alarm:    #c62033;
  --vt-alarm-glow: rgba(198,32,51,.22);
  --vt-led-off:  #cfd4dc;

  --vt-drop: rgba(20,16,8,.18);
  --vt-glow-scale: .45;
}

/* ------------------------------------------------------------
   The door
   ------------------------------------------------------------ */
:root body.ng-vault .card.ngVault{
  position: relative;
  isolation: isolate;
  border: 1px solid var(--vt-line);
  border-radius: 20px;
  padding: 18px 18px 16px;
  color: var(--vt-ink);
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(217,164,65,.10), transparent 60%),
    repeating-linear-gradient(180deg, var(--vt-brush) 0 1px, transparent 1px 3px),
    linear-gradient(180deg, var(--vt-steel-2), var(--vt-steel-1) 40%, var(--vt-steel-0));
  box-shadow:
    inset 0 1px 0 var(--vt-edge-hi),
    inset 0 0 0 1px rgba(0,0,0,.25),
    0 24px 60px var(--vt-drop);
}

/* Brass frame + corner rivets. */
:root body.ng-vault .card.ngVault::before{
  content: "";
  position: absolute; inset: 7px;
  border-radius: 14px;
  border: 1px solid var(--vt-line-soft);
  pointer-events: none;
  z-index: 0;
}
:root body.ng-vault .card.ngVault::after{
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
  --rv: radial-gradient(circle, var(--vt-brass-hi) 0 1.5px, var(--vt-brass) 2px 3.2px, var(--vt-brass-lo) 3.4px 4.2px, transparent 4.6px);
  background:
    var(--rv) 10px 10px / 12px 12px no-repeat,
    var(--rv) calc(100% - 10px) 10px / 12px 12px no-repeat,
    var(--rv) 10px calc(100% - 10px) / 12px 12px no-repeat,
    var(--rv) calc(100% - 10px) calc(100% - 10px) / 12px 12px no-repeat;
  opacity: .9;
}
:root body.ng-vault .card.ngVault > *{ position: relative; z-index: 1; }

/* Door states. */
@keyframes vtDoorOpen{
  0%   { box-shadow: inset 0 1px 0 var(--vt-edge-hi), 0 0 0 0 var(--vt-set-glow), 0 24px 60px var(--vt-drop); }
  30%  { box-shadow: inset 0 1px 0 var(--vt-edge-hi), 0 0 0 10px transparent, 0 0 60px var(--vt-set-glow), 0 24px 60px var(--vt-drop); }
  100% { box-shadow: inset 0 1px 0 var(--vt-edge-hi), 0 0 0 0 transparent, 0 0 28px var(--vt-set-glow), 0 24px 60px var(--vt-drop); }
}
@keyframes vtAlarm{
  0%,100% { border-color: var(--vt-line); box-shadow: inset 0 1px 0 var(--vt-edge-hi), 0 24px 60px var(--vt-drop); }
  20%,60% { border-color: var(--vt-alarm); box-shadow: inset 0 0 0 2px var(--vt-alarm), 0 0 40px var(--vt-alarm-glow), 0 24px 60px var(--vt-drop); }
}
:root body.ng-vault .card.ngVault.vtWon{
  border-color: var(--vt-set);
  animation: vtDoorOpen 1.6s ease-out forwards;
}
:root body.ng-vault .card.ngVault.vtAlarm{
  animation: vtAlarm 1.1s ease-in-out 2;
}

/* ------------------------------------------------------------
   HUD — dial, state, attempt LEDs, sound
   ------------------------------------------------------------ */
:root body.ng-vault .row.puzzleRow{
  margin-bottom: 6px;
  gap: 12px;
  flex-wrap: wrap;
}
:root body.ng-vault .vtHud{
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
:root body.ng-vault .vtDial{
  width: 54px; height: 54px;
  flex: 0 0 auto;
  border-radius: 50%;
  background:
    radial-gradient(circle at 35% 30%, var(--vt-steel-3), var(--vt-steel-1) 70%);
  box-shadow:
    inset 0 1px 0 var(--vt-edge-hi),
    inset 0 -2px 4px var(--vt-edge-lo),
    0 0 0 2px var(--vt-brass-lo),
    0 0 0 3px var(--vt-line-soft),
    0 6px 14px var(--vt-drop);
  display: grid; place-items: center;
}
:root body.ng-vault .vtDial svg{
  width: 46px; height: 46px;
  transform: rotate(var(--vt-rot, 0deg));
  transition: transform .9s cubic-bezier(.2,.9,.25,1.05);
  will-change: transform;
}
:root body.ng-vault .vtDial.vtDialSnap svg{ transition: none; }
:root body.ng-vault .vtDial .tick{ stroke: var(--vt-dim); stroke-width: 1.4; stroke-linecap: round; }
:root body.ng-vault .vtDial .tick.major{ stroke: var(--vt-brass); stroke-width: 2.2; }
:root body.ng-vault .vtDial .needle{ fill: var(--vt-brass-hi); stroke: var(--vt-brass-lo); stroke-width: .6; }
:root body.ng-vault .vtDial .hub{ fill: var(--vt-brass); stroke: var(--vt-brass-lo); stroke-width: 1; }

:root body.ng-vault .vtHudText{ display: flex; flex-direction: column; gap: 5px; min-width: 0; }
:root body.ng-vault .vtHudTitle{
  font-family: var(--vt-display);
  font-size: 19px;
  line-height: 1;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--vt-brass-hi);
  text-shadow: 0 1px 0 rgba(0,0,0,.35);
  display: flex; align-items: baseline; gap: 8px;
}
:root body.ng-vault .vtHudState{
  font-family: var(--vt-display);
  font-size: 12px;
  letter-spacing: .14em;
  padding: 3px 8px 2px;
  border-radius: 999px;
  border: 1px solid var(--vt-line);
  color: var(--vt-dim);
  background: var(--vt-steel-0);
  transition: color .3s, border-color .3s, background .3s, box-shadow .3s;
}
:root body.ng-vault .vtHudState[data-state="open"]{
  color: var(--vt-set-ink);
  background: linear-gradient(180deg, var(--vt-set), var(--vt-set-2));
  border-color: var(--vt-set-2);
  box-shadow: 0 0 14px var(--vt-set-glow);
}
:root body.ng-vault .vtHudState[data-state="sealed"]{
  color: #fff;
  background: linear-gradient(180deg, var(--vt-alarm), #9c1e2b);
  border-color: #8a1a27;
}
:root[data-theme="light"] body.ng-vault .vtHudState[data-state="sealed"]{ color: #fff; }

:root body.ng-vault .vtLeds{ display: flex; gap: 6px; align-items: center; }
:root body.ng-vault .vtLeds i{
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--vt-led-off);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.5), 0 1px 0 var(--vt-edge-hi);
  transition: background .25s, box-shadow .25s;
}
:root body.ng-vault .vtLeds i.used{
  background: radial-gradient(circle at 40% 35%, var(--vt-brass-hi), var(--vt-brass) 60%, var(--vt-brass-lo));
  box-shadow: 0 0 8px rgba(217,164,65,.55), inset 0 0 2px rgba(0,0,0,.35);
}
:root body.ng-vault .vtLeds i.win{
  background: radial-gradient(circle at 40% 35%, #b8ffd6, var(--vt-set) 55%, var(--vt-set-2));
  box-shadow: 0 0 10px var(--vt-set-glow), inset 0 0 2px rgba(0,0,0,.35);
}
:root body.ng-vault .vtLeds i.lose{
  background: radial-gradient(circle at 40% 35%, #ffb3ba, var(--vt-alarm) 55%, #8a1a27);
  box-shadow: 0 0 10px var(--vt-alarm-glow), inset 0 0 2px rgba(0,0,0,.35);
}
@keyframes vtLedPop{ 0%{transform:scale(1)} 40%{transform:scale(1.5)} 100%{transform:scale(1)} }
:root body.ng-vault .vtLeds i.pop{ animation: vtLedPop .4s ease; }

:root body.ng-vault .vtSound{
  margin-left: 4px;
  width: 34px; height: 34px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--vt-line);
  background: var(--vt-steel-0);
  color: var(--vt-brass);
  font-size: 15px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  box-shadow: inset 0 1px 0 var(--vt-edge-hi);
}
:root body.ng-vault .vtSound[aria-pressed="false"]{ opacity: .6; }

/* Mode pills → combination length. */
:root body.ng-vault .modeSeg{ gap: 6px; }
:root body.ng-vault .modeSeg .seg{
  font-family: var(--vt-display);
  font-weight: 400;
  letter-spacing: .06em;
  text-transform: uppercase;
  font-size: 13px;
  padding: 7px 13px 6px;
  border: 1px solid var(--vt-line);
  background: var(--vt-steel-0);
  color: var(--vt-dim);
  box-shadow: inset 0 1px 0 var(--vt-edge-hi);
  transition: transform .12s, background .15s, color .15s;
}
:root body.ng-vault .modeSeg .seg:hover{ color: var(--vt-ink); border-color: var(--vt-brass); background: var(--vt-steel-2); }
:root body.ng-vault .modeSeg .seg.on{
  background: linear-gradient(180deg, var(--vt-fill-hi), var(--vt-fill) 55%, var(--vt-fill-lo));
  color: var(--vt-fill-ink);
  border-color: var(--vt-brass-lo);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 0 16px rgba(217,164,65,.35);
}
:root body.ng-vault .card.ngVault .smallrow .mono#modeTag{
  color: var(--vt-dim);
  font-size: 13px;
  letter-spacing: .04em;
}

/* ------------------------------------------------------------
   Gauges (fingerprint cards)
   ------------------------------------------------------------ */
:root body.ng-vault .stats{ gap: 10px; margin: 10px 0 14px; }

:root body.ng-vault .stat[data-card]{
  position: relative;
  border: 1px solid var(--vt-line);
  border-radius: 14px;
  padding: 12px 8px 9px;
  background:
    radial-gradient(90% 60% at 50% 0%, rgba(255,255,255,.06), transparent 70%),
    linear-gradient(180deg, var(--vt-steel-2), var(--vt-steel-0));
  box-shadow:
    inset 0 1px 0 var(--vt-edge-hi),
    inset 0 -2px 0 rgba(0,0,0,.35),
    0 8px 18px var(--vt-drop);
  transition: transform .14s ease, border-color .2s, box-shadow .2s;
  cursor: default;
}
:root body.ng-vault .stat[data-card].fpLocked{ cursor: pointer; }
:root body.ng-vault .stat[data-card].fpLocked:hover{
  transform: translateY(-2px);
  border-color: var(--vt-brass);
}

/* LED in the top-left: red while locked, green once the gauge is live. */
:root body.ng-vault .stat[data-card]::before{
  content: "";
  position: absolute; left: 9px; top: 9px;
  width: 8px; height: 8px; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #b8ffd6, var(--vt-set) 55%, var(--vt-set-2));
  box-shadow: 0 0 8px var(--vt-set-glow);
}
:root body.ng-vault .stat[data-card].fpLocked::before{
  background: radial-gradient(circle at 40% 35%, #ffb3ba, var(--vt-alarm) 55%, #8a1a27);
  box-shadow: 0 0 8px var(--vt-alarm-glow);
}

:root body.ng-vault .stat .k{
  font-family: var(--vt-display);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--vt-dim);
}
:root body.ng-vault .stat .v{
  font-family: var(--vt-display);
  font-size: 26px;
  line-height: 1.05;
  margin-top: 4px;
  color: var(--vt-brass-hi);
  text-shadow: 0 0 calc(14px * var(--vt-glow-scale)) rgba(217,164,65,.45), 0 1px 0 rgba(0,0,0,.4);
  letter-spacing: .02em;
}
:root[data-theme="light"] body.ng-vault .stat .v{ text-shadow: none; }
:root body.ng-vault .stat[data-card="SH"] .v{ letter-spacing: .12em; }
:root body.ng-vault .stat .hint{ color: var(--vt-dim); font-size: 11.5px; margin-top: 5px; }

/* Locked gauge: needle parked, "tap" reads as a prompt not a value. */
:root body.ng-vault .stat.fpLocked .v{
  color: var(--vt-dim);
  text-shadow: none;
  font-size: 15px;
  letter-spacing: .14em;
  text-transform: uppercase;
  padding-top: 6px;
  padding-bottom: 5px;
  display: inline-flex; align-items: center; gap: 6px;
}
:root body.ng-vault .stat.fpLocked .v::before{
  content: "";
  width: 10px; height: 12px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 12'><path d='M2 5V3.5a3 3 0 0 1 6 0V5' fill='none' stroke='black' stroke-width='1.6'/><rect x='1' y='5' width='8' height='6.5' rx='1.2' fill='black'/></svg>") center / contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 12'><path d='M2 5V3.5a3 3 0 0 1 6 0V5' fill='none' stroke='black' stroke-width='1.6'/><rect x='1' y='5' width='8' height='6.5' rx='1.2' fill='black'/></svg>") center / contain no-repeat;
}
@keyframes vtGaugeLive{
  0%   { transform: scale(.96); box-shadow: 0 0 0 0 var(--vt-set-glow), inset 0 1px 0 var(--vt-edge-hi); }
  40%  { transform: scale(1.05); box-shadow: 0 0 0 8px transparent, 0 0 26px var(--vt-set-glow), inset 0 1px 0 var(--vt-edge-hi); }
  100% { transform: scale(1); box-shadow: 0 0 0 0 transparent, 0 8px 18px var(--vt-drop), inset 0 1px 0 var(--vt-edge-hi); }
}
:root body.ng-vault .stat.vtLive{ animation: vtGaugeLive .55s cubic-bezier(.2,.9,.3,1.2); }

/* The little ? help buttons and their popover, in brass. */
:root body.ng-vault .fpHelp{
  top: 7px; right: 7px;
  border-color: var(--vt-line);
  background: var(--vt-steel-0);
  color: var(--vt-brass);
}
:root body.ng-vault .fpHelp:hover{ background: var(--vt-steel-3); border-color: var(--vt-brass); }
:root body.ng-vault .fpPop{
  background: var(--vt-steel-1);
  color: var(--vt-ink);
  border-color: var(--vt-line);
  box-shadow: 0 14px 30px var(--vt-drop);
}
:root body.ng-vault .fpPopTitle{ font-family: var(--vt-display); font-weight: 400; letter-spacing: .06em; color: var(--vt-brass-hi); }

:root body.ng-vault .tip.mono{
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--vt-dim);
  letter-spacing: .02em;
  margin: 0 2px 4px;
}
:root body.ng-vault .msg{
  color: var(--vt-ink);
  font-size: 14px;
  margin: 8px 2px 6px;
  min-height: 20px;
}
:root body.ng-vault .msg:not(:empty)::before{ content: "▸ "; color: var(--vt-brass); }

/* ------------------------------------------------------------
   Tumbler rows (the board)
   ------------------------------------------------------------ */
:root body.ng-vault .board{ gap: 8px; margin-top: 6px; counter-reset: turn; }

:root body.ng-vault .turn{
  position: relative;
  counter-increment: turn;
  border: 1px solid var(--vt-line-soft);
  border-radius: 14px;
  padding: 10px 12px 9px 44px;
  background: linear-gradient(90deg, rgba(0,0,0,.28), transparent 42px), var(--vt-steel-1);
  box-shadow: inset 0 1px 0 var(--vt-edge-hi), inset 0 -1px 0 rgba(0,0,0,.35);
  align-items: center;
}
:root body.ng-vault .turn::before{
  content: counter(turn, decimal-leading-zero);
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 40px;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--vt-display);
  font-size: 15px;
  letter-spacing: .06em;
  color: var(--vt-brass);
  border-right: 1px solid var(--vt-line-soft);
}
:root body.ng-vault .turn:last-child{ border-color: var(--vt-line); }
@keyframes vtRowIn{ from{ opacity:0; transform: translateY(6px) } to{ opacity:1; transform:none } }
:root body.ng-vault .turn.vtNew{ animation: vtRowIn .28s ease-out both; }

/* Tumblers. */
:root body.ng-vault .tiles{ gap: 8px; }
:root body.ng-vault .tile{
  width: 46px; height: 46px;
  border-radius: 12px;
  font-family: var(--vt-display);
  font-weight: 400;
  font-size: 24px;
  line-height: 1;
  color: var(--vt-brass-hi);
  background: linear-gradient(180deg, var(--vt-steel-3), var(--vt-steel-1) 55%, var(--vt-steel-0));
  border: 1px solid rgba(0,0,0,.35);
  box-shadow:
    inset 0 2px 0 var(--vt-edge-hi),
    inset 0 -3px 0 var(--vt-edge-lo),
    0 4px 10px var(--vt-drop);
  text-shadow: 0 1px 0 rgba(0,0,0,.45);
  transition: transform .15s ease;
}
:root[data-theme="light"] body.ng-vault .tile{ color: var(--vt-brass-lo); text-shadow: none; }
:root body.ng-vault .tile.b{ background: linear-gradient(180deg, var(--vt-steel-3), var(--vt-steel-1) 55%, var(--vt-steel-0)); }

/* The site paints .tile.g/.tile.y with !important, so these must too. */
:root body.ng-vault .tile.g{
  background: linear-gradient(180deg, var(--vt-set-hi), var(--vt-set) 40%, var(--vt-set-lo)) !important;
  border-color: var(--vt-set-2) !important;
  color: var(--vt-set-ink);
  text-shadow: 0 1px 0 rgba(255,255,255,.25);
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.35),
    inset 0 -3px 0 rgba(0,0,0,.30),
    0 0 calc(18px * var(--vt-glow-scale)) var(--vt-set-glow),
    0 4px 10px var(--vt-drop);
}
:root body.ng-vault .tile.y{
  background: linear-gradient(180deg, #ffe08a, var(--vt-catch) 40%, var(--vt-catch-2)) !important;
  border-color: var(--vt-catch-2) !important;
  color: var(--vt-catch-ink);
  text-shadow: 0 1px 0 rgba(255,255,255,.3);
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.35),
    inset 0 -3px 0 rgba(0,0,0,.28),
    0 0 calc(14px * var(--vt-glow-scale)) var(--vt-catch-glow),
    0 4px 10px var(--vt-drop);
}

/* Flip faces during the reveal (app.js swaps them for real tiles after). */
:root body.ng-vault .tile.tileFlip{ background: transparent; box-shadow: none; border-color: transparent; }
:root body.ng-vault .tile.tileFlip .tileFlipFront{
  background: linear-gradient(180deg, var(--vt-steel-3), var(--vt-steel-1) 55%, var(--vt-steel-0));
  border: 1px solid rgba(0,0,0,.35);
  box-shadow: inset 0 2px 0 var(--vt-edge-hi), inset 0 -3px 0 var(--vt-edge-lo);
}
:root body.ng-vault .tile.tileFlip .tileFlipFront::after{
  content: "";
  width: 14px; height: 3px; border-radius: 2px;
  background: var(--vt-brass-lo);
  opacity: .8;
}
:root body.ng-vault .tile.tileFlip .tileFlipBack{
  border: 1px solid rgba(0,0,0,.35);
  color: var(--vt-brass-hi);
  background: linear-gradient(180deg, var(--vt-steel-3), var(--vt-steel-1) 55%, var(--vt-steel-0));
}
:root body.ng-vault .tileFlipBack.g{ background: linear-gradient(180deg, var(--vt-set-hi), var(--vt-set) 40%, var(--vt-set-lo)); border-color: var(--vt-set-2); color: var(--vt-set-ink); }
:root body.ng-vault .tileFlipBack.y{ background: linear-gradient(180deg, #ffe08a, var(--vt-catch) 40%, var(--vt-catch-2)); border-color: var(--vt-catch-2); color: var(--vt-catch-ink); }
:root body.ng-vault .tile.tileFlip .tileFlipInner{ transition-duration: 520ms; }

/* Feedback readouts under each row. */
:root body.ng-vault .fp{
  margin-top: 8px;
  gap: 6px;
  justify-content: center;
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .02em;
}
:root body.ng-vault .fp .fpt{
  border: 1px solid var(--vt-line-soft);
  border-radius: 8px;
  padding: 4px 8px;
  background: var(--vt-steel-0);
  color: var(--vt-dim);
  box-shadow: inset 0 1px 0 var(--vt-edge-hi);
}
:root body.ng-vault .fp .ok{
  background: var(--vt-steel-0) !important;
  border-color: var(--vt-set-2) !important;
  color: var(--vt-set);
  box-shadow: inset 0 0 0 1px var(--vt-set-2), inset 0 1px 0 var(--vt-edge-hi);
}
:root[data-theme="light"] body.ng-vault .fp .ok{ color: var(--vt-set-2); }
:root body.ng-vault .fp .high{
  background: var(--vt-steel-0) !important;
  border-color: var(--vt-catch-2) !important;
  color: var(--vt-catch);
}
:root[data-theme="light"] body.ng-vault .fp .high{ color: #8a5f00; }
:root body.ng-vault .fp .low{ background: var(--vt-steel-0); border-color: var(--vt-cold); color: var(--vt-cold); }
:root body.ng-vault .fp .bad{ background: var(--vt-steel-0); border-color: var(--vt-alarm); color: var(--vt-alarm); }

/* Row that opened the door. */
@keyframes vtRowOpen{
  0%   { box-shadow: inset 0 0 0 1px var(--vt-set), 0 0 0 0 var(--vt-set-glow); }
  50%  { box-shadow: inset 0 0 0 1px var(--vt-set), 0 0 0 10px transparent, 0 0 30px var(--vt-set-glow); }
  100% { box-shadow: inset 0 0 0 1px var(--vt-set), 0 0 0 0 transparent, 0 0 18px var(--vt-set-glow); }
}
:root body.ng-vault .turn.vtOpen{
  border-color: var(--vt-set-2);
  animation: vtRowOpen 1.2s ease-out forwards;
}

/* ------------------------------------------------------------
   Dial input + keypad
   ------------------------------------------------------------ */
:root body.ng-vault .inputRow{ margin-top: 10px; gap: 8px; flex-wrap: nowrap; }
/* The input's intrinsic width (size=20 at a wide letter-spacing) must never
   push the button out of the card: let it shrink, keep the button whole. */
:root body.ng-vault .card.ngVault .inputRow input#guess{ flex: 1 1 auto; min-width: 0; width: auto; }
:root body.ng-vault .card.ngVault .inputRow button#submit{ flex: 0 0 auto; white-space: nowrap; }
:root body.ng-vault .card.ngVault input#guess{
  font-family: var(--vt-display);
  font-size: 22px;
  letter-spacing: .32em;
  text-align: center;
  color: var(--vt-brass-hi);
  background: var(--vt-steel-0);
  border: 1px solid var(--vt-line);
  border-radius: 14px;
  padding: 10px 12px;
  box-shadow: inset 0 3px 8px rgba(0,0,0,.45), inset 0 -1px 0 var(--vt-edge-hi);
  caret-color: var(--vt-brass);
}
:root[data-theme="light"] body.ng-vault .card.ngVault input#guess{
  color: var(--vt-brass-lo);
  box-shadow: inset 0 2px 6px rgba(20,16,8,.14);
}
:root body.ng-vault .card.ngVault input#guess::placeholder{
  font-family: var(--font-ui);
  font-size: 14px;
  letter-spacing: .02em;
  color: var(--vt-dim);
  opacity: .9;
}
:root body.ng-vault .card.ngVault input#guess:focus{
  outline: none;
  border-color: var(--vt-brass);
  box-shadow: inset 0 3px 8px rgba(0,0,0,.45), 0 0 0 3px rgba(217,164,65,.22);
}
:root body.ng-vault .card.ngVault button#submit{
  font-family: var(--vt-display);
  font-weight: 400;
  font-size: 16px;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 10px 18px;
  border-radius: 14px;
  color: var(--vt-fill-ink);
  background: linear-gradient(180deg, var(--vt-fill-hi), var(--vt-fill) 55%, var(--vt-fill-lo));
  border: 1px solid var(--vt-brass-lo);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.4), inset 0 -2px 0 rgba(0,0,0,.25), 0 6px 14px var(--vt-drop);
  transition: transform .1s, filter .15s;
}
:root body.ng-vault .card.ngVault button#submit:hover{ filter: brightness(1.06); }
:root body.ng-vault .card.ngVault button#submit:active{ transform: translateY(2px); box-shadow: inset 0 1px 0 rgba(255,255,255,.4), 0 2px 6px var(--vt-drop); }

:root body.ng-vault .pad{ margin-top: 10px; gap: 8px; }
:root body.ng-vault .card.ngVault .padbtn{
  font-family: var(--vt-display);
  font-weight: 400;
  font-size: 22px;
  padding: 11px 0 9px;
  border-radius: 12px;
  color: var(--vt-brass-hi);
  background: linear-gradient(180deg, var(--vt-steel-3), var(--vt-steel-1) 55%, var(--vt-steel-0));
  border: 1px solid rgba(0,0,0,.35);
  box-shadow: inset 0 2px 0 var(--vt-edge-hi), inset 0 -3px 0 var(--vt-edge-lo), 0 4px 10px var(--vt-drop);
  text-shadow: 0 1px 0 rgba(0,0,0,.45);
  transition: transform .07s ease, box-shadow .07s ease;
}
:root[data-theme="light"] body.ng-vault .card.ngVault .padbtn{ color: var(--vt-brass-lo); text-shadow: none; }
:root body.ng-vault .card.ngVault .padbtn:active,
:root body.ng-vault .card.ngVault .padbtn.vtDown{
  transform: translateY(3px);
  background: linear-gradient(180deg, var(--vt-steel-1), var(--vt-steel-0));
  box-shadow: inset 0 2px 4px rgba(0,0,0,.5), 0 0 0 var(--vt-drop);
}
:root body.ng-vault .card.ngVault .padbtn[data-k="go"]{
  color: var(--vt-fill-ink);
  background: linear-gradient(180deg, var(--vt-fill-hi), var(--vt-fill) 55%, var(--vt-fill-lo));
  border-color: var(--vt-brass-lo);
  text-shadow: none;
}
:root body.ng-vault .card.ngVault .padbtn[data-k="bk"]{ color: var(--vt-dim); font-size: 19px; }

:root body.ng-vault .actions{ margin-top: 12px; }
:root body.ng-vault .card.ngVault .actions button.ghost{
  font-family: var(--vt-display);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: .08em;
  text-transform: uppercase;
  border: 1px solid var(--vt-line);
  background: var(--vt-steel-0);
  color: var(--vt-dim);
  border-radius: 12px;
  padding: 9px 14px 8px;
  box-shadow: inset 0 1px 0 var(--vt-edge-hi);
}
:root body.ng-vault .card.ngVault .actions button.ghost:not(:disabled):hover{ color: var(--vt-brass-hi); border-color: var(--vt-brass); }
:root body.ng-vault .card.ngVault .actions button#shareBtn:not(:disabled){
  color: var(--vt-fill-ink);
  background: linear-gradient(180deg, var(--vt-fill-hi), var(--vt-fill) 55%, var(--vt-fill-lo));
  border-color: var(--vt-brass-lo);
}

:root body.ng-vault .card.ngVault .smallrow .label{ color: var(--vt-dim); font-size: 13px; letter-spacing: .06em; text-transform: uppercase; }
:root body.ng-vault .card.ngVault .smallrow .mono[data-stat-value]{ font-family: var(--vt-display); color: var(--vt-brass-hi); letter-spacing: .06em; }
:root[data-theme="light"] body.ng-vault .card.ngVault .smallrow .mono[data-stat-value]{ color: var(--vt-brass-lo); }

/* ------------------------------------------------------------
   Phones
   ------------------------------------------------------------ */
@media (max-width: 520px){
  :root body.ng-vault .card.ngVault{ padding: 14px 12px 12px; border-radius: 16px; }
  :root body.ng-vault .vtDial{ width: 46px; height: 46px; }
  :root body.ng-vault .vtDial svg{ width: 40px; height: 40px; }
  :root body.ng-vault .vtHudTitle{ font-size: 17px; }
  :root body.ng-vault .modeSeg .seg{ padding: 6px 10px 5px; font-size: 12px; min-width: 0; }
  :root body.ng-vault .stat[data-card]{ padding: 10px 6px 8px; }
  :root body.ng-vault .stat .v{ font-size: 22px; }
  :root body.ng-vault .stat.fpLocked .v{ font-size: 13px; }
  :root body.ng-vault .turn{ padding: 8px 8px 8px 36px; }
  :root body.ng-vault .turn::before{ width: 32px; font-size: 13px; }
  :root body.ng-vault .tile{ width: 40px; height: 40px; font-size: 21px; border-radius: 10px; }
  :root body.ng-vault .tiles{ gap: 6px; }
  :root body.ng-vault .fp .fpt{ padding: 3px 6px; font-size: 11.5px; }
  :root body.ng-vault .card.ngVault input#guess{ font-size: 19px; letter-spacing: .24em; }
}

@media (prefers-reduced-motion: reduce){
  :root body.ng-vault .vtDial svg{ transition: none; }
  :root body.ng-vault .card.ngVault.vtWon,
  :root body.ng-vault .card.ngVault.vtAlarm,
  :root body.ng-vault .turn.vtOpen,
  :root body.ng-vault .stat.vtLive,
  :root body.ng-vault .vtLeds i.pop,
  :root body.ng-vault .turn.vtNew{ animation: none; }
}

/* ------------------------------------------------------------
   Next attempt — a live tumbler row that mirrors what is being typed,
   so the board is never empty and the guess is seen before it is turned.
   ------------------------------------------------------------ */
:root body.ng-vault .turn.vtNext{
  border-style: dashed;
  border-color: var(--vt-line);
  background: linear-gradient(90deg, rgba(0,0,0,.18), transparent 42px), transparent;
  box-shadow: none;
  counter-increment: none;
}
:root body.ng-vault .turn.vtNext::before{
  content: attr(data-n);
  color: var(--vt-dim);
}
:root body.ng-vault .turn.vtNext .tile{
  color: var(--vt-dim);
  background: transparent;
  border: 1px dashed var(--vt-line);
  box-shadow: none;
  text-shadow: none;
}
:root body.ng-vault .turn.vtNext .tile.has{
  color: var(--vt-brass-hi);
  border-style: solid;
  background: linear-gradient(180deg, var(--vt-steel-3), var(--vt-steel-1) 55%, var(--vt-steel-0));
  box-shadow: inset 0 2px 0 var(--vt-edge-hi), inset 0 -3px 0 var(--vt-edge-lo), 0 4px 10px var(--vt-drop);
}
:root[data-theme="light"] body.ng-vault .turn.vtNext .tile.has{ color: var(--vt-brass-lo); }
@keyframes vtTumblerIn{ 0%{ transform: translateY(-6px) scale(.9); } 60%{ transform: translateY(1px) scale(1.04); } 100%{ transform: none; } }
:root body.ng-vault .turn.vtNext .tile.has.in{ animation: vtTumblerIn .18s ease-out; }
:root body.ng-vault .turn.vtNext .vtNextLabel{
  margin-top: 8px;
  font-family: var(--vt-display);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--vt-dim);
}

/* On phones the input row goes sticky with a flat card background; give it
   the door's steel instead so it does not read as a grey band. */
@media (max-width: 720px){
  :root body.ng-vault .card.ngVault .inputRow{
    background: linear-gradient(180deg, transparent, var(--vt-steel-1) 22%);
    padding: 12px 0 6px;
    gap: 8px;
  }
}

/* ------------------------------------------------------------
   Phones: the keypad and the dial input become one sticky cluster at the
   bottom, the rows tighten, and the typed-preview row goes (the input shows
   the digits there). With the old layout each guess pushed the result off
   the top and the player scrolled up to read it, then back down to type.
   720px, not 520: large phones report a wider viewport and were getting
   the desktop row, with the Guess button pushed outside the card.
   ------------------------------------------------------------ */
@media (max-width: 720px){
  :root body.ng-vault .turn.vtNext{ display: none; }

  :root body.ng-vault .turn{ padding: 7px 8px 7px 34px; border-radius: 12px; }
  :root body.ng-vault .tile{ width: 38px; height: 38px; font-size: 20px; }
  :root body.ng-vault .fp{ margin-top: 6px; gap: 4px; }
  :root body.ng-vault .fp .fpt{ padding: 2px 5px; font-size: 11px; border-radius: 6px; }
  :root body.ng-vault .board{ gap: 6px; }

  :root body.ng-vault .card.ngVault .inputRow{
    position: sticky;
    bottom: var(--vt-pad-h, 104px);
    z-index: 50;
    flex-direction: row;
    align-items: stretch;
    gap: 8px;
    margin-top: 8px;
    padding: 8px 0 6px;
    background: linear-gradient(180deg, transparent, var(--vt-steel-1) 30%);
  }
  :root body.ng-vault .card.ngVault .inputRow input#guess{ width: auto; flex: 1 1 auto; min-width: 0; padding: 8px 10px; }
  :root body.ng-vault .card.ngVault .inputRow button#submit{ width: auto; flex: 0 0 auto; padding: 8px 14px; font-size: 14px; }

  :root body.ng-vault .card.ngVault .pad{
    position: sticky;
    bottom: 0;
    z-index: 50;
    margin-top: 0;
    padding: 4px 0 8px;
    background: var(--vt-steel-1);
    box-shadow: 0 -8px 12px -8px rgba(0,0,0,.5);
  }
  :root body.ng-vault .card.ngVault .padbtn{ padding: 9px 0 8px; font-size: 20px; }
}

/* ---------- the post-win dialog, in brass ---------- */
:root body.ng-vault .gvWin{ background: linear-gradient(180deg, var(--vt-steel-2, #1d2430), var(--vt-steel-0, #0a0c10)); color: var(--vt-display, #f3efe6); border: 1px solid var(--vt-line); box-shadow: inset 0 1px 0 var(--vt-edge-hi), 0 30px 70px rgba(0,0,0,.5); }
:root body.ng-vault .gvWin h2{ font-family: 'Lilita One', 'Outfit', system-ui, sans-serif; font-weight: 400; font-size: 26px; letter-spacing: .02em; color: var(--vt-brass-hi); }
:root body.ng-vault .gvWin .gvWinSub, :root body.ng-vault .gvWinNextDesc, :root body.ng-vault .gvWin .gvWinSmall, :root body.ng-vault .gvWin .gvWinX{ color: var(--vt-dim); opacity: 1; }
:root body.ng-vault .gvWinNext, :root body.ng-vault .gvWinRow .gvWinBtn{ background: var(--vt-steel-0, #0a0c10); border-color: var(--vt-line); color: var(--vt-display, #f3efe6); box-shadow: inset 0 1px 0 var(--vt-edge-hi); }
:root body.ng-vault .gvWinNext:hover, :root body.ng-vault .gvWinRow .gvWinBtn:hover{ border-color: var(--vt-brass); filter: none; }
:root body.ng-vault .gvWinNextName{ font-family: 'Lilita One', 'Outfit', system-ui, sans-serif; font-weight: 400; letter-spacing: .03em; }
:root body.ng-vault .gvWinNextArr{ color: var(--vt-brass-hi); opacity: 1; }
:root body.ng-vault .gvWinRow .gvWinBtn.primary{ background: linear-gradient(180deg, var(--vt-brass-hi), var(--vt-brass)); color: #1a1712; border-color: var(--vt-brass-lo); }
