/**
 * @file
 * Design tokens — Mosman Events 2026.
 *
 * PALETTE CONTINUITY
 * ------------------
 * Every brand colour below is carried over verbatim from the outgoing
 * `mosman_events` theme (css/custom_css/sass/style.scss and css/colors.css).
 * Nothing has been re-hued. What changed is how the colours are *organised*:
 * raw hex values now live in one place as `--me-*` primitives, and every
 * component reads a semantic token (`--surface-2`, `--text-accent`, …) that
 * points at a primitive. Re-skinning the site is a one-file edit.
 *
 * ACCESSIBILITY NOTE
 * ------------------
 * The brand hues are unchanged, but three derived steps were added because the
 * originals do not reach WCAG AA in the places the old theme used them. Each is
 * the same hue, moved only as far as it had to be:
 *
 *   #EC008C on #202833 ..... 3.50:1  the old theme's magenta-on-navy body text
 *   #FF63BA on #202833 ..... 5.48:1  --me-magenta-300, accent text on any panel
 *
 *   white on #EC008C ....... 4.25:1  the old theme's button and flag labels
 *   white on #DB0083 ....... 4.84:1  --me-magenta-600, accent as a solid fill
 *
 *   #656F7D on #202833 ..... 2.92:1  the old theme's muted metadata on cards
 *   #939CA6 on #202833 ..... 5.31:1  --me-slate-200, muted text
 *
 * Verified: every text/background pair the system can produce clears 4.5:1,
 * and every non-text pair (borders, focus ring, status flags) clears 3:1, in
 * both the dark and light palettes.
 *
 * #EC008C itself is untouched and is still the brand colour: it carries every
 * border, rule, focus accent and hover state, and it is what the eye reads as
 * "Mosman pink". The derived steps only appear where text contrast demands it.
 */

:root {
  /* ---------------------------------------------------------------------
   * 1. Brand primitives — inherited palette
   * ------------------------------------------------------------------ */
  --me-magenta:      #ec008c; /* brand accent, from $pink — unchanged */
  --me-magenta-300:  #ff63ba; /* accent TEXT on any dark surface (>= 4.8:1) */
  --me-magenta-600:  #db0083; /* accent as a SOLID FILL under white text (4.84:1) */
  --me-magenta-700:  #b8006e; /* pressed / active state, and light-mode links */
  --me-magenta-050:  #ffe6f4; /* tint for light contexts and print */

  --me-navy:         #233145; /* panel / control surface */
  --me-navy-deep:    #202833; /* elevated band, slideshow backdrop */
  --me-navy-900:     #18202b; /* derived: recessed wells, table stripes */

  --me-black:        #000000; /* true black — scrims and shadows only */

  /**
   * The page canvas.
   *
   * It used to be #000000, and next to the navy cards, header and footer that
   * read as two unrelated materials: an absence with panels floating on it. The
   * canvas is now the darkest step of the SAME navy ramp — #0b0f16 sits below
   * --me-navy-900 (#18202b) on the same hue — so the page reads as one material
   * lit from the front, and a card at --surface-1 (#202833) still separates
   * cleanly (L* 5 against L* 16, plus its hairline and resting shadow).
   *
   * True black is kept as --me-black and is still what every scrim, image
   * gradient and drop shadow is mixed from; nothing about those changed.
   */
  --me-ink:          #0b0f16;
  --me-white:        #ffffff;
  --me-off-white:    #fafafa;
  --me-line:         #e7e7e8;
  --me-slate:        #656f7d; /* borders, decorative icons — NOT text on dark */
  --me-slate-200:    #939ca6; /* muted TEXT — clears 4.5:1 on every dark surface */
  --me-slate-300:    #99a1a7; /* secondary text */

  /* Status colours — new, none existed in the old theme. Hue-matched to navy. */
  --me-success:      #2ecc8f;
  --me-warning:      #f5a623;
  --me-error:        #ff5c5c;
  --me-info:         #4aa8ff;

  /* ---------------------------------------------------------------------
   * 2. Semantic surfaces (dark-first — the site's established identity)
   * ------------------------------------------------------------------ */
  --surface-0: var(--me-ink);        /* page canvas */
  --surface-1: var(--me-navy-deep);  /* cards, bands */
  --surface-2: var(--me-navy);       /* controls, inputs, chips */
  /* Hover state of surface-2. Deliberately reserved for --text-primary: it is
     light enough that muted and accent text would fall under 4.5:1 on it, and
     nothing in the theme puts either there. */
  --surface-3: #2c3b52;
  --surface-well: var(--me-navy-900);
  --surface-inverse: var(--me-white);
  --surface-scrim: color-mix(in srgb, var(--me-black) 78%, transparent);

  --border-subtle: color-mix(in srgb, var(--me-white) 12%, transparent);
  --border-strong: color-mix(in srgb, var(--me-white) 26%, transparent);
  --border-accent: var(--me-magenta);

  /* ---------------------------------------------------------------------
   * 3. Semantic text
   * ------------------------------------------------------------------ */
  --text-primary:   var(--me-white);
  --text-secondary: var(--me-slate-300);
  --text-muted:     var(--me-slate-200);
  --text-accent:    var(--me-magenta-300);
  --text-on-accent: var(--me-white);

  /*
   * THE CURRENT PAGE'S MENU ITEM. BRAND MAGENTA, NOT THE LIGHTENED ACCENT.
   *
   * Everywhere else accent text is --me-magenta-300, because #ec008c on a dark
   * panel is only 4.52:1 and that is too close to the 4.5 line to spend on body
   * copy. Here it is the right call and it measures as passing: this is one
   * short uppercase bold label on the page canvas (#0b0f16, the darkest surface
   * in the theme), never over a card or a picture, so 4.52:1 is the real
   * number rather than a best case. It also matches the underline beneath it,
   * which has always been solid --me-magenta.
   *
   * IT CANNOT BE THE SAME COLOUR IN LIGHT MODE. #ec008c on white is 4.25:1,
   * which fails — so the light blocks below swap it for --me-magenta-700
   * (6.44:1), the same substitution --text-accent already makes.
   */
  --nav-active-text: var(--me-magenta);

  /*
   * The WHEN / WHERE / BOOKING / MORE INFORMATION bands on an event page.
   *
   * Flat brand magenta, as asked for, replacing a gradient tinted from the
   * event's own artwork. Worth knowing: white on #ec008c is 4.25:1, and the
   * label is bold 14.7px — not "large text" — so the AA requirement is 4.5:1
   * and this is just under it. `--me-magenta-600` (#db0083) is 4.84:1, looks
   * the same, and is the token the theme reserves for exactly this job.
   * See the note on `.panel__title` in components/event-detail.css.
   */
  --panel-title-bg: var(--me-magenta);

  /* The accent used as a solid background beneath white text. Distinct from
     --me-magenta, which stays the brand colour for borders and rules. */
  --accent-solid:       var(--me-magenta-600);
  --accent-solid-hover: var(--me-magenta-700);
  --text-inverse:   var(--me-navy-deep);

  /* ---------------------------------------------------------------------
   * 4. Typography
   * The old theme called for 'proxima-nova' with no fallback stack and no
   * @font-face — it silently fell back to the browser default anywhere
   * Typekit wasn't loaded. We keep Proxima Nova first, then a real stack.
   * ------------------------------------------------------------------ */
  --font-sans: "proxima-nova", "Proxima Nova", "Söhne", -apple-system,
    BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-display: var(--font-sans);
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* Fluid scale: min at 360px viewport, max at 1440px. */
  --step--2: clamp(0.694rem, 0.68rem + 0.07vw, 0.735rem);
  --step--1: clamp(0.833rem, 0.80rem + 0.15vw, 0.919rem);
  --step-0:  clamp(1rem, 0.96rem + 0.19vw, 1.125rem);
  --step-1:  clamp(1.2rem, 1.12rem + 0.36vw, 1.406rem);
  --step-2:  clamp(1.44rem, 1.31rem + 0.61vw, 1.758rem);
  --step-3:  clamp(1.728rem, 1.52rem + 0.96vw, 2.197rem);
  --step-4:  clamp(2.074rem, 1.75rem + 1.46vw, 2.747rem);
  --step-5:  clamp(2.488rem, 2.00rem + 2.15vw, 3.433rem);
  --step-6:  clamp(2.986rem, 2.28rem + 3.12vw, 4.292rem);

  --leading-tight: 1.1;
  --leading-snug: 1.25;
  --leading-normal: 1.6;
  --leading-loose: 1.75;

  --tracking-tight: -0.02em;
  --tracking-normal: 0;
  --tracking-wide: 0.06em;
  --tracking-wider: 0.12em;

  --weight-regular: 400;
  --weight-medium: 600;
  --weight-bold: 700;
  --weight-black: 800;

  /* ---------------------------------------------------------------------
   * 5. Space — 4px base, named by t-shirt size
   * ------------------------------------------------------------------ */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs:  0.75rem;
  --space-s:   1rem;
  --space-m:   1.5rem;
  --space-l:   2rem;
  --space-xl:  3rem;
  --space-2xl: 4rem;
  --space-3xl: 6rem;

  /* Section rhythm scales with the viewport. */
  --space-section: clamp(2.5rem, 1.5rem + 4vw, 5rem);

  /* ---------------------------------------------------------------------
   * 6. Layout
   * ------------------------------------------------------------------ */
  --wrapper-max: 82.5rem;   /* 1320px */
  --wrapper-wide: 96rem;    /* 1536px — full-bleed bands */
  --wrapper-prose: 44rem;   /* comfortable measure for body copy */
  --gutter: clamp(1rem, 0.5rem + 2.4vw, 3rem);

  /* Design token: the minimum height of the main header bar. */
  --header-height: 4.5rem;

  /* Measured total header height (main bar + utility bar), published by
     js/behaviours.js. Everything that sticks below the header or scrolls
     beneath it reads THIS, never --header-height — the header's real height
     depends on what an editor places in it. The fallback here is correct for
     the default arrangement, so the page is right before any script runs.
     These must stay separate: .site-header__inner takes its min-height from
     --header-height, so writing a measured value back into that token would
     grow the header on every measurement. */
  --header-offset: 7rem;


  /* ---------------------------------------------------------------------
   * 7. Shape, elevation, motion
   * ------------------------------------------------------------------ */
  --radius-xs: 4px;
  --radius-s: 8px;
  --radius-m: 12px;
  --radius-l: 20px;
  --radius-pill: 999px;

  --shadow-1: 0 1px 2px rgb(0 0 0 / 40%);
  --shadow-2: 0 6px 20px -6px rgb(0 0 0 / 60%);
  --shadow-3: 0 18px 48px -12px rgb(0 0 0 / 70%);
  --shadow-accent: 0 8px 28px -10px color-mix(in srgb, var(--me-magenta) 55%, transparent);

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --duration-fast: 120ms;
  --duration-base: 220ms;
  --duration-slow: 420ms;

  --focus-ring: 3px solid var(--me-magenta-300);
  --focus-offset: 2px;

  /**
   * One hover language for everything that lifts.
   *
   * Cards used to rise 6px from a flat resting state straight into a large
   * shadow, which is a lot of movement for a grid of thirty. They now sit on a
   * small resting shadow — so a card looks like an object before you touch it —
   * and rise half as far into a shadow one step up. Anything else in the theme
   * that lifts reads these, so the whole site moves the same way.
   */
  --lift: -4px;
  --lift-rest-shadow: var(--shadow-1);
  --lift-hover-shadow: var(--shadow-2);

  /* ---------------------------------------------------------------------
   * 8. Component-level aliases
   * ------------------------------------------------------------------ */
  --card-bg: var(--surface-1);
  /* A touch crisper than --border-subtle: a card's edge is the thing that has
     to survive being seen at the far side of a twenty-card grid. */
  --card-border: color-mix(in srgb, var(--me-white) 16%, transparent);
  --card-radius: var(--radius-m);

  /**
   * How much of its own artwork colour a card takes.
   *
   * Event and hub cards carry `--card-c1`, read out of their picture by GD, and
   * wash it up from the foot of the card body. This is the strength of that
   * wash, and it is a token because it is the one number in the effect worth
   * arguing about: too little and a grid is still twenty navy rectangles, too
   * much and the listing turns into a colour chart and the card stops being a
   * card.
   *
   * 36% of a tint that has already been mixed half-and-half into black (see
   * card-hover.css) moves a card a shade or two — enough to see across a grid,
   * not enough to notice on one card. The darkening is what makes 36% safe:
   * the wash can only ever lower the card's luminance, so the metadata sitting
   * on it keeps its contrast. Measured worst case across the whole palette
   * gamut: 5.14:1 for muted text, against 5.34 on an untinted card.
   *
   * Set it to 0% to turn the whole treatment off site-wide.
   */
  --card-wash: 36%;

  /**
   * Listing image shape — the shape the card is actually SERVED.
   *
   * This has been wrong twice, in both directions, and the reason is worth
   * writing down: the number that matters is not the size the artwork is
   * authored at, it is the size the image style hands the card.
   *
   * It was 825/465, then I changed it to 847.5/465 because that is the
   * authoring spec. The pictures then arrived a hair narrower than the box and
   * `contain` pillarboxed them — a thin band of card showing down each side,
   * measured at 97.4% of the card's width in a screenshot, which is 825/465
   * inside an 847.5/465 box to within a rounding error. The derivative is
   * 825x465; the 22.5px difference is the image style, not the source file.
   *
   * So: 825/465, and `cover`. Box and picture are the same shape, so the
   * picture fills the card's full width with nothing trimmed and no band —
   * and an off-spec upload fills it too, losing a sliver rather than showing a
   * gap.
   *
   * IF THE IMAGE STYLE CHANGES, THIS CHANGES WITH IT. Measure a rendered
   * thumbnail rather than reading the spec.
   */
  --card-media-ratio: 825 / 465;

  /*
   * `cover`, now that the box and the derivative are the same shape.
   *
   * `contain` was the right answer while they disagreed — it showed the whole
   * picture rather than silently trimming it. With them in agreement it has no
   * work to do, and its failure mode is the wrong one here: a band of card
   * down each side of a thumbnail reads as a mistake, while `cover` keeps
   * every picture flush to the card's edges and only ever loses a sliver of an
   * off-spec upload.
   *
   * Set this back to `contain` if an upload ever needs to be seen whole more
   * than the grid needs to be flush.
   */
  --card-media-fit: cover;

  /*
   * THE SHAPE OF THE SLIDESHOW BAND. ONE NUMBER, READ IN TWO PLACES.
   *
   * `.slide__media` uses it as its aspect-ratio, and `.slider__controls` uses
   * it to work out where the picture's foot is, because a sibling's used
   * height is not something CSS can ask for. They have to agree or the dots
   * float off the artwork, and the only way to guarantee that is for both to
   * read the same custom property — which is now the case.
   *
   * It used to be 16 / 9 here while the pictures sized themselves from their
   * own dimensions, published per slide as `--slide-ratio`. Those two were
   * never the same number, so the control row sat about 2.5% of the band's
   * height adrift — roughly 15px at laptop width.
   *
   * 2.39:1 IS THE SHAPE TO AUTHOR SLIDE ARTWORK AT. Anything else is fitted
   * to it with `object-fit: cover`, so a picture of another shape is cropped
   * rather than distorted or letterboxed — but it is cropped, so the file
   * should be made at this ratio. At the 1320px container that is a 552px
   * band; at 390px wide it is a 149px strip.
   *
   * It applies at every width, with no breakpoint. See the note above the
   * `.slide__media` rule in components/slider.css for why.
   */
  --slider-media-ratio: 2.39;

  /**
   * Collection (hub) cards: one square picture, edge to edge.
   *
   * This used to be a 16:9 panel with the artwork LETTERBOXED into it
   * (`contain`), because hub images were branded graphics with type in them —
   * the Creation Space wordmark, the Law Week poster — and cropping cut the
   * title off. Council now authors hub artwork square, so a square card crops
   * nothing and the picture can be the card.
   *
   * THE OLD BEHAVIOUR IS ONE LINE AWAY. Set --hub-media-fit back to `contain`
   * and the artwork is letterboxed again, inside the square. Do that if a hub
   * turns up with a wide graphic whose ends are being cut — `cover` on a 16:9
   * image in a square frame takes roughly a quarter off each side.
   */
  --hub-media-ratio: 1 / 1;
  --hub-media-fit: cover;
  --hub-media-bg: color-mix(in srgb, var(--me-white) 6%, var(--surface-2));

  /**
   * The glass plate the hub card's words sit on.
   *
   * Two numbers, and they are a pair: the scrim darkens the photograph under
   * the plate, the plate itself is --card-bg at less than full opacity, and
   * what the visitor sees through it is the product of the two.
   *
   * BOTH ARE MEASURED FROM THE PLATE'S OWN TOP EDGE, not from the card, and
   * both are nothing for the first --hub-refract of it. That band is the
   * picture's; these two only have to hold up under the words.
   *
   * THEY LOOK HIGH, AND THEY HAVE TO BE. The plate sits over artwork nobody
   * has approved in advance — the Spring School Holidays graphic is almost
   * white. Text over a pale photograph through a light plate fails WCAG AA
   * badly: at 72% over white, the accent link measures 3.1:1. Worked through
   * the whole range, roughly 8% of the picture is the most that can show
   * through and still clear 4.5:1 on a white image, however the 8% is split
   * between the scrim and the plate.
   *
   * At these values, against a PURE WHITE photograph: white 13.1:1, the accent
   * link 4.8:1, muted text 4.7:1. Over ordinary artwork it is far better —
   * 5.5:1 and up. The glass reads as glass because of the blur, the highlight
   * along its top edge and the colour that comes through, not because it is
   * faint.
   */
  /**
   * The slideshow's frame on a phone.
   *
   * A landscape picture at 390px wide is about 220px tall, and the caption and
   * control row need roughly 170px of that. Cropping the frame to 4:3 buys back
   * enough height that the overlay sits on about half the picture instead of
   * three quarters.
   *
   * IT IS A CROP, AND IT COSTS ABOUT 12.5% OFF EACH SIDE of a 16:9 source.
   * Slide artwork here is branded graphics that are not authored to a safe
   * area, so some of them will lose a little at the edges.
   *
   * SET THIS TO `auto` TO TURN THE CROP OFF. The frame then takes the
   * picture's own shape, nothing is trimmed, and the overlay covers more of it.
   * That is the whole revert — nothing else reads this.
   */
  --slide-mobile-ratio: 4 / 3;

  --hub-scrim: 70%;
  --hub-glass: 78%;

  /**
   * The refraction band: how deep the glass stays nearly clear at its top edge.
   *
   * This is the part of the plate the picture swims through. Above it the scrim
   * has not started and the glass is barely there, so the artwork comes through
   * at close to full strength, only out of focus. Below it the glass is at
   * --hub-glass and the text begins.
   *
   * It also sets the plate's top padding, so raising it moves the first line of
   * type down with it and the two can never fall out of step.
   */
  --hub-refract: 1.75rem;

  --chip-bg: var(--surface-2);
  --chip-bg-active: var(--accent-solid);
  --chip-text: var(--text-primary);
  --chip-text-active: var(--text-on-accent);

  --input-bg: var(--surface-2);
  --input-text: var(--text-primary);
  --input-placeholder: var(--me-slate-300);
  /**
   * A control needs an edge.
   *
   * This was `transparent`, which is fine on the page canvas — --surface-2
   * against --surface-0 is a clear step. Inside a card it is not: an input at
   * #233145 on a #202833 panel is a barely-visible smudge, and the newsletter
   * band and the event page's booking panel are exactly that case. A hairline
   * costs nothing on the canvas and makes the field a field on a panel.
   */
  --input-border: var(--border-subtle);
  --input-border-focus: var(--me-magenta);
  --input-radius: var(--radius-s);
  --input-height: 2.875rem; /* 46px — matches the old 45px control height */

  --footer-bg: var(--surface-1);
  --footer-text: var(--text-secondary);

  /**
   * The rich-text writing surface.
   *
   * Paper and ink, and deliberately NOT --surface-*: these two do not flip with
   * the colour scheme. A CKEditor field appears on the front-end form and on
   * Drupal's own admin screens, and the theme is only the last word on the
   * first of those — so the sheet is light in both, and the text on it is dark
   * in both. That is what stops it ever coming out white on white.
   *
   * The same two values are written as literals in css/theme/editor.css, the
   * copy Drupal loads inside the editor, where no token exists.
   */
  --editor-paper: #ffffff;
  --editor-ink: #202833;
}

/**
 * COLOUR SCHEME
 * =============
 * The site is DARK by default, on every device, regardless of what the
 * visitor's operating system prefers. That is deliberate: the dark canvas with
 * magenta accents is the site's identity, and a council events site should not
 * change its brand appearance because someone's laptop is set to light mode.
 *
 * The scheme is chosen in Appearance → Mosman Events 2026 → Settings:
 *
 *   Dark (default)  <html data-me-theme="dark">   always dark
 *   Light           <html data-me-theme="light">  always light
 *   Follow visitor  <html data-me-theme="auto">   dark, unless the OS asks
 *                                                 for light
 *
 * mosman_events_2026_preprocess_html() stamps the attribute. Nothing below
 * reacts to prefers-color-scheme unless the attribute is "auto", so an
 * unconfigured site — and a site whose cache has not been rebuilt — still
 * renders dark.
 *
 * The light palette is the same set of colours with the roles swapped: navy
 * becomes the ink, off-white becomes the canvas, and the accent darkens to
 * --me-magenta-700 so it holds 4.5:1 on white.
 */

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

  --surface-0: var(--me-white);
  --surface-1: var(--me-off-white);
  --surface-2: #eef0f3;
  --surface-3: #e3e6eb;
  --surface-well: #f2f4f7;
  --surface-inverse: var(--me-navy-deep);
  --surface-scrim: color-mix(in srgb, var(--me-navy-deep) 72%, transparent);

  --border-subtle: var(--me-line);
  --border-strong: #c9ced6;

  /* The dark palette's card edge is a white tint, which is nothing on paper. */
  --card-border: #dcdfe4;

  --text-primary: var(--me-navy-deep);
  --text-secondary: #4a5563;
  --text-muted: var(--me-slate);
  --text-accent: var(--me-magenta-700);
  --text-inverse: var(--me-white);

  /* #ec008c on white is 4.25:1 and fails AA; this is 6.44:1. */
  --nav-active-text: var(--me-magenta-700);

  --accent-solid: var(--me-magenta-700);
  --accent-solid-hover: #93005a;

  --shadow-1: 0 1px 2px rgb(32 40 51 / 8%);
  --shadow-2: 0 6px 20px -6px rgb(32 40 51 / 16%);
  --shadow-3: 0 18px 48px -12px rgb(32 40 51 / 22%);

  --chip-text: var(--me-navy-deep);
  --input-placeholder: var(--me-slate);

  /* The footer stays dark in the light palette — it anchors the page and
     matches how Mosman Council's other sites end. */
  --footer-bg: var(--me-navy-deep);
  --footer-text: var(--me-slate-300);
}

/* "Follow the visitor's system" — the only place prefers-color-scheme is read. */
@media (prefers-color-scheme: light) {
  :root[data-me-theme="auto"] {
    color-scheme: light;

    --surface-0: var(--me-white);
    --surface-1: var(--me-off-white);
    --surface-2: #eef0f3;
    --surface-3: #e3e6eb;
    --surface-well: #f2f4f7;
    --surface-inverse: var(--me-navy-deep);
    --surface-scrim: color-mix(in srgb, var(--me-navy-deep) 72%, transparent);

    --border-subtle: var(--me-line);
    --border-strong: #c9ced6;
    --card-border: #dcdfe4;

    --text-primary: var(--me-navy-deep);
    --text-secondary: #4a5563;
    --text-muted: var(--me-slate);
    --text-accent: var(--me-magenta-700);
    --text-inverse: var(--me-white);

    /* #ec008c on white is 4.25:1 and fails AA; this is 6.44:1. */
    --nav-active-text: var(--me-magenta-700);

    --accent-solid: var(--me-magenta-700);
    --accent-solid-hover: #93005a;

    --shadow-1: 0 1px 2px rgb(32 40 51 / 8%);
    --shadow-2: 0 6px 20px -6px rgb(32 40 51 / 16%);
    --shadow-3: 0 18px 48px -12px rgb(32 40 51 / 22%);

    --chip-text: var(--me-navy-deep);
    --input-placeholder: var(--me-slate);
    --footer-bg: var(--me-navy-deep);
    --footer-text: var(--me-slate-300);
  }
}

/* Dark is the default and the fallback: no attribute at all still means dark. */
:root,
:root[data-me-theme="dark"] {
  color-scheme: dark;
}

/* Respect reduced motion globally rather than per-component. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 1ms;
    --duration-base: 1ms;
    --duration-slow: 1ms;
  }
}

/* Windows high-contrast / forced-colors: let the OS win. */
@media (forced-colors: active) {
  :root {
    --border-subtle: CanvasText;
    --border-strong: CanvasText;
    --focus-ring: 3px solid Highlight;
  }
}
