/* Agoramores — "december" theme overrides. Loaded after main.css.
   Every selector here is scoped to body[data-theme-id="december"]. */

/* December — a spruce wood on a clear midnight, snow falling, one star up.

   The anchor motif is the EVERGREEN, built in three depths so the wood has real
   distance in it: a hazy blue-green treeline standing on the horizon, a spruce
   midground, and near-black pines in the foreground with lights strung through
   them. Every tree in all three depths is one conic-gradient wedge tiled with
   repeat-x — see the wedge tokens below — so the whole wood costs six gradients
   and paints once. There is no image, no SVG, no url() anywhere in this file.

   Colour discipline. Holly red is the anchor: it leads both heading gradients,
   returns mid-cycle in each, owns --border, the table header, the tarot card's
   keyline and numeral, the navigation star and every hover accent. Candle gold
   is the warm second, snow white and ice the reading colours, and the greens
   are structural — they are what the wood is made of, not what the text is.
   Red is deliberately NOT the body-emphasis colour; see the note on
   --tt-chartreuse below, which records the contrast measurement behind that.

   Motion is two falling-snow depths and nothing else. The stars do not drift —
   a still winter sky is the point — so this month spends the same ambient
   budget July does, just on different layers. Everything else in the scene,
   including the star, the treeline and the string lights, is painted in the
   first frame and never moves. */
body[data-theme-id="december"] {
  /* ---- Ink -------------------------------------------------------------- */
  --dec-void: #0d0905;        /* deepest ink — table-header text, hard shadows */
  --dec-night: #17110a;       /* the page ground */
  --dec-midnight: #291e10;    /* code, inputs, the astrolabe face */
  --dec-hearth: #131e13;      /* the breadcrumb card — the one allowed fill */
  /* Link-hover paired to THIS block's ground (standing rule 2026-08-14),
     not the mode name. #0a1220 is dark: #FF465A clears 5.60:1 here. */
  --link-hover: #FF4947;

  /* ---- Sky, top to horizon ---------------------------------------------- */
  --dec-sky-top: #100b06;
  --dec-sky-mid: #241a10;
  --dec-sky-low: #3c2f1d;
  --dec-sky-rim: #4f422d;

  /* ---- The wood. Atmospheric perspective, and it is the only thing separating
     the three depths: there is no outline, no stroke and no rim light anywhere
     in the wood. Each depth is a flat silhouette one step lighter and bluer
     than the depth in front of it, and each depth carries TWO rows in slightly
     different tones so the near and middle distances have interior depth too.
     (A rim light was tried here and pulled: at any alpha strong enough to see,
     an offset lighter copy of a cone reads as a drawn outline down one flank
     rather than as light, and a wood full of outlined trees looks like clip
     art. Tone separation does the same job and cannot fail that way.) ------- */
  --dec-haze: #59513d;        /* far treeline, hazier half */
  --dec-haze-deep: #463f30;   /* far treeline, nearer half */
  --dec-spruce: #264226;      /* midground, front row */
  --dec-spruce-far: #2f472e;  /* midground, back row — a step lighter and bluer */
  --dec-pine: #142314;        /* foreground, front row — the darkest thing here */
  --dec-pine-far: #1c2e1c;    /* foreground, back row */
  --dec-pine-lit: #578f56;    /* not a tree: the scrollbar and the time-bar rule, 4.95:1 */
  --dec-needle: #6bad6a;      /* 7.04:1 — a heading stop that can carry text */
  --dec-mint: #b2d4b1;        /* 11.66:1 — links at rest, tags, emphasis */

  /* ---- Snow on the ground. Moonlit snow at night is a cold slate, not white:
     painting it white would put 2.7:1 text ground under the bottom of every
     viewport, since .night-sky is fixed and the footer scrolls over it. The
     snow reads as snow from the lit crest along its undulating edge, the
     glints scattered through it and the near-black pines standing in it. ---- */
  --dec-drift: #483c2d;
  --dec-drift-deep: #281d13;
  --dec-drift-lit: #80725e;

  /* ---- Reading colours --------------------------------------------------- */
  --dec-frost: #f2e6d2;       /* body copy, 16.16:1 on --dec-night */
  --dec-ice: #c6bfaf;         /* soft copy, 10.28:1 */
  /* Muted, 8.00:1 on the page. Lifted one step from the obvious #8ca4bb, which
     measured 7.27:1 on the page but only 4.29:1 against the composited tree
     band at the foot of the viewport — and .more-items, the calendar weekday
     row and the agenda dates all take this colour and all scroll over that
     band. At this value the worst measured ground still reads 4.70:1. */
  --dec-slate: #b0a899;
  --dec-star: #eee8ce;        /* the star, and the brightest snowflakes */
  --dec-rose: #e4a4a4;        /* a berry already picked — visited links, 9.00:1 */

  /* ---- Warmth and the anchor --------------------------------------------- */
  --dec-gold: #f0c453;        /* candle gold, 11.36:1 */
  --dec-ember: #ffdc8a;       /* the lit wick, 14.15:1 */
  --dec-red: #ee4b4a;         /* HOLLY RED — the anchor, 5.12:1 */
  --dec-berry: #cf3736;       /* deep berry, 3.80:1 — structure only, never text */

  /* ---- The wedge kit -----------------------------------------------------
     A conifer is one conic-gradient. The cone is centred on the TOP edge of
     its tile (at 50% 0%) and opens downward around 180deg, so the apex is the
     treetop and the tile bottom cuts the skirt off flat. Half-angle sets the
     taper; tile height sets how tall the tree is; tile WIDTH sets what the row
     reads as, which is the whole trick:

       tile narrower than the tree  the cones overlap and the row fuses into a
                                    solid mass with tips above it — a far wood
       tile equal to the tree       the trees just touch — a middle distance
       tile wider than the tree     separated trees you can count — the near row

     Up close, two cones make a tree a spruce rather than a triangle: a narrow
     spire (10deg) running the full height and a wide skirt (26deg) flaring from
     partway down. At middle distance that tiering is below the resolution of
     the silhouette, so those rows are a single 14deg cone, and the far line is
     a single 17deg cone fused into a band.

     Six rows, in three pairs. Within each pair the two rows use tile widths
     with no small common factor (5.1/7.3, 2.3/3.4, 0.8/1.05) and different
     heights, so their crowns interleave on a period far longer than the screen
     and the row stops reading as a picket fence — the same reason October gives
     its three pumpkin rows three different tile lengths.

     tan(10deg)=0.176, tan(14deg)=0.249, tan(17deg)=0.306, tan(26deg)=0.488.
     Every tile width below is derived from one of those against its tile
     height, so the mobile block rescales the whole wood and the silhouette,
     the overlaps and the gaps all come with it. */
  --dec-wedge-far-a: conic-gradient(at 50% 0%, transparent 0deg 163deg, var(--dec-haze) 163deg 197deg, transparent 197deg);
  --dec-wedge-far-b: conic-gradient(at 50% 0%, transparent 0deg 163deg, var(--dec-haze-deep) 163deg 197deg, transparent 197deg);
  --dec-wedge-mid-a: conic-gradient(at 50% 0%, transparent 0deg 166deg, var(--dec-spruce) 166deg 194deg, transparent 194deg);
  --dec-wedge-mid-b: conic-gradient(at 50% 0%, transparent 0deg 166deg, var(--dec-spruce-far) 166deg 194deg, transparent 194deg);
  --dec-wedge-near-a-crown: conic-gradient(at 50% 0%, transparent 0deg 170deg, var(--dec-pine) 170deg 190deg, transparent 190deg);
  --dec-wedge-near-a-skirt: conic-gradient(at 50% 0%, transparent 0deg 154deg, var(--dec-pine) 154deg 206deg, transparent 206deg);
  --dec-wedge-near-b-crown: conic-gradient(at 50% 0%, transparent 0deg 170deg, var(--dec-pine-far) 170deg 190deg, transparent 190deg);
  --dec-wedge-near-b-skirt: conic-gradient(at 50% 0%, transparent 0deg 154deg, var(--dec-pine-far) 154deg 206deg, transparent 206deg);
  /* Snow caught on the upper branches. Each cap repeats the half-angle of the
     crown it sits on, so its flanks land exactly on that crown's flanks and it
     reads as frost on the tree rather than a pale triangle floating over one. */
  --dec-wedge-mid-cap: conic-gradient(at 50% 0%, transparent 0deg 166deg, rgba(242, 230, 210, 0.11) 166deg 194deg, transparent 194deg);
  --dec-wedge-near-cap: conic-gradient(at 50% 0%, transparent 0deg 170deg, rgba(242, 230, 210, 0.15) 170deg 190deg, transparent 190deg);

  /* A drift of snow: a half-ellipse anchored on the bottom edge of its tile, so
     it is solid underneath and curved on top. The lit stop sits at 92-99% of
     the radius, NOT at 0% — 0% is the gradient's centre, which is at the BOTTOM
     of this shape, so lighting there would put the moonlight under the snow.
     Tiles are set wider than twice the ellipse's half-width below, so adjacent
     domes overlap and the union is one continuous undulating bank rather than a
     row of separate mounds. */
  --dec-drift-dome: radial-gradient(
    ellipse 54% 100% at 50% 100%,
    var(--dec-drift) 0 88%,
    var(--dec-drift-lit) 92% 99%,
    transparent 100%
  );
  /* The bank at the viewer's feet takes the same shape one plane darker: snow
     this close is in its own shadow, the mid-distance field behind it is what
     catches the sky, and the step between the two is what makes the ground read
     as two planes instead of one flat wash. It is also the ground body copy
     scrolls over, so darker is the legible choice as well as the true one. */
  --dec-drift-dome-near: radial-gradient(
    ellipse 54% 100% at 50% 100%,
    var(--dec-drift-deep) 0 90%,
    var(--dec-drift) 94% 99%,
    transparent 100%
  );

  /* ---- Scene geometry.
     Everything in the ground layer is expressed against these, and the row
     bases and the light strings are expressed as FRACTIONS of them, so the
     media block at the foot rescales the entire wood from this list alone.

     The vertical order is the whole composition, and it is what the first
     attempt got backwards: distance raises a tree's base toward the horizon and
     shrinks it, so a far tree's TOP must sit well below a near tree's top. Here
     the near crowns reach 8.6rem, the middle 6.0rem and the far line 5.6rem,
     over a horizon at 3.6rem. --------------------------------------------- */
  --dec-ground: clamp(10.5rem, 28vh, 16.5rem);  /* height of the ground element */
  --dec-snow-h: 3.6rem;                         /* the horizon, measured up from the foot */
  --dec-drift-h: 1.5rem;                        /* the drift at the viewer's feet */

  --dec-far-a-w: 0.8rem;
  --dec-far-a-h: 1.5rem;
  --dec-far-b-w: 1.05rem;
  --dec-far-b-h: 1.9rem;

  --dec-mid-a-w: 2.5rem;
  --dec-mid-a-h: 4.4rem;
  --dec-mid-a-cap: 0.8rem;
  --dec-mid-b-w: 3.7rem;
  --dec-mid-b-h: 3.5rem;

  --dec-near-a-w: 5.5rem;
  --dec-near-a-crown: 8.6rem;
  --dec-near-a-skirt: 3.9rem;
  --dec-near-a-cap: 1.5rem;
  --dec-near-b-w: 7.3rem;
  --dec-near-b-crown: 6.8rem;
  --dec-near-b-skirt: 3.1rem;
  --dec-near-b-cap: 1.25rem;

  /* ---- Shared token set --------------------------------------------------- */
  --tt-bg: var(--dec-night);
  --tt-bg-alt: var(--dec-midnight);
  --tt-cyan: var(--dec-frost);
  --tt-cyan-soft: var(--dec-ice);
  --tt-yellow: var(--dec-ember);
  --tt-orange: var(--dec-gold);
  /* Bold copy is candle gold, not holly red, and this is a measurement rather
     than a preference: .night-sky is position:fixed, so the bottom ~15rem of
     every viewport has the snow field behind it, and --dec-red reads 3.29:1 on
     --dec-drift — under the 4.5:1 floor for the weight <strong> sets at. Gold
     holds 7.31:1 on the same ground and 11.36:1 on the page. Red keeps every
     structural job in the theme instead: --border, the table header, both
     heading gradients, --tt-pink, the tarot keyline and every hover accent. */
  --tt-chartreuse: var(--dec-gold);
  --tt-green: var(--dec-mint);
  --tt-pink: var(--dec-red);
  --tt-purple: var(--dec-berry);
  --tt-blue: var(--dec-ice);
  --tt-teal: var(--dec-pine-lit);
  --tt-gray: var(--dec-slate);
  --tt-gold: var(--dec-gold);
  --tt-red: var(--dec-red);
  --tt-breadcrumb-text: var(--dec-ember);
  --tt-breadcrumb-glow: rgba(255, 200, 122, 0.45);
  /* Hover/focus halo for the zodiac glyphs, checked against BOTH grounds it has
     to work on: the page (--dec-night) and the breadcrumb card (--dec-hearth),
     which is where the chips actually sit. A warm candle white with real alpha,
     so a Sagittarius arrow or an ogham stave traces like a filament. Never a
     border — the rule that consumes this token lives once, in main.css. */
  --zodiac-glow: rgba(255, 214, 138, 0.78);

  /* Structural border palette. Red leads and returns at stops five and eight,
     so every frame, rail, rule and section marker in the theme is red-dominant
     with candle gold, snow and pine reading as the intervals between. */
  --tt-heading-rainbow: linear-gradient(
    90deg,
    var(--dec-red),
    var(--dec-gold),
    var(--dec-frost),
    var(--dec-needle),
    var(--dec-red),
    var(--dec-mint),
    var(--dec-ice),
    var(--dec-red)
  );
  --tt-heading-rainbow-vertical: linear-gradient(
    180deg,
    var(--dec-red),
    var(--dec-gold),
    var(--dec-frost),
    var(--dec-needle),
    var(--dec-red),
    var(--dec-mint),
    var(--dec-ice),
    var(--dec-red)
  );
  /* Heading text gradient: an eight-colour cycle stated twice across the 200%
     background main.css sets, then closed on red, so headingRainbowFlow loops
     with no visible reset. Red sits at stops one and six of each cycle.
     Every stop clears 5:1 on --dec-night and the hues step
     red > gold > candle > snow > pine > red > frost-green > ice, which is
     enough separation that the gradient reads as a gradient on a dark ground
     instead of collapsing into one dark smear the way an all-700s ramp does. */
  --tt-heading-text-rainbow: linear-gradient(
    90deg,
    var(--dec-red),
    var(--dec-gold),
    var(--dec-ember),
    var(--dec-frost),
    var(--dec-needle),
    var(--dec-red),
    var(--dec-mint),
    var(--dec-ice),
    var(--dec-red),
    var(--dec-gold),
    var(--dec-ember),
    var(--dec-frost),
    var(--dec-needle),
    var(--dec-red),
    var(--dec-mint),
    var(--dec-ice),
    var(--dec-red)
  );

  /* ---- Type --------------------------------------------------------------
     One override, no webfont, no network request: headings take an old-style
     book serif. Hoefler Text and Baskerville ship on macOS, Georgia is on
     effectively every machine and is the sturdiest screen serif there is, so
     the fallback is as good as the first choice rather than a consolation.
     This is the type a Christmas annual or a carol sheet is set in, and it
     stands apart from the humanist sans the body keeps.

     Body copy is left alone, and as of 2026-08-15 this sheet could not touch it
     anyway: --font-text is locked in main.css and is the same on every theme.
     The reasoning this comment already carried is the reasoning behind the lock
     — swapping the reading face for atmosphere is a change to legibility made
     for decoration, which is the wrong way round. (The face itself changed:
     Optima lost the job to Lucida Grande on defocus behaviour. The argument for
     leaving it alone did not.) --font-mono and --font-cursive are untouched:
     the brand wordmark and markdown H1 are locked fixtures and keep their own
     stack. */
  --font-heading: "Hoefler Text", Baskerville, "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;

  --bg: var(--dec-night);
  --surface: transparent;
  --text: var(--tt-cyan);
  --text-soft: var(--tt-cyan-soft);
  --muted: var(--tt-gray);
  --border: var(--dec-red);
  --border-dim: rgba(238, 75, 74, 0.3);
  --border-teal: rgba(87, 143, 86, 0.55);
  background: var(--dec-night);
  color: var(--tt-cyan);
  color-scheme: dark;
}

/* The cold outside the glass. The CRT scanline is a permanent fixture and
   stays; it just runs frost-blue here instead of cyan, with one very shallow
   diagonal pass over it so the pane is never optically clean. Both alphas sit
   near the floor on purpose: this element is fixed at z-index 5, above the
   text, so it has to be felt and never read. */
body[data-theme-id="december"]::before {
  background:
    repeating-linear-gradient(
      0deg,
      rgba(227, 218, 203, 0.016) 0 1px,
      transparent 1px 4px
    ),
    repeating-linear-gradient(
      74deg,
      rgba(242, 230, 210, 0.012) 0 1px,
      transparent 1px 11px
    );
}

/* ---------------------------------------------------------------------------
   THE SKY, and the star.

   Four star layers, then the sky under them. Every star layer is the same
   12rem box at the same background-position, which is the only way to get four
   differently-shaped gradients concentric: background-position aligns the
   image's X% point with the container's X% point, so layers of DIFFERENT sizes
   at one position are not centred on the same spot. Same size, same position,
   guaranteed concentric.

   The two spikes are radial-gradients with an extreme aspect ratio rather than
   thin bars, because a bar cannot fade along its own length and a spike must:
   an ellipse 1.6px wide and 4.6rem tall falls off to nothing at both ends, so
   the ray tapers the way starlight does. No rotation is possible on a
   background layer, which is exactly why this is a four-point star.

   All static. The star of a winter night does not twinkle here — the falling
   snow is this month's entire motion budget. */
body[data-theme-id="december"] .night-sky {
  background-color: var(--dec-night);
  background-image:
    /* core */
    radial-gradient(circle at 50% 50%, var(--dec-star) 0 2.4px, rgba(238, 232, 206, 0.72) 4.5px, transparent 9px),
    /* vertical ray */
    radial-gradient(ellipse 2px 4.1rem at 50% 50%, rgba(238, 232, 206, 0.95) 0 5%, rgba(238, 232, 206, 0.3) 24%, transparent 100%),
    /* horizontal ray */
    radial-gradient(ellipse 3rem 2px at 50% 50%, rgba(238, 232, 206, 0.8) 0 5%, rgba(238, 232, 206, 0.24) 26%, transparent 100%),
    /* halo */
    radial-gradient(circle at 50% 50%, rgba(255, 220, 138, 0.3) 0 6%, rgba(240, 196, 83, 0.12) 22%, transparent 58%),
    /* candlelight pooled low and centre — something lit is down there */
    radial-gradient(ellipse at 50% 106%, rgba(240, 196, 83, 0.1), transparent 34%),
    /* cold moonwash off to one side */
    radial-gradient(ellipse at 77% 99%, rgba(128, 114, 94, 0.15), transparent 30%),
    /* the sky itself, darkest overhead and opening toward the horizon */
    linear-gradient(
      180deg,
      var(--dec-sky-top) 0%,
      var(--dec-night) 32%,
      var(--dec-sky-mid) 60%,
      var(--dec-sky-low) 85%,
      var(--dec-sky-rim) 100%
    );
  background-size:
    9rem 9rem,
    9rem 9rem,
    9rem 9rem,
    9rem 9rem,
    auto,
    auto,
    auto;
  /* Low and to one side: a star standing over the wood. The first attempt put
     it at 78% 14%, which is inside the breadcrumb card at desktop width and
     behind the brand at phone width — the card is the one element with an
     opaque fill, so the star simply vanished under it. Down here the only thing
     in front of the star is body copy, and it is dim enough to sit behind a
     line of text without fighting it. */
  background-position: 86% 70%, 86% 70%, 86% 70%, 86% 70%, 0 0, 0 0, 0 0;
  background-repeat: no-repeat;
}

/* The fixed stars. main.css drifts and twinkles this layer; December stops both
   — a clear, hard, cold winter sky is still, and the snow in front of it is
   where all the movement belongs. Five depths of pinpricks, the brightest ones
   picking up a trace of candle gold so the sky is not a monochrome dot screen. */
body[data-theme-id="december"] .night-sky::before {
  opacity: 0.85;
  background-image:
    radial-gradient(circle at 18% 26%, rgba(238, 232, 206, 0.95) 0 1.05px, transparent 1.7px),
    radial-gradient(circle at 71% 14%, rgba(242, 230, 210, 0.82) 0 0.9px, transparent 1.5px),
    radial-gradient(circle at 44% 76%, rgba(240, 196, 83, 0.6) 0 0.85px, transparent 1.4px),
    radial-gradient(circle at 86% 55%, rgba(242, 230, 210, 0.68) 0 0.8px, transparent 1.35px),
    radial-gradient(circle at 57% 37%, rgba(198, 191, 175, 0.6) 0 0.6px, transparent 1.1px);
  background-size: 13rem 14rem, 17rem 15rem, 22rem 19rem, 28rem 25rem, 9rem 10rem;
  background-position: 0 0, 3rem 5rem, 7rem 2rem, 1rem 9rem, 5rem 6rem;
  animation: none;
  transform: none;
}

/* ---------------------------------------------------------------------------
   THE SNOW. Two depths on the two star layers that already existed.

   Both tile 15rem tall and both keyframes end exactly 15rem below where they
   start, so each column restarts on a tile boundary and there is no seam. The
   sway is the reason each keyframe has interior stops: y advances by an equal
   quarter-tile every 25% and the timing function is linear, so vertical speed
   is dead constant, while x runs out and back as a triangle wave. Snow drifts;
   rain does not; and doing it this way costs one extra transform interpolation
   rather than a second animation on the same element.

   Density is set by tile width, not layer count — halving a tile doubles the
   flakes on screen for no extra paint. Transform only: no filter, no
   background-position animation, nothing that repaints the layer. --------- */
body[data-theme-id="december"] .night-sky__stars--far {
  inset: -16rem -3rem;
  opacity: 0.66;
  background-image:
    radial-gradient(circle at 26% 18%, rgba(242, 230, 210, 0.72) 0 1px, transparent 1.7px),
    radial-gradient(circle at 68% 63%, rgba(227, 218, 203, 0.6) 0 0.85px, transparent 1.5px),
    radial-gradient(circle at 41% 84%, rgba(242, 230, 210, 0.55) 0 0.9px, transparent 1.55px),
    radial-gradient(circle at 83% 33%, rgba(198, 191, 175, 0.5) 0 0.75px, transparent 1.35px),
    radial-gradient(circle at 12% 57%, rgba(242, 230, 210, 0.46) 0 0.7px, transparent 1.25px);
  background-size:
    5rem 15rem,
    7rem 15rem,
    9rem 15rem,
    12rem 15rem,
    3.75rem 15rem;
  background-position: 0 0, 1.4rem 0, 3.1rem 0, 0.6rem 0, 2.2rem 0;
  background-repeat: repeat;
  animation: decemberSnowFar 13s linear infinite;
}

body[data-theme-id="december"] .night-sky__stars--near {
  inset: -16rem -3rem;
  opacity: 0.82;
  background-image:
    radial-gradient(circle at 33% 27%, var(--dec-star) 0 1.75px, rgba(238, 232, 206, 0.28) 2.6px, transparent 3.4px),
    radial-gradient(circle at 71% 58%, rgba(242, 230, 210, 0.88) 0 1.45px, transparent 2.5px),
    radial-gradient(circle at 14% 77%, rgba(242, 230, 210, 0.8) 0 1.6px, transparent 2.7px),
    radial-gradient(circle at 56% 12%, rgba(227, 218, 203, 0.7) 0 1.2px, transparent 2.1px);
  background-size:
    8rem 15rem,
    11rem 15rem,
    15rem 15rem,
    6rem 15rem;
  background-position: 0 0, 2.7rem 0, 5.4rem 0, 1.1rem 0;
  background-repeat: repeat;
  animation: decemberSnowNear 7.5s linear infinite;
}

/* THE CONSTELLATIONS ARE HELD STILL.

   The shared layer turns at the sidereal rate, which is right for every month
   that has not said otherwise. This one has: the falling snow is December's
   entire motion budget and the stars do not drift, so the wheel keeps the
   angle the bootstrap stamped on it and stops there. Nothing is lost by it —
   the figures are still tonight's figures, at tonight's angle. `rotate` is a
   separate property from `transform` and carries that stamp, so killing the
   animation cannot take the orientation with it.

   Cooled to the month's own snow-blue and candle-gold, and quieter than the
   default: this is a clear midnight seen through a wood, and a bright chart
   over it would compete with the one star that is supposed to own the sky. */
body[data-theme-id="december"] .night-sky__constellations {
  animation: none;
  --constellation-strength: 0.4;
  --constellation-line: rgba(227, 218, 203, 0.2);
  --constellation-star: rgba(242, 230, 210, 0.9);
  --constellation-star-bright: var(--dec-star);
  --constellation-star-faint: rgba(198, 191, 175, 0.66);
  --constellation-halo: rgba(227, 218, 203, 0.22);
  /* The emblem takes the candle gold, which is this month's one warm colour
     and the only thing in the wood that is not snow, ice or spruce. */
  --constellation-emblem: rgba(238, 232, 206, 0.82);
}

/* ---------------------------------------------------------------------------
   THE GROUND — snow field, and the far treeline standing on it.

   This element is the shared ground slot: July's city silhouette, October's
   tilled field, December's wood. It carries the two farthest planes; the two
   pseudo-elements carry the nearer ones, and because ::after paints over
   ::before which paints over the element's own background, the stacking order
   is the depth order for free.

   The snowline undulates rather than ruling straight across: two wide, low
   radial domes tiled at different periods, each with its top few percent in the
   lit tone, so the crest catches moonlight along a curve. The far trees are
   planted a little above the nominal snowline so the domes do not bury them.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"] .night-sky__aurora {
  display: block;
  z-index: 2;
  left: 0;
  right: 0;
  top: auto;
  bottom: 0;
  inset-block-start: auto;
  height: var(--dec-ground);
  clip-path: none;
  box-shadow: none;
  background-color: transparent;
  background-image:
    /* the snowline, undulating, on two periods */
    var(--dec-drift-dome),
    var(--dec-drift-dome),
    /* glints in the snow — crystals catching the moon, two scattered rows */
    radial-gradient(circle at 38% 44%, rgba(242, 230, 210, 0.42) 0 0.8px, transparent 1.5px),
    radial-gradient(circle at 66% 61%, rgba(227, 218, 203, 0.3) 0 0.65px, transparent 1.3px),
    /* the snow field between the wood and the horizon, deepening forward */
    linear-gradient(180deg, var(--dec-drift) 0%, #3c3123 40%, #312417 76%, var(--dec-drift-deep) 100%),
    /* Atmospheric haze, banked on the far treeline. It sits ABOVE the two far
       tree layers and BELOW the snow, so it washes the wood without touching
       the ground, and it is densest at the tree bases and clears going up —
       which is the way distance actually reads, and half the reason the far
       line looks further off than the spruce standing in front of it. */
    linear-gradient(180deg, transparent 0%, rgba(128, 114, 94, 0.12) 52%, rgba(128, 114, 94, 0.24) 100%),
    /* far treeline: the nearer, taller, darker band over the hazier one */
    var(--dec-wedge-far-b),
    var(--dec-wedge-far-a);
  background-size:
    17rem 0.85rem,
    11.5rem 0.6rem,
    2.6rem calc(var(--dec-snow-h) * 0.62),
    3.9rem calc(var(--dec-snow-h) * 0.34),
    100% var(--dec-snow-h),
    100% calc(var(--dec-far-b-h) * 1.5),
    var(--dec-far-b-w) var(--dec-far-b-h),
    var(--dec-far-a-w) var(--dec-far-a-h);
  background-position:
    left 0px bottom var(--dec-snow-h),
    left 4rem bottom var(--dec-snow-h),
    left 0px bottom 0px,
    left 1.3rem bottom calc(var(--dec-snow-h) * 0.5),
    left 0px bottom 0px,
    left 0px bottom calc(var(--dec-snow-h) + 0.1rem),
    left calc(var(--dec-far-b-w) * 0.4) bottom calc(var(--dec-snow-h) + 0.1rem),
    left 0px bottom calc(var(--dec-snow-h) + 0.1rem);
  background-repeat: repeat-x;
}

body[data-theme-id="december"] .night-sky__aurora::before,
body[data-theme-id="december"] .night-sky__aurora::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-repeat: repeat-x;
}

/* MIDGROUND SPRUCE. Two rows, one cone each.

   No tiering at this distance: a 14deg cone 4.4rem tall is about 70px on a
   desktop, and a skirt flare on something that size is below the resolution of
   its own silhouette — it would cost two more gradients to draw nothing.

   Row A is the front row: taller, darker, standing lower. Row B is behind it,
   shorter, a step lighter, standing higher. Tile widths 2.3rem and 3.4rem have
   no small common factor, so the two rows only realign every 39rem and the band
   never falls into a repeat you can see. Row A's trees are 2.19rem across on a
   2.3rem tile — just touching, which is what a middle distance looks like —
   while row B's are 1.74rem on a 3.4rem tile and read as gaps behind them.

   Both bases are fractions of the horizon rather than fixed lengths, so the
   media block moves the horizon and the wood follows it. */
body[data-theme-id="december"] .night-sky__aurora::before {
  background-image:
    var(--dec-wedge-mid-cap),
    var(--dec-wedge-mid-a),
    var(--dec-wedge-mid-b);
  background-size:
    var(--dec-mid-a-w) var(--dec-mid-a-cap),
    var(--dec-mid-a-w) var(--dec-mid-a-h),
    var(--dec-mid-b-w) var(--dec-mid-b-h);
  background-position:
    left 0px bottom calc(var(--dec-snow-h) * 0.44 + var(--dec-mid-a-h) - var(--dec-mid-a-cap)),
    left 0px bottom calc(var(--dec-snow-h) * 0.44),
    left calc(var(--dec-mid-b-w) * 0.32) bottom calc(var(--dec-snow-h) * 0.64);
}

/* FOREGROUND PINE, the lights, and the drift at your feet.

   Two tiered rows in near-black green, both standing on the floor of the frame.
   Row A is an 8.6rem spire with a 3.80rem skirt on a 5.1rem tile, so these
   trees stand a clear 1.3rem apart and you can count them — which is what near
   looks like, and the exact opposite of the fused far band. Row B is 6.8rem on
   a 7.3rem tile, a step lighter, filling the gaps on a different period.

   The DRIFT is the topmost layer, in front of the trunks, and it is what fixes
   the composition: without it the near trees run straight off the bottom edge
   and the snow is stranded behind them in a strip near the horizon, so the
   picture reads as trees-on-sky instead of as a wood you are standing in. Two
   dome tiles at different periods, overlapping into one continuous bank.

   The lights are three rows of dots at three heights on three tile widths with
   no common factor, so they read as a string threaded through the wood rather
   than as a grid. Each is a hot centre inside a soft corona, and the corona is
   part of the same radial-gradient rather than a box-shadow, so it costs
   nothing extra. They are static: a twinkle would be a third continuous
   animation and the scene is already complete without one.

   Every size and offset here is a fraction of a geometry token, so the media
   block rescales the wood and the lights come with it — there is no second
   position list to keep in sync. */
body[data-theme-id="december"] .night-sky__aurora::after {
  background-image:
    var(--dec-drift-dome-near),
    var(--dec-drift-dome-near),
    radial-gradient(circle at 50% 50%, var(--dec-ember) 0 1.5px, rgba(255, 220, 138, 0.26) 2.7px, transparent 4.4px),
    radial-gradient(circle at 50% 50%, var(--dec-red) 0 1.4px, rgba(238, 75, 74, 0.24) 2.6px, transparent 4.2px),
    radial-gradient(circle at 50% 50%, var(--dec-star) 0 1.2px, rgba(238, 232, 206, 0.22) 2.3px, transparent 3.8px),
    var(--dec-wedge-near-cap),
    var(--dec-wedge-near-a-crown),
    var(--dec-wedge-near-a-skirt),
    var(--dec-wedge-near-cap),
    var(--dec-wedge-near-b-crown),
    var(--dec-wedge-near-b-skirt);
  background-size:
    29rem var(--dec-drift-h),
    17.5rem calc(var(--dec-drift-h) * 0.7),
    calc(var(--dec-near-a-w) * 0.61) 1.4rem,
    calc(var(--dec-near-a-w) * 0.84) 1.4rem,
    calc(var(--dec-near-a-w) * 1.16) 1.2rem,
    var(--dec-near-a-w) var(--dec-near-a-cap),
    var(--dec-near-a-w) var(--dec-near-a-crown),
    var(--dec-near-a-w) var(--dec-near-a-skirt),
    var(--dec-near-b-w) var(--dec-near-b-cap),
    var(--dec-near-b-w) var(--dec-near-b-crown),
    var(--dec-near-b-w) var(--dec-near-b-skirt);
  background-position:
    left 0px bottom 0px,
    left 7rem bottom 0px,
    left calc(var(--dec-near-a-w) * 0.31) bottom calc(var(--dec-near-a-crown) * 0.42),
    left calc(var(--dec-near-a-w) * 0.1) bottom calc(var(--dec-near-a-crown) * 0.6),
    left calc(var(--dec-near-a-w) * 0.57) bottom calc(var(--dec-near-a-crown) * 0.5),
    left calc(var(--dec-near-a-w) * 0.18) bottom calc(var(--dec-near-a-crown) - var(--dec-near-a-cap)),
    left calc(var(--dec-near-a-w) * 0.18) bottom 0px,
    left calc(var(--dec-near-a-w) * 0.18) bottom 0px,
    left calc(var(--dec-near-b-w) * 0.49) bottom calc(var(--dec-near-b-crown) - var(--dec-near-b-cap)),
    left calc(var(--dec-near-b-w) * 0.49) bottom 0px,
    left calc(var(--dec-near-b-w) * 0.49) bottom 0px;
}

/* Fireworks are Independence Day furniture: July theme only. The JS also refuses
   to spawn them off-July, so this is belt-and-braces for any burst already on
   screen when the theme is switched. */
body[data-theme-id="december"] .night-sky__fireworks {
  display: none;
}

/* ---------------------------------------------------------------------------
   THE CARD. The breadcrumb bar is the one element allowed its own background,
   so it is the lit thing in the picture: a deep spruce panel with candlelight
   pooling up from its foot, a fine dusting of snow across it, and two strings
   of lights running the gutter between the outer border and the inset keyline
   — top and bottom, gold and red alternating because each pair of rows shares
   a tile width and sits half a tile apart.

   The card ground is --dec-hearth rather than anything lighter for a reason
   that is measured, not aesthetic: --dec-red has to stay legible on it, because
   main.css paints .tarot-card__numeral-date in --tt-red at 0.66rem. On
   --dec-hearth that is 4.65:1.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"] .breadcrumb-nav {
  background:
    radial-gradient(circle at 50% 50%, var(--dec-ember) 0 1.3px, rgba(255, 220, 138, 0.2) 2.4px, transparent 3.6px)
      left 0.85rem top 0.14rem / 2.6rem 0.5rem repeat-x,
    radial-gradient(circle at 50% 50%, var(--dec-red) 0 1.3px, rgba(238, 75, 74, 0.2) 2.4px, transparent 3.6px)
      left 2.15rem top 0.14rem / 2.6rem 0.5rem repeat-x,
    radial-gradient(circle at 50% 50%, var(--dec-ember) 0 1.3px, rgba(255, 220, 138, 0.2) 2.4px, transparent 3.6px)
      left 1.5rem bottom 0.14rem / 2.6rem 0.5rem repeat-x,
    radial-gradient(circle at 50% 50%, var(--dec-red) 0 1.3px, rgba(238, 75, 74, 0.2) 2.4px, transparent 3.6px)
      left 0.2rem bottom 0.14rem / 2.6rem 0.5rem repeat-x,
    /* snow dust across the panel */
    radial-gradient(circle at 33% 27%, rgba(242, 230, 210, 0.12) 0 0.7px, transparent 1.3px)
      0 0 / 19px 23px repeat,
    radial-gradient(circle at 71% 64%, rgba(227, 218, 203, 0.09) 0 0.6px, transparent 1.2px)
      7px 3px / 29px 31px repeat,
    /* candlelight rising from the foot of the card */
    radial-gradient(ellipse at 50% 122%, rgba(240, 196, 83, 0.16), transparent 64%)
      0 0 / 100% 100% no-repeat,
    linear-gradient(180deg, #172517 0%, var(--dec-hearth) 62%, #0c160c 100%)
      0 0 / 100% 100% no-repeat;
  box-shadow: 0 0 20px rgba(238, 75, 74, 0.12);
}

/* The existing terminal sweep becomes a pass of warm light across the panel.
   Same element, same animation, same duration — only the colours change. */
body[data-theme-id="december"] .breadcrumb-nav::before {
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 220, 138, 0.2),
    rgba(238, 75, 74, 0.12),
    transparent
  );
}

/* Belt-and-braces, per the permanent note on .celestial-chip in main.css: the
   chips carry no border, no ring and no box halo under any theme. Their
   hover/focus affordance is the glyph halo cast from --zodiac-glow above. This
   pin exists so no future rule in this sheet can reach them by accident.

   Note what is NOT here: `transform: none`. December's chrome is allowed to
   move, so the chips keep the lift main.css gives them — the flat-chrome pins
   in october.css and november.css are those months' own decision, not a
   site-wide one, and copying them here would be cargo cult. Nothing in this
   sheet selects a bare `button` or a bare `a` in a way that could reach the
   strip either; every chrome rule below is written against classes for exactly
   that reason. */
body[data-theme-id="december"] .celestial-chip,
body[data-theme-id="december"] .celestial-chip:hover,
body[data-theme-id="december"] .celestial-chip:focus-visible {
  border: 0;
  box-shadow: none;
  outline: none;
}

/* ---------------------------------------------------------------------------
   HEADER
   --------------------------------------------------------------------------- */

/* The wordmark is the candle in the window. */
body[data-theme-id="december"] .brand a {
  text-shadow:
    0 0 10px rgba(255, 220, 138, 0.6),
    0 0 26px rgba(240, 196, 83, 0.32),
    0 0 48px rgba(238, 75, 74, 0.2);
}

body[data-theme-id="december"] .brand a:hover {
  text-shadow:
    0 0 12px rgba(255, 220, 138, 0.9),
    0 0 32px rgba(240, 196, 83, 0.5),
    0 0 68px rgba(238, 75, 74, 0.28);
}

body[data-theme-id="december"] .time-bar {
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.1),
    inset 0 -1px 0 rgba(13, 9, 5, 0.5);
  letter-spacing: 0.12em;
}

/* ---------------------------------------------------------------------------
   HEADINGS
   --------------------------------------------------------------------------- */

/* Every heading's bloom goes warm. main.css casts a cyan halo here, which is
   July's colour and has been leaking onto this month; candle gold with a holly
   undertone puts the headings back in December.

   It has to stay a BLURRED shadow. These letters are painted with
   background-clip:text, and text-shadow renders in the text phase — on top of
   the clipped background — so a zero-blur shadow would fill the transparent
   glyph with a flat block and bury the gradient entirely. (October needs a
   hard-edged shadow and therefore has to use filter: drop-shadow instead, which
   reads the composited alpha. This theme wants a soft glow, so text-shadow is
   the right tool and no filter is involved.)

   The heading-section trigger IS the h1..h6 element — the renderer emits
   <summary><h2 class="heading-section__trigger">…</h2></summary> — so `main h2`
   already reaches it. It is named explicitly anyway, because main.css styles
   `.markdown-page .heading-section__trigger` at (0,3,0) and a bare `main h2`
   under this theme would not outrank it. */
body[data-theme-id="december"] main h1,
body[data-theme-id="december"] .page-title,
body[data-theme-id="december"] main h2,
body[data-theme-id="december"] main h3,
body[data-theme-id="december"] main h4,
body[data-theme-id="december"] main h5,
body[data-theme-id="december"] main h6,
body[data-theme-id="december"] .markdown-page .heading-section__trigger {
  text-shadow:
    0 0 14px rgba(240, 196, 83, 0.22),
    0 0 34px rgba(238, 75, 74, 0.14);
}

/* A book serif sets a little tighter than the humanist sans it replaces, so H2
   and H3 take a hair of tracking back to keep the colour of the line even.
   Sizes are untouched: the serif is not appreciably wider, so nothing has to
   come down to stay off a second line. */
body[data-theme-id="december"] main h2,
body[data-theme-id="december"] main h3 {
  letter-spacing: 0.012em;
}

/* The rule under a section title, in the structural rainbow so it stays inside
   the shared border palette and therefore leads on red. Short and left-aligned,
   because the body copy under it is left-aligned and a centred rule under a
   left-set heading reads as a mistake.

   Safe on a background-clip:text heading: the pseudo-element carries no text,
   so -webkit-text-fill-color has nothing to act on, and background-clip is set
   on the h2 rather than inherited by it. */
body[data-theme-id="december"] main h2::after {
  content: "";
  display: block;
  width: min(7rem, 32%);
  height: 2px;
  margin: 0.55rem 0 0;
  background: var(--tt-heading-rainbow);
  opacity: 0.85;
}

/* The section rails and the table-of-contents accent are lit tubing rather than
   July's cyan filament. Both already draw from --tt-heading-rainbow-vertical,
   so they are red-led before this rule touches them. */
body[data-theme-id="december"] .heading-section::before {
  box-shadow: 0 0 10px rgba(238, 75, 74, 0.26);
}

/* ---------------------------------------------------------------------------
   LINKS. At rest they are frosted evergreen — clearly not the snow-white body
   copy, and clearly not the gold that means "emphasis" here. On hover they
   light like a wick. Visited is a berry already picked.

   This is (0,2,2) and the doubled .celestial-chip.celestial-chip block in
   main.css is (0,3,0), so none of it reaches the zodiac strip: the chips keep
   their own colour, their own halo and their own hover. Nothing below sets
   -webkit-text-fill-color, which is the property that broke the chips under the
   monochrome months this file used to be one of.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"] main a {
  color: var(--dec-mint);
}

/* Hover colour is --link-hover, standing user rule 2026-08-14: #FF465A on
   every theme, not --dec-ember any more. The candle-glow shadow below is
   independent art (amber/ember, never matched 1:1 to the link's own hex) and
   is left as it was. */
body[data-theme-id="december"] a:hover,
body[data-theme-id="december"] a:focus-visible {
  color: var(--link-hover);
  text-shadow:
    0 0 8px rgba(255, 220, 138, 0.82),
    0 0 16px rgba(240, 196, 83, 0.52),
    0 0 28px rgba(238, 75, 74, 0.28);
  animation: decemberCandleGlow 1.4s ease-in-out infinite alternate;
}

body[data-theme-id="december"] a:visited {
  color: var(--dec-rose);
  text-shadow: none;
}

/* main a:visited has to be restated: the rule above is (0,2,2) and would
   otherwise be beaten by nothing, but `main a` at (0,2,2) with a later source
   position would win the resting colour back on a visited link. Same weight,
   stated after, so visited holds. */
body[data-theme-id="december"] main a:visited {
  color: var(--dec-rose);
}

body[data-theme-id="december"] .eyebrow {
  letter-spacing: 0.3em;
  text-shadow: 0 0 10px rgba(240, 196, 83, 0.4);
}

/* ---------------------------------------------------------------------------
   SURFACES. Everything below already had a fill or a frame in main.css. Each
   gains a cold seat and a frosted top edge; nothing gains a background it did
   not already have, and there is still exactly one page background.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"] input,
body[data-theme-id="december"] textarea,
body[data-theme-id="december"] select,
body[data-theme-id="december"] code,
body[data-theme-id="december"] pre {
  background-color: rgba(41, 30, 16, 0.58);
  color: var(--dec-frost);
}

/* main.css hangs a hardcoded July-cyan halo on `button:hover, .sitemap-link:hover`
   — rgba(52, 226, 226, 0.22), not a token — so it survives every month unless a
   theme takes it down. December brings it back to candle gold.

   Scoped by CLASS and never by element, which is the whole point: the strip ran
   mixed for a while — one <button> moon among seven <a> signs — and a
   `body[…] button:hover` rule here would have put a box halo on that one chip
   while its neighbours stayed clean. All eight are anchors today, which changes
   nothing about the rule: the next element change would be the third time this
   bit someone, and a class selector cannot be bitten by it at all. */
body[data-theme-id="december"] .sitemap-link:hover,
body[data-theme-id="december"] .sitemap-link:focus-visible {
  border-color: var(--dec-ember);
  color: var(--dec-ember);
  box-shadow: 0 0 16px rgba(255, 220, 138, 0.28);
}

/* The frosted lip goes on block surfaces only. Inline code is left without it
   on purpose: an inline box fragments across a line break and the hairline
   would break with it, leaving half-drawn edges mid-sentence. */
body[data-theme-id="december"] input,
body[data-theme-id="december"] textarea,
body[data-theme-id="december"] select,
body[data-theme-id="december"] pre {
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.1),
    inset 0 -1px 0 rgba(13, 9, 5, 0.5);
}

/* A code block is one pane, not one per line: the tint belongs to the <pre> and
   the <code> inside it stays clear. Stated explicitly because the tinted-surface
   rule above outranks main.css's `pre code`. */
body[data-theme-id="december"] pre code {
  background-color: transparent;
  box-shadow: none;
}

/* The table header is where holly red does its loudest structural work. Void
   ink on the anchor red is 5.42:1, and the header is set in the same book serif
   as the section titles so a table reads as part of the document rather than as
   a widget dropped into it. */
body[data-theme-id="december"] th {
  background: var(--dec-red);
  color: var(--dec-void);
  font-family: var(--font-heading);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Cards keep their rainbow frame and gain a frosted top edge, with the ambient
   bloom moved from July's purple to holly red, warming to gold on hover. */
body[data-theme-id="december"] .hero-card,
body[data-theme-id="december"] .folder-section {
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.08),
    0 0 22px rgba(238, 75, 74, 0.08);
}

body[data-theme-id="december"] .hero-card:hover,
body[data-theme-id="december"] .folder-section:hover {
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.18),
    0 0 26px rgba(240, 196, 83, 0.16);
}

/* No left rule on quotes — border-left is reserved for anchors inside a list,
   and a blockquote is not one. The inset wash just moves from July's green to
   candle gold. */
body[data-theme-id="december"] blockquote {
  color: var(--dec-ice);
  box-shadow: inset 1rem 0 1.4rem -1.2rem rgba(240, 196, 83, 0.45);
}

body[data-theme-id="december"] .tag {
  letter-spacing: 0.1em;
}

/* The footer scrolls over the snow field, because .night-sky is fixed and the
   ground sits at the bottom of every viewport. --muted (--dec-slate) reads
   4.27:1 there, so the footer takes the soft ice instead at 6.04:1. Same
   problem October solved for its loam field, same fix. */
body[data-theme-id="december"] footer {
  color: var(--dec-ice);
  letter-spacing: 0.12em;
}

/* The scrollbar is the last piece of trim: a rail lit along its upper edge. */
body[data-theme-id="december"]::-webkit-scrollbar-thumb,
body[data-theme-id="december"] ::-webkit-scrollbar-thumb {
  background-image: linear-gradient(
    180deg,
    rgba(242, 230, 210, 0.24) 0%,
    rgba(242, 230, 210, 0.04) 44%,
    rgba(13, 9, 5, 0.3) 100%
  );
}

/* ---------------------------------------------------------------------------
   CALENDAR. The grid draws almost everything from tokens already set above, so
   only two things need saying: the toolbar buttons want the same cold seat as
   the rest of the chrome, and the event swatch is one of the two places in the
   whole stylesheet where border-left is legitimate — it is an <a> inside the
   <ul> of a day cell, and the rule doubles as the category colour. Its July
   cyan is retuned to this month's evergreen; the category overrides in main.css
   keep working, since each of them resolves through a --tt-* token this file
   has already set.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"] .calendar-app__nav,
body[data-theme-id="december"] .calendar-app__today {
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.1),
    inset 0 -1px 0 rgba(13, 9, 5, 0.5);
}

body[data-theme-id="december"] .calendar-app__nav:hover,
body[data-theme-id="december"] .calendar-app__today:hover,
body[data-theme-id="december"] .calendar-app__nav:focus-visible,
body[data-theme-id="december"] .calendar-app__today:focus-visible {
  background: rgba(240, 196, 83, 0.12);
}

body[data-theme-id="december"] .calendar-event__link {
  color: var(--dec-mint);
  border-left-color: var(--dec-pine-lit);
  background: rgba(178, 212, 177, 0.09);
}

body[data-theme-id="december"] .calendar-event__link:hover,
body[data-theme-id="december"] .calendar-event__link:focus-visible {
  color: var(--dec-ember);
  background: rgba(255, 220, 138, 0.14);
}

/* ---------------------------------------------------------------------------
   RESPONSIVE. The entire wood is expressed against the geometry tokens, so the
   whole scene rescales from this one block and keeps its silhouette: every tile
   width is derived from its tile height by the same tangent, so shrinking both
   together preserves which rows fuse, which touch and which stand apart.
   --------------------------------------------------------------------------- */
@media (max-width: 800px) {
  body[data-theme-id="december"] {
    --dec-ground: clamp(7.5rem, 24vh, 11.5rem);
    --dec-snow-h: 2.5rem;
    --dec-drift-h: 1.05rem;

    --dec-far-a-w: 0.56rem;
    --dec-far-a-h: 1.05rem;
    --dec-far-b-w: 0.72rem;
    --dec-far-b-h: 1.3rem;

    --dec-mid-a-w: 1.75rem;
    --dec-mid-a-h: 3rem;
    --dec-mid-a-cap: 0.55rem;
    --dec-mid-b-w: 2.55rem;
    --dec-mid-b-h: 2.4rem;

    --dec-near-a-w: 3.8rem;
    --dec-near-a-crown: 5.9rem;
    --dec-near-a-skirt: 2.7rem;
    --dec-near-a-cap: 1.05rem;
    --dec-near-b-w: 5rem;
    --dec-near-b-crown: 4.6rem;
    --dec-near-b-skirt: 2.1rem;
    --dec-near-b-cap: 0.85rem;
  }

  /* The card tightens with the bar, so the light strings move in to stay inside
     the narrower frame gutter main.css sets at this width. This is the one part
     of the theme that does NOT scale from the geometry tokens, because it is
     chrome rather than scenery: it follows the card, not the wood. */
  body[data-theme-id="december"] .breadcrumb-nav {
    background-position:
      left 0.6rem top 0.08rem,
      left 1.55rem top 0.08rem,
      left 1.1rem bottom 0.08rem,
      left 0.15rem bottom 0.08rem,
      0 0,
      7px 3px,
      0 0,
      0 0;
    background-size:
      1.9rem 0.36rem,
      1.9rem 0.36rem,
      1.9rem 0.36rem,
      1.9rem 0.36rem,
      19px 23px,
      29px 31px,
      100% 100%,
      100% 100%;
  }
}

/* ---------------------------------------------------------------------------
   REDUCED MOTION. Month blocks set their ambient motion on higher-specificity
   selectors than the generic .night-sky rules, so they need their own entry.
   The snow stops where it stands: every flake, tree, light and star is still
   painted, so the first frame and the final frame are the complete picture and
   only the travel is removed.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  body[data-theme-id="december"] .night-sky::before,
  body[data-theme-id="december"] .night-sky__stars--far,
  body[data-theme-id="december"] .night-sky__stars--near {
    animation: none !important;
    transform: none !important;
  }

  body[data-theme-id="december"] a:hover,
  body[data-theme-id="december"] a:focus-visible {
    animation: none;
  }
}

/* ---------------------------------------------------------------------------
   REDUCED DATA. The travel stops as above, and the snow is thinned to two
   gradients a depth instead of five and four. The scene still reads as snow
   over a wood; it just fills a fraction of the pixels doing it. The wood itself
   is untouched — it is static, it paints once, and removing it would cost the
   page its picture for no saving worth having.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-data: reduce) {
  body[data-theme-id="december"] .night-sky::before,
  body[data-theme-id="december"] .night-sky__stars--far,
  body[data-theme-id="december"] .night-sky__stars--near {
    animation: none;
    transform: none;
  }

  body[data-theme-id="december"] .night-sky__stars--far {
    background-image:
      radial-gradient(circle at 26% 18%, rgba(242, 230, 210, 0.72) 0 1px, transparent 1.7px),
      radial-gradient(circle at 68% 63%, rgba(227, 218, 203, 0.6) 0 0.85px, transparent 1.5px);
    background-size: 7rem 15rem, 12rem 15rem;
    background-position: 0 0, 3.1rem 0;
  }

  body[data-theme-id="december"] .night-sky__stars--near {
    background-image:
      radial-gradient(circle at 33% 27%, var(--dec-star) 0 1.75px, rgba(238, 232, 206, 0.28) 2.6px, transparent 3.4px),
      radial-gradient(circle at 14% 77%, rgba(242, 230, 210, 0.8) 0 1.6px, transparent 2.7px);
    background-size: 11rem 15rem, 15rem 15rem;
    background-position: 0 0, 5.4rem 0;
  }

  body[data-theme-id="december"] a:hover,
  body[data-theme-id="december"] a:focus-visible {
    animation: none;
  }
}

/* ===========================================================================
   DECEMBER BY DAY.

   The same wood, the same decorations, at two in the afternoon.

   Nothing is taken down and nothing is added. What changes is that the light
   is now coming from the sky instead of from the lights, and that single fact
   reorganises the whole picture:

     · The sky is a real winter blue overhead, washing to white at the horizon.
     · The snow stops being moonlit slate and becomes actual snow — the
       brightest thing on the page, which is what it is by day.
     · The wood goes PALE, not dark. Snow-laden spruce in flat winter light is
       a soft blue-green mass, and it has to be pale for a second reason given
       under the ramp below.
     · The string lights stop glowing. An unlit bulb in daylight is a small
       bead of coloured glass with a highlight in it and a shadow under it, so
       that is what they are drawn as. They are not deleted — the decorations
       are still up, they are simply not doing anything, which is exactly what
       a Christmas light looks like at two in the afternoon.
     · Red and gold stop being light sources and become materials: ribbon and
       gilt, at ink weight, which is the only weight they can carry on paper.

   HOW THE FLIP IS DONE. The base block routes almost everything through the
   --dec-* ramp, including the whole wedge kit and both drift domes, and a
   custom property resolves against the winning declaration on the SAME element
   — so redeclaring the ramp here re-lights the entire wood, both snow banks,
   every --tt-* token, both heading gradients and the calendar in one pass. The
   midground spruce rule needs no counterpart at all for that reason. What is
   left below is only what the sheet still paints with a literal rgba().

   THE RED MEASUREMENT, redone for daylight. The night block hands bold copy to
   candle gold rather than holly red, and records why: .night-sky is fixed, so
   the foot of every viewport has scenery behind it, and --dec-red measured
   3.29:1 on the night snow. The same test by day, against the day grounds:

     --dec-red #c1121f on the page      #eef4fb   5.62:1
                       on the snow field #f6fafe   5.94:1
                       on the near bank  #e6eff8   5.35:1
                       on the card       #dfeee2   5.18:1  (night: 4.65:1)
                       ON THE NEAR WOOD  #b4cabb   3.47:1  <- still short

   So the answer comes out the same and the reason is exactly inverted: at
   night red failed against the snow because the snow was the LIGHT thing in a
   dark scene; by day it fails against the wood because the wood is the DARK
   thing in a light one. Bold copy therefore stays in the gold family, one step
   deeper than at night — --dec-ember measures 4.64:1 on that same near wood
   and 7.26:1 on the page, and --dec-gold does not (3.35:1), which is why
   --tt-chartreuse is repointed below rather than left where it is. Red keeps
   every structural job it already had.

   WHY THE WOOD IS PALE, measured. By day the text is dark, so the hazard
   inverts with it: dark ink on a dark tree is the failure this mode has to
   design around, and the near row is the darkest ground in the viewport. The
   near front row is set at the exact lightness where the LIGHTEST text colour
   in use still clears the floor — --dec-slate reads 4.71:1 on it, which is the
   same margin the night block holds itself to for the same token. Everything
   else follows from that one number: --dec-ice 5.49:1, --dec-frost 9.49:1,
   --dec-mint 4.72:1, --dec-rose 4.86:1, --dec-ember 4.64:1.

   The cost is that the far treeline nearly dissolves — about 1.2:1 against the
   snow. That is not a compromise, it is what a far treeline in winter haze
   actually looks like, and the near band gets its punch back from the white
   snow caps and from the beads, which by day are the darkest, most saturated
   marks anywhere in the scene.
   =========================================================================== */
body[data-theme-id="december"][data-mode="day"] {
  /* ---- Ink ---- */
  --dec-void: #19140d;        /* deepest value; hard shadows */
  /* DAY IS A LADDER, NOT A CLAMP (2026-08-16). Nine of the values in this
     block were above the no-white ceiling, and clamping them all to it put
     the sky, the page, the snow bank and the lit crest on one value — a day
     scene with no weather and no snow in it. They are re-cut below as ten
     ordered steps inside L 0.869–0.929, keeping the original order exactly:
     sky darkest overhead and opening to the horizon, drifts climbing to the
     lit crest, the page sitting between them. The steps are smaller than they
     were, which is honest for a bright overcast — this is a day with no sun
     in it, and it never had much modelling to lose. */
  --dec-night: #ece1d0;       /* the page ground — snow light off a cold sky */
  --dec-midnight: #e0d9cf;    /* code, inputs, the astrolabe face */
  --dec-hearth: #dceddc;      /* the breadcrumb card — the one allowed fill */
  /* The ground is light: the dark-ground hover misses here, so day takes the
     light-ground variant of the same scarlet — 5.11:1. */
  --link-hover: #BC0900;

  /* ---- Sky, zenith to horizon. Same direction as at night, opposite ends:
     the deep value is overhead and it opens toward the light at the horizon.
     By day that means a weighted grey at the top of the page rather than a
     wash, because a page whose top edge is the ground colour has no weather
     in it. ---- */
  --dec-sky-top: #dbd3c6;
  --dec-sky-mid: #e6ddcd;
  --dec-sky-low: #eee2d0;
  --dec-sky-rim: #f1e5d1;

  /* ---- The wood, snow-laden. The ladder keeps its order and its direction —
     near darkest, far lightest, each depth one step lighter than the
     one in front — it is only compressed into the top of the value range for
     the reason measured above. There is still no outline, no stroke and no rim
     light: tone separation alone, as at night. ---- */
  --dec-haze: #e5dfd6;
  --dec-haze-deep: #dfdbd3;
  --dec-spruce: #c7d5c7;
  --dec-spruce-far: #cfdacf;
  --dec-pine: #b8c9b8;        /* the darkest thing in the scene, and the number
                                the whole day text ramp is set against */
  --dec-pine-far: #c0d0c0;
  --dec-pine-lit: #3a6839;    /* not a tree: scrollbar and time-bar rule, 5.83:1 */
  --dec-needle: #376937;      /* 5.82:1 — a heading stop that can carry text */
  --dec-mint: #335733;        /* 7.39:1 — links at rest, tags, emphasis */

  /* ---- Snow. At night this is deliberately a cold slate, because painting it
     white would have put 2.7:1 under the foot of every viewport. By day the
     snow is still the brightest surface on the page: the near bank is a step
     down because it is in the viewer's own shadow, and the crest is the
     ceiling itself — the lightest value anything in this workspace may take.
     Not white, and not trying to be. ---- */
  --dec-drift: #efe4d1;
  --dec-drift-deep: #e8dfd0;
  --dec-drift-lit: #f2e6d2;

  /* ---- Reading colours, 12.77 / 7.40 / 6.57 on the page ---- */
  --dec-frost: #241e16;
  --dec-ice: #4d4436;
  --dec-slate: #534c3f;
  /* The star is gone by day — but this token also tints the snowflakes, and a
     flake seen against a bright sky is not white, it is its own shadow. */
  --dec-star: #a09584;
  --dec-rose: #843333;        /* a berry already picked — visited links, 7.61:1 */

  /* ---- Warmth and the anchor. Gilt rather than candlelight: on paper the
     "brighter" gold has to be the DEEPER one, because distance from the ground
     is what emphasis is made of here. ---- */
  --dec-gold: #8a5c05;        /* 5.25:1 */
  --dec-ember: #6b4a0e;       /* 7.26:1 — and 4.64:1 on the near wood */
  --dec-red: #c11510;         /* HOLLY RED — the anchor, 5.62:1 */
  --dec-berry: #d16464;       /* 3.32:1 — structure only, never text */

  /* Bold copy moves one step down the gold, per the measurement in the header
     comment: --dec-gold cannot hold 4.5:1 against the near wood and --dec-ember
     can. This is the only --tt-* remapping the day needs; every other token
     re-lights through the ramp above. */
  --tt-chartreuse: var(--dec-ember);

  /* Snow caught on the branches. At night these are a whisper (0.11 and 0.15)
     because they sit on near-black trees and any more would read as a pale
     triangle floating over the crown. By day the trees are pale and the caps
     are the only thing giving the crowns an edge, so they go to real white —
     which is also just true, since a snow-laden branch in sunlight is the
     brightest thing in a wood. Each cap still repeats the half-angle of the
     crown it sits on, so its flanks land exactly on that crown's flanks. */
  --dec-wedge-mid-cap: conic-gradient(at 50% 0%, transparent 0deg 166deg, rgba(242, 230, 210, 0.62) 166deg 194deg, transparent 194deg);
  --dec-wedge-near-cap: conic-gradient(at 50% 0%, transparent 0deg 170deg, rgba(242, 230, 210, 0.75) 170deg 190deg, transparent 190deg);

  /* Hover/focus halo for the zodiac glyphs, checked against both grounds it
     has to work on — the page (#eef4fb) and the card (#dfeee2), which is where
     the chips actually sit. Both are pale, so the halo cuts the other way from
     the night's candle white: a deep holly traced around the glyph. Still a
     text-shadow on the glyph and a drop-shadow on the moon's path, drawn once
     in main.css, so it follows the character's contour and can never render as
     a rectangle. Never a border, in either mode. */
  --zodiac-glow: rgba(122, 21, 20, 0.5);
  --tt-breadcrumb-glow: rgba(107, 74, 14, 0.22);

  --border-dim: rgba(193, 21, 16, 0.32);
  --border-teal: rgba(58, 104, 57, 0.5);
  /* Cut the other way: on a pale card the lit lip of an engraved stroke falls
     white below the glyph, not black. */
  --tt-engrave: 0 1px 0 rgba(242, 230, 210, 0.75);

  background: var(--dec-night);
  color: var(--tt-cyan);
  color-scheme: light;
}

/* The cold outside the glass, still there, still felt and never read — it just
   changes sign. A frost-blue thread over near-black becomes a faint shadow
   thread over white, with the same very shallow diagonal pass over it so the
   pane is never optically clean. */
body[data-theme-id="december"][data-mode="day"]::before {
  background:
    repeating-linear-gradient(
      0deg,
      rgba(36, 30, 22, 0.028) 0 1px,
      transparent 1px 4px
    ),
    repeating-linear-gradient(
      74deg,
      rgba(36, 30, 22, 0.018) 0 1px,
      transparent 1px 11px
    );
}

/* ---------------------------------------------------------------------------
   THE SKY, without the star.

   Four of the base block's seven layers exist only to draw the star — core,
   two rays, halo — and a star at two in the afternoon is not a subtlety, it is
   a mistake, so they go rather than fade. What is left is the sky itself plus
   two low washes, which are the same two the night block has, re-lit: the
   candlelight pooled low becomes the low winter sun, and the cold moonwash off
   to one side becomes the cold quarter of the sky opposite it. A December sun
   in the northern afternoon never gets far above the treeline, which is why
   both are still banked along the bottom edge.

   Sizes and positions are restated here because the layer count changes; the
   base's four 9rem star boxes have nothing left to size.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"][data-mode="day"] .night-sky {
  background-color: var(--dec-night);
  background-image:
    radial-gradient(ellipse at 22% 104%, rgba(247, 230, 192, 0.55), transparent 38%),
    radial-gradient(ellipse at 82% 100%, rgba(197, 185, 167, 0.28), transparent 32%),
    linear-gradient(
      180deg,
      var(--dec-sky-top) 0%,
      var(--dec-sky-mid) 34%,
      var(--dec-sky-low) 74%,
      var(--dec-sky-rim) 100%
    );
  background-size: auto, auto, auto;
  background-position: 0 0, 0 0, 0 0;
  background-repeat: no-repeat;
}

/* The fixed stars go entirely. Hidden rather than faded — honest, and it is
   also the cheapest thing this switch can do to a slow machine, since a
   display:none layer is not composited at all. */
body[data-theme-id="december"][data-mode="day"] .night-sky::before {
  display: none;
}

/* ---------------------------------------------------------------------------
   THE SNOW keeps falling, on the same two depths, at the same two speeds.

   This is the month's whole motion budget and it is just as true by day, so
   neither layer is hidden — but a white flake on a white sky is nothing, and
   that is the entire problem to solve. Falling snow seen against a bright sky
   reads DARKER than the sky, because you are looking at the shadowed side of
   it; seen against the wood it reads lighter. Both are true at once on this
   page, since the sky fills most of the viewport and the wood fills the foot.

   The far depth takes the sky case and goes soft blue throughout. The near
   depth, which is the one you actually watch, is built to satisfy both: a
   white core inside a slate rim, so the rim carries it over the pale sky and
   the core carries it over the trees.

   No `animation` is restated anywhere in this counterpart, on purpose — the
   base declarations stay in play, so the existing reduced-motion block still
   stops them at its own weight without needing a day entry.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"][data-mode="day"] .night-sky__stars--far {
  opacity: 0.5;
  background-image:
    radial-gradient(circle at 26% 18%, rgba(137, 123, 101, 0.5) 0 1px, transparent 1.7px),
    radial-gradient(circle at 68% 63%, rgba(150, 137, 116, 0.42) 0 0.85px, transparent 1.5px),
    radial-gradient(circle at 41% 84%, rgba(137, 123, 101, 0.38) 0 0.9px, transparent 1.55px),
    radial-gradient(circle at 83% 33%, rgba(163, 151, 131, 0.34) 0 0.75px, transparent 1.35px),
    radial-gradient(circle at 12% 57%, rgba(150, 137, 116, 0.3) 0 0.7px, transparent 1.25px);
}

body[data-theme-id="december"][data-mode="day"] .night-sky__stars--near {
  opacity: 0.72;
  background-image:
    radial-gradient(circle at 33% 27%, rgba(242, 230, 210, 0.92) 0 1.2px, rgba(131, 117, 94, 0.55) 2px, transparent 3.4px),
    radial-gradient(circle at 71% 58%, rgba(242, 230, 210, 0.85) 0 1px, rgba(137, 123, 101, 0.5) 1.8px, transparent 2.5px),
    radial-gradient(circle at 14% 77%, rgba(242, 230, 210, 0.9) 0 1.1px, rgba(131, 117, 94, 0.48) 1.9px, transparent 2.7px),
    radial-gradient(circle at 56% 12%, rgba(242, 230, 210, 0.8) 0 0.85px, rgba(150, 137, 116, 0.44) 1.5px, transparent 2.1px);
}

/* ---------------------------------------------------------------------------
   THE GROUND. Eight layers, same order, same geometry — nothing here restates
   background-size or background-position, so the base block's scene tokens and
   the mobile rescale both still drive it, and the two drift domes and the two
   far wedges arrive already re-lit through the ramp.

   Three layers are literals and need saying:

     glints    at night these are crystals catching the moon, painted lighter
               than the snow. There is nothing lighter than sunlit snow, so by
               day they invert into the small blue shadows between the drifts —
               the same scattered rows, reading as texture instead of sparkle.
     field     the snow between the wood and the horizon, now white and
               deepening only slightly forward.
     haze      the atmospheric bank on the far treeline. It stays exactly where
               it is and keeps its job — densest at the tree bases, clearing
               going up — but distance in daylight washes toward WHITE, not
               toward slate, so the wash itself changes colour. This is what
               actually dissolves the far line; the far tree tokens only have
               to get out of its way.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"][data-mode="day"] .night-sky__aurora {
  background-image:
    var(--dec-drift-dome),
    var(--dec-drift-dome),
    radial-gradient(circle at 38% 44%, rgba(161, 147, 127, 0.3) 0 0.8px, transparent 1.5px),
    radial-gradient(circle at 66% 61%, rgba(175, 163, 144, 0.24) 0 0.65px, transparent 1.3px),
    linear-gradient(180deg, var(--dec-drift) 0%, #f2e6d2 40%, #f2e6d2 76%, var(--dec-drift-deep) 100%),
    linear-gradient(180deg, transparent 0%, rgba(242, 230, 210, 0.4) 52%, rgba(242, 230, 210, 0.72) 100%),
    var(--dec-wedge-far-b),
    var(--dec-wedge-far-a);
}

/* The midground spruce needs no counterpart: every layer in it is one of the
   wedge tokens, and those resolve through --dec-spruce, --dec-spruce-far and
   --dec-wedge-mid-cap, all of which are redeclared above. It re-lights for
   free, which is the whole argument for the ramp. */

/* ---------------------------------------------------------------------------
   THE FOREGROUND, and the lights unlit.

   Eleven layers, same order. Eight of them — both near banks, both crowns,
   both skirts and both caps — are tokens and arrive re-lit. The three that
   are not are the string lights, and they are the point of this rule.

   At night each bulb is a hot centre inside a soft corona, and the corona is
   part of the same radial-gradient rather than a box-shadow. By day there is
   no corona, because there is nothing lit. What is left is the object: a bead
   of coloured glass roughly 3px across, with a specular pinpoint at its centre
   and a tight contact shadow at its rim. Same three tile widths with no common
   factor, same three heights, so they still read as a string threaded through
   the wood rather than as a grid — and the two saturated ones are now the
   darkest, most chromatic marks in the whole scene, which is what keeps the
   near band reading against pale trees.

   Still static. A twinkle would be a third continuous animation, and it would
   be a lie twice over in this mode.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"][data-mode="day"] .night-sky__aurora::after {
  background-image:
    var(--dec-drift-dome-near),
    var(--dec-drift-dome-near),
    radial-gradient(circle at 50% 50%, rgba(242, 230, 210, 0.6) 0 0.5px, var(--dec-gold) 0.9px 1.6px, rgba(61, 41, 6, 0.3) 2.2px, transparent 3px),
    radial-gradient(circle at 50% 50%, rgba(242, 230, 210, 0.55) 0 0.5px, var(--dec-red) 0.9px 1.5px, rgba(90, 13, 13, 0.28) 2.1px, transparent 2.9px),
    radial-gradient(circle at 50% 50%, rgba(242, 230, 210, 0.92) 0 1px, rgba(180, 171, 154, 0.55) 1.7px, rgba(103, 92, 75, 0.22) 2.3px, transparent 3.1px),
    var(--dec-wedge-near-cap),
    var(--dec-wedge-near-a-crown),
    var(--dec-wedge-near-a-skirt),
    var(--dec-wedge-near-cap),
    var(--dec-wedge-near-b-crown),
    var(--dec-wedge-near-b-skirt);
}

/* ---------------------------------------------------------------------------
   THE CARD. Still the one element allowed its own fill, still a spruce panel
   with snow dusted across it and two strings of lights in the gutter — the
   light on it now falls from above instead of pooling up from its foot, and
   the bulbs are the same beads as the ones in the wood.

   Only background-image and the frame are restated. The per-layer positions,
   sizes and repeats come from the base shorthand and from the mobile block
   below it, and both are left untouched so the eight-layer geometry, including
   the tightened light strings at phone width, still holds.

   The card ground is measured for the same reason it is at night — main.css
   paints .tarot-card__numeral-date in --tt-red at 0.66rem. On the day
   --dec-hearth that is 5.18:1, against 4.65:1 at night, so the numeral has
   more room here than it has ever had. --tt-gold, which sets the numeral
   itself and the breadcrumb separators, reads 4.83:1 on the same ground, and
   --tt-breadcrumb-text 6.69:1.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"][data-mode="day"] .breadcrumb-nav {
  background-image:
    radial-gradient(circle at 50% 50%, rgba(242, 230, 210, 0.6) 0 0.45px, var(--dec-gold) 0.8px 1.35px, rgba(61, 41, 6, 0.3) 1.9px, transparent 2.6px),
    radial-gradient(circle at 50% 50%, rgba(242, 230, 210, 0.55) 0 0.45px, var(--dec-red) 0.8px 1.3px, rgba(90, 13, 13, 0.28) 1.85px, transparent 2.5px),
    radial-gradient(circle at 50% 50%, rgba(242, 230, 210, 0.6) 0 0.45px, var(--dec-gold) 0.8px 1.35px, rgba(61, 41, 6, 0.3) 1.9px, transparent 2.6px),
    radial-gradient(circle at 50% 50%, rgba(242, 230, 210, 0.55) 0 0.45px, var(--dec-red) 0.8px 1.3px, rgba(90, 13, 13, 0.28) 1.85px, transparent 2.5px),
    radial-gradient(circle at 33% 27%, rgba(242, 230, 210, 0.8) 0 0.7px, transparent 1.3px),
    radial-gradient(circle at 71% 64%, rgba(242, 230, 210, 0.6) 0 0.6px, transparent 1.2px),
    radial-gradient(ellipse at 50% -24%, rgba(242, 230, 210, 0.5), transparent 64%),
    linear-gradient(180deg, #dceddc 0%, var(--dec-hearth) 58%, #d4e3d4 100%);
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.8),
    inset 0 -1px 0 rgba(38, 57, 38, 0.16),
    0 1px 14px rgba(46, 37, 24, 0.1);
}

/* The terminal sweep stays a pass of light across the panel; on a pale panel it
   has to be white to be a pass of light at all. */
body[data-theme-id="december"][data-mode="day"] .breadcrumb-nav::before {
  background: linear-gradient(
    90deg,
    transparent,
    rgba(242, 230, 210, 0.6),
    rgba(193, 21, 16, 0.1),
    transparent
  );
}

/* ---------------------------------------------------------------------------
   HEADER AND HEADINGS.

   Every warm halo in this theme is a light source seen in the dark, and none
   of them survives the flip as a halo: on white, a bright glow is nothing and
   a heavy dark one is a smudge. Each becomes a lit lip plus a soft cast
   shadow, which is what a struck or printed mark actually has in daylight.
   --------------------------------------------------------------------------- */

/* The candle in the window is a window by day; the wordmark is simply printed. */
body[data-theme-id="december"][data-mode="day"] .brand a {
  text-shadow:
    0 1px 0 rgba(242, 230, 210, 0.9),
    0 2px 10px rgba(138, 92, 5, 0.28);
}

body[data-theme-id="december"][data-mode="day"] .brand a:hover {
  text-shadow:
    0 1px 0 rgba(242, 230, 210, 0.95),
    0 2px 14px rgba(193, 21, 16, 0.32);
}

body[data-theme-id="december"][data-mode="day"] .time-bar {
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.8),
    inset 0 -1px 0 rgba(46, 37, 24, 0.14);
}

/* Still a BLURRED shadow, for the reason the night rule gives at length: these
   letters are painted with background-clip:text and text-shadow renders in the
   text phase, so a zero-blur shadow would fill the transparent glyph with a
   flat block and bury the gradient. Only the colour and the alpha move. */
body[data-theme-id="december"][data-mode="day"] main h1,
body[data-theme-id="december"][data-mode="day"] .page-title,
body[data-theme-id="december"][data-mode="day"] main h2,
body[data-theme-id="december"][data-mode="day"] main h3,
body[data-theme-id="december"][data-mode="day"] main h4,
body[data-theme-id="december"][data-mode="day"] main h5,
body[data-theme-id="december"][data-mode="day"] main h6,
body[data-theme-id="december"][data-mode="day"] .markdown-page .heading-section__trigger {
  text-shadow:
    0 0 10px rgba(193, 21, 16, 0.16),
    0 0 26px rgba(138, 92, 5, 0.1);
}

/* The h2 rule draws from --tt-heading-rainbow and re-lights for free; only the
   rail's glow is a literal, and lit tubing on a bright afternoon is a painted
   stripe with a shadow under it. */
body[data-theme-id="december"][data-mode="day"] .heading-section::before {
  box-shadow: 0 1px 4px rgba(193, 21, 16, 0.22);
}

/* ---------------------------------------------------------------------------
   LINKS. Every colour arrives through the ramp — frosted evergreen at rest
   (7.39:1), deep gilt on hover (7.26:1), berry once read (7.61:1), and all
   three clear 4.5:1 over the near wood as well. Only the shadows need saying.

   The hover pulse is re-lit, not removed and not doubled: decemberCandleGlow
   animates three warm halos and animates nothing at all on paper, so the day
   uses its own keyframe. The two are mutually exclusive — one hovered element,
   one loop, text-shadow only — and neither can ever run at the same time as
   the other.

   This is (0,3,2), and main.css's doubled .celestial-chip.celestial-chip block
   is (0,3,0) plus its own :hover, so as at night none of it reaches the zodiac
   strip. Nothing here sets -webkit-text-fill-color.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"][data-mode="day"] a:hover,
body[data-theme-id="december"][data-mode="day"] a:focus-visible {
  text-shadow: 0 1px 0 rgba(242, 230, 210, 0.8);
  animation: decemberRibbonBloom 1.4s ease-in-out infinite alternate;
}

body[data-theme-id="december"][data-mode="day"] .eyebrow {
  text-shadow: 0 1px 0 rgba(242, 230, 210, 0.75);
}

/* ---------------------------------------------------------------------------
   SURFACES. The cold seat under the inputs and code inverts into a cooler,
   whiter sheet laid on the page — still a tint of --dec-midnight, still not a
   second page background. The frosted lip stays at the top and the shadow at
   the foot, so the panel reads as raised in both modes, and inline <code> is
   still left without the lip for the reason the night rule gives.
   --------------------------------------------------------------------------- */
body[data-theme-id="december"][data-mode="day"] input,
body[data-theme-id="december"][data-mode="day"] textarea,
body[data-theme-id="december"][data-mode="day"] select,
body[data-theme-id="december"][data-mode="day"] code,
body[data-theme-id="december"][data-mode="day"] pre {
  background-color: rgba(235, 230, 223, 0.66);
}

body[data-theme-id="december"][data-mode="day"] input,
body[data-theme-id="december"][data-mode="day"] textarea,
body[data-theme-id="december"][data-mode="day"] select,
body[data-theme-id="december"][data-mode="day"] pre {
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.9),
    inset 0 -1px 0 rgba(46, 37, 24, 0.12);
}

/* Still scoped by CLASS and never by element, for the reason spelled out on
   the night rule: the chip strip is mixed and a bare `button:hover` here would
   put a box halo on the moon while its seven anchor neighbours stayed clean. */
body[data-theme-id="december"][data-mode="day"] .sitemap-link:hover,
body[data-theme-id="december"][data-mode="day"] .sitemap-link:focus-visible {
  box-shadow: 0 1px 8px rgba(138, 92, 5, 0.24);
}

/* The table header is where holly red does its loudest structural work in
   either mode. The band is the anchor red; what changes is the lettering,
   which at night is void ink on a bright red and by day has to be the snow —
   #ffffff on #c1121f is 6.22:1, where the night's --dec-void on the day red
   would be 3.0:1 and fail. --dec-drift-lit is the palette's white, so the
   header takes the same token the lit crest of the snow does. */
body[data-theme-id="december"][data-mode="day"] th {
  color: var(--dec-drift-lit);
}

body[data-theme-id="december"][data-mode="day"] .hero-card,
body[data-theme-id="december"][data-mode="day"] .folder-section {
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.85),
    0 1px 10px rgba(46, 37, 24, 0.07);
}

body[data-theme-id="december"][data-mode="day"] .hero-card:hover,
body[data-theme-id="december"][data-mode="day"] .folder-section:hover {
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.95),
    0 2px 14px rgba(46, 37, 24, 0.12);
}

/* Still no left rule on a quote; the inset wash just has to be gilt-on-paper
   rather than candlelight-on-black. */
body[data-theme-id="december"][data-mode="day"] blockquote {
  box-shadow: inset 1rem 0 1.4rem -1.2rem rgba(138, 92, 5, 0.4);
}

/* The footer needs no day counterpart. The night rule lifts it off --muted
   because that token reads 4.27:1 on the night snow; by day the snow is the
   BRIGHTEST ground on the page and the darkest one is the near wood, where
   --dec-ice measures 5.49:1 and --dec-slate 4.71:1. Both clear, so the night's
   choice is simply already correct here and restating it would be noise. */

body[data-theme-id="december"][data-mode="day"]::-webkit-scrollbar-thumb,
body[data-theme-id="december"][data-mode="day"] ::-webkit-scrollbar-thumb {
  background-image: linear-gradient(
    180deg,
    rgba(242, 230, 210, 0.7) 0%,
    rgba(242, 230, 210, 0.12) 44%,
    rgba(46, 37, 24, 0.18) 100%
  );
}

/* Calendar. Colours and the event swatch all arrive through the ramp; the
   washes behind them are literals, and a 0.09 alpha of a pale night colour is
   invisible on paper. Same hues, day values. */
body[data-theme-id="december"][data-mode="day"] .calendar-app__nav,
body[data-theme-id="december"][data-mode="day"] .calendar-app__today {
  box-shadow:
    inset 0 1px 0 rgba(242, 230, 210, 0.85),
    inset 0 -1px 0 rgba(46, 37, 24, 0.12);
}

body[data-theme-id="december"][data-mode="day"] .calendar-app__nav:hover,
body[data-theme-id="december"][data-mode="day"] .calendar-app__today:hover,
body[data-theme-id="december"][data-mode="day"] .calendar-app__nav:focus-visible,
body[data-theme-id="december"][data-mode="day"] .calendar-app__today:focus-visible {
  background: rgba(138, 92, 5, 0.12);
}

body[data-theme-id="december"][data-mode="day"] .calendar-event__link {
  background: rgba(51, 87, 51, 0.08);
}

body[data-theme-id="december"][data-mode="day"] .calendar-event__link:hover,
body[data-theme-id="december"][data-mode="day"] .calendar-event__link:focus-visible {
  background: rgba(138, 92, 5, 0.13);
}

/* ---------------------------------------------------------------------------
   REDUCED MOTION AND REDUCED DATA, extended for the day.

   Both existing blocks select at (0,1,2). The day rules above are (0,2,2) and
   would outrank them, so anything the counterpart restates that those blocks
   also touch needs a day entry, or the day would quietly reinstate what the
   preference turns off. Two things qualify: the link pulse, because the day
   keyframe is declared at (0,2,2), and the thinned snow, because the day
   background-images are.

   The layer ANIMATIONS deliberately need no entry — nothing above restates
   `animation` on .night-sky__stars--*, so the base declarations are still the
   ones in play and both existing blocks already stop them at their own weight.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  body[data-theme-id="december"][data-mode="day"] a:hover,
  body[data-theme-id="december"][data-mode="day"] a:focus-visible {
    animation: none;
  }
}

@media (prefers-reduced-data: reduce) {
  body[data-theme-id="december"][data-mode="day"] a:hover,
  body[data-theme-id="december"][data-mode="day"] a:focus-visible {
    animation: none;
  }

  /* Two gradients a depth instead of five and four, held still, matching the
     thinning the night block does — and on the same tiles, since neither block
     restates background-size or background-position here. */
  body[data-theme-id="december"][data-mode="day"] .night-sky__stars--far {
    background-image:
      radial-gradient(circle at 26% 18%, rgba(137, 123, 101, 0.5) 0 1px, transparent 1.7px),
      radial-gradient(circle at 68% 63%, rgba(150, 137, 116, 0.42) 0 0.85px, transparent 1.5px);
  }

  body[data-theme-id="december"][data-mode="day"] .night-sky__stars--near {
    background-image:
      radial-gradient(circle at 33% 27%, rgba(242, 230, 210, 0.92) 0 1.2px, rgba(131, 117, 94, 0.55) 2px, transparent 3.4px),
      radial-gradient(circle at 14% 77%, rgba(242, 230, 210, 0.9) 0 1.1px, rgba(131, 117, 94, 0.48) 1.9px, transparent 2.7px);
  }
}

/* ---------------------------------------------------------------------------
   KEYFRAMES.

   Both snow loops travel exactly one 15rem background tile, so each restarts
   with no seam. y advances a quarter tile every 25% under linear timing, which
   keeps the fall speed dead constant, while x runs out and back as a triangle
   wave and returns to zero at the loop boundary — the drift, without a second
   animation and without an easing curve that would make the fall itself
   surge. Transform only, on two isolated fixed layers.
   --------------------------------------------------------------------------- */
@keyframes decemberSnowFar {
  0% { transform: translate3d(0, 0, 0); }
  25% { transform: translate3d(0.5rem, 3.75rem, 0); }
  50% { transform: translate3d(0, 7.5rem, 0); }
  75% { transform: translate3d(-0.5rem, 11.25rem, 0); }
  100% { transform: translate3d(0, 15rem, 0); }
}

@keyframes decemberSnowNear {
  0% { transform: translate3d(0, 0, 0); }
  25% { transform: translate3d(0.85rem, 3.75rem, 0); }
  50% { transform: translate3d(0, 7.5rem, 0); }
  75% { transform: translate3d(-0.85rem, 11.25rem, 0); }
  100% { transform: translate3d(0, 15rem, 0); }
}

/* Hover-only, one element at a time, text-shadow alone — a wick guttering.
   Replaces July's hotpink keyframe rather than adding to it. */
@keyframes decemberCandleGlow {
  from {
    text-shadow:
      0 0 6px rgba(255, 220, 138, 0.7),
      0 0 12px rgba(240, 196, 83, 0.44),
      0 0 22px rgba(238, 75, 74, 0.2);
  }
  to {
    text-shadow:
      0 0 9px rgba(255, 220, 138, 0.96),
      0 0 20px rgba(240, 196, 83, 0.72),
      0 0 32px rgba(238, 75, 74, 0.38);
  }
}

/* The daylight counterpart of the wick above, and the only other keyframe in
   this file. Nothing on a bright page can gutter, so the hovered link deepens
   instead — the gilt sinks a little further into the stock and comes back. Same
   property, same duration, same single hovered element, and the two are
   mutually exclusive, so the mode switch can never stack a second loop on
   anything. The white lip is held across both stops so the letter keeps its
   relief while the bloom moves under it. */
@keyframes decemberRibbonBloom {
  from {
    text-shadow:
      0 1px 0 rgba(242, 230, 210, 0.8),
      0 0 6px rgba(138, 92, 5, 0.22),
      0 1px 4px rgba(46, 37, 24, 0.16);
  }
  to {
    text-shadow:
      0 1px 0 rgba(242, 230, 210, 0.9),
      0 0 10px rgba(193, 21, 16, 0.34),
      0 1px 7px rgba(46, 37, 24, 0.3);
  }
}
