/* ===========================================================================
   ATI — Apple Trade In Japan, operated by PCS Wireless Japan K.K.
   Tokens exported from Figma YIsOBNB42fuGjQfQ1K84nI (run ds-ati-2026-09-06).
   Layout follows the "Design" section pattern (2251:7738).

   Single theme: the colour collection is Light-only by design decision, so
   every colour is painted explicitly rather than inherited.
   ======================================================================== */
:root{
  --brand-50:#f1f4fd;--brand-100:#e0e5fb;--brand-500:#4964df;--brand-600:#314cc4;--brand-700:#2a3f9d;
  --n-50:#fafafa;--n-100:#f2f2f2;--n-200:#e0e0e0;--n-300:#bdbdbd;--n-400:#a0a0a0;
  --n-500:#828282;--n-600:#666;--n-700:#4f4f4f;--n-800:#333;--n-900:#1a1a1a;
  --amber-300:#f0be72;--amber-500:#b26a00;--red-500:#c62828;--red-700:#8e1d1d;

  /* Off-system values hardcoded in the Figma layers, not bound to variables */
  --step-green:#3eb400;        /* completed node + progress fill */
  --branch-idle:#ededed;       /* untravelled connector */
  /* Quote card ground: cyan/100 (#E1F0FA) at 75%. Border is color/border/focus
     (= brand/500 #4964DF), 3px, dashed 8/4 in Figma — CSS cannot set a border
     dash length, so the browser's own dash pattern is used. */
  --upload-bg:#f0f6ff;      /* file-upload card ground; brand/50 is #F1F4FD */
  --upload-border:#5987ef;  /* file-upload card border; brand/400 is #6F85E7 */
  --quote-bg:rgba(225,240,250,.75);
  --quote-border:var(--brand-500);
  --alert-bg:#fefce8;

  --fs-xs:12px;--fs-sm:14px;--fs-md:16px;--fs-lg:18px;--fs-xl:20px;
  --fs-2xl:24px;--fs-3xl:30px;--fs-4xl:36px;--fs-5xl:48px;
  --lh-xs:16px;--lh-sm:20px;--lh-md:24px;--lh-lg:28px;--lh-2xl:32px;
  --lh-3xl:38px;--lh-4xl:44px;--lh-5xl:56px;
  --sp-xs:4px;--sp-sm:8px;--sp-md:12px;--sp-lg:16px;--sp-xl:24px;--sp-2xl:32px;
  --sp-button-y:var(--sp-md); /* component token, aliased to the scale */
  --sp-field-y:10px;          /* off-scale literal, shared by Input + Dropdown */
  --dissolve:400ms;   /* fade out then fade in, so the felt duration is ~800ms.
                         Figma's own convention is 300ms; slowed deliberately. */
  --r-sm:4px;--r-md:6px;--r-card:8px;--r-quote:16px;--r-full:9999px;
  --sans:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Arial,sans-serif;
  --jp:"Noto Sans JP",var(--sans);
}
*,*::before,*::after{box-sizing:border-box}
body{margin:0;background:var(--n-50);color:var(--n-800);font-family:var(--sans);
  font-size:var(--fs-md);line-height:var(--lh-md);letter-spacing:-.01em;-webkit-font-smoothing:antialiased}
:where(a,button,input,select,[tabindex]):focus-visible{outline:2px solid var(--brand-500);outline-offset:2px;border-radius:var(--r-sm)}
@media (prefers-reduced-motion:reduce){*{animation-duration:.01ms!important;transition-duration:.01ms!important}}
img{display:block;max-width:100%}
/* All spacing here comes from flex/grid gap, never from <p> margins. Zeroing
   them matches Tailwind's preflight (which the Next.js build gets for free)
   and prevents the browser default from inflating a measured gap. */
#app p,#app h1,#app h2,#app h3,#app ol,#app ul{margin:0}
/* overflow-x:CLIP, not hidden. `hidden` turns body into a scroll container,
   which makes position:sticky resolve against body instead of the viewport —
   the sticky header would silently stop sticking. `clip` prevents sideways
   scroll without creating that container. */
html,body{max-width:100%;overflow-x:clip}
/* Wide content scrolls inside its own container, never the page body */
.scroll-x{overflow-x:auto;-webkit-overflow-scrolling:touch}

/* Type — the 20 Figma text styles, display/heading stepping down on small screens */
.t-display{font-size:var(--fs-3xl);line-height:var(--lh-3xl);font-weight:700;letter-spacing:-.02em;text-wrap:balance;margin:0}
.t-display-md{font-size:var(--fs-4xl);line-height:var(--lh-4xl);font-weight:700;letter-spacing:-.02em;margin:0}
.t-h1{font-size:var(--fs-2xl);line-height:var(--lh-2xl);font-weight:600;letter-spacing:-.015em;text-wrap:balance;margin:0}
/* Confirmation's heading is H1 size at Bold weight, not Semi Bold */
.t-h1-bold{font-size:var(--fs-2xl);line-height:var(--lh-2xl);font-weight:700;letter-spacing:-.015em;text-wrap:balance;margin:0}
.t-h2{font-size:var(--fs-xl);line-height:var(--lh-xl,28px);font-weight:600;letter-spacing:-.015em;margin:0}
.t-h3{font-size:var(--fs-lg);line-height:var(--lh-lg);font-weight:600;letter-spacing:-.01em;margin:0}
.t-h4{font-size:var(--fs-lg);line-height:var(--lh-md);font-weight:600;letter-spacing:-.01em;margin:0}
/* Card description: Heading/H4 size at Regular weight — not a heading */
.t-card-body{font-size:var(--fs-lg);line-height:var(--lh-md);font-weight:400;letter-spacing:-.01em;margin:0}
.t-body-lg{font-size:var(--fs-md);line-height:var(--lh-md);margin:0}
.t-body{font-size:var(--fs-md);line-height:var(--lh-md);margin:0}
.t-label-lg{font-size:var(--fs-md);line-height:var(--lh-md);font-weight:500;letter-spacing:-.01em;margin:0}
.t-label-lg-s{font-size:var(--fs-md);line-height:var(--lh-md);font-weight:600;letter-spacing:-.01em;margin:0}
.t-label-md{font-size:var(--fs-sm);line-height:var(--lh-sm);font-weight:500;letter-spacing:-.005em;margin:0}
.t-label-md-s{font-size:var(--fs-sm);line-height:var(--lh-sm);font-weight:600;letter-spacing:-.005em;margin:0}
.t-label-sm{font-size:var(--fs-xs);line-height:var(--lh-xs);font-weight:500;margin:0}
.t-label-sm-s{font-size:var(--fs-xs);line-height:var(--lh-xs);font-weight:600;margin:0}
.t-sm{font-size:var(--fs-sm);line-height:var(--lh-sm);letter-spacing:-.005em;margin:0}
.t-sm-strong{font-size:var(--fs-sm);line-height:var(--lh-sm);font-weight:600;letter-spacing:-.005em;margin:0}
.t-body-strong{font-size:var(--fs-md);line-height:var(--lh-md);font-weight:600;letter-spacing:-.01em;margin:0}
.t-caption{font-size:var(--fs-xs);line-height:var(--lh-xs);margin:0}
@media (min-width:768px){
  .t-display{font-size:var(--fs-4xl);line-height:var(--lh-4xl)}
  .t-display-md{font-size:var(--fs-5xl);line-height:var(--lh-5xl)}
  .t-h1,.t-h1-bold{font-size:var(--fs-3xl);line-height:var(--lh-3xl)}
  .t-h2{font-size:var(--fs-2xl);line-height:var(--lh-2xl)}
  .t-h3{font-size:var(--fs-xl);line-height:var(--lh-lg)}   /* Heading/H3 = 20/28 */
  .t-body-lg{font-size:var(--fs-lg);line-height:var(--lh-lg)}
}
.muted{color:var(--n-500)}.tert{color:var(--n-600)}.faint{color:var(--n-400)}
.ink{color:var(--n-900)}.brandtext{color:var(--brand-600)}
/* Tabular figures. Inter's tnum digits are visibly different letterforms —
   flat-topped 1 with a foot serif, uniform advances — so use this only
   where digits must align between rows or a value updates in place.
   NOT on reference IDs (QT-…, TRADE-…), which read as prose. */
.num{font-variant-numeric:tabular-nums}

/* Header — px80 py24 on desktop, white on the neutral/50 page */
/* Sticky header that compacts on scroll.
   NOT in the Figma design — the frames show a static 73px header. Authored to
   give long screens (Personal Details, Trade-in Kit) more room.

   The state class lives on <html>, not on .hdr: render() rebuilds the header
   on every state change, so a class set directly on it would be wiped. */
.hdr{background:#fff;border-bottom:1px solid var(--n-200);width:100%;position:sticky;top:0;z-index:20;
  transition:box-shadow .2s ease}
.hdr-in{display:flex;align-items:center;justify-content:space-between;padding:16px;gap:16px;
  transition:padding .2s ease}
@media (min-width:768px){.hdr-in{padding:24px 40px}}
@media (min-width:1024px){.hdr-in{padding:24px 80px}}

/* Compact: 73px -> 45px, with a shadow to lift it off the content it overlaps */
.is-scrolled .hdr{box-shadow:0 1px 4px rgba(0,0,0,.06)}
.is-scrolled .hdr-in{padding:8px 16px}
@media (min-width:768px){.is-scrolled .hdr-in{padding:10px 40px}}
@media (min-width:1024px){.is-scrolled .hdr-in{padding:10px 80px}}
/* The lockup shrinks a touch so the compaction reads as deliberate */
.lockup img{transition:width .2s ease,height .2s ease}
.is-scrolled .lockup img{width:97px;height:20px}
/* Clickable: returns to the homepage. No hover treatment, matching the other
   controls; :focus-visible still gets the global ring.
   Gap stays at 10 — the Figma lockup keeps 10 between the mark and the
   wordmark now that the divider between them is gone (measured: 116 + 10 + 40
   = 166 wide). */
.lockup{display:flex;align-items:center;gap:10px;
  background:none;border:0;padding:0;cursor:pointer;font-family:inherit;text-align:left}
.lockup img{height:24px;width:116px}
.lockup .title{font-size:12px;line-height:16px;font-weight:600;color:var(--n-900);white-space:nowrap}
@media (max-width:359px){.lockup .title{display:none}}
.lang{font-family:var(--jp);font-size:12px;line-height:16px;font-weight:500;color:var(--n-500);
  letter-spacing:-.03em;background:none;border:0;cursor:pointer;padding:4px}
.lang:hover{color:var(--n-800)}

/* Homepage: from tablet up, the content column takes the height left below the
   header and centres its children as a group, so the gaps between hero, cards
   and footer are preserved and the whole block sits in the middle of any screen.
   Mobile is left alone — the stacked cards fill the viewport there, so it keeps
   the normal top-aligned scroll. Below 760px tall there is no slack to centre
   into and centring would push the top of the block out of reach, so that
   reverts to top-aligned flow too. */
@media (min-width:768px){
  /* margin-block:auto, not flex:1 + justify-content:center. Auto margins split
     whatever height is left over below the header, so the block sits in the
     middle of any window — and when the content is taller than the window they
     collapse to 0 instead of pushing the top out of reach. That removes the
     max-height breakpoint this used to need. */
  .page--home .content{margin-block:auto}
  /* The column's padding is asymmetric for top-aligned flow (pt 40 / pb 60), and
     centring the padded box would leave 20px more air below the footer than above
     the hero. On home the bottom padding is only slack, so match it to the top and
     the block reads as optically centred. */
  .page--home .content{padding-bottom:32px}
}
@media (min-width:1024px){ .page--home .content{padding-bottom:40px} }

/* Ambient particle field — homepage and the final confirmation only.
   Both are bookends: nothing to read closely, nothing to type, no value or
   deadline to misread. Every task screen in between stays flat.

   The canvas is a fixed sibling of #app, not a child: render() replaces #app's
   innerHTML on every state change, which would destroy the canvas and restart
   the field on each keystroke. It is painted behind #app and never captures a
   pointer. Opacity is what fades it in and out per screen, so the field keeps
   drifting underneath instead of restarting when you return to home. */
/* The field is masked out where the content sits. In the reference every text
   block is on a solid card and the dots only ever appear outside it; our
   confirmation copy has no fill of its own, so without this the dots land
   between the letters. JS keeps the hole on the measured content box. */
#amb{position:fixed;inset:0;width:100%;height:100%;z-index:0;pointer-events:none;
  opacity:0;transition:opacity .8s ease;
  --amb-x:50%;--amb-y:44%;--amb-rx:40%;--amb-ry:30%;
  -webkit-mask-image:radial-gradient(var(--amb-rx) var(--amb-ry) at var(--amb-x) var(--amb-y),
    transparent 0 62%,#000 100%);
  mask-image:radial-gradient(var(--amb-rx) var(--amb-ry) at var(--amb-x) var(--amb-y),
    transparent 0 62%,#000 100%)}
#amb.is-on{opacity:1}
#app{position:relative;z-index:1}
/* A static tint radiating from behind the content, the way the reference does
   it — all of the motion is carried by the dots, none by the wash. */
.page--amb{position:relative}
.page--amb::before{content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(62% 46% at 50% 42%,rgba(73,100,223,.07) 0%,transparent 70%)}

/* Content column — gap 60, px 80, pt 40, pb 60 */
.page{display:flex;flex-direction:column;align-items:center;min-height:100vh}
/* 1280 cap + auto margins = a 1120px inner column after the 80px gutters,
   matching the Figma frame. Applies to every screen, not just the homepage. */
.content{width:100%;min-width:0;max-width:1280px;margin-inline:auto;
  display:flex;flex-direction:column;align-items:center;gap:32px;padding:24px 16px 32px}
@media (min-width:768px){.content{gap:40px;padding:32px 40px 40px}}
@media (min-width:1024px){.content{gap:60px;padding:40px 80px 60px}}
.wrap{width:100%;min-width:0;max-width:1120px;display:flex;flex-direction:column;align-items:center;gap:inherit}
.wrap-home{gap:32px}
@media (min-width:768px){.wrap-home{gap:56px}}
@media (min-width:1024px){.wrap-home{gap:80px}}

/* Stepper — 9 nodes, 25x4 connectors */
.step-mob{display:flex;flex-direction:column;gap:8px;width:100%}
.step-full{display:none}
@media (min-width:768px){.step-mob{display:none}
  /* Hugs its content (~430px) and sits at the start of the column, matching
     the Figma component. Growing the li spread the nodes across 1120px. */
  .step-full{display:flex;align-items:center;list-style:none;margin:0;padding:0;
    width:auto;flex:none;align-self:flex-start}}
.step-full li{display:flex;align-items:center}
/* 31 wide with -3 margins either side: lays out as 25, but the line runs 3px
   under the node on each side. The idle node's asset is 25 wide inside a 30px
   box, so its built-in stub starts 2.5px in and its circle ends 3px short of the
   box — which left a white gap in the connector at both ends. 3 rather than 2.5
   because pulling the circles 0.5 inside their viewBox (to stop them being
   clipped) moved that right edge in by the same amount. The node is positioned,
   so it paints over the overlap wherever the circle fills its box. */
.branch{width:31px;height:4px;flex:none;margin-inline:-3px}
.node{position:relative;width:30px;height:30px;display:flex;align-items:center;justify-content:center;flex:none}
.node img{position:absolute;inset:0;width:100%;height:100%}
.node.idle img{width:25px;left:2.5px}
.node span{position:relative;font-size:var(--fs-md);line-height:var(--lh-md);font-weight:600;color:#fff;letter-spacing:-.01em}
.mob-track{height:4px;width:100%;border-radius:var(--r-full);background:var(--branch-idle);overflow:hidden}
.mob-fill{height:100%;border-radius:var(--r-full);background:var(--step-green);transition:width .3s}

/* stepper + header block: gap 16, title gap 4, left aligned across 1120 */
.sh{display:flex;flex-direction:column;align-items:flex-start;gap:16px;width:100%}
.sh-title{display:flex;flex-direction:column;gap:4px;width:100%}

/* Cards */
.card{background:#fff;border:1px solid var(--n-200);border-radius:var(--r-card);
  box-shadow:0 2px 3px rgba(0,0,0,.08)}
.grid3{display:grid;gap:16px;width:100%;min-width:0}
@media (min-width:768px){.grid3{grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}}
@media (min-width:1024px){.grid3{grid-template-columns:repeat(3,minmax(0,1fr));gap:40px}}
/* Cards stretch to the tallest in the row — grid does this by default, so the
   fix was removing the align-self that was overriding it. */
.entry{display:flex;align-items:flex-start;padding:24px;text-align:left;text-decoration:none;
  font-family:inherit;cursor:pointer;background:#fff;border:1px solid var(--n-200);
  border-radius:var(--r-card);box-shadow:0 2px 6px rgba(0,0,0,.08);
  transition:box-shadow .15s,border-color .15s;height:100%;width:100%}
@media (min-width:768px){.entry{padding:32px}}
@media (min-width:1024px){.entry{padding:48px}}
/* Hover per the component: stroke goes brand and gains a second pixel. The
   extra pixel is an inset ring rather than a wider border, so the box model
   is identical between states and nothing shifts. */
.entry:hover,.entry:focus-visible{
  border-color:var(--brand-500);outline:none;
  box-shadow:inset 0 0 0 1px var(--brand-500),0 10px 12px rgba(0,0,0,.12)}
.entry-in{display:flex;flex-direction:column;align-items:flex-start;gap:20px;flex:1;min-width:0}
/* Device Option uses 36px padding where To Do Cards uses 48px */
@media (min-width:1024px){.entry--device{padding:36px}}

/* Buttons — radius 6, py8 px16, Semi Bold 16/24 */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  border-radius:var(--r-md);border:1px solid transparent;font-family:inherit;
  /* Figma draws the 1px stroke *inside* the frame, so a Large button is 48px
     tall at padding 12. Deduct the border here or every button lands 2px tall. */
  padding:calc(var(--sp-button-y) - 1px) 15px;
  font-size:var(--fs-md);line-height:var(--lh-md);font-weight:600;letter-spacing:-.01em;
  cursor:pointer;transition:background-color .15s,border-color .15s,color .15s;width:100%}
.btn:disabled{cursor:not-allowed}
.btn-p{background:var(--brand-500);color:#fff}
.btn-p:hover:not(:disabled){background:var(--brand-600)}
.btn-p:active:not(:disabled){background:var(--brand-700)}
.btn-p:disabled{background:var(--n-200);color:var(--n-400)}
.btn-s{background:#fff;border-color:var(--brand-500);color:var(--brand-600)}
.btn-s:hover:not(:disabled){background:var(--brand-50)}
.btn-s:disabled{border-color:var(--n-200);color:var(--n-400)}
/* Device Condition's single forward control */
.btn-356{width:100%}
@media (min-width:768px){.btn-356{width:356px}}

/* Navigation: pair (16px gap, each flex-1) or single full-width.
   On mobile the pair stacks with the primary on top — authored, no mobile design. */
.ctas{display:flex;flex-direction:column-reverse;gap:16px;width:100%}
@media (min-width:768px){.ctas{flex-direction:row;align-items:flex-start}.ctas>.btn{flex:1;min-width:0}}
.backlink{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;
  padding:8px 16px;border-radius:var(--r-md);background:none;border:0;cursor:pointer;font-family:inherit}
/* Above-stepper variant: left-aligned, py-8 / pr-16, hugging its content so a
   full-width strip of empty space is not clickable.
   No hover state by request — the :focus-visible ring is untouched, since
   keyboard focus is a separate concern. */
.backlink--inline{width:auto;align-self:flex-start;justify-content:flex-start;padding:8px 16px 8px 0;
  position:relative}
/* At 12/16 the visual box is only 32px tall. The label stays that size while
   the hit area reaches 44px — the extension is invisible and takes no layout
   space, so the 16px gap to the stepper is unchanged. */
.backlink--inline::after{content:"";position:absolute;left:0;right:0;top:-6px;bottom:-6px}
.backlink--resend{width:100%;justify-content:center;padding:0}
.backlink--resend:hover{background:none}
.backlink:not(.backlink--inline):hover{background:var(--brand-50)}
.backlink img{width:13px;height:12px}
/* Mobile keeps the label to one word; the tail returns at tablet up. */
.backlink-more{display:none}
@media (min-width:768px){.backlink-more{display:inline}}
/* On mobile the label is only the word "Back", so it goes up to 14/20 — the
   12px step is sized for the full phrase on desktop. Scoped to the back link
   so the .t-label-sm-s utility keeps its 12px meaning elsewhere. Line height
   moves with it, otherwise 14px text would sit in a 16px box. */
@media (max-width:767px){
  .backlink--inline .t-label-sm-s{font-size:var(--fs-sm);line-height:var(--lh-sm)}
}

/* Progress bar — 166x4, radius 5, green fill. Radius exceeds half the height,
   so the bar and its fill read as fully rounded. */
.pbar{height:4px;width:100%;max-width:166px;border-radius:5px;background:var(--n-200);overflow:hidden}
.pbar>div{height:100%;border-radius:5px;background:var(--step-green);transition:width .3s ease-out}

/* Radio — 28px control + label, gap 8; row gap 26 */
.radio-row{display:flex;align-items:center;gap:26px;flex-wrap:wrap;justify-content:center}
/* Checklist under a condition question. The question itself stays centred, as
   it is in the design; a bulleted list cannot be centred sensibly, so the note
   is a left-aligned block within the centred column. */
/* Question to subheading is 8px in the design. */
.qgroup{display:flex;flex-direction:column;align-items:center;gap:8px;
  width:100%;max-width:560px;min-width:0}
/* Left-aligned question: the heading and the checklist align to one left edge
   rather than each hugging and centring independently. */
.qgroup.is-left{align-items:flex-start}
.qgroup.is-left .qnote{max-width:100%}
/* The note hugs its own content and is centred, so its left edge sits inboard
   of a wider question and outboard of a narrower one — which is what the design
   does on every screen (question 483 / note 297 on Q5, note wider than the
   heading on Q6). max-width only kicks in to wrap a very long item. */
.qnote{display:flex;flex-direction:column;align-items:flex-start;gap:4px;
  max-width:560px;text-align:left}
.qnote ul{margin:0;padding-left:20px;display:flex;flex-direction:column;gap:2px}
.qnote li{font-size:var(--fs-sm);line-height:var(--lh-sm);color:var(--n-600);
  letter-spacing:-.005em}
/* Dissolve between condition questions. The answered block fades out before
   the screen changes and the incoming one fades in, so the two reads as a
   single transition rather than a jump. Reduced motion skips both. */
/* Progress bar to question is 32px, held by .pwrap so it does not inherit the
   content column's 60px gap. */
.pwrap{display:flex;flex-direction:column;align-items:center;gap:32px;width:100%;min-width:0}
/* 32px from the question group down to the Yes/No radios; the question and
   its subheading sit 8px apart inside .qgroup. */
.qblock{display:flex;flex-direction:column;align-items:center;gap:32px}
/* The fade-in only runs when the question actually changes (.is-in). Putting
   it on .qblock itself meant every render restarted it — so answering, which
   re-renders in place to show the selected radio, dropped the question to
   opacity 0 and faded it back in, then the fade-out began while that was
   still running. Two animations per click, which read as a flicker. */
.qblock.is-in{animation:q-in var(--dissolve) ease-out}
.qblock.is-out{opacity:0;transition:opacity var(--dissolve) ease-in}
/* The incoming question rises slightly as it fades, which reads as forward
   progress rather than a straight swap. */
@keyframes q-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
/* Only while the box is being resized: without it a short-to-tall move spills
   the checklist over the radios for the length of the animation. */
.qgroup.is-sizing{overflow:hidden}
@media (prefers-reduced-motion:reduce){
  .qblock.is-in{animation:none}
  .qblock.is-out{transition:none;opacity:1}
}
.radio{display:inline-flex;align-items:center;gap:8px;cursor:pointer;border-radius:var(--r-sm);
  padding:8px;min-height:44px}
@media (min-width:768px){.radio{padding:2px;min-height:0}}
.radio input{position:absolute;width:1px;height:1px;opacity:0;margin:0;pointer-events:none}
.radio:has(input:focus-visible){outline:2px solid var(--brand-500);outline-offset:2px}
.radio img{width:28px;height:28px}
.radio span{font-size:var(--fs-md);line-height:var(--lh-md);font-weight:500;color:var(--n-600);letter-spacing:-.01em}

/* Checkbox. Drawn from tokens, since the design system ships no checkbox
   asset: 20px box on the .field-icon scale, radius r-sm, neutral/300 stroke,
   and brand/500 for the selected state. The native input stays in the DOM,
   visually hidden but focusable, so keyboard and assistive tech get a real
   checkbox. Touch target is 44px, relaxing on desktop. */
.check{display:inline-flex;align-items:flex-start;gap:8px;cursor:pointer;
  border-radius:var(--r-sm);padding:8px;min-height:44px}
@media (min-width:768px){.check{padding:2px;min-height:0}}
.check input{position:absolute;width:1px;height:1px;opacity:0;margin:0;pointer-events:none}
.check:has(input:focus-visible){outline:2px solid var(--brand-500);outline-offset:2px}
.check-box{position:relative;flex:none;width:20px;height:20px;margin-top:2px;
  border:1px solid var(--n-300);border-radius:var(--r-sm);background:#fff;
  transition:background .15s,border-color .15s}
.check:hover .check-box{border-color:var(--n-500)}
/* Selected: brand blue fill and stroke. */
.check input:checked+.check-box{background:var(--brand-500);border-color:var(--brand-500)}
/* The tick is two borders rotated 45deg — no asset needed, and it scales with
   the box rather than being a fixed bitmap. */
.check input:checked+.check-box::after{content:"";position:absolute;
  left:6px;top:2px;width:5px;height:10px;
  border:2px solid #fff;border-top:0;border-left:0;transform:rotate(45deg)}
.check-label{font-size:var(--fs-sm);line-height:var(--lh-sm);font-weight:500;
  color:var(--n-700);letter-spacing:-.005em}
.check-label a{color:var(--brand-600);font-weight:600;text-decoration:underline}

/* Fields — radius 6, padding 8/16, 1px inside stroke */
/* label -> field -> hint, 8px apart */
.fw{display:flex;flex-direction:column;gap:8px;width:100%;min-width:0}
.flabel{font-size:var(--fs-sm);line-height:var(--lh-sm);font-weight:500;color:var(--n-700);margin:0}
.field{display:flex;align-items:center;gap:8px;width:100%;border-radius:var(--r-md);
  /* Stroke is inside in Figma, so deduct it (see .btn) - a field is 44px tall. */
  padding:calc(var(--sp-field-y) - 1px) 15px;border:1px solid var(--n-200);background:#fff;
  transition:border-color .15s}
.field:hover{border-color:var(--n-300)}
.field:focus-within{border-color:var(--brand-500)}
.field.err{border-color:var(--red-500)}
.field input,.field select,.dd-val{width:100%;border:0;outline:0;padding:0;background:transparent;
  font-family:inherit;font-size:var(--fs-md);line-height:var(--lh-md);color:var(--n-800);letter-spacing:-.01em}
/* Strip the native select arrow — the Figma chevron is rendered instead.
   Without this, both appear. */
.field select{appearance:none;-webkit-appearance:none;-moz-appearance:none;cursor:pointer}
/* Date of birth picker. The .field shell above is reused untouched, so the
   closed state is unchanged; the panel borrows the card radius, neutral
   strokes, brand fill and shadow already used elsewhere. */
.dp-wrap{position:relative}
.dp-btn{display:flex;align-items:center;justify-content:center;flex:none;
  width:20px;height:20px;padding:0;border:0;background:none;cursor:pointer}
.dp-btn>img{width:20px;height:20px;display:block}
/* Right-aligned: the panel's right edge meets the field's, which also puts it
   directly under the calendar button that opens it. */
.dp{position:absolute;top:calc(100% + 6px);right:0;z-index:30;
  display:flex;flex-direction:column;gap:8px;width:312px;padding:12px;
  background:#fff;border:1px solid var(--n-200);border-radius:var(--r-card);
  box-shadow:0 2px 6px rgba(0,0,0,.08)}
.dp-head{display:flex;align-items:center;gap:4px}
.dp-sel{display:flex;gap:6px;flex:1;min-width:0}
.dp-selbox{position:relative;display:flex;flex:1;min-width:0}
/* The native caret honours padding-right only in Chromium — Safari pins it to
   the border, so padding alone looked like nothing had changed. Strip the OS
   arrow and render the same Figma chevron the .field selects use, then the 8px
   gap is real padding on every browser. Right padding clears the icon. */
.dp-sel select{flex:1;min-width:0;height:32px;padding:0 28px 0 8px;cursor:pointer;
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  font-family:inherit;font-size:var(--fs-sm);line-height:var(--lh-sm);
  color:var(--n-800);background:#fff;border:1px solid var(--n-200);
  border-radius:var(--r-md)}
.dp-caret{position:absolute;top:50%;right:8px;width:16px;height:16px;
  transform:translateY(-50%);pointer-events:none}
.dp-nav{display:flex;align-items:center;justify-content:center;flex:none;
  width:32px;height:32px;padding:0;cursor:pointer;background:#fff;
  border:1px solid var(--n-200);border-radius:var(--r-md)}
.dp-nav:hover{background:var(--n-100)}
.dp-nav>img{width:13px;height:12px}
.dp-next>img{transform:rotate(180deg)}
.dp-dow,.dp-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.dp-dow>span{text-align:center;font-size:var(--fs-xs);line-height:var(--lh-xs);
  font-weight:500;color:var(--n-500)}
.dp-day{height:36px;padding:0;border:0;background:none;cursor:pointer;
  border-radius:var(--r-md);font-family:inherit;font-size:var(--fs-sm);
  line-height:var(--lh-sm);color:var(--n-800)}
.dp-day:hover{background:var(--n-100)}
.dp-day.is-today{box-shadow:inset 0 0 0 1px var(--n-300)}
.dp-day.is-sel{background:var(--brand-500);color:#fff;font-weight:600}
.dp-day[disabled]{color:var(--n-300);cursor:default}
.dp-day[disabled]:hover{background:none}
/* On a phone the fixed 312px panel is narrower than the 343px field it hangs
   from. Pin both edges instead so it matches the input exactly, the way the
   dropdown list already does. Desktop keeps the fixed width, right-aligned
   under the calendar button. */
@media (max-width:767px){
  .dp{left:0;right:0;width:auto}
}
.field-icon{width:20px;height:20px;flex:none;pointer-events:none}
/* Dropdown. The trigger is the .field shell as a button, so it inherits the
   hover, focus and error strokes every other input already has. */
.dd-wrap{position:relative}
.dd-btn{cursor:pointer;text-align:left;font-family:inherit}
.dd-btn[aria-expanded="true"]{border-color:var(--brand-500)}
.dd-val{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dd-val.is-ph{color:var(--n-500)}
/* Disabled field, matching the Dropdown component's State=disabled variant:
   neutral/200 fill and stroke, neutral/400 for both the label and the value.
   A cascading dropdown is inert until the one above it has been answered. */
.field--dis{background:var(--n-200);border-color:var(--n-200);cursor:not-allowed}
.field--dis:hover{border-color:var(--n-200)}
.field--dis .dd-val{color:var(--n-400)}
.field--dis .field-icon{opacity:.4}
.dd-wrap.is-dis .flabel{color:var(--n-400)}
.dd{position:absolute;top:calc(100% + 6px);left:0;right:0;z-index:30;
  display:flex;flex-direction:column;max-height:264px;overflow-y:auto;padding:6px;
  background:#fff;border:1px solid var(--n-200);border-radius:var(--r-card);
  box-shadow:0 2px 6px rgba(0,0,0,.08)}
.dd-opt{width:100%;padding:9px 10px;border:0;background:none;cursor:pointer;
  text-align:left;border-radius:var(--r-md);font-family:inherit;
  font-size:var(--fs-md);line-height:var(--lh-md);color:var(--n-800);
  letter-spacing:-.01em}
.dd-opt:hover,.dd-opt.is-active{background:var(--n-100)}
.dd-opt.is-sel{color:var(--brand-600);font-weight:600}
.field input::placeholder{color:var(--n-500)}
/* Hints render at 14/20 in neutral/400 — Body/Small size, not Caption.
   margin:0 matters: without it the browser's default <p> margin is added to
   the 8px field->hint gap and the 32px hint->button gap. */
.fhint{font-size:var(--fs-sm);line-height:var(--lh-sm);color:var(--n-400);margin:0}
.fhint.err{color:var(--red-700)}

.col{display:flex;flex-direction:column;gap:16px;width:100%;min-width:0}
/* Form screens: 550px wide, 32px between the field group and the CTAs.
   The CTAs live inside this block for that reason — as a sibling of it they
   would inherit the content column's 60px gap. */
.form-col,.identify-col{display:flex;flex-direction:column;align-items:flex-start;gap:32px;
  width:100%;max-width:550px;min-width:0;margin-inline:auto}
/* "serial and device found": the field group and the success card, 16px apart */
.found-group{display:flex;flex-direction:column;align-items:flex-start;gap:16px;width:100%;min-width:0}
.rowbox{display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap;
  background:#fff;border:1px solid var(--n-200);border-radius:var(--r-card);padding:16px;width:100%;min-width:0}
@media (min-width:480px){.rowbox{gap:16px;flex-wrap:nowrap;padding:20px 24px}}
/* Device found: a success card, not a neutral one. Ground #F1FDF4 with a
   25%-opacity #3EB400 border. Neither is a token — green/100 is #E3F6E9 and
   there are no alpha tokens — so both are off-system design values. */
.found{display:flex;align-items:flex-start;gap:16px;width:100%;padding:24px;
  border-radius:var(--r-card);background:#f1fdf4;border:1px solid rgba(62,180,0,.25);overflow:hidden}
.found img{width:22px;height:22px;flex:none}
/* The three lines sit tight with no gap — they read as one block */
.found-text{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;flex:1;min-width:0}
.found-text p{margin:0}
.note{display:flex;align-items:flex-start;gap:16px;border:1px solid var(--amber-300);
  background:var(--alert-bg);border-radius:var(--r-card);padding:20px 24px;width:100%}
.note img{width:24px;height:24px;flex:none}
/* Copy is neutral/900 — the amber carries in the icon and border only */
.note p{color:var(--n-900)}

/* Quote card — 3px dashed brand border, 16px radius, translucent cyan */
.quote{display:flex;align-items:center;gap:16px;border:3px dashed var(--quote-border);
  border-radius:var(--r-quote);background:var(--quote-bg);padding:16px;width:100%;min-width:0;overflow:hidden}
@media (min-width:480px){.quote{padding:24px;gap:24px}}
@media (min-width:640px){.quote{gap:48px}}
.quote-gift{width:63px;height:42px;flex:none;display:none}
@media (min-width:640px){.quote-gift{display:block}}
.locked{display:flex;align-items:center;gap:8px}
.locked img{width:15px;height:16px;flex:none}
.locked p{font-size:var(--fs-sm);line-height:var(--lh-sm);font-weight:600;color:var(--brand-500);letter-spacing:-.01em}
@media (min-width:480px){.locked p{font-size:var(--fs-lg);line-height:var(--lh-md)}}

/* Trade-in kit — 716 + 1px divider + 357, 23px gaps */
/* On mobile only, the CTA is the last thing in the column, after the estimate —
   you confirm once you have seen what you are confirming. It is a sibling of
   the two columns rather than a child of the left one so the single column can
   order it last. Tablet reorders it back above the estimate, and from 1024 up
   the grid places it under the step cards in column 1, where the design puts
   it — so only the phone layout changes. */
.kit{display:grid;gap:32px;width:100%;min-width:0}
@media (min-width:1024px){
  .kit{grid-template-columns:minmax(0,1fr) 1px minmax(0,320px);
    column-gap:23px;row-gap:32px;align-items:start}
  .kit-main{grid-column:1;grid-row:1}
  /* span 2, not 1/-1: with no explicit rows there is no last explicit line for
     -1 to reach, so the divider would stop above the button. */
  .kit-div{grid-column:2;grid-row:1 / span 2}
  .kit-side{grid-column:3;grid-row:1}
  .kit-cta{grid-column:1;grid-row:2}
}
@media (min-width:768px) and (max-width:1023px){
  /* Still one column here, but wide enough that the estimate is not a scroll
     away, so the CTA keeps its designed place above it. */
  .kit-cta{order:2}
  .kit-side{order:3}
}
@media (min-width:1280px){.kit{grid-template-columns:minmax(0,1fr) 1px 357px}}
.kit-cta{width:100%}
.kit-main{display:flex;flex-direction:column;gap:32px;min-width:0}
.kit-side{display:flex;flex-direction:column;gap:16px;min-width:0}
.kit-div{display:none;background:var(--n-200)}
@media (min-width:1024px){.kit-div{display:block;align-self:stretch}}
.kit-grid{display:grid;gap:16px;min-width:0}
@media (min-width:560px){.kit-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}}
@media (min-width:1200px){.kit-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
/* Cards stretch to the tallest in the row; icon then text, 20px apart */
.kit-cell{display:flex;flex-direction:column;align-items:flex-start;gap:20px;height:100%;
  background:#fff;border:1px solid var(--n-200);border-radius:var(--r-card);padding:24px}
.kit-cell-text{display:flex;flex-direction:column;align-items:flex-start;gap:4px;width:100%}
/* Sidebar quote is smaller than the main one: padding 20, gap 20, H1 value */
.quote--sm{padding:20px;gap:20px}
.quote-sm-text{display:flex;flex-direction:column;align-items:flex-start;gap:4px;flex:1;min-width:0}
.quote--sm .locked p{font-size:var(--fs-sm);line-height:var(--lh-sm)}

/* Confirmation — container gap 32, header group gap 16, 550 detail card */
.done-col{display:flex;flex-direction:column;align-items:center;gap:32px;width:100%;max-width:550px;
  min-width:0;margin-inline:auto}
.done-head{display:flex;flex-direction:column;align-items:center;gap:16px;width:100%;min-width:0}
.done-card{display:flex;flex-direction:column;gap:10px;width:100%;background:#fff;
  border:1px solid var(--n-200);border-radius:var(--r-card);padding:20px 24px;overflow:hidden}
.done-row{display:flex;align-items:center;gap:16px;width:100%}
.done-row>p:first-child{flex:1;min-width:0}

/* Track my trade-in (Figma 2356:3532).
   Two alignments on one page: the title block spans the 1120 gutter grid while
   the body is a 738 column centred in it. `.content` already supplies the 60px
   gap between them at desktop, so both are direct children of it. */
.trk{display:flex;flex-direction:column;gap:24px;width:100%;max-width:738px;min-width:0}
.badge{display:inline-flex;align-items:center;padding:4px 8px;border-radius:12px;
  /* Off-system pair: neither #EDF6FF nor #1084FE is a token yet. */
  background:#edf6ff;color:#1084fe;white-space:nowrap;align-self:flex-start}
.trk-card{display:flex;flex-direction:column;gap:16px;width:100%;min-width:0;background:#fff;
  border:1px solid var(--n-200);border-radius:var(--r-card);padding:23px;overflow:hidden}
/* "Trade-in status" is 16px on a 16px line height - the Caption style with the
   size overridden in the design, so it can't be one of the .t-* classes. */
.trk-card-h{font-size:var(--fs-md);line-height:16px;font-weight:600;color:var(--n-900)}
.trk-steps{display:flex;flex-direction:column;width:100%;min-width:0}
.tstep{display:flex;gap:8px;align-items:flex-start;width:100%;min-width:0}
/* The rail stretches so the 2px connector fills whatever the body needs. */
.tstep-rail{display:flex;flex-direction:column;align-items:center;align-self:stretch;
  flex:none;width:48px}
.tstep-rail>img{width:28px;height:28px;flex:none}
.tstep-rail>i{flex:1 0 0;min-height:1px;width:2px;background:var(--n-200)}
.tstep--done .tstep-rail>i{background:#3eb400}
.tstep-body{display:flex;flex-direction:column;align-items:flex-start;gap:4px;
  padding-bottom:32px;flex:1;min-width:0}
.tstep--end .tstep-body{padding-bottom:24px}
.tphoto{display:flex;gap:16px;align-items:flex-start;width:100%;max-width:593px;min-width:0;
  background:var(--n-50);border:1px solid var(--n-300);border-radius:var(--r-card);
  padding:16px 24px;overflow:hidden}
.tphoto>img{width:22px;height:18px;flex:none}
/* The divider belongs to the row, not the button, so the button can hug its
   label. The hover tint then reads as a pill around the content — the same
   treatment as the Trade-in Details footer (.dt-rail button) — rather than a
   full-width grey band. It also stops a 653px strip of empty space being
   clickable. Row padding 7 + button padding 8 reproduces the old 15px gap
   below the divider exactly, so nothing moves. */
.trk-support-row{display:flex;width:100%;border-top:1px solid var(--n-200);padding-top:7px}
.trk-support{display:flex;gap:4px;align-items:flex-start;
  border:0;border-radius:var(--r-md);background:none;
  padding:8px 16px;cursor:pointer;font:inherit;text-align:left}
.trk-support>img{width:16px;height:16px;flex:none;margin-top:2px}
/* Tint, not an underline — the underline was removed by request. */
.trk-support:hover{background:var(--n-100)}
@media (max-width:767px){
  .tstep-rail{width:28px}
  .tstep-body{padding-bottom:24px}
  .trk-card{padding:15px}
}

/* Look Up Trade-In (2279:2960) — a 400px card under a segmented tab strip,
   with a wider 550px reassurance caption. Both centred on the same axis.
   The card is 400 because its content is a fixed 350 plus 25 either side. */
.lu{display:flex;flex-direction:column;align-items:center;gap:24px;width:100%;min-width:0}
.lu-group{display:flex;flex-direction:column;align-items:flex-start;gap:8px;
  width:100%;max-width:400px;min-width:0}
.tabs{display:flex;align-items:flex-start;background:var(--n-100);
  border-radius:var(--r-md);padding:6px}
.tab{padding:8px 16px;border:0;background:none;border-radius:3px;cursor:pointer;
  font-family:inherit;font-size:var(--fs-sm);line-height:var(--lh-sm);font-weight:500;
  letter-spacing:-.005em;color:var(--n-500);white-space:nowrap}
.tab:hover{color:var(--n-800)}
/* Selected is a white chip with a 1px inside stroke, so the border is deducted
   from the padding (see .btn) — otherwise the strip grows 2px on selection. */
.tab[aria-selected=true]{background:#fff;border:1px solid var(--n-200);
  border-radius:var(--r-md);padding:7px 15px;color:var(--n-900)}
/* Full-width variant: the strip fills its column and the tabs split it
   evenly. Same chip treatment as the hugging version used elsewhere. */
.tabs--split{width:100%}
/* Identify: tab strip above a white card, the Look Up Trade-In pattern. The
   group gap is 8, matching .lu-group; the card itself is .tab-card. */
.id-group{display:flex;flex-direction:column;align-items:flex-start;gap:8px;
  width:100%;min-width:0}
.tabs--split .tab{flex:1;text-align:center}
.tab-card{display:flex;flex-direction:column;align-items:flex-start;gap:16px;
  width:100%;min-width:0;background:#fff;border:1px solid var(--n-200);
  border-radius:var(--r-card);padding:24px}
.lu-note{width:100%;max-width:550px}

/* Look-up Enter OTP (2279:3832) — 550 column, four blocks 32px apart.
   The six boxes are 62px tall here against 44px on the journey's Email OTP;
   that is a fixed height set on the instances, not a token. Kept as drawn. */
.luotp{display:flex;flex-direction:column;align-items:center;gap:32px;
  width:100%;max-width:550px;min-width:0}
.luotp-group{display:flex;flex-direction:column;align-items:flex-start;gap:16px;
  width:100%;min-width:0}
.luotp-row{display:flex;gap:16px;width:100%;min-width:0}
.luotp-row .field{height:62px;justify-content:center;padding:0 1px;min-width:0}
.luotp-row input{text-align:center;font-size:var(--fs-xl);font-weight:600;letter-spacing:0}
@media (max-width:479px){
  .luotp-row{gap:8px}
  .luotp-row .field{height:52px}
  .luotp-row input{font-size:var(--fs-lg)}
}

/* Trade-In Lists (2279:3963) — a 930 column of cards centred in the 1120 grid.
   Card padding is 16/20 with the border ADDED (the design's children sit at
   17/21 inside a 930x130 frame), unlike the Track cards where the stroke
   overlaps the padding. Matched per frame rather than normalised. */
.tilist{display:flex;flex-direction:column;align-items:flex-start;gap:20px;
  width:100%;max-width:930px;min-width:0}
.tid{display:flex;flex-direction:column;align-items:flex-start;gap:6px;
  width:100%;min-width:0;background:#fff;border:1px solid var(--n-200);
  border-radius:var(--r-card);padding:16px 20px;overflow:hidden;
  cursor:pointer;font-family:inherit;text-align:left;
  transition:box-shadow .15s,border-color .15s}
/* Hover matches the file's other clickable cards (.entry): the stroke goes
   brand and gains a second pixel as an inset ring, so the box model is
   identical between states and nothing shifts. Not specified in the design. */
.tid:hover,.tid:focus-visible{border-color:var(--brand-500);
  box-shadow:inset 0 0 0 1px var(--brand-500),0 10px 12px rgba(0,0,0,.12)}
.tid:hover .tid-view>span{text-decoration:underline}
.tid-top{display:flex;align-items:center;justify-content:space-between;gap:16px;width:100%}
/* .badge pins itself to the start of a column; in this row it must centre. */
.tid-top .badge{align-self:center}
/* Warn tone. #92400D is not a token — amber/500 is #B26A00. */
.badge--warn{background:var(--alert-bg);color:#92400d}
.tid-view{display:flex;align-items:center;gap:8px;flex:none}
.tid-view>img{width:6px;height:10px;flex:none}
.tid-mid{display:flex;align-items:flex-start;gap:60px;width:100%;min-width:0}
.tid-name{display:flex;flex-direction:column;align-items:flex-start;
  justify-content:center;flex:1;min-width:0}
/* The list and the trailing button are both 20px-gapped children of the
   column, so the <ol> repeats the gap rather than nesting a new rhythm. */
.tilist-items{display:flex;flex-direction:column;gap:20px;width:100%;min-width:0;
  list-style:none;margin:0;padding:0}
@media (max-width:559px){.tid-mid{flex-direction:column;gap:8px}}

/* Trade-in Details (2279:4184) — a 930 column holding a three-tab panel and a
   footer rail of text actions. */
.dt{display:flex;flex-direction:column;align-items:flex-start;gap:24px;
  width:100%;max-width:930px;min-width:0}
.dt-group{display:flex;flex-direction:column;align-items:flex-start;gap:8px;width:100%;min-width:0}
.dt-panel{display:flex;flex-direction:column;align-items:flex-start;gap:16px;
  width:100%;min-width:0;background:#fff;border:1px solid var(--n-200);
  border-radius:var(--r-card);padding:24px}
.dt-card{display:flex;flex-direction:column;align-items:flex-start;gap:16px;
  width:100%;min-width:0;background:#fff;border:1px solid var(--n-200);
  border-radius:var(--r-card);padding:24px;overflow:hidden}
.dt-card--tight{padding:20px 24px;gap:20px}
/* Callouts. The info ground/border pair reuses the file-upload card's
   off-system #F0F6FF / #5987EF; warn and good reuse the journey's values. */
.dt-note{display:flex;gap:12px;align-items:flex-start;width:100%;min-width:0;
  border-radius:var(--r-card);padding:20px 24px;overflow:hidden}
.dt-note--info{background:var(--upload-bg);border:1px solid rgba(89,135,239,.5);padding:24px}
.dt-note--warn{background:var(--alert-bg);border:1px solid var(--amber-300)}
.dt-note--good{background:#f1fdf4;border:1px solid rgba(62,180,0,.25)}
.dt-note>img{flex:none}
.dt-note-text{display:flex;flex-direction:column;align-items:flex-start;gap:4px;
  justify-content:center;flex:1;min-width:0}
.dt-issues{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:2px}
.dt-issues li{font-size:var(--fs-sm);line-height:var(--lh-sm);color:var(--n-600);
  letter-spacing:-.005em}
/* Compact vertical stepper: 22px node, 58px pitch, body starting at x=37.
   Absolutely positioned in Figma; flexbox here so it reflows and the
   connector stretches to whatever the copy needs. */
.dsteps{display:flex;flex-direction:column;width:100%;min-width:0}
.dstep{display:flex;gap:15px;align-items:flex-start;min-width:0}
.dstep-rail{display:flex;flex-direction:column;align-items:center;
  align-self:stretch;flex:none;width:22px}
.dstep-rail>i{flex:1 0 0;min-height:1px;width:2px;background:var(--step-green)}
.dnode{display:flex;align-items:center;justify-content:center;flex:none;
  width:22px;height:22px;border-radius:50%;background:var(--step-green)}
.dnode>img{width:8.5px;height:8px}
.dstep-body{display:flex;flex-direction:column;align-items:flex-start;gap:4px;
  padding-bottom:18px;min-width:0}
.dstep:last-child .dstep-body{padding-bottom:0}
.dt-row{display:flex;align-items:center;gap:16px;width:100%;min-width:0}
.dt-row>p:first-child{flex:1;min-width:0}
.dt-data{display:flex;flex-direction:column;gap:10px;width:100%;min-width:0}
.row-val{white-space:nowrap}
/* On a phone these values are long enough to squeeze the label into a two-line
   wrap, so each pair stacks: label, value, 8px to the next pair. Opt-in per
   card (.dt-data / .done-card--stack) because it is not always wanted: the
   Track card's values are short and read better side by side, as does the
   Quoted value row below the rule, which is the total rather than a data pair. */
@media (max-width:767px){
  .dt-data,.done-card--stack{gap:8px}
  .dt-data .dt-row,
  .done-card--stack .done-row{flex-direction:column;align-items:flex-start;gap:0}
  .dt-data .dt-row>p:first-child,
  .done-card--stack .done-row>p:first-child{flex:none}
  .row-val{white-space:normal}
}
.dt-rule{height:1px;width:100%;background:var(--n-200);flex:none}
/* Destructive button — same geometry as .btn, error stroke and ink. */
.btn-d{background:#fff;border-color:var(--red-500);color:var(--red-500)}
.btn-d:hover:not(:disabled){background:#fdf6f6}
.dt-pair{display:flex;gap:16px;align-items:stretch;width:100%;min-width:0}
.dt-offer{display:flex;flex-direction:column;align-items:center;justify-content:center;
  flex:1;min-width:0;text-align:center;background:#fff;border:1px solid var(--n-300);
  border-radius:var(--r-card);padding:20px 24px;overflow:hidden}
.dt-offer--warn{border:1.5px solid var(--amber-500)}
.dt-offer--good{border:1.5px solid #12873f}
.dt-offer-in{display:flex;flex-direction:column;gap:4px;justify-content:center;width:100%}
.dt-photos{display:flex;gap:16px;align-items:stretch;width:100%;min-width:0;height:256px}
.dt-photo{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:4px;flex:1;min-width:0;background:#fff;border:1px solid var(--n-300);
  border-radius:var(--r-card);padding:20px 24px;overflow:hidden}
.dt-photo>img{width:24px;height:24px}
/* This screen's upload card is p24, where the journey's Identity screen
   uses py20 - so the padding is overridden rather than the base changed. */
/* Doubled class: the base .upload-card rule is defined later in the sheet,
   so a single-class modifier would lose the tie on source order. */
.upload-card.upload-card--p24{padding:24px}
.dt-rail{display:flex;align-items:center;gap:4px;width:100%;
  border-top:1px solid var(--n-100);padding-top:8px}
.dt-rail button{display:flex;align-items:center;justify-content:center;gap:4px;
  padding:8px 16px;border:0;border-radius:var(--r-md);background:none;
  cursor:pointer;font-family:inherit}
.dt-rail button:hover{background:var(--n-100)}
.dt-rail img{width:16px;height:16px;flex:none}
.dt-rail .div{width:1px;height:24px;background:var(--n-200);flex:none}
@media (max-width:767px){
  .dt-pair,.dt-photos{flex-direction:column}
  .dt-photos{height:auto}
  .dt-photo{min-height:160px}
  .dt-panel{padding:16px}
}
/* Trade-in Details has three tabs, and the third carries an amount — they do
   not fit a phone. Below 768 a dropdown stands in for them. Scoped with the
   child selector so Look Up Trade-In's two tabs are untouched at every width;
   it also outranks the bare .tabs rule regardless of source order. */
.dt-tabs-sel{display:block;width:100%;min-width:0}
.dt-group>.tabs{display:none}
@media (min-width:768px){
  .dt-tabs-sel{display:none}
  .dt-group>.tabs{display:flex}
}

/* Contact Support (2313:2835) — a 550 form column. */
.sup{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;
  gap:32px;width:100%;max-width:550px;min-width:0}
.sup-inputs{display:flex;flex-direction:column;align-items:flex-start;gap:16px;
  width:100%;min-width:0}
/* The message field is a fixed 120 tall with py8 rather than the shared
   field-y, and the text sits at the top. */
.field--area{height:120px;align-items:flex-start;padding:7px 15px}
.field--area textarea{width:100%;height:100%;border:0;outline:0;padding:0;
  background:transparent;resize:none;font-family:inherit;font-size:var(--fs-md);
  line-height:var(--lh-md);color:var(--n-800);letter-spacing:-.01em}
.attach{display:flex;align-items:center;gap:16px;width:100%;min-width:0;background:#fff;
  border:1px solid var(--n-200);border-radius:var(--r-md);padding:15px;cursor:pointer;
  font-family:inherit;text-align:left;overflow:hidden}
.attach:hover{border-color:var(--n-300)}
.attach>img{width:20px;height:20px;flex:none}
.attach-text{display:flex;flex-direction:column;align-items:flex-start;
  justify-content:center;flex:1;min-width:0;height:36px}

/* Request Confirmation (2316:3137) — 550 column: head, ticket card, detail
   card, then a numbered "what happens next" rail. */
.rc{display:flex;flex-direction:column;align-items:flex-start;gap:24px;
  width:100%;max-width:550px;min-width:0}
.rc-head{display:flex;flex-direction:column;align-items:center;gap:16px;width:100%;min-width:0}
/* The ticket card reuses the dashed quote card, but px24 py20 with no gap. */
.quote.quote--ticket{padding:20px 24px;gap:0}
.rc-note{display:flex;flex-direction:column;align-items:flex-start;gap:8px;width:100%;
  min-width:0;border-top:1px solid var(--n-200);padding:12px 8px 8px}
.rc-item{display:flex;gap:12px;align-items:flex-start;width:100%;min-width:0}
.rc-num{display:flex;align-items:center;justify-content:center;flex:none;
  width:28px;height:28px;border-radius:14px;background:var(--n-100)}
.rc-item-text{display:flex;flex-direction:column;align-items:flex-start;
  justify-content:center;flex:1;min-width:0}
/* 60px above the footer, which is the content column's own gap. The 24px
   padding-top used to add to that (making it 84), and margin-top:auto
   pinned the footer to the bottom of the viewport so the gap grew with the
   window. Figma measures a flat 60 with space left below, so both are gone. */
.footer{width:100%;display:flex;align-items:center;justify-content:center}
/* 14/20. Line height moves with the size — 14px text in a 16px box sits
   tight and risks clipping descenders. */
.footer p{font-size:var(--fs-sm);line-height:var(--lh-sm);font-weight:500;color:var(--n-300);text-align:center}
.footer .jp{font-family:var(--jp)}

/* Trade-In intro: three stages. Absolute in Figma; flexbox here so the row
   scales and can stack on a phone instead of overflowing. */
.stages{display:flex;flex-direction:column;align-items:center;gap:16px;width:100%;max-width:598px;
  list-style:none;margin:0;padding:0}
.stages li{display:flex;flex-direction:column;align-items:center;width:100%}
.stage-node{display:flex;flex-direction:column;align-items:center;gap:16px}
.stage-ring{position:relative;width:80px;height:80px;display:flex;align-items:center;justify-content:center}
.stage-ring>img:first-child{position:absolute;inset:0;width:80px;height:80px}
.stage-conn{width:7px;height:40px;border-radius:9999px;background:var(--n-900);margin:16px 0}
@media (min-width:640px){
  .stages{flex-direction:row;align-items:flex-start;gap:0}
  .stages li{flex-direction:row;align-items:flex-start;width:auto;flex:1}
  .stages li:last-child{flex:none}
  .stage-node{width:80px}
  .stage-conn{width:auto;flex:1;height:7px;margin:37px 0 0}
}
/* Trade-in values table */
.tt{width:100%;max-width:738px;display:flex;flex-direction:column;gap:10px;
  background:#fff;border:1px solid var(--n-200);border-radius:var(--r-card);padding:24px}
.tt-row{display:flex;align-items:flex-start;gap:20px;width:100%;padding:10px 0}
.tt-row+.tt-row{border-top:1px solid var(--n-100)}
.tt-head{display:flex;align-items:flex-start;gap:20px;width:100%}
.tt-dev{flex:1;min-width:0}
.tt-val{white-space:nowrap;font-weight:600}

.center{text-align:center}
/* Breakpoint readout — tells you which tier you are looking at on a real
   device, which is otherwise guesswork. Delete this rule and #bp to remove. */
#bp{position:fixed;right:8px;bottom:8px;z-index:99;background:var(--n-900);color:#fff;
  font-size:10px;line-height:1;padding:5px 7px;border-radius:var(--r-full);opacity:.55;
  font-variant-numeric:tabular-nums;pointer-events:none;font-weight:600;letter-spacing:.04em}
#bp::after{content:"MOBILE"}
@media (min-width:768px){#bp::after{content:"TABLET"}}
@media (min-width:1024px){#bp::after{content:"DESKTOP"}}
.stack-sm{display:flex;flex-direction:column;gap:8px}
/* Personal Details: fields 16px apart, and the button 32px below via .form-col */
.field-stack{display:flex;flex-direction:column;gap:16px;width:100%;min-width:0}
/* Button plus its "still needed" hint, 8px apart, so the hint does not add to
   the 32px gap above the button. */
.submit-block{display:flex;flex-direction:column;gap:8px;width:100%;min-width:0}
.stack-4,.stack-16,.stack-24{display:flex;flex-direction:column;align-items:flex-start;width:100%;min-width:0}
.stack-4{gap:4px}.stack-16{gap:16px}.stack-24{gap:24px}
/* File-upload card. Ground #F0F6FF on a #5987EF border — neither is a token
   (brand/50 is #F1F4FD, brand/400 is #6F85E7), so both are off-system. */
.upload-card{display:flex;align-items:flex-start;gap:16px;width:100%;text-align:left;
  padding:20px 24px;border-radius:var(--r-card);background:var(--upload-bg);
  border:1px solid var(--upload-border);font-family:inherit;cursor:pointer;
  transition:box-shadow .15s}
.upload-card:hover{box-shadow:0 2px 6px rgba(0,0,0,.08)}
.upload-card>img:first-child{width:16px;height:22px;flex:none;margin-top:2px}
.upload-text{display:flex;flex-direction:column;align-items:flex-start;flex:1;min-width:0}
.upload-tick{width:22px;height:22px;flex:none;margin-top:2px}
.field-row{display:flex;flex-direction:column;gap:16px;width:100%;min-width:0}
@media (min-width:480px){.field-row{flex-direction:row}.field-row>.fw{flex:1;min-width:0}}
.grid2{display:grid;gap:16px}
@media (min-width:640px){.grid2{grid-template-columns:1fr 1fr}}
/* Label -> boxes is 16px on this screen, unlike the 8px on regular fields */
.otp-block{display:flex;flex-direction:column;gap:16px;width:100%;min-width:0}
.otp-row{display:flex;gap:8px;width:100%;min-width:0}
.otp-row .field{padding:calc(var(--sp-field-y) - 1px) 1px;min-width:0}
.otp-row input{text-align:center;font-size:var(--fs-lg);font-weight:600;letter-spacing:0}
@media (min-width:480px){
  .otp-row{gap:16px}
  .otp-row .field{padding:calc(var(--sp-field-y) - 1px) 3px}
  .otp-row input{font-size:var(--fs-xl)}
}
