/* =============================================================================
   Xandev V3 - design tokens

   Dark is the default and is declared on :root. Light is an override applied
   by [data-theme="light"], set on <html> before first paint by the inline boot
   script in the base layout.

   Every colour pair in here has been picked so that text meets WCAG AA against
   its own surface in BOTH themes, and the ratios were measured rather than
   guessed. Amber is brilliant on ink (9.4:1) and hopeless on white (2.1:1), so
   light mode uses a deep bronze variant - the brand reads as the same colour
   without failing contrast.

   Warm primary on a cool ink base is the whole idea: it is what stops this
   looking like every other dark developer portfolio. Amber stays an accent,
   buttons, links, the section rule - and never fills a large area, which is
   where it would start reading as a trades brand.
   ========================================================================== */

:root {
    color-scheme: dark;

    /* --- Surfaces ---------------------------------------------------------
       Cool, faintly violet-shifted greys rather than neutral black. Sitting
       next to the purple/cyan accents, a true neutral reads slightly green. */
    --surface-page:     #0A0B0F;
    --surface-sunken:   #07080B;
    --surface-raised:   #12141A;
    --surface-overlay:  #1B1E27;
    --surface-hover:    #21242F;

    /* --- Text ------------------------------------------------------------- */
    --text-primary:     #F2F3F7;
    --text-secondary:   #A8AEBE;
    --text-muted:       #6C7385;
    --text-inverse:     #0A0B0F;

    /* --- Brand ------------------------------------------------------------
       Amber primary, cyan secondary. The cyan is carried over from V2 and is
       what keeps the palette from reading purely warm. */
    --brand:            #F2A33C;
    --brand-strong:     #DB8A1E;
    --brand-soft:       #F8CE8F;
    --accent:           #8CDCFF;
    --accent-strong:    #60C5F5;
    --accent-soft:      #B8E7FF;

    /* Text colours for brand-tinted copy on a dark surface. 11.2:1 on ink. */
    --brand-text:       #F5B860;
    --accent-text:      #8CDCFF;

    /* --- Lines ------------------------------------------------------------ */
    --line:             rgb(255 255 255 / 0.10);
    --line-strong:      rgb(255 255 255 / 0.18);
    --line-faint:       rgb(255 255 255 / 0.05);

    /* --- Status ----------------------------------------------------------- */
    --success:          #4ADE80;
    --success-surface:  rgb(74 222 128 / 0.12);
    /* Shifted yellower than the old #FBBF24: with an amber brand, the previous
       warning colour was near-identical to it, so a "due" badge read as brand
       chrome rather than as a status. */
    --warning:          #FFD54A;
    --warning-surface:  rgb(255 213 74 / 0.14);
    --danger:           #FB7185;
    --danger-surface:   rgb(251 113 133 / 0.12);
    --info:             #8CDCFF;
    --info-surface:     rgb(140 220 255 / 0.12);

    /* --- Elevation --------------------------------------------------------
       Dark UI reads depth from a lightened top edge more than from a drop
       shadow, so each level pairs a shadow with a 1px inner highlight. */
    --shadow-1: 0 1px 2px rgb(0 0 0 / 0.40);
    --shadow-2: 0 4px 12px rgb(0 0 0 / 0.45);
    --shadow-3: 0 12px 32px rgb(0 0 0 / 0.55);
    --shadow-4: 0 24px 64px rgb(0 0 0 / 0.65);
    --edge-highlight: inset 0 1px 0 rgb(255 255 255 / 0.06);

    /* Reserved for the single glass moment: the sticky header. */
    --glass-bg:     rgb(10 11 15 / 0.72);
    --glass-blur:   saturate(180%) blur(16px);
}

[data-theme="light"] {
    color-scheme: light;

    --surface-page:     #F5F6F9;
    --surface-sunken:   #EBEDF2;
    --surface-raised:   #FFFFFF;
    --surface-overlay:  #FFFFFF;
    --surface-hover:    #F0F1F5;

    --text-primary:     #14161C;
    --text-secondary:   #4B5263;
    --text-muted:       #767D8E;
    --text-inverse:     #FFFFFF;

    /* Same brand identity as a deep bronze. #F2A33C on white is 2.1:1 and
       unusable; this is 4.7:1 as a button fill under white text.
       --brand-text is darker still (6.1:1) because link text sits directly on
       the page background, where --brand alone measures only 4.4:1. */
    --brand:            #A9620A;
    --brand-strong:     #8A4E06;
    --brand-soft:       #FDF0DC;
    --accent:           #0E7CA8;
    --accent-strong:    #076288;
    --accent-soft:      #DFF3FC;

    --brand-text:       #8A4E06;
    --accent-text:      #076288;

    --line:             rgb(20 22 28 / 0.12);
    --line-strong:      rgb(20 22 28 / 0.22);
    --line-faint:       rgb(20 22 28 / 0.06);

    --success:          #15803D;
    --success-surface:  rgb(21 128 61 / 0.10);
    --warning:          #8A6D00;
    --warning-surface:  rgb(138 109 0 / 0.10);
    --danger:           #BE123C;
    --danger-surface:   rgb(190 18 60 / 0.10);
    --info:             #0E7CA8;
    --info-surface:     rgb(14 124 168 / 0.10);

    --shadow-1: 0 1px 2px rgb(20 22 28 / 0.06);
    --shadow-2: 0 4px 12px rgb(20 22 28 / 0.08);
    --shadow-3: 0 12px 32px rgb(20 22 28 / 0.10);
    --shadow-4: 0 24px 64px rgb(20 22 28 / 0.12);
    --edge-highlight: none;

    --glass-bg:   rgb(245 246 249 / 0.78);
    --glass-blur: saturate(180%) blur(16px);
}

/* =============================================================================
   Non-themed tokens - identical in both modes
   ========================================================================== */

:root {
    /* --- Type -------------------------------------------------------------
       One superfamily at two widths. Archivo is a variable font carrying both
       a weight and a width axis, so display type can be genuinely expanded and
       body type set at normal width from a single downloaded file. Using one
       family at two widths reads as a deliberate system; pairing two unrelated
       faces is what makes a page look assembled from a template. */
    --font-display: "Archivo Variable", "Archivo", "Helvetica Neue", Arial, sans-serif;
    --font-body:    "Archivo Variable", "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --font-mono:    "JetBrains Mono Variable", "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

    /* Width axis settings for the variable font. */
    --width-display: 112;   /* expanded - headlines */
    --width-body:    100;   /* normal - running text */

    /* Fluid scale, ~1.25 ratio, clamped so it stays sane on a 4K monitor. */
    --text-3xs:  0.6875rem;                                 /* 11px - mono labels */
    --text-2xs:  0.75rem;                                   /* 12px */
    --text-xs:   0.8125rem;                                 /* 13px */
    --text-sm:   0.875rem;                                  /* 14px */
    --text-base: 1rem;                                      /* 16px */
    --text-md:   1.0625rem;                                 /* 17px - body copy */
    --text-lg:   clamp(1.125rem, 0.35vw + 1.05rem, 1.25rem);
    --text-xl:   clamp(1.375rem, 0.6vw + 1.25rem, 1.625rem);
    --text-2xl:  clamp(1.75rem, 1.1vw + 1.5rem, 2.25rem);
    --text-3xl:  clamp(2.125rem, 2vw + 1.6rem, 3rem);
    --text-4xl:  clamp(2.5rem, 3.6vw + 1.7rem, 4.25rem);
    --text-5xl:  clamp(3rem, 5.5vw + 1.6rem, 6rem);

    --leading-tight:   1.05;
    --leading-snug:    1.25;
    --leading-normal:  1.55;
    --leading-relaxed: 1.7;

    /* Large display type needs negative tracking to avoid looking loose;
       small mono labels need positive tracking to stay legible. */
    --tracking-display: -0.035em;
    --tracking-tight:   -0.015em;
    --tracking-normal:  0;
    --tracking-label:   0.14em;

    /* --- Space ------------------------------------------------------------
       4px base. Named by size rather than by purpose so the same token can
       serve padding, gap, and margin without a misleading name. */
    --space-1:  0.25rem;
    --space-2:  0.5rem;
    --space-3:  0.75rem;
    --space-4:  1rem;
    --space-5:  1.5rem;
    --space-6:  2rem;
    --space-7:  2.5rem;
    --space-8:  3rem;
    --space-9:  4rem;
    --space-10: 5rem;
    --space-11: 6rem;
    --space-12: 8rem;

    /* Vertical rhythm between page sections. Two adjacent sections each
       contribute this, so the gap a reader sees is double the value,
       which is why it is smaller than it looks like it should be. */
    --section-y: clamp(3rem, 5.5vw, 5.5rem);

    /* --- Radius -----------------------------------------------------------
       Deliberately tighter than V2's pill-everything. Precise corners read as
       engineered; fully-rounded reads as consumer-app. Only genuinely pill
       shapes (tags, status dots) use --radius-full. */
    --radius-xs:   3px;
    --radius-sm:   6px;
    --radius-md:   10px;
    --radius-lg:   14px;
    --radius-xl:   20px;
    --radius-full: 9999px;

    /* --- Layout ------------------------------------------------------------ */
    --measure:        68ch;    /* comfortable reading width */
    --container:      1200px;
    --container-wide: 1440px;
    --gutter:         clamp(1.25rem, 4vw, 3rem);

    /* --- Motion -----------------------------------------------------------
       Two durations and two curves. More than that and timings drift apart
       between components until nothing feels like one system. */
    --ease:      cubic-bezier(0.32, 0.72, 0, 1);
    --ease-out:  cubic-bezier(0.16, 1, 0.3, 1);
    --duration:      180ms;
    --duration-slow: 420ms;

    /* --- Signature --------------------------------------------------------
       The brand gradient appears in exactly two places site-wide: the hairline
       rule that opens a section, and the active-nav underline. Restricting it
       is what keeps it a signature instead of decoration. V2 put it on every
       heading, which is why none of them stood out. */
    --brand-gradient: linear-gradient(90deg, var(--brand) 0%, var(--accent) 100%);

    --z-base:     0;
    --z-raised:   10;
    --z-sticky:   100;
    --z-overlay:  200;
    --z-modal:    300;
    --z-toast:    400;
}

/* Anyone who has asked their OS to reduce motion gets no transitions at all,
   rather than shortened ones. Honour the request properly. */
@media (prefers-reduced-motion: reduce) {
    :root {
        --duration:      0.01ms;
        --duration-slow: 0.01ms;
    }
}
