/* Madar design tokens -- docs/DESIGN_SYSTEM.md §2 (colour), §3 (type), §6.1
   (spacing/radii), §10 (focus). THIS FILE IS THE ONLY PLACE A HEX VALUE MAY
   APPEAR. Everything else uses var(--...). Enforced by core/test_design_rules.py.

   Do not add component styles here; see base.css.

   HOW TO READ THIS FILE
   Every light token is immediately followed by its dark twin, in role order, so a
   reviewer can see at a glance that no token lost its pair. The pairing table comes
   from docs/design/artboards/theme.py -- the script that generated all 34 dark
   artboards from their light originals -- which is why no two dark screens disagree.
   Dark mode is a token swap, never a second stylesheet and never per-screen values.

   THREE THEME STATES, in this order (the order matters):
     1. :root                                   -- light, the default
     2. @media (prefers-color-scheme: dark)     -- the OS preference, when the user
        :root:not([data-theme="light"])            has expressed none. Guarded so an
                                                   explicit "light" choice still wins.
     3. :root[data-theme="dark"]                -- an explicit choice, wins over both
   base.html also stamps data-theme before first paint, so there is no flash; the
   media block is the no-JS fallback, not the primary path.

   Replaced 15 Sep 2026. The previous palette (--primary #0D6E5C jade, a gold
   --accent, a --shadow) is gone -- see docs/DESIGN_SYSTEM.md §2. Two traps if you
   are reading older code:
     * --bg and --surface SWAPPED MEANINGS. --bg is now the tint (#FAFAF8) and
       --surface is white. Old code written against the reverse is inverted, not
       merely off-colour, and white-on-white raises no error anywhere.
     * --accent, --accent-soft, --shadow, --text, --text-muted, --text-inverse and
       --surface-raised no longer exist. See §2.2 for what replaced each. */

:root {

  /* ==== SURFACES AND STRUCTURE (§2.2) ============================ light ==== */
  --bg:               #FAFAF8;  /* the content area's ground                    */
  --surface:          #FFFFFF;  /* cards, tables, forms                         */
  --surface-2:        #FCFCFA;  /* table head, pagination footer                */
  --border:           #E8E7E3;  /* every card and input border                  */
  --row:              #F4F3EF;  /* divider between table rows; skeleton fill    */
  --line:             #F1F0EC;  /* rule above/below a card header               */
  --chip:             #F4F5F1;  /* tab container, neutral fill                  */
  --chip-2:           #F1F2EE;  /* secondary button fill                        */

  /* ==== INK ====================================================== light ==== */
  --ink:              #16211A;  /* body text and headings                       */
  /* #687268 IS THE PACKAGE'S VALUE as of Issue 13, which fixed the light
     muted ink at source (#8A938B was 3.2:1 on white, under AA for the
     11-13px text it carries everywhere). This project had already corrected
     it independently, to #677068, and Issue 13 blesses that: "shipped
     tokens that match these three categories are hereby blessed -- they are
     now package values."

     Taking the package's exact figure anyway, because the two differ by one
     unit of red and nothing else, and a permanent 1-off between the token
     and every artboard that draws it is noise in every future likeness
     check for no gain. 5.01:1 on white, 4.79:1 on the page ground, 4.57:1
     on the --chip -- the worst case the package quotes. */
  --muted:            #687268;  /* secondary lines, table head labels           */
  --muted-warm:       #6A746B;  /* page-header description, KPI label           */
  --muted-2:          #5F6A61;  /* form labels, inactive tab text               */
  --faint:            #8B8F8B;  /* adjacent-month day numbers                   */
  --chevron:          #8A908A;  /* the row-end arrow                            */
  --on-primary:       #FDFDFD;  /* text on the PRIMARY FILL only -- split from
                                   --on-dark on 17 Sep 2026, when the calendar
                                   package lifted the dark primary and paired
                                   it with dark ink: one token can no longer
                                   serve both a light fill and a dark ground.
                                   #FDFDFD, not #FFFFFF, on purpose: in this
                                   system #FFFFFF means A SURFACE and #FDFDFD
                                   means FOREGROUND WHITE (§2.1).               */
  --on-dark:          #FDFDFD;  /* text on a DARK GROUND (sidebar, topbar,
                                   auth brand panel, marketing footer) -- the
                                   role --on-primary used to also carry.       */

  /* ==== SIDEBAR -- a dark surface in BOTH themes (§6.2) ========== light ==== */
  --sidebar:          #14261A;
  --sidebar-active:   #1F3A28;
  --sidebar-text:     #9FB0A4;
  --sidebar-dim:      #7E9184;  /* role line, bell                              */
  --sidebar-dim-2:    #7B9081;  /* date line -- LIGHTENED, see below            */
  --sidebar-line:     #22372A;  /* rule above the user block                    */
  --sidebar-badge:    #223A2A;  /* inactive counter pill background             */

  /* THE ACTIVE ROW'S ICON (SHELL_SPEC §2b, 6 Oct package). The reference does
     this with its brand red; ours is the brand's light green. Deliberately
     the SAME value in both themes -- it is absent from the package's
     theme.py swap table, so the generated dark twins keep it, and one value
     that is right on both grounds beats two that can disagree.
     Measured on every ground it is painted on: 9.07:1 on --sidebar and
     7.07:1 on --sidebar-active in light; 11.99:1 and 10.3:1 in dark. */
  --sidebar-accent:   #7FD69B;

  /* THE LOCKED SHELL'S PROGRESS BAR (ONBOARDING_SPEC §0 -- the N/7 card that
     sits where the date line usually does). A GRAPHIC: a 5px bar, measured
     at 3:1 against the track it is painted on, which is --sidebar.

     THE SAME VALUE IN BOTH THEMES, and for the same reason --sidebar-accent
     is: the package's theme.py carries no swap for the drawn #56705E, so
     `OnboardingDark.dc.html` draws the same value on a dark ground too --
     one value that is right on both beats two that can disagree. Verified by
     reading the generated dark twin, not assumed from the absence.

     A MEASURED CORRECTION TO THE DRAWING, not the drawing. #56705E is
     2.93:1 on light --sidebar -- under WCAG 1.4.11's 3:1 for a graphic, and
     the bar is the ONLY thing carrying "how far along am I" at a glance, so
     3:1 is owed rather than arguable. Re-derived by §2.3's discipline (hold
     hue and chroma, move lightness only): h and s are unchanged and
     lightness moves by 0.010, which lands on 3.05:1 light and 4.04:1 dark.
     The drawn value is one hundredth of a lightness step away and the two
     are indistinguishable side by side; recorded in docs/HANDOFF.md §7 so
     nobody "restores" it from the artboard. */
  --sidebar-progress: #587360;

  /* THE CURRENT STEP'S CARD FILL (ONBOARDING_SPEC §2: "2px primary border,
     `#FAFCFA` fill"). A GROUND, so it is in docs/design/contrast_check.py's
     GROUNDS table rather than in USAGE, and every foreground the step card
     paints on it is measured there.

     BOTH VALUES ARE THE PACKAGE'S OWN -- theme.py maps `"#FAFCFA":
     "#0A140D"  # highlighted step card`, so the dark half is the designer's
     answer to this question and not one invented here. The same blessed
     category --brand-ink is in.

     It needs a token of its own rather than borrowing --bg or --surface
     because it is neither: the step card is a card (--surface would make it
     indistinguishable from the six collapsed ones) sitting on the page
     ground (--bg at #FAFAF8 is the ground it has to read AGAINST). A faint
     tint between the two is the whole device. */
  --step-current-bg: #FAFCFA;

  /* THE BELL'S UNREAD COUNT (SHELL_SPEC §1). A MEASURED PAIR, not a ground
     with an assumed white numeral -- the numeral is 10px/700, so it is small
     text and owes 4.5:1, and the artboard's own dark twin does not clear it:
     theme.py USED TO swap the red #DC2626 -> #E05A5A, on which the drawn
     #FDFDFD numeral measured 3.57:1.

     SUPERSEDED 10 Oct 2026 by the package's Issue 13, which fixed it at
     source by darkening the GROUND rather than the numeral. This file's
     earlier resolution moved the numeral instead (#16211A on #E05A5A,
     4.56:1) -- a real fix, and the package's is better.
     Light: #FDFDFD on #DC2626 = 4.75:1. Dark: #FDFDFD on #C73A3A = 5.04:1. */
  /* THE GUEST-STATE PILLS' TWO OWN DOTS (GUESTS_SPEC §5). The other five
     states reuse tokens that already exist and already swap per theme --
     success, warning, info, --tag-text and --link -- which is the whole
     point of §1's "where a guest state shares a word with the grid it keeps
     the grid's colour exactly". Only these two had no token.

     Same value in both themes: each clears 3:1 on its own pill ground
     light AND dark, so a swap would be two numbers to keep right instead of
     one. Measured on --chip, the ground both are painted on.

     --guest-dot-none IS NOT THE ARTBOARD'S VALUE and that is a measured
     correction, not a preference. The drawing specifies #9AA39B, which is
     2.37:1 on --chip in light mode -- under 1.4.11's 3:1, which this
     project applies to status dots by its own standing convention (every
     *-dot token in contrast_check.USAGE is a "graphic"). #7F8880 is the
     nearest neutral of the same character that clears it: 3.34:1 light,
     4.72:1 dark. Recorded in docs/LIKENESS.md. */
  --guest-dot-upcoming: #4F7A58;   /* 4.50:1 light, 3.50:1 dark on --chip   */
  --guest-dot-none:     #7F8880;   /* 3.34:1 light, 4.72:1 dark on --chip   */

  --badge-urgent:      #DC2626;
  --badge-urgent-text: #FDFDFD;

  /* DANGER TEXT ON THE SIDEBAR'S DARK GROUND -- the phone drawer's
     «تسجيل الخروج» row (SHELL_SPEC §3, MobileDrawer).

     Needed because neither existing danger token works here, and both were
     measured rather than assumed: --danger-text (#8A372C) is dark-on-dark,
     and --danger-dot (#C65748) is 3.68:1 on --sidebar -- under the 4.5:1
     this row owes as 14px text.

     The value is the PACKAGE'S OWN: theme.py maps the artboard's logout red
     #B42318 to #F09B9B for a dark ground, so this is the designer's answer
     to this exact question rather than one invented here. Same in both
     themes; worst case 5.82:1 (light --sidebar-active), best 9.87:1. */
  --danger-on-dark:    #F09B9B;

  /* ==== BRAND ==================================================== light ==== */
  --primary:          #27462E;  /* a FILL. Never used as text -- see --link.    */
  --primary-hover:    #1B331F;  /* ADDITION -- 01 specifies no hover (§11)      */
  --primary-soft:     #E9F0EC;

  /* The brand colour AS TEXT. Split from --primary 15 Sep 2026 because the
     two have different contrast thresholds and only one of them passed: a
     fill needs 3:1 as a graphic, a link needs 4.5:1 as text, and in dark mode
     --primary measured 3.77:1 as link text on --surface. Conflating them is
     what hid that. --primary fills; --link is read. */
  --link:             #27462E;
  /* THE BRAND/LOGO CHIP'S INK -- its own token since the token sync round
     (11 Oct 2026), and the designer's blessed category (a).

     It was `var(--link)`, which was already the SECOND answer here: the
     first was `--sidebar`, which is #000000 in dark against a #132A1D
     fill -- 1.38:1, an invisible glyph on every authenticated screen.
     `--link` fixed the invisibility (4.80:1 dark) but it is a different
     ROLE wearing the same number, and the package does not agree with it:
     it draws this chip 39 times per theme as #14261A on #E9F0EC and
     #7FD69B on #132A1D -- 13.72:1 and 8.71:1. The designer's own fix is a
     BRAND_CHIP sentinel in theme.py for exactly this reason.

     Neither value is new to the palette (#14261A is light --sidebar,
     #7FD69B is dark --weekend-text), so this splits a role out rather
     than adding a colour. Both painters of the square take it -- the app
     sidebar/login panel (.wordmark__glyph) and the marketing footer
     (.m-wordmark--on-dark .m-wordmark__glyph), which base.css and
     marketing.css already record as the same square. */
  --brand-ink:        #14261A;
  --link-hover:       #1B331F;

  /* The inverted ground: active tab, active filter chip, active page button.
     MUST be its own pair, not --ink + --on-primary: in dark mode --ink and
     --on-primary are BOTH #F0F5F1, so that combination rendered the active
     tab as light text on a light fill -- contrast 1.00:1, invisible. Found
     by the §12 audit, not by looking. */
  --inverse-surface:  #16211A;
  --on-inverse:       #FDFDFD;

  /* ==== STATUS (§2.3 -- re-derived from this palette, NOT 01's values) light = */
  /* Chroma capped at the brand's own; hues pulled onto the palette's axes.
     MEASURED, not estimated (core/test_design_rules.py recomputes these on
     every run). Worst ratio against any ground each token is used on:
       light text  5.15-6.81   (5.15 is --neutral-text; an earlier comment
                                here said "6.3-7.9" and silently excluded it)
       light dots  3.12-3.73   (was stated as 3.3-4.3)
       dark  text  8.77-10.34
       dark  dots  3.94-6.56   (was stated as 5.3-7.2; 3.94 is --neutral-dot)
     AA normal text 4.5 + WCAG 1.4.11 graphic 3.0, both themes.               */
  --success-bg:       #E7F4E9;
  --success-border:   #D2E6D5;
  --success-text:     #2E623B;
  --success-dot:      #4E925E;

  --warning-bg:       #FAF2D2;
  --warning-border:   #ECE1B8;
  --warning-text:     #6B530C;
  --warning-dot:      #A2801A;

  --danger-bg:        #FEEAE7;
  --danger-border:    #F5D7D2;
  --danger-text:      #8A372C;
  --danger-dot:       #C65748;

  --info-bg:          #E4F1FE;
  --info-border:      #CDE2F5;
  --info-text:        #225984;
  --info-dot:         #3C86C0;

  --neutral-bg:       #F4F5F1;  /* cancelled / expired / no-state               */
  --neutral-border:   #D5DAD3;  /* ADDED 18 Sep 2026 -- the neutral ramp was the
                                   only one of the five without a border, so the
                                   grid's blocked pill borrowed --faint. The
                                   agenda's «مسجَّل» pill draws this exact value
                                   (CalendarAgenda.dc.html), which completes the
                                   ramp rather than repeating the workaround.  */
  --neutral-text:     #5F6A61;
  --neutral-dot:      #848D85;

  /* ==== TAG AND AVATAR -- the palette's warm axis ================ light ==== */
  --tag-bg:           #F5EBDC;
  --tag-text:         #7A5B33;
  --avatar-bg:        #EDE3D4;
  --avatar-text:      #6B4F2C;

  /* ==== CALENDAR (§6.9) ========================================== light ==== */
  --weekend-header:   #F0F5F1;  /* Fri/Sat in the month head                    */
  --weekend-cell:     #F7FAF8;  /* Fri/Sat in the month body. CORRECTED from
                                   #FBFCFB on 19 Sep 2026: that value appears
                                   in NO artboard. Every calendar artboard
                                   that tints a weekend cell draws #F7FAF8 --
                                   the same value as --night-cell, which is
                                   why the two stay separate tokens: one
                                   value, two meanings, and a later change to
                                   either must not move the other.           */
  --weekend-text:     #1B5E34;  /* Fri/Sat's NAME in the month head. ADDED
                                   19 Sep 2026: CalendarMonth.dc.html tints
                                   the weekend header's TEXT as well as its
                                   ground, and the build only had the ground.
                                   Not --success-text: Friday is not a
                                   success, and a token borrowed for a
                                   meaning it does not have is how a later
                                   restyle of one moves the other.           */
  --night-cell:       #F7FAF8;  /* Day view: the 00-07 and 23 hour columns' tint */
  --chart-bar:        #27462E;  /* Dashboard: a collections bar (DASHBOARD_SPEC
                                   §5.1). A FILL, not a foreground -- nothing
                                   is ever painted on top of it, and bar height
                                   is data, so it carries no text to measure.  */
  --chart-rule:       #E8E7E3;  /* the 3px rule an EMPTY day draws instead of a
                                   gap. §5.1 is explicit that the owner must
                                   see the day happened and was empty, so this
                                   is a real mark with its own token rather
                                   than a lighter --chart-bar.                */
  --donut-1:          #27462E;  /* Dashboard: the units donut, largest segment
                                   first. Four shades of the ONE brand green
                                   (§6), stepped far enough apart to stay
                                   separable at a 2px gap. COLOUR IS NEVER THE
                                   ONLY SIGNAL here -- every segment is also
                                   named and numbered in the legend beside it,
                                   which is why these four are allowed to be
                                   shades of one hue at all.                  */
  --donut-2:          #4A7355;
  --donut-3:          #8FB39A;
  --donut-4:          #C7D8CC;
  --mast-icon:        #CBD8CE;  /* phone app-bar icon strokes -- the SAME value
                                   in both themes, as MobileShell and
                                   MobileShellDark both draw it              */
  --tag-on-dark:      #D6BF93;  /* BRONZE ON A DARK SURFACE, and the SAME value
                                   in both themes for the same reason
                                   --mast-icon above is: the sidebar is dark
                                   in BOTH, so a token painted on it has one
                                   correct value, not two.

                                   THE BACK-OFFICE'S THIRD STAFF MARK needs
                                   it (BACKOFFICE_SPEC §0: the brand sub-line
                                   reads «إدارة المنصة» in bronze). Neither
                                   existing bronze works there -- --tag-text
                                   is #7A5B33 in light mode, 1.9:1 on
                                   --sidebar, and --avatar-text's light value
                                   #6B4F2C is just as unusable. The lane that
                                   built the back-office could not add this:
                                   tokens.css is on docs/LANES.md's
                                   never-touch list by name, so it painted
                                   the sub-line --sidebar-dim and listed the
                                   need. This is that one line.

                                   MEASURED, not assumed: 8.88:1 on --sidebar
                                   in light and 11.73:1 in dark.             */
  --day-chip-active:  #FCFDFC;  /* MobileCalendar: today's chip fill on the mast */
  --day-chip-active-ink: #1A1F1B; /* the number on that fill                     */
  --day-chip-active-sub: #4A554C; /* the weekday word on that fill               */
  --free-dash:        #C3C8C3;  /* MobileCalendar: the free-unit card's dashes   */

  /* ==== FOCUS (§10) ============================================== light ==== */
  /* Two tokens because one cannot work: --focus on the sidebar measures 1.51:1
     -- the brand green on the dark-green sidebar is nearly the same colour.    */
  --focus:            #27462E;  /* rings on light grounds  (10.0-10.5:1)        */
  --focus-on-dark:    #E9F0EC;  /* rings inside the sidebar (10.7-13.7:1)       */

  /* ==== TYPOGRAPHY (§3) -- no dark variant ================================= */
  --font-sans: "IBM Plex Sans Arabic", "Noto Sans Arabic", "Segoe UI", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  /* Scale: 11/12/13/14(base)/15/17/20/24/26/32/38/56. Base is 14px, not 16px. */
  --fs-11: 11px;  --fs-12: 12px;  --fs-13: 13px;  --fs-14: 14px;
  --fs-15: 15px;  --fs-17: 17px;  --fs-20: 20px;  --fs-24: 24px;
  --fs-26: 26px;  --fs-32: 32px;  --fs-38: 38px;  --fs-56: 56px;

  /* ==== SPACING (§6.1) -- a value not on this scale is a bug =============== */
  --sp-2:  2px;   --sp-4:  4px;   --sp-6:  6px;   --sp-8:  8px;
  --sp-10: 10px;  --sp-12: 12px;  --sp-14: 14px;  --sp-16: 16px;
  --sp-18: 18px;  --sp-20: 20px;  --sp-22: 22px;  --sp-26: 26px;
  --sp-32: 32px;  --sp-48: 48px;  --sp-64: 64px;
  /* --sp-20 is NOT on 01 §4's scale (…18 / 22 / 26…), but 01 §5 requires a
     20px sidebar padding and 01 §6.9 a 20px gesture-area padding, and both
     artboards use 20px. 01 contradicts its own scale. Without this token the
     nearest value is 22px, which is what shipped in Phase A -- in one case
     under a comment that claimed 20px. Added as a recorded correction to 01
     rather than rounding the spec to fit the scale. */

  /* ==== RADII (§6.1) ====================================================== */
  --radius-xs:   6px;    /* status pills, tags, skeleton lines                 */
  --radius-sm:   8px;    /* inputs, buttons                                    */
  --radius:      10px;   /* cards                                              */
  --radius-lg:   12px;   /* large cards                                        */
  --radius-xl:   16px;   /* websites, the mobile centre action                 */
  --radius-pill: 999px;  /* pills, chips, toggles                              */

  /* ==== SHELL METRICS (§6.2) ============================================== */
  --sidebar-width: 248px;
  /* The collapsed icon rail (SHELL_SPEC §2b). Labels become tooltips; the
     active pill and the badges survive. */
  --sidebar-rail-width: 72px;
  /* The desktop top bar, owned by base.html and on EVERY desktop screen
     (SHELL_SPEC §1). This is the 56px every artboard frame grew by. */
  --appbar-height: 56px;
  /* 44px, not 42 (SHELL_SPEC §2b, 6 Oct package). It is also the touch
     target minimum the phone drawer owes, so the two rules now agree
     instead of the drawer having to override the sidebar. */
  --nav-item-height: 44px;
  --control-height: 44px;  /* buttons and fields -- the 44px touch target      */

  /* ==== THE SAFE AREA (device-matrix round, 15 Oct 2026) ==================
     THE OWNER'S DEFECT, ON HIS OWN iPhone 16 Pro Max: the bottom control bar
     sat behind Safari's own bottom bar. Two separate causes, and these two
     tokens are the second one's single point of truth.

     WHY A TOKEN AND NOT `env()` AT EACH SITE. `env(safe-area-inset-bottom)`
     was already written at two places in this project (base.css's drawer
     foot, wizard.css's action bar) and **both were inert**, because the
     viewport meta had no `viewport-fit=cover` -- without it the insets are
     defined to be zero. Two correct-looking lines did nothing for weeks and
     reading either one told you nothing. Routing every site through one
     token means there is exactly one place to check, and `cover` is now on
     the meta in `templates/base.html`.

     AND -- the reason this shape was chosen over `env()` inline -- a token
     is MEASURABLE OFF-DEVICE. Headless Chromium and WebKit both report
     these insets as 0px (measured, both engines; see
     `core/device_profiles.py`), so no emulator can prove the inset reaches
     the bar. A test CAN set `--safe-area-bottom: 34px` on the root and
     measure that the bar grew by 34px and stayed inside the viewport, which
     is what `core/test_device_matrix.py` does. Inline `env()` is
     unoverridable and therefore untestable here.

     The `0px` fallback is load-bearing, not defensive: `env()` with no
     fallback is INVALID on an engine that knows nothing of the variable,
     which takes the whole `calc()` with it. */
  --safe-area-bottom: env(safe-area-inset-bottom, 0px);
  --safe-area-top: env(safe-area-inset-top, 0px);
  /* THE INLINE INSETS ARE NOT OPTIONAL ONCE `cover` IS ON, and this is the
     part the round's brief did not ask for and the round needed anyway.
     `viewport-fit=cover` extends the layout viewport into EVERY unsafe
     area, not just the bottom one -- so an iPhone held in landscape puts
     ~47px of each side under the notch and the rounded corner. Adding
     `cover` without these two would have fixed a bottom bar and broken
     both page edges. */
  --safe-area-start: env(safe-area-inset-left, 0px);
  --safe-area-end: env(safe-area-inset-right, 0px);

  /* ==== THE PHONE SHELL'S BOTTOM BARS (device-matrix round, 15 Oct 2026) ==
     The height each bottom bar occupies BEFORE the safe-area inset is added.
     They exist because those bars became `position: fixed` in this round
     (see `.bottom-nav` in base.css for why `sticky` cannot work on iOS),
     and a fixed bar is out of flow -- so the content column has to reserve
     exactly this much or the last row of every long screen sits under it.

     MEASURED, not chosen, and the second one was WRONG until it was measured
     rather than derived: 83px is `.bottom-nav` rendered at 430x932 in both
     engines (8px top padding + the 54px centre action + 20px gesture area;
     the 54px plus button is the tallest cell, not the 44px items).

     73px is `.form-action-bar`, measured the same way. It was first written
     as 80px by adding 8 + 20 to its `min-block-size: 52px` -- but that
     minimum is never reached: the bar's real content is a 44px button, so
     44 + 8 + 20 + 1px border = 73px, and the min-block-size does nothing.
     The over-reserve was 7px of dead space under every form screen on a
     phone, which is the same complaint this round exists to answer. Caught
     by `_review/iphone-bottombar/check_reserve.py`, which asserts the
     reserve EQUALS the bar's measured height rather than trusting the
     arithmetic.

     A HARD-CODED HEIGHT DRIFTS, so it is gated rather than trusted:
     `core/test_device_gates.py` measures each bar in the browser and fails
     if the reserve is not its real height. Change the bar, run the gate,
     change the token -- in that order. */
  --bottom-nav-height: 83px;
  --form-action-bar-height: 73px;
}

/* ============================================================================
   DARK -- true black (OLED). The page ground is #000000 and surfaces lift from
   it in steps. Declared twice, identically: once for the OS preference and once
   for an explicit choice. Keep the two blocks in sync -- if you add a token
   above, it needs a twin in BOTH blocks below.
   ========================================================================= */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:             #000000;
    --surface:        #0C0F0D;
    --surface-2:      #111511;
    --border:         #1F241F;
    --row:            #161A16;
    --line:           #161A16;
    --chip:           #171C18;
    --chip-2:         #171C18;

    --ink:            #F0F5F1;
    --muted:          #8B978D;
    --muted-warm:     #8B978D;
    --muted-2:        #A4B0A7;
    --faint:          #59635B;
    --chevron:        #59635B;
    --on-primary:     #08120C;
    --on-dark:        #F0F5F1;

    --sidebar:        #000000;
    --sidebar-active: #16241B;
    --sidebar-text:   #8B978D;
    --sidebar-dim:    #6E7C73;
    --sidebar-dim-2:  #6E7C73;
    --sidebar-line:   #1A201B;
    --sidebar-badge:  #16241B;
    /* ISSUE 13 RESOLVED THIS AT SOURCE AND ITS ANSWER MEASURES BETTER.
       Both sides agreed the problem: theme.py's old #DC2626 -> #E05A5A
       left the drawn near-white numeral at 3.57:1. This project fixed it
       by darkening the NUMERAL (#16211A on #E05A5A, 4.56:1); the package
       fixed it by darkening the GROUND (#FDFDFD on #C73A3A, 5.04:1).

       The package wins on the owner's standing ruling -- "a correction
       enters the package first and ships from it, the CSS never quietly
       wins" -- and it also wins on the measurement, which is the happier
       way for that rule to be settled. A red badge with white digits is
       also what a badge looks like everywhere else. */
    --badge-urgent:      #C73A3A;
    --badge-urgent-text: #F0F5F1;

    /* See the two notes in the light block: one value in both
       themes, and the package's own dark value. */
    --sidebar-progress: #587360;
    --step-current-bg: #0A140D;
    --primary:        #57AD79;
    --primary-hover:  #6FBF8F;
    --primary-soft:   #132A1D;
    --link:           #57AD79;
      /* See the brand-chip note in the light block. */
    --brand-ink:        #7FD69B;
    --link-hover:     #6FBF8F;
    --inverse-surface: #F0F5F1;
    --on-inverse:     #0C0F0D;

    /* #132A1D IS THE PACKAGE'S OWN DARK SUCCESS GROUND -- it appears 325
       times across the dark artboards, 195 of them under success text.
       #0D1E11 appears NOWHERE in the package: it was invented, and it is
       the owner's Year-view defect.

       MEASURED against the dark card ground #0C0F0D:
         drawn   #132A1D  1.26:1   -- subtle, but a chip you can see
         before  #0D1E11  1.11:1   -- half that; the pill vanished
       On the Year grid that turned every occupied day from a filled chip
       into a bare green number, which is exactly "the date numbers render
       wrong in dark, light is fine".

       `--success-text` stays #8CD99C (a measured correction, not a drawn
       value): 9.09:1 on the new ground, better than the artboard's own
       #7FD69B at 8.71:1. */
    --success-bg:     #132A1D;
    --success-border: #1C3422;
    --success-text:   #7FD69B;
    --success-dot:    #56AE6C;

    --warning-bg:     #241E0C;
    --warning-border: #382D07;
    --warning-text:   #E8C55E;
    --warning-dot:    #C0992D;

    --danger-bg:      #2A1111;
    --danger-border:  #43241F;
    --danger-text:    #F09B9B;
    --danger-dot:     #DF6A59;

    --info-bg:        #0E1E36;
    --info-border:    #173044;
    --info-text:      #8CB8F5;
    --info-dot:       #489BDB;

    --neutral-bg:     #171C18;
    --neutral-border: #2A322C;
    --neutral-text:   #A4B0A7;
    --neutral-dot:    #6E7C73;

    --tag-bg:         #241E12;
    --tag-text:       #D6BF93;
    --avatar-bg:      #241E12;
    --avatar-text:    #D6BF93;

    --weekend-header: #0E140F;
    --weekend-cell:   #080B08;
    --weekend-text:   #7FD69B;
    --night-cell:     #080B08;
    --chart-bar:      #57AD79;
    --chart-rule:     #262B27;
    --donut-1:        #57AD79;
    --donut-2:        #3F8159;
    --donut-3:        #2E5C41;
    --donut-4:        #23402F;
    --mast-icon:      #CBD8CE;
    --tag-on-dark:    #D6BF93;
    --day-chip-active: #DCE7DE;
    --day-chip-active-ink: #0C0F0D;
    --day-chip-active-sub: #4A554C;
    --free-dash:      #4C554E;

    --focus:          #6FC28C;
    --focus-on-dark:  #6FC28C;
  }
}

:root[data-theme="dark"] {
  --bg:             #000000;
  --surface:        #0C0F0D;
  --surface-2:      #111511;
  --border:         #1F241F;
  --row:            #161A16;
  --line:           #161A16;
  --chip:           #171C18;
  --chip-2:         #171C18;

  --ink:            #F0F5F1;
  --muted:          #8B978D;
  --muted-warm:     #8B978D;
  --muted-2:        #A4B0A7;
  --faint:          #59635B;
  --chevron:        #59635B;
  --on-primary:     #08120C;
  --on-dark:        #F0F5F1;

  --sidebar:        #000000;
  --sidebar-active: #16241B;
  --sidebar-text:   #8B978D;
  --sidebar-dim:    #6E7C73;
  --sidebar-dim-2:  #6E7C73;
  --sidebar-line:   #1A201B;
  --sidebar-badge:  #16241B;
  /* See the note on the prefers-color-scheme copy above (Issue 13). */
  --badge-urgent:      #C73A3A;
  --badge-urgent-text: #F0F5F1;

  /* See the two notes in the light block: one value in both
     themes, and the package's own dark value. */
  --sidebar-progress: #587360;
  --step-current-bg: #0A140D;
  --primary:        #57AD79;
  --primary-hover:  #6FBF8F;
  --primary-soft:   #132A1D;
  --link:           #57AD79;
  /* See the brand-chip note in the light block. */
  --brand-ink:        #7FD69B;
  --link-hover:     #6FBF8F;
  --inverse-surface: #F0F5F1;
  --on-inverse:     #0C0F0D;

  /* See the note on the prefers-color-scheme copy above. */
  --success-bg:     #132A1D;
  --success-border: #1C3422;
  --success-text:   #7FD69B;
  --success-dot:    #56AE6C;

  --warning-bg:     #241E0C;
  --warning-border: #382D07;
  --warning-text:   #E8C55E;
  --warning-dot:    #C0992D;

  --danger-bg:      #2A1111;
  --danger-border:  #43241F;
  --danger-text:    #F09B9B;
  --danger-dot:     #DF6A59;

  --info-bg:        #0E1E36;
  --info-border:    #173044;
  --info-text:      #8CB8F5;
  --info-dot:       #489BDB;

  --neutral-bg:     #171C18;
  --neutral-border: #2A322C;
  --neutral-text:   #A4B0A7;
  --neutral-dot:    #6E7C73;

  --tag-bg:         #241E12;
  --tag-text:       #D6BF93;
  --avatar-bg:      #241E12;
  --avatar-text:    #D6BF93;

  --weekend-header: #0E140F;
  --weekend-cell:   #080B08;
  --weekend-text:   #7FD69B;
  --night-cell:     #080B08;
  --chart-bar:      #57AD79;
  --chart-rule:     #262B27;
  --donut-1:        #57AD79;
  --donut-2:        #3F8159;
  --donut-3:        #2E5C41;
  --donut-4:        #23402F;
  --mast-icon:      #CBD8CE;
  --tag-on-dark:    #D6BF93;
  --day-chip-active: #DCE7DE;
  --day-chip-active-ink: #0C0F0D;
  --day-chip-active-sub: #4A554C;
  --free-dash:      #4C554E;

  --focus:          #6FC28C;
  --focus-on-dark:  #6FC28C;
}
