/* Offer Radar — the design system. Every colour, size, radius, shadow and timing on every page is a value
   here, so a tweak is one edit (Colin, 2026-09-27: "I might want to tweak colors or components in the
   future"). Decisions behind it: docs/ux/direction-decisions.md.

   Colour rule, enforced by the components below:
     blue   = interactive, focus, information, glow
     lime   = a live 0% offer, or the $1 trial (the one primary action) — nothing else
     coral  = ended / negative / not met · violet = personal-card offers · amber = dated, stale, soon
     green  = a requirement you clear, a healthy reading. Status only: a 0% offer is always lime
     kinds  = six hues for what a rule is about (score, time, money, place, ties, paper), on icon tiles
              only, so a list of requirements scans by kind. Category, never status (added 2026-09-28,
              Colin: "wouldn't hurt to add more color")

   Two layers, so an unrebuilt page can't half-change:
     1. tokens and a few global fixes (focus rings, reduced motion) apply everywhere, now
     2. components apply inside <body class="v2">; a page opts in when it is rebuilt              */
:root{
  /* canvas */
  --bg:#030a1a; --bg-2:#071230; --bg-3:#0b1a40;
  --surface:rgba(255,255,255,.035); --surface-2:rgba(255,255,255,.06);
  --line:rgba(150,180,255,.10); --line-2:rgba(150,180,255,.18); --line-3:rgba(150,180,255,.30);
  /* ink. --ink-3 was #6b7797 (4.4:1 on --bg, 3.4:1 on lock cards); #8591ae clears AA on every surface.
     --ink-4 is the old --ink-3, for hairlines, glyphs and disabled things, never for text. */
  --ink:#f2f4ff; --ink-2:#aeb8d6; --ink-3:#8591ae; --ink-4:#4d5875;
  /* signal */
  --blue:#2e72ff; --blue-2:#0455ff; --blue-deep:#0340cc; --blue-glow:rgba(4,85,255,.55);
  --link:#6b9bff;            /* text links: 7.3:1 on --bg; --blue stays for fills, borders, focus */
  --lime:#c1ff71; --lime-2:#96d94e; --lime-hi:#d6ff96; --on-lime:#04122b;
  --coral:#ff6a4d; --sand:#dfe6ff; --amber:#ffb84d;
  --violet:#b9a7ff;          /* personal-card offers: a secondary note beside lime, never lime itself */
  --ok:#3ee0a4;              /* cleared, healthy: bluer than lime so the two never read as one */
  --k-score:#4cc9f0; --k-time:#8ea2ff; --k-money:#f5c95c; --k-place:#d08cff; --k-tie:#ff8fb8; --k-paper:#aab6d3;

  /* type: nine text steps, four figure steps, nothing smaller than 11px */
  --sans:"Figtree",ui-sans-serif,system-ui,sans-serif;
  --serif:"Instrument Serif",Georgia,serif;
  --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,monospace;
  --t-display:clamp(46px,6.6vw,96px);  /* hero only · lh .94 */
  --t-h1:clamp(36px,5vw,64px);         /* section headline · lh 1 */
  --t-h2:clamp(26px,2.8vw,36px);       /* feature headline · lh 1.1 */
  --t-h3:21px;                         /* card, tile, drawer title · lh 1.2 */
  --t-lede:clamp(17px,1.45vw,20px);    /* lh 1.5 */
  --t-body:16px;                       /* lh 1.55 */
  --t-ui:14px;                         /* tables, controls · lh 1.45 */
  --t-small:13px;                      /* meta lines · lh 1.45 */
  --t-label:11px;                      /* mono, caps, +0.1em — the floor */
  --t-fig-xl:clamp(52px,6vw,84px); --t-fig-l:40px; --t-fig:28px; --t-fig-s:20px;
  --track-d:-.046em; --track-h:-.04em;  /* display tracking, tuned for Figtree */

  /* space (4-based), radius, elevation */
  --s-1:4px; --s-2:8px; --s-3:12px; --s-4:16px; --s-5:20px; --s-6:24px; --s-7:32px; --s-8:40px; --s-9:56px; --s-10:72px; --s-11:96px; --s-12:128px;
  --gutter:clamp(16px,4vw,40px); --maxw:1200px; --section:clamp(88px,10vw,144px);
  --r-xs:6px; --r-s:10px; --r-m:14px; --r:20px; --r-pill:999px;
  /* backdrop blur: floating popovers, and the large glass panels (audit X28) */
  --blur-float:18px; --blur-glass:22px;
  --e-1:inset 0 1px 0 rgba(255,255,255,.07),0 0 0 1px var(--line);
  --e-2:inset 0 1px 0 rgba(255,255,255,.18),0 24px 60px -28px rgba(0,0,0,.75);
  --e-3:inset 0 1px 0 rgba(255,255,255,.16),0 40px 110px -30px rgba(0,0,0,.92);

  /* motion: exits faster than entrances; travel eases both ways; only transform and opacity move */
  --d-1:140ms; --d-2:240ms; --d-3:560ms; --d-4:1100ms;
  --ease:cubic-bezier(.22,1,.36,1); --ease-in:cubic-bezier(.64,0,.78,0); --ease-io:cubic-bezier(.65,0,.35,1);
}

/* ---------- global, every page: focus you can see, motion you can switch off ---------- */
:focus-visible{outline:2px solid var(--link);outline-offset:2px}
:focus:not(:focus-visible){outline:none}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:1ms!important;animation-iteration-count:1!important;transition-duration:150ms!important;scroll-behavior:auto!important}
}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.tnum{font-variant-numeric:tabular-nums}

/* liquid glass: floating surfaces only (nav, drawer, filters, tiles, tooltips). Never on long lists. */
.glass{position:relative;background:linear-gradient(160deg,rgba(255,255,255,.07),rgba(255,255,255,.02) 40%,rgba(4,85,255,.07));backdrop-filter:blur(var(--blur-glass)) saturate(1.5);-webkit-backdrop-filter:blur(var(--blur-glass)) saturate(1.5);border:1px solid transparent;background-clip:padding-box;box-shadow:inset 0 1px 0 rgba(255,255,255,.22),inset 0 -1px 0 rgba(255,255,255,.04),0 30px 80px -30px rgba(0,0,0,.7)}
.glass::before{content:"";position:absolute;inset:-1px;border-radius:inherit;padding:1px;background:linear-gradient(150deg,rgba(255,255,255,.45),rgba(255,255,255,.08) 30%,rgba(46,114,255,.35) 70%,rgba(255,255,255,.18));-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;pointer-events:none}
.glass::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;background:radial-gradient(120% 60% at 15% -10%,rgba(255,255,255,.14),transparent 55%)}
.glass>*{position:relative;z-index:1}

/* shared primitives kept for pages not yet rebuilt */
.zero-pill{display:inline-flex;align-items:center;gap:6px;font-family:var(--mono);font-size:var(--t-small);color:var(--on-lime);background:linear-gradient(180deg,var(--lime-hi),var(--lime));padding:var(--s-1) var(--s-2);border-radius:var(--r-xs);font-weight:500;white-space:nowrap;box-shadow:inset 0 1px 0 rgba(255,255,255,.5)}
.mono-label{font-family:var(--mono);font-size:var(--t-label);letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.btn-blue{background:linear-gradient(180deg,#2a6af5,var(--blue-deep));color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,.3),0 10px 30px -12px var(--blue-glow)}   /* white on it clears 4.5:1 top to bottom */
.btn-lime,.btn-trial{background:linear-gradient(180deg,var(--lime-hi),var(--lime) 56%,#b2f25a);color:var(--on-lime);box-shadow:inset 0 1px 0 rgba(255,255,255,.65),0 12px 32px -14px rgba(193,255,113,.7)}

/* ---------- account header (every surface; account.js renders it) ----------
   "Start for $1" is the trial, so it is lime (decision 6); the trial countdown is status, not an action. */
.acct-wrap{display:flex;align-items:center;gap:10px}
.acct-signin{font-size:var(--t-ui);font-weight:500;color:var(--ink-2);text-decoration:none;padding:var(--s-2) 10px;border-radius:var(--r-pill);transition:color var(--d-1),background-color var(--d-1)}
.acct-signin:hover{color:var(--ink);background:rgba(255,255,255,.06)}
.acct-cta{display:inline-flex;align-items:center;height:36px;padding:0 var(--s-4);border-radius:var(--r-pill);font-size:var(--t-ui);font-weight:600;color:var(--on-lime);text-decoration:none;background:linear-gradient(180deg,var(--lime-hi),var(--lime) 56%,#b2f25a);box-shadow:inset 0 1px 0 rgba(255,255,255,.65),0 10px 26px -12px rgba(193,255,113,.7);white-space:nowrap;transition:transform var(--d-2) var(--ease),box-shadow var(--d-2) var(--ease)}
.acct-cta:hover{transform:translateY(-1px);box-shadow:inset 0 1px 0 rgba(255,255,255,.75),0 16px 36px -12px rgba(193,255,113,.75)}
.acct-trial{display:inline-flex;align-items:center;gap:var(--s-2);height:32px;padding:0 13px;border-radius:var(--r-pill);font-family:var(--mono);font-size:var(--t-label);letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2);text-decoration:none;background:rgba(255,255,255,.05);box-shadow:inset 0 0 0 1px var(--line-2);white-space:nowrap}
.acct-trial .ds{display:none}
/* on a phone the countdown is short, or the header outgrows the screen and the whole page scrolls sideways (2026-09-29) */
@media(max-width:640px){.acct-trial{padding:0 10px}.acct-trial .dl{display:none}.acct-trial .ds{display:inline;text-transform:none;letter-spacing:0}}
.acct-trial::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--amber)}
/* Flight Deck, one click from anywhere in Radar (the mirror of Flight Deck's "Offer Radar" button) */
.acct-deck{display:inline-flex;align-items:center;gap:var(--s-2);height:36px;padding:0 14px 0 var(--s-2);border-radius:var(--r-pill);color:var(--ink-2);font-size:var(--t-ui);font-weight:500;text-decoration:none;box-shadow:inset 0 0 0 1px var(--line-2);transition:color var(--d-1),box-shadow var(--d-1),background-color var(--d-1);white-space:nowrap}
.acct-deck:hover{color:var(--ink);box-shadow:inset 0 0 0 1px var(--line-3);background:rgba(255,255,255,.04)}
.acct-deck .mark{width:22px;height:22px}
@media(max-width:640px){.acct-deck{padding:0 7px}.acct-deck .t{display:none}}
.acct{position:relative}
.acct-btn{width:36px;height:36px;border-radius:50%;border:1px solid var(--line-2);background:rgba(255,255,255,.06);cursor:pointer;display:grid;place-items:center;padding:0;transition:border-color var(--d-1),background-color var(--d-1)}
.acct-btn:hover{border-color:var(--blue);background:rgba(46,114,255,.14)}
.acct-av{font-family:var(--sans);font-size:var(--t-small);font-weight:600;letter-spacing:.02em;color:var(--ink)}
.acct-menu{position:absolute;right:0;top:calc(100% + 10px);min-width:232px;padding:6px;border-radius:var(--r-m);z-index:60;background:var(--bg-2);border:1px solid var(--line-2);box-shadow:var(--e-3)}
.acct-head{padding:10px var(--s-3) var(--s-3);border-bottom:1px solid var(--line);margin-bottom:6px}
.acct-head b{display:block;font-weight:500;font-size:var(--t-ui);color:var(--ink)}
.acct-head span{display:block;font-family:var(--mono);font-size:var(--t-label);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
.acct-menu a{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px var(--s-3);border-radius:9px;font-size:var(--t-ui);color:var(--ink-2);text-decoration:none}
.acct-menu a:hover{background:rgba(46,114,255,.14);color:var(--ink)}
.acct-menu a i{font-style:normal;font-family:var(--mono);font-size:var(--t-label);color:var(--ink-3)}
.acct-sep{height:1px;background:var(--line);margin:6px var(--s-2)}
/* the footer every Radar page shares (landing has its own): the lockup and what we are, then the places (audit X35) */
.v2 footer.ft{box-shadow:inset 0 1px 0 var(--line);padding:var(--s-8) 0 120px}
.v2 footer.ft .fwrap{max-width:1320px;margin:0 auto;padding:0 var(--gutter,var(--s-6));display:grid;grid-template-columns:1.3fr 1fr 1fr;gap:28px}
.v2 footer.ft p{margin:14px 0 0;color:var(--ink-3);font-size:var(--t-small);line-height:1.6;max-width:46ch}
.v2 footer.ft .fh{display:block;margin:0 0 var(--s-3);font:500 var(--t-label)/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.v2 footer.ft a.l{display:block;color:var(--ink-2);font-size:var(--t-ui);padding:5px 0}.v2 footer.ft a.l:hover{color:var(--ink)}
@media (pointer:coarse){.v2 footer.ft a.l{padding:11px 0}}
@media(max-width:760px){.v2 footer.ft .fwrap{grid-template-columns:1fr 1fr}.v2 footer.ft .fwrap>div:first-child{grid-column:1/-1}}
/* for the eyes of a screen reader only: a page's heading when the page shows it as a tab */
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
/* UI.say's toast: what just happened, for a moment, above everything */
.toast{position:fixed;left:50%;bottom:28px;z-index:90;transform:translate(-50%,12px);opacity:0;pointer-events:none;padding:11px 18px;border-radius:var(--r-pill);background:var(--bg-3);box-shadow:var(--e-3),inset 0 0 0 1px rgba(62,224,164,.45);color:var(--ink);font-size:var(--t-ui);font-weight:550;transition:opacity var(--d-2) var(--ease),transform var(--d-2) var(--ease)}
.toast::before{content:"✓";margin-right:var(--s-2);color:var(--ok)}
.toast.on{opacity:1;transform:translate(-50%,0)}
@media(max-width:760px){.toast{bottom:92px}}
@media (prefers-reduced-motion:reduce){.toast{transition:none}}
/* the phone menu (account.js navHtml): shown only where the page hides its own links */
.acct-nav{position:relative;display:none}
.acct-nav-btn{width:36px;height:36px;border-radius:50%;border:1px solid var(--line-2);background:rgba(255,255,255,.06);color:var(--ink-2);display:grid;place-items:center;padding:0;cursor:pointer}
.acct-nav-btn:hover,.acct-nav-btn[aria-expanded=true]{color:var(--ink);border-color:var(--line-3);background:rgba(255,255,255,.1)}
.acct-nav-list{position:absolute;right:0;top:calc(100% + 10px);min-width:208px;padding:6px;border-radius:var(--r-m);z-index:60;background:var(--bg-2);border:1px solid var(--line-2);box-shadow:var(--e-3)}
.acct-nav-list a{display:block;padding:11px var(--s-3);border-radius:9px;font-size:var(--t-body);color:var(--ink-2);text-decoration:none}
.acct-nav-list a:hover,.acct-nav-list a:focus-visible{background:rgba(46,114,255,.14);color:var(--ink)}
@media(max-width:640px){.acct-nav{display:block}}
@media(max-width:860px){.acct-wrap.nav-860 .acct-nav{display:block}}
@media(max-width:640px){.acct-cta{padding:0 var(--s-3)}.acct-signin{display:none}}
/* save control, used on bank rows and the bank page — saved is a state, so blue, not lime */
.savebtn{display:inline-flex;align-items:center;gap:7px;height:32px;padding:0 var(--s-3);border-radius:var(--r-pill);border:1px solid var(--line-2);background:rgba(255,255,255,.05);color:var(--ink-2);font-size:var(--t-small);font-weight:500;cursor:pointer;transition:border-color var(--d-1),color var(--d-1),background-color var(--d-1)}
.savebtn:hover{border-color:var(--blue);color:var(--ink);background:rgba(46,114,255,.12)}
.savebtn.on{border-color:rgba(107,155,255,.55);color:var(--ink);background:rgba(46,114,255,.16)}
.savebtn.locked{opacity:.75}

/* =====================================================================================================
   Components — inside body.v2 only
   ===================================================================================================== */
.v2{background:var(--bg);color:var(--ink);font:400 var(--t-body)/1.55 var(--sans);letter-spacing:-.006em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
.v2 ::selection{background:var(--blue);color:#fff}
.v2 [hidden]{display:none!important}   /* a component's display rule must never un-hide it */
.v2 .label{font:500 var(--t-label)/1.2 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.v2 .serif{font-family:var(--serif);font-style:italic;font-weight:400;letter-spacing:-.01em}
.v2 a.link,.v2 .prose a{color:var(--link)}

/* film grain: removes banding in the navy gradients; reads as material, not noise */
.v2.grain::after{content:"";position:fixed;inset:-50%;z-index:100;pointer-events:none;opacity:.055;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .9 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}

/* buttons: one rule
     .btn-trial  lime · the $1 trial, and nothing else
     .btn-blue   blue · every other purchase or commit (Flight School, sign in, save)
     .btn-ghost  outline · navigation ("Open the map", "Full profile")
     .btn-quiet  text · tertiary                                                          */
.v2 .btn{--h:44px;display:inline-flex;align-items:center;justify-content:center;gap:10px;height:var(--h);padding:0 calc(var(--h)*.42);border-radius:var(--r-pill);border:0;
  font:550 var(--t-body)/1 var(--sans);letter-spacing:-.01em;white-space:nowrap;cursor:pointer;text-decoration:none;position:relative;isolation:isolate;color:var(--ink);
  transition:transform var(--d-2) var(--ease),box-shadow var(--d-2) var(--ease),background-color var(--d-1),color var(--d-1)}
.v2 .btn-s{--h:36px;font-size:var(--t-ui)}.v2 .btn-l{--h:54px;font-size:var(--t-body)}
.v2 .btn-trial,.v2 .btn-lime{color:var(--on-lime)}.v2 .btn-blue{color:#fff}   /* .v2 .btn sets ink; the filled buttons need their own */
.v2 .btn:active{transform:scale(.975);transition-duration:80ms}
.v2 .btn[disabled],.v2 .btn[aria-disabled=true]{opacity:.5;cursor:default;transform:none}
.v2 .btn .arr{width:17px;height:17px;transition:transform var(--d-2) var(--ease)}
.v2 .btn:hover .arr{transform:translateX(3px)}
.v2 .btn-trial:hover{transform:translateY(-1px);box-shadow:inset 0 1px 0 rgba(255,255,255,.75),0 18px 44px -12px rgba(193,255,113,.75)}
.v2 .btn-blue:hover{transform:translateY(-1px);box-shadow:inset 0 1px 0 rgba(255,255,255,.4),0 18px 44px -12px var(--blue-glow)}
.v2 .btn-ghost{background:rgba(255,255,255,.05);box-shadow:inset 0 0 0 1px var(--line-2),inset 0 1px 0 rgba(255,255,255,.1)}
.v2 .btn-ghost:hover{background:rgba(255,255,255,.09);box-shadow:inset 0 0 0 1px var(--line-3),inset 0 1px 0 rgba(255,255,255,.14)}
.v2 .btn-quiet{background:none;color:var(--ink-2);padding:0 10px}.v2 .btn-quiet:hover{color:var(--ink)}
.v2 .btn.loading{color:transparent;pointer-events:none}
.v2 .btn.loading::after{content:"";position:absolute;inset:0;margin:auto;width:18px;height:18px;border-radius:50%;color:var(--ink);
  background:conic-gradient(from 0deg,transparent 0 250deg,currentColor);-webkit-mask:radial-gradient(circle,transparent 55%,#000 57%);mask:radial-gradient(circle,transparent 55%,#000 57%);animation:v2-spin .8s linear infinite}
.v2 .btn-trial.loading::after{color:var(--on-lime)}.v2 .btn-blue.loading::after{color:#fff}
@keyframes v2-spin{to{transform:rotate(360deg)}}
/* on a touch screen every control's touch area is at least 44 px, with no change to how it looks: an invisible
   ::after reaches past the edges (audit B19, D21). Loading buttons draw their spinner on ::after and can't be tapped. */
@media (pointer:coarse){.v2 .btn-s,.acct-btn,.acct-nav-btn,.acct-cta,.acct-deck,.acct-trial,.v2 .seg>a,.v2 .seg>button,.v2 .lockup{position:relative}.v2 .btn-s::after,.acct-btn::after,.acct-nav-btn::after,.acct-cta::after,.acct-deck::after,.acct-trial::after,.v2 .seg>a::after,.v2 .seg>button::after,.v2 .lockup::after{content:"";position:absolute;left:50%;top:50%;width:max(100%,44px);height:max(100%,44px);transform:translate(-50%,-50%)}}

/* segmented tabs: a place you are, never an action you take */
.v2 .seg{position:relative;display:inline-flex;padding:var(--s-1);border-radius:var(--r-pill);background:rgba(255,255,255,.04);box-shadow:inset 0 0 0 1px var(--line)}
.v2 .seg>button,.v2 .seg>a{position:relative;z-index:1;display:inline-flex;align-items:center;height:34px;padding:0 var(--s-4);border:0;background:none;border-radius:var(--r-pill);font:500 var(--t-ui)/1 var(--sans);color:var(--ink-3);cursor:pointer;text-decoration:none;transition:color var(--d-2)}
.v2 .seg>button:hover,.v2 .seg>a:hover{color:var(--ink-2)}
.v2 .seg>[aria-selected=true],.v2 .seg>[aria-current=page]{color:var(--ink)}
.v2 .seg .ind{position:absolute;z-index:0;top:4px;bottom:4px;border-radius:var(--r-pill);background:rgba(46,114,255,.16);box-shadow:inset 0 0 0 1px rgba(107,155,255,.35),inset 0 1px 0 rgba(255,255,255,.12);transition:left var(--d-3) var(--ease),width var(--d-3) var(--ease)}

/* pills: what a thing is */
.v2 .zero{display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 9px;border-radius:var(--r-xs);font:500 var(--t-small)/1 var(--mono);letter-spacing:.01em;white-space:nowrap;color:var(--on-lime);background:linear-gradient(180deg,var(--lime-hi),var(--lime));box-shadow:inset 0 1px 0 rgba(255,255,255,.5)}
.v2 .pill{display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 9px;border-radius:var(--r-xs);font:500 var(--t-label)/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;white-space:nowrap;color:var(--ink-2);box-shadow:inset 0 0 0 1px var(--line-2)}
.v2 .pill.info{color:var(--link);box-shadow:inset 0 0 0 1px rgba(107,155,255,.4)}
.v2 .pill.end{color:var(--coral);box-shadow:inset 0 0 0 1px rgba(255,106,77,.4)}
.v2 .pill.per{color:var(--violet);box-shadow:inset 0 0 0 1px rgba(185,167,255,.4)}
.v2 .pill.soon{color:var(--amber);box-shadow:inset 0 0 0 1px rgba(255,184,77,.4)}
.v2 .pill.ok{color:var(--ok);box-shadow:inset 0 0 0 1px rgba(62,224,164,.42)}
.v2 .pill.new0{color:var(--lime);box-shadow:inset 0 0 0 1px rgba(193,255,113,.45)}   /* a new live 0%: lime is earned */

/* kind tile: what a requirement is about, in its category hue. Never a status */
.v2 .kt{--k:var(--k-paper);flex:none;width:34px;height:34px;border-radius:var(--r-s);display:grid;place-items:center;color:var(--k);
  background:linear-gradient(150deg,color-mix(in srgb,var(--k) 30%,transparent),color-mix(in srgb,var(--k) 8%,transparent));
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--k) 36%,transparent),inset 0 1px 0 rgba(255,255,255,.14)}
.v2 .kt svg{width:17px;height:17px}
.v2 .kt.s{width:28px;height:28px;border-radius:8px}.v2 .kt.s svg{width:14px;height:14px}
.v2 .k-score{--k:var(--k-score)}.v2 .k-time{--k:var(--k-time)}.v2 .k-money{--k:var(--k-money)}
.v2 .k-place{--k:var(--k-place)}.v2 .k-tie{--k:var(--k-tie)}.v2 .k-paper{--k:var(--k-paper)}

/* status mark: met, not met, clears on a date, can't tell, nothing to pass */
.v2 .stm{flex:none;width:26px;height:26px;border-radius:50%;display:grid;place-items:center;font:700 var(--t-small)/1 var(--sans);font-style:normal}
.v2 .stm.ok{color:#04122b;background:var(--ok);box-shadow:0 0 18px -4px rgba(62,224,164,.7)}
.v2 .stm.no{color:#fff;background:var(--coral);box-shadow:0 0 18px -4px rgba(255,106,77,.7)}
.v2 .stm.soon{color:#2a1800;background:var(--amber);box-shadow:0 0 18px -4px rgba(255,184,77,.7)}
.v2 .stm.unknown,.v2 .stm.info{color:var(--ink-2);background:rgba(255,255,255,.08);box-shadow:inset 0 0 0 1px var(--line-2)}

/* the lock: shows the layer exists and what it answers, never a value */
.v2 .lock{display:grid;grid-template-columns:auto 1fr auto;gap:14px;align-items:center;padding:14px var(--s-4);border-radius:var(--r-m);background:linear-gradient(90deg,rgba(46,114,255,.07),transparent 70%);box-shadow:inset 0 0 0 1px var(--line)}
.v2 .lock .ico{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;background:rgba(255,255,255,.05);box-shadow:inset 0 0 0 1px var(--line-2);color:var(--ink-2)}
.v2 .lock b{display:block;font-weight:550;font-size:var(--t-ui);letter-spacing:-.01em}
.v2 .lock p{margin:2px 0 0;color:var(--ink-3);font-size:var(--t-small);line-height:1.45}
.v2 .lock.trial{background:linear-gradient(90deg,rgba(193,255,113,.07),transparent 70%)}
.v2 .lock.trial .ico{color:var(--lime)}
@media(max-width:480px){.v2 .lock{grid-template-columns:auto 1fr}.v2 .lock .btn{grid-column:1/-1;justify-self:start}}

/* live: only claims "today" when the data is under a day old; amber once it isn't */
.v2 .live{display:inline-flex;align-items:center;gap:var(--s-2);font:500 var(--t-label)/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2)}
.v2 .live>i{position:relative;width:7px;height:7px;border-radius:50%;background:var(--lime)}
.v2 .live>i::after{content:"";position:absolute;inset:0;border-radius:50%;animation:v2-ping 2.4s var(--ease) infinite}
.v2 .live.stale>i{background:var(--amber)}.v2 .live.stale>i::after{animation:none}
@keyframes v2-ping{0%{box-shadow:0 0 0 0 rgba(193,255,113,.55)}100%{box-shadow:0 0 0 11px rgba(193,255,113,0)}}

/* brand lockups (marks.js draws the marks) */
.v2 .mark{width:28px;height:28px;flex:none;display:block}
/* space held before marks.js and account.js fill them, so the header doesn't grow a beat after first paint (layout shift, 2026-09-29) */
.v2 .lockup>[data-mark]{width:28px;height:28px;flex:none;display:block}
.v2 #acct-host{min-height:36px}
.v2 .lockup{display:inline-flex;align-items:center;gap:11px;color:var(--ink);text-decoration:none}
.v2 .lockup b{font-weight:650;font-size:var(--t-body);letter-spacing:-.025em;line-height:1}
.v2 .lockup small{display:block;margin-top:var(--s-1);font:500 var(--t-label)/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3)}
.v2 .mark .sweep{animation:v2-sweep 4s linear infinite;transform-origin:16px 16px}
@keyframes v2-sweep{to{transform:rotate(360deg)}}
/* the sweep turns only while the data is live (UI.fresh): a day-old export stills every radar mark on the page */
html[data-stale] .mark .sweep{animation:none}
@media (prefers-reduced-motion:reduce){.v2 .mark .sweep{animation:none}}

/* reveal once, never replay */
.v2 .rv{opacity:0;transform:translateY(18px);transition:opacity var(--d-3) var(--ease),transform var(--d-3) var(--ease)}
.v2 .rv.in{opacity:1;transform:none}
.v2 .rv.d1{transition-delay:60ms}.v2 .rv.d2{transition-delay:120ms}.v2 .rv.d3{transition-delay:180ms}
@media (prefers-reduced-motion:reduce){.v2 .rv{transform:none}}
/* the first screen rises in with CSS alone: .rv waits for ui.js, and the hero's text is what the page is judged on
   (Lighthouse's largest paint was 95% waiting for the reveal, 2026-09-29) */
.v2 .rise{animation:v2-rise var(--d-3) var(--ease) both}.v2 .rise.d1{animation-delay:60ms}.v2 .rise.d2{animation-delay:120ms}
@keyframes v2-rise{from{opacity:.01;transform:translateY(18px)}}
@media (prefers-reduced-motion:reduce){.v2 .rise{animation:none}}

/* skeletons: the shape of what is coming, not a spinner */
.v2 .skel{display:block;border-radius:var(--r-xs);background:linear-gradient(90deg,rgba(255,255,255,.05),rgba(255,255,255,.10),rgba(255,255,255,.05));background-size:200% 100%;animation:v2-skel 1.4s var(--ease-io) infinite}
@keyframes v2-skel{to{background-position:-200% 0}}

/* ---------- 0% terms: solid lime for purchases, lime outline for transfers, violet for personal cards ---------- */
.v2 .zero.ghost{background:rgba(193,255,113,.1);color:var(--lime);box-shadow:inset 0 0 0 1px rgba(193,255,113,.4)}
.v2 .zero.per{background:linear-gradient(180deg,#d4c9ff,var(--violet));color:#1a1040}
.v2 .zero.per.ghost{background:rgba(185,167,255,.1);color:var(--violet);box-shadow:inset 0 0 0 1px rgba(185,167,255,.4)}

/* ---------- surfaces ---------- */
.v2 .panel{border-radius:var(--r-m);background:var(--surface);box-shadow:var(--e-1)}
.v2 .card{border-radius:var(--r);background:var(--surface);box-shadow:var(--e-1)}
.v2 .calm{padding:var(--s-5) 22px;border-radius:var(--r-m);background:var(--surface);box-shadow:var(--e-1);color:var(--ink-2);font-size:var(--t-body);line-height:1.6}
.v2 .calm b{color:var(--ink);font-weight:550}.v2 .calm a{color:var(--link)}
.v2 .chev{width:16px;height:16px;flex:none}

/* ---------- logo plate: the bank's own logo on white, or its initials ---------- */
.v2 .plate{width:44px;height:44px;border-radius:11px;background:#fff;display:grid;place-items:center;overflow:hidden;flex:none;box-shadow:0 6px 16px -8px rgba(0,0,0,.8)}
.v2 .plate img{width:78%;height:78%;object-fit:contain}
.v2 .plate.mono{background:linear-gradient(150deg,#16306e,#0a1a44);color:var(--ink);font:650 var(--t-body)/1 var(--sans);letter-spacing:-.02em}
.v2 .plate.xl{width:68px;height:68px;border-radius:17px;box-shadow:0 18px 40px -18px rgba(0,0,0,.9),0 0 0 1px rgba(255,255,255,.08)}
.v2 .plate.sm{width:32px;height:32px;border-radius:8px}.v2 .plate.xs{width:22px;height:22px;border-radius:var(--r-xs);font-size:var(--t-label)}
.v2 .stack{display:inline-flex}.v2 .stack .plate{margin-left:-7px;box-shadow:0 0 0 2px var(--bg)}.v2 .stack .plate:first-child{margin-left:0}

/* ---------- the card as an object (decision 3): tilt on a spring, sheen, contact shadow. ui.js drives the vars.
   Width is set where it is used; everything else scales with it. ---------- */
.v2 .face{--rx:0deg;--ry:0deg;--mx:50%;--my:50%;--lift:0px;--sheen:0;position:relative;display:block;flex:none;width:96px;aspect-ratio:1.586;border-radius:7.5%/11.9%;overflow:hidden;
  transform:perspective(700px) rotateX(var(--rx)) rotateY(var(--ry)) translateZ(var(--lift));box-shadow:0 14px 28px -14px rgba(0,0,0,.95),0 0 0 1px rgba(255,255,255,.06)}
.v2 .face img{width:100%;height:100%;object-fit:cover;display:block}
.v2 .face::after{content:"";position:absolute;inset:0;background:radial-gradient(circle at var(--mx) var(--my),rgba(255,255,255,calc(.3*var(--sheen))),transparent 55%);mix-blend-mode:screen;pointer-events:none}
/* a card with no art of its own: the bank's colour, its name, a chip and the network */
.v2 .plateface{display:flex;flex-direction:column;justify-content:space-between;padding:0;container-type:inline-size;background:linear-gradient(135deg,var(--c1,#1c3a86),var(--c2,#0b1d4f) 62%,#060f2c)}
.v2 .plateface .bn{display:block;font:650 11cqi/1.1 var(--sans);letter-spacing:-.015em;color:#fff}
.v2 .plateface .cn{display:block;margin-top:3%;font:500 6cqi/1.2 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.72);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.v2 .plateface .chip{width:15%;aspect-ratio:1.35;border-radius:12%;background:linear-gradient(135deg,#ecd894,#b8983e)}
.v2 .plateface .net{align-self:flex-end;font:700 italic 10cqi/1 var(--sans);color:#fff;opacity:.9;letter-spacing:.02em}
.v2 .plateface>:first-child{margin:7.5cqi 8cqi 0}.v2 .plateface>.chip{margin:0 8cqi}.v2 .plateface>.net{margin:0 8cqi 7.5cqi}

/* ---------- fields ---------- */
.v2 .fld{margin-top:18px}
.v2 .fld>label{display:block;margin-bottom:var(--s-2);font-size:var(--t-ui);font-weight:550;color:var(--ink-2)}
.v2 .inp{position:relative;display:flex;align-items:center}
.v2 .inp input,.v2 .inp select,.v2 .inp textarea{width:100%;min-height:50px;padding:0 var(--s-4);border-radius:12px;border:0;background:rgba(255,255,255,.045);box-shadow:inset 0 0 0 1px var(--line-2);color:var(--ink);font:inherit;font-size:var(--t-body);outline:0;transition:box-shadow var(--d-1),background-color var(--d-1)}
.v2 .inp input:focus,.v2 .inp select:focus,.v2 .inp textarea:focus{background:rgba(255,255,255,.06);box-shadow:inset 0 0 0 1.5px var(--link),0 0 0 4px rgba(46,114,255,.18)}
.v2 .inp select{appearance:none;-webkit-appearance:none;cursor:pointer}
.v2 .inp .aff{position:absolute;right:8px;height:34px;padding:0 10px;border:0;border-radius:8px;background:none;color:var(--ink-3);font:inherit;font-size:var(--t-small);cursor:pointer}
.v2 .inp .aff:hover{color:var(--ink);background:rgba(255,255,255,.05)}
.v2 .inp.bad input,.v2 .inp.bad select{box-shadow:inset 0 0 0 1.5px var(--coral)}
.v2 .err{margin-top:var(--s-2);font-size:var(--t-ui);color:#ff8f78;line-height:1.45}
.v2 .hint{margin-top:var(--s-2);font-size:var(--t-small);color:var(--ink-3);line-height:1.45}

/* ---------- choices: pill toggles, option cards, radio cards, a switch ---------- */
.v2 .segs{display:flex;flex-wrap:wrap;gap:var(--s-2)}
.v2 .segs>button{height:40px;padding:0 var(--s-4);border-radius:var(--r-pill);border:0;background:rgba(255,255,255,.04);box-shadow:inset 0 0 0 1px var(--line-2);color:var(--ink-2);font:inherit;font-size:var(--t-ui);cursor:pointer;transition:background-color var(--d-1),box-shadow var(--d-1),color var(--d-1)}
.v2 .segs>button:hover{color:var(--ink)}
.v2 .segs>button[aria-pressed=true]{background:rgba(46,114,255,.16);box-shadow:inset 0 0 0 1.5px var(--link);color:var(--ink)}
.v2 .opts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.v2 .opts>button{text-align:left;padding:18px;border-radius:var(--r-m);border:0;background:rgba(255,255,255,.035);box-shadow:inset 0 0 0 1px var(--line-2);color:var(--ink);font:inherit;cursor:pointer;transition:background-color var(--d-1),box-shadow var(--d-1)}
.v2 .opts>button b{display:block;font-size:20px;font-weight:600;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.v2 .opts>button span{display:block;margin-top:5px;font-size:var(--t-small);color:var(--ink-3)}
.v2 .opts>button:hover{background:rgba(255,255,255,.055)}
.v2 .opts>button[aria-pressed=true]{background:rgba(46,114,255,.12);box-shadow:inset 0 0 0 1.5px var(--link)}
.v2 .choice{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.v2 .choice label{position:relative;display:block;padding:14px var(--s-4) 14px 44px;border-radius:var(--r-m);background:rgba(255,255,255,.03);box-shadow:inset 0 0 0 1px var(--line-2);cursor:pointer;transition:background-color var(--d-1),box-shadow var(--d-1)}
.v2 .choice label:hover{background:rgba(255,255,255,.05)}
.v2 .choice input{position:absolute;left:16px;top:17px;width:16px;height:16px;accent-color:var(--blue)}
.v2 .choice label:has(input:checked){background:rgba(46,114,255,.1);box-shadow:inset 0 0 0 1.5px var(--link)}
.v2 .choice b{display:block;font-size:var(--t-ui);font-weight:600}.v2 .choice span{display:block;margin-top:3px;font-size:var(--t-small);color:var(--ink-3);line-height:1.4}
.v2 .toggle{display:inline-flex;align-items:center;gap:10px;padding:0;border:0;background:none;font:inherit;font-size:var(--t-ui);color:var(--ink-2);cursor:pointer}
.v2 .toggle>i{position:relative;width:36px;height:22px;border-radius:11px;background:rgba(255,255,255,.1);box-shadow:inset 0 0 0 1px var(--line-2);transition:background-color var(--d-2)}
.v2 .toggle>i::after{content:"";position:absolute;left:3px;top:3px;width:16px;height:16px;border-radius:50%;background:var(--sand);transition:transform var(--d-2) var(--ease)}
.v2 .toggle[aria-pressed=true]>i{background:var(--blue)}.v2 .toggle[aria-pressed=true]>i::after{transform:translateX(14px);background:#fff}
@media(max-width:560px){.v2 .choice{grid-template-columns:1fr}}

/* ---------- where a rule comes from: the bank's words, our guidance, or arithmetic ---------- */
.v2 .src{display:inline-flex;align-items:center;height:20px;padding:0 7px;border-radius:5px;font:500 var(--t-label)/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);box-shadow:inset 0 0 0 1px var(--line-2);white-space:nowrap}
.v2 .src.bank{color:var(--link);box-shadow:inset 0 0 0 1px rgba(107,155,255,.4)}
.v2 .src.bcp{color:var(--sand)}

/* ---------- progress and rings: drawn in once when seen (ui.js) ---------- */
.v2 .prog{height:6px;border-radius:3px;background:rgba(255,255,255,.07);overflow:hidden}
.v2 .prog>i{display:block;height:100%;width:0;border-radius:3px;background:linear-gradient(90deg,var(--blue-deep),var(--link));transition:width 1.2s var(--ease)}
.v2 .prog.zero-left>i{background:linear-gradient(90deg,var(--lime-2),var(--lime))}   /* time left on a live 0% */
.v2 .ring{position:relative;width:74px;height:74px;flex:none}
.v2 .ring svg{width:100%;height:100%;transform:rotate(-90deg)}
.v2 .ring .t{fill:none;stroke:rgba(255,255,255,.07);stroke-width:6}
.v2 .ring .v{fill:none;stroke-width:6;stroke-linecap:round;transition:stroke-dashoffset 1.3s var(--ease)}
.v2 .ring>b{position:absolute;inset:0;display:grid;place-items:center;font-weight:600;font-size:22px;letter-spacing:-.03em;font-variant-numeric:tabular-nums}

/* ---------- disclosure for what is never counted (wording updates, re-reads) ---------- */
.v2 details.fold>summary{cursor:pointer;list-style:none;color:var(--ink-3);font-size:var(--t-small);padding:var(--s-2) 2px}
.v2 details.fold>summary::-webkit-details-marker{display:none}
.v2 details.fold>summary::before{content:"▸ "}.v2 details.fold[open]>summary::before{content:"▾ "}
.v2 details.fold>div{font-size:var(--t-small);color:var(--ink-3);line-height:1.7}
