/* ============================================================================
   dpt.v1.css — the one place DPT brand values are defined.

   Consumed by: dpt-ops-dashboard, dpt-staff-dashboard, dpt-roster-portal,
   dpt-athlete-portal, dpt-habit-tracker, and the WordPress child theme.

   Token values come from astra_childtheme/style.css and the /style-guide/ page.
   They are copied here verbatim under --dp-* names. Where an app previously
   defined its own colour, it now aliases to one of these instead of holding a
   second copy that can drift.

   Rules for changing this file:
     1. Change a value HERE, never in an app.
     2. Bump nothing — the filename is versioned (v1). A breaking change means
        a dpt.v2.css that apps adopt one at a time.
     3. Run sync.mjs and push each app. The apps hold copies on purpose; see
        README.md for why a package or submodule was rejected.
   ========================================================================= */

/* ---------------------------------------------------------------- fonts ---
   Self-hosted so the type does not depend on a third party being reachable.
   Both are variable fonts: one file each covers every weight we use.
   Oswald is OFL-1.1, Roboto is Apache-2.0 — both permit self-hosting.
   The unicode-range is the Google "latin" subset; anything outside it falls
   back to the system stack rather than downloading a second file.
   font-display:swap so text is readable immediately on a slow gym connection.
   -------------------------------------------------------------------------*/
@font-face {
  font-family: 'Oswald';
  font-style: normal;
  font-weight: 200 700;
  font-display: swap;
  src: url('fonts/oswald.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('fonts/roboto.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* ---------------------------------------------------------- colour ---
     Verbatim from astra_childtheme/style.css. Do not "improve" these; the
     marketing site, the booking wizard and five apps all resolve them. */
  --dp-brand:        #FFC72C;   /* --c-brand       primary CTA on the site */
  --dp-brand-dark:   #D69E06;   /* --c-brand-dark  its hover */
  --dp-green:        #00753C;   /* --c-green       green that is safe as text */
  --dp-green-brand:  #00A651;   /* --c-green-brand fills, accents */
  --dp-green-hover:  #008C47;   /* --c-green-hover */
  --dp-ink:          #141A21;   /* --c-ink */
  --dp-ink-deep:     #0D1117;   /* --c-ink-deep    app chrome */
  --dp-slate:        #55606B;   /* --c-slate       muted text */
  --dp-paper:        #F4F4F4;   /* --c-paper */
  --dp-mint:         #E6F6EE;   /* --c-mint */
  --dp-border:       #D7DBD4;   /* --c-border */
  --dp-field-border: #92968F;   /* --c-field-border */
  --dp-field-hover:  #7A7F78;   /* --c-field-border-hover */
  --dp-white:        #FFFFFF;
  --dp-error:        #C43D3D;   /* --c-error       form validation */

  /* App-only additions. The site has no dark UI and one error colour; these
     screens rank severity and need to be read across a gym. Each status has a
     vivid MARK step for rails and fills, and a text-safe step — the same split
     as --dp-brand / --dp-brand-dark. Every pair was contrast-checked, not
     eyeballed; the numbers are in README.md. */
  --dp-good:         #00753C;
  --dp-good-wash:    #E6F6EE;
  --dp-warn:         #96540A;
  --dp-warn-wash:    #FBEFD8;
  --dp-crit:         #D92D20;   /* mark only — 4.1:1 on its wash, fails as text */
  --dp-crit-ink:     #C42115;   /* text step — 5.1:1 */
  --dp-crit-wash:    #FDECEA;
  --dp-raised-dark:  #1A222C;   /* the value v1.10.0 lifted cards to */

  /* ------------------------------------------------------- action pair ---
     One pair for every primary control, so no app has to decide again.

     The fill does not move: it is the vivid brand green. What moves is the
     label on top of it. White on #00A651 measures 3.19:1 and fails AA at any
     size that matters; the deep ink is 5.92:1 on the same fill. Dark type on
     a bright fill is also the site's own pattern — .btn.big has always been
     ink on #FFC72C at 12.22:1 — so this is the existing rule applied to the
     other brand colour rather than a new idea.

     Hover goes BRIGHTER, not darker. With a dark label, darkening the fill
     walks toward the label and kills the contrast; #00B357 is 6.84:1. */
  --dp-action:       #00A651;
  --dp-action-ink:   #0D1117;
  --dp-action-hover: #00B357;

  /* --------------------------------------------------- attention pair ---
     Gold is never text on a light surface. #D69E06 on white is 2.40:1 and
     there is no gold step that passes — the colour is defined by being
     bright. So gold is a fill, a pill or a rail, and ink sits on it. Where a
     light surface needs an action in words, that is green (--dp-green,
     5.82:1), not gold. */
  --dp-attention:     #FFC72C;
  --dp-attention-ink: #141A21;

  /* ------------------------------------------------------------ type --- */
  --dp-font-heading: 'Oswald', 'Roboto Condensed', 'Arial Narrow', sans-serif;
  --dp-font-body:    'Roboto', -apple-system, 'Segoe UI', Arial, sans-serif;
  --dp-fs-display: clamp(2.75rem, 1.5rem + 5vw, 4.5rem);
  --dp-fs-h1:      clamp(2.25rem, 1.4rem + 3.6vw, 3.5rem);
  --dp-fs-h2:      clamp(1.75rem, 1.3rem + 2vw, 2.5rem);
  --dp-fs-h3:      clamp(1.25rem, 1.1rem + .8vw, 1.5rem);
  --dp-fs-lead:    clamp(1.0625rem, 1rem + .5vw, 1.25rem);
  --dp-fs-body:    1rem;
  --dp-fs-small:   0.875rem;

  /* ---------------------------------------------------- space & shape --- */
  --dp-sp-1: 4px;  --dp-sp-2: 8px;  --dp-sp-3: 16px;
  --dp-sp-4: 24px; --dp-sp-5: 48px; --dp-sp-6: 96px;
  --dp-radius:    8px;
  --dp-radius-lg: 16px;
  --dp-btn-h:     48px;   /* standalone, per the site */
  --dp-btn-h-sm:  44px;   /* in-card, and the phone minimum */
  --dp-btn-h-desk: 40px;  /* app-only: dense tables. See README Deltas. */
  --dp-shadow:    0 4px 18px rgba(13,17,23,.14);
  --dp-shadow-lg: 0 12px 32px rgba(13,17,23,.18);
  --dp-measure:   65ch;
}

/* =============================================================== theme ===
   Light and dark, built on light-dark() rather than a duplicated block.

   How it resolves:
     - no data-theme      -> color-scheme: light dark, so the OS decides
     - data-theme=light   -> pinned light
     - data-theme=dark    -> pinned dark
   brand/theme.js sets the attribute before first paint and persists the
   choice; without JS the OS preference still works.

   Every token below is declared TWICE on purpose. The first declaration is
   the plain light value; the second wraps it in light-dark(). A browser too
   old for light-dark() (Safari < 17.5) drops the second as invalid and keeps
   the first, so it renders the light theme it has always rendered instead of
   an unstyled page. Do not "clean up" the duplicates.

   The raw palette above does NOT flip — #FFC72C is #FFC72C in both themes.
   What flips is this semantic layer, and apps alias to these names. That
   split is the whole reason an app can gain dark mode by editing one :root
   block rather than every rule it owns.
   -------------------------------------------------------------------------*/
:root                    { color-scheme: light dark; }
:root[data-theme="light"]{ color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

:root {
  /* --- surfaces --- */
  --dp-surface:        #F4F4F4;
  --dp-surface:        light-dark(#F4F4F4, #0D1117);   /* the page */
  --dp-surface-raised: #FFFFFF;
  --dp-surface-raised: light-dark(#FFFFFF, #1A222C);   /* cards, modals */
  --dp-surface-sunken: #ECEEF0;
  --dp-surface-sunken: light-dark(#ECEEF0, #080B0F);   /* wells, table heads */

  /* Chrome is the dark bar the apps already had in light mode, so it barely
     moves — it just stops being the only dark thing on the screen. */
  --dp-chrome:     #0D1117;
  --dp-chrome:     light-dark(#0D1117, #06090D);
  --dp-chrome-ink: #FFFFFF;
  --dp-chrome-ink: light-dark(#FFFFFF, #E8EBEE);

  /* --- text --- */
  --dp-text:       #141A21;
  --dp-text:       light-dark(#141A21, #E8EBEE);       /* 15.8:1 on surface */
  --dp-text-muted: #55606B;
  --dp-text-muted: light-dark(#55606B, #A2ADB6);       /* 8.3:1 on surface */
  --dp-line:       #D7DBD4;
  --dp-line:       light-dark(#D7DBD4, #2C3644);

  /* --- action ---
     BREAK 3 in README: on ink the green brightens to #2BE07B. #00A651 on
     #0D1117 is 5.9:1 — legal, but muddy at 12px in a bright gym. The bright
     step is 10.9:1. The label stays dark in both themes, so "green means it
     does something" survives the toggle. */
  --dp-action-t:      #00A651;
  --dp-action-t:      light-dark(#00A651, #2BE07B);
  --dp-action-t-ink:  #0D1117;
  --dp-action-t-ink:  light-dark(#0D1117, #06120B);
  --dp-action-t-hover:#00B357;
  --dp-action-t-hover:light-dark(#00B357, #5CE99A);

  /* Green as WORDS. On light that is the deep step; on dark the bright one,
     because a deep green on near-black is unreadable. */
  --dp-green-text: #00753C;
  --dp-green-text: light-dark(#00753C, #2BE07B);

  /* --- status ---
     Gold does not move: #FFC72C is 12.1:1 on the dark surface and 11.2:1
     under ink on a gold fill. It is the one brand colour that needs no
     dark-mode variant. */
  --dp-good-t:      #00753C;
  --dp-good-t:      light-dark(#00753C, #2BE07B);
  --dp-good-wash-t: #E6F6EE;
  --dp-good-wash-t: light-dark(#E6F6EE, #0E2A1C);
  --dp-warn-t:      #96540A;
  --dp-warn-t:      light-dark(#96540A, #F0B45A);
  --dp-warn-wash-t: #FBEFD8;
  --dp-warn-wash-t: light-dark(#FBEFD8, #2A2413);
  --dp-crit-t:      #C42115;
  --dp-crit-t:      light-dark(#C42115, #FF8078);
  --dp-crit-wash-t: #FDECEA;
  --dp-crit-wash-t: light-dark(#FDECEA, #2B1614);

  --dp-shadow-t:    0 4px 18px rgba(13,17,23,.14);
  --dp-shadow-t:    light-dark(0 4px 18px rgba(13,17,23,.14), 0 4px 18px rgba(0,0,0,.5));
}

/* The focus ring has to be visible on both. The bright green is 10.9:1 on the
   dark surface and still 3.4:1 on the light one, which clears the 3:1 that
   non-text UI needs. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline-color: var(--dp-action-t);
}

/* The toggle itself, so no app writes its own. Sits happily in a dark bar or
   on a light surface: it borrows whatever text colour it inherits. */
.dp-theme-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; padding: 0;
  border: 1px solid currentColor; border-radius: 8px;
  background: transparent; color: inherit; cursor: pointer;
  opacity: .75; transition: opacity .12s;
}
.dp-theme-btn:hover { opacity: 1; }
.dp-theme-btn svg { display: block; width: 17px; height: 17px; }
/* Only one of the two icons is ever shown. */
:root[data-theme="dark"] .dp-theme-btn .dp-i-moon,
:root:not([data-theme="dark"]) .dp-theme-btn .dp-i-sun { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .dp-theme-btn .dp-i-moon { display: none; }
  :root:not([data-theme]) .dp-theme-btn .dp-i-sun  { display: block; }
}

/* ------------------------------------------------------- shared floor ---
   The accessibility baseline every app was missing. Scoped to plain elements
   so adopting this file cannot restyle an app's existing components.
   -------------------------------------------------------------------------*/

/* A visible focus ring on everything keyboard-reachable. None of the five apps
   had one; :focus-visible means mouse users never see it. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--dp-green-brand);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Respect the OS setting. Vestibular disorders are not an edge case. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Tap targets. Applied opt-in via .dp-tap so it cannot silently resize an
   app's existing controls — add the class where a target is too small. */
.dp-tap { min-height: var(--dp-btn-h-sm); min-width: var(--dp-btn-h-sm); }

/* Screen-reader-only text, for icon-only controls that need a name. */
.dp-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Wide content must scroll inside its own box, never the page body. */
.dp-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Digits that stack in columns should line up. */
.dp-num { font-variant-numeric: tabular-nums; }
