/* ==========================================================================
   retro-desktop-theme / shell
   --------------------------------------------------------------------------
   The operating system: desktop, icons, windows, taskbar, programs menu.
   This file is the archetype rather than a garnish. Delete it and shell.js
   and you still have a readable page built from tokens.css and
   components.css, which is the JS-last contract the shell class is built on.

   HOW THE PROGRESSIVE ENHANCEMENT WORKS. The markup is an ordinary document:
   a header, a nav of anchor links, window articles in reading order, a
   footer nav. This file styles that document twice:

     1. The base styles below assume no JavaScript. Windows are stacked
        beveled cards in document order, the icon nav is a visible grid of
        anchor links, and the taskbar's shortcut bar is a nav that jumps to
        each window. The page scrolls like a page. Everything is reachable
        and readable.

     2. shell.js puts `rd-live` on the <html> element as its first act.
        Every rule scoped under .rd-live upgrades the same markup into an
        operating system: the page stops scrolling, windows become openable
        surfaces above the desktop, icons open them, the taskbar tracks them
        beside the shortcut bar that does not change. No markup is
        duplicated; the document is the OS.

   THE BEVELS ARE CONSTRUCTED, NEVER DECLARED. Nothing in this file says
   border-style: outset. Every raised and sunken edge is one of the four
   composed shadow tokens from tokens.css, which is what makes an era bevel
   both accurate (four lines in a fixed order, not one flat edge) and
   re-skinnable (CUSTOMIZE.md flattens the whole theme by rewriting two
   token values).

   Every color here is a var() reference to tokens.css. There is not one
   color literal in this file.

   Requires tokens.css. Load it, then components.css, then this, then the
   script:

     <link rel="stylesheet" href="tokens/tokens.css" />
     <link rel="stylesheet" href="components/components.css" />
     <link rel="stylesheet" href="shell/shell.css" />
     <script src="shell/shell.js" defer></script>
   ========================================================================== */

/* --------------------------------------------------------------------------
   DESKTOP, AND THE WALLPAPER SYSTEM
   The body is the desktop, and the desktop ground is a wallpaper slot, not a
   color. Two axes stay independent: the register (tokens.css) says what
   colors exist, the wallpaper (a data attribute on body) says how the ground
   composes them. This is the shell class's standard mechanism, inherited
   from the pilot, and the attribute name is deliberately the same one.

   THE MECHANISM:
     body[data-wallpaper="quiet"]  flat teal, and also what you get with no
                                   attribute at all, so the no-JS document
                                   carries it by plain CSS
     body[data-wallpaper="slats"]  reveals the inline SVG slat pattern

   shell.js only toggles the attribute; every visual belongs to these
   attribute-scoped rules. The picker, like all behavior, exists only after
   enhancement.

   THE DEFAULT IS FLAT, AND THAT IS THE DEVIATION FROM THE PILOT. The pilot
   enhances into its scene and falls back to its quiet field. Here the flat
   teal IS the era: a solid field behind beveled gray chrome is the thing
   being rebuilt, and a demo that boots into a pattern would be showing the
   costume before the thing wearing it. So quiet is the default in both
   directions and the pattern is opt-in.

   CONTRAST BY CONSTRUCTION, POINTING THE OTHER WAY. The pilot's ground is
   light, so its rule is that the wallpaper may paint only with light tokens.
   This ground is dark and the only ink allowed on it is white, so the rule
   inverts: the wallpaper may paint only with the ground tones and only
   DOWNWARD from the teal. The guarantee is the measurement, not the
   direction. White on every paint this layer is allowed to use:
     ground 4.77:1, slat 5.75:1, groove 7.18:1
   All three clear AA for the icon labels, which are the only text that ever
   sits on the wallpaper. The class guarantee, should a future variant want
   paint lighter than the ground: a token-driven scrim between wallpaper and
   content, with the ratios re-measured through it. No shipped variant needs
   one.
   -------------------------------------------------------------------------- */
.rd-desktop-ground {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background-color: var(--rd-ground);
  color: var(--rd-ink);
  font-family: var(--rd-font-ui);
  font-size: var(--rd-text-body);
  font-weight: var(--rd-weight-body);
  line-height: var(--rd-leading-body);
}

/* The slat layer: an inline SVG in the page markup, because an SVG loaded
   through an image or a data URI is an isolated document that cannot read
   custom properties. Inlined, the paint rules below reach it and a re-skin
   of tokens.css re-skins the wallpaper with everything else. Hidden until
   the body attribute asks for it, so it costs the no-JS document nothing
   but bytes. */
.rd-wallpaper {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.rd-wallpaper > svg {
  width: 100%;
  height: 100%;
}

body[data-wallpaper="slats"] .rd-wallpaper {
  display: block;
}

/* Wallpaper paint rules. Only the three ground tones, per the contract
   above. */
.rd-wallpaper .rd-art-slat {
  fill: var(--rd-ground-slat);
}

.rd-wallpaper .rd-art-groove {
  fill: var(--rd-ground-groove);
}

.rd-wallpaper .rd-art-lift {
  fill: var(--rd-ground);
}

/* Anyone who has asked for more contrast gets the flat field regardless of
   what the picker says. Placed after the slats rule so it wins on source
   order at equal specificity. */
@media (prefers-contrast: more) {
  body[data-wallpaper] .rd-wallpaper {
    display: none;
  }
}

/* The OS does not scroll; its windows do. Only when live: without the
   script the page is a page, and pages scroll. */
.rd-live,
.rd-live .rd-desktop-ground {
  overflow: hidden;
  height: 100vh;
  height: 100dvh;
}

/* --------------------------------------------------------------------------
   SKIP LINK
   Above everything, including the programs menu. A raised control, like
   every other button here.
   -------------------------------------------------------------------------- */
.rd-skip {
  position: absolute;
  left: -9999px;
}

.rd-skip:focus {
  left: var(--rd-space-3);
  top: var(--rd-space-3);
  z-index: var(--rd-z-skip);
  padding: var(--rd-space-2) var(--rd-space-4);
  background: var(--rd-face);
  color: var(--rd-ink);
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-raise);
  font-weight: var(--rd-weight-bold);
  font-size: var(--rd-text-sm);
}

/* --------------------------------------------------------------------------
   MASTHEAD
   The document header, for the page that has not been enhanced yet. Live, it
   goes away entirely rather than becoming a chip: this era's desktop had no
   menu bar and no brand plate, and the product's name is carried where the
   era carried it, in the title bar of every window ("Read me first -
   Tambour") and in the document title.
   -------------------------------------------------------------------------- */
.rd-brand {
  padding: var(--rd-space-6) var(--rd-space-4) 0;
}

/* Both of these are desk ink, not page ink, and that is not a style choice.
   The masthead is the one piece of prose that sits directly on the desktop
   ground, and the ground is dark: full black on the teal measures 4.40:1 and
   the muted ink is worse. White is 4.77:1 and clears AA. The tagline gives
   up its muted tone to get there, which is the right trade; there is no
   lighter-than-white to demote it to. This was caught by rendering the no-JS
   document rather than by reading the file, which is the argument for
   rendering it. */
.rd-brand-name {
  margin: 0;
  font-size: var(--rd-text-h1);
  font-weight: var(--rd-weight-bold);
  color: var(--rd-desk-ink);
}

.rd-brand-tagline {
  margin: var(--rd-space-2) 0 0;
  max-width: var(--rd-measure);
  color: var(--rd-desk-ink);
}

.rd-live .rd-brand {
  display: none;
}

/* --------------------------------------------------------------------------
   ICONS
   A nav of anchor links wearing three costumes, one element, never
   duplicated:
     as a page      a wrapping grid under the masthead
     live, closed   a column-major grid pinned to the desktop's top-left,
                    which is where this era put it
     live, open     the programs menu, standing above the launcher button

   The third costume has a cost worth naming: opening the menu takes the
   icons off the desktop, because they are the same six anchors. The
   alternative was a second copy of the nav in the markup, and the class
   forbids duplicated markup for good reasons. Closing the menu puts them
   back.

   No icon plate. The pilot gives each glyph a tile with a border and a
   shadow; this era set its glyphs directly on the wallpaper with the label
   underneath, and the label is the only thing with a background, and only
   when it is selected.
   -------------------------------------------------------------------------- */
.rd-icons {
  padding: var(--rd-space-6) var(--rd-space-4);
}

.rd-icons-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--rd-space-2);
}

.rd-icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--rd-space-1);
  width: var(--rd-icon-cell);
  padding: var(--rd-space-2) var(--rd-space-1);

  text-decoration: none;
  text-align: center;
  border-radius: var(--rd-radius);
}

.rd-icon:focus-visible {
  outline: var(--rd-ring-width) var(--rd-ring-style) var(--rd-ring-invert);
  outline-offset: calc(-1 * var(--rd-ring-inset));
}

.rd-icon-glyph {
  display: grid;
  place-items: center;
  width: var(--rd-icon-size);
  height: var(--rd-icon-size);
}

.rd-icon-glyph > svg {
  width: 100%;
  height: 100%;
}

/* Era selection: the label, not the glyph, takes the highlight. */
.rd-icon-label {
  padding: 0 var(--rd-space-1);
  font-size: var(--rd-text-xs);
  line-height: var(--rd-leading-snug);
  color: var(--rd-desk-ink);
}

.rd-icon:hover .rd-icon-label,
.rd-icon:focus-visible .rd-icon-label {
  background: var(--rd-accent);
  color: var(--rd-accent-ink);
}

/* Icon artwork. Four paint classes, the same three-tone logic the era's
   16-color icons used: paper, chrome, one accent, one warning fill. Painted
   from tokens so a re-skin reaches the icons too. */
.rd-ico-paper {
  fill: var(--rd-surface);
  stroke: var(--rd-ink);
}

.rd-ico-face {
  fill: var(--rd-face);
  stroke: var(--rd-ink);
}

.rd-ico-accent {
  fill: var(--rd-accent);
  stroke: var(--rd-ink);
}

.rd-ico-warn {
  fill: var(--rd-fill-warning);
  stroke: var(--rd-ink);
}

.rd-ico-line {
  fill: none;
  stroke: var(--rd-ink);
}

/* Live, closed: the desktop grid. Column-major with a fixed row count, so
   icons fill downward and then start a second column, which is the order
   this era filled a desktop in. */
.rd-live .rd-icons {
  position: fixed;
  top: var(--rd-space-3);
  left: var(--rd-space-2);
  padding: 0;
}

.rd-live .rd-icons-list {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(4, auto);
  gap: var(--rd-space-1);
}

/* --------------------------------------------------------------------------
   WINDOW, AS A PAGE
   Without the script a window is a beveled card: a raised frame cut from the
   face, a title bar in the accent, a sunken white client area, stacked in
   reading order with the page scrolling past. The [data-rd-controls] slot
   stays empty; close and minimize are injected by shell.js because a control
   that does nothing must not exist.
   -------------------------------------------------------------------------- */
.rd-window {
  max-width: var(--rd-window-width);
  margin: 0 auto var(--rd-space-8);
  /* Twice the bevel, so the client area clears the frame's own edge with a
     line of face still showing. That is this era's window frame. */
  padding: calc(var(--rd-bevel-width) * 2);

  display: flex;
  flex-direction: column;

  background: var(--rd-face);
  border-radius: var(--rd-radius-window);
  box-shadow: var(--rd-raise);
}

.rd-titlebar {
  display: flex;
  align-items: center;
  gap: var(--rd-space-2);
  min-height: var(--rd-titlebar-height);
  padding: 0 var(--rd-space-1) 0 var(--rd-space-2);

  background: var(--rd-accent);
  color: var(--rd-accent-ink);
}

.rd-title {
  margin: 0;
  font-size: var(--rd-text-sm);
  font-weight: var(--rd-weight-bold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The double line. Era title bars filled the space between the name and the
   controls with a pair of rules; it is the one piece of decoration the
   chrome allowed itself. Drawn in currentColor so it follows the title bar's
   ink into the idle state and through any re-skin. Decorative and
   aria-hidden in the markup: it says nothing. */
.rd-titlelines {
  flex: 1;
  min-width: 0;
  height: 5px;
  background-image: linear-gradient(
    to bottom,
    currentColor 0 1px,
    transparent 1px 3px,
    currentColor 3px 4px,
    transparent 4px
  );
}

.rd-controls {
  display: flex;
  gap: var(--rd-space-1);
}

/* The title-bar control. 24px square, which is the WCAG 2.5.8 minimum
   exactly; see the note in tokens.css for why it is not larger. The press is
   the bevel inverting, which is the only press feedback this era had and the
   only one it needs. */
.rd-control {
  display: grid;
  place-items: center;
  width: var(--rd-control-size);
  height: var(--rd-control-size);
  padding: 0;

  color: var(--rd-ink);
  background: var(--rd-face);
  border: 0;
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-raise-thin);
  cursor: pointer;
}

.rd-control:active {
  box-shadow: var(--rd-sink-thin);
}

.rd-control:focus-visible {
  outline: var(--rd-ring-width) var(--rd-ring-style) var(--rd-ring);
  outline-offset: calc(-1 * var(--rd-ring-inset));
}

.rd-control > svg {
  width: 10px;
  height: 10px;
}

.rd-window-body {
  padding: var(--rd-space-6);
  margin-top: var(--rd-bevel-width);
  background: var(--rd-surface);
  box-shadow: var(--rd-sink-thin);
  overflow-wrap: break-word;
}

.rd-window-body > :first-child {
  margin-top: 0;
}

/* --------------------------------------------------------------------------
   WINDOW, LIVE
   The same article, floating. Closed windows are display:none, which also
   removes them from the tab order; no aria-hidden bookkeeping is needed.
   Position: centered under the top edge, pushed by the cascade custom
   properties shell.js sets per window, clamped so a cascaded window cannot
   leave the viewport on a narrow screen.
   -------------------------------------------------------------------------- */
.rd-live .rd-window {
  display: none;
  position: fixed;
  left: clamp(
    var(--rd-space-2),
    calc(50% - var(--rd-window-width) / 2 + var(--rd-dx, 0px)),
    calc(100% - var(--rd-window-width) - var(--rd-space-2))
  );
  top: calc(var(--rd-space-8) + var(--rd-dy, 0px));
  width: min(var(--rd-window-width), calc(100vw - 2 * var(--rd-space-2)));
  max-height: calc(
    100dvh - var(--rd-taskbar-height) - var(--rd-space-8) - var(--rd-space-8)
  );
  margin: 0;
  z-index: var(--rd-z-window);
}

.rd-live .rd-window.rd-open {
  display: flex;
  animation: rd-window-in var(--rd-duration) var(--rd-ease);
}

/* The window behind is not dimmed or shrunk; its title bar goes gray. That
   was the entire visual language for focus in this era, and it still works
   because the accent appears exactly once on screen. */
.rd-live .rd-window:not(.rd-top) > .rd-titlebar {
  background: var(--rd-title-idle);
}

.rd-live .rd-window:focus-visible {
  outline: var(--rd-ring-width) var(--rd-ring-style) var(--rd-ring);
  outline-offset: var(--rd-ring-width);
}

/* The body is the scroll region. shell.js gives it tabindex="0" so a
   keyboard user can scroll a long window without a pointer. */
.rd-live .rd-window-body {
  overflow-y: auto;
}

/* The one animation, and it is stepped rather than eased: this era expanded
   an opening window through a few wireframe rectangles, so a smooth rise
   would be the wrong decade's motion. Under prefers-reduced-motion the
   tokens collapse the duration and zero the scale, and the window simply
   appears. */
@keyframes rd-window-in {
  from {
    transform: scale(var(--rd-open-scale));
  }
  to {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   TASKBAR
   The launcher at the left, a sunken tray at the right, and between them two
   lists rather than one. The shortcut bar is a fixed text index of every
   window, the same with the script and without it. The tasklist is
   shell.js's, rebuilt on every change to track what is open.

   WHY BOTH, AND WHAT WAS WRONG BEFORE. The static list used to be the
   tasklist, and enhancement destroyed it: with the script running, the only
   complete set of text links to this site vanished and was replaced by
   whatever happened to be open. Correct taskbar behaviour, and also the
   entire second navigation surface disappearing exactly for the readers who
   have JavaScript. The Programs menu does not cover it, because its rows
   carry glyphs and an icon with a label is still an icon surface. Class
   decision 44 in desktop-os-theme's docs/class-decisions.md is the rule;
   this repo inherited the pilot's gap and now inherits its fix. The
   shortcuts survive by construction: shell.js has no selector that reaches
   them.

   WHERE ERA FIDELITY LOSES TO ACCESSIBILITY, AND BY HOW MUCH. This repo
   names each such loss at the token that forced it; this one has no token
   to sit at, and it is the only one measured in years rather than in
   pixels or in ratios. A strip of pinned shortcuts on the taskbar is
   Quick Launch, which arrived with the IE4 desktop update in 1997, two
   years after the year this register wears. Every part of how it is drawn
   is 1995 (flat on the face until you point at it, then a thin raised
   bevel, which is exactly how this era's toolbar buttons behaved), but the
   strip itself is 1997. The alternative that would have been strictly in
   period is a File/Edit-style menu bar inside the window chrome, and this
   demo has six windows, so that is six identical navigation landmarks
   interleaved with the content in the no-JS reading. Two years of
   anachronism is the cheaper price, and naming it is the rule.

   ONE ROW WHEN LIVE, NEVER TWO. --rd-taskbar-height is load-bearing: the
   live window height is calc(100dvh - that). A taskbar that wrapped to a
   second row would put the bottom edge of every window silently under the
   chrome, and nothing would fail while it happened. So live, the strip does
   not wrap; it scrolls. As a page there is no such constraint and no fixed
   strip to overflow, so it wraps like the ordinary footer nav it is. This is
   class decision 45, filed by this strip and the pilot's together.
   -------------------------------------------------------------------------- */
.rd-taskbar {
  background: var(--rd-face);
  box-shadow: inset 0 1px 0 0 var(--rd-bevel-hi);
}

.rd-taskbar-inner {
  display: flex;
  align-items: center;
  gap: var(--rd-space-2);
  min-height: var(--rd-taskbar-height);
  padding: var(--rd-space-1) var(--rd-space-1);
}

/* Both lists live in here; the launcher and the tray sit outside it so
   neither ever scrolls away from the corner it belongs in. */
.rd-taskbar-scroll {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--rd-space-2);
}

.rd-shortcuts,
.rd-tasklist {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--rd-space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Live, the strip becomes one scrolling line. It needs no room reserved for
   the focus ring, which is the one place the era's drawing is easier than
   the pilot's: this ring is dotted and drawn INSIDE the control, at a
   negative offset, so an overflow container has nothing of it to clip. That
   is the stated exception to part 3 of class decision 45, and the reason it
   is stated: the reservation is owed by ring geometry, not by the existence
   of a scroll box. */
.rd-live .rd-taskbar-scroll {
  flex-wrap: nowrap;
  overflow-x: auto;
}

.rd-live .rd-shortcuts,
.rd-live .rd-tasklist {
  flex: none;
  flex-wrap: nowrap;
}

/* The divider is the era's own: a sunken hairline groove, the separator
   every 95-era toolbar used between groups of buttons. It earns its place
   only when there is something on both sides of it, and empty is both the
   no-JS state and the nothing-open state. */
.rd-tasklist:not(:empty) {
  padding-left: var(--rd-space-2);
  box-shadow: inset 1px 0 0 0 var(--rd-bevel-shadow),
    inset 2px 0 0 0 var(--rd-bevel-hi);
}

/* --------------------------------------------------------------------------
   THE SHORTCUT BAR
   Flat text on the face, raising to a thin bevel under the pointer and under
   focus. That is not a modern hover style borrowed back: hot tracking, where
   a flat toolbar button raises only when you point at it, is what this era's
   toolbars did, and it is the reason a shortcut and a task entry can share
   one strip without being confused for each other. A task entry stands for a
   window that exists right now, and is raised all the time; a shortcut
   stands for a place you can go, and is flat until you reach for it.

   Contrast, measured on the face: full ink 11.54:1. Muted ink measures
   4.87:1, which clears AA and reads as a row of disabled menus, which is
   precisely the wrong thing for the one surface that has to look like
   navigation. Full ink.
   -------------------------------------------------------------------------- */
.rd-shortcut {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  max-width: 180px;
  padding: var(--rd-space-1) var(--rd-space-2);

  font-family: var(--rd-font-ui);
  font-size: var(--rd-text-sm);
  color: var(--rd-ink);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;

  background: var(--rd-face);
  border: 0;
  border-radius: var(--rd-radius);
}

.rd-shortcut:hover {
  box-shadow: var(--rd-raise-thin);
}

.rd-shortcut:focus-visible {
  box-shadow: var(--rd-raise-thin);
  outline: var(--rd-ring-width) var(--rd-ring-style) var(--rd-ring);
  outline-offset: calc(-1 * var(--rd-ring-inset));
}

.rd-task {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  min-width: 60px;
  max-width: 180px;
  padding: var(--rd-space-1) var(--rd-space-2);

  font-family: var(--rd-font-ui);
  font-size: var(--rd-text-sm);
  color: var(--rd-ink);
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;

  background: var(--rd-face);
  border: 0;
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-raise-thin);
  cursor: pointer;
}

.rd-task:focus-visible {
  outline: var(--rd-ring-width) var(--rd-ring-style) var(--rd-ring);
  outline-offset: calc(-1 * var(--rd-ring-inset));
}

/* The top window's entry is pressed in and bold. aria-pressed carries the
   state; this rule makes it visible. */
.rd-task[aria-pressed="true"] {
  box-shadow: var(--rd-sink-thin);
  font-weight: var(--rd-weight-bold);
  padding-left: calc(var(--rd-space-1) + 1px);
}

/* A minimized window's entry: still present, still raised, visibly parked. */
.rd-task.rd-task-min {
  color: var(--rd-ink-muted);
}

/* The launcher: the taskbar's menu button. It exists at every width, because
   in this era it was chrome the desktop always had rather than a mobile
   affordance, which is the other place this shell parts company with the
   pilot. Injected by shell.js: it only means something live. */
.rd-launcher {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: var(--rd-space-2);
  min-height: 26px;
  padding: var(--rd-space-1) var(--rd-space-2);

  font-family: var(--rd-font-ui);
  font-size: var(--rd-text-sm);
  font-weight: var(--rd-weight-bold);
  color: var(--rd-ink);

  background: var(--rd-face);
  border: 0;
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-raise-thin);
  cursor: pointer;
}

.rd-launcher[aria-expanded="true"] {
  box-shadow: var(--rd-sink-thin);
}

.rd-launcher:focus-visible {
  outline: var(--rd-ring-width) var(--rd-ring-style) var(--rd-ring);
  outline-offset: calc(-1 * var(--rd-ring-inset));
}

.rd-launcher > svg {
  width: 16px;
  height: 16px;
}

/* The tray. A sunken well at the end of the taskbar holding the clock and
   the wallpaper button, which is where this era kept both. */
.rd-tray {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--rd-space-1);
  padding: var(--rd-space-1) var(--rd-space-2);
  box-shadow: var(--rd-sink-thin);
}

.rd-tray-btn {
  display: grid;
  place-items: center;
  width: var(--rd-control-size);
  height: var(--rd-control-size);
  padding: 0;

  color: var(--rd-ink);
  background: var(--rd-face);
  border: 0;
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-raise-thin);
  cursor: pointer;
}

.rd-tray-btn:active {
  box-shadow: var(--rd-sink-thin);
}

.rd-tray-btn:focus-visible {
  outline: var(--rd-ring-width) var(--rd-ring-style) var(--rd-ring);
  outline-offset: calc(-1 * var(--rd-ring-inset));
}

.rd-tray-btn > svg {
  width: 14px;
  height: 14px;
}

.rd-clock {
  font-family: var(--rd-font-mono);
  font-size: var(--rd-text-sm);
  color: var(--rd-ink);
}

.rd-live .rd-taskbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--rd-z-chrome);
}

/* --------------------------------------------------------------------------
   THE PROGRAMS MENU
   The icon nav in its third costume: a raised panel standing on the taskbar
   above the launcher button, with the era's one hard drop shadow under it.
   Rows rather than cells, and the row highlight is the same accent the
   selected icon label uses.
   -------------------------------------------------------------------------- */
.rd-live .rd-icons.rd-open {
  top: auto;
  bottom: var(--rd-taskbar-height);
  left: var(--rd-space-1);
  z-index: var(--rd-z-launcher);

  min-width: 208px;
  padding: var(--rd-space-1);
  background: var(--rd-face);
  border-radius: var(--rd-radius-window);
  box-shadow: var(--rd-raise), var(--rd-drop);
  animation: rd-window-in var(--rd-duration) var(--rd-ease);
}

.rd-live .rd-icons.rd-open .rd-icons-list {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.rd-live .rd-icons.rd-open .rd-icon {
  flex-direction: row;
  align-items: center;
  gap: var(--rd-space-3);
  width: auto;
  padding: var(--rd-space-2);
  text-align: left;
}

.rd-live .rd-icons.rd-open .rd-icon-glyph {
  width: var(--rd-space-6);
  height: var(--rd-space-6);
}

.rd-live .rd-icons.rd-open .rd-icon-label {
  padding: 0;
  font-size: var(--rd-text-sm);
  color: var(--rd-ink);
  background: none;
}

.rd-live .rd-icons.rd-open .rd-icon:hover,
.rd-live .rd-icons.rd-open .rd-icon:focus-visible {
  background: var(--rd-accent);
}

.rd-live .rd-icons.rd-open .rd-icon:hover .rd-icon-label,
.rd-live .rd-icons.rd-open .rd-icon:focus-visible .rd-icon-label {
  color: var(--rd-accent-ink);
  background: none;
}

.rd-live .rd-icons.rd-open .rd-icon:focus-visible {
  outline-color: var(--rd-ring-invert);
}

/* --------------------------------------------------------------------------
   THE RESPONSIVE METAPHOR-TRANSFORM
   Under 768px a floating beveled window on a phone is a diorama, so the
   metaphor transforms rather than shrinks: the window goes full-bleed above
   the taskbar, the desktop grid goes away, and the taskbar stays with its
   launcher, because the menu is now the whole navigation and a phone still
   wants to know what is open. This transform is part of the archetype, not a
   degradation of it.

   Note what does NOT change: the bevels, the title bar, the tray, the
   double line. The era chrome is the point, and shrinking a window is not a
   reason to stop drawing it.
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
  .rd-live .rd-window {
    left: 0;
    top: 0;
    width: 100%;
    max-height: calc(100dvh - var(--rd-taskbar-height));
    height: calc(100dvh - var(--rd-taskbar-height));
    padding: 0;
    box-shadow: none;
  }

  /* The window is now a fixed height rather than a content-sized card, so
     the client area has to fill the frame. Without this the paper stops
     where the text stops and the rest of the screen is bare chrome. */
  .rd-live .rd-window-body {
    flex: 1;
    margin-top: 0;
    padding: var(--rd-space-4);
  }

  /* The desktop grid hides; the same nav is reachable as the menu, which is
     the launcher's whole job at this width. */
  .rd-live .rd-icons:not(.rd-open) {
    display: none;
  }

  .rd-live .rd-icons.rd-open {
    right: var(--rd-space-1);
    min-width: 0;
  }
}

/* --------------------------------------------------------------------------
   THE DESKTOP NOTE
   The register's one play object: a paper note pinned to the desktop, on the
   warning fill, raised like everything else, and square. It does not tilt; a
   tilted note is a later decade's sticker. As a page it sits in the document
   flow like the aside it is. Live on desktop it pins to the bottom-right,
   under the window pile, above the taskbar. On mobile there is no visible
   desktop to pin it to, so it stays hidden rather than floating over
   content.
   -------------------------------------------------------------------------- */
.rd-note {
  width: var(--rd-note-size);
  margin: 0 auto var(--rd-space-8);
  padding: var(--rd-space-3);

  background: var(--rd-fill-warning);
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-raise);

  font-size: var(--rd-text-sm);
  line-height: var(--rd-leading-snug);
  color: var(--rd-ink);
}

.rd-live .rd-note {
  position: fixed;
  right: var(--rd-space-4);
  bottom: calc(var(--rd-taskbar-height) + var(--rd-space-4));
  margin: 0;
  z-index: calc(var(--rd-z-window) - 1);
}

@media (max-width: 767px) {
  .rd-live .rd-note {
    display: none;
  }
}
