/* =========================================================================
   HINDERER MOTOR COMPANY — design tokens
   Single source of truth. No component may introduce a raw value.
   Every colour below is measured from the Figma file
   (rVcU822PQHDphMoBEqrrGz, node 2:11); contrast ratios are computed against
   the ground they actually sit on and recorded in the comment on each line.
   ========================================================================= */

:root {
  /* ---------------------------------------------------------------------
     GROUND & SURFACES
     Warm near-black, not #000 — taken from the hero's own bottom gradient.
     --------------------------------------------------------------------- */
  --bg:              #1f1d19;   /* page ground */
  --bg-raised:       #221f20;   /* inventory card title band */
  --bg-hover:        #262223;   /* one tonal step above raised — vehicle card hover */
  --bg-plate:        #3e2e1e;   /* step-card gradient, warm top stop */
  --bg-panel:        #33312d;   /* build panel gradient, cool top stop */
  /* Deeper than the ground and still warm. The page has no neutral black in
     it anywhere — #000 beside this ground reads blue, which is exactly the
     cheapness the warm near-black was chosen to avoid. Used for scrims over
     photography and for the ink button's hover. 18.87:1 with white. */
  --bg-deep:         #141310;
  --bg-card:         #f2efe9;   /* warm bone — the vehicle card. Pure #fff is
                                   absent rather than neutral and buzzed against
                                   the warm near-black ground. 14.66:1 with ink. */
  --bg-card-plain:   #ffffff;   /* review cards, which are quotations on paper */
  --bg-control:      #434343;   /* card action buttons */

  /* ---------------------------------------------------------------------
     INK  — ratios measured against --bg (#1f1d19)
     --------------------------------------------------------------------- */
  --ink:             #ffffff;   /* 16.83:1  headings, primary copy */
  --ink-quiet:       #e2e2e2;   /* 12.99:1  footer, legal */
  --ink-muted:       #b2a991;   /*  7.19:1  warm sand — all secondary body */
  --ink-inverse:     #1f1d19;   /* 16.83:1 on white — card metadata */
  --ink-card:        #707070;   /*  4.95:1 on white — review body */

  /* ---------------------------------------------------------------------
     ACCENT — copper.
     Derived, not chosen: sampled from the identity's own values in the
     Figma file (#a86537 heading fill, #a86537 button fill, #e07921 hero
     radial glow) — the same sodium/tail-light band the photography already
     holds. Judged where it lands: #a86537 clears 3:1 only as large type, so
     a second step exists for anything under 24px.
     --------------------------------------------------------------------- */
  --accent:          #a86537;   /*  3.67:1 — display ≥24px + solid fills only */
  --accent-ink:      #c8813f;   /*  5.34:1 — copper text below 24px */
  --accent-hover:    #b97240;   /*  4.32:1 — control hover */
  /* --accent-panel (a deep copper GROUND stop) was deleted with the copper
     contact panel: DS.html has always documented that panel's ground as
     --bg-raised, and the copper slab was drift. Copper is ink and fill here,
     never a ground — so there is no ground stop to keep. */
  --accent-glow:     #e07921;   /*  5.55:1 — hero radial. Referenced only through
                                   its channel form --glow-rgb; kept in hex so the
                                   palette shows the colour it is a tint of. */

  /* ---------------------------------------------------------------------
     SECONDARY — slate green. Sits opposite copper on the wheel and is the
     one hue the photography does not hold, so it separates the secondary
     action from the primary one without competing with the vehicles.
     --------------------------------------------------------------------- */
  --slate:           #405c58;   /*  7.27:1 with white label */
  --slate-lift:      #5f7673;   /*  4.85:1 with white label — hover/panel top */

  /* ---------------------------------------------------------------------
     TELEPHONE — the one gradient on the page, and the only hue outside the
     copper/slate pair. It reads as a live line rather than a link, which is
     the point: a call is not a page. The Figma ramp ended at #2B6459, which is
     2.46:1 on the ground and legal nowhere; the end stop is lifted so both
     ends clear AA.
     --------------------------------------------------------------------- */
  --tel:             #00998c;   /*  4.87:1 as text · 4.76:1 under ink-inverse */
  --tel-lift:        #00b7a9;   /*  6.77:1 — gradient start */
  /* The hover ground, and it is darker than --tel for one measured reason:
     white on --tel is 3.54:1 and fails. This clears 4.86:1, so the label can
     be the page's own ink instead of a second inverted rule to remember. */
  --tel-deep:        #00806f;

  /* A warm wash laid over photography in soft-light. Not a surface and not a
     text colour — it only ever tints an image. */
  --wash-warm:       #6f501e;

  /* ---------------------------------------------------------------------
     CHANNEL FORMS — an alpha cannot be taken from a hex, so any colour that
     is used translucently is also published as bare channels. Written as
     rgb(var(--x-rgb) / 0.5). If a value exists in both forms they must move
     together; nothing here may be redefined locally.
     --------------------------------------------------------------------- */
  --bg-rgb:         31 29 25;    /* = --bg */
  --bg-deep-rgb:    20 19 16;    /* = --bg-deep */
  --ink-rgb:        255 255 255; /* = --ink */
  --accent-rgb:     168 101 55;  /* = --accent */
  --accent-ink-rgb: 200 129 63;  /* = --accent-ink */
  /* = --slate-lift, and it is the LIFT step rather than --slate for a measured
     reason: as a wash it has to match copper's presence at the same alpha, and
     --slate-lift's luminance is 0.166 against copper's 0.179. --slate sits at
     0.095 and would have read as a stain rather than as a second light. */
  --slate-lift-rgb: 95 118 115;
  --tel-lift-rgb:   0 183 169;   /* = --tel-lift, for the progress fill's glow */
  /* The hero radial is one light source falling off through three stops, so
     the two inner ones are lighter tints of the glow rather than new hues. */
  --glow-in-rgb:  240 188 144;  /* radial centre */
  --glow-mid-rgb: 232 155 89;
  --glow-rgb:     224 121 33;   /* = --accent-glow, the outer stop */
  --shadow-rgb:   0 0 0;

  /* ---------------------------------------------------------------------
     RULES, BORDERS, FOCUS
     --------------------------------------------------------------------- */
  --rule:            rgb(var(--ink-rgb) / 0.12);
  --rule-strong:     rgb(var(--ink-rgb) / 0.28);
  /* The same two hairlines for a light surface. A rule is a tonal step away
     from its own ground, so on bone it steps DOWN — reusing the dark-ground
     rule there produces a line that is invisible. */
  --rule-inverse:        rgb(var(--bg-rgb) / 0.14);
  --rule-inverse-strong: rgb(var(--bg-rgb) / 0.30);
  --rule-control:    #a0a0a0;   /*  3.78:1 on --bg-control — UI boundary floor */
  --focus:           #ffffff;   /* 16.83:1 on ground · 4.58:1 on copper */

  /* ---------------------------------------------------------------------
     TYPE
     One voice. The Figma specifies Inter for every heading, lead, body and
     card, and Degular only on three button labels; Degular is licensed and
     not supplied, so it leads the display stack and Inter renders until the
     licence lands. Poppins (reviews + footer in the Figma) is folded into
     the same voice — a role, not a second voice.
     --------------------------------------------------------------------- */
  /* Inter Tight, not Inter: a slightly narrower set that sits better beside a
     condensed display face, and holds its colour at the small end of the ramp
     where this page does most of its reading. Inter stays as the fallback —
     same metrics family, so a failed load degrades rather than reflows. */
  --font-body:    "Inter Tight", "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* A third voice, and it has to earn the seat (typography I8). Oswald announces
     and Inter Tight informs; neither of them VALUES anything. In an auction
     catalogue the lot's price is set in a serif while the rubrics and the
     metadata stay sans — the change of face is what marks "this is what the
     object costs" apart from "this is how the page is organised".

     BOUNDED TO ONE ROLE: .vehicle__price. It appears on the vehicle card and
     nowhere else — not in section headings, not in a standfirst, not in body
     copy, labels or navigation. A section that wants a second rank under its
     title uses .section-sub in the display voice, like every other section on
     the page. Adding a second serif role is a change to the system, not a
     local decision. */
  --font-serif: "Playfair Display", "Iowan Old Style", Georgia, serif;
  --font-display: "Degular", "Hanken Grotesk", "Inter Tight", system-ui, -apple-system, sans-serif;

  /* Two voices, and the second has a systemic job the first cannot do:
     Inter carries reading and data (its tabular figures are why the spec
     plates align); the display voice carries headline mass. Degular is the
     licensed original. Hanken Grotesk is the stand-in — it matches Degular's
     large x-height and slightly narrow set without the geometric roundness
     that made the first stand-in read friendly on a technical brief. */

  /* Fluid so type is optically right at every width, not only at breakpoints.
     Body settles at 16px rather than 19. The steps below and above it move with
     it — a ramp where the "small" step ends up larger than body is not a ramp,
     and the 14px floor has to stay a floor. */
  --text-xs:      0.875rem;                                        /* 14px — hard floor */
  --text-sm:      clamp(0.875rem, 0.10vw + 0.85rem, 0.9375rem);    /* 14 → 15 */
  --text-body:    clamp(0.9375rem, 0.15vw + 0.90rem, 1rem);        /* 15 → 16 */
  --text-lead:    clamp(1.0625rem, 0.40vw + 0.95rem, 1.25rem);     /* 17 → 20 */
  --text-btn:     clamp(1.125rem, 0.55vw + 0.95rem, 1.4375rem);    /* 18 → 23 */
  --text-h3:      clamp(1.375rem, 0.90vw + 1.1rem, 1.75rem);       /* 22 → 28 */
  /* Two documented additions, both roles the ramp genuinely did not carry.
     The price sits between h3 and h2 because it must out-rank the car's own
     title without reaching the section heading; the spine is a vertical rule
     of caps read as texture, so it is sized to the block, not to the ramp. */
  --text-price:   clamp(1.5rem, 0.70vw + 1.3rem, 1.875rem);        /* 24 → 30 */
  --text-spine:   clamp(2rem, 2.80vw, 2.75rem);                    /* 32 → 44 */
  --text-h2:      clamp(1.625rem, 1.40vw + 1.2rem, 2.125rem);      /* 26 → 34 */
  --text-hero-2:  clamp(1.875rem, 2.40vw + 1.2rem, 3.25rem);       /* 30 → 52 */
  --text-display: clamp(2.5rem, 3.60vw + 1.4rem, 4rem);            /* 40 → 64 */
  /* The hero headline is one unbreakable phrase, so it is sized against the
     viewport rather than stepped: at any narrower rule it breaks after the
     dash, which is a break nobody chose. */
  --text-hero:    clamp(1.5rem, 7.4vw, 4rem);                      /* 24 → 64 */

  /* Weight is size-dependent and the correction is encoded, not remembered.
     Stems grow with the type, so the biggest sizes take the LIGHTEST weight;
     it is the small headings that need 500 to keep presence. Setting one
     weight across the whole ramp is what makes display type read fat. */
  --weight-display: 400;   /* 40px and up — hero, section titles */
  --weight-heading: 500;   /* 22–34px — sub-heads, card and step titles */
  --weight-body:    400;
  --weight-label:   600;   /* 14px labels — small type needs the compensation */

  /* Leading tightens as the type grows — long lines of large type need less
     of it, small reading type needs more. Six steps, and they are the only
     six: the build had four tokens and ten different values in the CSS, which
     is how .lead ended up at 1.55 and the paragraph beside it at 1.45.
     (line-height: 0 on an icon slot is a layout reset, not a type value.) */
  --lh-none:      1;      /* single-line caps — status pill, spine */
  --lh-display:   1.04;   /* 40px and up */
  --lh-heading:   1.14;   /* 22 → 34 */
  --lh-tight:     1.2;    /* sub-heads, clamped card titles */
  --lh-lead:      1.5;    /* 17 → 20 reading — lead, standfirst, contact value */
  --lh-body:      1.65;   /* 14 → 16 reading */

  /* Tracking tightens as the type grows, for the same optical reason */
  --track-display: -0.022em;
  --track-heading: -0.006em;
  --track-body:    0.005em;
  /* ONE uppercase tracking, and this is a revert of my own change made an hour
     earlier. I split this into two steps and raised labels to 0.10em, citing the
     rule that uppercase needs more tracking as the size drops. That rule is
     written for faces of normal width; Oswald is CONDENSED and drawn for caps,
     so it reaches the same "not jammed" at a much smaller number — and at 0.10em
     a five-letter label stopped reading as tracking and started reading as gaps
     between letters. The note that used to sit here said exactly that, and it
     was right. Everything uppercase takes this. */
  --track-caps:    0.03em;
  --track-num:     0.06em;   /* figures read aloud — phone, stock */

  /* Reading measures — long lines hurt reading in any aesthetic */
  --measure:       68ch;
  --measure-tight: 46ch;

  /* ---------------------------------------------------------------------
     SPACE — 4px base. Every gap in the build resolves to one of these.
     --------------------------------------------------------------------- */
  --space-1:   0.25rem;   /*   4 */
  --space-2:   0.5rem;    /*   8 */
  --space-3:   0.75rem;   /*  12 */
  --space-4:   1rem;      /*  16 */
  --space-5:   1.5rem;    /*  24 */
  --space-6:   2rem;      /*  32 */
  --space-7:   3rem;      /*  48 */
  --space-8:   4rem;      /*  64 */
  --space-9:   6rem;      /*  96 */
  --space-10:  8rem;      /* 128 */
  --space-11: 12rem;      /* 192 */

  /* ---- Content → CTA ------------------------------------------------------
     Two intervals, and only two, because the page has exactly two situations:
     a paragraph has just ended, or a block of cards has. A paragraph ends
     softly — ragged right edge, open descenders — so 48px reads as the next
     step of one thought. A card grid ends on a hard edge with borders and
     shadow, and at 48 the button sticks to it and reads as one more card, so
     that case gets 64. Anything else on the page picking a third value is a
     bug, not a decision. */
  --gap-cta-text: var(--space-7);   /* 48 — after prose */
  --gap-cta-grid: var(--space-8);   /* 64 — after a grid, strip or rail */

  /* CONTENT RHYTHM — the interval is chosen by relationship, not by eye.
     A gap picked straight from the raw scale gets picked again, differently,
     three sections later; naming the three distances is what stops that.
     Internal always smaller than external, so a group reads as one thing. */
  --space-text:     var(--space-3);   /*  12 — heading → its own body, label → value */
  --space-text-obj: var(--space-5);   /*  24 — text block → card, image, control */
  --space-block:    var(--space-8);   /*  64 — one content block → the next */

  /* Layout: the Figma content column is 1564px inside a 1920 frame */
  --container:  1564px;
  --gutter:     clamp(1.5rem, 5vw, 6rem);
  --grid-gap:   var(--space-6);

  /* Section rhythm — bottom-heavy (≈1:1.5) so a section ends rather than
     being shoved into the next one, and the page reads as chapters.
     Matched to the Figma's own section intervals, which run 200–300px. */
  --section-top:    clamp(4rem, 8vw, var(--space-10));    /*  64 → 128 */
  --section-bottom: clamp(5.5rem, 12vw, var(--space-11)); /*  88 → 192 */

  /* ---------------------------------------------------------------------
     RADIUS & ELEVATION
     Shadows appear only where the Figma has a genuinely floating layer.
     --------------------------------------------------------------------- */
  --radius-1:  3px;    /* card action buttons */
  --radius-2:  4px;    /* primary/secondary buttons */
  --radius-3:  10px;   /* media panels, review cards, map */
  --radius-4:  20px;   /* trade-in step plates, build panel */
  --radius-pill: 999px;

  /* A shadow is a claim about elevation, so only things that genuinely sit
     above something else carry one. The Figma drops a soft ambient shadow on
     every plate, band and card; those elements sit *in* the page, not above
     it, so the separation is carried by a hairline and a tonal step instead
     — which is also what keeps a dark page from going mushy.

     Exactly one thing on the page floats at rest, and it is the modal — which
     genuinely sits above everything. --shadow-float, the second resting step,
     was declared and documented and used by nothing once the contact block
     went full-bleed, so it is gone rather than left as an API that resolves to
     a shadow no one has seen. Restore it when a second floating layer arrives.
     --------------------------------------------------------------------- */
  --shadow-deep: 0 24px 60px -24px rgb(var(--shadow-rgb) / 0.75);  /* modal */

  /* The four below are RAISED-BY-INTERACTION: nothing
     wears them until the pointer or a selection puts it above its neighbours.
     They are tokens rather than inline values because a hover shadow that
     differs card-to-card is the fastest way for a dark page to look assembled
     from parts. --shadow-none is the transparent base a transition needs;
     box-shadow cannot animate from the keyword `none`. */
  --shadow-none:  0 0 0 rgb(var(--shadow-rgb) / 0);
  --shadow-lift:  0 18px 44px -12px rgb(var(--shadow-rgb) / 0.62);  /* vehicle card */
  --shadow-nudge: 0 16px 32px -18px rgb(var(--shadow-rgb) / 0.7);   /* step plate */
  --shadow-pop:   0 32px 64px -24px rgb(var(--shadow-rgb) / 0.8),
                  0 6px 18px -8px rgb(var(--shadow-rgb) / 0.5);     /* selected review */

  /* Cast upward. The one moment on the page where two sections genuinely
     occupy the same space, so it states a true fact about which is on top. */
  --shadow-scene: 0 -28px 60px -24px rgb(var(--shadow-rgb) / 0.75);

  /* ---------------------------------------------------------------------
     MOTION — the scale exists now so the animation pass has one source.
     Entering decelerates (ease-out); exiting accelerates (ease-in).
     --------------------------------------------------------------------- */
  --dur-1: 0.15s;
  --dur-2: 0.25s;
  --dur-3: 0.4s;
  --dur-4: 1.2s;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  /* Declared, not yet used: nothing on the page exits. Kept because entering
     and exiting are a pair — a dev adding a dismiss must not invent a curve. */
  --ease-in:  cubic-bezier(0.55, 0, 1, 0.45);

  /* Height of the persistent header — counted as a mass, used for
     scroll-margin so anchor targets are never hidden beneath it. */
  --header-h: 84px;

  /* Height of the configurator's phone bar, which is fixed over the document.
     One value, used by the bar AND by the clearance the document ends with —
     written twice they drift, and the drift is a footer nobody can reach. */
  --build-bar-h: 5.5rem;
}

@media (min-width: 62rem) {
  :root { --header-h: 136px; }
}
