/* TimePicker — visual layer. * * Reuses time-field tokens for the field-shaped portion (Input + Segments) * and the calendar/popover surface tokens for the popover Clock body. */ [data-time-picker] { --_time-field-height: var(--time-field-height-md); --_time-field-px: var(--time-field-px-md); --_time-field-gap: var(--time-field-gap-md); --_time-field-segment-px: var(--time-field-segment-px-md); --_time-field-font-size: var(--time-field-font-size-md); --_time-field-accent-border: var(--color-primary-border); --_time-field-accent-track: var(--color-primary-track); --_time-field-accent-text: var(--color-primary-text); display: inline-flex; flex-direction: column; gap: var(--time-field-stack-gap); inline-size: 100%; min-inline-size: 0; color: var(--time-field-color); font-family: var(--time-field-font-family); font-size: var(--_time-field-font-size); line-height: var(--time-field-line-height); } [data-time-picker][data-size='xs'] { --_time-field-height: var(--time-field-height-xs); --_time-field-px: var(--time-field-px-xs); --_time-field-gap: var(--time-field-gap-xs); --_time-field-segment-px: var(--time-field-segment-px-xs); --_time-field-font-size: var(--time-field-font-size-xs); } [data-time-picker][data-size='sm'] { --_time-field-height: var(--time-field-height-sm); --_time-field-px: var(--time-field-px-sm); --_time-field-gap: var(--time-field-gap-sm); --_time-field-segment-px: var(--time-field-segment-px-sm); --_time-field-font-size: var(--time-field-font-size-sm); } [data-time-picker][data-size='lg'] { --_time-field-height: var(--time-field-height-lg); --_time-field-px: var(--time-field-px-lg); --_time-field-gap: var(--time-field-gap-lg); --_time-field-segment-px: var(--time-field-segment-px-lg); --_time-field-font-size: var(--time-field-font-size-lg); } [data-time-picker][data-color='secondary'] { --_time-field-accent-border: var(--color-secondary-border); --_time-field-accent-track: var(--color-secondary-track); --_time-field-accent-text: var(--color-secondary-text); } [data-time-picker][data-color='neutral'] { --_time-field-accent-border: var(--color-neutral-border); --_time-field-accent-track: var(--color-neutral-track); --_time-field-accent-text: var(--color-neutral-text); } [data-time-picker][data-color='affirm'] { --_time-field-accent-border: var(--color-affirm-border); --_time-field-accent-track: var(--color-affirm-track); --_time-field-accent-text: var(--color-affirm-text); } [data-time-picker][data-color='fulfill'] { --_time-field-accent-border: var(--color-fulfill-border); --_time-field-accent-track: var(--color-fulfill-track); --_time-field-accent-text: var(--color-fulfill-text); } [data-time-picker][data-color='risk'] { --_time-field-accent-border: var(--color-risk-border); --_time-field-accent-track: var(--color-risk-track); --_time-field-accent-text: var(--color-risk-text); } [data-time-picker][data-color='threat'] { --_time-field-accent-border: var(--color-threat-border); --_time-field-accent-track: var(--color-threat-track); --_time-field-accent-text: var(--color-threat-text); } [data-time-picker][data-color='loss'] { --_time-field-accent-border: var(--color-loss-border); --_time-field-accent-track: var(--color-loss-track); --_time-field-accent-text: var(--color-loss-text); } /* ── Trigger ─────────────────────────────────────────────────────────────── */ [data-time-picker-trigger] { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; inline-size: var(--_time-field-height); block-size: var(--_time-field-height); padding: 0; border: var(--time-field-border-width) solid var(--time-field-border); border-radius: var(--time-field-radius); background: var(--time-field-bg); color: inherit; cursor: pointer; transition: background var(--time-field-transition-duration) var(--time-field-transition-ease), border-color var(--time-field-transition-duration) var(--time-field-transition-ease), box-shadow var(--time-field-transition-duration) var(--time-field-transition-ease), color var(--time-field-transition-duration) var(--time-field-transition-ease); } [data-time-picker-trigger]:hover { border-color: var(--_time-field-accent-border); background: var(--_time-field-accent-track); color: var(--_time-field-accent-text); } [data-time-picker-trigger]:focus-visible { outline: none; border-color: var(--_time-field-accent-border); box-shadow: var(--time-field-focus-shadow); } [data-time-picker-trigger][data-disabled], [data-time-picker-trigger]:disabled { cursor: not-allowed; opacity: var(--time-field-disabled-opacity); } /* Embedded trigger inside the input — flush affordance like date-picker. */ [data-time-field-input] [data-time-picker-trigger] { flex: 0 0 auto; /* `--time-field-segment-height` is scoped to `[data-time-field]` (not rendered here) → undefined, box collapsed. Use the picker-local `--_time-field-height` (scales per size). `font: inherit` so the `1em` icon tracks the field font. */ inline-size: calc(var(--_time-field-height) - var(--space-2)); block-size: calc(var(--_time-field-height) - var(--space-2)); margin-inline-start: auto; padding: 0; border: none; border-radius: var(--time-field-segment-radius); background: transparent; color: var(--time-field-segment-color); box-shadow: none; font: inherit; } [data-time-field-input] [data-time-picker-trigger]:hover { border: none; background: var(--_time-field-accent-track); color: var(--_time-field-accent-text); } [data-time-field-input] [data-time-picker-trigger]:focus-visible { outline: none; border: none; background: var(--field-segment-active-bg); color: var(--field-segment-active-text); } /* ── Popover content / Clock surface ─────────────────────────────────────── */ [data-popover-content]:has([data-time-picker-clock]) { --_popover-content-width-override: max-content; --_popover-content-min-width-override: max-content; --_popover-content-max-width-override: calc(100vw - var(--space-4)); } [data-time-picker-clock] { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-2-5); min-inline-size: 14rem; color: var(--color-content-primary); font-family: var(--font-ui); font-size: var(--font-size-sm); line-height: var(--leading-ui); } [data-time-picker-clock] [data-slider] { inline-size: 100%; } /* ── Labelled scale (ruler) above hour slider, below minute/second ───────── */ .time-picker-slider { display: flex; flex-direction: column; gap: 2px; inline-size: 100%; } /* Channel caption naming each slider (Hour / Minute / Second). Visual only — the soma Slider already carries the same text as `aria-label`, so the caption is `aria-hidden`. */ .time-picker-slider-label { margin-block-end: var(--space-1); color: var(--color-content-secondary); font-family: var(--font-ui); font-size: var(--font-size-xxs); font-weight: var(--font-weight-medium); letter-spacing: var(--tracking-caps); line-height: 1; text-transform: uppercase; } .time-picker-scale { position: relative; block-size: 0.875rem; inline-size: 100%; /* Inner inset matches the slider's thumb radius so endpoint labels align with the actual track endpoints, not the bounding box. */ padding-inline: calc(var(--_slider-thumb-size, 1rem) / 2); box-sizing: border-box; } .time-picker-scale-tick { position: absolute; inset-block: 0; transform: translateX(-50%); display: inline-flex; flex-direction: column; align-items: center; gap: 1px; color: var(--color-content-muted); font-family: var(--font-mono, var(--font-ui)); /* Smallest typographic step in the system token set — keeps the ruler readable but visually subordinate to the slider thumb / value. */ font-size: var(--font-size-xxs); line-height: 1; pointer-events: none; } .time-picker-scale-mark { display: block; inline-size: 1px; block-size: 4px; background: var(--color-border-default); } .time-picker-scale-label { display: block; } /* Below variant: marks rise to the top of the scale row so the label is underneath the track. */ .time-picker-scale-below .time-picker-scale-tick { flex-direction: column-reverse; } /* ── Per-channel accent palette ─────────────────────────────────────────── Differentiates the three sliders visually: hour uses the picker's primary accent, minute uses secondary (cool counterpart), second uses a muted tone so it visually subordinates. All three remain semantically equivalent — the differentiation is purely visual to help the user track which channel each slider drives. */ /* Hour = primary, Minute = secondary, Second = neutral. Tokens are resolved at the clock root using global CSS vars (not the picker's inherited `--_time-field-accent-*`) because the Popover content is portaled outside the picker scope — inherited custom properties do not cross portal boundaries. */ [data-time-picker-clock] [data-time-picker-hour-slider] { --_time-picker-slider-accent: var(--color-primary-border); --_time-picker-slider-track: var(--color-primary-track); } [data-time-picker-clock] [data-time-picker-minute-slider] { --_time-picker-slider-accent: var(--color-secondary-border); --_time-picker-slider-track: var(--color-secondary-track); } [data-time-picker-clock] [data-time-picker-second-slider] { --_time-picker-slider-accent: var(--color-neutral-border); --_time-picker-slider-track: var(--color-neutral-track); } /* ── Slider thumb / range reinforcement inside the clock ────────────────── The base slider recipe sets thumb color from --color-surface-default over the primary range; inside the popover this can blend with the popover surface. Bump emphasis with the per-channel accent. */ [data-time-picker-clock] [data-slider-thumb] { border-color: var(--_time-picker-slider-accent, var(--_time-field-accent-border)); box-shadow: var(--slider-thumb-shadow), 0 0 0 2px var(--color-surface-default); } [data-time-picker-clock] [data-slider-thumb]:focus-visible { box-shadow: var(--slider-thumb-focus-shadow), 0 0 0 2px var(--color-surface-default); } [data-time-picker-clock] [data-slider-range] { background: var(--_time-picker-slider-accent, var(--_time-field-accent-border)); } @media (prefers-reduced-motion: reduce) { [data-time-picker-trigger] { transition: none; } }