/* Nextstep4u v1 — homepage layout.
 *
 * Sits on top of app.css, which owns the tokens, the base reset, the type
 * rules and the motion layer. Nothing here declares a colour: every value is a
 * token, or dark mode breaks silently and nobody notices until a candidate
 * screenshots it.
 *
 * Class names are prefixed `v1-` where a collision with the old stylesheet was
 * possible. The old site is in old/frontend and shares this stylesheet's
 * ancestors, so the prefix is cheap insurance rather than fussiness.
 */

/* ── skip link ──────────────────────────────────────────────────────────── */
/* Off-screen until focused, then a real, visible target. Moved here because it
   was never defined in app.css — the markup referenced a class that did not
   exist, so the link simply sat at the top of the page in plain view. */
.skip{
  position:absolute;left:-9999px;top:0;z-index:100;
  background:var(--page);color:var(--ink);
  border:1px solid var(--line-3);border-radius:var(--r-sm);
  padding:12px 18px;font-weight:600;
}
.skip:focus{left:12px;top:12px;}

/* The `hidden` attribute has to beat a class that sets `display`. Without
   this, `.v1-stats{display:flex}` won on specificity and the empty, unverified
   stats strip still drew its top border under the hero buttons — a stray rule
   across the left column and 72px of space that pushed the headline off centre
   against the report card. Any component hidden by attribute is affected, so
   the reset belongs here rather than on one selector. */
[hidden]{display:none !important;}

/* ── shell ──────────────────────────────────────────────────────────────── */
.v1-wrap{max-width:1200px;margin:0 auto;padding:0 20px;}

/* 16px gutter on a phone, per the design brief. Anything less and the text
   touches the bezel on a 360px screen. */
@media (max-width:560px){ .v1-wrap{padding:0 16px;} }

/* ── the sale bar ───────────────────────────────────────────────────────
   A promotional surface, not part of the product palette. Its red lives here
   and nowhere else in the site: nothing else on the page uses it, so it never
   competes with blue for "this is the action" or with green for "this is
   free". It sits on the same navy as the report card and the footer, which is
   why it reads as a band across the top rather than as a broken component.

   Above the header and not sticky. The header keeps top:0 and slides over it.

   Every colour here is literal rather than a token, deliberately: adding
   --sale-* to the palette would invite the red into the rest of the site.
   Literal does not mean invented, though. These are all approved canvas
   colours. The bar was drafted in a hotter orange-red gradient that exists
   nowhere in the design, and scripts/check-palette.py refused the push --
   which is the check doing exactly its job. The palette holds one red, so the
   badge and the button wear it flat rather than as a gradient between two
   reds that do not exist. (Hex values are deliberately not quoted in this
   comment: the palette check reads comments too, and rightly so.) */
.v1-sale{
  position:relative;overflow:hidden;
  background:linear-gradient(120deg,#171F2C 0%,#1B2431 45%,#3A1F22 100%);
  border-bottom:1px solid rgba(255,255,255,.08);
  color:#fff;
}
/* A slow band of light crossing the bar. Decorative, behind everything, and
   the first thing prefers-reduced-motion switches off. */
.v1-sale-sweep{
  position:absolute;top:0;bottom:0;left:0;width:22%;pointer-events:none;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.10),transparent);
  animation:saleSweep 4.5s ease-in-out infinite;
}
@keyframes saleSweep{
  0%{transform:translateX(-120%);}
  60%,100%{transform:translateX(560%);}
}

.v1-sale-in{
  position:relative;max-width:1200px;margin:0 auto;
  padding:8px 20px;display:flex;align-items:center;gap:14px;min-width:0;
}
.v1-sale-lead{display:flex;align-items:center;gap:12px;min-width:0;flex:1;}

.v1-sale-badge{
  display:inline-flex;align-items:center;gap:6px;flex:none;
  background:#D93843;color:#fff;
  font-size:10px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;
  padding:5px 9px;border-radius:5px;white-space:nowrap;
  box-shadow:0 2px 12px rgba(217,56,67,.45);
}
.v1-sale-dot{
  width:5px;height:5px;border-radius:50%;background:#fff;
  animation:salePulse 1s ease-in-out infinite;
}
@keyframes salePulse{0%,100%{opacity:1;}50%{opacity:.25;}}

.v1-sale-head{
  font-size:14px;font-weight:700;line-height:1.3;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;
}
.v1-sale-seats{
  flex:none;white-space:nowrap;
  font-size:10.5px;font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;color:#FBE49B;
  border-left:1px solid rgba(255,255,255,.14);padding-left:12px;
}

.v1-sale-clock{display:flex;align-items:center;gap:9px;flex:none;}
.v1-sale-ends{
  font-size:10px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:#FBE49B;
}
.v1-sale-digits{
  display:flex;align-items:center;gap:4px;
  font-variant-numeric:tabular-nums;
  font-size:13.5px;font-weight:700;color:#fff;
}
.v1-sale-unit{
  min-width:28px;padding:4px 7px;text-align:center;border-radius:5px;
  background:rgba(217,56,67,.16);border:1px solid rgba(217,56,67,.45);
}
.v1-sale-sec{animation:saleTick 1s ease-in-out infinite;}
@keyframes saleTick{0%,100%{border-color:rgba(217,56,67,.45);}50%{border-color:rgba(217,56,67,.95);}}
.v1-sale-colon{color:#FBBC04;}
.v1-sale-days[hidden]{display:none;}

.v1-sale-end{display:flex;align-items:center;gap:6px;flex:none;}
.v1-sale-cta{
  display:inline-flex;align-items:center;
  background:#D93843;color:#fff;
  font-size:13px;font-weight:700;padding:9px 16px;border-radius:7px;
  white-space:nowrap;
  animation:saleBreathe 2.2s ease-in-out infinite;
  transition:filter .16s var(--ease);
}
.v1-sale-cta:hover{color:#fff;filter:brightness(1.08);}
@keyframes saleBreathe{
  0%,100%{box-shadow:0 0 0 0 rgba(217,56,67,.45);}
  50%{box-shadow:0 0 0 7px rgba(217,56,67,0);}
}
.v1-sale-x{
  color:#94A0AE;font-size:18px;line-height:1;padding:8px;border-radius:6px;
  transition:color .16s var(--ease),background .16s var(--ease);
}
.v1-sale-x:hover{color:#fff;background:rgba(255,255,255,.1);}

/* On a phone the bar keeps the offer and the button and drops the rest: the
   seat line, the words "Ends in" and the seconds are the first things to go,
   because a 360px screen has room for a claim and a way to act on it. */
@media (max-width:780px){
  .v1-sale-in{padding:7px 16px;gap:10px;}
  .v1-sale-seats,.v1-sale-ends{display:none;}
  .v1-sale-head{font-size:13px;}
  .v1-sale-digits{font-size:12.5px;}
  .v1-sale-unit{min-width:24px;padding:3px 5px;}
  .v1-sale-cta{padding:8px 12px;font-size:12.5px;}
}
@media (max-width:520px){
  .v1-sale-badge{padding:5px 7px;letter-spacing:.1em;}
  .v1-sale-clock{display:none;}
}

/* The bar is an offer, not an alarm. Nothing here pulses under reduced
   motion; the countdown still counts, because that is information. */
@media (prefers-reduced-motion:reduce){
  .v1-sale-sweep{display:none;}
  .v1-sale-dot,.v1-sale-sec,.v1-sale-cta{animation:none;}
}

/* ── the fixed top ──────────────────────────────────────────────────────
   The offer bar and the header stick as one block, so neither has to know the
   other's height. */
.v1-top{position:sticky;top:0;z-index:40;}

/* ── header ─────────────────────────────────────────────────────────────── */
/* Positioned, but no longer sticky in its own right — the wrapper above does
   that now. It stays `relative` because the mobile menu is absolutely placed
   against it at top:68px, and would otherwise measure from the top of the
   offer bar and land over the logo. */
.v1-head{
  position:relative;z-index:1;
  background:var(--page);border-bottom:1px solid var(--line);
}
.v1-head-in{display:flex;align-items:center;gap:28px;height:68px;}
.v1-logo{display:flex;align-items:center;gap:8px;font-weight:800;font-size:19px;color:var(--ink);letter-spacing:-.02em;}
.v1-logo-text span{color:var(--blue);}
/* Height-constrained, width auto, so a mark of any aspect ratio drops in
   without redesigning the header. The explicit width/height on the element
   reserves the space so the nav does not jump when it loads. */
.v1-logo-img{height:34px;width:auto;}

.v1-nav{display:flex;align-items:center;gap:26px;margin-left:8px;}
/* The whole nav is green. --green-deep and not the brighter --green-ink,
   because 15px at weight 500 is not large text: green-deep clears AA on white
   at 6.6:1, green-ink sits at 3.8:1 and would fail. The lighter one is the
   hover, where it reads as the link brightening. */
.v1-nav a{color:var(--green-deep);font-weight:500;font-size:15px;}
.v1-nav a:hover{color:var(--green-ink);}

/* Now that every link is green, the current page needs something other than
   colour to mark it — a weight bump and a rule under the word. */
.v1-nav a[aria-current="page"]{
  color:var(--green-deep);font-weight:700;
  box-shadow:inset 0 -2px 0 0 var(--green);
}

/* Current Affairs is the free half of the product. Green used to carry that
   on its own; with the whole nav green it cannot, so the weight does. */
.v1-nav a.is-free{font-weight:700;}
.v1-head-end{margin-left:auto;display:flex;align-items:center;gap:16px;}

/* ── the exam menu ──────────────────────────────────────────────────────
   One trigger standing in for every exam family. The panel is never removed
   from the DOM: it is hidden with visibility, which keeps it out of the
   accessibility tree and out of the tab order while still letting the open
   and close animate. */
.v1-drop{position:relative;}
.v1-drop-btn{
  display:inline-flex;align-items:center;gap:6px;
  color:var(--green-deep);font-weight:500;font-size:15px;font-family:inherit;
  padding:8px 0;transition:color .14s var(--ease);
}
.v1-drop-btn:hover,.v1-drop.open .v1-drop-btn{color:var(--green-ink);}
.v1-drop-caret{stroke:currentColor;transition:transform .22s var(--ease);}
.v1-drop.open .v1-drop-caret{transform:rotate(180deg);}

.v1-drop-panel{
  position:absolute;top:calc(100% + 12px);left:-16px;z-index:50;
  width:330px;padding:8px;
  background:var(--page);border:1px solid var(--line);
  border-radius:var(--r-lg);box-shadow:var(--shadow-2);
  opacity:0;visibility:hidden;transform:translateY(-8px) scale(.985);
  transform-origin:top left;
  transition:opacity .18s var(--ease),transform .22s var(--ease),visibility .22s;
}
.v1-drop.open .v1-drop-panel{opacity:1;visibility:visible;transform:none;}

/* A small notch tying the panel to the trigger it belongs to. */
.v1-drop-panel::before{
  content:"";position:absolute;top:-5px;left:24px;width:9px;height:9px;
  background:var(--page);border-left:1px solid var(--line);border-top:1px solid var(--line);
  transform:rotate(45deg);border-radius:2px 0 0 0;
}

.v1-drop-item{
  display:block;padding:11px 12px;border-radius:var(--r-md);
  transition:background .16s var(--ease),transform .16s var(--ease);
  /* Each row arrives a beat after the one above it. The delay only applies
     on the way in; closing takes everything with it at once. */
  opacity:0;transform:translateY(-4px);
}
.v1-drop.open .v1-drop-item{
  opacity:1;transform:none;
  transition:opacity .2s var(--ease),transform .2s var(--ease),background .16s var(--ease);
}
.v1-drop.open .v1-drop-item:nth-child(1){transition-delay:.03s;}
.v1-drop.open .v1-drop-item:nth-child(2){transition-delay:.07s;}
.v1-drop.open .v1-drop-item:nth-child(3){transition-delay:.11s;}
.v1-drop-item:hover{background:var(--blue-tint);}
.v1-drop-row{display:flex;align-items:center;gap:9px;}
.v1-drop-name{font-weight:700;font-size:15px;color:var(--ink);letter-spacing:-.01em;}
.v1-drop-item:hover .v1-drop-name{color:var(--blue);}
.v1-drop-note{display:block;margin-top:3px;font-size:12.5px;line-height:1.45;color:var(--ink-3);}

/* Not .v1-chip: that name is already the exam card's count pill further down
   this file, and the later rule would quietly win. */
.v1-drop-chip{
  font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  padding:3px 8px;border-radius:999px;
  background:var(--chip);color:var(--ink-4);
}
.v1-drop-chip-live{background:var(--green-bg);color:var(--green-deep);}

/* Every control is at least 44px tall. The design brief makes this a rule and
   not a preference — this audience is one-handed on a phone on a bus. */
.v1-btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:0 20px;border-radius:var(--r-md);
  font-weight:600;font-size:15px;white-space:nowrap;
  transition:transform .14s var(--ease),box-shadow .14s var(--ease),background .14s var(--ease);
}
.v1-btn:active{transform:translateY(1px);}
.v1-btn-primary{background:var(--blue-fill);color:#fff;box-shadow:var(--shadow-1);}
.v1-btn-primary:hover{background:var(--blue-deep);color:#fff;box-shadow:var(--shadow-3);}
.v1-btn-ghost{background:var(--page);color:var(--ink);border:1px solid var(--line-3);}
.v1-btn-ghost:hover{color:var(--ink);border-color:var(--ink-4);}
/* Amber is a SURFACE under near-black text, never text and never on dark.
   1.75:1 on white is the reason. */
.v1-btn-amber{background:var(--amber);color:var(--night);}
.v1-btn-amber:hover{color:var(--night);filter:brightness(.96);}
/* Near-black on green, not white. White on #00B696 is 2.58:1 — well under the
   4.5:1 body text has to clear, and this is the primary call to action on the
   WhatsApp band. Near-black takes it to 7.15:1 and keeps the vivid brand green,
   which is the same trade the amber button already makes: a bright brand colour
   is a SURFACE, and the text on it goes dark. */
.v1-btn-green{background:var(--green);color:var(--night);}
.v1-btn-green:hover{color:var(--night);filter:brightness(.95);}
.v1-link{color:var(--ink-2);font-weight:500;font-size:15px;}

.v1-burger{display:none;margin-left:auto;padding:10px;border-radius:var(--r-sm);min-height:44px;min-width:44px;}
.v1-burger svg{stroke:var(--ink);}

@media (max-width:900px){
  .v1-nav{
    display:none;position:absolute;top:68px;left:0;right:0;
    flex-direction:column;align-items:stretch;gap:0;
    background:var(--page);border-bottom:1px solid var(--line);padding:8px 20px 16px;
  }
  .v1-nav.open{display:flex;}
  .v1-nav > a{padding:13px 0;border-bottom:1px solid var(--line-2);}

  /* No room to float a panel over a 360px screen, so the exam menu becomes an
     ordinary accordion inside the stacked menu. */
  .v1-drop{border-bottom:1px solid var(--line-2);}
  .v1-drop-btn{width:100%;justify-content:space-between;padding:13px 0;}
  .v1-drop-panel{
    position:static;width:auto;padding:0 0 10px;
    border:0;border-radius:0;box-shadow:none;transform:none;
    display:none;
  }
  .v1-drop-panel::before{display:none;}
  .v1-drop.open .v1-drop-panel{display:block;}
  .v1-drop-item{background:var(--sunk);margin-bottom:6px;}
  .v1-burger{display:inline-flex;align-items:center;justify-content:center;}
  .v1-head-end .v1-link{display:none;}
  /* margin-left:auto stays. Cancelling it here left the button and the burger
     sitting against the logo with the right half of the header empty, which
     reads as a broken header rather than a compact one. */
  .v1-head-end{gap:10px;}
}

/* ── hero ───────────────────────────────────────────────────────────────── */
.v1-hero{background:var(--shell);border-bottom:1px solid var(--line);}
.v1-hero-grid{
  display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:center;
  padding:72px 0 76px;
}
.v1-eyebrow{
  display:inline-flex;align-items:center;gap:8px;
  background:var(--green-bg);color:var(--green-deep);
  border:1px solid var(--green-line);border-radius:999px;
  padding:7px 15px;font-size:12px;
  letter-spacing:.08em;text-transform:uppercase;font-weight:600;
}
.v1-h1{
  font-size:clamp(34px,5.2vw,58px);line-height:1.06;letter-spacing:-.035em;
  font-weight:800;margin:22px 0 0;color:var(--ink);
}
.v1-sub{font-size:clamp(16px,1.6vw,18px);color:var(--ink-3);margin-top:20px;max-width:35ch;}
.v1-cta-row{display:flex;flex-wrap:wrap;gap:12px;margin-top:32px;}

.v1-stats{
  display:flex;gap:48px;margin-top:44px;padding-top:28px;
  border-top:1px solid var(--line);
}
.v1-stat-n{
  font-variant-numeric:tabular-nums;
  font-size:30px;font-weight:600;color:var(--ink);letter-spacing:-.02em;
}
.v1-stat-l{font-size:13px;color:var(--ink-4);margin-top:2px;}

@media (max-width:900px){
  .v1-hero-grid{grid-template-columns:1fr;gap:36px;padding:44px 0 52px;}
  .v1-sub{max-width:none;}
  .v1-stats{gap:28px;flex-wrap:wrap;}
}

/* ── the report card ────────────────────────────────────────────────────── */
/* The single most important object on this page. It is the product, shown
   rather than described, so it is rendered at full fidelity and not as a
   screenshot — a screenshot cannot be read by a screen reader and goes blurry
   on the devices this audience actually holds. */
.v1-report{
  background:var(--night);border-radius:var(--r-xl);padding:28px;
  box-shadow:var(--shadow-2);color:#E6E9ED;
}
/* ── the proof card ─────────────────────────────────────────────────────
   One candidate's score crossing a cut-off. It works because a cut-off is the
   only number in this audience's life that matters: 87 and 118 mean nothing on
   their own, and everything either side of 112. */
.v1-proof-top{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;}
.v1-proof-pill{
  background:var(--green);color:#FFFFFF;border-radius:999px;
  padding:6px 13px;font-size:11px;
  letter-spacing:.09em;text-transform:uppercase;font-weight:600;
  font-variant-numeric:tabular-nums;
}
/* Centred in the card. The pair is the argument — 87 alone means nothing and
   118 alone means nothing — so it sits as one centred object rather than being
   left-aligned against everything else. */
.v1-jump{display:flex;align-items:center;justify-content:center;gap:24px;margin-top:22px;flex-wrap:wrap;}
.v1-jump-col{text-align:center;}
.v1-jump-col .n{
  font-variant-numeric:tabular-nums;
  font-size:46px;line-height:1;font-weight:700;letter-spacing:-.04em;
}
.v1-jump-col .l{font-size:13px;margin-top:8px;}
.v1-jump-from .n{color:#94A0AE;}
.v1-jump-from .l{color:#94A0AE;}
.v1-jump-to   .n{color:var(--amber);font-size:58px;}
.v1-jump-to   .l{color:var(--green);}
/* The arrow is the verb in this card — it is the thing that says "moved". It
   is sized to sit between the two numbers rather than beneath them, and it
   glows, because amber on near-black is the one place on this site where a
   glow reads as light rather than as a effect bolted on.
   Built from --amber-rgb so there is no second copy of the hex to drift. */
.v1-jump-arrow{
  color:var(--amber);
  font-size:40px;
  line-height:1;
  /* Two shadows: a tight one that reads as the glyph being lit, and a wide
     soft one that reads as the light falling on the panel around it. */
  text-shadow:
    0 0 10px rgba(var(--amber-rgb), .55),
    0 0 26px rgba(var(--amber-rgb), .30);
}

/* The bar reads left to right as the journey, with the cut-off marked where it
   actually falls. The marker is a line and a label, not a colour change, so it
   survives both themes and a monochrome screenshot. */
.v1-cut{margin-top:26px;}
.v1-cut-track{
  position:relative;height:12px;border-radius:999px;
  background:var(--night-3);overflow:visible;
}
.v1-cut-fill{
  display:block;height:100%;border-radius:999px;width:0;
  background:linear-gradient(90deg,var(--amber),var(--green));
  transition:width .8s var(--ease);
}
.v1-cut-track.in .v1-cut-fill{width:var(--w);}
.v1-cut-mark{
  position:absolute;top:-4px;bottom:-4px;width:2px;background:#FFFFFF;
  border-radius:2px;
}
.v1-cut-label{
  display:block;margin-top:10px;font-size:13px;color:#E6E9ED;
  font-variant-numeric:tabular-nums;
}

/* ── the review ticker ──────────────────────────────────────────────────
   One review at a time, rising out of the bottom. Only two rows exist in the
   DOM at once regardless of how many reviews there are, so 100 entries cost
   the same as 3.

   The viewport is a fixed height with overflow hidden: without it a longer
   quote would push the amber call to action down the card every few seconds,
   which is the kind of motion that makes a page feel broken rather than
   alive. */
.v1-reviews{
  margin-top:24px;padding-top:22px;border-top:1px solid var(--night-3);
}
.v1-reviews-port{position:relative;height:66px;overflow:hidden;}
.v1-reviews-port .v1-proof-quote{
  position:absolute;inset:0;margin:0;padding:0;border:0;
}
/* Entering from below, leaving upward. */
.v1-rev-enter{animation:rev-in .55s var(--ease) both;}
.v1-rev-exit{animation:rev-out .55s var(--ease) both;}
@keyframes rev-in{from{opacity:0;transform:translateY(100%);}to{opacity:1;transform:none;}}
@keyframes rev-out{from{opacity:1;transform:none;}to{opacity:0;transform:translateY(-100%);}}

/* The label and the count on one line, both 11px on the same 18px line box,
   so they sit on a single optical line rather than being centred against each
   other. */
.v1-reviews-foot{
  display:flex;align-items:center;gap:10px;margin-top:12px;
}
.v1-reviews-label,.v1-reviews-count{
  line-height:18px;height:18px;display:inline-flex;align-items:center;
}
.v1-reviews-label{
  font-size:11px;letter-spacing:.07em;font-weight:600;
  text-transform:uppercase;color:#94A0AE;
}
/* The count keeps the right edge; everything else stays left, against the
   quote it belongs to. */
.v1-reviews-foot .v1-reviews-count{margin-left:auto;}

/* Progress dots would need 100 of them. A count is honest and fits. */
.v1-reviews-count{
  font-variant-numeric:tabular-nums;
  font-size:11px;color:#94A0AE;
}

.v1-proof-quote{
  display:flex;gap:13px;align-items:flex-start;
  margin-top:24px;padding-top:22px;border-top:1px solid var(--night-3);
}
.v1-avatar{
  flex:0 0 auto;width:42px;height:42px;border-radius:999px;
  background:var(--blue-fill);color:#FFFFFF;
  display:flex;align-items:center;justify-content:center;
  font-weight:700;font-size:14px;letter-spacing:.02em;
}
.v1-proof-quote blockquote{font-size:14px;color:#E6E9ED;line-height:1.5;}
.v1-proof-quote figcaption{font-size:13px;color:#94A0AE;margin-top:5px;}

@media (max-width:560px){
  .v1-jump{gap:14px;}
  .v1-jump-col .n{font-size:38px;}
  .v1-jump-to .n{font-size:46px;}
}

.v1-report-top{display:flex;justify-content:space-between;align-items:baseline;gap:16px;flex-wrap:wrap;}
.v1-report-kicker{
  font-size:11px;letter-spacing:.1em;font-weight:600;
  text-transform:uppercase;color:#94A0AE;
}
.v1-report-meta{font-size:13px;color:#94A0AE;}
.v1-score-row{display:flex;align-items:baseline;gap:12px;margin-top:14px;}
.v1-score{
  font-variant-numeric:tabular-nums;
  font-size:58px;line-height:1;font-weight:700;color:var(--amber);letter-spacing:-.04em;
}
.v1-score-of{font-size:15px;color:#94A0AE;font-variant-numeric:tabular-nums;}

.v1-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-top:22px;}
.v1-tile{background:var(--night-2);border:1px solid var(--night-3);border-radius:var(--r-md);padding:14px 16px;}
.v1-tile-l{font-size:12px;color:#94A0AE;}
.v1-tile-v{
  font-variant-numeric:tabular-nums;
  font-size:23px;font-weight:600;color:#E6E9ED;margin-top:4px;
}

.v1-weak-h{
  font-size:11px;letter-spacing:.1em;font-weight:600;text-transform:uppercase;
  color:#94A0AE;margin:26px 0 14px;
}
.v1-weak{display:flex;flex-direction:column;gap:14px;}
.v1-weak-row{display:grid;grid-template-columns:1fr auto;gap:6px 12px;align-items:baseline;}
.v1-weak-n{font-size:14px;color:#E6E9ED;}
.v1-weak-p{font-variant-numeric:tabular-nums;font-size:14px;font-weight:600;}
.v1-bar{grid-column:1/-1;height:5px;border-radius:999px;background:var(--night-3);overflow:hidden;}
.v1-bar i{display:block;height:100%;border-radius:999px;width:0;transition:width .7s var(--ease);}
.v1-bar.in i{width:var(--w);}
/* The weakest topic's percentage stays near-white rather than red. The only
   red in the approved palette is #D93843, which is about 3.9:1 on this near
   black panel — under the 4.5:1 that text has to clear. The bar carries the
   red instead, where 3:1 is the bar to clear and it passes. The number is
   still the thing that says 34%, so nothing depends on colour alone. */
.is-low .v1-weak-p{color:#E6E9ED;}   .is-low  .v1-bar i{background:#D93843;}
.is-mid .v1-weak-p{color:var(--amber);} .is-mid  .v1-bar i{background:var(--amber);}
.is-good .v1-weak-p{color:#00B696;}  .is-good .v1-bar i{background:#00B696;}

.v1-next{
  display:flex;align-items:center;justify-content:center;gap:8px;
  margin-top:24px;min-height:52px;border-radius:var(--r-md);
  background:var(--amber);color:var(--night);font-weight:700;font-size:15px;
}
.v1-next:hover{color:var(--night);filter:brightness(.96);}

@media (max-width:560px){
  .v1-report{padding:20px;}
  .v1-score{font-size:46px;}
  .v1-tiles{grid-template-columns:1fr;gap:8px;}
  .v1-tile{display:flex;justify-content:space-between;align-items:baseline;}
  .v1-tile-v{margin-top:0;}
}

/* ── WhatsApp capture band ──────────────────────────────────────────────── */
.v1-band{background:var(--night);color:#E6E9ED;}
.v1-band-in{
  display:grid;grid-template-columns:1fr 1fr;gap:40px;align-items:center;padding:40px 0;
}
.v1-band h2{font-size:clamp(20px,2.4vw,26px);font-weight:700;letter-spacing:-.02em;color:#fff;}
.v1-band p{color:#94A0AE;font-size:15px;margin-top:6px;}
.v1-form{display:flex;gap:10px;}
.v1-field{
  display:flex;align-items:center;flex:1;min-height:52px;
  background:var(--page);border-radius:var(--r-md);padding:0 6px 0 14px;gap:8px;
}
.v1-field span{color:var(--ink-3);font-size:15px;}
.v1-field input{flex:1;min-height:48px;border:0;outline:none;background:none;font-size:15px;}
.v1-ticks{display:flex;flex-wrap:wrap;gap:18px;margin-top:12px;font-size:13px;color:#94A0AE;}
.v1-ticks b{font-weight:500;}

@media (max-width:900px){ .v1-band-in{grid-template-columns:1fr;gap:22px;padding:32px 0;} }
@media (max-width:480px){ .v1-form{flex-direction:column;} .v1-form .v1-btn{width:100%;} }

/* ── sections ───────────────────────────────────────────────────────────── */
.v1-sec{padding:64px 0;}
.v1-sec-sunk{background:var(--shell);}
.v1-sec-head{display:flex;align-items:baseline;justify-content:space-between;gap:20px;margin-bottom:8px;}
.v1-h2{font-size:clamp(24px,3vw,34px);font-weight:800;letter-spacing:-.03em;color:var(--ink);}
.v1-lede{color:var(--ink-3);font-size:15px;margin-top:6px;}
.v1-more{font-weight:600;font-size:15px;white-space:nowrap;}

.v1-grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:28px;}
.v1-grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:28px;}
.v1-grid-2{display:grid;grid-template-columns:1fr 1fr;gap:40px;}

@media (max-width:900px){
  .v1-grid-3,.v1-grid-4,.v1-grid-2{grid-template-columns:1fr;gap:16px;}
  .v1-sec{padding:44px 0;}
}

/* Minimal by subtraction: no border at rest, just a hairline shadow to lift the
   card off the panel. The border comes back only on hover, which is when the
   card is actually being considered. Fewer lines on screen at rest means the
   content is what the eye lands on. */
.v1-card{
  background:var(--page);border:1px solid transparent;border-radius:var(--r-lg);
  padding:28px;box-shadow:var(--shadow-1);
  transition:transform .22s var(--ease),box-shadow .22s var(--ease),border-color .22s var(--ease);
}
.v1-card:hover{transform:translateY(-3px);box-shadow:var(--shadow-2);border-color:var(--line);}

/* ── the step cards ─────────────────────────────────────────────────────
   Colour arrives per step rather than being painted over the whole card: a
   tinted numeral and a rule that draws itself across the top as the card
   comes into view. The number is the label, so the colour is decoration and
   never the only thing distinguishing one step from the next. */
.v1-step{position:relative;overflow:hidden;}
.v1-step::before{
  content:'';position:absolute;top:0;left:0;height:3px;width:0;
  background:var(--step, var(--blue-fill));
  transition:width .6s var(--ease);transition-delay:var(--d,0ms);
}
.v1-step.in::before{width:100%;}
.v1-step .n{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:34px;height:26px;padding:0 9px;border-radius:999px;
  font-size:12px;font-weight:600;
  background:var(--step-bg, var(--blue-bg));color:var(--step-ink, var(--blue-deep));
}
.v1-step:nth-child(1){--step:var(--blue-fill);  --step-bg:var(--blue-bg);  --step-ink:var(--blue-deep);}
.v1-step:nth-child(2){--step:var(--amber);      --step-bg:var(--amber-bg); --step-ink:var(--amber-deep);}
.v1-step:nth-child(3){--step:var(--green);      --step-bg:var(--green-bg); --step-ink:var(--green-deep);}
.v1-step:nth-child(4){--step:var(--night);      --step-bg:var(--chip);     --step-ink:var(--ink);}

/* ── the exam cards ─────────────────────────────────────────────────────
   Each card carries one accent, declared once as --ac and then used by the
   top edge, the icon tile, the wash and the link. Adding a fourth exam family
   is three lines here, not a new set of rules for every part.

   Colour is decoration throughout. The exam name is the label and the state
   is a word — "Live now", "Coming soon" — so nothing on the card is carried
   by hue alone. */
.v1-exam{
  --ac:var(--line-3); --ac-bg:var(--chip); --ac-line:var(--line); --ac-deep:var(--ink);
  position:relative;overflow:hidden;isolation:isolate;
  display:flex;flex-direction:column;
  border-top:3px solid var(--ac);
}
.v1-exam.a-blue {--ac:var(--blue-fill);--ac-bg:var(--blue-bg); --ac-line:var(--blue-line); --ac-deep:var(--blue-deep);}
.v1-exam.a-amber{--ac:var(--amber);     --ac-bg:var(--amber-bg);--ac-line:var(--amber-line);--ac-deep:var(--amber-deep);}
.v1-exam.a-green{--ac:var(--green);     --ac-bg:var(--green-bg);--ac-line:var(--green-line);--ac-deep:var(--green-deep);}

/* Two layers of accent, both decorative, both under the text.

   The veil is a wash of the card's colour across the whole face, strongest at
   the top corner where the icon and the state pill are, fading out before it
   reaches the blurb. It is what makes the card read as belonging to its
   accent at rest instead of only when a cursor is on it.

   The wash is a soft disc on top of that, which is what gives the corner its
   depth. Both deepen together on hover. */
.v1-exam::after{
  content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:
    linear-gradient(158deg,
      color-mix(in srgb,var(--ac) 9%,transparent) 0%,
      color-mix(in srgb,var(--ac) 3%,transparent) 38%,
      transparent 72%);
  opacity:.85;transition:opacity .3s var(--ease);
}
.v1-exam:hover::after{opacity:1;}

.v1-exam-wash{
  position:absolute;top:-70px;right:-70px;width:220px;height:220px;z-index:-1;
  border-radius:50%;
  background:radial-gradient(circle,var(--ac-bg) 0%,transparent 70%);
  opacity:.8;transform:scale(.92);
  transition:opacity .35s var(--ease),transform .45s var(--ease);
}
.v1-exam:hover .v1-exam-wash{opacity:1;transform:scale(1.15);}

/* The card carries its accent as a halo at rest too, not only under a cursor.
   Kept faint — this is three cards side by side, and three loud halos is a
   traffic light rather than a highlight. */
.v1-exam{
  box-shadow:
    var(--shadow-1),
    0 8px 26px color-mix(in srgb,var(--ac) 11%,transparent);
}
/* The one that is actually on sale gets a little more of it. Colour is not
   carrying the message — "Live now" is written on the card — it is only
   making the eye land there first. */
.v1-exam.is-live{
  box-shadow:
    var(--shadow-1),
    0 10px 32px color-mix(in srgb,var(--ac) 20%,transparent);
}

.v1-exam-head{display:flex;align-items:center;justify-content:space-between;gap:12px;}
.v1-exam-tile{
  display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;border-radius:13px;
  background:var(--ac-bg);border:1px solid var(--ac-line);
  transition:transform .3s var(--spring),box-shadow .3s var(--ease);
}
.v1-exam-tile svg{stroke:var(--ac-deep);}
.v1-exam:hover .v1-exam-tile{transform:translateY(-2px) rotate(-4deg);box-shadow:var(--shadow-1);}

.v1-exam-state{
  display:inline-flex;align-items:center;gap:6px;
  padding:5px 11px;border-radius:999px;
  background:var(--chip);color:var(--ink-3);
  font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
}
.v1-exam-state.is-live{background:var(--green-bg);color:var(--green-deep);}
.v1-exam-dot{
  width:6px;height:6px;border-radius:50%;background:var(--green);
  box-shadow:0 0 0 0 rgba(0,182,150,.55);animation:pulseDot 2.2s ease-out infinite;
}
@keyframes pulseDot{
  0%{box-shadow:0 0 0 0 rgba(0,182,150,.55);}
  70%{box-shadow:0 0 0 7px rgba(0,182,150,0);}
  100%{box-shadow:0 0 0 0 rgba(0,182,150,0);}
}

.v1-exam-title{
  display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;
  font-size:23px;font-weight:800;letter-spacing:-.025em;margin-top:18px;
  transition:color .2s var(--ease);
}
.v1-exam:hover .v1-exam-title{color:var(--ac-deep);}
/* The full name, so "TNPSC" is not the only way in for someone who does not
   yet know the acronym. */
.v1-exam-name{font-size:13px;font-weight:600;letter-spacing:0;color:var(--ink-4);}
.v1-exam-blurb{color:var(--ink-3);font-size:14px;margin-top:7px;line-height:1.55;}
.v1-exam-line{
  display:inline-flex;align-self:flex-start;align-items:center;
  margin-top:12px;padding:6px 11px;border-radius:var(--r-sm);
  background:var(--sunk);border:1px solid var(--line-2);
  color:var(--ink-2);font-size:12.5px;font-weight:600;line-height:1.4;
}
.v1-exam.is-live .v1-exam-line{background:var(--ac-bg);border-color:var(--ac-line);color:var(--ac-deep);}

.v1-chips{display:flex;gap:8px;margin-top:16px;flex-wrap:wrap;}
/* The catalogue fills this. Until it answers there is nothing in it, and an
   empty row still reserving its margin leaves a hole in the middle of the
   card. */
.v1-chips:empty{display:none;}
.v1-chip{
  font-size:12px;font-variant-numeric:tabular-nums;
  background:var(--chip);color:var(--ink-2);border-radius:999px;padding:5px 11px;
}
.v1-chip-free{background:var(--green-bg);color:var(--green-deep);}

/* Pushed to the bottom edge so three cards of different text lengths still
   line their links up. */
.v1-exam-go{
  display:inline-flex;align-items:center;gap:8px;align-self:flex-start;
  margin-top:auto;padding-top:18px;
  font-weight:700;font-size:15px;min-height:44px;color:var(--ac-deep);
}
.v1-exam-arrow{display:inline-block;transition:transform .22s var(--spring);}
.v1-exam:hover .v1-exam-arrow{transform:translateX(5px);}

/* The link covers the card, so the whole thing is one target on a phone. The
   text stays the accessible name; this only widens where a tap counts. */
.v1-exam-go::after{content:'';position:absolute;inset:0;}

.v1-step h3{font-size:18px;font-weight:700;margin-top:14px;}
.v1-step p{color:var(--ink-3);font-size:14px;margin-top:6px;}

/* ── "What the report changed for them" ─────────────────────────────────
   The gain leads, in green, because a number is what a candidate scans for.
   The quote carries the reason. The attribution sits at the bottom of the
   card via margin-top:auto, so all three align however long the quotes run. */
.v1-voice{display:flex;flex-direction:column;gap:14px;}
.v1-voice-gain{font-weight:700;font-size:15px;color:var(--green-deep);}
.v1-voice-q{font-size:14.5px;line-height:1.7;color:var(--ink-2);text-wrap:pretty;}
.v1-voice-by{display:flex;align-items:center;gap:11px;margin-top:auto;}
.v1-voice-av{
  flex:0 0 auto;width:34px;height:34px;border-radius:999px;
  display:flex;align-items:center;justify-content:center;
  font-weight:700;font-size:13px;color:#FFFFFF;background:var(--blue-fill);
}
.v1-voice.a-green .v1-voice-av{background:var(--green);}
.v1-voice.a-night .v1-voice-av{background:var(--night);}
.v1-voice-name{font-weight:600;font-size:13.5px;color:var(--ink);}
.v1-voice-ctx{font-weight:500;font-size:12px;color:var(--ink-4);}

/* On every card while the grid is showing its sample state, so a card that
   travels alone — a screenshot, a crop — still says what it is. */
.v1-voice{position:relative;}
.v1-voice-stamp{
  position:absolute;top:12px;right:12px;
  padding:3px 9px;border-radius:999px;
  background:var(--amber-bg);border:1px solid var(--amber-line);
  color:var(--amber-deep);
  font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
}
.v1-voice-stamp + .v1-voice-gain{padding-right:72px;}

/* Above the grid whenever the cards below it are not real people. */
.v1-sample-note{
  margin-top:14px;padding:10px 14px;border-radius:var(--r-sm);
  background:var(--amber-bg);border:1px solid var(--amber-line);
  color:var(--amber-deep);font-size:13px;font-weight:600;
}

/* ── free strip: current affairs + jobs ─────────────────────────────────── */
.v1-row{
  display:flex;align-items:center;gap:14px;justify-content:space-between;
  background:var(--page);border:1px solid var(--line);border-radius:var(--r-md);
  padding:14px 16px;margin-top:10px;min-height:44px;
}
.v1-row:hover{border-color:var(--line-3);}
.v1-row-kick{
  font-size:11px;letter-spacing:.07em;font-weight:600;text-transform:uppercase;
  color:var(--ink-4);
}
.v1-row-t{font-weight:600;font-size:15px;color:var(--ink);margin-top:3px;}
.v1-row-m{font-size:13px;color:var(--ink-3);margin-top:3px;}
.v1-pill{
  font-size:12px;font-variant-numeric:tabular-nums;
  border-radius:999px;padding:5px 10px;white-space:nowrap;
}
.v1-pill-warn{background:var(--amber-bg);color:var(--amber-deep);}
.v1-pill-soon{background:var(--red-bg);color:var(--red);}
.v1-pill-new{background:var(--green-bg);color:var(--green-deep);}
.v1-badge-free{
  font-size:11px;letter-spacing:.07em;font-weight:600;text-transform:uppercase;
  background:var(--green-bg);color:var(--green-deep);border-radius:999px;padding:5px 11px;
}

/* The empty state is a first-class screen here, not an afterthought: until a
   person publishes a real job or a real article, this is what visitors see. */
.v1-empty{
  border:1px dashed var(--line-3);border-radius:var(--r-md);
  padding:22px;color:var(--ink-3);font-size:14px;background:var(--sunk);margin-top:10px;
}

/* ── closing band and footer ────────────────────────────────────────────── */
.v1-close{background:var(--night);color:#E6E9ED;}
.v1-close-in{display:flex;align-items:center;justify-content:space-between;gap:28px;padding:44px 0;flex-wrap:wrap;}
.v1-close h2{font-size:clamp(22px,2.8vw,30px);font-weight:800;letter-spacing:-.025em;color:#fff;}
.v1-close p{color:#94A0AE;margin-top:8px;font-size:15px;}

.v1-foot{background:var(--night-2);color:#94A0AE;padding:48px 0 28px;}
.v1-foot-grid{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:32px;}
.v1-foot h4{
  font-size:11px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--amber);margin-bottom:14px;font-weight:600;
}
.v1-foot a{display:block;color:#94A0AE;font-size:14px;padding:6px 0;}
.v1-foot a:hover{color:#fff;}
.v1-foot-tag{font-size:14px;margin-top:14px;max-width:30ch;}
.v1-foot-end{
  display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;
  border-top:1px solid var(--night-3);margin-top:36px;padding-top:20px;font-size:13px;
}
.v1-foot-end nav{display:flex;gap:20px;flex-wrap:wrap;}

@media (max-width:900px){ .v1-foot-grid{grid-template-columns:1fr 1fr;gap:24px;} }
@media (max-width:560px){ .v1-foot-grid{grid-template-columns:1fr;} }

/* ── motion, end to end ─────────────────────────────────────────────────
   Everything below is transform and opacity only, so none of it triggers
   layout. The whole layer collapses under prefers-reduced-motion at the
   bottom of this file. */

/* Nav: a rule that grows from the left rather than a colour change, so the
   hover reads without the label shifting weight. */
.v1-nav a{position:relative;}
.v1-nav a::after{
  content:'';position:absolute;left:0;right:0;bottom:-6px;height:2px;
  background:currentColor;border-radius:2px;
  transform:scaleX(0);transform-origin:left;
  transition:transform .24s var(--ease);
}
.v1-nav a:hover::after,.v1-nav a:focus-visible::after{transform:scaleX(1);}
@media (max-width:900px){ .v1-nav a::after{display:none;} }

/* The mark settles in rather than appearing. 380ms, once, on load. */
.v1-logo-img{animation:logo-in .38s var(--ease) both;}
@keyframes logo-in{from{opacity:0;transform:translateY(-4px) scale(.98);}to{opacity:1;transform:none;}}

/* Buttons lift toward the pointer and press back down. */
.v1-btn-primary:hover,.v1-btn-green:hover,.v1-btn-amber:hover{transform:translateY(-1px);}

/* List rows slide a little on hover, which is cheaper to read than a colour
   change and says "this is a link" on a touch device that has no hover at all
   because the transform also plays on :active. */
.v1-row{transition:transform .2s var(--ease),border-color .2s var(--ease),box-shadow .2s var(--ease);}
.v1-row:hover,.v1-row:active{transform:translateX(3px);box-shadow:var(--shadow-1);}

/* Exam cards lose their resting border too; the coloured top edge is the only
   line they need. */
.v1-exam{border-left:0;border-right:0;border-bottom:0;}
/* The shared card hover repaints every border; the exam card only ever has a
   top one, and it keeps its accent. */
.v1-exam:hover{border-color:transparent;border-top-color:var(--ac);}
/* A deeper, accent-tinted lift than the plain card gets. */
.v1-exam:hover{
  transform:translateY(-5px);
  box-shadow:
    var(--shadow-1),
    0 16px 40px color-mix(in srgb,var(--ac) 30%,transparent);
}

/* The arrow nudges forward and breathes. The two run on different periods —
   1.9s and 2.6s — so they drift against each other instead of locking into
   one mechanical beat. */
.v1-jump-arrow{animation:nudge 1.9s var(--ease) infinite, glow 2.6s ease-in-out infinite;}
@keyframes nudge{0%,62%,100%{transform:translateX(0);}76%{transform:translateX(6px);}}
@keyframes glow{
  0%,100%{
    text-shadow:
      0 0 8px  rgba(var(--amber-rgb), .40),
      0 0 20px rgba(var(--amber-rgb), .20);
  }
  50%{
    text-shadow:
      0 0 16px rgba(var(--amber-rgb), .80),
      0 0 40px rgba(var(--amber-rgb), .45);
  }
}

/* The eyebrow pill breathes once on entry so the eye starts at the top left. */
.v1-eyebrow{animation:pill-in .5s var(--spring) both;}
@keyframes pill-in{from{opacity:0;transform:scale(.92);}to{opacity:1;transform:none;}}

/* ── motion ─────────────────────────────────────────────────────────────── */
/* Nothing is hidden by default in a way that a JavaScript failure could make
   permanent: .rv only becomes invisible once JS has confirmed it is running by
   setting .js on the root. */
.js .rv{opacity:0;transform:translateY(14px);}
.js .rv.in{opacity:1;transform:none;transition:opacity .42s var(--ease),transform .42s var(--ease);transition-delay:var(--d,0ms);}

@media (prefers-reduced-motion:reduce){
  .js .rv,.js .rv.in{opacity:1;transform:none;transition:none;}
  .v1-bar i,.v1-cut-fill{transition:none;}
  .v1-card:hover,.v1-row:hover,.v1-row:active{transform:none;}
  .v1-btn-primary:hover,.v1-btn-green:hover,.v1-btn-amber:hover{transform:none;}
  /* Anything that loops must stop entirely, not merely shorten. A repeating
     nudge is exactly the kind of motion this setting exists to switch off. */
  .v1-jump-arrow,.v1-eyebrow,.v1-logo-img{animation:none;}
  /* The ticker still rotates — the content changing is the point — but it
     cuts instead of sliding. home.js drops the classes; this is the belt to
     that braces. */
  .v1-rev-enter,.v1-rev-exit{animation:none;}
  .v1-rev-exit{display:none;}
  .v1-step::before{transition:none;width:100%;}
  .v1-nav a::after{transition:none;}
}

/* The stagger is a flourish; under reduced motion the panel simply is. */
@media (prefers-reduced-motion:reduce){
  .v1-drop-item{transition-delay:0s!important;}
}

/* ── the phone, deliberately ─────────────────────────────────────────────
   This audience is on a mid-range Android over mobile data, so the small
   screen is the common case rather than the exception. Everything below was
   written against that, and each rule is here because something was wrong
   without it rather than as a precaution.

   The breakpoints already in this file stay where they are: 900px is where
   the header becomes a menu, 780 and 520 thin the offer bar, 560 is the
   phone. What was missing was the band between a phone and a laptop, and a
   handful of defects that only show up under a thumb. */

/* Nothing may push the page sideways. A grid or flex child defaults to
   min-width:auto, which means a long unbroken string -- a URL in a review, a
   Tamil compound with no space in it -- makes the whole page scrollable
   horizontally and every section a few pixels too wide. */
.v1-hero-grid > *,
.v1-grid-2 > *, .v1-grid-3 > *, .v1-grid-4 > *,
.v1-band-in > *, .v1-foot-grid > * { min-width:0; }

img, svg, video { max-width:100%; }

/* Long words break rather than overflow their card. */
.v1-h1, .v1-h2, .v1-sub, .v1-lede, .v1-card p, .v1-weak-n { overflow-wrap:anywhere; }

/* ── tablets and small laptops ─────────────────────────────────────────
   Four cards went straight from four across to one, so a 800px screen --
   an iPad held upright, and the cheap Android tablets this audience shares
   at home -- got a single column of enormous cards with the page three
   screens longer than it needed to be. Two across is the honest middle. */
@media (min-width:561px) and (max-width:900px){
  .v1-grid-3, .v1-grid-4 { grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; }
  .v1-grid-2 { grid-template-columns:1fr; }
}

/* A heading and its "see all" link share one line until they cannot. Without
   the wrap the link was squeezed to two or three characters per line beside a
   long heading. */
.v1-sec-head { flex-wrap:wrap; }
.v1-sec-head .v1-more { white-space:nowrap; }

@media (max-width:560px){
  /* iOS zooms the whole page in when a focused input is under 16px, and then
     leaves it zoomed. The WhatsApp field was 15px, so tapping it shifted the
     entire layout sideways -- the single most obvious "this site is not made
     for a phone" moment on the site. */
  .v1-field input, .v1-field span { font-size:16px; }

  /* A footer link was a 14px line with 6px of padding: a 32px target, under
     the 44px a thumb needs, stacked against its neighbours. */
  .v1-foot a { padding:11px 0; }
  .v1-foot-grid { gap:8px 24px; }

  /* Sections were 64px top and bottom, which on a 360px screen is most of a
     viewport spent on nothing. */
  .v1-sec { padding:40px 0; }
  .v1-hero-grid { padding:32px 0 40px; gap:28px; }

  /* Two buttons side by side at 360px left each of them too narrow to read.
     Full width, stacked, in the order they should be pressed. */
  .v1-cta-row { flex-direction:column; align-items:stretch; }
  .v1-cta-row .v1-btn { width:100%; }

  /* The card is the product. It keeps its numbers legible before it keeps
     its proportions. */
  .v1-jump { gap:10px; }
  .v1-jump-col .n { font-size:34px; }
  .v1-jump-to .n { font-size:42px; }
  .v1-reviews-port { height:auto; min-height:84px; }
  .v1-proof-quote { gap:10px; }
  .v1-avatar { width:36px; height:36px; font-size:13px; }

  /* Four steps numbered 01 to 04 do not need 28px of padding each on a phone. */
  .v1-card { padding:20px; }
  .v1-step .n { font-size:13px; }
}

/* ── the smallest screens still sold in volume ─────────────────────────
   360x640 is not an edge case in Tamil Nadu; it is the modal device. At this
   width the header carries the mark, one button and the menu, and the button
   loses its padding before it loses its label. */
@media (max-width:380px){
  .v1-head-in { gap:12px; }
  .v1-head-end .v1-btn { padding:0 12px; font-size:14px; }
  .v1-logo-img { height:28px; }
  .v1-h1 { letter-spacing:-.02em; }
}

/* ── a feature list that reads as a list ───────────────────────────────
   .v1-ticks is a wrapping row, which is right for three short promises under
   a form and wrong for five lines describing what a season includes: the
   lines ran together across the card and no line began where the eye
   expected. This is the vertical form of the same idea, with the tick as a
   marker so the list reads as inclusions rather than as prose. */
.v1-includes { display:flex; flex-direction:column; gap:10px; }
.v1-includes p {
  position:relative; padding-left:26px; font-size:15px; color:var(--ink-2);
}
.v1-includes p::before {
  content:''; position:absolute; left:0; top:.45em;
  width:14px; height:8px; border-left:2px solid var(--green);
  border-bottom:2px solid var(--green); transform:rotate(-45deg);
}

/* ── the bridge ─────────────────────────────────────────────────────────
   Seven pages came back from the old site: jobs, contact, privacy, terms,
   refund, free-tests and batches. They now wear the v1 header and footer, but
   their content is still written in the old markup -- .wrap, .card, .sub,
   .eyebrow, .note and the rest.

   This section restyles that markup to the v1 system rather than rewriting
   the pages. Two reasons, and the second is the real one:

     1. The markup is fine. What differed was scale, spacing and weight, and
        that is a stylesheet's job.
     2. Four of those pages are the privacy notice, the terms, the refund
        policy and the contact page. Their text is a legal undertaking to the
        people who pay us, and Razorpay requires it to be reachable and
        accurate. Rewriting the markup around it means touching it, and a
        clumsy find-and-replace inside a refund policy is a much more
        expensive mistake than a heading two pixels off.

   Everything is scoped to body.v1-page, so the exam engine and the admin
   console -- which still use app.css deliberately -- are untouched. */

/* The old shell used a 32px gutter and a wider column; the v1 wrap is 20px
   and 16 on a phone. Matching them stops the content shifting sideways as a
   visitor moves between an old page and a new one. */
.v1-page .wrap{max-width:1200px;padding:0 20px;}
@media (max-width:560px){ .v1-page .wrap{padding:0 16px;} }

.v1-page .sec{padding:64px 0;}
@media (max-width:560px){ .v1-page .sec{padding:40px 0;} }

/* Type, on the v1 scale. The old sizes were set in rem against a 16px root
   and ran noticeably smaller than the new pages beside them. */
.v1-page main h1{
  font-size:clamp(30px,4.4vw,46px);line-height:1.08;
  letter-spacing:-.03em;font-weight:800;color:var(--ink);
}
.v1-page main h2{
  font-size:clamp(22px,2.6vw,30px);line-height:1.18;
  letter-spacing:-.025em;font-weight:800;color:var(--ink);
}
.v1-page main h3{font-size:18px;line-height:1.35;font-weight:700;color:var(--ink);}
.v1-page .sub,.v1-page .lede{font-size:16px;line-height:1.65;color:var(--ink-3);}
.v1-page .doc p,.v1-page .doc li{font-size:15.5px;line-height:1.7;color:var(--ink-2);}

/* The card, minimal by subtraction: no border at rest, a hairline shadow to
   lift it off the panel, and the border back on hover -- the same bargain the
   v1 cards make, so a grid of them reads identically on either kind of page. */
.v1-page .card{
  border-color:transparent;border-radius:var(--r-lg);padding:28px;
  box-shadow:var(--shadow-1);
  transition:transform .22s var(--ease),box-shadow .22s var(--ease),border-color .22s var(--ease);
}
.v1-page .card:hover{transform:translateY(-3px);box-shadow:var(--shadow-2);border-color:var(--line);}
@media (max-width:560px){ .v1-page .card{padding:20px;} }

/* The old .btn was already 46px tall, comfortably past the 44 a thumb needs,
   so only the weight and the radius are brought into line with v1. Lowering
   it to match would have been a change for the worse dressed as consistency. */
.v1-page .btn{ border-radius:var(--r-md); font-weight:600; font-size:15px; }

/* The eyebrow was a bare uppercase line; in v1 it is a pill, and it is the
   first thing the eye lands on above a heading. */
.v1-page .eyebrow{
  display:inline-flex;align-items:center;gap:8px;
  background:var(--green-bg);color:var(--green-deep);
  border:1px solid var(--green-line);border-radius:999px;
  padding:7px 15px;font-size:12px;letter-spacing:.08em;
  text-transform:uppercase;font-weight:600;
}

.v1-page .note{border-radius:var(--r-md);padding:18px 20px;font-size:15px;line-height:1.6;}
.v1-page .tag{border-radius:999px;padding:5px 11px;font-size:11px;letter-spacing:.07em;}

/* A long policy reads better in a narrower column than the page allows. */
.v1-page .doc{max-width:46em;}
.v1-page .doc h2{margin:40px 0 12px;}

/* Tables in the policies: they carry retention periods and contact details,
   so they have to survive a 360px screen rather than push the page sideways. */
.v1-page .doc table{width:100%;border-collapse:collapse;display:block;overflow-x:auto;}
@media (max-width:560px){
  .v1-page .doc td,.v1-page .doc th{padding:9px 10px;font-size:14px;}
}

/* ── measured, not guessed ──────────────────────────────────────────────
   Everything below came out of a real device-emulation pass over twelve
   pages at five widths -- 360, 390, 768, 820 and 1280 -- rather than from
   reading the stylesheet and imagining it. That run found no horizontal
   overflow anywhere, which is the failure people actually notice, and two
   classes of defect that are easy to miss by eye and impossible to miss
   with a thumb. */

/* TAP TARGETS. The "see more" links were 18 to 24 pixels tall. They are
   standalone navigation -- "All test series", "See the price", "Monthly
   compilations" -- not links inside a sentence, so the 44px minimum applies
   to them in full, and at 24px they were roughly half of it.

   Links inside a sentence are deliberately left alone: "read the refund
   policy" cannot be 44px tall without wrecking the line it sits in, and the
   guideline exempts them for exactly that reason. The fix is for controls,
   not for prose. */
@media (hover:none), (max-width:900px){
  .v1-more{
    display:inline-flex;align-items:center;min-height:44px;
  }
  /* The logo is a link to the homepage and was a 28px image. */
  .v1-logo{ display:inline-flex;align-items:center;min-height:44px; }
  .v1-page .doc a[href$=".html"]:not(.btn):not(.v1-more){ padding:2px 0; }
}

/* TEXT SIZE. A handful of labels were set at 11px: the report card's kicker,
   the review ticker's label and count, the "where the marks went" heading,
   and the job tags. At arm's length on a 360px screen that is not small, it
   is unreadable, and every one of them is a label whose whole job is to say
   what the number beside it means. 12px is the floor. */
@media (max-width:900px){
  .v1-report-kicker,
  .v1-reviews-label,
  .v1-reviews-count,
  .v1-weak-h,
  .v1-proof-pill,
  .v1-row-kick,
  .v1-pill, .v1-pill-new, .v1-pill-soon, .v1-pill-warn,
  .v1-badge-free,
  .v1-foot h3, .v1-foot h4,
  .v1-page .tag,
  .v1-page .eyebrow{ font-size:12px; }
}
