/*
Theme Name:   Dean Izod
Theme URI:    https://deanizod.com
Description:  Child theme of Twenty Twenty-Five for the Dean Izod portfolio. Built to the Drafting Table Figma framework (file ovoRtIozPfWjs4nCFAlEMX). Tokens are defined here and in theme.json; nothing is hard-coded in templates.
Author:       Dean Izod
Author URI:   https://deanizod.com
Template:     twentytwentyfive
Version:      0.4.1
Requires at least: 6.7
Tested up to: 7.1
Requires PHP: 8.1
License:      GPL-2.0-or-later
Text Domain:  dean-izod
*/

/* ===========================================================================
   COLOUR TOKENS
   19 tokens, read from the Figma Colour variable collection.
   Light is the authored mode. Dark is the mode the site ships in.
   =========================================================================== */

:root {
  /* Grounds */
  --c-bg-page:            #FAF9F6;
  --c-bg-raised:          #FFFFFF;
  --c-bg-sunken:          #F2F0EA;
  --c-bg-inverse:         #1A1A17;
  --c-bg-accent:          #C2452C;
  --c-bg-accent-subtle:   #F7E8E4;

  /* Text */
  --c-text-primary:           #1A1A17;  /* 16.6:1 on page */
  --c-text-secondary:         #6E6B62;  /*  5.1:1 on page */
  --c-text-tertiary:          #767369;  /*  4.5:1 — LOCKED, do not lighten */
  --c-text-accent:            #A5331C;  /*  6.5:1 on page */
  --c-text-on-inverse:        #FAF9F6;
  --c-text-on-accent:         #FFFFFF;
  --c-text-accent-on-inverse: #D4604A;  /*  4.6:1 on ink */

  /* Stroke */
  --c-border-hairline:    #D6D3CA;
  --c-border-strong:      #1A1A17;
  --c-border-on-inverse:  #4A4842;
  --c-border-accent:      #C2452C;
  --c-border-field:       #767369;  /* 4.5:1 — WCAG 1.4.11 control boundary. LOCKED. */
}

/* ---------------------------------------------------------------------------
   DARK — the shipping mode.

   Eight values marked (figma) are confirmed from the handoff note, page 6.
   Eleven marked (derived) were worked out on 31 October from the logic of the
   set, not read from the Colour collection. Every one is contrast-checked and
   the ratio is noted. If the Dark mode in Figma disagrees, Figma wins — these
   are a working set so the site can be built, not a design decision.

   The derivation, so it can be argued with:
   - bg/inverse flips to the paper ground. The handoff note states this
     outright: "the footer is bound to bg/inverse, which in Dark mode resolves
     to the light paper." Everything "on-inverse" therefore takes its LIGHT
     value, because the inverse ground in Dark is the light ground.
   - the accent holds its hue in both modes. #C2452C carries white at 5.02:1
     either way, so a filled accent block needs no second value.
   - border/field must clear 4.5:1 for WCAG 1.4.11. #8A867C gives 5.12:1 on
     page and 4.70:1 on raised. It is the tertiary text value, reused.
   --------------------------------------------------------------------------- */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --c-bg-page:         #131312;  /* figma  */
    --c-bg-raised:       #1C1C1A;  /* figma  */
    --c-bg-sunken:       #0B0B0A;  /* figma  */
    --c-text-primary:    #F4F2EC;  /* figma  — 16.6:1 on page */
    --c-text-secondary:  #A8A49A;  /* figma  */
    --c-text-tertiary:   #8A867C;  /* figma  — 4.70:1 on raised, the floor */
    --c-text-accent:     #E0705A;  /* figma  */
    --c-border-hairline: #2E2E2B;  /* figma  */

    --c-bg-inverse:             #FAF9F6;  /* derived — the paper ground */
    --c-bg-accent:              #C2452C;  /* derived — unchanged */
    --c-bg-accent-subtle:       #2A1714;  /* derived — 15.2:1 w/ primary */
    --c-text-on-inverse:        #131312;  /* derived — 17.7:1 on inverse */
    --c-text-on-accent:         #FFFFFF;  /* derived — 5.02:1 on accent */
    --c-text-accent-on-inverse: #A5331C;  /* derived — 6.45:1 on inverse */
    --c-border-strong:          #F4F2EC;  /* derived — 16.6:1 on page */
    --c-border-on-inverse:      #D6D3CA;  /* derived — decorative hairline */
    --c-border-accent:          #C2452C;  /* derived — unchanged */
    --c-border-field:           #8A867C;  /* derived — 5.12:1, clears 1.4.11 */
  }
}

:root[data-theme="dark"] {
  --c-bg-page:         #131312;
  --c-bg-raised:       #1C1C1A;
  --c-bg-sunken:       #0B0B0A;
  --c-text-primary:    #F4F2EC;
  --c-text-secondary:  #A8A49A;
  --c-text-tertiary:   #8A867C;
  --c-text-accent:     #E0705A;
  --c-border-hairline: #2E2E2B;

  --c-bg-inverse:             #FAF9F6;
  --c-bg-accent:              #C2452C;
  --c-bg-accent-subtle:       #2A1714;
  --c-text-on-inverse:        #131312;
  --c-text-on-accent:         #FFFFFF;
  --c-text-accent-on-inverse: #A5331C;
  --c-border-strong:          #F4F2EC;
  --c-border-on-inverse:      #D6D3CA;
  --c-border-accent:          #C2452C;
  --c-border-field:           #8A867C;
}

/* ===========================================================================
   GROUND CONTEXTS
   The Figma variant names Paper and Ink read backwards once the file runs
   dark. Paper = sits on the page ground. Ink = sits on the inverted ground.
   Build to these class names, never to the variant words.
   =========================================================================== */

.is-on-page {
  --ground:        var(--c-bg-page);
  --ground-text:   var(--c-text-primary);
  --ground-quiet:  var(--c-text-secondary);
  --ground-accent: var(--c-text-accent);
  --ground-rule:   var(--c-border-hairline);
}

.is-on-inverse {
  --ground:        var(--c-bg-inverse);
  --ground-text:   var(--c-text-on-inverse);
  --ground-quiet:  var(--c-text-secondary);
  --ground-accent: var(--c-text-accent-on-inverse);
  --ground-rule:   var(--c-border-on-inverse);
}

/* On sunken grounds, tertiary text fails at 4.2:1. Step it up to secondary.
   This is a rule from the Figma accessibility pass, enforced here. */
.is-on-sunken {
  --c-text-tertiary: var(--c-text-secondary);
}

/* ===========================================================================
   SPACING — 4px base, twelve steps
   =========================================================================== */

:root {
  --s-2xs: 4px;
  --s-xs:  8px;
  --s-sm:  12px;
  --s-md:  16px;
  --s-lg:  24px;
  --s-xl:  32px;
  --s-2xl: 48px;
  --s-3xl: 64px;
  --s-4xl: 96px;
  --s-5xl: 128px;
  --s-6xl: 160px;
  --s-7xl: 200px;

  /* Section rhythm. 80px is off the 4px scale — it is measured from the
     frames, not documented. Flagged for Dean: 80 or 96 (--s-4xl)? */
  --s-section: 80px;
}

/* ===========================================================================
   GRID
   Canvas widths 1440 / 834 / 390. Container = canvas minus two margins.
   =========================================================================== */

:root {
  --container: 1248px;
  --margin:    96px;
  --gutter:    24px;
  --columns:   12;
  --measure:   760px;  /* hard cap on any body column, whatever the container */
}

/* ===========================================================================
   BREAKPOINTS — settled 31 October

   1024px and 768px. The Figma canvases are 1440 / 834 / 390, which are
   drawing widths, not thresholds: a 1440 design has to hold up at 1280 and
   1366, which are the two commonest laptop widths, so the first break sits
   above 834 rather than on it.

   Where the file contradicted itself, the written spec board won over the
   drawn frame. The spec says the nav becomes a drawer "at 834"; the 834
   frame still shows a full desktop header. 834 is below 1024, so the drawer
   is on by then and the written rule holds. The drawn frame is the error.

   768 is taken verbatim from the spec board: buttons go full width below it
   and the List work card is not used below it.
   =========================================================================== */

@media (max-width: 1023px) {
  :root {
    --container: 738px;
    --margin:    48px;
    --gutter:    20px;
    --columns:   8;
    --measure:   none;
  }
}

@media (max-width: 767px) {
  :root {
    --container: 350px;
    --margin:    20px;
    --gutter:    16px;
    --columns:   4;
  }
}

/* ===========================================================================
   STROKE AND RADIUS
   Namespaced apart from the colour tokens of the same name, which collide
   in the Figma file (border/hairline is both a colour and a width).
   =========================================================================== */

:root {
  --bw-hairline: 1px;
  --bw-medium:   2px;
  --bw-accent:   2px;
  --radius-sm:   2px;  /* form inputs only. Everything else is square. */
}

/* No shadow or elevation tokens exist, by design. Lift is done with hairlines. */

/* ===========================================================================
   BASE
   =========================================================================== */

body {
  background: var(--c-bg-page);
  color: var(--c-text-primary);
}

/* Focus is a hard requirement. Do not remove it. The browser default is not
   sufficient against either ground. Applies to cards and nav links too —
   the Figma file specifies focus on Button and Form Field only, which is a
   gap flagged in the audit. */
:where(a, button, input, textarea, select, [tabindex]):focus-visible {
  outline: var(--bw-accent) solid var(--c-border-accent);
  outline-offset: 3px;
}

/* ===========================================================================
   MOTION
   prefers-reduced-motion is a hard requirement, not a nicety.
   =========================================================================== */

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