/* === ATOMS === */

/* .chrome-rim-glint — the inner, thinner glint band nested inside a
   liquid-chrome rim's outer metal band (src/tokens/chrome-metal.js
   applyLayeredConicChrome). From a rim's outer edge inward: the metal
   band (the rim element's own padding, e.g. .tab-group-rim/.step-card),
   then this glint band, then the actual fill content —
   matching a reference bezel where the base shading sits flush to the
   outer edge and the dynamic chromatic glint reads as its own thinner,
   more inset stroke, rather than both sharing one band's full width.
   border-radius: inherit keeps the nested-corner curve correct whether
   the outer rim is a pill or a card. */
.chrome-rim-glint {
  padding: 0.75px;
  border-radius: inherit;
}

/* .btn-rim / .btn / .btn-small / .btn-primary (src/atoms/button.js) — a
   small button with the "reflective" liquid-chrome rim, same
   double-band structure as .tab-group-rim/.chrome-rim-glint (a metal
   band, this element's own padding, then the thinner glint band nested
   inside), retro-rectangle clip-path'd rather than a plain border-radius
   pill. .btn-rim needs no background of its own — applyLayeredConicChrome
   (src/atoms/button.js) sets its conic-gradient background-image
   directly via JS, the same as .tab-group-rim. align-self: flex-start —
   without it this stretches to fill a flex-column container's cross
   axis, the same layout bug .tab-group-rim needed the same fix for. */
.btn-rim {
  display: inline-block;
  align-self: flex-start;
  padding: 1.5px;
  filter: drop-shadow(0 4px 20px rgba(0, 0, 0, 0.09)) drop-shadow(0 1px 4px rgba(0, 0, 0, 0.06));
}

.btn-rim[hidden] {
  display: none;
}

/* .btn — base button styling shared by every size/color variant. White
   fill (var(--color-surface)) is the "reflective" rim's actual
   reflective surface — a transparent button, like .tab or the old
   .kod-see-more, would show the glint band's own background straight
   through, reading as a thin ring rather than a solid button. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: var(--color-surface);
  font-family: var(--font-sans);
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s ease;
}

.btn:hover {
  background: var(--color-surface-tint);
}

.btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.btn-small {
  padding: 7px 14px;
  border-radius: var(--radius-interactive);
  font-size: 0.8125rem;
}

/* border-radius above is only the :focus-visible fallback shape for
   browsers that don't clip an element's own outline to its clip-path —
   see .tab's identical comment, this file, for the fuller reasoning;
   .btn's real shape comes from its own retro-rectangle clip-path
   (src/atoms/button.js). */
.btn-icon {
  flex-shrink: 0;
}

/* color, not just --sheen-base: an icon alongside the label (e.g. a
   chevron using stroke="currentColor") isn't a descendant of .btn-label,
   so it needs a real, non-transparent color to inherit — only the label
   span's own color gets overridden to transparent by .text-sheen. Same
   reasoning as .kod-see-more's own chevron used to need, styles/
   organisms/kueh-of-day.css. */
.btn-primary {
  color: var(--color-primary-strong);
  --sheen-base: var(--color-primary-strong);
}

/* .rim-matte-inner / .rim-matte-inner-glint — the static counterpart to
   .chrome-rim-glint's liquid rim: same double-band structure (a wider
   metal band, its thickness this element's own padding, then a thinner
   more-inset glint band nested inside), but fixed diagonal gradients from
   the metal palette (styles/tokens.css) instead of a --chrome-angle-
   driven conic sweep — no rotation, no per-element randomization, no JS
   wiring beyond src/atoms/matte-rim.js's wrapWithInnerMatteRim (which
   just builds the two-element nest and shapes each band's clip-path, not
   a rotation loop). Pick a matte rim over the liquid rim wherever a metal
   bezel shouldn't visually react to the cursor.

   "Inner" specifically: the rim, its glint band, and the fill it wraps
   are one visual unit sharing a single outer edge and a single elevation
   shadow (see .kod-media-column .rim-matte-inner, styles/organisms/
   kueh-of-day.css, for where that shadow actually lives) — the rim reads
   as this object's own material, not a separate frame. That's distinct
   from the "outer" rim (.rim-matte-outer / wrapWithOuterMatteRim, below):
   a metal bezel wrapping something that's already a complete, self-
   contained visual unit with its own bounds — e.g. framing a small icon,
   or adding a bezel around a control that might already carry its own
   shadow — where the frame and the thing it frames read as two separate
   layers, not one fused object.

   border-radius: inherit is the shape fallback for plain rectangular/
   pill consumers; a clip-path'd consumer (retro-rectangle shapes) needs its
   own clip-path set on both bands directly, since clip-path doesn't
   inherit the way border-radius does — wrapWithInnerMatteRim handles
   that automatically.

   The dark/mid stops are color-mix()'d toward white, not used raw and
   not blended toward --metal-base — --metal-base itself (#6b6e78) is a
   fairly dark medium gray, so an earlier pass that compressed the range
   by blending the shadow/highlight endpoints *toward --metal-base* still
   anchored the whole rim around that dark tone and read as too heavy
   overall, even though the swing between darkest and lightest had
   shrunk. Mixing toward white instead raises the average lightness while
   keeping the same light/dark rhythm (contrast .matte-metal-surface,
   which needed the same "blend toward white, not toward a mid-dark
   token" move for its own, much wider panel).

   The highlight stop is the opposite case: --metal-highlight is itself
   #ffffff (styles/tokens.css), so color-mix()'ing it *toward white* is a
   no-op — 60% white blended with 40% white is still just white,
   regardless of the ratio, which is why this peak was reading as a flat,
   blazing #fff no matter how "toned down" the percentage looked on
   paper. Blending it toward --metal-base instead is what actually pulls
   it down to a light-but-not-pure-white gray. */
.rim-matte-inner {
  width: 100%;
  height: 100%;
  padding: 1.5px;
  border-radius: inherit;
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--rim-base, var(--metal-base)) 45%, white) 0%,
    color-mix(in srgb, var(--rim-base, var(--metal-base)) 30%, white) 20%,
    color-mix(in srgb, var(--metal-highlight) 88%, var(--rim-base, var(--metal-base))) 45%,
    color-mix(in srgb, var(--rim-base, var(--metal-base)) 30%, white) 65%,
    color-mix(in srgb, var(--rim-base, var(--metal-base)) 45%, white) 100%
  );
}

/* .metal-seam / .metal-seam-line (src/atoms/metal-seam.js) — two thin
   flush lines sitting side by side, touching with no gap between them
   (.metal-seam's own gap: 0): not a scored groove cut into one sheet,
   but the butted edges of two separate sheets of metal meeting — one
   edge catching the light (:first-child, the glint side), the other
   sitting just behind it in that glint's shadow (:last-child). No
   border-radius on either — flush square ends are what let the line's
   own top/bottom edges land exactly on the section's top/bottom edges
   (see .kod-seam-line's negative-offset bleed, kueh-of-day.css) rather
   than reading as a rounded rod capped short of it.

   Both stops are mixed toward *white*, not toward --metal-base/-shadow
   directly — the same move .rim-matte-inner's own comment above
   explains (its darkest stop is "45% metal-base, 55% white", never raw
   metal-base), and for the same reason: .matte-metal-surface's own panel
   is itself mostly white (background-color: 24% metal-base into white,
   below), so anything anchored at metal-base's/-shadow's own darkness
   reads as heavily dark by comparison regardless of how it's then tuned.

   Each line holds a flat baseline for most of its length, with only a
   short window right around the vertical midpoint (42%-58%) actually
   shifting toward its highlight/shadow extreme — a brief glint/shadow
   moment, not a value sustained the full height (an earlier pass ramped
   from each end straight to the midpoint, so nearly the whole line sat
   partway toward the extreme instead of holding a calm baseline). The
   glint edge's baseline (28% metal-base into white) reads close to the
   panel's own tone; its brief peak (10% metal-base into white) lifts
   only a little above that — not pure white, which read as blown-out
   against this panel. The shadow edge's baseline/peak (52%/70% metal-base
   into white — darkened from an earlier 40%/55%, which didn't read as
   clearly darker than the glint edge) sit a shade darker throughout,
   without crushing toward raw --metal-base or --metal-shadow. */
.metal-seam {
  display: flex;
  gap: 0;
  width: 100%;
  height: 100%;
}

.metal-seam-line {
  width: 1px;
  height: 100%;
}

.metal-seam-line:first-child {
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--metal-base) 28%, white) 0%,
    color-mix(in srgb, var(--metal-base) 28%, white) 42%,
    color-mix(in srgb, var(--metal-base) 10%, white) 50%,
    color-mix(in srgb, var(--metal-base) 28%, white) 58%,
    color-mix(in srgb, var(--metal-base) 28%, white) 100%
  );
}

.metal-seam-line:last-child {
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--metal-base) 52%, white) 0%,
    color-mix(in srgb, var(--metal-base) 52%, white) 42%,
    color-mix(in srgb, var(--metal-base) 70%, white) 50%,
    color-mix(in srgb, var(--metal-base) 52%, white) 58%,
    color-mix(in srgb, var(--metal-base) 52%, white) 100%
  );
}

/* .metal-seam-horizontal — same two-line construction, rotated: a
   full-bleed row divider instead of a column divider. flex-direction:
   column stacks the two lines top-to-bottom instead of side-by-side; each
   line swaps its own width/height (100%/1px instead of 1px/100%) and its
   gradient axis (to right instead of to bottom) but keeps the identical
   color-mix stops, so it reads as the same seam material just turned 90deg.
   height: 2px overrides the base .metal-seam's own height:100% — the
   vertical seam stretches to fill a column's own height (set by its
   parent), but a horizontal seam's "height" is really just its own two
   1px lines stacked, not something that should stretch to fill whatever
   block-level parent it sits in. */
.metal-seam-horizontal {
  flex-direction: column;
  height: 2px;
}

.metal-seam-horizontal .metal-seam-line {
  width: 100%;
  height: 1px;
}

.metal-seam-horizontal .metal-seam-line:first-child {
  background: linear-gradient(
    to right,
    color-mix(in srgb, var(--metal-base) 28%, white) 0%,
    color-mix(in srgb, var(--metal-base) 28%, white) 42%,
    color-mix(in srgb, var(--metal-base) 10%, white) 50%,
    color-mix(in srgb, var(--metal-base) 28%, white) 58%,
    color-mix(in srgb, var(--metal-base) 28%, white) 100%
  );
}

.metal-seam-horizontal .metal-seam-line:last-child {
  background: linear-gradient(
    to right,
    color-mix(in srgb, var(--metal-base) 52%, white) 0%,
    color-mix(in srgb, var(--metal-base) 52%, white) 42%,
    color-mix(in srgb, var(--metal-base) 70%, white) 50%,
    color-mix(in srgb, var(--metal-base) 52%, white) 58%,
    color-mix(in srgb, var(--metal-base) 52%, white) 100%
  );
}

/* .rim-matte-inner-tinted — recolors the rim from the neutral --metal-base
   to the current theme's primary-strong color (--rim-base, which
   .rim-matte-inner/-glint's gradients above already fall back from) —
   same color-mix ratios, so the light/dark rhythm is identical, just built
   from a different base hue. For a matte rim sitting inside a solid
   theme-colored area (the countdown clock's water-clock window, on the
   dark hero background) rather than the light, neutral surfaces
   .rim-matte-inner was built for — a plain gray/silver bezel there would
   read as a mismatched material dropped onto the green, not a rim that
   belongs to the same object. --rim-base is a custom property, so setting
   it here on the outer rim reaches the nested .rim-matte-inner-glint band
   too without that band needing its own modifier class.
   display/width/height: also switches from "stretch to fill an
   already-sized ambient layout" (kueh-of-day's own grid/flex column,
   which .rim-matte-inner's width/height: 100% assume) to "shrink-wrap
   around the fillEl it wraps" — the countdown viewport's size is driven
   bottom-up by its own digit content instead. */
.rim-matte-inner-tinted {
  --rim-base: var(--color-primary-strong);
  display: inline-block;
  width: auto;
  height: auto;
}

.rim-matte-inner-tinted .rim-matte-inner-glint {
  display: inline-block;
  width: auto;
  height: auto;
}

/* .housing-frame-wrap / .housing-frame (src/atoms/housing-frame.js) — a
   thick decorative material housing drawn OUTSIDE an element's own edge:
   a plain div clipped to a shape (clip-path: path(...), set in JS) with
   a static conic-gradient background (the same "wrap dark/light bands
   around the shape's contour, from one shared center" math the site's
   interactive liquid-chrome rims use — chrome-metal.js's
   computeConicChromeLayers — just with no rotation registered, so it
   stays fixed rather than tracking the cursor/scroll). Originated for
   the hero countdown's own water-clock window (src/organisms/
   countdown-clock.js) — reusable for any other shape/button/UI element
   that wants the same treatment.

   .housing-frame-wrap: a plain shrink-wrapped positioning box around
   both the wrapped element and the frame — needed because a clip-path'd
   fillEl (a retro-shape window, .rim-matte-inner, etc.) would otherwise
   clip the frame's own outward bleed away if the frame were nested
   inside it instead of being a sibling (clip-path clips *all* of an
   element's descendants, not just its own background).

   left/top/width/height on .housing-frame are set directly in JS
   (wrapWithHousingFrame's own update()), not a fixed inset/100% here —
   the div's own box has to actually extend past fillEl's edge by the
   current outset amount (not just be clipped to a shape that does),
   since background painting stops at the border-box regardless of what
   clip-path reveals beyond it. */
.housing-frame-wrap {
  position: relative;
  display: inline-block;
  width: auto;
  height: auto;
}

/* Noise layer + --housing-metal (the conic-gradient, set via
   outline.style.setProperty in housing-frame.js) painted together in one
   background-image list — JS sets a custom property here instead of
   background-image directly, since assigning el.style.backgroundImage
   would replace this whole property (including the CSS-defined noise
   layer below it) rather than adding to it; a custom property, unlike
   other style properties, still gets read by this rule's own var()
   regardless of whether it's set inline or here in the stylesheet.

   The noise texture itself is the exact same feTurbulence recipe
   .matte-metal-surface uses below (tiled 200x200, desaturated, multiply-
   blended at 0.25 opacity) — same brushed-steel grain, so the housing
   reads as that same material rather than a flat gradient. Duplicated
   literally rather than factored into a shared custom property, so
   retuning one doesn't risk silently changing the other. */
/* will-change: transform pins this to its own stable compositing layer —
   mobile Safari only, this was observed briefly rendering dark/blank a
   few seconds into each drop-chute release cycle (src/organisms/
   drop-chute.js) and correcting a moment later, with no underlying
   style/DOM change at all (confirmed via computed-style polling) — a
   stale-tile/layer-eviction repaint bug, not a real state change. Forcing
   a dedicated layer here is the standard workaround for that class of
   WebKit bug — same reasoning as .drop-chute's own will-change (styles/
   organisms/drop-chute.css), which was showing the identical symptom. */
.housing-frame {
  position: absolute;
  pointer-events: none;
  will-change: transform;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.25'/%3E%3C/svg%3E"),
    var(--housing-metal);
  background-repeat: repeat, no-repeat;
  background-size: 200px 200px, 100% 100%;
  background-blend-mode: multiply, normal;
}

/* width/height: 100% (not just relying on a block element's default
   fill-width) matters here specifically because height doesn't share
   that default — a block box with no explicit height shrink-wraps its
   content instead, so a child further down this chain asking for its
   own height: 100% would resolve against `auto` and get an ellipse
   instead of a circle wherever an ancestor (like .rim-matte-inner) does
   have a real pixel height, e.g. a fixed-size circular badge
   (.kod-tag-icon-badge, kueh-of-day.css) rather than a shrink-to-content
   rim like .tab-group-rim. Harmless no-op for those shrink-to-content
   consumers, since 100% against an auto-height ancestor still just
   resolves to auto. */
.rim-matte-inner-glint {
  width: 100%;
  height: 100%;
  padding: 0.75px;
  border-radius: inherit;
  background: linear-gradient(
    135deg,
    transparent 0%,
    color-mix(in srgb, var(--metal-highlight) 94%, var(--rim-base, var(--metal-base))) 45%,
    transparent 60%
  );
}

/* .retro-shape-fill — the filled <path>'s own SVG wrapper whenever
   createRetroShape is called with a `fill` option (src/atoms/retro-shape.js),
   e.g. nested inside .rim-matte-inner-glint via wrapWithInnerMatteRim's own
   fillRefs param. Every such consumer needs this: DOM order alone doesn't
   keep it behind the rest of its parent's content (a position:absolute box
   paints in its own stacking step regardless of tree order) — z-index: -1
   against the parent's own position:relative (which makes that parent the
   stacking context) is what actually pins it behind them. width/height:100%
   is what makes the fill actually cover its parent's box in the first
   place — without it, the SVG falls back to its own unstyled intrinsic
   size (confirmed directly: a consumer outside kueh-of-day.js, where this
   rule originally lived scoped to that one stylesheet, rendered with no
   visible fill at all until this was promoted here). */
.retro-shape-fill {
  position: absolute;
  z-index: -1;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* .wire-bundle (src/atoms/wire-bundle.js) — a generative colored-wire
   background. No z-index needed the way .retro-shape-fill above needs -1:
   its consumer (src/organisms/check-in.js) appends it AFTER the fill svg
   and BEFORE any real foreground content, so plain DOM order alone paints
   it in between. width/height: 100% + the SVG's own
   preserveAspectRatio="none" stretches its fixed 0 0 100 100 viewBox
   (wire-bundle.js's own comment) to match whatever real box it's dropped
   into. */
.wire-bundle {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* .rim-matte-outer-wrap / .rim-matte-outer (src/atoms/matte-rim.js's
   wrapWithOuterMatteRim) — the "outer" counterpart .rim-matte-inner's own
   comment above describes: a thin metal bezel framing an already-complete
   element from *outside* its edge, rather than rim+glint+fill sharing one
   edge as a single fused object. Structurally this is wrapWithHousingFrame's
   own "grow the wrapped shape's silhouette outward by a flat outset"
   technique (.housing-frame-wrap/.housing-frame, below) — a div sized/
   positioned in JS to extend past fillEl on every side, clipped to a path
   grown outward by that same amount — just carrying .rim-matte-inner's
   own thin static gradient instead of housing's thick conic "liquid
   chrome" + noise texture. One band, not two (no separate glint layer):
   at the thin 1-2px scale this rim is meant for, a nested glint band
   would be imperceptibly thin on top of it, unlike .rim-matte-inner-glint
   which has real reachable padding to work with.

   Positioning is a mirror of .housing-frame-wrap/.housing-frame:
   left/top/width/height/clip-path are all set directly in JS (the
   wrapper needs a size other than fillEl's own to stay unclipped by any
   clip-path fillEl itself carries), display: inline-block/width: auto so
   the wrap shrink-wraps to fillEl rather than stretching. */
.rim-matte-outer-wrap {
  position: relative;
  display: inline-block;
  width: auto;
  height: auto;
}

.rim-matte-outer {
  position: absolute;
  pointer-events: none;
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--rim-base, var(--metal-base)) 45%, white) 0%,
    color-mix(in srgb, var(--rim-base, var(--metal-base)) 30%, white) 20%,
    color-mix(in srgb, var(--metal-highlight) 88%, var(--rim-base, var(--metal-base))) 45%,
    color-mix(in srgb, var(--rim-base, var(--metal-base)) 30%, white) 65%,
    color-mix(in srgb, var(--rim-base, var(--metal-base)) 45%, white) 100%
  );
}

/* .matte-metal-surface — a full matte steel panel background (reference:
   a brushed elevator control panel), the "surface" counterpart to
   .rim-matte-inner's "rim" — same static metal palette (styles/
   tokens.css), no cursor/scroll reaction. Three layers, painted top to
   bottom:
     1. a tiled feTurbulence noise texture, desaturated and blended with
        `multiply` (baked into the SVG's own `opacity` attribute —
        background-image layers have no CSS opacity of their own),
        approximating brushed steel's fine grain without drawing actual
        directional strokes. `multiply` specifically, not `overlay` —
        overlay only meaningfully darkens where the noise is already
        dark and barely lightens on a near-white base like this one, so
        the grain read as essentially invisible at first; multiply
        darkens proportionally to the noise's own value regardless of
        how light the base is. 0.25 landed between two bad extremes —
        0.16 read as no texture at all, 0.4 read as visible speckling
        rather than a fine grain.
     2. a soft off-center radial highlight (`soft-light`), reading as a
        broad, diffuse light source rather than a hard specular point.
     3. a vertical (top-to-bottom) linear-gradient drifting cool ->
        neutral -> warm -> neutral, each stop a color-mix() of a metal
        token with white (18-30% token, the rest white) rather than the
        raw token — a lighter mix than .rim-matte-inner's own (a thin rim
        can carry a stronger shadow-to-highlight range and still read as
        polished metal edge; a whole panel this size at that much
        contrast reads as a strip light, not brushed steel), but not so
        light the drift disappears entirely — an earlier pass at 10-12%
        flattened it past the point of being visible at all. One stop
        also mixes in a touch of --color-accent — the day's rotating
        palette (src/tokens/colors.js, applyPalette) — so the panel picks
        up a faint ambient cast matching today's kueh without needing any
        cursor/scroll reaction of its own; the palette already only
        changes once per page load, so this stays as static as every
        other stop. */
.matte-metal-surface {
  background-color: color-mix(in srgb, var(--metal-base) 24%, white);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.25'/%3E%3C/svg%3E"),
    radial-gradient(ellipse 90% 70% at 22% 15%, rgba(255, 255, 255, 0.22), transparent 60%),
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--metal-base-cool) 30%, white) 0%,
      color-mix(in srgb, var(--metal-base) 24%, white) 32%,
      color-mix(in srgb, var(--color-accent) 18%, color-mix(in srgb, var(--metal-base) 24%, white)) 55%,
      color-mix(in srgb, var(--metal-base-warm) 30%, white) 76%,
      color-mix(in srgb, var(--metal-base) 24%, white) 100%
    );
  background-repeat: repeat, no-repeat, no-repeat;
  /* 100% 100vh (not `cover`) on the radial-highlight and linear-gradient
     layers — `cover`'s percentage stops are sized against whatever box is
     painting the background, so every time .kueh-of-day-section's own
     height changes (e.g. mid-transition while "See more" expands
     .kod-content-window and the section grows with it) `cover` recomputes
     against the new, taller box and the gradient visibly restretches/
     redistributes frame-to-frame — a "moving gradient" during what should
     just be a height change. Sizing to 100vh instead ties the gradient's
     scale to the viewport height, a value that doesn't change when the
     section resizes, so growing the section just reveals more of the same
     fixed-scale gradient rather than recalculating a stretched one — and
     since the linear-gradient's own 100% stop already equals this
     background's flat background-color exactly, any height beyond 100vh
     (an unusually tall expanded state) fades into that flat color with no
     visible seam rather than an abrupt cutoff.
     (An earlier attempt used background-attachment: fixed instead, which
     sizes/positions a layer against the viewport directly — cleaner in
     theory, but it silently falls back to acting like `scroll` here,
     because .kueh-of-day-section also carries the `reveal` class, and
     `.reveal.visible` sets `transform: translateY(0)` — any non-`none`
     transform, even a no-op identity one, creates a new containing block
     that background-attachment: fixed treats as its viewport substitute.
     Sizing against 100vh instead sidesteps that interaction entirely.) */
  background-size: 200px 200px, 100% 100vh, 100% 100vh;
  background-blend-mode: multiply, soft-light, normal;
}

/* .metal-rivet-row / .metal-rivet (src/atoms/rivets.js) — a sparse row of
   small embossed metal dots, meant to sit along a .matte-metal-surface
   panel's top/bottom edge (reference: a riveted steel panel's seam).
   justify-content: space-between spreads the dots across the row's real,
   current width — its container (.metal-rivet-row-top/bottom,
   kueh-of-day.css) is pinned to the section's own left/right edges, so
   this always matches the section's actual rendered width at any
   viewport, no vw-based guessing that could under/overshoot. gap: 85px
   is a *floor* space-between won't compress below; in practice it only
   ever becomes the binding constraint right at the width where the
   container stops having room to spare, which is also exactly the width
   where kueh-of-day.css's own media query takes over and switches the
   container itself to a centered, fixed layout — see that rule for why
   space-between alone can't produce a symmetric bleed past that point
   (it collapses to flex-start, one-sided, once there's no free space
   left to distribute). */
.metal-rivet-row {
  display: flex;
  justify-content: space-between;
  gap: 85px;
  pointer-events: none;
}

/* Runs the row top-to-bottom instead of left-to-right — the Kueh of the
   Day seam (.kod-seam-rivets, kueh-of-day.css) running alongside the
   vertical line between its two columns, rather than a panel's flat
   top/bottom edge. width/height: 100% (not the base rule's implicit
   shrink-to-content) is what lets space-between distribute dots across
   the seam's own actual rendered height, the same reasoning the base
   row's width: 100% container (.metal-rivet-row-top/-bottom) relies on.
   gap: 40px is a much lower floor than the horizontal row's 85px — the
   seam is a section-height line, not a section-width one, so fewer
   pixels are available to spread a handful of dots across. */
.metal-rivet-row-vertical {
  flex-direction: column;
  gap: 40px;
  width: auto;
  height: 100%;
}

/* radial-gradient (not a flat fill) is what reads as a small embossed
   bump rather than a flat dot — a highlight near the top-left, same
   light-source convention .rim-matte-inner's own diagonal gradient uses,
   darkening toward the edge. Every stop is color-mix()'d toward white,
   not toward raw --metal-base — --metal-base itself is noticeably darker
   than .matte-metal-surface's own rendered tone (that panel blends
   --metal-base only ~18-22% into white), so anchoring the rivet's
   mid-tone on raw --metal-base sat visibly darker than the panel it's
   supposed to sit flush on, even after the highlight/shadow range itself
   had been softened. Mixing toward white instead lands the rivet's own
   mid-tone close to the panel's actual color (same fix .rim-matte-inner
   needed for the same reason). The highlight stop is the opposite case,
   same as .rim-matte-inner's own highlight stop: --metal-highlight is
   itself #ffffff, so mixing it *toward white* never actually dims it —
   blended toward --metal-base instead. The two box-shadows add the
   actual dimensionality: a soft drop shadow beneath (it's raised off the
   panel) and a faint inset shadow along the bottom edge (the underside,
   where the bump curves away from the light). */
.metal-rivet {
  width: 7px;
  height: 7px;
  flex-shrink: 0;
  border-radius: 50%;
  background: radial-gradient(
    circle at 35% 30%,
    color-mix(in srgb, var(--metal-highlight) 80%, var(--metal-base)) 0%,
    color-mix(in srgb, var(--metal-base) 22%, white) 55%,
    color-mix(in srgb, var(--metal-base) 40%, white) 100%
  );
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), inset 0 -0.5px 0.5px rgba(0, 0, 0, 0.18);
}

/* .text-sheen — a subtle, fixed-vertical light band across text: base
   color, a slightly lighter step, back to base. Unlike the liquid-chrome
   rims, this never rotates — it tracks cursor Y only (src/tokens/
   chrome-metal.js registerForSheen), via --sheen-pos (0%-100% down the
   element). Cursor above the element pins the light to the very top,
   cursor below pins it to the bottom, cursor alongside the element makes
   the light step follow it. Elements using this set --sheen-base to
   whatever their own color would normally be (can't just use currentColor:
   this rule sets color: transparent to reveal the gradient, and
   currentColor would then resolve to that same transparent, not the
   element's real intended color). */
.text-sheen {
  background: linear-gradient(to bottom,
    var(--sheen-base) 0%,
    var(--sheen-base) calc(var(--sheen-pos) - 25%),
    color-mix(in srgb, var(--sheen-base) 80%, white) var(--sheen-pos),
    var(--sheen-base) calc(var(--sheen-pos) + 25%),
    var(--sheen-base) 100%
  );
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* .icon-sheen marks which icons src/organisms/chrome-accents.js's blanket
   sweep should apply the light accent to — the actual visual treatment is
   .icon-sheen-wrap/.icon-sheen-highlight below, built at runtime by
   applyIconFillSheen() (src/tokens/chrome-metal.js), since it needs a
   cloned DOM layer, not just a CSS rule on the icon itself. */

/* .icon-sheen-wrap — sizes to the base icon (its only in-flow child);
   .icon-sheen-highlight is the lightened clone, absolutely positioned
   exactly on top of it. */
.icon-sheen-wrap {
  position: relative;
  display: inline-flex;
  vertical-align: middle;
}

/* The clone is masked to a soft band around --sheen-pos (identical shape to
   .text-sheen's gradient, see atoms.css above, so both accents move
   together) — everywhere outside that band the mask is fully transparent,
   so the clone (and its brightened pixels) simply doesn't render there and
   the base icon underneath shows through unchanged. Because the mask is
   multiplied against the clone's own alpha, the highlight can never bleed
   past the icon's own silhouette the way a drop-shadow does — it only ever
   lightens pixels the icon already paints, which is what reads as a fill
   catching light rather than a glow around the icon. brightness()/
   saturate() (not a recolored fill/stroke) is what keeps this working
   regardless of the icon's own fill complexity. */
.icon-sheen-highlight {
  position: absolute;
  inset: 0;
  filter: brightness(1.6) saturate(0.7);
  -webkit-mask-image: linear-gradient(to bottom,
    transparent 0%,
    transparent calc(var(--sheen-pos) - 25%),
    white var(--sheen-pos),
    transparent calc(var(--sheen-pos) + 25%),
    transparent 100%
  );
  mask-image: linear-gradient(to bottom,
    transparent 0%,
    transparent calc(var(--sheen-pos) - 25%),
    white var(--sheen-pos),
    transparent calc(var(--sheen-pos) + 25%),
    transparent 100%
  );
  pointer-events: none;
}

/* .tab — the tab group's sliding .tab-highlight (src/molecules/
   tab-group.js) paints the selected-tab background, so .tab itself has no
   background of its own; that now lives on the .tab-fill child below,
   split out specifically so it can stack *below* the highlight while the
   label stacks *above* it (see .tab-fill's own comment). position:
   relative with no z-index here is deliberate: it anchors .tab-fill's
   inset:0 without giving .tab itself a stacking context of its own, which
   is what lets .tab-fill and .text-sheen (children) escape past it and
   stack independently against the highlight sibling instead of moving as
   one fused unit with .tab. Text color still switches per aria-selected
   here (needs to read against the highlight once it slides underneath).
   border-radius is only a fallback for :focus-visible in browsers that
   don't clip an element's own outline to its clip-path (outline, like
   box-shadow, generally paints outside the clipped region), using
   --radius-interactive rather than the old --radius-pill so that fallback
   at least approximates the retro-rectangle's character instead of a
   leftover pill. */
.tab {
  position: relative;
  appearance: none;
  border: none;
  background: none;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  font-weight: 600;
  padding: 9px 20px;
  border-radius: var(--radius-interactive);
  cursor: pointer;
  --sheen-base: var(--color-text-on-surface-muted);
}

/* .tab-fill — the actual hover-tint layer (see .tab's own comment above
   for why this isn't just .tab's own background). z-index: -2 puts it one
   step below .tab-highlight's own -1 (molecules.css) once both escape
   .tab's non-stacking-context box to compare directly against each other
   — so a hovered, not-currently-selected tab's tint always sits *behind*
   the sliding indicator rather than fighting it for the top layer while
   it transits past. clip-path: inherit copies .tab's own retro-rectangle
   shape (set inline by tab-group.js's shapeElement) so the tint fills the
   identical silhouette without its own separate clip-path wiring.
   aria-hidden/pointer-events: none — purely decorative, never a click or
   hover target of its own (the real button underneath still is). */
.tab-fill {
  position: absolute;
  inset: 0;
  z-index: -2;
  border-radius: inherit;
  clip-path: inherit;
  pointer-events: none;
  transition: background-color 0.15s ease;
}

.tab:hover:not([aria-selected="true"]) .tab-fill {
  background-color: var(--color-surface-tint);
}

.tab:hover:not([aria-selected="true"]) {
  --sheen-base: var(--color-text-on-surface);
}

.tab[aria-selected="true"] {
  --sheen-base: var(--color-text-on-primary);
}

.tab:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Escapes .tab's own (non-)stacking context the same way .tab-fill does
   above, but lands *above* .tab-highlight (z-index: -1, molecules.css) —
   so the label always reads on top of the sliding indicator, whichever
   tab it's currently under mid-transition. Scoped to .tab specifically,
   not the shared .text-sheen rule itself, since other .text-sheen
   consumers (e.g. .btn-label, src/atoms/button.js) have no such sibling
   to escape past and don't need this. */
.tab .text-sheen {
  position: relative;
  z-index: 0;
}

/* .kueh-icon — small inline SVG wrapper, sits next to the kueh name */
.kueh-icon {
  display: inline-flex;
  vertical-align: middle;
  flex-shrink: 0;
}
