/* ============================================================
   PARAMOUNT ASIA (PASIA), Design Tokens
   The shared design system every mock-up is built from.
   Deep-green "mountain" identity + gold, on a warm calm canvas.
   International corporate · rooted in trust · direct for HK.

   Colours are derived from the PASIA badge logo:
     deep forest #082f2a / #0e4038, gold #c99a47 / #d4a650,
     sage peak #829182, silver ridge #bfc2c0, white snow.

   Never redefine a token inside a page. Add page-scoped classes
   instead. Type base stays >= 16px for fast, easy HK reading.
   ============================================================ */

:root {
  /* ---------- BRAND · greens (mountain, carries the page) ---------- */
  --deep-forest:  #082f2a;   /* darkest ground · badge outer, footers */
  --forest:       #0e4038;   /* PRIMARY · brand soul, badge inner */
  --pine:         #16564b;   /* interactive green · hovers, links */
  --sage:         #7f9186;   /* muted peak green · secondary, quiet fills */

  /* ---------- BRAND · gold (accent, premium, "rooted in trust") --- */
  --gold:         #c99a47;   /* PRIMARY accent · the one warm moment */
  --gold-bright:  #d8b25e;   /* highlights, hover on gold, underlines */
  --gold-deep:    #7e622e;   /* gold text on light · ~5.2:1 on mist (WCAG AA) */

  /* ---------- SUPPORT ---------- */
  --silver:       #bfc2c0;   /* cool "snow ridge" grey · fine UI accents */

  /* ---------- NEUTRALS · warm surfaces + text ---------- */
  --paper:        #ffffff;   /* cards, primary surface */
  --mist:         #f7f4ee;   /* warm off-white · page background */
  --surface-2:    #efeadd;   /* raised warm fill · quiet bands */
  --ink:          #14231f;   /* body text · green-black */
  --ink-soft:     #45524d;   /* secondary text */
  --ink-faint:    #5f6b66;   /* captions, meta, placeholders · ~5.1:1 on paper (WCAG AA) */
  --line:         #e5e0d4;   /* warm hairlines, borders */
  /* Added in the WP fork. PASIA had no softer second hairline, and the starter
     role name --hairline-soft needs one to alias onto. Letting it fall through
     to the starter's blue-tinted rgba(27,94,122,.08) would be off-brand. */
  --line-soft:    #f0ece2;   /* the quieter hairline, inside cards and rows */

  /* ---------- TINTS (translucent brand, for bands + chips) -------- */
  --forest-tint-05: rgba(14,64,56,.05);
  --forest-tint-10: rgba(14,64,56,.10);
  --forest-tint-20: rgba(14,64,56,.20);
  --gold-tint-10:   rgba(201,154,71,.12);
  --gold-tint-20:   rgba(201,154,71,.22);

  /* ---------- DECORATION (opaque, for oversized decorative glyphs) ----------
     A tint is a SURFACE FILL, and §1.7 of AGENTS.md forbids using one as a text
     colour without exception. The oversized watermarks in this design are real
     elements carrying real characters (a block numeral, an opening quotation
     mark), so they need a colour token that is not a tint. Naming them is the
     whole fix: nobody can mistake `--watermark` for a text colour and then
     "correct" its contrast, which is what a tint token sitting in a `color`
     declaration invites.

     THESE ARE THE COMPOSITED VALUES, NOT NEW COLOURS. Each is its tint painted
     over its own ground and flattened, so the rendering does not change. That
     holds for antialiased glyph edges as well as for solid coverage, because
     ground*(1-c) + composited*c expands to ground*(1-ac) + tint*ac, which is
     exactly what the translucent form paints at coverage c.

       --watermark       rgba(14,64,56,.05)   on --paper  ->  243,245,245
                         1.09:1 on --paper, which is the point of it.
       --watermark-gold  rgba(201,154,71,.12) on --paper  ->  248,243,233

     BOTH VALUES ARE READ OFF A PAINTED PIXEL, not calculated. The pen-and-paper
     blend gives 248.52 for the gold red channel and it was written down as 249;
     the browser composites in premultiplied 8-bit and lands on 248, and a
     screenshot of the two forms differs on every antialiased edge if you take
     the arithmetic's word for it. Measure, do not derive.

     THE THIRD ONE CANNOT BE FLATTENED, stated plainly rather than fudged. It
     paints on linear-gradient(150deg, var(--forest), var(--deep-forest)), so it
     composites to #36543b at the forest end and #324630 at the deep-forest end
     (measured, same method). One solid value would be right at a single point
     on that gradient and wrong along the rest of it, so it stays translucent
     and takes the name instead: the name is the fix that was actually asked
     for, and it is available here whether or not the value can be flattened. */
  --watermark:              #f3f5f5;
  --watermark-gold:         #f8f3e9;
  --watermark-gold-on-dark: rgba(201,154,71,.22);

  /* ---------- SEMANTIC ---------- */
  --price:        #1c6b4a;   /* rate/salary green (HK job-card style) */
  --price-bg:     #e6f4ec;
  --success:      #1c6b4a;
  --warning:      #b4791f;
  --danger:       #b23b2e;
  --info:         var(--pine);

  /* ---------- TYPE FAMILIES ----------
     Display: Fraunces, a warm, optical old-style serif. Premium,
              institutional, distinctive; pairs with gold.
     Body/UI: Inter, clean, neutral, international, fast to read.
     Chinese (Phase 1): fall through to system CJK below.        */
  --display: "Fraunces", "Times New Roman", Georgia, serif;
  --sans: "Inter", -apple-system, "Segoe UI", "Noto Sans SC",
          "Noto Sans TC", "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;

  /* ---------- FLUID TYPE SCALE (min 16px body) ---------- */
  --text-xs:    clamp(.75rem, .72rem + .12vw, .8125rem);   /* 12–13 */
  --text-sm:    clamp(.8125rem, .78rem + .16vw, .9375rem); /* 13–15 */
  --text-base:  clamp(1rem, .96rem + .2vw, 1.125rem);      /* 16–18 */
  --text-lg:    clamp(1.125rem, 1.05rem + .34vw, 1.375rem);/* 18–22 */
  --text-xl:    clamp(1.3rem, 1.15rem + .7vw, 1.75rem);    /* 21–28 */
  --text-2xl:   clamp(1.6rem, 1.3rem + 1.4vw, 2.4rem);     /* 26–38 */
  --text-3xl:   clamp(2rem, 1.5rem + 2.3vw, 3.25rem);      /* 32–52 */
  --text-hero:  clamp(2.5rem, 1.6rem + 4.2vw, 5rem);       /* 40–80 */

  /* ABOVE THE LADDER AND DELIBERATELY NOT PART OF IT: the size of a decorative
     watermark glyph, which is scaled to the card that crops it rather than read
     as text. services.html `.sv-block::after` is the signed-off value and this
     is it unchanged. Deriving it from --text-hero was tried first and lands
     12.5% short at the bottom of the range, 3.5rem against 4rem (measured
     57.9px against 64px at 375px), because the two clamps have different
     floors. A decorative display size is its own decision, so it is a token
     rather than a calc on a body-text step. */
  --text-watermark: clamp(4rem, 9vw, 7rem);                /* 64–112 */

  /* ALSO ABOVE THE LADDER, FOR THE OPPOSITE REASON: the helper card's name is
     the one type size in this system that is deliberately FLAT.

     `.hcard .who h3` is the only consumer. Every signed-off mock-up sets it as
     a bare `1.2rem`: css/site.css line 353, and again in index.html line 301
     for the front page's `.c-helper`. Both files declare --text-lg and use it a
     few rules away, on `.head p` and `.pg-hero .lede`, so the flat value is a
     decision rather than an omission. A card name sits beside a fixed 60px
     avatar inside a grid track whose floor is a pixel constant, and it is the
     one heading on those pages that is not meant to grow with the viewport.

     IT WAS ON --text-lg HERE, which is clamp(1.125rem, 1.05rem + .34vw,
     1.375rem). Measured in the browser against 1.2rem = 19.2px at a 16px root:
     21.70px at 1440 (+13.0%), 20.28px at 1024 (+5.6%), 19.41px at 768 (+1.1%),
     18px at 375 and at 320 (-6.3%). So the ladder was not one step too big
     everywhere. It crossed the design's value at about 706px and drifted either
     side of it, which is why the same card reads as too large on a laptop and
     slightly small on a phone. A reviewer on a desktop sees only the first half.

     DO NOT REUSE THIS ON ANOTHER CARD and do not put it back on the ladder.
     `.vc-job h3`, the vacancy card one page away, is --text-xl and is supposed
     to be. This token names ONE card's title, the way --btn-font-size names one
     component's size. */
  --card-title-size: 1.2rem;                               /* flat, 19.2px */

  --leading-tight: 1.08;
  --leading-snug:  1.28;
  --leading-body:  1.65;

  /* ---------- SPACING (8px base rhythm) ---------- */
  --s-1: .5rem;  --s-2: .75rem; --s-3: 1rem;   --s-4: 1.5rem;
  --s-5: 2rem;   --s-6: 3rem;   --s-7: 4.5rem; --s-8: 7rem;
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --section-y: clamp(3.5rem, 7vw, 7rem);
  /* The gap in a two-column "text beside a photograph" split. index.html
     `.c-svc-head`, services.html `.sv-intro` and the BLUF's own split are all
     this one clamp, and on services.html the BLUF sits directly above the
     services grid, so the two gaps have to agree. Three copies of one literal
     is what §1.1 of AGENTS.md calls a missing token. */
  --gap-split: clamp(2rem, 5vw, 4rem);
  /* THE FIRST EM-RELATIVE GAP TOKEN, and the unit is the whole reason it is a
     token rather than a number in components.css. The inline separator
     `<span class="sep">` sits between facts on one line, and it appears at
     --text-sm in a card sub line and at --text-xs in a card footer, so its
     breathing space has to scale with the text it is set in. Every spacing
     token above is rem: --s-1 is .5rem and would be the same 8px in both
     places, which is why none of them fits and why the value was sitting as a
     literal. `gap: .6em` on .eyebrow and `.55em` on .chipset below are the same
     idiom, and they are allowed to be literals only because they are in this
     file. AGENTS.md §1.1.

     TWO CONSUMERS ADDED, and they widen what this token names rather than
     bending it. `.vd-meta li` and `.vd-glance-facts li` in components.css are
     the vacancy detail page's facts rows, and the gap they take is the one
     between a bold label and its value inside a wrapping inline row: the same
     "breathing space between facts on one line" this token was written for,
     the same .45em, and em-relative for the same reason. The mock-up writes it
     as a bare .45em in both places, which is the third and fourth copy of the
     literal and so the case §1.1 already answers. Not a second token at the
     same value: two tokens with one value and one argument is worse than a
     token with four consumers. */
  --sep-gap: .45em;
  /* The gap in a wrapping row of pills INSIDE a card. `.hcard .chips` and
     `.vc-job .tags` are the two consumers and the mock-ups write both as the
     same bare 6px, which is below --s-1 (8px) and so has no entry on the 8px
     rhythm above. Two copies of one literal is what AGENTS.md §1.1 calls a
     missing token, the same argument --gap-split makes for three. It stays px
     rather than em, unlike --sep-gap: this gap sits between pills that carry
     their own padding, not between words that scale with a type size. */
  --pill-row-gap: 6px;
  --container-width: 1200px;
  --container-narrow: 760px;
  /* Header height – the sticky-offset reference for any `position:sticky`
     element that must clear the site header (see .site-header min-height). */
  --header-h: 72px;

  /* ---------- RADII ---------- */
  --r-sm:   8px;
  --r-md:   14px;
  --r-lg:   22px;
  --r-pill: 100px;

  /* ---------- ELEVATION (warm-tinted, soft) ---------- */
  --shadow-s:     0 1px 2px rgba(20,35,31,.06), 0 2px 6px rgba(20,35,31,.05);
  --shadow-m:     0 8px 24px -12px rgba(20,35,31,.22);
  --shadow-lift:  0 22px 48px -24px rgba(20,35,31,.32);
  --shadow-green: 0 14px 32px -16px rgba(14,64,56,.5);
  --shadow-gold:  0 12px 30px -14px rgba(201,154,71,.5);

  /* ---------- MOTION ---------- */
  --dur-fast:   150ms;
  --dur-normal: 300ms;
  --dur-slow:   600ms;
  --ease-out-soft: cubic-bezier(.22, 1, .36, 1);
  --ease-in-out:   cubic-bezier(.65, 0, .35, 1);
  /* The card hover lift, as a translateY offset. READ THE SCOPE BEFORE REUSING
     IT: the theme carries six distinct lift distances across twelve sites
     (-2 through -7px) because each mock-up chose its own, so this is NOT a
     claim that every lift is the same. It is the -3px CARD lift specifically,
     which components.css states twice, on `.hcard:hover` and on `.vc-job:hover`,
     and which those two do have to agree on: they are the same card shape in
     the same grid one page apart. The other -3px copies live in
     sections/icon-cards.css, sections/team-roster.css and layout.css and are
     still literals; converting them belongs with whoever owns those files. */
  --lift-hover: -3px;

  /* ---------- SEMANTIC STATE SURFACES (alerts, validation) ---------- */
  --danger-bg:   #fbecea;  --danger-border:  #f0cdc8;  --danger-ink:  #7a271f;
  --success-bg:  #e6f4ec;  --success-border: #bfe3d0;  --success-ink: #1c5239;
  --warning-bg:  #fbf1dd;  --warning-border: #ecd7a6;  --warning-ink: #7a5713;
  --info-bg:     #e4eef5;  --info-border:    #c4dced;  --info-ink:    #2a5f88;

  /* ---------- BRAND UTILITY TOKENS (de-duplicated from pages) ---------- */
  --whatsapp:      #1fab54;         /* WhatsApp brand green */
  /* The pill actually uses this one. White on --whatsapp is 3.00:1 and fails
     AA at the label's size; this clears it at 5.27:1 in the same hue. */
  --whatsapp-deep: #0d7a63;
  --ridge-far:     #123f38;         /* hero ridge SVG fills */
  --ridge-mid:     #0d352f;
  --ridge-near:    #082a25;
  --hero-overlay:  rgba(8,47,42,.9);/* photo+ridge hero: ~90% wash, subtle photo */
  --on-dark-strong: rgba(255,255,255,.82); /* body text on forest */
  --on-dark:        rgba(255,255,255,.66);
  --on-dark-faint:  rgba(255,255,255,.5);
  --on-dark-line:   rgba(255,255,255,.10);
  /* Added in the WP fork. The mock-up's site.css writes these translucent
     values inline in eight places; naming them is what lets a stylesheet other
     than this one stay literal-free (AGENTS.md §1.1). Values unchanged. */
  --on-dark-fill:       rgba(255,255,255,.08);
  --on-dark-fill-hover: rgba(255,255,255,.14);
  --on-dark-fill-soft:  rgba(255,255,255,.06);
  --on-dark-border:     rgba(255,255,255,.20);
  --paper-veil:         rgba(255,255,255,.92);
  --hero-wash-deep:     rgba(8,26,23,.94);   /* --deep-forest at 94% */
  --scrim-ink:          rgba(20,35,31,.72);  /* --ink at 72%, for photo captions */

  /* ---------- Z-INDEX SCALE (prevents overlay collisions) ---------- */
  --z-raised: 2;  --z-sticky: 50; --z-float: 60; --z-scrim: 65;
  --z-drawer: 70; --z-modal: 80;  --z-toast: 90;

  /* ---------- FORM CONTROL TOKENS ---------- */
  --input-border: var(--line);
  --input-border-focus: var(--gold);
  --input-ring: 0 0 0 3px var(--gold-tint-10);
  --input-ring-error: 0 0 0 3px rgba(178,59,46,.14);
  --container-form: 560px;

  /* ---------- CANONICAL BREAKPOINTS (documented; use these only) ----------
     1024px  nav collapses to drawer (header is content-dense)
      860px  3-col → 2-col / split heroes stack
      620px  2-col → 1-col, compact mobile
      560px  smallest phones: hide non-essential chrome
     QA at 320 / 375 / 768 / 1024 / 1440 / 1920. */

  /* ============================================================
     STARTER ALIAS LAYER
     Added by the WordPress fork, per pasia-wp-build-spec.md §7.

     The usual fork advice is to re-brand the starter's role tokens.
     It is inverted here on purpose: PASIA's system is the richer one
     (81 tokens against 60) and it is signed off across 27 pages. So
     PASIA is the base and the starter's role NAMES alias onto it.
     Mock-up CSS then pastes in unchanged, and any surviving starter
     section re-brands automatically.

     Only two token names collided, both the same role in both
     systems, so PASIA's values simply won: --ink and --text-hero.

     Do not re-derive this block. Do not "improve" it.
     ============================================================ */

  /* Starter role names, aliased onto the PASIA design system. */
  --brand-primary:        var(--forest);        /* #0e4038 */
  --brand-primary-hover:  var(--pine);          /* #16564b */
  --brand-accent:         var(--gold);          /* #c99a47 */
  --brand-accent-hover:   var(--gold-bright);   /* #d8b25e */
  --brand-support:        var(--success);       /* #1c6b4a */
  --brand-support-hover:  #17563b;
  --brand-support-on-dark: var(--gold-bright);
  --brand-tint:           var(--forest-tint-20);
  --brand-tint-soft:      var(--forest-tint-10);
  --surface:              var(--paper);
  --surface-alt:          var(--mist);
  --ink-muted:            var(--ink-soft);
  --hairline:             var(--line);
  --hairline-soft:        var(--line-soft);     /* NEW - added to the PASIA block above */
  --white:                var(--paper);
  --font-heading:         var(--display);
  --font-body:            var(--sans);
  --space-xs: var(--s-1); --space-s: var(--s-2); --space-m: var(--s-3);
  --space-l:  var(--s-4); --space-xl: var(--s-5);
  --section-space-s: var(--s-6); --section-space-m: var(--s-7); --section-space-l: var(--s-8);
  --space-gutter: var(--gutter);
  --container: var(--container-width);          /* 1200px, not the starter's 1380px */
  --radius-sm: var(--r-sm); --radius-md: var(--r-md);
  --radius-lg: var(--r-lg); --radius-pill: var(--r-pill);
  --shadow-sm: var(--shadow-s); --shadow-md: var(--shadow-m); --shadow-lg: var(--shadow-lift);
  --duration-fast: var(--dur-fast); --duration-normal: var(--dur-normal);
  --ease-out: var(--ease-out-soft);

  /* ---------- Alias layer, part two: names spec §7 does not list ----------
     Five starter tokens are read by surviving starter stylesheets and by the
     Theme Settings override layer but have no line in the spec's block. Left
     out they would resolve to nothing and those rules would silently lose
     their value, so they are mapped here on the same ladder the spec uses
     (xs -> --s-1 ... xl -> --s-5), continued one step each way. */
  --space-3xs: calc(var(--s-1) / 2);            /* 4px  */
  --space-2xs: var(--s-1);                      /* 8px  */
  --space-2xl: var(--s-6);                      /* 48px */
  --text-eyebrow: var(--text-xs);

  /* ---------- Semantic type scale onto PASIA's size ladder ----------
     PASIA sizes by ladder (--text-xs ... --text-hero); the starter names by
     role (--text-h1 ... --text-h4). Spec §7 flags this as the one judgement
     call in the mapping rather than an identity. Checked against the surviving
     starter sections (hero, page-head, cta, pillars, stats-band, testimonials)
     at 375 / 768 / 1440. */
  --text-h1:    var(--text-3xl);                /* 32 - 52 */
  --text-h2:    var(--text-2xl);                /* 26 - 38 */
  --text-h3:    var(--text-xl);                 /* 21 - 28 */
  --text-h4:    var(--text-lg);                 /* 18 - 22 */
  --text-body:  var(--text-base);               /* 16 - 18 */
  --text-lead:  var(--text-lg);                 /* 18 - 22 */
  --text-small: var(--text-sm);                 /* 13 - 15 */
}

/* ---------------------------------------------------------------------------
 * Button component tokens.
 *
 * The starter's names, PASIA's values, in PASIA's own units. .btn above reads
 * these instead of the literals it shipped with, so the rendering is unchanged
 * and Theme Settings finally has something real to override. The starter's
 * separate .btn-primary / .btn-ghost / .btn-outline block in components.css is
 * DELETED: it collided with the three rules above at equal specificity and,
 * loading later, quietly won. That would have made every starter-section
 * button gold where the signed-off design has forest green, and it would not
 * have surfaced until 27 pages were built on top of it.
 *
 * There is now exactly one button system. Markup is `class="btn btn-primary"`,
 * `btn btn-gold` or `btn btn-ghost`, and `.btn-ghost.on-dark` on a dark band.
 * ------------------------------------------------------------------------- */
:root {
  --btn-radius: var(--r-pill);
  /* em, not px: the mock-up's buttons scale with their own font size. Theme
     Settings emits px if the client changes one, which is them choosing a
     fixed size rather than a drifted default. */
  --btn-padding-block: .95em;
  --btn-padding-inline: 1.7em;
  --btn-padding-inline-secondary: 1.7em;
  --btn-font-size: var(--text-base);
  --btn-font-weight: 600;
  --btn-font-weight-secondary: 600;
  --btn-letter-spacing: normal;
  --btn-text-transform: none;
  --btn-border-width: 1.5px;
}

/* ============================================================
   BASE RESET + PRIMITIVES
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--sans);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--ink);
  background: var(--mist);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "kern" 1, "liga" 1;
}

/* `overflow-wrap: anywhere` ON THE HEADING ELEMENT ITSELF, and the breadth is
   the decision, not the value.

   base.css already carries this argument twice, once on `.pg-hero h1` and once
   on `.head h2`, and both notes say the exposure arrives with the client's
   copy rather than with today's. Neither was extended, and the reason it had to
   be is arithmetic: 29 of the theme's 34 sections declare an editable
   `heading`, `.head` is optional, and a section that renders its `h2` outside a
   `.head` had no cover at all. Measured with one 66-character unbreakable
   token, one element at a time, restoring between measurements:

     consultation-scheduler.heading  document 320 -> 1336   (+1016)
                                     document 1440 -> 2679  (+1239)
     statement.heading               +1016 at 320, +1052 at 1440
     office-details.heading          +809 at 320,  +445 at 1440
     cta-split.heading               +788 at 320,  +647 at 1440
     cta-dark.heading                +799 at 320,  +541 at 1440
     directors-letter.salutation     +740 at 320,  +286 at 1440
     bluf.heading                    +630 at 320,  +185 at 1440
     hero.heading (front page)       document NEVER MOVES, and the h1 is cut
                                     1352px at 320 and 2187px at 1440 inside
                                     `section.hero`'s own overflow: hidden
     .pasia-cta-panel h2             cut 851px at 320, 954px at 1440

   THE ELEMENT AND NOT A CLASS, because a section heading is a section heading
   whether or not it sits inside `.head`, and there is no such thing in this
   theme as a heading a designer wrote: AGENTS.md §1.2 forbids style fields and
   §2 makes `heading` a content field, so every h1 to h5 on the site is client
   free text arriving through `wp_postmeta`. Naming the element is therefore the
   same breadth as naming the exposure. It is also the lowest specificity there
   is, (0,0,1), so every deliberate choice already in the theme still wins:
   `.pg-hero h1` keeps `break-word`, `.pasia-insight-card h3` keeps
   `break-word`, `.head h2` keeps `anywhere`, and `.hero h1 em` keeps its
   `white-space: nowrap`, which suppresses overflow-wrap outright and is the one
   place a designer did choose not to break.

   `anywhere` AND NOT `break-word`, measured rather than argued. Both values
   were run over the whole exposed set at 320 and 1440. `break-word` closed the
   clipped cases but left THREE headings still moving the document by the full
   amount, consultation-scheduler (+1016/+1239), office-details (+809/+445) and
   cta-split (+788/+647), because each of those sits in a grid or flex track
   whose automatic minimum is the item's min-content width and only `anywhere`
   is taken into account when min-content is computed. That is the same finding
   base.css records for `.head h2`, re-measured on its siblings. `anywhere`
   closed all ten. */
h1, h2, h3, h4, h5 {
  font-family: var(--display);
  font-weight: 600;
  line-height: var(--leading-tight);
  letter-spacing: -.015em;
  color: var(--ink);
  text-wrap: balance;
  overflow-wrap: anywhere;
}

p { text-wrap: pretty; }

a { color: var(--pine); text-decoration: none; }
a:hover { color: var(--forest); }

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

strong, b { font-weight: 600; color: var(--ink); }

:focus-visible { outline: 3px solid var(--gold-deep); outline-offset: 2px; border-radius: 2px; box-shadow: 0 0 0 6px var(--gold-tint-20); }

/* ============================================================
   SHARED UTILITY PRIMITIVES (safe to use across all mock-ups)
   ============================================================ */

/* Eyebrow / kicker */
/* `overflow-wrap: anywhere` for the same reason the heading block above has it,
   and with the same standing: 26 of the theme's 34 sections declare an editable
   `eyebrow`, so this primitive is client free text on three quarters of the
   site and it had no `overflow-wrap` at all. One 66-character unbreakable
   token, one element at a time:

     hero.eyebrow (front page)   cut 478px past `section.hero`'s clip edge at
                                 320. The document never moves, so no width
                                 sweep in this build could see it.
     consultation-scheduler      document 320 -> 798 (+478)

   `anywhere` IS LOAD-BEARING HERE, not a copy of the heading rule's value.
   `.eyebrow` is `inline-flex`, so it is shrink-to-fit and its used width comes
   from max-content unless min-content moves; `break-word` was measured and left
   the hero eyebrow cut by the identical 478px. This is the `.crumbs` case in
   base.css exactly, a flex context where only `anywhere` changes the intrinsic
   minimum, and it is why the two rules do not share a value with `.pg-hero h1`.

   The `::before` rule is `flex: none`, so the 26px gold dash never shrinks and
   the wrapped label starts under itself rather than under the dash. */
.eyebrow {
  display: inline-flex; align-items: center; gap: .6em;
  font-family: var(--sans);
  font-size: var(--text-xs); font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--gold-deep);
  overflow-wrap: anywhere;
}
.eyebrow::before {
  content: ""; width: 26px; height: 1.5px;
  background: var(--gold); flex: none;
}
.eyebrow.on-dark { color: var(--gold-bright); }
.eyebrow.on-dark::before { background: var(--gold-bright); }

/* Buttons. Values come from the --btn-* tokens below so Theme Settings can
   reach them; every default is the signed-off literal it replaced.

   THE FLUENT FORMS SUBMIT BUTTON IS ON THESE SELECTORS, NOT ON A COPY OF THEM,
   and §1.6 of AGENTS.md is the whole reason. A client pastes a form shortcode
   and the plugin renders `<button class="ff-btn ff-btn-submit">`, which no
   theme rule reached: measured on a live form inside a PASIA card, it painted
   Fluent Forms' own rgb(26,126,251) at a 7px radius and weight 500, inside a
   forest-and-gold panel. The obvious fix is to write the primary-button
   treatment again under the plugin's class name, and that is precisely the
   second `.btn-primary` this file exists to prevent: two owners for one look,
   drifting apart the first time anyone touches the tokens. Naming the plugin's
   button here instead means it IS the button system rather than a copy of it,
   and a change to --btn-radius or --forest reaches it for free.

   Scoped to `.pasia-form-card` so it is the theme's own card that adopts the
   plugin's button, never a form somewhere else on the page, and carrying
   `.fluentform` so the selector outranks the plugin's own rules whichever
   stylesheet the browser loads last. components.css, FLUENT FORMS, carries the
   rest of the mapping and the measurements. */
.btn,
.pasia-form-card .fluentform .ff-btn.ff-btn-submit {
  display: inline-flex; align-items: center; gap: .55em;
  font-family: var(--sans); font-weight: var(--btn-font-weight); font-size: var(--btn-font-size);
  line-height: 1; padding: var(--btn-padding-block) var(--btn-padding-inline);
  letter-spacing: var(--btn-letter-spacing); text-transform: var(--btn-text-transform);
  border: var(--btn-border-width) solid transparent; border-radius: var(--btn-radius);
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: transform var(--dur-fast) var(--ease-out-soft),
              background-color var(--dur-normal) ease,
              color var(--dur-normal) ease,
              box-shadow var(--dur-normal) ease;
}
.btn:hover,
.pasia-form-card .fluentform .ff-btn.ff-btn-submit:hover { transform: translateY(-2px); }
.btn-primary,
.pasia-form-card .fluentform .ff-btn.ff-btn-submit { background: var(--forest); color: #fff; box-shadow: var(--shadow-green); }
.btn-primary:hover,
.pasia-form-card .fluentform .ff-btn.ff-btn-submit:hover { background: var(--deep-forest); color: #fff; }
.btn-gold { background: var(--gold); color: var(--deep-forest); box-shadow: var(--shadow-gold); }
.btn-gold:hover { background: var(--gold-bright); color: var(--deep-forest); }
.btn-ghost { border-color: var(--forest); color: var(--forest); font-weight: var(--btn-font-weight-secondary); padding-inline: var(--btn-padding-inline-secondary); }
.btn-ghost:hover { background: var(--forest-tint-05); }
.btn-ghost.on-dark { border-color: rgba(255,255,255,.45); color: #fff; }
.btn-ghost.on-dark:hover { background: rgba(255,255,255,.12); }

/* Pills / tags (HK job-card style) */
.tag {
  display: inline-block;
  font-family: var(--sans); font-size: var(--text-xs); font-weight: 600;
  letter-spacing: .01em; padding: .42em 1em; border-radius: var(--r-pill);
  background: var(--surface-2); color: var(--ink-soft);
}
.tag--active { background: var(--gold-tint-20); color: var(--gold-deep); font-weight: 700; }
.tag--new    { background: var(--price-bg); color: var(--price); font-weight: 700; }
.tag--forest { background: var(--forest-tint-10); color: var(--forest); }

/* Price chip (range-based rate cards / salary) */
.price {
  font-family: var(--sans); font-weight: 700; color: var(--price);
  background: linear-gradient(transparent 62%, var(--price-bg) 62%);
  padding: 0 .15em;
}

/* Layout helpers */
.container { max-width: var(--container-width); margin-inline: auto; padding-inline: var(--gutter); }
.container-narrow { max-width: var(--container-narrow); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: var(--section-y); }

/* Reduced motion: honour it everywhere */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}
