/* ============================================================================
   TRADE HANDY AUSTRALIA — th-tokens.css  ·  v1.0.0  ·  4 Aug 2026

   THE FOUNDATION LAYER. Load order:
        th-core.css  →  th-tokens.css  →  th-semantic.css  →  th-components.css

   Every value here came from published token documentation or measured
   production CSS (Carbon, Polaris, Atlassian, Geist, Linear, Stripe, Notion,
   Material 3, Radix). None of it is preference. See _MASTER-PLAN.md Part 1.

   THREE RULES THAT GOVERN THIS FILE
     1. Application code touches SEMANTIC tokens only, never raw values.
     2. Line-height in px ALWAYS lands on a multiple of 4.
     3. Hierarchy is built in NEUTRALS so colour is free to carry meaning.
   ========================================================================= */

:root{

/* ─────────────────────────────────────────────────────────────────────────
   TYPE — hand-tuned integers. Nobody world-class ships a modular ratio.
   Carbon runs a 14px PRODUCT scale and a 16px MARKETING scale from the same
   company, deliberately. We do the same.
   ───────────────────────────────────────────────────────────────────────── */
  --fs-11: 11px;  --lh-11: 16px;  --ls-11:  .05em;   /* overline, uppercase  */
  --fs-12: 12px;  --lh-12: 16px;  --ls-12:  0;       /* meta, timestamps     */
  --fs-13: 13px;  --lh-13: 20px;  --ls-13: -.01em;   /* DENSE body — tables  */
  --fs-14: 14px;  --lh-14: 20px;  --ls-14: -.011em;  /* DEFAULT body/buttons */
  --fs-15: 15px;  --lh-15: 24px;  --ls-15: -.011em;  /* roomy body, modals   */
  --fs-16: 16px;  --lh-16: 24px;  --ls-16: -.011em;  /* MOBILE INPUT MINIMUM */
  --fs-20: 20px;  --lh-20: 28px;  --ls-20: -.012em;  /* section heading      */
  --fs-24: 24px;  --lh-24: 32px;  --ls-24: -.014em;  /* page title           */
  --fs-32: 32px;  --lh-32: 40px;  --ls-32: -.022em;  /* marketing h2         */
  --fs-48: 48px;  --lh-48: 52px;  --ls-48: -.022em;  /* marketing display    */
  --fs-64: 64px;  --lh-64: 64px;  --ls-64: -.022em;  /* hero only            */

  /* Three weights. Medium is the BUTTON/LABEL/NAV weight — never bold.
     Off-round values are variable-font optical axes (Linear ships 400/510/590). */
  --fw-regular:  400;
  --fw-medium:   510;
  --fw-semibold: 590;

  /* 🔴 Mobile inputs must be >=16px or iOS Safari zooms the viewport on focus. */
  --fs-input-mobile: var(--fs-16);

/* ─────────────────────────────────────────────────────────────────────────
   SPACE — 4px base. The 6px and 20px steps matter more than they look:
   6px is the correct icon-to-label gap at 13px text; 20px is the correct
   card padding when 16 is tight and 24 is baggy.
   ───────────────────────────────────────────────────────────────────────── */
  --sp-0:    0;      --sp-025:  2px;   --sp-05:   4px;   --sp-075:  6px;
  --sp-1:    8px;    --sp-15:  12px;   --sp-2:   16px;   --sp-25:  20px;
  --sp-3:   24px;    --sp-4:   32px;   --sp-5:   40px;   --sp-6:   48px;
  --sp-8:   64px;    --sp-10:  80px;   --sp-12:  96px;   --sp-16: 128px;

/* ─────────────────────────────────────────────────────────────────────────
   RADIUS — by ELEMENT, not one value everywhere.
   Trend 2025-26: controls went DOWN to 4-8px, containers went UP to 12-16px.
   12px radius on a 32px button reads as a mistake.
   ───────────────────────────────────────────────────────────────────────── */
  --r-xs:    2px;   /* badges, checkboxes, keyboard hints            */
  --rad-sm:    4px;   /* tags, lozenges, tooltips, table thumbnails    */
  --rad-md:    6px;   /* BUTTONS, INPUTS, SELECTS, NAV ITEMS <- default */
  --rad-lg:    8px;   /* cards, dropdown menus, popovers              */
  --rad-xl:   12px;   /* modals, page containers, tables, columns      */
  --rad-2xl:  16px;   /* media players, full-screen sheets             */
  --rad-full: 9999px; /* avatars, pills, status dots                   */

  /* NESTING: inner = outer - padding. Same radius on both makes the corner
     gap visibly vary — one of the most reliable amateur tells.
     FOCUS RING radius = element radius + 2px, offset 2px. */
  --r-focus-md: 8px;   /* for a --rad-md element */
  --r-focus-lg: 10px;  /* for a --rad-lg element */

/* ─────────────────────────────────────────────────────────────────────────
   CONTROL SIZES
   ───────────────────────────────────────────────────────────────────────── */
  --ctl-sm:  32px;  --ctl-md:  36px;  --ctl-lg:  44px;
  --row-compact: 32px;  --row-default: 40px;  --row-comfortable: 48px;

  /* Icons: FOUR sizes only. Off-grid sizes (11,15,17,19) are an amateur tell. */
  --icon-sm: 12px;  --icon-md: 16px;  --icon-lg: 20px;  --icon-xl: 24px;

  /* 🔴 FIELD TARGETS. Standard work gloves reduce effective touch precision
     to 20-25mm. 44px is NOT enough for a gloved thumb on a primary action. */
  --tap-min:   44px;
  --tap-field: 56px;

/* ─────────────────────────────────────────────────────────────────────────
   ELEVATION — the hairline lives INSIDE the shadow token.
   Alpha 4-9%, multi-layer, hue-tinted. `0 2px 4px rgba(0,0,0,.2)` is the
   most recognisable cheap shadow in existence — never ship it.
   ───────────────────────────────────────────────────────────────────────── */
  --ring:     0 0 0 1px rgba(16,32,44,.08);
  --sh-xs:    0 1px 2px rgba(16,32,44,.05);
  --sh-sm:    0 1px 3px rgba(16,32,44,.06), 0 1px 2px rgba(16,32,44,.04);
  --sh-md:    0 4px 8px -2px rgba(16,32,44,.06), 0 2px 4px -2px rgba(16,32,44,.04);
  --sh-lg:    0 12px 16px -4px rgba(16,32,44,.06), 0 4px 6px -2px rgba(16,32,44,.03);
  --sh-xl:    0 24px 32px -8px rgba(16,32,44,.08), 0 8px 16px -4px rgba(16,32,44,.04);
  --sh-menu:  var(--ring), var(--sh-lg);
  --sh-modal: var(--ring), var(--sh-xl);

  /* Button physics — the two lines that stop a button being a coloured div. */
  --btn-edge:      inset 0 0 0 1px rgba(0,0,0,.10);
  --btn-highlight: inset 0 .5px 0 1.5px rgba(255,255,255,.22);

/* ─────────────────────────────────────────────────────────────────────────
   NEUTRAL SURFACE LADDER — hierarchy without shadow (Linear's model).
   WARM neutrals: ~4% of the bronze hue, so bronze never looks foreign.
   Saturation stays under 8% — above ~10% a grey stops being neutral.
   ───────────────────────────────────────────────────────────────────────── */
  --surface-0: #08131C;   /* canvas — NEVER #000: halation, no room below   */
  --surface-1: #0F1E2A;
  --surface-2: #162836;
  --surface-3: #1D3342;
  --hairline:  rgba(255,255,255,.09);
  --hairline-2:rgba(255,255,255,.055);

/* ─────────────────────────────────────────────────────────────────────────
   MOTION
   ───────────────────────────────────────────────────────────────────────── */
  --ease-out:  cubic-bezier(.25,.46,.45,.94);
  --ease-in-out: cubic-bezier(.4,0,.2,1);
  --dur-fast:  120ms;
  --dur:       160ms;
  --dur-slow:  240ms;

/* ─────────────────────────────────────────────────────────────────────────
   BRAND RAMP — the M365 model. Fluent supplies 16 shades and maps them into
   160+ alias tokens; swap the ramp and the whole app re-skins with ZERO
   semantic meaning changing. Word blue / Excel green / PowerPoint orange are
   the same skeleton with a different ramp.

   🔴 --brand-* MAY APPEAR IN EXACTLY FOUR PLACES:
        logo · primary CTA · selected state · focus ring
      Anywhere else needs a written justification.
   ───────────────────────────────────────────────────────────────────────── */
  --brand-10:  #001A1B;   --brand-20:  #002527;   --brand-30:  #00373A;
  --brand-40:  #004A4D;   --brand-50:  #005E61;   --brand-60:  #007376;
  --brand-70:  #00898C;   --brand-80:  #00B8BB;   /* <- the pivot, TH teal  */
  --brand-90:  #1FC7C9;   --brand-100: #45D2D4;   --brand-110: #6BDCDD;
  --brand-120: #90E5E6;   --brand-130: #B0EDEE;   --brand-140: #CBF3F4;
  --brand-150: #E0F8F9;   --brand-160: #EFFCFC;

  --brand-solid: var(--brand-80);
  --brand-tint:  rgba(0,184,187,.13);   /* selected-state wash — a TINT      */
  --brand-fg:    #04201C;               /* text on a solid brand fill        */
  --fg-on-solid: #FFFFFF;               /* text on a solid SIGNAL fill       */
  --focus:       var(--brand-90);       /* lifted for contrast on dark       */
}

/* ─────────────────────────────────────────────────────────────────────────
   LIGHT SURFACES — reading. Dark is for canvas, light is for reading.
   ───────────────────────────────────────────────────────────────────────── */
.theme-light,[data-theme="light"]{
  --surface-0: #FFFFFF;
  --surface-1: #F7F9FA;
  --surface-2: #EFF3F5;
  --surface-3: #E5EAEE;
  --hairline:  rgba(16,32,44,.11);
  --hairline-2:rgba(16,32,44,.06);
  --focus:     #007376;                 /* darker: needs contrast on white   */
  --btn-highlight: inset 0 .5px 0 1.5px rgba(255,255,255,.55);
}

/* ─────────────────────────────────────────────────────────────────────────
   DARK MODE SHADOWS — different, not just darker.
   Elevate with SURFACE LIGHTNESS; raise shadow alpha 2-4x; FLIP the hairline
   to white. Geist goes 4% light -> 16-32% dark. Linear 6% -> 35%.
   ───────────────────────────────────────────────────────────────────────── */
:root,[data-theme="dark"]{
  --ring:     0 0 0 1px rgba(255,255,255,.10);
  --sh-xs:    0 1px 2px rgba(0,0,0,.30);
  --sh-sm:    0 1px 3px rgba(0,0,0,.36), 0 1px 2px rgba(0,0,0,.24);
  --sh-md:    0 4px 8px -2px rgba(0,0,0,.40), 0 2px 4px -2px rgba(0,0,0,.28);
  --sh-lg:    0 12px 16px -4px rgba(0,0,0,.44), 0 4px 6px -2px rgba(0,0,0,.28);
  --sh-xl:    0 24px 32px -8px rgba(0,0,0,.52), 0 8px 16px -4px rgba(0,0,0,.32);
  --btn-edge: inset 0 0 0 1px rgba(255,255,255,.12);
}

/* ─────────────────────────────────────────────────────────────────────────
   TYPE UTILITIES
   ───────────────────────────────────────────────────────────────────────── */
.t-11{font-size:var(--fs-11);line-height:var(--lh-11);letter-spacing:var(--ls-11);
      text-transform:uppercase;font-weight:var(--fw-medium)}
.t-12{font-size:var(--fs-12);line-height:var(--lh-12)}
.t-13{font-size:var(--fs-13);line-height:var(--lh-13);letter-spacing:var(--ls-13)}
.t-14{font-size:var(--fs-14);line-height:var(--lh-14);letter-spacing:var(--ls-14)}
.t-15{font-size:var(--fs-15);line-height:var(--lh-15);letter-spacing:var(--ls-15)}
.t-16{font-size:var(--fs-16);line-height:var(--lh-16);letter-spacing:var(--ls-16)}
.t-20{font-size:var(--fs-20);line-height:var(--lh-20);letter-spacing:var(--ls-20);font-weight:var(--fw-semibold)}
.t-24{font-size:var(--fs-24);line-height:var(--lh-24);letter-spacing:var(--ls-24);font-weight:var(--fw-semibold)}
.t-32{font-size:var(--fs-32);line-height:var(--lh-32);letter-spacing:var(--ls-32);font-weight:var(--fw-semibold)}
.t-48{font-size:var(--fs-48);line-height:var(--lh-48);letter-spacing:var(--ls-48);font-weight:var(--fw-semibold)}

/* 🔴 EVERY NUMBER. Money, quantities, timestamps, IDs, distances, counts.
   Numbers that change width as they update is an instant amateur signal —
   and this is an invoicing product. */
.tnum{font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}

/* Text beside a line icon needs MEDIUM weight — regular looks anaemic
   against a 1.5px stroke (Atlassian's rule). */
.t-with-icon{font-weight:var(--fw-medium)}

/* Reading measure. Anything past ~75 characters is unreadable. */
.measure{max-width:68ch}

/* ─────────────────────────────────────────────────────────────────────────
   FOCUS — one treatment, product-wide.
   Use `outline`, NOT box-shadow: box-shadow rings vanish in Windows
   forced-colors mode. WCAG 2.2 SC 2.4.11 needs >=2px and >=3:1.
   ───────────────────────────────────────────────────────────────────────── */
:where(a,button,input,select,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--focus);
  outline-offset:2px;
  border-radius:var(--r-focus-md);
}

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