:root {
  --nl-canvas: var(--void, #060a14);
  --nl-canvas-gradient: var(--void-gradient, linear-gradient(#0c1426, #060a14));
  --nl-surface-card: var(--card-tint, #141c34);
  --nl-surface-card-deep: var(--card-tint-deep, #090e1c);
  /* Tracks the active theme like its sibling surfaces. A fixed literal here renders
     dark-on-dark in every light theme, where --ink is dark. */
  --nl-surface-elevated: var(--card-tint, #141c34);
  --nl-overlay: rgba(2, 6, 15, .46);
  --nl-text-primary: var(--ink, #e9effb);
  --nl-text-secondary: var(--dim, #a7b5d0);
  --nl-text-tertiary: var(--faint, #8da0c2);
  --nl-border: var(--glass-border, rgba(255, 255, 255, .12));
  --nl-border-strong: rgba(255, 255, 255, .22);
  --nl-accent: var(--accent, #7c9cff);
  /* The accent as ink. A light theme's accent is a mid-tone chosen to fill a
     control, and as text it measured 2.6 to 3.6 to one on its own panels;
     those themes declare a deeper --accent-ink of the same hue. Fills,
     borders and rings keep --nl-accent. */
  --nl-accent-text: var(--accent-ink, var(--accent, #7c9cff));
  --nl-on-accent: #071018;
  --nl-focus: #a9c4ff;
  --nl-focus-outer: rgba(3, 7, 18, .86);
  --nl-status-success: #34d399;
  --nl-status-danger: #fb7185;
  --nl-status-warning: #fbbf24;
  /* Type. A closed set: if a size is not on this list it is not a decision,
     it is someone nudging a number until one screen looked right. Seven steps
     cover the whole product; the clock is the single deliberate exception and
     scales fluidly because it is the one thing read from across the room. */
  --nl-text-2xs: 11px;
  --nl-text-xs: 12px;
  --nl-text-sm: 13px;
  --nl-text-md: 14px;
  --nl-text-lg: 16px;
  --nl-text-xl: 20px;
  --nl-text-2xl: 24px;
  /* Tracking is a function of size, from a table, never per element. Positive
     tracking belongs to uppercase micro-labels and to nothing else. */
  --nl-track-tight: -0.01em;
  --nl-track-none: 0;
  --nl-track-label: 0.06em;
  --nl-track-wide: 0.12em;
  --nl-space-1: 4px; --nl-space-2: 8px; --nl-space-3: 12px; --nl-space-4: 16px;
  --nl-space-5: 20px; --nl-space-6: 24px; --nl-space-8: 32px; --nl-space-10: 40px; --nl-space-12: 48px;
  --nl-radius-sm: 10px; --nl-radius-md: 14px; --nl-radius-lg: 18px; --nl-radius-xl: 24px;
  /* Elevation. One light source, above and slightly in front, for the whole
     product. Three steps: a control that lifts off its surface, a surface that
     floats over the page, and a surface that owns the screen. There were
     eighty-four distinct shadows here, which is not a vocabulary, it is
     eighty-four different implied light sources. */
  /* Selection and focus are a ring, not a bloom. One width, so a focused input,
     a chosen theme and a card being dragged all say the same thing the same
     way; previously they said it at one, two, three and four pixels. */
  --nl-ring: 0 0 0 3px var(--accent-glow);
  --nl-ring-tight: 0 0 0 2px var(--accent);
  /* A theme tints and dampens the ladder; it does not get to redeclare it.
     Six dark themes used to write out their own card shadow, differing only in
     the hue of a glow and two points of alpha, and three light themes wrote a
     hand-tinted one with a white rim on top. Two variables replace all twelve. */
  --nl-shadow-ink: #000;
  --nl-shadow-strength: 1;
  --nl-shadow-1:
    0 1px 2px color-mix(in srgb, var(--nl-shadow-ink) calc(14% * var(--nl-shadow-strength)), transparent),
    0 2px 8px color-mix(in srgb, var(--nl-shadow-ink) calc(10% * var(--nl-shadow-strength)), transparent);
  --nl-shadow-2:
    0 4px 12px color-mix(in srgb, var(--nl-shadow-ink) calc(18% * var(--nl-shadow-strength)), transparent),
    0 12px 32px color-mix(in srgb, var(--nl-shadow-ink) calc(22% * var(--nl-shadow-strength)), transparent);
  /* A drawer is not lifted off the board, it is beside it. The ladder above is
     for things that rise, so borrowing it here aimed the shadow downward, past
     the bottom edge, where no page is left to receive it — and the panel lost
     the one cue that made it read as sliding over the page rather than being
     pasted onto it. This one points back the way the drawer came in. */
  --nl-shadow-drawer:
    -8px 0 24px color-mix(in srgb, var(--nl-shadow-ink) calc(26% * var(--nl-shadow-strength)), transparent),
    -32px 0 64px color-mix(in srgb, var(--nl-shadow-ink) calc(30% * var(--nl-shadow-strength)), transparent);
  --nl-shadow-3:
    0 8px 24px color-mix(in srgb, var(--nl-shadow-ink) calc(26% * var(--nl-shadow-strength)), transparent),
    0 32px 64px color-mix(in srgb, var(--nl-shadow-ink) calc(30% * var(--nl-shadow-strength)), transparent);
  --nl-motion-fast: 120ms;
  --nl-motion-control: 170ms;
  --nl-motion-panel: 260ms;
  --nl-motion-enter: 320ms;
  /* Two curves, and which one applies is not a matter of taste but of what the
     motion is for. Something that travels — a drawer entering, a menu appearing,
     a panel sliding — should leave fast and settle slow, which is the
     emphasized curve. Something that merely answers — a colour under the
     cursor, an opacity, a two-pixel nudge — is not travelling anywhere, and
     given a decelerate curve it snaps at the start and crawls at the end.
     Sweeping one token across all of them is how every hover in this product
     came to feel abrupt at once. */
  --nl-ease-state: ease;
  --nl-ease-emphasized: cubic-bezier(.2, .8, .2, 1);
  /* One deliberate overshoot for moments that should feel like they landed. */
  /* Duration and curve travel together. Kept apart, 119 call sites re-pair them
     by hand and several quietly pair a token duration with a bare `ease`. */
  --nl-transition-fast: var(--nl-motion-fast) var(--nl-ease-state);
  --nl-transition-control: var(--nl-motion-control) var(--nl-ease-state);
  --nl-transition-panel: var(--nl-motion-panel) var(--nl-ease-emphasized);
  /* Travel at control speed, and at fast speed. The composites exist so that
     nobody has to pair a duration with a curve by hand, and a rule that does
     is a rule whose intent was never written down: it was exactly such hand
     pairing that survived the sweep which moved every state transition onto
     the travel curve, so twenty-six controls kept snapping under the cursor
     after the sweep was declared reverted. A test now forbids the pairing
     outside this file, which means every call site has to say which of these
     it means. */
  --nl-transition-enter: var(--nl-motion-control) var(--nl-ease-emphasized);
  --nl-transition-enter-fast: var(--nl-motion-fast) var(--nl-ease-emphasized);
  --nl-transition-pop: var(--nl-motion-control) var(--nl-ease-pop);
  --nl-transition-pop-fast: var(--nl-motion-fast) var(--nl-ease-pop);
  --nl-transition-pop-panel: var(--nl-motion-panel) var(--nl-ease-pop);
  --nl-ease-pop: cubic-bezier(.2, .9, .3, 1.25);
  /* A third kind of motion: something being put down. A folder settling into
     its row, a copy landing on its tile, a bar arriving at the bottom of the
     window. It is sampled from a damped spring — damping ratio 0.78, two per
     cent past the mark and back — instead of drawn as a Bézier, because a
     placed thing should arrive the way an object does: quickly, with one
     breath of settle. A spring spends the second half of its time within a
     hair of rest, so its durations are longer than the travel it covers.
     Colour and opacity never use it; they have nowhere to overshoot to. The
     linear() form is below, behind @supports; this is the fallback. */
  --nl-ease-spring: var(--nl-ease-emphasized);
  --nl-motion-settle: 420ms;
  --nl-transition-settle: var(--nl-motion-settle) var(--nl-ease-spring);
  --nl-transition-settle-fast: var(--nl-motion-panel) var(--nl-ease-spring);
  /* The one motion longer than a panel: a new theme spreading across the page
     from the card that chose it. It happens a few times in a product's life,
     and it is the only transition that covers the whole screen. */
  --nl-motion-reveal: 460ms;
  --nl-transition-reveal: var(--nl-motion-reveal) var(--nl-ease-emphasized);
  /* Three levels of one material. The four raw filter sliders that used to sit
     in settings were an unmade decision handed to the user, and they could be
     driven to states where text stopped being readable. */
  /* One ladder, named, so a new layer has to say where it belongs rather than
     pick a number bigger than the last one someone remembered. There were
     twenty distinct literals from 0 to 500, #toast-dock was declared twice with
     two different values, and the portalled select list sat below the confirm
     dialog it can be opened from. */
  --nl-z-background: 0;
  --nl-z-veil: 1;
  /* <main id="page"> deliberately has no layer of its own: giving it one made it
     a stacking context, which trapped the search bar inside it and forced the
     scrim below the whole composition. */
  /* Page furniture — the settings button and the folded-folder dock — sits above
     the board but below the scrim, so focusing search quiets them too. */
  --nl-z-chrome: 4;
  --nl-z-scrim: 6;
  --nl-z-raised: 10;
  --nl-z-float: 20;
  /* The drawer's own backdrop sits below it. Putting the two the other way
     round is not a cosmetic mistake: the scrim swallows every click meant for
     the panel it is dimming behind. */
  --nl-z-drawer-scrim: 90;
  --nl-z-drawer: 100;
  --nl-z-overlay: 200;
  --nl-z-modal: 300;
  --nl-z-menu: 400;
  --nl-z-toast: 500;
  --nl-target-min: 40px;
}

/* The spring itself, forty samples of it (see --nl-ease-spring above). */
@supports (transition-timing-function: linear(0, 1)) {
  :root { --nl-ease-spring: linear(0, 0.0215, 0.0766, 0.1533, 0.2422, 0.3362, 0.4299, 0.5196, 0.6028, 0.6781, 0.7446, 0.8022, 0.8512, 0.892, 0.9253, 0.952, 0.973, 0.9889, 1.0007, 1.009, 1.0146, 1.0179, 1.0195, 1.0199, 1.0194, 1.0182, 1.0166, 1.0148, 1.0129, 1.0111, 1.0093, 1.0077, 1.0062, 1.0049, 1.0038, 1.0028, 1.002, 1.0014, 1.0009, 1); }
}

html[data-glass="subtle"] {
  --glass-blur: 12px;
  --glass-saturate: 130%;
  --glass-opacity: 0.86;
  --glass-border-sheen: 0.2;
}

html[data-glass="off"] {
  --glass-blur: 0px;
  --glass-saturate: 100%;
  --glass-opacity: 1;
  --glass-border-sheen: 0;
}

/* High legibility — asked for by the system (prefers-contrast: more) or by the
   switch in Appearance. Solid glass, the quieter text tiers pulled towards the
   ink, and a shadow under the words that sit straight on the sky. The sky
   itself is dimmed and its quiet zones held to 7:1 by the scripts. */
html[data-legibility="high"] {
  --glass-blur: 0px;
  --glass-saturate: 100%;
  --glass-opacity: 1;
  --glass-border-sheen: 0;
  --nl-text-secondary: color-mix(in oklch, var(--dim, #a7b5d0) 50%, var(--ink, #e9effb));
  --nl-text-tertiary: color-mix(in oklch, var(--faint, #8da0c2) 45%, var(--ink, #e9effb));
}
html[data-legibility="high"] :is(#clock, #date, #greet) {
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7), 0 0 12px rgba(0, 0, 0, 0.45);
}
html.light-ui[data-legibility="high"] :is(#clock, #date, #greet) {
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8), 0 0 12px rgba(255, 255, 255, 0.55);
}

/* Forced colours: the system decides every colour, so the painted sky — which
   it cannot recolour — steps aside, and so does anything translucent over it. */
@media (forced-colors: active) {
  #bg-canvas, #veil, #dim { display: none !important; }
  :where(.card, #search, #cfg, .glass-context-menu, .quick-modal-card, .toast) {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
}

/* Blur is not free and is not universal. Where the browser cannot do it, the
   surface must already be opaque enough to read against, not merely lighter. */
@supports not (backdrop-filter: blur(1px)) {
  :root { --glass-opacity: 0.96; }
}

:where(button, a, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--nl-focus);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--nl-focus-outer);
}

/* Form controls do not inherit type from the page: the browser gives buttons
   its own face at 13.33px. So the rail, the first-run actions, Export, Save
   mood and a dozen other buttons rendered in Arial, and the three typography
   slots never reached any of them. Zero specificity, so every component rule
   that sets its own size, weight or colour still wins. */
:where(button, input, select, textarea, optgroup) {
  font-family: inherit;
  font-size: var(--nl-text-sm);
  letter-spacing: inherit;
  color: inherit;
}

/* Placeholders are text. The browser's grey measured 3.2 to one on the
   settings fields in Nord Frost; the tertiary tier is held above 4.8. */
::placeholder {
  color: var(--nl-text-tertiary);
  opacity: 1;
}

/* Author display rules must never override the platform's closed-layer state. */
[hidden] { display: none !important; }

.nl-visually-hidden {
  position: fixed; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

@supports (color: color-mix(in oklch, white, black)) {
  :root {
    --nl-border-strong: color-mix(in oklch, var(--nl-text-primary) 24%, transparent);
    /* Lift the card tint toward the text colour: lighter than the card on dark themes,
       darker than it on light ones, so it separates in both directions. */
    --nl-surface-elevated: color-mix(in srgb, var(--card-tint, #141c34) 88%, var(--ink, #e9effb) 12%);
  }
}

@media (prefers-reduced-motion: reduce) {
  :root { --nl-motion-control: 80ms; --nl-motion-panel: 100ms; --nl-motion-enter: 100ms; --nl-motion-settle: 100ms; --nl-motion-reveal: 100ms; }
}
